]> git.mxchange.org Git - flightgear.git/blob - Lib/Debug/logstream.hxx
Merge FG_Lib as subdirectory
[flightgear.git] / Lib / Debug / logstream.hxx
1 // Stream based logging mechanism.
2 //
3 // Written by Bernie Bright, 1998
4 //
5 // Copyright (C) 1998  Bernie Bright - bbright@c031.aone.net.au
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 //
21 // $Id$
22 // (Log is kept at end of this file)
23
24 #ifndef _LOGSTREAM_H
25 #define _LOGSTREAM_H
26
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30
31
32 #include <Include/compiler.h>
33
34 #ifdef FG_HAVE_STD_INCLUDES
35 # include <streambuf>
36 # include <iostream>
37 #else
38 # include <iostream.h>
39 # include "Include/fg_traits.hxx"
40 #endif
41
42 #include "debug_types.h"
43
44 #ifndef FG_HAVE_NATIVE_SGI_COMPILERS
45 FG_USING_STD(streambuf);
46 FG_USING_STD(ostream);
47 FG_USING_STD(cerr);
48 FG_USING_STD(endl);
49 #endif
50
51 //
52 // TODO:
53 //
54 // 1. Change output destination. Done.
55 // 2. Make logbuf thread safe.
56 // 3. Read environment for default debugClass and debugPriority.
57 //
58
59 //-----------------------------------------------------------------------------
60 //
61 // logbuf is an output-only streambuf with the ability to disable sets of
62 // messages at runtime. Only messages with priority >= logbuf::logPriority
63 // and debugClass == logbuf::logClass are output.
64 //
65 class logbuf : public streambuf
66 {
67 public:
68
69 #ifndef FG_HAVE_STD_INCLUDES
70     typedef char_traits<char>           traits_type;
71     typedef char_traits<char>::int_type int_type;
72     typedef char_traits<char>::pos_type pos_type;
73     typedef char_traits<char>::off_type off_type;
74 #endif
75 //     logbuf( streambuf* sb ) : sbuf(sb) {}
76     logbuf();
77     ~logbuf();
78
79     // Is logging enabled?
80     bool enabled() { return logging_enabled; }
81
82     // Set the logging level of subsequent messages.
83     void set_log_state( fgDebugClass c, fgDebugPriority p );
84
85     // Set the global logging level.
86     static void set_log_level( fgDebugClass c, fgDebugPriority p );
87
88     //
89     void set_sb( streambuf* sb );
90
91 protected:
92
93     inline virtual int sync();
94     int_type overflow( int ch );
95 //     int xsputn( const char* s, istreamsize n );
96
97 private:
98
99     // The streambuf used for actual output. Defaults to cerr.rdbuf().
100     static streambuf* sbuf;
101
102     static bool logging_enabled;
103     static fgDebugClass logClass;
104     static fgDebugPriority logPriority;
105
106 private:
107
108     // Not defined.
109     logbuf( const logbuf& );
110     void operator= ( const logbuf& );
111 };
112
113 inline int
114 logbuf::sync()
115 {
116 #ifdef FG_HAVE_STD_INCLUDES
117         return sbuf->pubsync();
118 #else
119         return sbuf->sync();
120 #endif
121 }
122
123 inline void
124 logbuf::set_log_state( fgDebugClass c, fgDebugPriority p )
125 {
126     logging_enabled = ((c & logClass) != 0 && p >= logPriority);
127 }
128
129 inline logbuf::int_type
130 logbuf::overflow( int c )
131 {
132     return logging_enabled ? sbuf->sputc(c) : (EOF == 0 ? 1: 0);
133 }
134
135 //-----------------------------------------------------------------------------
136 //
137 // logstream manipulator for setting the log level of a message.
138 //
139 struct loglevel
140 {
141     loglevel( fgDebugClass c, fgDebugPriority p )
142         : logClass(c), logPriority(p) {}
143
144     fgDebugClass logClass;
145     fgDebugPriority logPriority;
146 };
147
148 //-----------------------------------------------------------------------------
149 //
150 // A helper class that ensures a streambuf and ostream are constructed and
151 // destroyed in the correct order.  The streambuf must be created before the
152 // ostream but bases are constructed before members.  Thus, making this class
153 // a private base of logstream, declared to the left of ostream, we ensure the
154 // correct order of construction and destruction.
155 //
156 struct logstream_base
157 {
158 //     logstream_base( streambuf* sb ) : lbuf(sb) {}
159     logstream_base() {}
160
161     logbuf lbuf;
162 };
163
164 //-----------------------------------------------------------------------------
165 //
166 // 
167 //
168 class logstream : private logstream_base, public ostream
169 {
170 public:
171     // The default is to send messages to cerr.
172     logstream( ostream& out )
173 //      : logstream_base(out.rdbuf()),
174         : logstream_base(),
175           ostream(&lbuf) { lbuf.set_sb(out.rdbuf());}
176
177     void set_output( ostream& out ) { lbuf.set_sb( out.rdbuf() ); }
178
179     // Set the global log class and priority level.
180      void setLogLevels( fgDebugClass c, fgDebugPriority p );
181
182     // Output operator to capture the debug level and priority of a message.
183     inline ostream& operator<< ( const loglevel& l );
184 };
185
186 inline ostream&
187 logstream::operator<< ( const loglevel& l )
188 {
189     lbuf.set_log_state( l.logClass, l.logPriority );
190     return *this;
191 }
192
193 //-----------------------------------------------------------------------------
194 //
195 // Return the one and only logstream instance.
196 // We use a function instead of a global object so we are assured that cerr
197 // has been initialised.
198 //
199 inline logstream&
200 fglog()
201 {
202     static logstream logstrm( cerr );
203     return logstrm;
204 }
205
206 #ifdef FG_NDEBUG
207 # define FG_LOG(C,P,M)
208 #else
209 # define FG_LOG(C,P,M) fglog() << loglevel(C,P) << M << endl
210 #endif
211
212 #endif // _LOGSTREAM_H
213
214 // $Log$
215 // Revision 1.4  1999/03/02 01:01:47  curt
216 // Tweaks for compiling with native SGI compilers.
217 //
218 // Revision 1.3  1999/01/19 20:53:35  curt
219 // Portability updates by Bernie Bright.
220 //
221 // Revision 1.2  1998/11/07 19:07:02  curt
222 // Enable release builds using the --without-logging option to the configure
223 // script.  Also a couple log message cleanups, plus some C to C++ comment
224 // conversion.
225 //
226 // Revision 1.1  1998/11/06 21:20:42  curt
227 // Initial revision.
228 //