Spinning Topp Logo BlackTopp Studios
inc
streamlogging.h
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 
41 #ifndef _logging_h
42 #define _logging_h
43 
44 #include "crossplatformexport.h"
45 #include <iostream>
46 
47 ////////////////////////////////////////////////////////////////////////////////////////////////////
48 // LogLevel Declaration and Tools
49 //////////////////////////////////////////////////
50 
51 /// @brief These are used with IOStreams to control when output is actually written and when it is not.
52 /// @details This is a bitfield that is used the LogStream to control the output of specific messages.
53 /// @n This can be edited (and the Mezzanine recompiled). Any replacement must include the members
54 /// LL_Lowest, LL_Highest and LL_FlagLimit.
55 enum LogLevel {
56  LL_None = 0, ///< No flag are set, not intended for use in actual logging, but for use in binary maths.
57 
58  LL_Trace = 1, ///< This should be used for detailed output that only the craziest corner case requires.
59  LL_Debug = 2, ///< Output that is generally not useful, unless it is time to fix a bug.
60  LL_Warn = 4, ///< Stuff that might help a technician figure a problem out or that could indicate a deeper problem while not being a problem itself.
61  LL_Error = 8, ///< A porblem has happened, but it doesn't require execution to terminate immediately. For example Spelling.
62  LL_Fatal = 16, ///< A problem has happened and it cannot be recovered from, perhaps memory exhaustion or the GPU barfed or something like that.
63 
64  LL_TraceAndHigher = LL_Trace|LL_Debug|LL_Warn|LL_Error|LL_Fatal, ///< Includes Trace, Debug, Warn, Error and Fatal, all of them.
65  LL_DebugAndHigher = LL_Debug|LL_Warn|LL_Error|LL_Fatal, ///< Includes Debug, Warn, Error and Fatal. A reasonable setting while debugging
66  LL_WarnAndHigher = LL_Warn|LL_Error|LL_Fatal, ///< Includes Warn, Error and Fatal. Likely useful for troubleshooting.
67  LL_ErrorAndHigher = LL_Error|LL_Fatal, ///< Includes Error and Fatal. Probably a good default for shipping code.
68  LL_FatalAndHigher = LL_Fatal, ///< Includes Fatal. Here for naming consistency
69 
70  LL_Lowest = 1, ///< Is the lowest bitvalue intended to be used for logging.
71  LL_Highest = 16, ///< IS the highest bitvalue intended to be used for logging.
72  LL_FlagLimit = 32 ///< The next higher power of two past the valid loglevels, will therefor be exactly 1 higher than a full bitfield.
73 };
74 
75 /// @brief Merge 2 log levels into 1
76 /// @details To maintain type safety normal bitwise operations should not be used with loglevels
77 /// @param First One of many LogLevel instances to merge into one.
78 /// @param Second Another of many loglevel instances to merge.
79 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second);
80 
81 /// @brief Merge 3 log levels into 1
82 /// @param First One of many LogLevel instances to merge into one.
83 /// @param Second Another of many loglevel instances to merge.
84 /// @param Third Another of many loglevel instances to merge.
85 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third);
86 
87 /// @brief Merge 4 log levels into 1
88 /// @param First One of many LogLevel instances to merge into one.
89 /// @param Second Another of many loglevel instances to merge.
90 /// @param Third Another of many loglevel instances to merge.
91 /// @param Fourth Another of many loglevel instances to merge.
92 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third, LogLevel Fourth);
93 
94 /// @brief Merge 5 log levels into 1
95 /// @param First One of many LogLevel instances to merge into one.
96 /// @param Second Another of many loglevel instances to merge.
97 /// @param Third Another of many loglevel instances to merge.
98 /// @param Fourth Another of many loglevel instances to merge.
99 /// @param Fifth Another of many loglevel instances to merge.
100 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third, LogLevel Fourth, LogLevel Fifth);
101 
102 /// @brief Merge 6 log levels into 1
103 /// @param First One of many LogLevel instances to merge into one.
104 /// @param Second Another of many loglevel instances to merge.
105 /// @param Third Another of many loglevel instances to merge.
106 /// @param Fourth Another of many loglevel instances to merge.
107 /// @param Fifth Another of many loglevel instances to merge.
108 /// @param Sixth Another of many loglevel instances to merge.
109 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third, LogLevel Fourth, LogLevel Fifth, LogLevel Sixth);
110 
111 /// @brief Merge 7 log levels into 1
112 /// @param First One of many LogLevel instances to merge into one.
113 /// @param Second Another of many loglevel instances to merge.
114 /// @param Third Another of many loglevel instances to merge.
115 /// @param Fourth Another of many loglevel instances to merge.
116 /// @param Fifth Another of many loglevel instances to merge.
117 /// @param Sixth Another of many loglevel instances to merge.
118 /// @param Seventh Another of many loglevel instances to merge.
119 /// @return All of the LogLevels merged into one bitfield that is still a valid LogLevel.
120 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third, LogLevel Fourth, LogLevel Fifth, LogLevel Sixth, LogLevel Seventh);
121 
122 /// @brief Merge 8 log levels into 1
123 /// @param First This
124 /// @param Second accepts
125 /// @param Third a
126 /// @param Fourth truly
127 /// @param Fifth obnoxious
128 /// @param Sixth amount
129 /// @param Seventh of
130 /// @param Eighth parameters.
131 /// @return All of the LogLevels merged into one bitfield that is still a valid LogLevel.
132 /// @todo Replace this Shenanigans with a variadic template when it becomes available. Though this crao should be easy for even bad optimizers to cleanup.
133 LogLevel MEZZ_LIB MergeLogLevel(LogLevel First, LogLevel Second, LogLevel Third, LogLevel Fourth, LogLevel Fifth, LogLevel Sixth, LogLevel Seventh, LogLevel Eighth);
134 
135 
136 ////////////////////////////////////////////////////////////////////////////////////////////////////
137 // STD Streams configuration
138 //////////////////////////////////////////////////
139 
140 /// @brief The Standard Streams will Use the log levels set here
141 /// @details This defaults to Trace and debug
142 void MEZZ_LIB SetStandardLoggingLevel(LogLevel NewLevel);
143 
144 /// @brief Retrieve thelog loglevel in use by the stanard
145 /// @details This defaults to logging everything (Trace and Higher)
146 LogLevel MEZZ_LIB GetStandardLoggingLevel();
147 
148 
149 ////////////////////////////////////////////////////////////////////////////////////////////////////
150 // LogStream and Modifiers
151 //////////////////////////////////////////////////
152 
153 /// @brief A stream that tracks its own level of logging.
154 /// @tparam CharType This is kind of character that the stream will work with.
155 /// @tparam CharTraits The traits (move, equality, assignment, etc...) of the character type passed in
156 /// @details Instances of this stream can be configured to treat log messages differently depending on the LogLevel
157 /// of the message and Level actively being logged. In other regards this is a normal output stream.
158 template<class CharType, class CharTraits = std::char_traits<CharType> >
159 class LogStream : public std::basic_ostream<CharType, CharTraits>
160 {
161  /// @brief The LogLevel for stream insertion that will be completed.
162  /// @details If messages passed in come in on a level with at least one bit this matching bitfield, then the message is
163  /// streamed, otherwise it is dropped silently.
164  LogLevel ActivelyLogging;
165 
166  public:
167  /// @brief Buffer Stealing Constructor
168  /// @details When used to create a LogStream this will use the rdbuf of another std::basic_ostream
169  /// @param OutputStream This is the stream to steal the buffer from
170  /// @param WillLog The starting LogLevel to capture, which Defaults to LL_Highest.
171  LogStream(std::basic_ostream<CharType, CharTraits>& OutputStream, LogLevel WillLog = LL_Highest)
172  : std::basic_ostream<CharType, CharTraits>(OutputStream.rdbuf()),
173  ActivelyLogging(WillLog)
174  { }
175 
176  /// @brief Change the level of what this Stream is logging.
177  /// @param NewLevel After this returns any messages sent to this stream will be compared against this.
178  void SetLoggingLevel(LogLevel NewLevel)
179  { ActivelyLogging = NewLevel; }
180 
181  /// @brief What will currently be logged?
182  /// @return A LogLevel that is the bitmap of what will be logged.
183  LogLevel GetLoggingLevel()
184  { return ActivelyLogging; }
185 
186  /// @brief Custom Manipulator inserter
187  /// @param pf Accepts a pointer to a LogStream Manipulator
188  /// @return Whatever stream the manipulator returns which should be *this.
189  LogStream<CharType, CharTraits>& operator<< (LogStream<CharType, CharTraits>& (*pf) (LogStream<CharType, CharTraits>&))
190  { return pf(*this); }
191 };
192 
193 /// @brief This is a Stream modifier that sets the level of following messages to be inserted into the stream.
194 /// @details This specific method is for LogStream, but it is intended to appear outwardly similar to
195 /// standard streams Versions.
196 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
197 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
198 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
199 /// @param CurrentLevel The new level the receiving stream should log.
200 /// @return A reference to the stream being modified.
201 /// @note When inserted into any standard this affects all standard streams.
202 template<class CharType, class CharTraits>
203 LogStream<CharType, CharTraits>& MessageLogLevel(LogStream<CharType, CharTraits>& OutputStream, LogLevel CurrentLevel)
204 {
205  if(CurrentLevel & OutputStream.GetLoggingLevel())
206  { OutputStream.clear(std::basic_ios<CharType, CharTraits>::goodbit); }
207  else
208  { OutputStream.setstate(std::basic_ios<CharType, CharTraits>::failbit); }
209  return OutputStream;
210 }
211 
212 /// @brief The stream this is inserted into will treat this following inserted messages as traces.
213 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
214 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
215 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
216 /// @return A reference to the stream being modified.
217 /// @note When inserted into any standard this affects all standard streams.
218 /// @details Sample usage:
219 /// @code
220 /// LogStream Log(cout);
221 /// Log << LogTrace << "Entering function int MeaningOfLifeUniverseAndEverything(42).";
222 /// @endcode
223 template<class CharType, class CharTraits>
225  { return MessageLogLevel(OutputStream, LL_Trace); }
226 
227 /// @brief The stream this is inserted into will treat this following inserted messages as debug messages.
228 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
229 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
230 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
231 /// @return A reference to the stream being modified.
232 /// @note When inserted into any standard this affects all standard streams.
233 /// @details Sample usage:
234 /// @code
235 /// LogStream Log(cout);
236 /// Log << LogDebug << "Sample Log Message.";
237 /// @endcode
238 template<class CharType, class CharTraits>
240  { return MessageLogLevel(OutputStream, LL_Debug); }
241 
242 /// @brief The stream this is inserted into will treat this following inserted messages as warnings.
243 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
244 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
245 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
246 /// @return A reference to the stream being modified.
247 /// @note When inserted into any standard this affects all standard streams.
248 /// @details Sample usage:
249 /// @code
250 /// LogStream Log(cout);
251 /// Log << LogWarn << "Danger Will Robinson, Danger!!!";
252 /// @endcode
253 template<class CharType, class CharTraits>
255  { return MessageLogLevel(OutputStream, LL_Warn); }
256 
257 /// @brief The stream this is inserted into will treat this following inserted messages as errors.
258 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
259 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
260 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
261 /// @return A reference to the stream being modified.
262 /// @note When inserted into any standard this affects all standard streams.
263 /// @details Sample usage:
264 /// @code
265 /// LogStream Log(cout);
266 /// Log << LogError << "The System is dowm, the system is down, Bwoo Dee boo do do.";
267 /// @endcode
268 template<class CharType, class CharTraits>
270  { return MessageLogLevel(OutputStream, LL_Error); }
271 
272 /// @brief The stream this is inserted into will treat this following inserted messages as fatal.
273 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
274 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
275 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
276 /// @return A reference to the stream being modified.
277 /// @note When inserted into any standard this affects all standard streams.
278 /// @details Sample usage:
279 /// @code
280 /// LogStream Log(cout);
281 /// Log << LogFatal << "The Tuna contains too much Flipper!!!";
282 /// @endcode
283 template<class CharType, class CharTraits>
285  { return MessageLogLevel(OutputStream, LL_Fatal); }
286 
287 
288 ////////////////////////////////////////////////////////////////////////////////////////////////////
289 // Standard Stream Modifiers
290 //////////////////////////////////////////////////
291 
292 
293 /// @brief This is a Stream modifier that sets the level of following messages to be inserted into the stream.
294 /// @details This specific method is for standard streams, but it is intended to appear outwardly similar to
295 /// LogStream Versions.
296 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
297 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
298 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
299 /// @param CurrentLevel The new level the receiving stream should log.
300 /// @return A reference to the stream being modified.
301 /// @note When inserted into any standard this affects all standard streams.
302 template<class CharType, class CharTraits>
303 std::basic_ostream<CharType, CharTraits>& MessageLogLevel(std::basic_ostream<CharType, CharTraits>& OutputStream, LogLevel CurrentLevel)
304 {
305  if(CurrentLevel & GetStandardLoggingLevel())
306  { OutputStream.clear(std::basic_ios<CharType, CharTraits>::goodbit); }
307  else
308  { OutputStream.setstate(std::basic_ios<CharType, CharTraits>::failbit); }
309  return OutputStream;
310 }
311 
312 /// @brief The messages following the insertion of this into a standard stream will be treated as traces.
313 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
314 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
315 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
316 /// @return A reference to the stream being modified.
317 /// @note When inserted into any standard this affects all standard streams.
318 /// @details Here is a sample of use:
319 /// @code
320 /// cout << LogTrace << "Entering function int MeaningOfLifeUniverseAndEverything(42).";
321 /// @endcode
322 template<class CharType, class CharTraits>
323 std::basic_ostream<CharType, CharTraits>& LogTrace(std::basic_ostream<CharType, CharTraits>& OutputStream)
324  { return MessageLogLevel(OutputStream, LL_Trace); }
325 
326 /// @brief The messages following the insertion of this into a standard stream will be treated as debug messages.
327 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
328 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
329 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
330 /// @return A reference to the stream being modified.
331 /// @note When inserted into any standard this affects all standard streams.
332 /// @details Here is a sample of use:
333 /// @code
334 /// cout << LogDebug << "Opening file foo.txt.";
335 /// @endcode
336 template<class CharType, class CharTraits>
337 std::basic_ostream<CharType, CharTraits>& LogDebug(std::basic_ostream<CharType, CharTraits>& OutputStream)
338  { return MessageLogLevel(OutputStream, LL_Debug); }
339 
340 /// @brief The messages following the insertion of this into a standard stream will be treated as warnings.
341 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
342 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
343 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
344 /// @return A reference to the stream being modified.
345 /// @note When inserted into any standard this affects all standard streams.
346 /// @details Here is a sample of use:
347 /// @code
348 /// cout << LogWarn << "Danger Will Robinson, Danger!!!";
349 /// @endcode
350 template<class CharType, class CharTraits>
351 std::basic_ostream<CharType, CharTraits>& LogWarn(std::basic_ostream<CharType, CharTraits>& OutputStream)
352  { return MessageLogLevel(OutputStream, LL_Warn); }
353 
354 /// @brief The messages following the insertion of this into a standard stream will be treated as Errors.
355 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
356 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
357 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
358 /// @return A reference to the stream being modified.
359 /// @note When inserted into any standard this affects all standard streams.
360 /// @details Here is a sample of use:
361 /// @code
362 /// cout << LogError << "The System is dowm, the system is down, Bwoo Dee boo do do.";
363 /// @endcode
364 template<class CharType, class CharTraits>
365 std::basic_ostream<CharType, CharTraits>& LogError(std::basic_ostream<CharType, CharTraits>& OutputStream)
366  { return MessageLogLevel(OutputStream, LL_Error); }
367 
368 /// @brief The messages following the insertion of this into a standard stream will be treated as fatal.
369 /// @tparam CharType This is used as type inference to allow type safety when inserting this into a stream.
370 /// @tparam CharTraits This is used as type inference to allow type safety when inserting this into a stream.
371 /// @param OutputStream This is the stream to be modified and is the left hand operand of operator<<.
372 /// @return A reference to the stream being modified.
373 /// @note When inserted into any standard this affects all standard streams.
374 /// @details Here is a sample of use:
375 /// @code
376 /// cout << LogFatal << "The Tuna contains too much Flipper!!!";
377 /// @endcode
378 template<class CharType, class CharTraits>
379 std::basic_ostream<CharType, CharTraits>& LogFatal(std::basic_ostream<CharType, CharTraits>& OutputStream)
380  { return MessageLogLevel(OutputStream, LL_Fatal); }
381 
382 
383 #endif //_logging_h
A stream that tracks its own level of logging.
This file is used on some platforms to determine what data should be read and written to and from a s...
STL namespace.
LogStream(std::basic_ostream< CharType, CharTraits > &OutputStream, LogLevel WillLog=LL_Highest)
Buffer Stealing Constructor.
void SetLoggingLevel(LogLevel NewLevel)
Change the level of what this Stream is logging.
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
LogLevel GetLoggingLevel()
What will currently be logged?