summaryrefslogtreecommitdiffstats
path: root/base/logging.h
diff options
context:
space:
mode:
Diffstat (limited to 'base/logging.h')
-rw-r--r--base/logging.h178
1 files changed, 170 insertions, 8 deletions
diff --git a/base/logging.h b/base/logging.h
index a1d439c..de8de71 100644
--- a/base/logging.h
+++ b/base/logging.h
@@ -75,6 +75,18 @@
//
// We also override the standard 'assert' to use 'DLOG_ASSERT'.
//
+// Lastly, there is:
+//
+// PLOG(ERROR) << "Couldn't do foo";
+// DPLOG(ERROR) << "Couldn't do foo";
+// PLOG_IF(ERROR, cond) << "Couldn't do foo";
+// DPLOG_IF(ERROR, cond) << "Couldn't do foo";
+// PCHECK(condition) << "Couldn't do foo";
+// DPCHECK(condition) << "Couldn't do foo";
+//
+// which append the last system error to the message in string form (taken from
+// GetLastError() on Windows and errno on POSIX).
+//
// The supported severity levels for macros that allow you to specify one
// are (in increasing order of severity) INFO, WARNING, ERROR, ERROR_REPORT,
// and FATAL.
@@ -192,18 +204,33 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL;
// A few definitions of macros that don't generate much code. These are used
// by LOG() and LOG_IF, etc. Since these are used all over our code, it's
// better to have compact code for these operations.
+#define COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, logging::LOG_INFO , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, logging::LOG_WARNING , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, logging::LOG_ERROR , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, \
+ logging::LOG_ERROR_REPORT , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, logging::LOG_FATAL , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
+ logging::ClassName(__FILE__, __LINE__, \
+ logging::LOG_DFATAL_LEVEL , ##__VA_ARGS__)
+
#define COMPACT_GOOGLE_LOG_INFO \
- logging::LogMessage(__FILE__, __LINE__)
+ COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
#define COMPACT_GOOGLE_LOG_WARNING \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_WARNING)
+ COMPACT_GOOGLE_LOG_EX_WARNING(LogMessage)
#define COMPACT_GOOGLE_LOG_ERROR \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR)
+ COMPACT_GOOGLE_LOG_EX_ERROR(LogMessage)
#define COMPACT_GOOGLE_LOG_ERROR_REPORT \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR_REPORT)
+ COMPACT_GOOGLE_LOG_EX_ERROR_REPORT(LogMessage)
#define COMPACT_GOOGLE_LOG_FATAL \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_FATAL)
+ COMPACT_GOOGLE_LOG_EX_FATAL(LogMessage)
#define COMPACT_GOOGLE_LOG_DFATAL \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_DFATAL_LEVEL)
+ COMPACT_GOOGLE_LOG_EX_DFATAL(LogMessage)
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
@@ -211,8 +238,9 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL;
// as COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that
// the Windows SDK does for consistency.
#define ERROR 0
-#define COMPACT_GOOGLE_LOG_0 \
- logging::LogMessage(__FILE__, __LINE__, logging::LOG_ERROR)
+#define COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
+ COMPACT_GOOGLE_LOG_EX_ERROR(ClassName , ##__VA_ARGS__)
+#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
// We use the preprocessor's merging operator, "##", so that, e.g.,
// LOG(INFO) becomes the token COMPACT_GOOGLE_LOG_INFO. There's some funny
@@ -235,12 +263,38 @@ const LogSeverity LOG_DFATAL_LEVEL = LOG_FATAL;
#define SYSLOG_ASSERT(condition) \
SYSLOG_IF(FATAL, !(condition)) << "Assert failed: " #condition ". "
+#if defined(OS_WIN)
+#define LOG_GETLASTERROR(severity) \
+ COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
+ ::logging::GetLastSystemErrorCode()).stream()
+#define LOG_GETLASTERROR_MODULE(severity, module) \
+ COMPACT_GOOGLE_LOG_EX_ ## severity(Win32ErrorLogMessage, \
+ ::logging::GetLastSystemErrorCode(), module).stream()
+// PLOG is the usual error logging macro for each platform.
+#define PLOG(severity) LOG_GETLASTERROR(severity)
+#define DPLOG(severity) DLOG_GETLASTERROR(severity)
+#elif defined(OS_POSIX)
+#define LOG_ERRNO(severity) \
+ COMPACT_GOOGLE_LOG_EX_ ## severity(ErrnoLogMessage, \
+ ::logging::GetLastSystemErrorCode()).stream()
+// PLOG is the usual error logging macro for each platform.
+#define PLOG(severity) LOG_ERRNO(severity)
+#define DPLOG(severity) DLOG_ERRNO(severity)
+// TODO(tschmelcher): Should we add OSStatus logging for Mac?
+#endif
+
+#define PLOG_IF(severity, condition) \
+ !(condition) ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity)
+
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode.
#define CHECK(condition) \
LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". "
+#define PCHECK(condition) \
+ PLOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". "
+
// A container for a string pointer which can be evaluated to a bool -
// true iff the pointer is NULL.
struct CheckOpString {
@@ -301,6 +355,20 @@ std::string* MakeCheckOpString(const int& v1,
#define DLOG_ASSERT(condition) \
true ? (void) 0 : LOG_ASSERT(condition)
+#if defined(OS_WIN)
+#define DLOG_GETLASTERROR(severity) \
+ true ? (void) 0 : logging::LogMessageVoidify() & LOG_GETLASTERROR(severity)
+#define DLOG_GETLASTERROR_MODULE(severity, module) \
+ true ? (void) 0 : logging::LogMessageVoidify() & \
+ LOG_GETLASTERROR_MODULE(severity, module)
+#elif defined(OS_POSIX)
+#define DLOG_ERRNO(severity) \
+ true ? (void) 0 : logging::LogMessageVoidify() & LOG_ERRNO(severity)
+#endif
+
+#define DPLOG_IF(severity, condition) \
+ true ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity)
+
enum { DEBUG_MODE = 0 };
// This macro can be followed by a sequence of stream parameters in
@@ -315,6 +383,9 @@ enum { DEBUG_MODE = 0 };
#define DCHECK(condition) \
while (false && (condition)) NDEBUG_EAT_STREAM_PARAMETERS
+#define DPCHECK(condition) \
+ while (false && (condition)) NDEBUG_EAT_STREAM_PARAMETERS
+
#define DCHECK_EQ(val1, val2) \
while (false && (val1) == (val2)) NDEBUG_EAT_STREAM_PARAMETERS
@@ -354,11 +425,24 @@ enum { DEBUG_MODE = 0 };
#define DLOG_IF(severity, condition) LOG_IF(severity, condition)
#define DLOG_ASSERT(condition) LOG_ASSERT(condition)
+#if defined(OS_WIN)
+#define DLOG_GETLASTERROR(severity) LOG_GETLASTERROR(severity)
+#define DLOG_GETLASTERROR_MODULE(severity, module) \
+ LOG_GETLASTERROR_MODULE(severity, module)
+#elif defined(OS_POSIX)
+#define DLOG_ERRNO(severity) LOG_ERRNO(severity)
+#endif
+
+#define DPLOG_IF(severity, condition) PLOG_IF(severity, condition)
+
// debug-only checking. not executed in NDEBUG mode.
enum { DEBUG_MODE = 1 };
#define DCHECK(condition) \
LOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". "
+#define DPCHECK(condition) \
+ PLOG_IF(FATAL, !(condition)) << "Check failed: " #condition ". "
+
// Helper macro for binary operators.
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
#define DCHECK_OP(name, op, val1, val2) \
@@ -413,6 +497,20 @@ DECLARE_DCHECK_STROP_IMPL(_stricmp, false)
#define DLOG_ASSERT(condition) \
true ? (void) 0 : LOG_ASSERT(condition)
+#if defined(OS_WIN)
+#define DLOG_GETLASTERROR(severity) \
+ true ? (void) 0 : logging::LogMessageVoidify() & LOG_GETLASTERROR(severity)
+#define DLOG_GETLASTERROR_MODULE(severity, module) \
+ true ? (void) 0 : logging::LogMessageVoidify() & \
+ LOG_GETLASTERROR_MODULE(severity, module)
+#elif defined(OS_POSIX)
+#define DLOG_ERRNO(severity) \
+ true ? (void) 0 : logging::LogMessageVoidify() & LOG_ERRNO(severity)
+#endif
+
+#define DPLOG_IF(severity, condition) \
+ true ? (void) 0 : logging::LogMessageVoidify() & PLOG(severity)
+
enum { DEBUG_MODE = 0 };
// This macro can be followed by a sequence of stream parameters in
@@ -428,6 +526,10 @@ extern bool g_enable_dcheck;
!logging::g_enable_dcheck ? void (0) : \
LOG_IF(ERROR_REPORT, !(condition)) << "Check failed: " #condition ". "
+#define DPCHECK(condition) \
+ !logging::g_enable_dcheck ? void (0) : \
+ PLOG_IF(ERROR_REPORT, !(condition)) << "Check failed: " #condition ". "
+
// Helper macro for binary operators.
// Don't use this macro directly in your code, use DCHECK_EQ et al below.
#define DCHECK_OP(name, op, val1, val2) \
@@ -597,6 +699,66 @@ class LogMessageVoidify {
void operator&(std::ostream&) { }
};
+#if defined(OS_WIN)
+typedef unsigned long SystemErrorCode;
+#elif defined(OS_POSIX)
+typedef int SystemErrorCode;
+#endif
+
+// Alias for ::GetLastError() on Windows and errno on POSIX. Avoids having to
+// pull in windows.h just for GetLastError() and DWORD.
+SystemErrorCode GetLastSystemErrorCode();
+
+#if defined(OS_WIN)
+// Appends a formatted system message of the GetLastError() type.
+class Win32ErrorLogMessage {
+ public:
+ Win32ErrorLogMessage(const char* file,
+ int line,
+ LogSeverity severity,
+ SystemErrorCode err,
+ const char* module);
+
+ Win32ErrorLogMessage(const char* file,
+ int line,
+ LogSeverity severity,
+ SystemErrorCode err);
+
+ std::ostream& stream() { return log_message_.stream(); }
+
+ // Appends the error message before destructing the encapsulated class.
+ ~Win32ErrorLogMessage();
+
+ private:
+ SystemErrorCode err_;
+ // Optional name of the module defining the error.
+ const char* module_;
+ LogMessage log_message_;
+
+ DISALLOW_COPY_AND_ASSIGN(Win32ErrorLogMessage);
+};
+#elif defined(OS_POSIX)
+// Appends a formatted system message of the errno type
+class ErrnoLogMessage {
+ public:
+ ErrnoLogMessage(const char* file,
+ int line,
+ LogSeverity severity,
+ SystemErrorCode err);
+
+ std::ostream& stream() { return log_message_.stream(); }
+
+ // Appends the error message before destructing the encapsulated class.
+ ~ErrnoLogMessage();
+
+ private:
+ SystemErrorCode err_;
+ LogMessage log_message_;
+
+ DISALLOW_COPY_AND_ASSIGN(ErrnoLogMessage);
+};
+#endif // OS_WIN
+
// Closes the log file explicitly if open.
// NOTE: Since the log file is opened as necessary by the action of logging
// statements, there's no guarantee that it will stay closed