initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame^] | 1 | // Copyright 2008, Google Inc. |
| 2 | // All rights reserved. |
| 3 | // |
| 4 | // Redistribution and use in source and binary forms, with or without |
| 5 | // modification, are permitted provided that the following conditions are |
| 6 | // met: |
| 7 | // |
| 8 | // * Redistributions of source code must retain the above copyright |
| 9 | // notice, this list of conditions and the following disclaimer. |
| 10 | // * Redistributions in binary form must reproduce the above |
| 11 | // copyright notice, this list of conditions and the following disclaimer |
| 12 | // in the documentation and/or other materials provided with the |
| 13 | // distribution. |
| 14 | // * Neither the name of Google Inc. nor the names of its |
| 15 | // contributors may be used to endorse or promote products derived from |
| 16 | // this software without specific prior written permission. |
| 17 | // |
| 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | |
| 30 | #ifndef BASE_LOGGING_H__ |
| 31 | #define BASE_LOGGING_H__ |
| 32 | |
| 33 | #include <string> |
| 34 | #include <cstring> |
| 35 | #include <sstream> |
| 36 | |
| 37 | #include "base/basictypes.h" |
| 38 | #include "base/scoped_ptr.h" |
| 39 | |
| 40 | // |
| 41 | // Optional message capabilities |
| 42 | // ----------------------------- |
| 43 | // Assertion failed messages and fatal errors are displayed in a dialog box |
| 44 | // before the application exits. However, running this UI creates a message |
| 45 | // loop, which causes application messages to be processed and potentially |
| 46 | // dispatched to existing application windows. Since the application is in a |
| 47 | // bad state when this assertion dialog is displayed, these messages may not |
| 48 | // get processed and hang the dialog, or the application might go crazy. |
| 49 | // |
| 50 | // Therefore, it can be beneficial to display the error dialog in a separate |
| 51 | // process from the main application. When the logging system needs to display |
| 52 | // a fatal error dialog box, it will look for a program called |
| 53 | // "DebugMessage.exe" in the same directory as the application executable. It |
| 54 | // will run this application with the message as the command line, and will |
| 55 | // not include the name of the application as is traditional for easier |
| 56 | // parsing. |
| 57 | // |
| 58 | // The code for DebugMessage.exe is only one line. In WinMain, do: |
| 59 | // MessageBox(NULL, GetCommandLineW(), L"Fatal Error", 0); |
| 60 | // |
| 61 | // If DebugMessage.exe is not found, the logging code will use a normal |
| 62 | // MessageBox, potentially causing the problems discussed above. |
| 63 | |
| 64 | |
| 65 | // Instructions |
| 66 | // ------------ |
| 67 | // |
| 68 | // Make a bunch of macros for logging. The way to log things is to stream |
| 69 | // things to LOG(<a particular severity level>). E.g., |
| 70 | // |
| 71 | // LOG(INFO) << "Found " << num_cookies << " cookies"; |
| 72 | // |
| 73 | // You can also do conditional logging: |
| 74 | // |
| 75 | // LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; |
| 76 | // |
| 77 | // The above will cause log messages to be output on the 1st, 11th, 21st, ... |
| 78 | // times it is executed. Note that the special COUNTER value is used to |
| 79 | // identify which repetition is happening. |
| 80 | // |
| 81 | // The CHECK(condition) macro is active in both debug and release builds and |
| 82 | // effectively performs a LOG(FATAL) which terminates the process and |
| 83 | // generates a crashdump unless a debugger is attached. |
| 84 | // |
| 85 | // There are also "debug mode" logging macros like the ones above: |
| 86 | // |
| 87 | // DLOG(INFO) << "Found cookies"; |
| 88 | // |
| 89 | // DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies"; |
| 90 | // |
| 91 | // All "debug mode" logging is compiled away to nothing for non-debug mode |
| 92 | // compiles. LOG_IF and development flags also work well together |
| 93 | // because the code can be compiled away sometimes. |
| 94 | // |
| 95 | // We also have |
| 96 | // |
| 97 | // LOG_ASSERT(assertion); |
| 98 | // DLOG_ASSERT(assertion); |
| 99 | // |
| 100 | // which is syntactic sugar for {,D}LOG_IF(FATAL, assert fails) << assertion; |
| 101 | // |
| 102 | // We also override the standard 'assert' to use 'DLOG_ASSERT'. |
| 103 | // |
| 104 | // The supported severity levels for macros that allow you to specify one |
| 105 | // are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL. |
| 106 | // |
| 107 | // There is also the special severity of DFATAL, which logs FATAL in |
| 108 | // debug mode, ERROR in normal mode. |
| 109 | // |
| 110 | // Very important: logging a message at the FATAL severity level causes |
| 111 | // the program to terminate (after the message is logged). |
| 112 | |
| 113 | namespace logging { |
| 114 | |
| 115 | // Where to record logging output? A flat file and/or system debug log via |
| 116 | // OutputDebugString. Defaults to LOG_ONLY_TO_FILE. |
| 117 | enum LoggingDestination { LOG_NONE, |
| 118 | LOG_ONLY_TO_FILE, |
| 119 | LOG_ONLY_TO_SYSTEM_DEBUG_LOG, |
| 120 | LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG }; |
| 121 | |
| 122 | // Indicates that the log file should be locked when being written to. |
| 123 | // Often, there is no locking, which is fine for a single threaded program. |
| 124 | // If logging is being done from multiple threads or there can be more than |
| 125 | // one process doing the logging, the file should be locked during writes to |
| 126 | // make each log outut atomic. Other writers will block. |
| 127 | // |
| 128 | // All processes writing to the log file must have their locking set for it to |
| 129 | // work properly. Defaults to DONT_LOCK_LOG_FILE. |
| 130 | enum LogLockingState { LOCK_LOG_FILE, DONT_LOCK_LOG_FILE }; |
| 131 | |
| 132 | // On startup, should we delete or append to an existing log file (if any)? |
| 133 | // Defaults to APPEND_TO_OLD_LOG_FILE. |
| 134 | enum OldFileDeletionState { DELETE_OLD_LOG_FILE, APPEND_TO_OLD_LOG_FILE }; |
| 135 | |
| 136 | // Sets the log file name and other global logging state. Calling this function |
| 137 | // is recommended, and is normally done at the beginning of application init. |
| 138 | // If you don't call it, all the flags will be initialized to their default |
| 139 | // values, and there is a race condition that may leak a critical section |
| 140 | // object if two threads try to do the first log at the same time. |
| 141 | // See the definition of the enums above for descriptions and default values. |
| 142 | // |
| 143 | // The default log file is initialized to "debug.log" in the application |
| 144 | // directory. You probably don't want this, especially since the program |
| 145 | // directory may not be writable on an enduser's system. |
| 146 | #if defined(WIN32) |
| 147 | void InitLogging(const wchar_t* log_file, LoggingDestination logging_dest, |
| 148 | LogLockingState lock_log, OldFileDeletionState delete_old); |
| 149 | #else |
| 150 | // TODO(avi): do we want to do a unification of character types here? |
| 151 | void InitLogging(const char* log_file, LoggingDestination logging_dest, |
| 152 | LogLockingState lock_log, OldFileDeletionState delete_old); |
| 153 | #endif |
| 154 | |
| 155 | // Sets the log level. Anything at or above this level will be written to the |
| 156 | // log file/displayed to the user (if applicable). Anything below this level |
| 157 | // will be silently ignored. The log level defaults to 0 (everything is logged) |
| 158 | // if this function is not called. |
| 159 | void SetMinLogLevel(int level); |
| 160 | |
| 161 | // Gets the curreng log level. |
| 162 | int GetMinLogLevel(); |
| 163 | |
| 164 | // Sets the log filter prefix. Any log message below LOG_ERROR severity that |
| 165 | // doesn't start with this prefix with be silently ignored. The filter defaults |
| 166 | // to NULL (everything is logged) if this function is not called. Messages |
| 167 | // with severity of LOG_ERROR or higher will not be filtered. |
| 168 | void SetLogFilterPrefix(const char* filter); |
| 169 | |
| 170 | // Sets the common items you want to be prepended to each log message. |
| 171 | // process and thread IDs default to off, the timestamp defaults to on. |
| 172 | // If this function is not called, logging defaults to writing the timestamp |
| 173 | // only. |
| 174 | void SetLogItems(bool enable_process_id, bool enable_thread_id, |
| 175 | bool enable_timestamp, bool enable_tickcount); |
| 176 | |
| 177 | // Sets the Log Assert Handler that will be used to notify of check failures. |
| 178 | // The default handler shows a dialog box, however clients can use this |
| 179 | // function to override with their own handling (e.g. a silent one for Unit |
| 180 | // Tests) |
| 181 | typedef void (*LogAssertHandlerFunction)(const std::string& str); |
| 182 | void SetLogAssertHandler(LogAssertHandlerFunction handler); |
| 183 | |
| 184 | typedef int LogSeverity; |
| 185 | const LogSeverity LOG_INFO = 0; |
| 186 | const LogSeverity LOG_WARNING = 1; |
| 187 | const LogSeverity LOG_ERROR = 2; |
| 188 | const LogSeverity LOG_FATAL = 3; |
| 189 | const LogSeverity LOG_NUM_SEVERITIES = 4; |
| 190 | |
| 191 | // LOG_DFATAL_LEVEL is LOG_FATAL in debug mode, ERROR in normal mode |
| 192 | #ifdef NDEBUG |
| 193 | const LogSeverity LOG_DFATAL_LEVEL = LOG_ERROR; |
| 194 | #else |
| 195 | const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL; |
| 196 | #endif |
| 197 | |
| 198 | // A few definitions of macros that don't generate much code. These are used |
| 199 | // by LOG() and LOG_IF, etc. Since these are used all over our code, it's |
| 200 | // better to have compact code for these operations. |
| 201 | #define COMPACT_GOOGLE_LOG_INFO \ |
| 202 | logging::LogMessage(__FILE__, __LINE__) |
| 203 | #define COMPACT_GOOGLE_LOG_WARNING \ |
| 204 | logging::LogMessage(__FILE__, __LINE__, logging::LOG_WARNING) |
| 205 | #define COMPACT_GOOGLE_LOG_ERROR \ |
| 206 | logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR) |
| 207 | #define COMPACT_GOOGLE_LOG_FATAL \ |
| 208 | logging::LogMessage(__FILE__, __LINE__, logging::LOG_FATAL) |
| 209 | #define COMPACT_GOOGLE_LOG_DFATAL \ |
| 210 | logging::LogMessage(__FILE__, __LINE__, logging::LOG_DFATAL_LEVEL) |
| 211 | |
| 212 | // wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets |
| 213 | // substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us |
| 214 | // to keep using this syntax, we define this macro to do the same thing |
| 215 | // as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that |
| 216 | // the Windows SDK does for consistency. |
| 217 | #define ERROR 0 |
| 218 | #define COMPACT_GOOGLE_LOG_0 \ |
| 219 | logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR) |
| 220 | |
| 221 | // We use the preprocessor's merging operator, "##", so that, e.g., |
| 222 | // LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny |
| 223 | // subtle difference between ostream member streaming functions (e.g., |
| 224 | // ostream::operator<<(int) and ostream non-member streaming functions |
| 225 | // (e.g., ::operator<<(ostream&, string&): it turns out that it's |
| 226 | // impossible to stream something like a string directly to an unnamed |
| 227 | // ostream. We employ a neat hack by calling the stream() member |
| 228 | // function of LogMessage which seems to avoid the problem. |
| 229 | |
| 230 | #define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream() |
| 231 | #define SYSLOG(severity) LOG(severity) |
| 232 | |
| 233 | #define LOG_IF(severity, condition) \ |
| 234 | !(condition) ? (void) 0 : logging::LogMessageVoidify() & LOG(severity) |
| 235 | #define SYSLOG_IF(severity, condition) LOG_IF(severity, condition) |
| 236 | |
| 237 | #define LOG_ASSERT(condition) \ |
| 238 | LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " |
| 239 | #define SYSLOG_ASSERT(condition) \ |
| 240 | SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". " |
| 241 | |
| 242 | // CHECK dies with a fatal error if condition is not true. It is *not* |
| 243 | // controlled by NDEBUG, so the check will be executed regardless of |
| 244 | // compilation mode. |
| 245 | #define CHECK(condition) \ |
| 246 | LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " |
| 247 | |
| 248 | // A container for a string pointer which can be evaluated to a bool - |
| 249 | // true iff the pointer is NULL. |
| 250 | struct CheckOpString { |
| 251 | CheckOpString(std::string* str) : str_(str) { } |
| 252 | // No destructor: if str_ is non-NULL, we're about to LOG(FATAL), |
| 253 | // so there's no point in cleaning up str_. |
| 254 | operator bool() const { return str_ != NULL; } |
| 255 | std::string* str_; |
| 256 | }; |
| 257 | |
| 258 | // Build the error message string. This is separate from the "Impl" |
| 259 | // function template because it is not performance critical and so can |
| 260 | // be out of line, while the "Impl" code should be inline. |
| 261 | template<class t1, class t2> |
| 262 | std::string* MakeCheckOpString(const t1& v1, const t2& v2, const char* names) { |
| 263 | std::ostringstream ss; |
| 264 | ss << names << " (" << v1 << " vs. " << v2 << ")"; |
| 265 | std::string* msg = new std::string(ss.str()); |
| 266 | return msg; |
| 267 | } |
| 268 | |
| 269 | extern std::string* MakeCheckOpStringIntInt(int v1, int v2, const char* names); |
| 270 | |
| 271 | template<int, int> |
| 272 | std::string* MakeCheckOpString(const int& v1, const int& v2, const char* names) { |
| 273 | return MakeCheckOpStringIntInt(v1, v2, names); |
| 274 | } |
| 275 | |
| 276 | // Plus some debug-logging macros that get compiled to nothing for production |
| 277 | // |
| 278 | // DEBUG_MODE is for uses like |
| 279 | // if (DEBUG_MODE) foo.CheckThatFoo(); |
| 280 | // instead of |
| 281 | // #ifndef NDEBUG |
| 282 | // foo.CheckThatFoo(); |
| 283 | // #endif |
| 284 | |
| 285 | #ifndef NDEBUG |
| 286 | |
| 287 | #define DLOG(severity) LOG(severity) |
| 288 | #define DLOG_IF(severity, condition) LOG_IF(severity, condition) |
| 289 | #define DLOG_ASSERT(condition) LOG_ASSERT(condition) |
| 290 | |
| 291 | // debug-only checking. not executed in NDEBUG mode. |
| 292 | enum { DEBUG_MODE = 1 }; |
| 293 | #define DCHECK(condition) \ |
| 294 | LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " |
| 295 | |
| 296 | // Helper macro for binary operators. |
| 297 | // Don't use this macro directly in your code, use DCHECK_EQ et al below. |
| 298 | #define DCHECK_OP(name, op, val1, val2) \ |
| 299 | if (logging::CheckOpString _result = \ |
| 300 | logging::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ |
| 301 | logging::LogMessage(__FILE__, __LINE__, _result).stream() |
| 302 | |
| 303 | // Helper functions for string comparisons. |
| 304 | // To avoid bloat, the definitions are in logging.cc. |
| 305 | #define DECLARE_DCHECK_STROP_IMPL(func, expected) \ |
| 306 | std::string* Check##func##expected##Impl(const char* s1, \ |
| 307 | const char* s2, \ |
| 308 | const char* names); |
| 309 | DECLARE_DCHECK_STROP_IMPL(strcmp, true) |
| 310 | DECLARE_DCHECK_STROP_IMPL(strcmp, false) |
| 311 | DECLARE_DCHECK_STROP_IMPL(_stricmp, true) |
| 312 | DECLARE_DCHECK_STROP_IMPL(_stricmp, false) |
| 313 | #undef DECLARE_DCHECK_STROP_IMPL |
| 314 | |
| 315 | // Helper macro for string comparisons. |
| 316 | // Don't use this macro directly in your code, use CHECK_STREQ et al below. |
| 317 | #define DCHECK_STROP(func, op, expected, s1, s2) \ |
| 318 | while (CheckOpString _result = \ |
| 319 | logging::Check##func##expected##Impl((s1), (s2), \ |
| 320 | #s1 " " #op " " #s2)) \ |
| 321 | LOG(FATAL) << *_result.str_ |
| 322 | |
| 323 | // String (char*) equality/inequality checks. |
| 324 | // CASE versions are case-insensitive. |
| 325 | // |
| 326 | // Note that "s1" and "s2" may be temporary strings which are destroyed |
| 327 | // by the compiler at the end of the current "full expression" |
| 328 | // (e.g. DCHECK_STREQ(Foo().c_str(), Bar().c_str())). |
| 329 | |
| 330 | #define DCHECK_STREQ(s1, s2) DCHECK_STROP(strcmp, ==, true, s1, s2) |
| 331 | #define DCHECK_STRNE(s1, s2) DCHECK_STROP(strcmp, !=, false, s1, s2) |
| 332 | #define DCHECK_STRCASEEQ(s1, s2) DCHECK_STROP(_stricmp, ==, true, s1, s2) |
| 333 | #define DCHECK_STRCASENE(s1, s2) DCHECK_STROP(_stricmp, !=, false, s1, s2) |
| 334 | |
| 335 | #define DCHECK_INDEX(I,A) DCHECK(I < (sizeof(A)/sizeof(A[0]))) |
| 336 | #define DCHECK_BOUND(B,A) DCHECK(B <= (sizeof(A)/sizeof(A[0]))) |
| 337 | |
| 338 | #else // NDEBUG |
| 339 | |
| 340 | #define DLOG(severity) \ |
| 341 | true ? (void) 0 : logging::LogMessageVoidify() & LOG(severity) |
| 342 | |
| 343 | #define DLOG_IF(severity, condition) \ |
| 344 | true ? (void) 0 : logging::LogMessageVoidify() & LOG(severity) |
| 345 | |
| 346 | #define DLOG_ASSERT(condition) \ |
| 347 | true ? (void) 0 : LOG_ASSERT(condition) |
| 348 | |
| 349 | enum { DEBUG_MODE = 0 }; |
| 350 | |
| 351 | // This macro can be followed by a sequence of stream parameters in |
| 352 | // non-debug mode. The DCHECK and friends macros use this so that |
| 353 | // the expanded expression DCHECK(foo) << "asdf" is still syntactically |
| 354 | // valid, even though the expression will get optimized away. |
| 355 | #define NDEBUG_EAT_STREAM_PARAMETERS \ |
| 356 | logging::LogMessage(__FILE__, __LINE__).stream() |
| 357 | |
| 358 | // Set to true in InitLogging when we want to enable the dchecks in release. |
| 359 | extern bool g_enable_dcheck; |
| 360 | #define DCHECK(condition) \ |
| 361 | !logging::g_enable_dcheck ? void (0) : \ |
| 362 | LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". " |
| 363 | |
| 364 | // Helper macro for binary operators. |
| 365 | // Don't use this macro directly in your code, use DCHECK_EQ et al below. |
| 366 | #define DCHECK_OP(name, op, val1, val2) \ |
| 367 | if (logging::g_enable_dcheck) \ |
| 368 | if (logging::CheckOpString _result = \ |
| 369 | logging::Check##name##Impl((val1), (val2), #val1 " " #op " " #val2)) \ |
| 370 | logging::LogMessage(__FILE__, __LINE__, _result).stream() |
| 371 | |
| 372 | #define DCHECK_STREQ(str1, str2) \ |
| 373 | while (false) NDEBUG_EAT_STREAM_PARAMETERS |
| 374 | |
| 375 | #define DCHECK_STRCASEEQ(str1, str2) \ |
| 376 | while (false) NDEBUG_EAT_STREAM_PARAMETERS |
| 377 | |
| 378 | #define DCHECK_STRNE(str1, str2) \ |
| 379 | while (false) NDEBUG_EAT_STREAM_PARAMETERS |
| 380 | |
| 381 | #define DCHECK_STRCASENE(str1, str2) \ |
| 382 | while (false) NDEBUG_EAT_STREAM_PARAMETERS |
| 383 | |
| 384 | #endif // NDEBUG |
| 385 | |
| 386 | // Helper functions for DCHECK_OP macro. |
| 387 | // The (int, int) specialization works around the issue that the compiler |
| 388 | // will not instantiate the template version of the function on values of |
| 389 | // unnamed enum type - see comment below. |
| 390 | #define DEFINE_DCHECK_OP_IMPL(name, op) \ |
| 391 | template <class t1, class t2> \ |
| 392 | inline std::string* Check##name##Impl(const t1& v1, const t2& v2, \ |
| 393 | const char* names) { \ |
| 394 | if (v1 op v2) return NULL; \ |
| 395 | else return MakeCheckOpString(v1, v2, names); \ |
| 396 | } \ |
| 397 | inline std::string* Check##name##Impl(int v1, int v2, const char* names) { \ |
| 398 | if (v1 op v2) return NULL; \ |
| 399 | else return MakeCheckOpString(v1, v2, names); \ |
| 400 | } |
| 401 | DEFINE_DCHECK_OP_IMPL(EQ, ==) |
| 402 | DEFINE_DCHECK_OP_IMPL(NE, !=) |
| 403 | DEFINE_DCHECK_OP_IMPL(LE, <=) |
| 404 | DEFINE_DCHECK_OP_IMPL(LT, < ) |
| 405 | DEFINE_DCHECK_OP_IMPL(GE, >=) |
| 406 | DEFINE_DCHECK_OP_IMPL(GT, > ) |
| 407 | #undef DEFINE_DCHECK_OP_IMPL |
| 408 | |
| 409 | // Equality/Inequality checks - compare two values, and log a LOG_FATAL message |
| 410 | // including the two values when the result is not as expected. The values |
| 411 | // must have operator<<(ostream, ...) defined. |
| 412 | // |
| 413 | // You may append to the error message like so: |
| 414 | // DCHECK_NE(1, 2) << ": The world must be ending!"; |
| 415 | // |
| 416 | // We are very careful to ensure that each argument is evaluated exactly |
| 417 | // once, and that anything which is legal to pass as a function argument is |
| 418 | // legal here. In particular, the arguments may be temporary expressions |
| 419 | // which will end up being destroyed at the end of the apparent statement, |
| 420 | // for example: |
| 421 | // DCHECK_EQ(string("abc")[1], 'b'); |
| 422 | // |
| 423 | // WARNING: These may not compile correctly if one of the arguments is a pointer |
| 424 | // and the other is NULL. To work around this, simply static_cast NULL to the |
| 425 | // type of the desired pointer. |
| 426 | |
| 427 | #define DCHECK_EQ(val1, val2) DCHECK_OP(EQ, ==, val1, val2) |
| 428 | #define DCHECK_NE(val1, val2) DCHECK_OP(NE, !=, val1, val2) |
| 429 | #define DCHECK_LE(val1, val2) DCHECK_OP(LE, <=, val1, val2) |
| 430 | #define DCHECK_LT(val1, val2) DCHECK_OP(LT, < , val1, val2) |
| 431 | #define DCHECK_GE(val1, val2) DCHECK_OP(GE, >=, val1, val2) |
| 432 | #define DCHECK_GT(val1, val2) DCHECK_OP(GT, > , val1, val2) |
| 433 | |
| 434 | |
| 435 | #define NOTREACHED() DCHECK(false) |
| 436 | |
| 437 | // Redefine the standard assert to use our nice log files |
| 438 | #undef assert |
| 439 | #define assert(x) DLOG_ASSERT(x) |
| 440 | |
| 441 | // This class more or less represents a particular log message. You |
| 442 | // create an instance of LogMessage and then stream stuff to it. |
| 443 | // When you finish streaming to it, ~LogMessage is called and the |
| 444 | // full message gets streamed to the appropriate destination. |
| 445 | // |
| 446 | // You shouldn't actually use LogMessage's constructor to log things, |
| 447 | // though. You should use the LOG() macro (and variants thereof) |
| 448 | // above. |
| 449 | class LogMessage { |
| 450 | public: |
| 451 | LogMessage(const char* file, int line, LogSeverity severity, int ctr); |
| 452 | |
| 453 | // Two special constructors that generate reduced amounts of code at |
| 454 | // LOG call sites for common cases. |
| 455 | // |
| 456 | // Used for LOG(INFO): Implied are: |
| 457 | // severity = LOG_INFO, ctr = 0 |
| 458 | // |
| 459 | // Using this constructor instead of the more complex constructor above |
| 460 | // saves a couple of bytes per call site. |
| 461 | LogMessage(const char* file, int line); |
| 462 | |
| 463 | // Used for LOG(severity) where severity != INFO. Implied |
| 464 | // are: ctr = 0 |
| 465 | // |
| 466 | // Using this constructor instead of the more complex constructor above |
| 467 | // saves a couple of bytes per call site. |
| 468 | LogMessage(const char* file, int line, LogSeverity severity); |
| 469 | |
| 470 | // A special constructor used for check failures. |
| 471 | // Implied severity = LOG_FATAL |
| 472 | LogMessage(const char* file, int line, const CheckOpString& result); |
| 473 | |
| 474 | ~LogMessage(); |
| 475 | |
| 476 | std::ostream& stream() { return stream_; } |
| 477 | |
| 478 | private: |
| 479 | void Init(const char* file, int line); |
| 480 | |
| 481 | LogSeverity severity_; |
| 482 | std::ostringstream stream_; |
| 483 | int message_start_; // offset of the start of the message (past prefix info). |
| 484 | |
| 485 | DISALLOW_EVIL_CONSTRUCTORS(LogMessage); |
| 486 | }; |
| 487 | |
| 488 | // A non-macro interface to the log facility; (useful |
| 489 | // when the logging level is not a compile-time constant). |
| 490 | inline void LogAtLevel(int const log_level, std::string const &msg) { |
| 491 | LogMessage(__FILE__, __LINE__, log_level).stream() << msg; |
| 492 | } |
| 493 | |
| 494 | // This class is used to explicitly ignore values in the conditional |
| 495 | // logging macros. This avoids compiler warnings like "value computed |
| 496 | // is not used" and "statement has no effect". |
| 497 | class LogMessageVoidify { |
| 498 | public: |
| 499 | LogMessageVoidify() { } |
| 500 | // This has to be an operator with a precedence lower than << but |
| 501 | // higher than ?: |
| 502 | void operator&(std::ostream&) { } |
| 503 | }; |
| 504 | |
| 505 | // Closes the log file explicitly if open. |
| 506 | // NOTE: Since the log file is opened as necessary by the action of logging |
| 507 | // statements, there's no guarantee that it will stay closed |
| 508 | // after this call. |
| 509 | void CloseLogFile(); |
| 510 | |
| 511 | } // namespace Logging |
| 512 | |
| 513 | // These functions are provided as a convenience for logging, which is where we |
| 514 | // use streams (it is against Google style to use streams in other places). It |
| 515 | // is designed to allow you to emit non-ASCII Unicode strings to the log file, |
| 516 | // which is normally ASCII. It is relatively slow, so try not to use it for |
| 517 | // common cases. Non-ASCII characters will be converted to UTF-8 by these operators. |
| 518 | std::ostream& operator<<(std::ostream& out, const wchar_t* wstr); |
| 519 | inline std::ostream& operator<<(std::ostream& out, const std::wstring& wstr) { |
| 520 | return out << wstr.c_str(); |
| 521 | } |
| 522 | |
| 523 | #endif // BASE_LOGGING_H__ |