]> git.mxchange.org Git - simgear.git/blob - simgear/debug/logstream.hxx
gcc-3.0.x fixes.
[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 #include <simgear/compiler.h>
30
31 // At least Irix needs this
32 #ifdef SG_HAVE_NATIVE_SGI_COMPILERS
33 #include <char_traits.h>
34 #endif
35
36 #ifdef SG_HAVE_STD_INCLUDES
37 # include <streambuf>
38 # include <iostream>
39 #else
40 # include <iostream.h>
41 # include <simgear/sg_traits.hxx>
42 #endif
43
44 #include <simgear/debug/debug_types.h>
45
46 #ifndef SG_HAVE_NATIVE_SGI_COMPILERS
47 SG_USING_STD(streambuf);
48 SG_USING_STD(ostream);
49 SG_USING_STD(cerr);
50 SG_USING_STD(endl);
51 #else
52 SG_USING_STD(char_traits);
53 #endif
54
55 #ifdef __MWERKS__
56 SG_USING_STD(iostream);
57 #endif
58
59 //
60 // TODO:
61 //
62 // 1. Change output destination. Done.
63 // 2. Make logbuf thread safe.
64 // 3. Read environment for default debugClass and debugPriority.
65 //
66
67 /**
68  * logbuf is an output-only streambuf with the ability to disable sets of
69  * messages at runtime. Only messages with priority >= logbuf::logPriority
70  * and debugClass == logbuf::logClass are output.
71  */
72 class logbuf : public streambuf
73 {
74 public:
75
76 #ifndef SG_HAVE_STD_INCLUDES
77     typedef char_traits<char>           traits_type;
78     typedef char_traits<char>::int_type int_type;
79     // typedef char_traits<char>::pos_type pos_type;
80     // typedef char_traits<char>::off_type off_type;
81 #endif
82     // logbuf( streambuf* sb ) : sbuf(sb) {}
83     /** Constructor */
84     logbuf();
85
86     /** Destructor */
87     ~logbuf();
88
89     /**
90      * Is logging enabled?
91      * @return true or false*/
92     bool enabled() { return logging_enabled; }
93
94     /**
95      * Set the logging level of subsequent messages.
96      * @param c debug class
97      * @param p priority
98      */
99     void set_log_state( sgDebugClass c, sgDebugPriority p );
100
101     /**
102      * Set the global logging level.
103      * @param c debug class
104      * @param p priority
105      */
106     static void set_log_level( sgDebugClass c, sgDebugPriority p );
107
108     /**
109      * Set the stream buffer
110      * @param sb stream buffer
111      */
112     void set_sb( streambuf* sb );
113
114 protected:
115
116     /** sync/flush */
117     inline virtual int sync();
118
119     /** overflow */
120     int_type overflow( int ch );
121     // int xsputn( const char* s, istreamsize n );
122
123 private:
124
125     // The streambuf used for actual output. Defaults to cerr.rdbuf().
126     static streambuf* sbuf;
127
128     static bool logging_enabled;
129     static sgDebugClass logClass;
130     static sgDebugPriority logPriority;
131
132 private:
133
134     // Not defined.
135     logbuf( const logbuf& );
136     void operator= ( const logbuf& );
137 };
138
139 inline int
140 logbuf::sync()
141 {
142 #ifdef SG_HAVE_STD_INCLUDES
143         return sbuf->pubsync();
144 #else
145         return sbuf->sync();
146 #endif
147 }
148
149 inline void
150 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
151 {
152     logging_enabled = ((c & logClass) != 0 && p >= logPriority);
153 }
154
155 inline logbuf::int_type
156 logbuf::overflow( int c )
157 {
158     return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
159 }
160
161 /**
162  * logstream manipulator for setting the log level of a message.
163  */
164 struct loglevel
165 {
166     loglevel( sgDebugClass c, sgDebugPriority p )
167         : logClass(c), logPriority(p) {}
168
169     sgDebugClass logClass;
170     sgDebugPriority logPriority;
171 };
172
173 /**
174  * A helper class that ensures a streambuf and ostream are constructed and
175  * destroyed in the correct order.  The streambuf must be created before the
176  * ostream but bases are constructed before members.  Thus, making this class
177  * a private base of logstream, declared to the left of ostream, we ensure the
178  * correct order of construction and destruction.
179  */
180 struct logstream_base
181 {
182     // logstream_base( streambuf* sb ) : lbuf(sb) {}
183     logstream_base() {}
184
185     logbuf lbuf;
186 };
187
188 /**
189  * Class to manage the debug logging stream.
190  */
191 class logstream : private logstream_base, public ostream
192 {
193 public:
194     /**
195      * The default is to send messages to cerr.
196      * @param out output stream
197      */
198     logstream( ostream& out )
199         // : logstream_base(out.rdbuf()),
200         : logstream_base(),
201           ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
202
203     /**
204      * Set the output stream
205      * @param out output stream
206      */
207     void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
208
209     /**
210      * Set the global log class and priority level.
211      * @param c debug class
212      * @param p priority
213      */
214     void setLogLevels( sgDebugClass c, sgDebugPriority p );
215
216     /**
217      * Output operator to capture the debug level and priority of a message.
218      * @param l log level
219      */
220     inline ostream& operator<< ( const loglevel& l );
221 };
222
223 inline ostream&
224 logstream::operator<< ( const loglevel& l )
225 {
226     lbuf.set_log_state( l.logClass, l.logPriority );
227     return *this;
228 }
229
230
231 /**
232  * \relates logstream
233  * Return the one and only logstream instance.
234  * We use a function instead of a global object so we are assured that cerr
235  * has been initialised.
236  * @return current logstream
237  */
238 inline logstream&
239 sglog()
240 {
241     static logstream logstrm( cerr );
242     return logstrm;
243 }
244
245
246 /** \def SG_LOG(C,P,M)
247  * Log a message.
248  * @param C debug class
249  * @param P priority
250  * @param M message
251  */
252 #ifdef FG_NDEBUG
253 # define SG_LOG(C,P,M)
254 #elif defined( __MWERKS__ )
255 # define SG_LOG(C,P,M) ::sglog() << ::loglevel(C,P) << M << std::endl
256 #else
257 # define SG_LOG(C,P,M) sglog() << loglevel(C,P) << M << endl
258 #endif
259
260
261 #endif // _LOGSTREAM_H
262