Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Nov 20, 2009, 4:55:40 PM (14 years ago)
Author:
rgrieder
Message:

Merged console branch back to trunk.

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/libraries/util/OutputHandler.h

    r5738 r6105  
    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{
    50     //! The OutputHandler acts like std::cout, but redirects output to the console, the logfile and the ingame shell.
     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    */
     60    namespace OutputLevel
     61    {
     62        enum Value
     63        {
     64            None    = 0,
     65            Error   = 1,
     66            Warning = 2,
     67            Info    = 3,
     68            Debug   = 4,
     69            Verbose = 5,
     70            Ultra   = 6,
     71        };
     72    }
     73
     74    // Forward declarations for classes in the source file
     75    class LogFileWriter;
     76    class ConsoleWriter;
     77    class MemoryLogWriter;
     78
     79    /**
     80    @brief
     81        The OutputHandler acts like std::cout, but output isn't only shown in the console.
     82
     83        You can register your own listener for output by inheriting from OutputListner.
     84        And if you need the output previously processed, iterate over it with
     85        OutputHandler::getOutputVector[Begin/End].
     86        The way to output text is to first set the desired output level with
     87        OutputHandler::getOutStream(level) and then use the "<<" operator like with std::cout.
     88    */
    5189    class _UtilExport OutputHandler
    5290    {
    5391        public:
    54             enum OutputDevice
    55             {
    56                 LD_All = 0,
    57                 LD_Console = 1,
    58                 LD_Logfile = 2,
    59                 LD_Shell = 3
    60             };
    61 
    62             static OutputHandler& getOutStream();
    63 
    64             /** @brief Puts some text on the outstream. @param text The text */
     92            //! Returns a reference to the only existing instance of the OutputHandler class.
     93            static OutputHandler& getInstance();
     94
     95            //! Sets the output level and returns a stream to be used with "<<"
     96            static inline OutputHandler& getOutStream(int level)
     97                { return OutputHandler::getInstance().setOutputLevel(level); }
     98
     99            typedef std::vector<std::pair<int, std::string> >::const_iterator OutputVectorIterator;
     100            //! Returns an iterator to the beginning of the all-output vector
     101            OutputVectorIterator getOutputVectorBegin() const;
     102            //! Returns an iterator to the end of the all-output vector
     103            OutputVectorIterator getOutputVectorEnd() const;
     104
     105            //! Writes to all output devices
    65106            static inline const std::string& log(const std::string& text)
    66                 { OutputHandler::getOutStream().setOutputLevel(0); OutputHandler::getOutStream().output(text + "\n"); return text; }
    67 
    68             /** @brief Puts an error on the outstream. @param text The text */
     107                { OutputHandler::getOutStream(0).output(text) << std::endl; return text; }
     108
     109            //! Writes an error message to the output
    69110            static inline const std::string& error(const std::string& text)
    70                 { OutputHandler::getOutStream().setOutputLevel(1); OutputHandler::getOutStream().output(text + "\n"); return text; }
    71 
    72             /** @brief Puts a warning on the outstream. @param text The text */
     111                { OutputHandler::getOutStream(1).output(text) << std::endl; return text; }
     112
     113            //! Writes a warning message to the output
    73114            static inline const std::string& warning(const std::string& text)
    74                 { OutputHandler::getOutStream().setOutputLevel(2); OutputHandler::getOutStream().output(text + "\n"); return text; }
    75 
    76             /** @brief Puts an info on the outstream. @param text The text */
     115                { OutputHandler::getOutStream(2).output(text) << std::endl; return text; }
     116
     117            //! Writes an informational message to the output
    77118            static inline const std::string& info(const std::string& text)
    78                 { OutputHandler::getOutStream().setOutputLevel(3); OutputHandler::getOutStream().output(text + "\n"); return text; }
    79 
    80             /** @brief Puts some debug output on the outstream. @param text The text */
     119                { OutputHandler::getOutStream(3).output(text) << std::endl; return text; }
     120
     121            //! Writes a debug message to the output
    81122            static inline const std::string& debug(const std::string& text)
    82                 { OutputHandler::getOutStream().setOutputLevel(4); OutputHandler::getOutStream().output(text + "\n"); return text; }
    83 
    84             /** @brief Returns a reference to the logfile. @return The logfile */
    85             inline std::ofstream& getLogfile()
    86                 { return this->logfile_; }
    87 
    88             /** @brief Returns a pointer to the OutputBuffer. @return The OutputBuffer */
    89             inline OutputBuffer* getOutputBuffer()
    90                 { return this->outputBuffer_; }
    91 
    92             /** @brief Sets the level of the incoming output. @param level The level of the incoming output @return The OutputHandler itself */
     123                { OutputHandler::getOutStream(4).output(text) << std::endl; return text; }
     124
     125            //! Registers an object that receives output via a provided std::ostream
     126            void registerOutputListener(OutputListener* listener);
     127            //! Unregisters an object that receives output via a provided std::ostream
     128            void unregisterOutputListener(OutputListener* listener);
     129
     130            //! Set the log path once the program has been properly initialised
     131            void setLogPath(const std::string& path);
     132            //! Disables the std::cout stream for output
     133            void disableCout();
     134            //! Enables the std::cout stream for output (startup behaviour)
     135            void enableCout();
     136
     137            //! Sets the level of the incoming output and returns the OutputHandler
    93138            inline OutputHandler& setOutputLevel(int level)
    94139                { this->outputLevel_ = level; return *this; }
    95140
    96             /** @brief Returns the level of the incoming output. @return The level */
     141            //! Returns the level of the incoming output
    97142            inline int getOutputLevel() const
    98143                { return this->outputLevel_; }
    99144
    100             static void setSoftDebugLevel(OutputHandler::OutputDevice device, int level);
    101             static int getSoftDebugLevel(OutputHandler::OutputDevice device = OutputHandler::LD_All);
    102 
    103             static void setLogPath(const std::string& path);
    104 
    105             void setOutputBuffer(OutputBuffer* buffer);
    106 
     145            //! Returns the maximum debug level over all registered listeners (devices)
     146            static int getSoftDebugLevel() { return softDebugLevel_s; }
     147            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
     148            int  getSoftDebugLevel(const std::string& name) const;
     149            //! Sets the soft debug level for a listener by its name   @remarks Only works for registered listeners!
     150            void setSoftDebugLevel(const std::string& name, int level);
     151
     152            /**
     153            @brief
     154                General template that copes with all output.
     155                Required because operator << might be ambiguous.
     156                @a output will be streamed into every listener with an appropriate debug level
     157            @return
     158                Returns a reference to the OutputHandler so you can use it again directly
     159            */
    107160            template <class T>
    108161            OutputHandler& output(const T& output);
    109162
    110             /** @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 */
     163            //! Overloaded << operator, redirects the output to the listeners
    111164            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
    112             /** @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 */
     165            //! Overloaded << operator, redirects the output to the listeners
    113166            inline OutputHandler& operator<<(short val)              { return this->output(val); }
    114             /** @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 */
     167            //! Overloaded << operator, redirects the output to the listeners
    115168            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
    116             /** @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 */
     169            //! Overloaded << operator, redirects the output to the listeners
    117170            inline OutputHandler& operator<<(int val)                { return this->output(val); }
    118             /** @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 */
     171            //! Overloaded << operator, redirects the output to the listeners
    119172            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
    120             /** @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 */
     173            //! Overloaded << operator, redirects the output to the listeners
    121174            inline OutputHandler& operator<<(long val)               { return this->output(val); }
    122             /** @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 */
     175            //! Overloaded << operator, redirects the output to the listeners
    123176            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
    124             /** @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 */
     177            //! Overloaded << operator, redirects the output to the listeners
    125178            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
    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 */
     179            //! Overloaded << operator, redirects the output to the listeners
    127180            inline OutputHandler& operator<<(unsigned long long 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 */
     181            //! Overloaded << operator, redirects the output to the listeners
    129182            inline OutputHandler& operator<<(float 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 */
     183            //! Overloaded << operator, redirects the output to the listeners
    131184            inline OutputHandler& operator<<(double 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 */
     185            //! Overloaded << operator, redirects the output to the listeners
    133186            inline OutputHandler& operator<<(long double 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 */
     187            //! Overloaded << operator, redirects the output to the listeners
    135188            inline OutputHandler& operator<<(const void* 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 */
     189            //! Overloaded << operator, redirects the output to the listeners
    137190            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
    138191
    139             OutputHandler& operator<<(std::streambuf* sb);
    140 
    141             OutputHandler& operator<<(std::ostream& (*manipulator)(std::ostream&));
    142             OutputHandler& operator<<(std::ios& (*manipulator)(std::ios&));
    143             OutputHandler& operator<<(std::ios_base& (*manipulator)(std::ios_base&));
     192            //! Overloaded << operator, redirects the output to the listeners
     193            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
     194
     195            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
     196            template <class T>
     197            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
     198
     199            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     200            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
     201            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     202            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
     203            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
     204            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
     205
     206            //! Dummy operator required by Debug.h for the ternary operator
     207            inline operator int() const { return 0; }
     208
     209            //! Name of the OutputListener that writes to the log file
     210            static const std::string logFileOutputListenerName_s;
    144211
    145212        private:
    146             explicit OutputHandler();
    147             OutputHandler(const OutputHandler& oh);
    148             virtual ~OutputHandler();
    149 
    150             std::ofstream logfile_;              //!< The logfile where the output is logged
    151             std::string logfilename_;            //!< The name of the logfile
    152             OutputBuffer fallbackBuffer_;        //!< The OutputBuffer that gets used if there is no other OutputBuffer
    153             OutputBuffer* outputBuffer_;         //!< The OutputBuffer to put output in (usually used by the Shell)
    154             int outputLevel_;                    //!< The level of the incoming output
    155             int softDebugLevel_[4];              //!< The soft debug level for each OutputDevice - the configurable maximal output level
     213            OutputHandler();
     214            ~OutputHandler();
     215            OutputHandler(const OutputHandler& rhs); //! Unused and undefined
     216
     217            std::list<OutputListener*> listeners_;        //!< Array with all registered output listeners
     218            int                        outputLevel_;      //!< The level of the incoming output
     219            LogFileWriter*             logFile_;          //!< Listener that writes to the log file
     220            ConsoleWriter*             consoleWriter_;    //!< Listener for std::cout (just program beginning)
     221            MemoryLogWriter*           output_;           //!< Listener that Stores ALL output below the current soft debug level
     222            static int                 softDebugLevel_s;  //!< Maximum of all soft debug levels. @note This is only static for faster access
    156223    };
    157224
    158225    /**
    159         @brief Redirects the output to the console and the logfile.
    160         @param output The value that should be shown in the console
    161         @return A reference to the OutputHandler itself
     226    @brief
     227        Interface for listening to output.
     228    @remarks
     229        Remember to register the listener (not done automatically!)
    162230    */
     231    class OutputListener
     232    {
     233        friend class OutputHandler;
     234
     235    public:
     236        OutputListener(const std::string& name)
     237            : outputStream_(NULL)
     238            , name_(name)
     239            , softDebugLevel_(OutputLevel::Info)
     240        {}
     241        virtual ~OutputListener() {}
     242
     243        //! Gets called whenever output is put into the stream
     244        virtual void outputChanged(int level) {}
     245        //! Returns the name of this output listener
     246        const std::string& getOutputListenerName() const { return this->name_; }
     247        //! Returns the soft debug level of the listener
     248        int getSoftDebugLevel() const { return this->softDebugLevel_; }
     249        //! Sets the soft debug level of the listener
     250        void setSoftDebugLevel(int level)
     251        {
     252            this->softDebugLevel_ = level;
     253            OutputHandler::getInstance().setSoftDebugLevel(this->name_, level);
     254        }
     255
     256    protected:
     257        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
     258
     259    private:
     260        const std::string name_;           //!< Name of the listener, constant and unique!
     261        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
     262    };
     263
    163264    template<class T>
    164     OutputHandler& OutputHandler::output(const T& output)
    165     {
    166         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= this->outputLevel_)
    167             std::cout << output;
    168 
    169         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= this->outputLevel_)
     265    inline OutputHandler& OutputHandler::output(const T& output)
     266    {
     267        for (std::list<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
    170268        {
    171             this->logfile_ << output;
    172             this->logfile_.flush();
     269            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
     270            {
     271                std::ostream& stream = *((*it)->outputStream_);
     272                stream << output;
     273                stream.flush();
     274                (*it)->outputChanged(this->outputLevel_);
     275            }
    173276        }
    174 
    175         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= this->outputLevel_)
    176             (*this->outputBuffer_) << output;
    177277
    178278        return *this;
    179279    }
    180 
    181     /**
    182         @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.
    183         @param out The OutputHandler itself
    184         @param output The class that should be shown in the console
    185         @return The OutputHandler itself
    186     */
    187     template<class T>
    188     OutputHandler& operator<<(OutputHandler& out, const T& output)
    189     {
    190         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Console) >= out.getOutputLevel())
    191             std::cout << output;
    192 
    193         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Logfile) >= out.getOutputLevel())
    194         {
    195             out.getLogfile() << output;
    196             out.getLogfile().flush();
    197         }
    198 
    199         if (OutputHandler::getSoftDebugLevel(OutputHandler::LD_Shell) >= out.getOutputLevel())
    200             (*out.getOutputBuffer()) << output;
    201 
    202         return out;
    203     }
    204280}
    205281
Note: See TracChangeset for help on using the changeset viewer.