|
30 | 30 |
|
31 | 31 | // Internal Includes |
32 | 32 | #include <osvr/Util/Export.h> |
33 | | -#include <osvr/Util/LineLogger.h> |
34 | 33 | #include <osvr/Util/Log.h> // for LoggerPtr |
35 | 34 | #include <osvr/Util/LogLevel.h> |
36 | 35 |
|
|
39 | 38 |
|
40 | 39 | // Standard includes |
41 | 40 | #include <initializer_list> |
42 | | -#include <memory> // for std::shared_ptr |
43 | | -#include <string> // for std::string |
| 41 | +#include <memory> // for std::shared_ptr |
| 42 | +#include <sstream> // for std::ostringstream |
| 43 | +#include <string> // for std::string |
44 | 44 |
|
45 | 45 | // Forward declarations |
46 | 46 |
|
@@ -120,51 +120,104 @@ namespace util { |
120 | 120 | /// Set the log level at which this logger will trigger a flush. |
121 | 121 | OSVR_UTIL_EXPORT void flushOn(LogLevel level); |
122 | 122 |
|
| 123 | + /// An object returned the logging functions (including operator<<), |
| 124 | + /// serves to accumulate streamed output in a single ostringstream |
| 125 | + /// then write it to the logger at the end of the expression's |
| 126 | + /// lifetime. |
| 127 | + class StreamProxy { |
| 128 | + public: |
| 129 | + StreamProxy(Logger &logger, LogLevel level) |
| 130 | + : logger_(logger), level_(level), |
| 131 | + os_(new std::ostringstream) {} |
| 132 | + |
| 133 | + StreamProxy(Logger &logger, LogLevel level, const char *msg) |
| 134 | + : logger_(logger), level_(level), |
| 135 | + os_(new std::ostringstream) { |
| 136 | + os_->operator<<(msg); |
| 137 | + } |
| 138 | + |
| 139 | + /// destructor appends the finished stringstream at the end |
| 140 | + /// of the expression. |
| 141 | + ~StreamProxy() { |
| 142 | + if (active_ && os_) { |
| 143 | + logger_.write(level_, os_->str().c_str()); |
| 144 | + } |
| 145 | + } |
| 146 | + |
| 147 | + /// move construction |
| 148 | + StreamProxy(StreamProxy &&other) |
| 149 | + : logger_(other.logger_), level_(other.level_), |
| 150 | + os_(std::move(other.os_)), active_(other.active_) { |
| 151 | + other.active_ = false; |
| 152 | + } |
| 153 | + |
| 154 | + StreamProxy(StreamProxy const &) = delete; |
| 155 | + StreamProxy &operator=(StreamProxy const &) = delete; |
| 156 | + |
| 157 | + operator std::ostream &() { return (*os_); } |
| 158 | + |
| 159 | + template <typename T> std::ostream &operator<<(T &&what) { |
| 160 | + (*os_) << std::forward<T>(what); |
| 161 | + return (*os_); |
| 162 | + } |
| 163 | + |
| 164 | + private: |
| 165 | + Logger &logger_; |
| 166 | + LogLevel level_; |
| 167 | + std::unique_ptr<std::ostringstream> os_; |
| 168 | + bool active_ = true; |
| 169 | + }; |
| 170 | + |
123 | 171 | /// @name logger->info(msg) (with optional << "more message") call |
124 | 172 | /// style |
125 | 173 | /// @{ |
126 | | - OSVR_UTIL_EXPORT detail::LineLogger trace(const char *msg); |
127 | | - OSVR_UTIL_EXPORT detail::LineLogger debug(const char *msg); |
128 | | - OSVR_UTIL_EXPORT detail::LineLogger info(const char *msg); |
129 | | - OSVR_UTIL_EXPORT detail::LineLogger notice(const char *msg); |
130 | | - OSVR_UTIL_EXPORT detail::LineLogger warn(const char *msg); |
131 | | - OSVR_UTIL_EXPORT detail::LineLogger error(const char *msg); |
132 | | - OSVR_UTIL_EXPORT detail::LineLogger critical(const char *msg); |
| 174 | + OSVR_UTIL_EXPORT StreamProxy trace(const char *msg); |
| 175 | + OSVR_UTIL_EXPORT StreamProxy debug(const char *msg); |
| 176 | + OSVR_UTIL_EXPORT StreamProxy info(const char *msg); |
| 177 | + OSVR_UTIL_EXPORT StreamProxy notice(const char *msg); |
| 178 | + OSVR_UTIL_EXPORT StreamProxy warn(const char *msg); |
| 179 | + OSVR_UTIL_EXPORT StreamProxy error(const char *msg); |
| 180 | + OSVR_UTIL_EXPORT StreamProxy critical(const char *msg); |
133 | 181 | /// @} |
134 | 182 |
|
135 | 183 | /// @name logger->info() << "msg" call style |
136 | 184 | /// @{ |
137 | | - OSVR_UTIL_EXPORT detail::LineLogger trace(); |
138 | | - OSVR_UTIL_EXPORT detail::LineLogger debug(); |
139 | | - OSVR_UTIL_EXPORT detail::LineLogger info(); |
140 | | - OSVR_UTIL_EXPORT detail::LineLogger notice(); |
141 | | - OSVR_UTIL_EXPORT detail::LineLogger warn(); |
142 | | - OSVR_UTIL_EXPORT detail::LineLogger error(); |
143 | | - OSVR_UTIL_EXPORT detail::LineLogger critical(); |
| 185 | + OSVR_UTIL_EXPORT StreamProxy trace(); |
| 186 | + OSVR_UTIL_EXPORT StreamProxy debug(); |
| 187 | + OSVR_UTIL_EXPORT StreamProxy info(); |
| 188 | + OSVR_UTIL_EXPORT StreamProxy notice(); |
| 189 | + OSVR_UTIL_EXPORT StreamProxy warn(); |
| 190 | + OSVR_UTIL_EXPORT StreamProxy error(); |
| 191 | + OSVR_UTIL_EXPORT StreamProxy critical(); |
144 | 192 | /// @} |
145 | 193 |
|
146 | 194 | /// logger.log(log_level, msg) (with optional << "more message") |
147 | 195 | /// call style |
148 | | - OSVR_UTIL_EXPORT detail::LineLogger log(LogLevel level, |
149 | | - const char *msg); |
| 196 | + OSVR_UTIL_EXPORT StreamProxy log(LogLevel level, const char *msg); |
150 | 197 |
|
151 | 198 | /// logger.log(log_level) << "msg" call style |
152 | | - OSVR_UTIL_EXPORT detail::LineLogger log(LogLevel level); |
| 199 | + OSVR_UTIL_EXPORT StreamProxy log(LogLevel level); |
153 | 200 |
|
154 | 201 | /// Make sure this logger has written out its data. |
155 | 202 | OSVR_UTIL_EXPORT void flush(); |
156 | 203 |
|
157 | 204 | /// Get the logger name |
158 | | - std::string const &getName() const { return name_; } |
| 205 | + OSVR_UTIL_EXPORT std::string const &getName() const { |
| 206 | + return name_; |
| 207 | + } |
159 | 208 |
|
160 | 209 | private: |
161 | 210 | static LoggerPtr |
162 | 211 | makeLogger(std::string const &name, |
163 | 212 | std::shared_ptr<spdlog::logger> const &logger); |
| 213 | + |
164 | 214 | /// In case a spdlog logger is not available, this will create a |
165 | 215 | /// fallback logger instance using just ostream. |
166 | 216 | static LoggerPtr makeFallback(std::string const &name); |
167 | 217 |
|
| 218 | + /// Pass the constructed message along to the underlying logger. |
| 219 | + OSVR_UTIL_EXPORT void write(LogLevel level, const char* msg); |
| 220 | + |
168 | 221 | const std::string name_; |
169 | 222 | std::shared_ptr<spdlog::logger> logger_; |
170 | 223 | }; |
|
0 commit comments