Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/OutputHandler.h @ 8749

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

Merged unity_build branch back to trunk.

Features:

  • Implemented fully automatic build units to speed up compilation if requested
  • Added DOUT macro for quick debug output
  • Activated text colouring in the POSIX IOConsole
  • DeclareToluaInterface is not necessary anymore

Improvements:

  • Output levels now change appropriately when switch back and forth from dev mode
  • Log level for the file output is now also correct during startup
  • Removed some header file dependencies in core and tools to speed up compilation

no more file for command line options

  • Improved util::tribool by adapting some concepts from boost::tribool

Regressions:

  • It is not possible anymore to specify command line arguments in an extra file because we've got config values for that purpose.
  • Property svn:eol-style set to native
File size: 12.9 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            TDebug  = -1,
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
82        The OutputHandler acts like @c std::cout, but output isn't only shown in the console.
83
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.
88        And if you need the output previously processed, iterate over it with
89        OutputHandler::getOutputVectorBegin and OutputHandler::getOutputVectorEnd.
90
91        The way to output text is to first set the desired output level with
92        @ref getOutStream "OutputHandler::getOutStream(level)" and then use
93        the "<<" operator like with @c std::cout. Alternatively you can use the COUT() macro.
94    */
95    class _UtilExport OutputHandler
96    {
97        public:
98            //! Returns a reference to the only existing instance of the OutputHandler class.
99            static OutputHandler& getInstance();
100
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); }
104
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;
108
109            //! Writes to all output devices
110            static inline void log(const std::string& text)
111                { OutputHandler::getOutStream(0).output(text) << std::endl; }
112
113            //! Writes an error message to the output
114            static inline void error(const std::string& text)
115                { OutputHandler::getOutStream(1).output(text) << std::endl; }
116
117            //! Writes a warning message to the output
118            static inline void warning(const std::string& text)
119                { OutputHandler::getOutStream(2).output(text) << std::endl; }
120
121            //! Writes an informational message to the output
122            static inline void info(const std::string& text)
123                { OutputHandler::getOutStream(3).output(text) << std::endl; }
124
125            //! Writes a debug message to the output
126            static inline void debug(const std::string& text)
127                { OutputHandler::getOutStream(4).output(text) << std::endl; }
128
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);
133
134            //! Set the log path once the program has been properly initialised
135            void setLogPath(const std::string& path);
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
141            //! Disables the std::cout stream for output
142            void disableCout();
143            //! Enables the std::cout stream for output (startup behaviour)
144            void enableCout();
145            //! Stop writing to the memory buffer (call this as soon as possible to minimise memory usage)
146            void disableMemoryLog();
147
148            //! Sets the level of the incoming output and returns the OutputHandler
149            inline OutputHandler& setOutputLevel(int level)
150                { this->outputLevel_ = level; return *this; }
151
152            //! Returns the level of the incoming output
153            inline int getOutputLevel() const
154                { return this->outputLevel_; }
155
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);
162
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            */
171            template <class T>
172            OutputHandler& output(const T& output);
173
174            //! Overloaded << operator, redirects the output to the listeners
175            inline OutputHandler& operator<<(unsigned char val)      { return this->output(val); }
176            //! Overloaded << operator, redirects the output to the listeners
177            inline OutputHandler& operator<<(short val)              { return this->output(val); }
178            //! Overloaded << operator, redirects the output to the listeners
179            inline OutputHandler& operator<<(unsigned short val)     { return this->output(val); }
180            //! Overloaded << operator, redirects the output to the listeners
181            inline OutputHandler& operator<<(int val)                { return this->output(val); }
182            //! Overloaded << operator, redirects the output to the listeners
183            inline OutputHandler& operator<<(unsigned int val)       { return this->output(val); }
184            //! Overloaded << operator, redirects the output to the listeners
185            inline OutputHandler& operator<<(long val)               { return this->output(val); }
186            //! Overloaded << operator, redirects the output to the listeners
187            inline OutputHandler& operator<<(unsigned long val)      { return this->output(val); }
188            //! Overloaded << operator, redirects the output to the listeners
189            inline OutputHandler& operator<<(long long val)          { return this->output(val); }
190            //! Overloaded << operator, redirects the output to the listeners
191            inline OutputHandler& operator<<(unsigned long long val) { return this->output(val); }
192            //! Overloaded << operator, redirects the output to the listeners
193            inline OutputHandler& operator<<(float val)              { return this->output(val); }
194            //! Overloaded << operator, redirects the output to the listeners
195            inline OutputHandler& operator<<(double val)             { return this->output(val); }
196            //! Overloaded << operator, redirects the output to the listeners
197            inline OutputHandler& operator<<(long double val)        { return this->output(val); }
198            //! Overloaded << operator, redirects the output to the listeners
199            inline OutputHandler& operator<<(const void* val)        { return this->output(val); }
200            //! Overloaded << operator, redirects the output to the listeners
201            inline OutputHandler& operator<<(bool val)               { return this->output(val); }
202
203            //! Overloaded << operator, redirects the output to the listeners
204            inline OutputHandler& operator<<(std::streambuf* sb)     { return this->output(sb); }
205
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); }
209
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
220        private:
221            OutputHandler();
222            ~OutputHandler();
223            OutputHandler(const OutputHandler& rhs);      //!< Copy-constructor: Unused and undefined
224
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
234    };
235
236    /**
237    @brief
238        Interface for listening to output.
239    @remarks
240        Remember to register the listener (not done automatically!)
241    */
242    class OutputListener
243    {
244        friend class OutputHandler;
245
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_; }
258
259    protected:
260        std::ostream*     outputStream_;   //!< Pointer to the associated output stream, can be NULL
261
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    };
266
267    template<class T>
268    inline OutputHandler& OutputHandler::output(const T& output)
269    {
270        for (std::vector<OutputListener*>::const_iterator it = this->listeners_.begin(); it != this->listeners_.end(); ++it)
271        {
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            }
279        }
280
281        return *this;
282    }
283}
284
285#endif /* _OutputHandler_H__ */
Note: See TracBrowser for help on using the repository browser.