]> git.lyx.org Git - lyx.git/blob - src/support/DebugStream.h
noncopyable + read ChangeLog
[lyx.git] / src / support / DebugStream.h
1 // -*- C++ -*-
2
3 // Created by Lars Gullik Bjønnes
4 // Copyright 1999 Lars Gullik Bjønnes (larsbj@lyx.org)
5 // Released into the public domain.
6
7 // Implemented and tested on g++ 2.7.2.3
8
9 // Primarily developed for use in the LyX Project http://www.lyx.org/
10 // but should be adaptable to any project.
11
12 #ifndef DEBUGSTREAM_H
13 #define DEBUGSTREAM_H
14
15 #ifdef __GNUG__
16 #pragma interface
17 #endif
18
19 #include "LOstream.h"
20
21 #ifdef TEST_DEBUGSTREAM
22 #include <string>
23 struct Debug {
24         ///
25         enum type {
26                 ///
27                 NONE = 0,
28                 ///
29                 INFO       = (1 << 0),   // 1
30                 ///
31                 WARN       = (1 << 1),   // 2
32                 ///
33                 CRIT       = (1 << 2)   // 4
34         };
35         ///
36         static const type ANY = type(INFO | WARN | CRIT);
37
38         /** A function to convert symbolic string names on debug levels
39             to their numerical value.
40         */
41         static Debug::type value(string const & val) {
42                 if (val == "NONE") return Debug::NONE;
43                 if (val == "INFO") return Debug::INFO;
44                 if (val == "WARN") return Debug::WARN;
45                 if (val == "CRIT") return Debug::CRIT;
46                 return Debug::NONE;
47         }
48
49 };
50 #endif
51
52 /** DebugStream is a ostream intended for debug output. It has also support
53     for a logfile. Debug output is output to cerr and if the logfile is set,
54     to the logfile.
55
56     Example of Usage:
57     DebugStream debug;
58     debug.level(Debug::INFO);
59     debug.debug(Debug::WARN) << "WARN\n";
60     debug[Debug::INFO] << "INFO\n";
61     debug << "Always\n";
62
63     Will output:
64     INFO
65     Always
66
67     If you want to have debug output from time critical code you should 
68     use this construct:
69     if (debug.debugging(Debug::INFO)) {
70          debug << "...debug output...\n";
71     }
72     
73     To give debug info even if no debug (NONE) is requested:
74     debug << "... always output ...\n";
75
76     To give debug output regardless of what debug level is set (!NONE):
77     debug.debug() << "...on debug output...\n";
78     debug[Debug::ANY] << "...on debug output...\n";
79
80     To give debug output when a specific debug level is set (INFO):
81     debug.debug(Debug::INFO) << "...info...\n";
82     debug[Debug::INFO] << "...info...\n";
83
84     To give debug output when either on of debug levels is set (INFO or CRIT):
85     debug.debug(Debug::type(Debug::INFO | Debug::CRIT)) << "...info/crit...\n";
86     debug[Debug::type(Debug::INFO | Debug::CRIT)] << "...info/crit...\n";
87
88 */
89
90 // This workaround is needed only for gcc 2.8.1 (and possibly egcs
91 // 1.0.x), which generates a compiler error when subclassing from
92 // std::. (JMarc)
93 #ifdef CXX_WORKING_NAMESPACES
94 class DebugStream : public std::ostream
95 #else
96 class DebugStream : public ostream
97 #endif
98 {
99 public:
100         /// Constructor, sets the debug level to t.
101         explicit DebugStream(Debug::type t = Debug::NONE);
102         
103         /// Constructor, sets the log file to f, and the debug level to t.
104         explicit
105         DebugStream(char const * f, Debug::type t = Debug::NONE);
106
107         ///
108         virtual ~DebugStream();
109         
110         /// Sets the debug level to t.
111         void level(Debug::type t) {
112                 dt = Debug::type(t & Debug::ANY);
113         }
114
115         /// Returns the current debug level.
116         Debug::type level() const {
117                 return dt;
118         }
119
120         /// Adds t to the current debug level.
121         void addLevel(Debug::type t) {
122                 dt = Debug::type(dt | t);
123         }
124
125         /// Deletes t from the current debug level.
126         void delLevel(Debug::type t) {
127                 dt = Debug::type(dt & ~t);
128         }
129
130         /// Sets the debugstreams' logfile to f.
131         void logFile(char const * f);
132         
133         /// Returns true if t is part of the current debug level.
134         bool debugging(Debug::type t = Debug::ANY) const
135         {
136                 if (dt & t) return true;
137                 return false;
138         }
139
140         
141         /** Returns the no-op stream if t is not part of the
142             current debug level otherwise the real debug stream
143             is used.
144         */
145         std::ostream & debug(Debug::type t = Debug::ANY) {
146                 if (dt & t) return *this;
147                 return nullstream;
148         }
149
150         
151         /** This is an operator to give a more convenient use:
152             dbgstream[Debug::INFO] << "Info!\n";
153         */
154         std::ostream & operator[](Debug::type t) {
155                 return debug(t);
156         }
157 private:
158         /// The current debug level
159         Debug::type dt;
160         /// The no-op stream.
161         std::ostream nullstream;
162         struct debugstream_internal;
163         debugstream_internal * internal;
164 };
165
166 #endif