Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Separate method in OutputHandler for updating the global debug level and using std::vector instead of std::list for the listeners.

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