1 // Copyright 2022 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 // ----------------------------------------------------------------------------- 16 // File: log/internal/nullstream.h 17 // ----------------------------------------------------------------------------- 18 // 19 // Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal` 20 // implement a subset of the `LogMessage` API and are used instead when logging 21 // of messages has been disabled. 22 23 #ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_ 24 #define ABSL_LOG_INTERNAL_NULLSTREAM_H_ 25 26 #ifdef _WIN32 27 #include <cstdlib> 28 #else 29 #include <unistd.h> 30 #endif 31 #include <ios> 32 #include <ostream> 33 34 #include "absl/base/attributes.h" 35 #include "absl/base/config.h" 36 #include "absl/base/log_severity.h" 37 #include "absl/strings/string_view.h" 38 39 namespace absl { 40 ABSL_NAMESPACE_BEGIN 41 namespace log_internal { 42 43 // A `NullStream` implements the API of `LogMessage` (a few methods and 44 // `operator<<`) but does nothing. All methods are defined inline so the 45 // compiler can eliminate the whole instance and discard anything that's 46 // streamed in. 47 class NullStream { 48 public: AtLocation(absl::string_view,int)49 NullStream& AtLocation(absl::string_view, int) { return *this; } 50 template <typename SourceLocationType> AtLocation(SourceLocationType)51 NullStream& AtLocation(SourceLocationType) { 52 return *this; 53 } NoPrefix()54 NullStream& NoPrefix() { return *this; } WithVerbosity(int)55 NullStream& WithVerbosity(int) { return *this; } 56 template <typename TimeType> WithTimestamp(TimeType)57 NullStream& WithTimestamp(TimeType) { 58 return *this; 59 } 60 template <typename Tid> WithThreadID(Tid)61 NullStream& WithThreadID(Tid) { 62 return *this; 63 } 64 template <typename LogEntryType> WithMetadataFrom(const LogEntryType &)65 NullStream& WithMetadataFrom(const LogEntryType&) { 66 return *this; 67 } WithPerror()68 NullStream& WithPerror() { return *this; } 69 template <typename LogSinkType> ToSinkAlso(LogSinkType *)70 NullStream& ToSinkAlso(LogSinkType*) { 71 return *this; 72 } 73 template <typename LogSinkType> ToSinkOnly(LogSinkType *)74 NullStream& ToSinkOnly(LogSinkType*) { 75 return *this; 76 } 77 template <typename LogSinkType> OutputToSink(LogSinkType *,bool)78 NullStream& OutputToSink(LogSinkType*, bool) { 79 return *this; 80 } InternalStream()81 NullStream& InternalStream() { return *this; } 82 }; 83 template <typename T> 84 inline NullStream& operator<<(NullStream& str, const T&) { 85 return str; 86 } 87 inline NullStream& operator<<(NullStream& str, 88 std::ostream& (*)(std::ostream& os)) { 89 return str; 90 } 91 inline NullStream& operator<<(NullStream& str, 92 std::ios_base& (*)(std::ios_base& os)) { 93 return str; 94 } 95 96 // `NullStreamMaybeFatal` implements the process termination semantics of 97 // `LogMessage`, which is used for `DFATAL` severity and expression-defined 98 // severity e.g. `LOG(LEVEL(HowBadIsIt()))`. Like `LogMessage`, it terminates 99 // the process when destroyed if the passed-in severity equals `FATAL`. 100 class NullStreamMaybeFatal final : public NullStream { 101 public: NullStreamMaybeFatal(absl::LogSeverity severity)102 explicit NullStreamMaybeFatal(absl::LogSeverity severity) 103 : fatal_(severity == absl::LogSeverity::kFatal) {} ~NullStreamMaybeFatal()104 ~NullStreamMaybeFatal() { 105 if (fatal_) _exit(1); 106 } 107 108 private: 109 bool fatal_; 110 }; 111 112 // `NullStreamFatal` implements the process termination semantics of 113 // `LogMessageFatal`, which means it always terminates the process. `DFATAL` 114 // and expression-defined severity use `NullStreamMaybeFatal` above. 115 class NullStreamFatal final : public NullStream { 116 public: NullStreamFatal()117 NullStreamFatal() {} 118 // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so 119 // disable msvc's warning about the d'tor never returning. 120 #ifdef _MSC_VER 121 #pragma warning(push) 122 #pragma warning(disable : 4722) 123 #endif ~NullStreamFatal()124 ABSL_ATTRIBUTE_NORETURN ~NullStreamFatal() { _exit(1); } 125 #ifdef _MSC_VER 126 #pragma warning(pop) 127 #endif 128 }; 129 130 } // namespace log_internal 131 ABSL_NAMESPACE_END 132 } // namespace absl 133 134 #endif // ABSL_LOG_INTERNAL_GLOBALS_H_ 135