]> git.mxchange.org Git - simgear.git/blob - simgear/debug/logstream.hxx
Replace SG_USE_STD() by using std::
[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 General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 // $Id$
24
25 #ifndef _LOGSTREAM_H
26 #define _LOGSTREAM_H
27
28 #include <simgear/compiler.h>
29
30 #ifdef _MSC_VER
31 #  include <windows.h>
32 #endif
33
34 #include <streambuf>
35 #include <ostream>
36
37 #include <simgear/debug/debug_types.h>
38
39 using std::streambuf;
40 using std::ostream;
41
42 //
43 // TODO:
44 //
45 // 1. Change output destination. Done.
46 // 2. Make logbuf thread safe.
47 // 3. Read environment for default debugClass and debugPriority.
48 //
49
50 /**
51  * logbuf is an output-only streambuf with the ability to disable sets of
52  * messages at runtime. Only messages with priority >= logbuf::logPriority
53  * and debugClass == logbuf::logClass are output.
54  */
55 #ifdef SG_NEED_STREAMBUF_HACK
56 class logbuf : public __streambuf
57 #else
58 class logbuf : public std::streambuf
59 #endif
60 {
61 public:
62     // logbuf( streambuf* sb ) : sbuf(sb) {}
63     /** Constructor */
64     logbuf();
65
66     /** Destructor */
67     ~logbuf();
68
69     /**
70      * Is logging enabled?
71      * @return true or false*/
72     bool enabled() { return logging_enabled; }
73
74     /**
75      * Set the logging level of subsequent messages.
76      * @param c debug class
77      * @param p priority
78      */
79     void set_log_state( sgDebugClass c, sgDebugPriority p );
80
81     /**
82      * Set the global logging level.
83      * @param c debug class
84      * @param p priority
85      */
86     static void set_log_level( sgDebugClass c, sgDebugPriority p );
87
88
89     /**
90      * Set the allowed logging classes.
91      * @param c All enabled logging classes anded together.
92      */
93     static void set_log_classes (sgDebugClass c);
94
95
96     /**
97      * Get the logging classes currently enabled.
98      * @return All enabled debug logging anded together.
99      */
100     static sgDebugClass get_log_classes ();
101
102
103     /**
104      * Set the logging priority.
105      * @param c The priority cutoff for logging messages.
106      */
107     static void set_log_priority (sgDebugPriority p);
108
109
110     /**
111      * Get the current logging priority.
112      * @return The priority cutoff for logging messages.
113      */
114     static sgDebugPriority get_log_priority ();
115
116
117     /**
118      * Set the stream buffer
119      * @param sb stream buffer
120      */
121     void set_sb( std::streambuf* sb );
122
123 #ifdef _MSC_VER
124     static void has_no_console() { has_console = false; }
125 #endif
126
127 protected:
128
129     /** sync/flush */
130     inline virtual int sync();
131
132     /** overflow */
133     int_type overflow( int ch );
134     // int xsputn( const char* s, istreamsize n );
135
136 private:
137
138     // The streambuf used for actual output. Defaults to cerr.rdbuf().
139     static std::streambuf* sbuf;
140
141     static bool logging_enabled;
142 #ifdef _MSC_VER
143     static bool has_console;
144 #endif
145     static sgDebugClass logClass;
146     static sgDebugPriority logPriority;
147
148 private:
149
150     // Not defined.
151     logbuf( const logbuf& );
152     void operator= ( const logbuf& );
153 };
154
155 inline int
156 logbuf::sync()
157 {
158         return sbuf->pubsync();
159 }
160
161 inline void
162 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
163 {
164     logging_enabled = ((c & logClass) != 0 && p >= logPriority);
165 }
166
167 inline logbuf::int_type
168 logbuf::overflow( int c )
169 {
170 #ifdef _MSC_VER
171     if ( logging_enabled ) {
172         if ( !has_console ) {
173             AllocConsole();
174             freopen("conin$", "r", stdin);
175             freopen("conout$", "w", stdout);
176             freopen("conout$", "w", stderr);
177             has_console = true;
178         }
179         return sbuf->sputc(c);
180     }
181     else
182         return EOF == 0 ? 1: 0;
183 #else
184     return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
185 #endif
186 }
187
188 /**
189  * logstream manipulator for setting the log level of a message.
190  */
191 struct loglevel
192 {
193     loglevel( sgDebugClass c, sgDebugPriority p )
194         : logClass(c), logPriority(p) {}
195
196     sgDebugClass logClass;
197     sgDebugPriority logPriority;
198 };
199
200 /**
201  * A helper class that ensures a streambuf and ostream are constructed and
202  * destroyed in the correct order.  The streambuf must be created before the
203  * ostream but bases are constructed before members.  Thus, making this class
204  * a private base of logstream, declared to the left of ostream, we ensure the
205  * correct order of construction and destruction.
206  */
207 struct logstream_base
208 {
209     // logstream_base( streambuf* sb ) : lbuf(sb) {}
210     logstream_base() {}
211
212     logbuf lbuf;
213 };
214
215 /**
216  * Class to manage the debug logging stream.
217  */
218 class logstream : private logstream_base, public std::ostream
219 {
220 public:
221     /**
222      * The default is to send messages to cerr.
223      * @param out output stream
224      */
225     logstream( std::ostream& out )
226         // : logstream_base(out.rdbuf()),
227         : logstream_base(),
228           std::ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
229
230     /**
231      * Set the output stream
232      * @param out output stream
233      */
234     void set_output( std::ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
235
236     /**
237      * Set the global log class and priority level.
238      * @param c debug class
239      * @param p priority
240      */
241     void setLogLevels( sgDebugClass c, sgDebugPriority p );
242
243     /**
244      * Output operator to capture the debug level and priority of a message.
245      * @param l log level
246      */
247     inline std::ostream& operator<< ( const loglevel& l );
248     friend logstream& sglog();
249 protected:
250     static logstream *global_logstream;
251     static void initGlobalLogstream();
252 };
253
254 inline std::ostream&
255 logstream::operator<< ( const loglevel& l )
256 {
257     lbuf.set_log_state( l.logClass, l.logPriority );
258     return *this;
259 }
260
261 /**
262  * \relates logstream
263  * Return the one and only logstream instance.
264  * We use a function instead of a global object so we are assured that cerr
265  * has been initialised.
266  * @return current logstream
267  */
268 inline logstream&
269 sglog()
270 {
271   if (logstream::global_logstream == NULL) {
272       logstream::initGlobalLogstream();
273   }
274   return *logstream::global_logstream;
275 }
276
277
278 /** \def SG_LOG(C,P,M)
279  * Log a message.
280  * @param C debug class
281  * @param P priority
282  * @param M message
283  */
284 #ifdef FG_NDEBUG
285 # define SG_LOG(C,P,M)
286 #else
287 # define SG_LOG(C,P,M) sglog() << loglevel(C,P) << M << std::endl
288 #endif
289
290 #define SG_ORIGIN __FILE__ ":" SG_STRINGIZE(__LINE__)
291
292 #endif // _LOGSTREAM_H
293