summaryrefslogtreecommitdiff
path: root/absl/log/internal/log_message.h
diff options
context:
space:
mode:
Diffstat (limited to 'absl/log/internal/log_message.h')
-rw-r--r--absl/log/internal/log_message.h48
1 files changed, 45 insertions, 3 deletions
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h
index 37a267c0..992bb630 100644
--- a/absl/log/internal/log_message.h
+++ b/absl/log/internal/log_message.h
@@ -41,6 +41,7 @@
#include "absl/log/internal/nullguard.h"
#include "absl/log/log_entry.h"
#include "absl/log/log_sink.h"
+#include "absl/strings/internal/has_absl_stringify.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
@@ -153,8 +154,17 @@ class LogMessage {
template <int SIZE>
LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
- // Default: uses `ostream` logging to convert `v` to a string.
- template <typename T>
+ // Types that support `AbslStringify()` are serialized that way.
+ template <typename T,
+ typename std::enable_if<
+ strings_internal::HasAbslStringify<T>::value, int>::type = 0>
+ LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Types that don't support `AbslStringify()` but do support streaming into a
+ // `std::ostream&` are serialized that way.
+ template <typename T,
+ typename std::enable_if<
+ !strings_internal::HasAbslStringify<T>::value, int>::type = 0>
LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
// Note: We explicitly do not support `operator<<` for non-const references
@@ -205,12 +215,44 @@ class LogMessage {
std::ostream stream_;
};
+// Helper class so that `AbslStringify()` can modify the LogMessage.
+class StringifySink final {
+ public:
+ explicit StringifySink(LogMessage& message) : message_(message) {}
+
+ void Append(size_t count, char ch) { message_ << std::string(count, ch); }
+
+ void Append(absl::string_view v) { message_ << v; }
+
+ // For types that implement `AbslStringify` using `absl::Format()`.
+ friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
+ sink->Append(v);
+ }
+
+ private:
+ LogMessage& message_;
+};
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <typename T,
+ typename std::enable_if<strings_internal::HasAbslStringify<T>::value,
+ int>::type>
+LogMessage& LogMessage::operator<<(const T& v) {
+ StringifySink sink(*this);
+ // Replace with public API.
+ AbslStringify(sink, v);
+ return *this;
+}
+
// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
-template <typename T>
+template <typename T,
+ typename std::enable_if<!strings_internal::HasAbslStringify<T>::value,
+ int>::type>
LogMessage& LogMessage::operator<<(const T& v) {
stream_ << log_internal::NullGuard<T>().Guard(v);
return *this;
}
+
inline LogMessage& LogMessage::operator<<(
std::ostream& (*m)(std::ostream& os)) {
stream_ << m;