Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Oct 27, 2009, 2:47:14 PM (15 years ago)
Author:
rgrieder
Message:

Changed Output concept a little bit to allow for more general use.
Every output (log) target has to be implemented as OutputListener. There is already a LogFileWriter and a MemoryLogWriter (stores ALL the log in a vector and provides iterators).
The OutputListener has a unique and constant name, a stream pointer and a soft debug level (that can only be changed via OutputHandler::setSoftDebugLevel(name, level)).
This concept doesn't require the OutputBuffer anymore, so I deleted it.

The adjustments in the Shell are just preliminary for this commit.

Location:
code/branches/console/src/libraries
Files:
2 deleted
15 edited

Legend:

Unmodified
Added
Removed
  • code/branches/console/src/libraries/core/ConfigValueIncludes.h

    r5738 r5994  
    4747    @param defvalue The default-value of the variable
    4848*/
    49 #define SetConfigValueGeneric(type, varname, defvalue) \
     49#define SetConfigValueGeneric(type, varname, entryname, sectionname, defvalue) \
    5050    static orxonox::Identifier* identifier##varname = this->getIdentifier(); \
    5151    orxonox::ConfigValueContainer* container##varname = identifier##varname->getConfigValueContainer(#varname); \
    5252    if (!container##varname) \
    5353    { \
    54         container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, identifier##varname->getName(), #varname, defvalue, varname); \
     54        container##varname = new orxonox::ConfigValueContainer(type, identifier##varname, sectionname, entryname, defvalue, varname); \
    5555        identifier##varname->addConfigValueContainer(#varname, container##varname); \
    5656    } \
    5757    container##varname->getValue(&varname, this)
    5858
    59 #define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, defvalue)
     59#define SetConfigValue(varname, defvalue) SetConfigValueGeneric(ConfigFileType::Settings, varname, identifier##varname->getName(), #varname, defvalue)
    6060
    6161
  • code/branches/console/src/libraries/core/Core.cc

    r5992 r5994  
    106106        void setConfigValues()
    107107        {
    108 #ifdef NDEBUG
    109             const unsigned int defaultLevelConsole = 1;
    110             const unsigned int defaultLevelLogfile = 3;
    111             const unsigned int defaultLevelShell   = 1;
     108#ifdef ORXONOX_RELEASE
     109            const unsigned int defaultLevelLogFile = 3;
    112110#else
    113             const unsigned int defaultLevelConsole = 3;
    114             const unsigned int defaultLevelLogfile = 4;
    115             const unsigned int defaultLevelShell   = 3;
    116 #endif
    117             SetConfigValue(softDebugLevelConsole_, defaultLevelConsole)
    118                 .description("The maximal level of debug output shown in the console")
    119                 .callback(this, &CoreConfiguration::debugLevelChanged);
    120             SetConfigValue(softDebugLevelLogfile_, defaultLevelLogfile)
    121                 .description("The maximal level of debug output shown in the logfile")
    122                 .callback(this, &CoreConfiguration::debugLevelChanged);
    123             SetConfigValue(softDebugLevelShell_, defaultLevelShell)
    124                 .description("The maximal level of debug output shown in the ingame shell")
    125                 .callback(this, &CoreConfiguration::debugLevelChanged);
     111            const unsigned int defaultLevelLogFile = 4;
     112#endif
     113            SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevelLogFile_, "softDebugLevelLogFile", "OutputHandler", defaultLevelLogFile)
     114                .description("The maximum level of debug output shown in the log file");
     115            OutputHandler::getInstance().setSoftDebugLevel(OutputHandler::logFileOutputListenerName_s, this->softDebugLevelLogFile_);
    126116
    127117            SetConfigValue(language_, Language::getInstance().defaultLanguage_)
     
    131121                .description("If true, all random actions are different each time you start the game")
    132122                .callback(this, &CoreConfiguration::initializeRandomNumberGenerator);
    133         }
    134 
    135         /**
    136             @brief Callback function if the debug level has changed.
    137         */
    138         void debugLevelChanged()
    139         {
    140             // softDebugLevel_ is the maximum of the 3 variables
    141             this->softDebugLevel_ = this->softDebugLevelConsole_;
    142             if (this->softDebugLevelLogfile_ > this->softDebugLevel_)
    143                 this->softDebugLevel_ = this->softDebugLevelLogfile_;
    144             if (this->softDebugLevelShell_ > this->softDebugLevel_)
    145                 this->softDebugLevel_ = this->softDebugLevelShell_;
    146 
    147             OutputHandler::setSoftDebugLevel(OutputHandler::LD_All,     this->softDebugLevel_);
    148             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Console, this->softDebugLevelConsole_);
    149             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Logfile, this->softDebugLevelLogfile_);
    150             OutputHandler::setSoftDebugLevel(OutputHandler::LD_Shell,   this->softDebugLevelShell_);
    151123        }
    152124
     
    179151        }
    180152
    181         int softDebugLevel_;                            //!< The debug level
    182         int softDebugLevelConsole_;                     //!< The debug level for the console
    183         int softDebugLevelLogfile_;                     //!< The debug level for the logfile
    184         int softDebugLevelShell_;                       //!< The debug level for the ingame shell
     153        int softDebugLevelLogFile_;                     //!< The debug level for the log file (belongs to OutputHandler)
    185154        std::string language_;                          //!< The language
    186155        bool bInitializeRandomNumberGenerator_;         //!< If true, srand(time(0)) is called
     
    228197
    229198        // Set the correct log path. Before this call, /tmp (Unix) or %TEMP% (Windows) was used
    230         OutputHandler::getOutStream().setLogPath(PathConfig::getLogPathString());
     199        OutputHandler::getInstance().setLogPath(PathConfig::getLogPathString());
    231200
    232201        // Parse additional options file now that we know its path
     
    328297        bGraphicsLoaded_ = false;
    329298        GameMode::bShowsGraphics_s = false;
    330     }
    331 
    332     /**
    333         @brief Returns the softDebugLevel for the given device (returns a default-value if the class is right about to be created).
    334         @param device The device
    335         @return The softDebugLevel
    336     */
    337     /*static*/ int Core::getSoftDebugLevel(OutputHandler::OutputDevice device)
    338     {
    339         switch (device)
    340         {
    341         case OutputHandler::LD_All:
    342             return Core::getInstance().configuration_->softDebugLevel_;
    343         case OutputHandler::LD_Console:
    344             return Core::getInstance().configuration_->softDebugLevelConsole_;
    345         case OutputHandler::LD_Logfile:
    346             return Core::getInstance().configuration_->softDebugLevelLogfile_;
    347         case OutputHandler::LD_Shell:
    348             return Core::getInstance().configuration_->softDebugLevelShell_;
    349         default:
    350             assert(0);
    351             return 2;
    352         }
    353     }
    354 
    355      /**
    356         @brief Sets the softDebugLevel for the given device. Please use this only temporary and restore the value afterwards, as it overrides the configured value.
    357         @param device The device
    358         @param level The level
    359     */
    360     /*static*/ void Core::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    361     {
    362         if (device == OutputHandler::LD_All)
    363             Core::getInstance().configuration_->softDebugLevel_ = level;
    364         else if (device == OutputHandler::LD_Console)
    365             Core::getInstance().configuration_->softDebugLevelConsole_ = level;
    366         else if (device == OutputHandler::LD_Logfile)
    367             Core::getInstance().configuration_->softDebugLevelLogfile_ = level;
    368         else if (device == OutputHandler::LD_Shell)
    369             Core::getInstance().configuration_->softDebugLevelShell_ = level;
    370 
    371         OutputHandler::setSoftDebugLevel(device, level);
    372299    }
    373300
  • code/branches/console/src/libraries/core/Core.h

    r5992 r5994  
    6969            void setConfigValues();
    7070
    71             static int   getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    72             static void  setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    7371            static const std::string& getLanguage();
    7472            static void  resetLanguage();
  • code/branches/console/src/libraries/core/GUIManager.cc

    r5992 r5994  
    5353#include "util/Exception.h"
    5454#include "util/OrxAssert.h"
    55 #include "Core.h"
    5655#include "LuaState.h"
    5756#include "PathConfig.h"
     
    7574                default: OrxAssert(false, "CEGUI log level out of range, inpect immediately!");
    7675            }
    77             OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
     76            OutputHandler::getOutStream(orxonoxLevel)
    7877                << "CEGUI: " << message << std::endl;
    7978
     
    121120        // set the log level according to ours (translate by subtracting 1)
    122121        ceguiLogger->setLoggingLevel(
    123             static_cast<LoggingLevel>(Core::getSoftDebugLevel(OutputHandler::LD_Logfile) - 1));
     122            static_cast<LoggingLevel>(OutputHandler::getInstance().getSoftDebugLevel("logFile") - 1));
    124123        this->ceguiLogger_ = ceguiLogger.release();
    125124
  • code/branches/console/src/libraries/core/GraphicsManager.cc

    r5929 r5994  
    408408            orxonoxLevel = 0;
    409409        }
    410         OutputHandler::getOutStream().setOutputLevel(orxonoxLevel)
     410        OutputHandler::getOutStream(orxonoxLevel)
    411411            << "Ogre: " << message << std::endl;
    412412    }
  • code/branches/console/src/libraries/core/IOConsole.cc

    r5986 r5994  
    6262        this->originalTerminalSettings_ = new termios;
    6363        this->setTerminalMode();
    64                 this->shell_.registerListener(this);
     64        this->shell_.registerListener(this);
    6565    }
    6666
     
    234234    }
    235235
     236#elif defined(ORXONOX_PLATFORM_WINDOWS)
     237
     238    IOConsole::IOConsole()
     239        : shell_(Shell::getInstance())
     240        , buffer_(Shell::getInstance().getInputBuffer())
     241    {
     242        this->setTerminalMode();
     243    }
     244
     245    IOConsole::~IOConsole()
     246    {
     247    }
     248
     249    void IOConsole::setTerminalMode()
     250    {
     251    }
     252
     253    void IOConsole::resetTerminalMode()
     254    {
     255    }
     256
     257    void IOConsole::update(const Clock& time)
     258    {
     259    }
     260
     261    void IOConsole::print(const std::string& text)
     262    {
     263    }
     264
     265    void IOConsole::printInputLine()
     266    {
     267    }
     268
    236269#endif /* ORXONOX_PLATFORM_UNIX */
    237270
     
    256289    void IOConsole::onlyLastLineChanged()
    257290    {
    258                 // Save cursor position and move it the beginning of the second to last line
    259                 std::cout << "\033[s\033[1F";
    260                 // Erase the second to last line
    261                 std::cout << "\033[K";
    262                 this->print(*(this->shell_.getNewestLineIterator()));
    263                 // Restore cursor
    264                 std::cout << "\033[u";
    265                 std::cout.flush();
     291        // Save cursor position and move it the beginning of the second to last line
     292        std::cout << "\033[s\033[1F";
     293        // Erase the second to last line
     294        std::cout << "\033[K";
     295        this->print(*(this->shell_.getNewestLineIterator()));
     296        // Restore cursor
     297        std::cout << "\033[u";
     298        std::cout.flush();
    266299    }
    267300
     
    272305    void IOConsole::lineAdded()
    273306    {
    274                 // Move curosr the beginning of the line and erase it
    275                 std::cout << "\033[1G\033[K";
    276                 this->print(*(this->shell_.getNewestLineIterator()));
    277                 std::cout << std::endl;
    278                 this->printInputLine();
     307        // Move curosr the beginning of the line and erase it
     308        std::cout << "\033[1G\033[K";
     309        this->print(*(this->shell_.getNewestLineIterator()));
     310        std::cout << std::endl;
     311        this->printInputLine();
    279312    }
    280313
     
    303336    void IOConsole::executed()
    304337    {
    305                 // Move curosr the beginning of the line
    306                 std::cout << "\033[1G";
    307         // Print command so the user knows what he typed
     338        // Move cursor the beginning of the line
     339        std::cout << "\033[1G";
     340        // Print command so the user knows what he has typed
    308341        std::cout << "orxonox>" << this->shell_.getInput() << std::endl;
    309                 this->printInputLine();
     342        this->printInputLine();
    310343    }
    311344
  • code/branches/console/src/libraries/core/LuaState.cc

    r5929 r5994  
    182182    void LuaState::luaLog(unsigned int level, const std::string& message)
    183183    {
    184         OutputHandler::getOutStream().setOutputLevel(level) << message << std::endl;
     184        OutputHandler::getOutStream(level) << message << std::endl;
    185185    }
    186186
  • code/branches/console/src/libraries/core/Shell.cc

    r5986 r5994  
    5151
    5252    Shell::Shell()
    53     {
    54         int level = Core::getSoftDebugLevel(OutputHandler::LD_Shell);
    55         Core::setSoftDebugLevel(OutputHandler::LD_Shell, -1);
    56 
     53        : OutputListener("shell")
     54    {
    5755        RegisterRootObject(Shell);
    5856
     
    6967        this->configureInputBuffer();
    7068
    71         this->outputBuffer_.registerListener(this);
    72         OutputHandler::getOutStream().setOutputBuffer(&this->outputBuffer_);
    73 
    7469        // Get a config file for the command history
    7570        this->commandHistoryConfigFileType_ = ConfigFileManager::getInstance().getNewConfigFileType();
    7671        ConfigFileManager::getInstance().setFilename(this->commandHistoryConfigFileType_, "commandHistory.ini");
    7772
     73        // Use a stringstream object to buffer the output and get it line by line in update()
     74        this->outputStream_ = &this->outputBuffer_;
     75
    7876        this->setConfigValues();
    7977
    80         Core::setSoftDebugLevel(OutputHandler::LD_Shell, level);
     78        // Get the previous output and add it to the Shell
     79        for (OutputHandler::OutputVectorIterator it = OutputHandler::getInstance().getOutputVectorBegin();
     80            it != OutputHandler::getInstance().getOutputVectorEnd(); ++it)
     81            this->addLine(it->second, it->first);
     82
     83        // Register the shell as output listener
     84        OutputHandler::getInstance().registerOutputListener(this);
    8185    }
    8286
    8387    Shell::~Shell()
    8488    {
    85         OutputHandler::getOutStream().setOutputBuffer(0);
    86         if (this->inputBuffer_)
    87             this->inputBuffer_->destroy();
     89        OutputHandler::getInstance().unregisterOutputListener(this);
     90        this->inputBuffer_->destroy();
    8891    }
    8992
    9093    void Shell::setConfigValues()
    9194    {
    92         SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, 100)
     95        SetConfigValueGeneric(commandHistoryConfigFileType_, maxHistoryLength_, "maxHistoryLength_", "Shell", 100)
    9396            .callback(this, &Shell::commandHistoryLengthChanged);
    94         SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, 0)
     97        SetConfigValueGeneric(commandHistoryConfigFileType_, historyOffset_, "historyOffset_", "Shell", 0)
    9598            .callback(this, &Shell::commandHistoryOffsetChanged);
    9699        SetConfigValueVectorGeneric(commandHistoryConfigFileType_, commandHistory_, std::vector<std::string>());
     100
     101#ifdef ORXONOX_RELEASE
     102        const unsigned int defaultLevel = 1;
     103#else
     104        const unsigned int defaultLevel = 3;
     105#endif
     106        SetConfigValueGeneric(ConfigFileType::Settings, softDebugLevel_, "softDebugLevelShell", "OutputHandler", defaultLevel)
     107            .description("The maximal level of debug output shown in the Shell");
     108        OutputHandler::getInstance().setSoftDebugLevel("shell", this->softDebugLevel_);
    97109    }
    98110
     
    182194    void Shell::addLine(const std::string& line, int level)
    183195    {
    184         int original_level = OutputHandler::getOutStream().getOutputLevel();
    185         OutputHandler::getOutStream().setOutputLevel(level);
    186 
    187         if (!this->finishedLastLine_)
    188             this->outputBuffer_ << std::endl;
    189 
    190         this->outputBuffer_ << line << std::endl;
    191         OutputHandler::getOutStream().setOutputLevel(original_level);
     196        if (level <= this->softDebugLevel_)
     197            this->lines_.push_front(line);
     198        this->updateListeners<&ShellListener::lineAdded>();
    192199    }
    193200
     
    238245        do
    239246        {
    240             newline = this->outputBuffer_.getLine(&output);
     247            std::getline(this->outputBuffer_, output);
     248
     249            bool eof = this->outputBuffer_.eof();
     250            bool fail = this->outputBuffer_.fail();
     251            if (eof)
     252                this->outputBuffer_.flush();
     253            if (eof || fail)
     254                this->outputBuffer_.clear();
     255            newline = (!eof && !fail);
    241256
    242257            if (!newline && output == "")
     
    246261            {
    247262                if (this->bAddOutputLevel_)
    248                     output.insert(0, 1, static_cast<char>(OutputHandler::getOutStream().getOutputLevel()));
    249 
    250                 this->lines_.insert(this->lines_.begin(), output);
     263                    output.insert(0, 1, static_cast<char>(OutputHandler::getInstance().getOutputLevel()));
     264
     265                this->lines_.push_front(output);
    251266
    252267                if (this->scrollPosition_)
     
    365380            return;
    366381        unsigned int cursorPosition = this->getCursorPosition();
    367         std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginning of the inputline untill the cursor position
    368         for (unsigned int newPos = this->historyPosition_+1; newPos<=this->historyOffset_; newPos++)
    369         {
    370             if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //search case insensitive
     382        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginning of the inputline untill the cursor position
     383        for (unsigned int newPos = this->historyPosition_ + 1; newPos <= this->historyOffset_; newPos++)
     384        {
     385            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // search case insensitive
    371386            {
    372387                this->historyPosition_ = newPos;
    373388                this->inputBuffer_->set(this->getFromHistory());
    374                 this->setCursorPosition( cursorPosition );
     389                this->setCursorPosition(cursorPosition);
    375390                return;
    376391            }
     
    383398            return;
    384399        unsigned int cursorPosition = this->getCursorPosition();
    385         std::string input_str( this->getInput().substr(0,cursorPosition) ); //only search for the expression from the beginn$
    386         for (unsigned int newPos = this->historyPosition_-1; newPos>0; newPos--)
    387         {
    388             if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) //sear$
     400        std::string input_str(this->getInput().substr(0, cursorPosition)); // only search for the expression from the beginn$
     401        for (unsigned int newPos = this->historyPosition_ - 1; newPos > 0; newPos--)
     402        {
     403            if (getLowercase(this->commandHistory_[this->historyOffset_ - newPos]).find(getLowercase(input_str)) == 0) // sear$
    389404            {
    390405                this->historyPosition_ = newPos;
    391406                this->inputBuffer_->set(this->getFromHistory());
    392                 this->setCursorPosition( cursorPosition );
     407                this->setCursorPosition(cursorPosition);
    393408                return;
    394409            }
  • code/branches/console/src/libraries/core/Shell.h

    r5986 r5994  
    3434#include <cassert>
    3535#include <list>
     36#include <sstream>
    3637#include <string>
    3738#include <vector>
    3839
    39 #include "util/OutputBuffer.h"
     40#include "util/OutputHandler.h"
    4041#include "input/InputBuffer.h"
    4142#include "OrxonoxClass.h"
     
    6162    };
    6263
    63     class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputBufferListener
     64    class _CoreExport Shell : public Singleton<Shell>, virtual public OrxonoxClass, public OutputListener
    6465    {
    6566        friend class Singleton<Shell>;
     
    7172            static void history();
    7273
    73             virtual void setConfigValues();
     74            void setConfigValues();
    7475            void commandHistoryOffsetChanged();
    7576            void commandHistoryLengthChanged();
     
    8081            inline InputBuffer* getInputBuffer()
    8182                { return this->inputBuffer_; }
    82             inline OutputBuffer& getOutputBuffer()
    83                 { return this->outputBuffer_; }
    8483
    8584            void setCursorPosition(unsigned int cursor);
     
    117116
    118117            virtual void outputChanged();
     118
    119119            void inputChanged();
    120120            void execute();
     
    144144            std::list<ShellListener*> listeners_;
    145145            InputBuffer* inputBuffer_;
    146             OutputBuffer outputBuffer_;
     146            std::stringstream outputBuffer_;
    147147            bool finishedLastLine_;
    148148            std::list<std::string> lines_;
     
    154154            unsigned int historyOffset_;
    155155            bool bAddOutputLevel_;
     156            int softDebugLevel_;
    156157
    157158            ConfigFileType commandHistoryConfigFileType_;
  • code/branches/console/src/libraries/util/CMakeLists.txt

    r5929 r5994  
    2929  CRC32.cc
    3030  ExprParser.cc
    31   OutputBuffer.cc
    3231  OutputHandler.cc
    3332  SignalHandler.cc
  • code/branches/console/src/libraries/util/Debug.h

    r5991 r5994  
    7676
    7777/**
    78 @def COUT
     78@brief
    7979    Logs text output: use exactly like std::cout, but specify an output
    80     level as argument. For example COUT(3) << "Some info" << std::endl;
     80    level as argument.
     81@example
     82    COUT(3) << "Some info" << std::endl;
    8183@note
    8284    The ? : operator requires both possible results to have the type of
  • code/branches/console/src/libraries/util/OrxAssert.h

    r5738 r5994  
    4444#ifndef NDEBUG
    4545#define OrxAssert(Assertion, ErrorMessage) \
    46     Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream().setOutputLevel(1) << ErrorMessage << std::endl); \
     46    Assertion ? ((void)0) : (void)(orxonox::OutputHandler::getOutStream(1) << ErrorMessage << std::endl); \
    4747    assert(Assertion)
    4848#else
  • code/branches/console/src/libraries/util/OutputHandler.cc

    r5983 r5994  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Implementation of the OutputHandler class.
     30@file
     31@brief
     32    Definition of classes related to output (logging).
    3233*/
    3334
    3435#include "OutputHandler.h"
    3536
     37#include <algorithm>
    3638#include <ctime>
    3739#include <cstdlib>
     40#include <fstream>
     41#include <sstream>
     42
     43#include "Debug.h"
    3844
    3945namespace orxonox
    4046{
     47    //! How the log file shall be named on the filesystem
     48    const std::string logFileBaseName_g = "orxonox.log";
     49
     50    /////////////////////////
     51    ///// LogFileWriter /////
     52    /////////////////////////
    4153    /**
    42         @brief Constructor: Opens the logfile and writes the first line.
    43         @param logfilename The name of the logfile
     54    @brief
     55        Writes the output to the log file.
     56    @note
     57        As long as the correct log path is not yet known (for pre main code), the
     58        LogFileWriter will write to a temporary file in /temp (Unix) or %TEMP% (Windows).
     59        As soon as you set the correct path setLogPath the content of the temporary file
     60        is read and put into the new file as well.
    4461    */
     62    class LogFileWriter : public OutputListener
     63    {
     64    public:
     65        //! Gets temporary log path and starts the log file
     66        LogFileWriter()
     67            : OutputListener(OutputHandler::logFileOutputListenerName_s)
     68        {
     69            // Get path for a temporary file
     70#ifdef ORXONOX_PLATFORM_WINDOWS
     71            char* pTempDir = getenv("TEMP");
     72            this->logFilename_ = std::string(pTempDir) + "/" + logFileBaseName_g;
     73#else
     74            this->logFilename_ = std::string("/tmp/") + logFileBaseName_g;
     75#endif
     76
     77            // Get current time
     78            time_t rawtime;
     79            struct tm* timeinfo;
     80            time(&rawtime);
     81            timeinfo = localtime(&rawtime);
     82
     83            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     84            this->logFile_ << "Started log on " << asctime(timeinfo) << std::endl;
     85            this->logFile_.flush();
     86
     87            this->outputStream_ = &this->logFile_;
     88            // Use default level until we get the configValue from the Core
     89            OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputLevel::Debug);
     90            OutputHandler::getInstance().registerOutputListener(this);
     91        }
     92
     93        //! Closes the log file
     94        ~LogFileWriter()
     95        {
     96            this->logFile_ << "Closed log" << std::endl;
     97            this->logFile_.close();
     98        }
     99
     100        //! Changes the log path
     101        void setLogPath(const std::string& path)
     102        {
     103            this->logFile_.close();
     104            // Read old file into a buffer
     105            std::ifstream old(this->logFilename_.c_str());
     106            this->logFilename_ = path + logFileBaseName_g;
     107            // Open the new file and feed it the content of the old one
     108            this->logFile_.open(this->logFilename_.c_str(), std::fstream::out);
     109            this->logFile_ << old.rdbuf();
     110            this->logFile_.flush();
     111            old.close();
     112        }
     113
     114    private:
     115        std::ofstream logFile_;     //! File handle for the log file
     116        std::string   logFilename_; //! Filename of the log file
     117    };
     118
     119
     120    ///////////////////////////
     121    ///// MemoryLogWriter /////
     122    ///////////////////////////
     123    /**
     124    @brief
     125        OutputListener that writes all the output piece by piece to an array
     126        associated with the corresponding output level.
     127    @note
     128        Only output below or equal to the current soft debug level is written
     129        to minimise huge arrays for the normal run.
     130    */
     131    class MemoryLogWriter : public OutputListener
     132    {
     133    public:
     134        friend class OutputHandler;
     135
     136        //! Sets the right soft debug level and registers itself
     137        MemoryLogWriter()
     138            : OutputListener("memoryLog")
     139        {
     140            this->outputStream_ = &this->buffer_;
     141            // We capture as much input as the listener with the highest level
     142            OutputHandler::getInstance().setSoftDebugLevel(this->getOutputListenerName(), OutputHandler::getSoftDebugLevel());
     143            OutputHandler::getInstance().registerOutputListener(this);
     144        }
     145
     146        //! Pushed the just written output to the internal array
     147        void outputChanged()
     148        {
     149            // Read ostringstream and store it
     150            this->output_.push_back(std::make_pair(OutputHandler::getInstance().getOutputLevel(), this->buffer_.str()));
     151            // Clear content and flags
     152            this->buffer_.str(std::string());
     153            this->buffer_.clear();
     154        }
     155
     156    private:
     157        std::ostringstream                        buffer_; //! Stream object used to process the output
     158        std::vector<std::pair<int, std::string> > output_; //! Vector containing ALL output
     159    };
     160
     161
     162    /////////////////////////
     163    ///// OutputHandler /////
     164    /////////////////////////
     165    const std::string OutputHandler::logFileOutputListenerName_s = "logFile";
     166          int         OutputHandler::softDebugLevel_s = hardDebugLevel;
     167
     168    //! Creates the LogFileWriter and the MemoryLogWriter
    45169    OutputHandler::OutputHandler()
    46     {
    47 #ifdef ORXONOX_PLATFORM_WINDOWS
    48         char* pTempDir = getenv("TEMP");
    49         this->logfilename_ = std::string(pTempDir) + "/orxonox.log";
    50 #else
    51         this->logfilename_ = "/tmp/orxonox.log";
    52 #endif
    53 #ifdef NDEBUG
    54         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 2;
    55         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 1;
    56 #else
    57         this->softDebugLevel_[LD_All] = this->softDebugLevel_[LD_Logfile] = 3;
    58         this->softDebugLevel_[LD_Console] = this->softDebugLevel_[LD_Shell] = 2;
    59 #endif
    60 
    61         this->outputBuffer_ = &this->fallbackBuffer_;
    62         this->logfile_.open(this->logfilename_.c_str(), std::fstream::out);
    63 
    64         time_t rawtime;
    65         struct tm* timeinfo;
    66         time(&rawtime);
    67         timeinfo = localtime(&rawtime);
    68 
    69         this->logfile_ << "Started log on " << asctime(timeinfo) << std::endl;
    70         this->logfile_.flush();
    71     }
    72 
    73     /**
    74         @brief Destructor: Writes the last line to the logfile and closes it.
    75     */
     170        : outputLevel_(OutputLevel::Verbose)
     171    {
     172        this->logFile_ = new LogFileWriter();
     173        this->output_  = new MemoryLogWriter();
     174    }
     175
     176    //! Destroys the LogFileWriter and the MemoryLogWriter
    76177    OutputHandler::~OutputHandler()
    77178    {
    78         this->logfile_ << "Closed log" << std::endl;
    79         this->logfile_.close();
    80     }
    81 
    82     /**
    83         @brief Returns a reference to the only existing instance of the OutputHandler class.
    84         @return The instance
    85     */
    86     OutputHandler& OutputHandler::getOutStream()
     179        delete this->logFile_;
     180        delete this->output_;
     181    }
     182
     183    OutputHandler& OutputHandler::getInstance()
    87184    {
    88185        static OutputHandler orxout;
     
    90187    }
    91188
    92     /**
    93         @brief Sets the soft debug level for a given output device.
    94         @param device The output device
    95         @param level The debug level
    96     */
    97     void OutputHandler::setSoftDebugLevel(OutputHandler::OutputDevice device, int level)
    98     {
    99         OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)] = level;
    100     }
    101 
    102     /**
    103         @brief Returns the soft debug level for a given output device.
    104         @param device The output device
    105         @return The debug level
    106     */
    107     int OutputHandler::getSoftDebugLevel(OutputHandler::OutputDevice device)
    108     {
    109         return OutputHandler::getOutStream().softDebugLevel_[static_cast<unsigned int>(device)];
    110     }
    111 
    112     /**
    113         @brief Sets the OutputBuffer, representing the third output stream.
    114         @param buffer The OutputBuffer
    115     */
    116     void OutputHandler::setOutputBuffer(OutputBuffer* buffer)
    117     {
    118         if (buffer == NULL)
    119             this->outputBuffer_ = &this->fallbackBuffer_;
    120         else
    121         {
    122             buffer->getStream() >> this->outputBuffer_->getStream().rdbuf();
    123             this->outputBuffer_ = buffer;
    124         }
    125     }
    126 
    127     /**
    128         @brief Sets the path where to create orxonox.log
    129         @param Path string with trailing slash
    130     */
     189    void OutputHandler::registerOutputListener(OutputListener* listener)
     190    {
     191        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     192        {
     193            if ((*it)->name_ == listener->name_)
     194            {
     195                COUT(2) << "OutputHandler, Warning: Trying to register two listeners with the same name!" << std::endl;
     196                return;
     197            }
     198        }
     199        this->listeners_.push_back(listener);
     200    }
     201
     202    void OutputHandler::unregisterOutputListener(OutputListener* listener)
     203    {
     204        this->listeners_.remove(listener);
     205    }
     206
    131207    void OutputHandler::setLogPath(const std::string& path)
    132208    {
    133         OutputHandler::getOutStream().logfile_.close();
    134         // store old content
    135         std::ifstream old;
    136         old.open(OutputHandler::getOutStream().logfilename_.c_str());
    137         OutputHandler::getOutStream().logfilename_ = path + "orxonox.log";
    138         OutputHandler::getOutStream().logfile_.open(OutputHandler::getOutStream().logfilename_.c_str(), std::fstream::out);
    139         OutputHandler::getOutStream().logfile_ << old.rdbuf();
    140         old.close();
    141         OutputHandler::getOutStream().logfile_.flush();
    142     }
    143 
    144     /**
    145         @brief Overloaded << operator, redirects the output to the console and the logfile.
    146         @param sb The streambuffer that should be shown in the console
    147         @return A reference to the OutputHandler itself
    148     */
    149     OutputHandler& OutputHandler::operator<<(std::streambuf* sb)
    150     {
    151         //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    152         //    std::cout << sb;
    153 
    154         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    155         {
    156             this->logfile_ << sb;
    157             this->logfile_.flush();
    158         }
    159 
    160         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    161             (*this->outputBuffer_) << sb;
    162 
    163         return *this;
    164     }
    165 
    166     /**
    167         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    168         @param manipulator A function, manipulating the outstream.
    169         @return A reference to the OutputHandler itself
    170     */
    171     OutputHandler& OutputHandler::operator<<(std::ostream& (*manipulator)(std::ostream&))
    172     {
    173         //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    174         //    manipulator(std::cout);
    175 
    176         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    177         {
    178             manipulator(this->logfile_);
    179             this->logfile_.flush();
    180         }
    181 
    182         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    183             (*this->outputBuffer_) << manipulator;
    184 
    185         return *this;
    186     }
    187 
    188     /**
    189         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    190         @param manipulator A function, manipulating the outstream.
    191         @return A reference to the OutputHandler itself
    192     */
    193     OutputHandler& OutputHandler::operator<<(std::ios& (*manipulator)(std::ios&))
    194     {
    195         //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    196         //    manipulator(std::cout);
    197 
    198         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    199         {
    200             manipulator(this->logfile_);
    201             this->logfile_.flush();
    202         }
    203 
    204         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    205             (*this->outputBuffer_) << manipulator;
    206 
    207         return *this;
    208     }
    209 
    210     /**
    211         @brief Overloaded << operator, redirects the output to the console, the logfile and the ingame shell.
    212         @param manipulator A function, manipulating the outstream.
    213         @return A reference to the OutputHandler itself
    214     */
    215     OutputHandler& OutputHandler::operator<<(std::ios_base& (*manipulator)(std::ios_base&))
    216     {
    217         //if (getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    218         //    manipulator(std::cout);
    219 
    220         if (getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
    221         {
    222             manipulator(this->logfile_);
    223             this->logfile_.flush();
    224         }
    225 
    226         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    227             (*this->outputBuffer_) << manipulator;
    228 
    229         return *this;
     209        this->logFile_->setLogPath(path);
     210    }
     211
     212    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorBegin() const
     213    {
     214        return this->output_->output_.begin();
     215    }
     216
     217    OutputHandler::OutputVectorIterator OutputHandler::getOutputVectorEnd() const
     218    {
     219        return this->output_->output_.end();
     220    }
     221
     222    int OutputHandler::getSoftDebugLevel(const std::string& name) const
     223    {
     224        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     225        {
     226            if ((*it)->name_ == name)
     227                return (*it)->softDebugLevel_;
     228        }
     229        return -1;
     230    }
     231
     232    void OutputHandler::setSoftDebugLevel(const std::string& name, int level)
     233    {
     234        int globalSoftDebugLevel = -1;
     235        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
     236        {
     237            if ((*it)->name_ == name)
     238                (*it)->softDebugLevel_ = level;
     239            if ((*it)->softDebugLevel_ > globalSoftDebugLevel)
     240                globalSoftDebugLevel = (*it)->softDebugLevel_;
     241        }
     242        // Update global soft debug level
     243        OutputHandler::softDebugLevel_s = globalSoftDebugLevel;
    230244    }
    231245}
  • code/branches/console/src/libraries/util/OutputHandler.h

    r5991 r5994  
    2323 *      Fabian 'x3n' Landau
    2424 *   Co-authors:
    25  *      ...
     25 *      Reto Grieder
    2626 *
    2727 */
    2828
    2929/**
    30     @file
    31     @brief Definition of the OutputHandler class.
    32 
    33     The OutputHandler acts like std::cout, but output isn't only shown in the console,
    34     but also written to the logfile and the ingame shell.
     30@file
     31@brief
     32    Declaration of classes related to output (logging).
    3533*/
    3634
     
    4038#include "UtilPrereqs.h"
    4139
    42 #include <iostream>
    43 #include <fstream>
     40#include <list>
     41#include <ostream>
    4442#include <string>
    45 
    46 #include "OutputBuffer.h"
     43#include <vector>
     44#include <utility>
    4745
    4846namespace orxonox
    4947{
     48    /**
     49    @brief
     50        Denotes different levels of text output (log output)
     51
     52        0, None   : Very important output
     53        1, Error  : Errors
     54        2, Warning: Warnings
     55        3, Info   : Information
     56        4, Debug  : Debug information
     57        5, Verbose: More debug information
     58        6, Ultra  : Crazy debug information
     59    */
    5060    namespace OutputLevel
    5161    {
     
    6272    }
    6373
    64     //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
     74    // Forward declarations for classes in the source file
     75    class LogFileWriter;
     76    class MemoryLogWriter;
     77
     78    /**
     79    @brief
     80        The OutputHandler acts like std::cout, but output isn't only shown in the console.
     81
     82        You can register your own listener for output by inheriting from OutputListner.
     83        And if you need the output previously processed, iterate over it with
     84        OutputHandler::getOutputVector[Begin/End].
     85        The way to output text is to first set the desired output level with
     86        OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
     87    */
    6588    class _UtilExport OutputHandler
    6689    {
    6790        public:
    68             enum OutputDevice
    69             {
    70                 LD_All = 0,
    71                 LD_Console = 1,
    72                 LD_Logfile = 2,
    73                 LD_Shell = 3
    74             };
    75 
    76             static OutputHandler& getOutStream();
     91            //! Returns a reference to the only existing instance of the OutputHandler class.
     92            static OutputHandler& getInstance();
     93
     94            //! Sets the output level and returns a stream to be used with "<<"
    7795            static inline OutputHandler& getOutStream(int level)
    78                 { return OutputHandler::getOutStream().setOutputLevel(level); }
    79 
    80             /** @brief Puts some text on the outstream. @param text The text */
     96                { return OutputHandler::getInstance().setOutputLevel(level); }
     97
     98            typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
     99            //! Returns an iterator to the beginning of the all-output vector
     100            OutputVectorIterator getOutputVectorBegin() const;
     101            //! Returns an iterator to the end of the all-output vector
     102            OutputVectorIterator getOutputVectorEnd() const;
     103
     104            //! Writes to all output devices
    81105            static inline const std::string& log(const std::string& text)
    82                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
    83 
    84             /** @brief Puts an error on the outstream. @param text The text */
     106                { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
     107
     108            //! Writes an error message to the output
    85109            static inline const std::string& error(const std::string& text)
    86                 { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
    87 
    88             /** @brief Puts a warning on the outstream. @param text The text */
     110                { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
     111
     112            //! Writes a warning message to the output
    89113            static inline const std::string& warning(const std::string& text)
    90                 { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
    91 
    92             /** @brief Puts an info on the outstream. @param text The text */
     114                { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
     115
     116            //! Writes an informational message to the output
    93117            static inline const std::string& info(const std::string& text)
    94                 { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
    95 
    96             /** @brief Puts some debug output on the outstream. @param text The text */
     118                { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
     119
     120            //! Writes a debug message to the output
    97121            static inline const std::string& debug(const std::string& text)
    98                 { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
    99 
    100             /** @brief Returns a reference to the logfile. @return The logfile */
    101             inline std::ofstream& getLogfile()
    102                 { return this->logfile_; }
    103 
    104             /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
    105             inline OutputBuffer* getOutputBuffer()
    106                 { return this->outputBuffer_; }
    107 
    108             /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
     122                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
     123
     124            //! Registers an object that receives output via a provided std::ostream
     125            void registerOutputListener(OutputListener* listener);
     126            //! Unregisters an object that receives output via a provided std::ostream
     127            void unregisterOutputListener(OutputListener* listener);
     128
     129            //! Set the log path once the program has been properly initialised
     130            void setLogPath(const std::string& path);
     131
     132            //! Sets the level of the incoming output and returns the OutputHandler
    109133            inline OutputHandler& setOutputLevel(int level)
    110134                { this->outputLevel_ = level; return *this; }
    111135
    112             /** @brief Returns the level of the incoming output. @return The level */
     136            //! Returns the level of the incoming output
    113137            inline int getOutputLevel() const
    114138                { return this->outputLevel_; }
    115139
    116             static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    117             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    118 
    119             static void setLogPath(const std::string& path);
    120 
    121             void setOutputBuffer(OutputBuffer* buffer);
    122 
     140            //! Returns the maximum debug level over all registered listeners (devices)
     141            static int getSoftDebugLevel() { return softDebugLevel_s; }
     142            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
     143            int  getSoftDebugLevel(const std::string& name) const;
     144            //! Sets the soft debug level for a listener by its name
     145            void setSoftDebugLevel(const std::string& name, int level);
     146
     147            /**
     148            @brief
     149                General template that copes with all output.
     150                Required because operator << might be ambiguous.
     151                @a output will be streamed into every listener with an appropriate debug level
     152            @return
     153                Returns a reference to the OutputHandler so you can use it again directly
     154            */
    123155            template <class T>
    124156            OutputHandler& output(const T& output);
    125157
    126             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     158            //! Overloaded << operator, redirects the output to the listeners
    127159            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
    128             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     160            //! Overloaded << operator, redirects the output to the listeners
    129161            inline OutputHandler& operator<<(short val)              { return this->output(val); }
    130             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     162            //! Overloaded << operator, redirects the output to the listeners
    131163            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
    132             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     164            //! Overloaded << operator, redirects the output to the listeners
    133165            inline OutputHandler& operator<<(int val)                { return this->output(val); }
    134             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     166            //! Overloaded << operator, redirects the output to the listeners
    135167            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
    136             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     168            //! Overloaded << operator, redirects the output to the listeners
    137169            inline OutputHandler& operator<<(long val)               { return this->output(val); }
    138             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     170            //! Overloaded << operator, redirects the output to the listeners
    139171            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
    140             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     172            //! Overloaded << operator, redirects the output to the listeners
    141173            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
    142             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     174            //! Overloaded << operator, redirects the output to the listeners
    143175            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
    144             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     176            //! Overloaded << operator, redirects the output to the listeners
    145177            inline OutputHandler& operator<<(float val)              { return this->output(val); }
    146             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     178            //! Overloaded << operator, redirects the output to the listeners
    147179            inline OutputHandler& operator<<(double val)             { return this->output(val); }
    148             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     180            //! Overloaded << operator, redirects the output to the listeners
    149181            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
    150             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     182            //! Overloaded << operator, redirects the output to the listeners
    151183            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
    152             /** @brief Overloaded << operator, redirects the output to the console and the logfile. @param val The value that should be shown in the console @return A reference to the OutputHandler itself */
     184            //! Overloaded << operator, redirects the output to the listeners
    153185            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
    154186
    155             OutputHandler& operator<<(std::streambuf* sb);
    156 
    157             OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
    158             OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
    159             OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
    160 
    161             /** @brief Dummy operator required by Debug.h for the ternary operator */
    162             inline operator int() { return 0; }
     187            //! Overloaded << operator, redirects the output to the listeners
     188            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
     189
     190            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
     191            template <class T>
     192            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
     193
     194            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     195            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
     196            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     197            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
     198            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     199            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
     200
     201            //! Dummy operator required by Debug.h for the ternary operator
     202            inline operator int() const { return 0; }
     203
     204            //! Name of the OutputListener that writes to the log file
     205            static const std::string logFileOutputListenerName_s;
    163206
    164207        private:
    165             explicit OutputHandler();
    166             OutputHandler(const OutputHandler& oh);
    167             virtual ~OutputHandler();
    168 
    169             std::ofstream logfile_;              //!< The logfile where the output is logged
    170             std::string logfilename_;            //!< The name of the logfile
    171             OutputBuffer fallbackBuffer_;        //!< The OutputBuffer that gets used if there is no other OutputBuffer
    172             OutputBuffer* outputBuffer_;         //!< The OutputBuffer to put output in (usually used by the Shell)
    173             int outputLevel_;                    //!< The level of the incoming output
    174             int softDebugLevel_[4];              //!< The soft debug level for each OutputDevice - the configurable maximal output level
     208            OutputHandler();
     209            ~OutputHandler();
     210            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
     211
     212            std::list<OutputListener*> listeners_; //!< Array with all registered output listeners
     213            int outputLevel_;                      //!< The level of the incoming output
     214            LogFileWriter* logFile_;               //!< Listener that writes to the log file
     215            MemoryLogWriter* output_;              //!< Listener that Stores ALL output below the current soft debug level
     216            static int softDebugLevel_s;           //!< Maximum of all soft debug levels. @note This is only static for faster access
    175217    };
    176218
    177     /**
    178         @brief Redirects the output to the console and the logfile.
    179         @param output The value that should be shown in the console
    180         @return A reference to the OutputHandler itself
    181     */
    182219    template<class T>
    183     OutputHandler& OutputHandler::output(const T& output)
    184     {
    185         //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    186         //    std::cout << output;
    187 
    188         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
     220    inline OutputHandler& OutputHandler::output(const T& output)
     221    {
     222        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
    189223        {
    190             this->logfile_ << output;
    191             this->logfile_.flush();
     224            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
     225            {
     226                std::ostream& stream = *((*it)->outputStream_);
     227                stream << output;
     228                stream.flush();
     229                (*it)->outputChanged();
     230            }
    192231        }
    193 
    194         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    195             (*this->outputBuffer_) << output;
    196232
    197233        return *this;
     
    199235
    200236    /**
    201         @brief Overloading of the non-member << operator to redirect the output of classes with self defined '<< to std::ostream' operators to the console and the logfile.
    202         @param out The OutputHandler itself
    203         @param output The class that should be shown in the console
    204         @return The OutputHandler itself
     237    @brief
     238        Interface for listening to output.
     239    @remarks
     240        Remember to register the listener (not done automatically!)
    205241    */
    206     template<class T>
    207     OutputHandler& operator<<(OutputHandler& out, const T& output)
    208     {
    209         //if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
    210         //    std::cout << output;
    211 
    212         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
    213         {
    214             out.getLogfile() << output;
    215             out.getLogfile().flush();
    216         }
    217 
    218         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
    219             (*out.getOutputBuffer()) << output;
    220 
    221         return out;
    222     }
     242    class OutputListener
     243    {
     244        friend class OutputHandler;
     245
     246    public:
     247        OutputListener(const std::string& name)
     248            : outputStream_(NULL)
     249            , name_(name)
     250        {}
     251        virtual ~OutputListener() {}
     252
     253        //! Gets called whenever output is put into the stream
     254        virtual void outputChanged() {}
     255        //! Returns the name of this output listener
     256        const std::string& getOutputListenerName() const { return this->name_; }
     257
     258    protected:
     259        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
     260
     261    private:
     262        const std::string name_;           //!< Name of the listener, constant and unique!
     263        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
     264    };
    223265}
    224266
  • code/branches/console/src/libraries/util/UtilPrereqs.h

    r5929 r5994  
    8787    class IntVector3;
    8888    class MultiType;
    89     class OutputBuffer;
    90     class OutputBufferListener;
    9189    class OutputHandler;
     90    class OutputListener;
    9291    template <ScopeID::Value>
    9392    class Scope;
Note: See TracChangeset for help on using the changeset viewer.