Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8518 was 8518, checked in by rgrieder, 13 years ago

Sorted out log level handling on startup and transferred its control back to Core.

  • Property svn:eol-style set to native
File size: 13.0 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        {
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
[7401]81        The OutputHandler acts like @c std::cout, but output isn't only shown in the console.
[6105]82
[7401]83        Output passed to the OutputHandler is distributed to all registered listeners,
84        for example the console, the logfile, or the ingame shell.
85
86        You can register your own listener for output by inheriting from OutputListener.
[6105]87        And if you need the output previously processed, iterate over it with
[7401]88        OutputHandler::getOutputVectorBegin and OutputHandler::getOutputVectorEnd.
89
[6105]90        The way to output text is to first set the desired output level with
[7401]91        @ref getOutStream "OutputHandler::getOutStream(level)" and then use
92        the "<<" operator like with @c std::cout. Alternatively you can use the COUT() macro.
[6105]93    */
[1586]94    class _UtilExport OutputHandler
[1505]95    {
96        public:
[6105]97            //! Returns a reference to the only existing instance of the OutputHandler class.
98            static OutputHandler& getInstance();
[1505]99
[6105]100            //! Sets the output level and returns a stream to be used with "<<"
101            static inline OutputHandler& getOutStream(int level)
102                { return OutputHandler::getInstance().setOutputLevel(level); }
[1505]103
[8515]104            typedef std::vector<std::pair<int, std::string> > OutputVector;
105            //! Returns all output written so far (empty if disableMemoryLog() was called)
106            const OutputVector& getOutput() const;
[6105]107
108            //! Writes to all output devices
[7284]109            static inline void log(const std::string& text)
110                { OutputHandler::getOutStream(0).output(text) << std::endl; }
[1505]111
[6105]112            //! Writes an error message to the output
[7284]113            static inline void error(const std::string& text)
114                { OutputHandler::getOutStream(1).output(text) << std::endl; }
[1505]115
[6105]116            //! Writes a warning message to the output
[7284]117            static inline void warning(const std::string& text)
118                { OutputHandler::getOutStream(2).output(text) << std::endl; }
[1505]119
[6105]120            //! Writes an informational message to the output
[7284]121            static inline void info(const std::string& text)
122                { OutputHandler::getOutStream(3).output(text) << std::endl; }
[1505]123
[6105]124            //! Writes a debug message to the output
[7284]125            static inline void debug(const std::string& text)
126                { OutputHandler::getOutStream(4).output(text) << std::endl; }
[1505]127
[6105]128            //! Registers an object that receives output via a provided std::ostream
129            void registerOutputListener(OutputListener* listener);
130            //! Unregisters an object that receives output via a provided std::ostream
131            void unregisterOutputListener(OutputListener* listener);
[1505]132
[6105]133            //! Set the log path once the program has been properly initialised
134            void setLogPath(const std::string& path);
[8517]135            /** Rewrites the log file (completely respects the current debug level).
136                Once disableMemoryLog() has been called, this function will do nothing.
137            */
138            void rewriteLogFile();
139
[6105]140            //! Disables the std::cout stream for output
141            void disableCout();
142            //! Enables the std::cout stream for output (startup behaviour)
143            void enableCout();
[8515]144            //! Stop writing to the memory buffer (call this as soon as possible to minimise memory usage)
145            void disableMemoryLog();
[1586]146
[6105]147            //! Sets the level of the incoming output and returns the OutputHandler
[1505]148            inline OutputHandler& setOutputLevel(int level)
149                { this->outputLevel_ = level; return *this; }
150
[6105]151            //! Returns the level of the incoming output
[1505]152            inline int getOutputLevel() const
153                { return this->outputLevel_; }
154
[6105]155            //! Returns the maximum debug level over all registered listeners (devices)
156            static int getSoftDebugLevel() { return softDebugLevel_s; }
157            //! Returns the soft debug level for a device by its name   @return The level or -1 if the listener was not found
158            int  getSoftDebugLevel(const std::string& name) const;
159            //! Sets the soft debug level for a listener by its name   @remarks Only works for registered listeners!
160            void setSoftDebugLevel(const std::string& name, int level);
[1505]161
[6105]162            /**
163            @brief
164                General template that copes with all output.
165                Required because operator << might be ambiguous.
166                @a output will be streamed into every listener with an appropriate debug level
167            @return
168                Returns a reference to the OutputHandler so you can use it again directly
169            */
[1505]170            template <class T>
171            OutputHandler& output(const T& output);
172
[6105]173            //! Overloaded << operator, redirects the output to the listeners
[1725]174            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
[6105]175            //! Overloaded << operator, redirects the output to the listeners
[1725]176            inline OutputHandler& operator<<(short val)              { return this->output(val); }
[6105]177            //! Overloaded << operator, redirects the output to the listeners
[1725]178            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
[6105]179            //! Overloaded << operator, redirects the output to the listeners
[1725]180            inline OutputHandler& operator<<(int val)                { return this->output(val); }
[6105]181            //! Overloaded << operator, redirects the output to the listeners
[1725]182            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
[6105]183            //! Overloaded << operator, redirects the output to the listeners
[1725]184            inline OutputHandler& operator<<(long val)               { return this->output(val); }
[6105]185            //! Overloaded << operator, redirects the output to the listeners
[1725]186            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
[6105]187            //! Overloaded << operator, redirects the output to the listeners
[1725]188            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
[6105]189            //! Overloaded << operator, redirects the output to the listeners
[1725]190            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
[6105]191            //! Overloaded << operator, redirects the output to the listeners
[1725]192            inline OutputHandler& operator<<(float val)              { return this->output(val); }
[6105]193            //! Overloaded << operator, redirects the output to the listeners
[1725]194            inline OutputHandler& operator<<(double val)             { return this->output(val); }
[6105]195            //! Overloaded << operator, redirects the output to the listeners
[1725]196            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
[6105]197            //! Overloaded << operator, redirects the output to the listeners
[1725]198            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
[6105]199            //! Overloaded << operator, redirects the output to the listeners
[1725]200            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
[1505]201
[6105]202            //! Overloaded << operator, redirects the output to the listeners
203            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
[1505]204
[6105]205            //! Overloaded << operator, redirect the output of classes with self defined 'operator <<' to the listeners
206            template <class T>
207            inline OutputHandler& operator<<(const T& val)           { return this->output(val); }
[1505]208
[6105]209            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
210            inline OutputHandler& operator<<(std::ostream&  (*manip)(std::ostream&))  { return this->output(manip); }
211            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
212            inline OutputHandler& operator<<(std::ios&      (*manip)(std::ios&))      { return this->output(manip); }
213            //! Overloaded << operator for std manipulators like std::endl, redirects the output to the listeners
214            inline OutputHandler& operator<<(std::ios_base& (*manip)(std::ios_base&)) { return this->output(manip); }
215
216            //! Dummy operator required by Debug.h for the ternary operator
217            inline operator int() const { return 0; }
218
[1505]219        private:
[6105]220            OutputHandler();
221            ~OutputHandler();
[7401]222            OutputHandler(const OutputHandler& rhs);      //!< Copy-constructor: Unused and undefined
[1586]223
[8516]224            /// Evaluates the maximum global log level
225            void updateGlobalDebugLevel();
226
227            std::vector<OutputListener*> listeners_;        //!< Array with all registered output listeners
228            int                          outputLevel_;      //!< The level of the incoming output
229            LogFileWriter*               logFile_;          //!< Writes output to the log file
230            ConsoleWriter*               consoleWriter_;    //!< Writes to std::cout (can be disabled)
231            MemoryLogWriter*             memoryBuffer_;     //!< Writes to memory as a buffer (can/must be stopped at some time)
232            static int                   softDebugLevel_s;  //!< Maximum of all soft debug levels. @note This is only static for faster access
[1505]233    };
234
235    /**
[6105]236    @brief
237        Interface for listening to output.
238    @remarks
239        Remember to register the listener (not done automatically!)
[1505]240    */
[6105]241    class OutputListener
[1505]242    {
[6105]243        friend class OutputHandler;
[1505]244
[6105]245    public:
246        OutputListener(const std::string& name)
247            : outputStream_(NULL)
248            , name_(name)
249            , softDebugLevel_(OutputLevel::Info)
250        {}
251        virtual ~OutputListener() {}
252
253        //! Gets called whenever output is put into the stream
254        virtual void outputChanged(int level) {}
255        //! Returns the name of this output listener
256        const std::string& getOutputListenerName() const { return this->name_; }
257        //! Returns the soft debug level of the listener
258        int getSoftDebugLevel() const { return this->softDebugLevel_; }
[1505]259
[6105]260    protected:
261        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
[1505]262
[6105]263    private:
264        const std::string name_;           //!< Name of the listener, constant and unique!
265        int               softDebugLevel_; //!< Current soft debug level that defines what kind of output is written to the stream
266    };
[1505]267
268    template<class T>
[6105]269    inline OutputHandler& OutputHandler::output(const T& output)
[1505]270    {
[8516]271        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
[1505]272        {
[6105]273            if (this->outputLevel_ <= (*it)->softDebugLevel_ && (*it)->outputStream_ != NULL)
274            {
275                std::ostream& stream = *((*it)->outputStream_);
276                stream << output;
277                stream.flush();
278                (*it)->outputChanged(this->outputLevel_);
279            }
[1505]280        }
281
[6105]282        return *this;
[1505]283    }
284}
285
286#endif /* _OutputHandler_H__ */
Note: See TracBrowser for help on using the repository browser.