blob: 36e884ef4d1deb482f8a055b7409488cd8de26cd [file] [log] [blame]
Yuri Wiitalab7979032019-11-08 15:17:20 -08001// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef PLATFORM_API_INTERNAL_LOGGING_MACROS_H_
6#define PLATFORM_API_INTERNAL_LOGGING_MACROS_H_
7
8#include <sstream>
9
10namespace openscreen {
11namespace platform {
12namespace internal {
13
14// The stream-based logging macros below are adapted from Chromium's
15// base/logging.h.
16class LogMessage {
17 public:
18 LogMessage(LogLevel level, const char* file, int line)
19 : level_(level), file_(file), line_(line) {}
20
21 ~LogMessage() {
22 LogWithLevel(level_, file_, line_, stream_.str());
23 if (level_ == LogLevel::kFatal) {
24 Break();
25 }
26 }
27
28 std::ostream& stream() { return stream_; }
29
30 protected:
31 const LogLevel level_;
32
33 // The file here comes from the __FILE__ macro, which should persist while
34 // we are doing the logging. Hence, keeping it unmanaged here and not
35 // creating a copy should be safe.
36 const char* const file_;
37 const int line_;
38 std::ostringstream stream_;
39};
40
41// Used by the OSP_LAZY_STREAM macro to return void after evaluating an ostream
42// chain expression.
43class Voidify {
44 public:
45 void operator&(std::ostream&) {}
46};
47
48} // namespace internal
49} // namespace platform
50} // namespace openscreen
51
52#define OSP_LAZY_STREAM(condition, stream) \
53 !(condition) ? (void)0 : openscreen::platform::internal::Voidify() & (stream)
54#define OSP_LOG_IS_ON(level_enum) \
55 openscreen::platform::IsLoggingOn( \
56 openscreen::platform::LogLevel::level_enum, __FILE__)
57#define OSP_LOG_STREAM(level_enum) \
58 openscreen::platform::internal::LogMessage( \
59 openscreen::platform::LogLevel::level_enum, __FILE__, __LINE__) \
60 .stream()
61
62#define OSP_VLOG \
63 OSP_LAZY_STREAM(OSP_LOG_IS_ON(kVerbose), OSP_LOG_STREAM(kVerbose))
64#define OSP_LOG_INFO \
65 OSP_LAZY_STREAM(OSP_LOG_IS_ON(kInfo), OSP_LOG_STREAM(kInfo))
66#define OSP_LOG_WARN \
67 OSP_LAZY_STREAM(OSP_LOG_IS_ON(kWarning), OSP_LOG_STREAM(kWarning))
68#define OSP_LOG_ERROR \
69 OSP_LAZY_STREAM(OSP_LOG_IS_ON(kError), OSP_LOG_STREAM(kError))
70#define OSP_LOG_FATAL \
71 OSP_LAZY_STREAM(OSP_LOG_IS_ON(kFatal), OSP_LOG_STREAM(kFatal))
72
73// TODO(miu): Remove this legacy alias.
74#define OSP_LOG OSP_LOG_INFO
75
76#define OSP_VLOG_IF(condition) !(condition) ? (void)0 : OSP_VLOG
77#define OSP_LOG_IF(level, condition) !(condition) ? (void)0 : OSP_LOG_##level
78
79// TODO(btolsch): Add tests for (D)OSP_CHECK and possibly logging.
80#define OSP_CHECK(condition) \
81 OSP_LOG_IF(FATAL, !(condition)) << "OSP_CHECK(" << #condition << ") failed: "
82
83#define OSP_CHECK_EQ(a, b) \
84 OSP_CHECK((a) == (b)) << (a) << " vs. " << (b) << ": "
85#define OSP_CHECK_NE(a, b) \
86 OSP_CHECK((a) != (b)) << (a) << " vs. " << (b) << ": "
87#define OSP_CHECK_LT(a, b) OSP_CHECK((a) < (b)) << (a) << " vs. " << (b) << ": "
88#define OSP_CHECK_LE(a, b) \
89 OSP_CHECK((a) <= (b)) << (a) << " vs. " << (b) << ": "
90#define OSP_CHECK_GT(a, b) OSP_CHECK((a) > (b)) << (a) << " vs. " << (b) << ": "
91#define OSP_CHECK_GE(a, b) \
92 OSP_CHECK((a) >= (b)) << (a) << " vs. " << (b) << ": "
93
94#if defined(_DEBUG) || defined(DCHECK_ALWAYS_ON)
95#define OSP_DCHECK_IS_ON() 1
96#define OSP_DCHECK(condition) OSP_CHECK(condition)
97#define OSP_DCHECK_EQ(a, b) OSP_CHECK_EQ(a, b)
98#define OSP_DCHECK_NE(a, b) OSP_CHECK_NE(a, b)
99#define OSP_DCHECK_LT(a, b) OSP_CHECK_LT(a, b)
100#define OSP_DCHECK_LE(a, b) OSP_CHECK_LE(a, b)
101#define OSP_DCHECK_GT(a, b) OSP_CHECK_GT(a, b)
102#define OSP_DCHECK_GE(a, b) OSP_CHECK_GE(a, b)
103#else
104#define OSP_DCHECK_IS_ON() 0
105// When DCHECKs are off, nothing will be logged. Use that fact to make
106// references to the |condition| expression (or |a| and |b|) so the compiler
107// won't emit unused variable warnings/errors when DCHECKs are turned off.
108#define OSP_EAT_STREAM OSP_LOG_IF(FATAL, false)
109#define OSP_DCHECK(condition) OSP_EAT_STREAM << !(condition)
110#define OSP_DCHECK_EQ(a, b) OSP_EAT_STREAM << !((a) == (b))
111#define OSP_DCHECK_NE(a, b) OSP_EAT_STREAM << !((a) != (b))
112#define OSP_DCHECK_LT(a, b) OSP_EAT_STREAM << !((a) < (b))
113#define OSP_DCHECK_LE(a, b) OSP_EAT_STREAM << !((a) <= (b))
114#define OSP_DCHECK_GT(a, b) OSP_EAT_STREAM << !((a) > (b))
115#define OSP_DCHECK_GE(a, b) OSP_EAT_STREAM << !((a) >= (b))
116#endif
117
118#define OSP_DVLOG OSP_VLOG_IF(OSP_DCHECK_IS_ON())
119#define OSP_DLOG_INFO OSP_LOG_IF(INFO, OSP_DCHECK_IS_ON())
120#define OSP_DLOG_WARN OSP_LOG_IF(WARN, OSP_DCHECK_IS_ON())
121#define OSP_DLOG_ERROR OSP_LOG_IF(ERROR, OSP_DCHECK_IS_ON())
122#define OSP_DLOG_FATAL OSP_LOG_IF(FATAL, OSP_DCHECK_IS_ON())
123#define OSP_DVLOG_IF(condition) OSP_VLOG_IF(OSP_DCHECK_IS_ON() && (condition))
124#define OSP_DLOG_IF(level, condition) \
125 OSP_LOG_IF(level, OSP_DCHECK_IS_ON() && (condition))
126
127// Log when unimplemented code points are reached: If verbose logging is turned
128// on, log always. Otherwise, just attempt to log once.
129#define OSP_UNIMPLEMENTED() \
130 if (OSP_LOG_IS_ON(kVerbose)) { \
131 OSP_LOG_STREAM(kVerbose) << __func__ << ": UNIMPLEMENTED() hit."; \
132 } else { \
133 static bool needs_warning = true; \
134 if (needs_warning) { \
135 OSP_LOG_WARN << __func__ << ": UNIMPLEMENTED() hit."; \
136 needs_warning = false; \
137 } \
138 }
139
140#define OSP_NOTREACHED() OSP_LOG_FATAL << __func__ << ": NOTREACHED() hit."
141
142#endif // PLATFORM_API_INTERNAL_LOGGING_MACROS_H_