]> git.mxchange.org Git - simgear.git/blob - simgear/debug/logstream.hxx
SG-ified logstream.
[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/fg_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     /** Destructor */
90     ~logbuf();
91
92     /** Is logging enabled? */
93     bool enabled() { return logging_enabled; }
94
95     /** Set the logging level of subsequent messages. */
96     void set_log_state( sgDebugClass c, sgDebugPriority p );
97
98     /** Set the global logging level. */
99     static void set_log_level( sgDebugClass c, sgDebugPriority p );
100
101     /** Set the stream buffer */
102     void set_sb( streambuf* sb );
103
104 protected:
105
106     /** sync/flush */
107     inline virtual int sync();
108
109     /** overflow */
110     int_type overflow( int ch );
111     // int xsputn( const char* s, istreamsize n );
112
113 private:
114
115     // The streambuf used for actual output. Defaults to cerr.rdbuf().
116     static streambuf* sbuf;
117
118     static bool logging_enabled;
119     static sgDebugClass logClass;
120     static sgDebugPriority logPriority;
121
122 private:
123
124     // Not defined.
125     logbuf( const logbuf& );
126     void operator= ( const logbuf& );
127 };
128
129 inline int
130 logbuf::sync()
131 {
132 #ifdef SG_HAVE_STD_INCLUDES
133         return sbuf->pubsync();
134 #else
135         return sbuf->sync();
136 #endif
137 }
138
139 inline void
140 logbuf::set_log_state( sgDebugClass c, sgDebugPriority p )
141 {
142     logging_enabled = ((c & logClass) != 0 && p >= logPriority);
143 }
144
145 inline logbuf::int_type
146 logbuf::overflow( int c )
147 {
148     return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
149 }
150
151 /**
152  * logstream manipulator for setting the log level of a message.
153  */
154 struct loglevel
155 {
156     loglevel( sgDebugClass c, sgDebugPriority p )
157         : logClass(c), logPriority(p) {}
158
159     sgDebugClass logClass;
160     sgDebugPriority logPriority;
161 };
162
163 /**
164  * A helper class that ensures a streambuf and ostream are constructed and
165  * destroyed in the correct order.  The streambuf must be created before the
166  * ostream but bases are constructed before members.  Thus, making this class
167  * a private base of logstream, declared to the left of ostream, we ensure the
168  * correct order of construction and destruction.
169  */
170 struct logstream_base
171 {
172     // logstream_base( streambuf* sb ) : lbuf(sb) {}
173     logstream_base() {}
174
175     logbuf lbuf;
176 };
177
178 /**
179  * Class to manage the debug logging stream.
180  */
181 class logstream : private logstream_base, public ostream
182 {
183 public:
184     /** The default is to send messages to cerr. */
185     logstream( ostream& out )
186         // : logstream_base(out.rdbuf()),
187         : logstream_base(),
188           ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
189
190     /** Set the output stream */
191     void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
192
193     /** Set the global log class and priority level. */
194     void setLogLevels( sgDebugClass c, sgDebugPriority p );
195
196     /** Output operator to capture the debug level and priority of a message. */
197     inline ostream& operator<< ( const loglevel& l );
198 };
199
200 inline ostream&
201 logstream::operator<< ( const loglevel& l )
202 {
203     lbuf.set_log_state( l.logClass, l.logPriority );
204     return *this;
205 }
206
207
208 /**
209  * Return the one and only logstream instance.
210  * We use a function instead of a global object so we are assured that cerr
211  * has been initialised.
212  */
213 inline logstream&
214 sglog()
215 {
216     static logstream logstrm( cerr );
217     return logstrm;
218 }
219
220
221 /** \def SG_LOG(C,P,M)
222  * Log a message = M of class = C and priority = P
223  */
224 #ifdef FG_NDEBUG
225 # define SG_LOG(C,P,M)
226 #elif defined( __MWERKS__ )
227 # define SG_LOG(C,P,M) ::sglog() << ::loglevel(C,P) << M << std::endl
228 #else
229 # define SG_LOG(C,P,M) sglog() << loglevel(C,P) << M << endl
230 #endif
231
232
233 #endif // _LOGSTREAM_H
234