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/util
Files:
2 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • 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.