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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.