xref: /aosp_15_r20/external/webrtc/third_party/abseil-cpp/absl/log/log_streamer.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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/log_streamer.h
17 // -----------------------------------------------------------------------------
18 //
19 // This header declares the class `LogStreamer` and convenience functions to
20 // construct LogStreamer objects with different associated log severity levels.
21 
22 #ifndef ABSL_LOG_LOG_STREAMER_H_
23 #define ABSL_LOG_LOG_STREAMER_H_
24 
25 #include <ios>
26 #include <memory>
27 #include <ostream>
28 #include <string>
29 #include <utility>
30 
31 #include "absl/base/config.h"
32 #include "absl/base/log_severity.h"
33 #include "absl/log/log.h"
34 #include "absl/strings/internal/ostringstream.h"
35 #include "absl/strings/string_view.h"
36 #include "absl/types/optional.h"
37 #include "absl/utility/utility.h"
38 
39 namespace absl {
40 ABSL_NAMESPACE_BEGIN
41 
42 // LogStreamer
43 //
44 // Although you can stream into `LOG(INFO)`, you can't pass it into a function
45 // that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
46 // `std::ostream` that buffers everything that's streamed in.  The buffer's
47 // contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
48 // If nothing is streamed in, an empty message is logged.  If the specified
49 // severity is `absl::LogSeverity::kFatal`, the program will be terminated when
50 // the `LogStreamer` is destroyed regardless of whether any data were streamed
51 // in.
52 //
53 // Factory functions corresponding to the `absl::LogSeverity` enumerators
54 // are provided for convenience; if the desired severity is variable, invoke the
55 // constructor directly.
56 //
57 // LogStreamer is movable, but not copyable.
58 //
59 // Examples:
60 //
61 //   ShaveYakAndWriteToStream(
62 //       yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());
63 //
64 //   {
65 //     // This logs a single line containing data streamed by all three function
66 //     // calls.
67 //     absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);
68 //     ShaveYakAndWriteToStream(yak1, streamer.stream());
69 //     streamer.stream() << " ";
70 //     ShaveYakAndWriteToStream(yak2, streamer.stream());
71 //     streamer.stream() << " ";
72 //     ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
73 //   }
74 class LogStreamer final {
75  public:
76   // LogStreamer::LogStreamer()
77   //
78   // Creates a LogStreamer with a given `severity` that will log a message
79   // attributed to the given `file` and `line`.
LogStreamer(absl::LogSeverity severity,absl::string_view file,int line)80   explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,
81                        int line)
82       : severity_(severity),
83         line_(line),
84         file_(file),
85         stream_(absl::in_place, &buf_) {
86     // To match `LOG`'s defaults:
87     stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
88   }
89 
90   // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
91   // and a program that streams into one has undefined behavior.
LogStreamer(LogStreamer && that)92   LogStreamer(LogStreamer&& that) noexcept
93       : severity_(that.severity_),
94         line_(that.line_),
95         file_(std::move(that.file_)),
96         buf_(std::move(that.buf_)),
97         stream_(std::move(that.stream_)) {
98     if (stream_.has_value()) stream_->str(&buf_);
99     that.stream_.reset();
100   }
101   LogStreamer& operator=(LogStreamer&& that) {
102     LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
103     severity_ = that.severity_;
104     file_ = std::move(that.file_);
105     line_ = that.line_;
106     buf_ = std::move(that.buf_);
107     stream_ = std::move(that.stream_);
108     if (stream_.has_value()) stream_->str(&buf_);
109     that.stream_.reset();
110     return *this;
111   }
112 
113   // LogStreamer::~LogStreamer()
114   //
115   // Logs this LogStreamer's buffered content as if by LOG.
~LogStreamer()116   ~LogStreamer() {
117     LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)
118         << buf_;
119   }
120 
121   // LogStreamer::stream()
122   //
123   // Returns the `std::ostream` to use to write into this LogStreamer' internal
124   // buffer.
stream()125   std::ostream& stream() { return *stream_; }
126 
127  private:
128   absl::LogSeverity severity_;
129   int line_;
130   std::string file_;
131   std::string buf_;
132   // A disengaged `stream_` indicates a moved-from `LogStreamer` that should not
133   // `LOG` upon destruction.
134   absl::optional<absl::strings_internal::OStringStream> stream_;
135 };
136 
137 // LogInfoStreamer()
138 //
139 // Returns a LogStreamer that writes at level LogSeverity::kInfo.
LogInfoStreamer(absl::string_view file,int line)140 inline LogStreamer LogInfoStreamer(absl::string_view file, int line) {
141   return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);
142 }
143 
144 // LogWarningStreamer()
145 //
146 // Returns a LogStreamer that writes at level LogSeverity::kWarning.
LogWarningStreamer(absl::string_view file,int line)147 inline LogStreamer LogWarningStreamer(absl::string_view file, int line) {
148   return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);
149 }
150 
151 // LogErrorStreamer()
152 //
153 // Returns a LogStreamer that writes at level LogSeverity::kError.
LogErrorStreamer(absl::string_view file,int line)154 inline LogStreamer LogErrorStreamer(absl::string_view file, int line) {
155   return absl::LogStreamer(absl::LogSeverity::kError, file, line);
156 }
157 
158 // LogFatalStreamer()
159 //
160 // Returns a LogStreamer that writes at level LogSeverity::kFatal.
161 //
162 // The program will be terminated when this `LogStreamer` is destroyed,
163 // regardless of whether any data were streamed in.
LogFatalStreamer(absl::string_view file,int line)164 inline LogStreamer LogFatalStreamer(absl::string_view file, int line) {
165   return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);
166 }
167 
168 ABSL_NAMESPACE_END
169 }  // namespace absl
170 
171 #endif  // ABSL_LOG_LOG_STREAMER_H_
172