1 /** \file logstream.hxx
2 * Stream based logging mechanism.
5 // Written by Bernie Bright, 1998
7 // Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
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.
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.
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.
28 #include <simgear/compiler.h>
38 #include <simgear/debug/debug_types.h>
46 // 1. Change output destination. Done.
47 // 2. Make logbuf thread safe.
48 // 3. Read environment for default debugClass and debugPriority.
52 * logbuf is an output-only streambuf with the ability to disable sets of
53 * messages at runtime. Only messages with priority >= logbuf::logPriority
54 * and debugClass == logbuf::logClass are output.
56 #ifdef SG_NEED_STREAMBUF_HACK
57 class logbuf : public __streambuf
59 class logbuf : public std::streambuf
63 // logbuf( streambuf* sb ) : sbuf(sb) {}
72 * @return true or false*/
73 bool enabled() { return logging_enabled; }
76 * Set the logging level of subsequent messages.
77 * @param c debug class
80 void set_log_state( sgDebugClass c, sgDebugPriority p );
82 bool would_log( sgDebugClass c, sgDebugPriority p ) const;
85 * Set the global logging level.
86 * @param c debug class
89 static void set_log_level( sgDebugClass c, sgDebugPriority p );
93 * Set the allowed logging classes.
94 * @param c All enabled logging classes anded together.
96 static void set_log_classes (sgDebugClass c);
100 * Get the logging classes currently enabled.
101 * @return All enabled debug logging anded together.
103 static sgDebugClass get_log_classes ();
107 * Set the logging priority.
108 * @param c The priority cutoff for logging messages.
110 static void set_log_priority (sgDebugPriority p);
114 * Get the current logging priority.
115 * @return The priority cutoff for logging messages.
117 static sgDebugPriority get_log_priority ();
121 * Set the stream buffer
122 * @param sb stream buffer
124 void set_sb( std::streambuf* sb );
127 static void has_no_console() { has_console = false; }
133 inline virtual int sync();
136 int_type overflow( int ch );
137 // int xsputn( const char* s, istreamsize n );
141 // The streambuf used for actual output. Defaults to cerr.rdbuf().
142 static std::streambuf* sbuf;
144 static bool logging_enabled;
146 static bool has_console;
148 static sgDebugClass logClass;
149 static sgDebugPriority logPriority;
154 logbuf( const logbuf& );
155 void operator= ( const logbuf& );
161 return sbuf->pubsync();
165 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
167 logging_enabled = ((c & logClass) != 0 && p >= logPriority);
171 logbuf::would_log( sgDebugClass c, sgDebugPriority p ) const
173 return ((c & logClass) != 0 && p >= logPriority);
176 inline logbuf::int_type
177 logbuf::overflow( int c )
180 if ( logging_enabled ) {
181 if ( !has_console ) {
183 freopen("conin$", "r", stdin);
184 freopen("conout$", "w", stdout);
185 freopen("conout$", "w", stderr);
188 return sbuf->sputc(c);
191 return EOF == 0 ? 1: 0;
193 return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
198 * logstream manipulator for setting the log level of a message.
202 loglevel( sgDebugClass c, sgDebugPriority p )
203 : logClass(c), logPriority(p) {}
205 sgDebugClass logClass;
206 sgDebugPriority logPriority;
210 * A helper class that ensures a streambuf and ostream are constructed and
211 * destroyed in the correct order. The streambuf must be created before the
212 * ostream but bases are constructed before members. Thus, making this class
213 * a private base of logstream, declared to the left of ostream, we ensure the
214 * correct order of construction and destruction.
216 struct logstream_base
218 // logstream_base( streambuf* sb ) : lbuf(sb) {}
225 * Class to manage the debug logging stream.
227 class logstream : private logstream_base, public std::ostream
231 * The default is to send messages to cerr.
232 * @param out output stream
234 logstream( std::ostream& out )
235 // : logstream_base(out.rdbuf()),
237 std::ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
240 * Set the output stream
241 * @param out output stream
243 void set_output( std::ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
246 * Set the global log class and priority level.
247 * @param c debug class
250 void setLogLevels( sgDebugClass c, sgDebugPriority p );
252 bool would_log( sgDebugClass c, sgDebugPriority p ) const
254 return lbuf.would_log( c, p );
258 * Output operator to capture the debug level and priority of a message.
261 inline std::ostream& operator<< ( const loglevel& l );
262 friend logstream& sglog();
263 static logstream *initGlobalLogstream();
265 static logstream *global_logstream;
269 logstream::operator<< ( const loglevel& l )
271 lbuf.set_log_state( l.logClass, l.logPriority );
277 * Return the one and only logstream instance.
278 * We use a function instead of a global object so we are assured that cerr
279 * has been initialised.
280 * @return current logstream
285 return *logstream::initGlobalLogstream();
289 /** \def SG_LOG(C,P,M)
291 * @param C debug class
296 # define SG_LOG(C,P,M)
298 # define SG_LOG(C,P,M) do { \
299 logstream& __tmplogstreamref(sglog()); \
300 if(__tmplogstreamref.would_log(C,P)) { \
301 __tmplogstreamref << loglevel(C,P) << M << std::endl; } \
305 #define SG_ORIGIN __FILE__ ":" SG_STRINGIZE(__LINE__)
307 #endif // _LOGSTREAM_H