Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/unity_build/src/libraries/util/OutputHandler.h @ 8678

Last change on this file since 8678 was 8524, checked in by rgrieder, 14 years ago

Fixed a serious problem with the debug levels for the Shells by introducing DevModeListener and moving the debug levels to the Shell again..

  • Property svn:eol-style set to native
File size: 12.9 KB
RevLine 
[1505]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
[6105]25 *      Reto Grieder
[1505]26 *
27 */
28
29/**
[6105]30@file
[7401]31@ingroup Util Output
[6105]32@brief
[7401]33    Declaration of classes related to output (logging), most notably OutputHandler and OutputListener.
[1505]34*/
35
36#ifndef _OutputHandler_H__
37#define _OutputHandler_H__
38
[1586]39#include "UtilPrereqs.h"
[1505]40
[6105]41#include <ostream>
[1505]42#include <string>
[6105]43#include <vector>
44#include <utility>
[1505]45
46namespace orxonox
47{
[6105]48    /**
49    @brief
50        Denotes different levels of text output (log output)
51
[7401]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
[6105]59    */
60    namespace OutputLevel
61    {
62        enum Value
63        {
[8522]64            TDebug  = -1,
[6105]65            None    = 0,
66            Error   = 1,
67            Warning = 2,
68            Info    = 3,
69            Debug   = 4,
70            Verbose = 5,
71            Ultra   = 6,
72        };
73    }
74
75    // Forward declarations for classes in the source file
76    class LogFileWriter;
77    class ConsoleWriter;
78    class MemoryLogWriter;
79
80    /**
81    @brief
[7401]82        The OutputHandler acts like @c std::cout, but output isn't only shown in the console.
[6105]83
[7401]84        Output passed to the OutputHandler is distributed to all registered listeners,
85        for example the console, the logfile, or the ingame shell.
86
87        You can register your own listener for output by inheriting from OutputListener.
[6105]88        And if you need the output previously processed, iterate over it with
[7401]89        OutputHandler::getOutputVectorBegin and OutputHandler::getOutputVectorEnd.
90
[6105]91        The way to output text is to first set the desired output level with
[7401]92        @ref getOutStream "OutputHandler::getOutStream(level)" and then use
93        the "<<" operator like with @c std::cout. Alternatively you can use the COUT() macro.
[6105]94    */
[1586]95    class _UtilExport OutputHandler
[1505]96    {
97        public:
[6105]98            //! Returns a reference to the only existing instance of the OutputHandler class.
99            static OutputHandler& getInstance();
[1505]100
[6105]101            //! Sets the output level and returns a stream to be used with "<<"
102            static inline OutputHandler& getOutStream(int level)
103                { return OutputHandler::getInstance().setOutputLevel(level); }
[1505]104
[8515]105            typedef std::vector<std::pair<int, std::string> > OutputVector;
106            //! Returns all output written so far (empty if disableMemoryLog() was called)
107            const OutputVector& getOutput() const;
[6105]108
109            //! Writes to all output devices
[7284]110            static inline void log(const std::string& text)
111                { OutputHandler::getOutStream(0).output(text) << std::endl; }
[1505]112
[6105]113            //! Writes an error message to the output
[7284]114            static inline void error(const std::string& text)
115                { OutputHandler::getOutStream(1).output(text) << std::endl; }
[1505]116
[6105]117            //! Writes a warning message to the output
[7284]118            static inline void warning(const std::string& text)
119                { OutputHandler::getOutStream(2).output(text) << std::endl; }
[1505]120
[6105]121            //! Writes an informational message to the output
[7284]122            static inline void info(const std::string& text)
123                { OutputHandler::getOutStream(3).output(text) << std::endl; }
[1505]124
[6105]125            //! Writes a debug message to the output
[7284]126            static inline void debug(const std::string& text)
127                { OutputHandler::getOutStream(4).output(text) << std::endl; }
[1505]128
[6105]129            //! Registers an object that receives output via a provided std::ostream
130            void registerOutputListener(OutputListener* listener);
131            //! Unregisters an object that receives output via a provided std::ostream
132            void unregisterOutputListener(OutputListener* listener);
[1505]133
[6105]134            //! Set the log path once the program has been properly initialised
135            void setLogPath(const std::string& path);
[8517]136            /** Rewrites the log file (completely respects the current debug level).
137                Once disableMemoryLog() has been called, this function will do nothing.
138            */
139            void rewriteLogFile();
140
[6105]141            //! Disables the std::cout stream for output
142            void disableCout();
143            //! Enables the std::cout stream for output (startup behaviour)
144            void enableCout();
[8515]145            //! Stop writing to the memory buffer (call this as soon as possible to minimise memory usage)
146            void disableMemoryLog();
[1586]147
[6105]148            //! Sets the level of the incoming output and returns the OutputHandler
[1505]149            inline OutputHandler& setOutputLevel(int level)
150                { this->outputLevel_ = level; return *this; }
151
[6105]152            //! Returns the level of the incoming output
[1505]153            inline int getOutputLevel() const
154                { return this->outputLevel_; }
155
[6105]156            //! Returns the maximum debug level over all registered listeners (devices)
157            static int getSoftDebugLevel() { return softDebugLevel_s; }
158            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
159            int  getSoftDebugLevel(const std::string& name) const;
160            //! Sets the soft debug level for a listener by its name   @remarks Only works for registered listeners!
161            void setSoftDebugLevel(const std::string& name, int level);
[1505]162
[6105]163            /**
164            @brief
165                General template that copes with all output.
166                Required because operator << might be ambiguous.
167                @a output will be streamed into every listener with an appropriate debug level
168            @return
169                Returns a reference to the OutputHandler so you can use it again directly
170            */
[1505]171            template <class T>
172            OutputHandler& output(const T& output);
173
[6105]174            //! Overloaded << operator, redirects the output to the listeners
[1725]175            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
[6105]176            //! Overloaded << operator, redirects the output to the listeners
[1725]177            inline OutputHandler& operator<<(short val)              { return this->output(val); }
[6105]178            //! Overloaded << operator, redirects the output to the listeners
[1725]179            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
[6105]180            //! Overloaded << operator, redirects the output to the listeners
[1725]181            inline OutputHandler& operator<<(int val)                { return this->output(val); }
[6105]182            //! Overloaded << operator, redirects the output to the listeners
[1725]183            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
[6105]184            //! Overloaded << operator, redirects the output to the listeners
[1725]185            inline OutputHandler& operator<<(long val)               { return this->output(val); }
[6105]186            //! Overloaded << operator, redirects the output to the listeners
[1725]187            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
[6105]188            //! Overloaded << operator, redirects the output to the listeners
[1725]189            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
[6105]190            //! Overloaded << operator, redirects the output to the listeners
[1725]191            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
[6105]192            //! Overloaded << operator, redirects the output to the listeners
[1725]193            inline OutputHandler& operator<<(float val)              { return this->output(val); }
[6105]194            //! Overloaded << operator, redirects the output to the listeners
[1725]195            inline OutputHandler& operator<<(double val)             { return this->output(val); }
[6105]196            //! Overloaded << operator, redirects the output to the listeners
[1725]197            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
[6105]198            //! Overloaded << operator, redirects the output to the listeners
[1725]199            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
[6105]200            //! Overloaded << operator, redirects the output to the listeners
[1725]201            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
[1505]202
[6105]203            //! Overloaded << operator, redirects the output to the listeners
204            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
[1505]205
[6105]206            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
207            template <class T>
208            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
[1505]209
[6105]210            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
211            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
212            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
213            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
214            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
215            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
216
217            //! Dummy operator required by Debug.h for the ternary operator
218            inline operator int() const { return 0; }
219
[1505]220        private:
[6105]221            OutputHandler();
222            ~OutputHandler();
[7401]223            OutputHandler(const OutputHandler& rhs);      //!< Copy-constructor: Unused and undefined
[1586]224
[8516]225            /// Evaluates the maximum global log level
226            void updateGlobalDebugLevel();
227
228            std::vector<OutputListener*> listeners_;        //!< Array with all registered output listeners
229            int                          outputLevel_;      //!< The level of the incoming output
230            LogFileWriter*               logFile_;          //!< Writes output to the log file
231            ConsoleWriter*               consoleWriter_;    //!< Writes to std::cout (can be disabled)
232            MemoryLogWriter*             memoryBuffer_;     //!< Writes to memory as a buffer (can/must be stopped at some time)
233            static int                   softDebugLevel_s;  //!< Maximum of all soft debug levels. @note This is only static for faster access
[1505]234    };
235
236    /**
[6105]237    @brief
238        Interface for listening to output.
239    @remarks
240        Remember to register the listener (not done automatically!)
[1505]241    */
[6105]242    class OutputListener
[1505]243    {
[6105]244        friend class OutputHandler;
[1505]245
[6105]246    public:
247        OutputListener(const std::string& name)
248            : outputStream_(NULL)
249            , name_(name)
250            , softDebugLevel_(OutputLevel::Info)
251        {}
252        virtual ~OutputListener() {}
253
254        //! Gets called whenever output is put into the stream
255        virtual void outputChanged(int level) {}
256        //! Returns the name of this output listener
257        const std::string& getOutputListenerName() const { return this->name_; }
[1505]258
[6105]259    protected:
260        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
[1505]261
[6105]262    private:
263        const std::string name_;           //!< Name of the listener, constant and unique!
264        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
265    };
[1505]266
267    template<class T>
[6105]268    inline OutputHandler& OutputHandler::output(const T& output)
[1505]269    {
[8516]270        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
[1505]271        {
[6105]272            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
273            {
274                std::ostream& stream = *((*it)->outputStream_);
275                stream << output;
276                stream.flush();
277                (*it)->outputChanged(this->outputLevel_);
278            }
[1505]279        }
280
[6105]281        return *this;
[1505]282    }
283}
284
285#endif /* _OutputHandler_H__ */
Note: See TracBrowser for help on using the repository browser.