1 // Copyright 2009 The RE2 Authors.  All Rights Reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 
5 #ifndef UTIL_LOGGING_H_
6 #define UTIL_LOGGING_H_
7 
8 // Simplified version of Google's logging.
9 
10 #include <assert.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <ostream>
14 #include <sstream>
15 
16 #include "util/util.h"
17 
18 // Debug-only checking.
19 #define DCHECK(condition) assert(condition)
20 #define DCHECK_EQ(val1, val2) assert((val1) == (val2))
21 #define DCHECK_NE(val1, val2) assert((val1) != (val2))
22 #define DCHECK_LE(val1, val2) assert((val1) <= (val2))
23 #define DCHECK_LT(val1, val2) assert((val1) < (val2))
24 #define DCHECK_GE(val1, val2) assert((val1) >= (val2))
25 #define DCHECK_GT(val1, val2) assert((val1) > (val2))
26 
27 // Always-on checking
28 #define CHECK(x)	if(x){}else LogMessageFatal(__FILE__, __LINE__).stream() << "Check failed: " #x
29 #define CHECK_LT(x, y)	CHECK((x) < (y))
30 #define CHECK_GT(x, y)	CHECK((x) > (y))
31 #define CHECK_LE(x, y)	CHECK((x) <= (y))
32 #define CHECK_GE(x, y)	CHECK((x) >= (y))
33 #define CHECK_EQ(x, y)	CHECK((x) == (y))
34 #define CHECK_NE(x, y)	CHECK((x) != (y))
35 
36 #define LOG_INFO LogMessage(__FILE__, __LINE__)
37 #define LOG_WARNING LogMessage(__FILE__, __LINE__)
38 #define LOG_ERROR LogMessage(__FILE__, __LINE__)
39 #define LOG_FATAL LogMessageFatal(__FILE__, __LINE__)
40 #define LOG_QFATAL LOG_FATAL
41 
42 // It seems that one of the Windows header files defines ERROR as 0.
43 #ifdef _WIN32
44 #define LOG_0 LOG_INFO
45 #endif
46 
47 #ifdef NDEBUG
48 #define LOG_DFATAL LOG_ERROR
49 #else
50 #define LOG_DFATAL LOG_FATAL
51 #endif
52 
53 #define LOG(severity) LOG_ ## severity.stream()
54 
55 #define VLOG(x) if((x)>0){}else LOG_INFO.stream()
56 
57 class LogMessage {
58  public:
LogMessage(const char * file,int line)59   LogMessage(const char* file, int line)
60       : flushed_(false) {
61     stream() << file << ":" << line << ": ";
62   }
Flush()63   void Flush() {
64     stream() << "\n";
65     std::string s = str_.str();
66     size_t n = s.size();
67     if (fwrite(s.data(), 1, n, stderr) < n) {}  // shut up gcc
68     flushed_ = true;
69   }
~LogMessage()70   ~LogMessage() {
71     if (!flushed_) {
72       Flush();
73     }
74   }
stream()75   std::ostream& stream() { return str_; }
76 
77  private:
78   bool flushed_;
79   std::ostringstream str_;
80 
81   LogMessage(const LogMessage&) = delete;
82   LogMessage& operator=(const LogMessage&) = delete;
83 };
84 
85 // Silence "destructor never returns" warning for ~LogMessageFatal().
86 // Since this is a header file, push and then pop to limit the scope.
87 #ifdef _MSC_VER
88 #pragma warning(push)
89 #pragma warning(disable: 4722)
90 #endif
91 
92 class LogMessageFatal : public LogMessage {
93  public:
LogMessageFatal(const char * file,int line)94   LogMessageFatal(const char* file, int line)
95       : LogMessage(file, line) {}
~LogMessageFatal()96   ATTRIBUTE_NORETURN ~LogMessageFatal() {
97     Flush();
98     abort();
99   }
100  private:
101   LogMessageFatal(const LogMessageFatal&) = delete;
102   LogMessageFatal& operator=(const LogMessageFatal&) = delete;
103 };
104 
105 #ifdef _MSC_VER
106 #pragma warning(pop)
107 #endif
108 
109 #endif  // UTIL_LOGGING_H_
110