]> git.mxchange.org Git - simgear.git/blob - simgear/debug/logstream.hxx
Tweaks.
[simgear.git] / simgear / debug / logstream.hxx
1 /** \file logstream.hxx
2  * Stream based logging mechanism.
3  */
4
5 // Written by Bernie Bright, 1998
6 //
7 // Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 // Library General Public License for more details.
18 //
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the
21 // Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 // Boston, MA  02111-1307, USA.
23 //
24 // $Id$
25
26 #ifndef _LOGSTREAM_H
27 #define _LOGSTREAM_H
28
29 #ifdef HAVE_CONFIG_H
30 #  include <config.h>
31 #endif
32
33 #include <simgear/compiler.h>
34
35 // At least Irix needs this
36 #ifdef SG_HAVE_NATIVE_SGI_COMPILERS
37 #include <char_traits.h>
38 #endif
39
40 #ifdef SG_HAVE_STD_INCLUDES
41 # include <streambuf>
42 # include <iostream>
43 #else
44 # include <iostream.h>
45 # include <simgear/sg_traits.hxx>
46 #endif
47
48 #include <simgear/debug/debug_types.h>
49
50 #ifndef SG_HAVE_NATIVE_SGI_COMPILERS
51 SG_USING_STD(streambuf);
52 SG_USING_STD(ostream);
53 SG_USING_STD(cerr);
54 SG_USING_STD(endl);
55 #else
56 SG_USING_STD(char_traits);
57 #endif
58
59 #ifdef __MWERKS__
60 SG_USING_STD(iostream);
61 #endif
62
63 //
64 // TODO:
65 //
66 // 1. Change output destination. Done.
67 // 2. Make logbuf thread safe.
68 // 3. Read environment for default debugClass and debugPriority.
69 //
70
71 /**
72  * logbuf is an output-only streambuf with the ability to disable sets of
73  * messages at runtime. Only messages with priority >= logbuf::logPriority
74  * and debugClass == logbuf::logClass are output.
75  */
76 class logbuf : public streambuf
77 {
78 public:
79
80 #ifndef SG_HAVE_STD_INCLUDES
81     typedef char_traits<char>           traits_type;
82     typedef char_traits<char>::int_type int_type;
83     // typedef char_traits<char>::pos_type pos_type;
84     // typedef char_traits<char>::off_type off_type;
85 #endif
86     // logbuf( streambuf* sb ) : sbuf(sb) {}
87     /** Constructor */
88     logbuf();
89
90     /** Destructor */
91     ~logbuf();
92
93     /**
94      * Is logging enabled?
95      * @return true or false*/
96     bool enabled() { return logging_enabled; }
97
98     /**
99      * Set the logging level of subsequent messages.
100      * @param c debug class
101      * @param p priority
102      */
103     void set_log_state( sgDebugClass c, sgDebugPriority p );
104
105     /**
106      * Set the global logging level.
107      * @param c debug class
108      * @param p priority
109      */
110     static void set_log_level( sgDebugClass c, sgDebugPriority p );
111
112     /**
113      * Set the stream buffer
114      * @param sb stream buffer
115      */
116     void set_sb( streambuf* sb );
117
118 protected:
119
120     /** sync/flush */
121     inline virtual int sync();
122
123     /** overflow */
124     int_type overflow( int ch );
125     // int xsputn( const char* s, istreamsize n );
126
127 private:
128
129     // The streambuf used for actual output. Defaults to cerr.rdbuf().
130     static streambuf* sbuf;
131
132     static bool logging_enabled;
133     static sgDebugClass logClass;
134     static sgDebugPriority logPriority;
135
136 private:
137
138     // Not defined.
139     logbuf( const logbuf& );
140     void operator= ( const logbuf& );
141 };
142
143 inline int
144 logbuf::sync()
145 {
146 #ifdef SG_HAVE_STD_INCLUDES
147         return sbuf->pubsync();
148 #else
149         return sbuf->sync();
150 #endif
151 }
152
153 inline void
154 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
155 {
156     logging_enabled = ((c & logClass) != 0 && p >= logPriority);
157 }
158
159 inline logbuf::int_type
160 logbuf::overflow( int c )
161 {
162     return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
163 }
164
165 /**
166  * logstream manipulator for setting the log level of a message.
167  */
168 struct loglevel
169 {
170     loglevel( sgDebugClass c, sgDebugPriority p )
171         : logClass(c), logPriority(p) {}
172
173     sgDebugClass logClass;
174     sgDebugPriority logPriority;
175 };
176
177 /**
178  * A helper class that ensures a streambuf and ostream are constructed and
179  * destroyed in the correct order.  The streambuf must be created before the
180  * ostream but bases are constructed before members.  Thus, making this class
181  * a private base of logstream, declared to the left of ostream, we ensure the
182  * correct order of construction and destruction.
183  */
184 struct logstream_base
185 {
186     // logstream_base( streambuf* sb ) : lbuf(sb) {}
187     logstream_base() {}
188
189     logbuf lbuf;
190 };
191
192 /**
193  * Class to manage the debug logging stream.
194  */
195 class logstream : private logstream_base, public ostream
196 {
197 public:
198     /**
199      * The default is to send messages to cerr.
200      * @param out output stream
201      */
202     logstream( ostream& out )
203         // : logstream_base(out.rdbuf()),
204         : logstream_base(),
205           ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
206
207     /**
208      * Set the output stream
209      * @param out output stream
210      */
211     void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
212
213     /**
214      * Set the global log class and priority level.
215      * @param c debug class
216      * @param p priority
217      */
218     void setLogLevels( sgDebugClass c, sgDebugPriority p );
219
220     /**
221      * Output operator to capture the debug level and priority of a message.
222      * @param l log level
223      */
224     inline ostream& operator<< ( const loglevel& l );
225 };
226
227 inline ostream&
228 logstream::operator<< ( const loglevel& l )
229 {
230     lbuf.set_log_state( l.logClass, l.logPriority );
231     return *this;
232 }
233
234
235 /**
236  * \relates logstream
237  * Return the one and only logstream instance.
238  * We use a function instead of a global object so we are assured that cerr
239  * has been initialised.
240  * @return current logstream
241  */
242 inline logstream&
243 sglog()
244 {
245     static logstream logstrm( cerr );
246     return logstrm;
247 }
248
249
250 /** \def SG_LOG(C,P,M)
251  * Log a message.
252  * @param C debug class
253  * @param P priority
254  * @param M message
255  */
256 #ifdef FG_NDEBUG
257 # define SG_LOG(C,P,M)
258 #elif defined( __MWERKS__ )
259 # define SG_LOG(C,P,M) ::sglog() << ::loglevel(C,P) << M << std::endl
260 #else
261 # define SG_LOG(C,P,M) sglog() << loglevel(C,P) << M << endl
262 #endif
263
264
265 #endif // _LOGSTREAM_H
266