summaryrefslogtreecommitdiff
path: root/abseil-cpp/absl/log/internal
diff options
context:
space:
mode:
Diffstat (limited to 'abseil-cpp/absl/log/internal')
-rw-r--r--abseil-cpp/absl/log/internal/BUILD.bazel383
-rw-r--r--abseil-cpp/absl/log/internal/append_truncated.h47
-rw-r--r--abseil-cpp/absl/log/internal/check_impl.h150
-rw-r--r--abseil-cpp/absl/log/internal/check_op.cc118
-rw-r--r--abseil-cpp/absl/log/internal/check_op.h394
-rw-r--r--abseil-cpp/absl/log/internal/conditions.cc83
-rw-r--r--abseil-cpp/absl/log/internal/conditions.h228
-rw-r--r--abseil-cpp/absl/log/internal/config.h45
-rw-r--r--abseil-cpp/absl/log/internal/flags.h53
-rw-r--r--abseil-cpp/absl/log/internal/globals.cc145
-rw-r--r--abseil-cpp/absl/log/internal/globals.h101
-rw-r--r--abseil-cpp/absl/log/internal/log_format.cc205
-rw-r--r--abseil-cpp/absl/log/internal/log_format.h78
-rw-r--r--abseil-cpp/absl/log/internal/log_impl.h216
-rw-r--r--abseil-cpp/absl/log/internal/log_message.cc633
-rw-r--r--abseil-cpp/absl/log/internal/log_message.h377
-rw-r--r--abseil-cpp/absl/log/internal/log_sink_set.cc296
-rw-r--r--abseil-cpp/absl/log/internal/log_sink_set.h54
-rw-r--r--abseil-cpp/absl/log/internal/nullguard.cc35
-rw-r--r--abseil-cpp/absl/log/internal/nullguard.h88
-rw-r--r--abseil-cpp/absl/log/internal/nullstream.h136
-rw-r--r--abseil-cpp/absl/log/internal/proto.cc220
-rw-r--r--abseil-cpp/absl/log/internal/proto.h288
-rw-r--r--abseil-cpp/absl/log/internal/stderr_log_sink_test.cc105
-rw-r--r--abseil-cpp/absl/log/internal/strip.h71
-rw-r--r--abseil-cpp/absl/log/internal/structured.h58
-rw-r--r--abseil-cpp/absl/log/internal/test_actions.cc75
-rw-r--r--abseil-cpp/absl/log/internal/test_actions.h90
-rw-r--r--abseil-cpp/absl/log/internal/test_helpers.cc82
-rw-r--r--abseil-cpp/absl/log/internal/test_helpers.h71
-rw-r--r--abseil-cpp/absl/log/internal/test_matchers.cc217
-rw-r--r--abseil-cpp/absl/log/internal/test_matchers.h94
-rw-r--r--abseil-cpp/absl/log/internal/voidify.h44
33 files changed, 5280 insertions, 0 deletions
diff --git a/abseil-cpp/absl/log/internal/BUILD.bazel b/abseil-cpp/absl/log/internal/BUILD.bazel
new file mode 100644
index 0000000..555c5e5
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/BUILD.bazel
@@ -0,0 +1,383 @@
+#
+# Copyright 2022 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = [
+ "//absl/log:__pkg__",
+])
+
+licenses(["notice"])
+
+cc_library(
+ name = "check_impl",
+ hdrs = ["check_impl.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":check_op",
+ ":conditions",
+ ":log_message",
+ ":strip",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_library(
+ name = "check_op",
+ srcs = ["check_op.cc"],
+ hdrs = ["check_op.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/log:__pkg__",
+ ],
+ deps = [
+ ":nullguard",
+ ":nullstream",
+ ":strip",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "conditions",
+ srcs = ["conditions.cc"],
+ hdrs = ["conditions.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":voidify",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_library(
+ name = "config",
+ hdrs = ["config.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/log:__pkg__",
+ ],
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_library(
+ name = "flags",
+ hdrs = ["flags.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/flags:flag",
+ ],
+)
+
+cc_library(
+ name = "format",
+ srcs = ["log_format.cc"],
+ hdrs = ["log_format.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":append_truncated",
+ ":config",
+ ":globals",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "//absl/time",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "globals",
+ srcs = ["globals.cc"],
+ hdrs = ["globals.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/log:__pkg__",
+ ],
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ "//absl/time",
+ ],
+)
+
+cc_library(
+ name = "log_impl",
+ hdrs = ["log_impl.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":conditions",
+ ":log_message",
+ ":strip",
+ ],
+)
+
+cc_library(
+ name = "log_message",
+ srcs = ["log_message.cc"],
+ hdrs = ["log_message.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/log:__pkg__",
+ ],
+ deps = [
+ ":append_truncated",
+ ":format",
+ ":globals",
+ ":log_sink_set",
+ ":nullguard",
+ ":proto",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:errno_saver",
+ "//absl/base:log_severity",
+ "//absl/base:raw_logging_internal",
+ "//absl/base:strerror",
+ "//absl/container:inlined_vector",
+ "//absl/debugging:examine_stack",
+ "//absl/log:globals",
+ "//absl/log:log_entry",
+ "//absl/log:log_sink",
+ "//absl/log:log_sink_registry",
+ "//absl/memory",
+ "//absl/strings",
+ "//absl/time",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "append_truncated",
+ hdrs = ["append_truncated.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/strings",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "log_sink_set",
+ srcs = ["log_sink_set.cc"],
+ hdrs = ["log_sink_set.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS + select({
+ "//conditions:default": [],
+ "@platforms//os:android": ["-llog"],
+ }),
+ deps = [
+ ":config",
+ ":globals",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/base:raw_logging_internal",
+ "//absl/cleanup",
+ "//absl/log:globals",
+ "//absl/log:log_entry",
+ "//absl/log:log_sink",
+ "//absl/strings",
+ "//absl/synchronization",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "nullguard",
+ srcs = ["nullguard.cc"],
+ hdrs = ["nullguard.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_library(
+ name = "nullstream",
+ hdrs = ["nullstream.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "strip",
+ hdrs = ["strip.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":log_message",
+ ":nullstream",
+ "//absl/base:log_severity",
+ ],
+)
+
+cc_library(
+ name = "structured",
+ hdrs = ["structured.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":log_message",
+ "//absl/base:config",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "test_actions",
+ testonly = True,
+ srcs = ["test_actions.cc"],
+ hdrs = ["test_actions.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/log:log_entry",
+ "//absl/strings",
+ "//absl/time",
+ ] + select({
+ "//absl:msvc_compiler": [],
+ "//conditions:default": [
+ ],
+ }),
+)
+
+cc_library(
+ name = "test_helpers",
+ testonly = True,
+ srcs = ["test_helpers.cc"],
+ hdrs = ["test_helpers.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":globals",
+ "//absl/base:config",
+ "//absl/base:log_severity",
+ "//absl/log:globals",
+ "//absl/log:initialize",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_library(
+ name = "test_matchers",
+ testonly = True,
+ srcs = ["test_matchers.cc"],
+ hdrs = ["test_matchers.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":test_helpers",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/log:log_entry",
+ "//absl/strings",
+ "//absl/time",
+ "@com_google_googletest//:gtest",
+ ] + select({
+ "//absl:msvc_compiler": [],
+ "//conditions:default": [
+ ],
+ }),
+)
+
+cc_library(
+ name = "voidify",
+ hdrs = ["voidify.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "proto",
+ srcs = ["proto.cc"],
+ hdrs = ["proto.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ "//absl/types:span",
+ ],
+)
+
+# Test targets
+cc_test(
+ name = "stderr_log_sink_test",
+ size = "small",
+ srcs = ["stderr_log_sink_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "no_test:os:android",
+ "no_test:os:ios",
+ "no_test_android",
+ "no_test_darwin_x86_64",
+ "no_test_ios",
+ "no_test_wasm",
+ ],
+ deps = [
+ ":test_helpers",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/log",
+ "//absl/log:globals",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/abseil-cpp/absl/log/internal/append_truncated.h b/abseil-cpp/absl/log/internal/append_truncated.h
new file mode 100644
index 0000000..f0e7912
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/append_truncated.h
@@ -0,0 +1,47 @@
+// Copyright 2022 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
+#define ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
+
+#include <cstddef>
+#include <cstring>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+// Copies into `dst` as many bytes of `src` as will fit, then truncates the
+// copied bytes from the front of `dst` and returns the number of bytes written.
+inline size_t AppendTruncated(absl::string_view src, absl::Span<char> &dst) {
+ if (src.size() > dst.size()) src = src.substr(0, dst.size());
+ memcpy(dst.data(), src.data(), src.size());
+ dst.remove_prefix(src.size());
+ return src.size();
+}
+// Likewise, but `n` copies of `c`.
+inline size_t AppendTruncated(char c, size_t n, absl::Span<char> &dst) {
+ if (n > dst.size()) n = dst.size();
+ memset(dst.data(), c, n);
+ dst.remove_prefix(n);
+ return n;
+}
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
diff --git a/abseil-cpp/absl/log/internal/check_impl.h b/abseil-cpp/absl/log/internal/check_impl.h
new file mode 100644
index 0000000..00f25f8
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/check_impl.h
@@ -0,0 +1,150 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_LOG_INTERNAL_CHECK_IMPL_H_
+#define ABSL_LOG_INTERNAL_CHECK_IMPL_H_
+
+#include "absl/base/optimization.h"
+#include "absl/log/internal/check_op.h"
+#include "absl/log/internal/conditions.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/strip.h"
+
+// CHECK
+#define ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text) \
+ ABSL_LOG_INTERNAL_CONDITION_FATAL(STATELESS, \
+ ABSL_PREDICT_FALSE(!(condition))) \
+ ABSL_LOG_INTERNAL_CHECK(condition_text).InternalStream()
+
+#define ABSL_LOG_INTERNAL_QCHECK_IMPL(condition, condition_text) \
+ ABSL_LOG_INTERNAL_CONDITION_QFATAL(STATELESS, \
+ ABSL_PREDICT_FALSE(!(condition))) \
+ ABSL_LOG_INTERNAL_QCHECK(condition_text).InternalStream()
+
+#define ABSL_LOG_INTERNAL_PCHECK_IMPL(condition, condition_text) \
+ ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text).WithPerror()
+
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \
+ ABSL_LOG_INTERNAL_CHECK_IMPL(condition, condition_text)
+#else
+#define ABSL_LOG_INTERNAL_DCHECK_IMPL(condition, condition_text) \
+ ABSL_LOG_INTERNAL_CHECK_IMPL(true || (condition), "true")
+#endif
+
+// CHECK_EQ
+#define ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_EQ, ==, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_NE, !=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_LE, <=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_LT, <, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_GE, >=, val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OP(Check_GT, >, val1, val1_text, val2, val2_text)
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_EQ_IMPL(val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_NE_IMPL(val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_LE_IMPL(val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_LT_IMPL(val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_GE_IMPL(val1, val1_text, val2, val2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_CHECK_GT_IMPL(val1, val1_text, val2, val2_text)
+#else // ndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define ABSL_LOG_INTERNAL_DCHECK_NE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define ABSL_LOG_INTERNAL_DCHECK_LE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define ABSL_LOG_INTERNAL_DCHECK_LT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define ABSL_LOG_INTERNAL_DCHECK_GE_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#define ABSL_LOG_INTERNAL_DCHECK_GT_IMPL(val1, val1_text, val2, val2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(val1, val2)
+#endif // def NDEBUG
+
+// CHECK_OK
+#define ABSL_LOG_INTERNAL_CHECK_OK_IMPL(status, status_text) \
+ ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)
+#define ABSL_LOG_INTERNAL_QCHECK_OK_IMPL(status, status_text) \
+ ABSL_LOG_INTERNAL_QCHECK_OK(status, status_text)
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \
+ ABSL_LOG_INTERNAL_CHECK_OK(status, status_text)
+#else
+#define ABSL_LOG_INTERNAL_DCHECK_OK_IMPL(status, status_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(status, nullptr)
+#endif
+
+// CHECK_STREQ
+#define ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, ==, true, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_STROP(strcmp, !=, false, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, ==, true, s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_QCHECK_STROP(strcasecmp, !=, false, s1, s1_text, s2, \
+ s2_text)
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL(s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL(s1, s1_text, s2, s2_text)
+#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text)
+#else // ndef NDEBUG
+#define ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#define ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL(s1, s1_text, s2, s2_text) \
+ ABSL_LOG_INTERNAL_DCHECK_NOP(s1, s2)
+#endif // def NDEBUG
+
+#endif // ABSL_LOG_INTERNAL_CHECK_IMPL_H_
diff --git a/abseil-cpp/absl/log/internal/check_op.cc b/abseil-cpp/absl/log/internal/check_op.cc
new file mode 100644
index 0000000..f4b6764
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/check_op.cc
@@ -0,0 +1,118 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/check_op.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#define strcasecmp _stricmp
+#else
+#include <strings.h> // for strcasecmp, but msvc does not have this header
+#endif
+
+#include <sstream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#define ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \
+ template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);
+#undef ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING
+
+CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) {
+ stream_ << exprtext << " (";
+}
+
+std::ostream& CheckOpMessageBuilder::ForVar2() {
+ stream_ << " vs. ";
+ return stream_;
+}
+
+std::string* CheckOpMessageBuilder::NewString() {
+ stream_ << ")";
+ return new std::string(stream_.str());
+}
+
+void MakeCheckOpValueString(std::ostream& os, const char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const signed char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "signed char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const unsigned char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "unsigned char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const void* p) {
+ if (p == nullptr) {
+ os << "(null)";
+ } else {
+ os << p;
+ }
+}
+
+// Helper functions for string comparisons.
+#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
+ std::string* Check##func##expected##Impl(const char* s1, const char* s2, \
+ const char* exprtext) { \
+ bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
+ if (equal == expected) { \
+ return nullptr; \
+ } else { \
+ return new std::string( \
+ absl::StrCat(exprtext, " (", s1, " vs. ", s2, ")")); \
+ } \
+ }
+DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
+#undef DEFINE_CHECK_STROP_IMPL
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/check_op.h b/abseil-cpp/absl/log/internal/check_op.h
new file mode 100644
index 0000000..20b01b5
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/check_op.h
@@ -0,0 +1,394 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/check_op.h
+// -----------------------------------------------------------------------------
+//
+// This file declares helpers routines and macros used to implement `CHECK`
+// macros.
+
+#ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_
+#define ABSL_LOG_INTERNAL_CHECK_OP_H_
+
+#include <stdint.h>
+
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/nullguard.h"
+#include "absl/log/internal/nullstream.h"
+#include "absl/log/internal/strip.h"
+
+// `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
+// should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) \
+ (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? (literal) \
+ : "")
+#else
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
+#endif
+
+#ifdef NDEBUG
+// `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing. However, we
+// still want the compiler to parse `x` and `y`, because we don't want to lose
+// potentially useful errors and warnings.
+#define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y) \
+ while (false && ((void)(x), (void)(y), 0)) \
+ ::absl::log_internal::NullStream().InternalStream()
+#endif
+
+#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \
+ while ( \
+ ::std::string* absl_log_internal_check_op_result ABSL_ATTRIBUTE_UNUSED = \
+ ::absl::log_internal::name##Impl( \
+ ::absl::log_internal::GetReferenceableValue(val1), \
+ ::absl::log_internal::GetReferenceableValue(val2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text \
+ " " #op " " val2_text))) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \
+ val2_text) \
+ while (::std::string* absl_log_internal_qcheck_op_result = \
+ ::absl::log_internal::name##Impl( \
+ ::absl::log_internal::GetReferenceableValue(val1), \
+ ::absl::log_internal::GetReferenceableValue(val2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \
+ val1_text " " #op " " val2_text))) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2, \
+ s2_text) \
+ while (::std::string* absl_log_internal_check_strop_result = \
+ ::absl::log_internal::Check##func##expected##Impl( \
+ (s1), (s2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
+ " " s2_text))) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result) \
+ .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2, \
+ s2_text) \
+ while (::std::string* absl_log_internal_qcheck_strop_result = \
+ ::absl::log_internal::Check##func##expected##Impl( \
+ (s1), (s2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
+ " " s2_text))) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result) \
+ .InternalStream()
+// This one is tricky:
+// * We must evaluate `val` exactly once, yet we need to do two things with it:
+// evaluate `.ok()` and (sometimes) `.ToString()`.
+// * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.
+// * `val` might be e.g. `ATemporary().GetStatus()`, which may return a
+// reference to a member of `ATemporary` that is only valid until the end of
+// the full expression.
+// * We don't want this file to depend on `absl::Status` `#include`s or linkage,
+// nor do we want to move the definition to status and introduce a dependency
+// in the other direction. We can be assured that callers must already have a
+// `Status` and the necessary `#include`s and linkage.
+// * Callsites should be small and fast (at least when `val.ok()`): one branch,
+// minimal stack footprint.
+// * In particular, the string concat stuff should be out-of-line and emitted
+// in only one TU to save linker input size
+// * We want the `val.ok()` check inline so static analyzers and optimizers can
+// see it.
+// * As usual, no braces so we can stream into the expansion with `operator<<`.
+// * Also as usual, it must expand to a single (partial) statement with no
+// ambiguous-else problems.
+#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text) \
+ for (::std::pair<const ::absl::Status*, ::std::string*> \
+ absl_log_internal_check_ok_goo; \
+ absl_log_internal_check_ok_goo.first = \
+ ::absl::log_internal::AsStatus(val), \
+ absl_log_internal_check_ok_goo.second = \
+ ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
+ ? nullptr \
+ : ::absl::status_internal::MakeCheckFailString( \
+ absl_log_internal_check_ok_goo.first, \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
+ " is OK")), \
+ !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second) \
+ .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text) \
+ for (::std::pair<const ::absl::Status*, ::std::string*> \
+ absl_log_internal_check_ok_goo; \
+ absl_log_internal_check_ok_goo.first = \
+ ::absl::log_internal::AsStatus(val), \
+ absl_log_internal_check_ok_goo.second = \
+ ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
+ ? nullptr \
+ : ::absl::status_internal::MakeCheckFailString( \
+ absl_log_internal_check_ok_goo.first, \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
+ " is OK")), \
+ !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_check_ok_goo.second) \
+ .InternalStream()
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class Status;
+template <typename T>
+class StatusOr;
+
+namespace status_internal {
+std::string* MakeCheckFailString(const absl::Status* status,
+ const char* prefix);
+} // namespace status_internal
+
+namespace log_internal {
+
+// Convert a Status or a StatusOr to its underlying status value.
+//
+// (This implementation does not require a dep on absl::Status to work.)
+inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
+template <typename T>
+const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
+ return &s.status();
+}
+
+// A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
+// See `MakeCheckOpString` for sample usage.
+class CheckOpMessageBuilder final {
+ public:
+ // Inserts `exprtext` and ` (` to the stream.
+ explicit CheckOpMessageBuilder(const char* exprtext);
+ ~CheckOpMessageBuilder() = default;
+ // For inserting the first variable.
+ std::ostream& ForVar1() { return stream_; }
+ // For inserting the second variable (adds an intermediate ` vs. `).
+ std::ostream& ForVar2();
+ // Get the result (inserts the closing `)`).
+ std::string* NewString();
+
+ private:
+ std::ostringstream stream_;
+};
+
+// This formats a value for a failing `CHECK_XX` statement. Ordinarily, it uses
+// the definition for `operator<<`, with a few special cases below.
+template <typename T>
+inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
+ os << log_internal::NullGuard<T>::Guard(v);
+}
+
+// Overloads for char types provide readable values for unprintable characters.
+void MakeCheckOpValueString(std::ostream& os, char v);
+void MakeCheckOpValueString(std::ostream& os, signed char v);
+void MakeCheckOpValueString(std::ostream& os, unsigned char v);
+void MakeCheckOpValueString(std::ostream& os, const void* p);
+
+namespace detect_specialization {
+
+// MakeCheckOpString is being specialized for every T and U pair that is being
+// passed to the CHECK_op macros. However, there is a lot of redundancy in these
+// specializations that creates unnecessary library and binary bloat.
+// The number of instantiations tends to be O(n^2) because we have two
+// independent inputs. This technique works by reducing `n`.
+//
+// Most user-defined types being passed to CHECK_op end up being printed as a
+// builtin type. For example, enums tend to be implicitly converted to its
+// underlying type when calling operator<<, and pointers are printed with the
+// `const void*` overload.
+// To reduce the number of instantiations we coerce these values before calling
+// MakeCheckOpString instead of inside it.
+//
+// To detect if this coercion is needed, we duplicate all the relevant
+// operator<< overloads as specified in the standard, just in a different
+// namespace. If the call to `stream << value` becomes ambiguous, it means that
+// one of these overloads is the one selected by overload resolution. We then
+// do overload resolution again just with our overload set to see which one gets
+// selected. That tells us which type to coerce to.
+// If the augmented call was not ambiguous, it means that none of these were
+// selected and we can't coerce the input.
+//
+// As a secondary step to reduce code duplication, we promote integral types to
+// their 64-bit variant. This does not change the printed value, but reduces the
+// number of instantiations even further. Promoting an integer is very cheap at
+// the call site.
+int64_t operator<<(std::ostream&, short value); // NOLINT
+int64_t operator<<(std::ostream&, unsigned short value); // NOLINT
+int64_t operator<<(std::ostream&, int value);
+int64_t operator<<(std::ostream&, unsigned int value);
+int64_t operator<<(std::ostream&, long value); // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long value); // NOLINT
+int64_t operator<<(std::ostream&, long long value); // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long long value); // NOLINT
+float operator<<(std::ostream&, float value);
+double operator<<(std::ostream&, double value);
+long double operator<<(std::ostream&, long double value);
+bool operator<<(std::ostream&, bool value);
+const void* operator<<(std::ostream&, const void* value);
+const void* operator<<(std::ostream&, std::nullptr_t);
+
+// These `char` overloads are specified like this in the standard, so we have to
+// write them exactly the same to ensure the call is ambiguous.
+// If we wrote it in a different way (eg taking std::ostream instead of the
+// template) then one call might have a higher rank than the other and it would
+// not be ambiguous.
+template <typename Traits>
+char operator<<(std::basic_ostream<char, Traits>&, char);
+template <typename Traits>
+signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
+template <typename Traits>
+unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
+template <typename Traits>
+const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
+template <typename Traits>
+const signed char* operator<<(std::basic_ostream<char, Traits>&,
+ const signed char*);
+template <typename Traits>
+const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
+ const unsigned char*);
+
+// This overload triggers when the call is not ambiguous.
+// It means that T is being printed with some overload not on this list.
+// We keep the value as `const T&`.
+template <typename T, typename = decltype(std::declval<std::ostream&>()
+ << std::declval<const T&>())>
+const T& Detect(int);
+
+// This overload triggers when the call is ambiguous.
+// It means that T is either one from this list or printed as one from this
+// list. Eg an enum that decays to `int` for printing.
+// We ask the overload set to give us the type we want to convert it to.
+template <typename T>
+decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
+ std::declval<const T&>()))
+Detect(char);
+
+} // namespace detect_specialization
+
+template <typename T>
+using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
+
+// Build the error message string. Specify no inlining for code size.
+template <typename T1, typename T2>
+ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString(
+ T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE;
+
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) {
+ CheckOpMessageBuilder comb(exprtext);
+ MakeCheckOpValueString(comb.ForVar1(), v1);
+ MakeCheckOpValueString(comb.ForVar2(), v2);
+ return comb.NewString();
+}
+
+// Add a few commonly used instantiations as extern to reduce size of objects
+// files.
+#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
+ extern template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
+#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
+
+// Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family. The
+// `(int, int)` override works around the issue that the compiler will not
+// instantiate the template version of the function on values of unnamed enum
+// type.
+#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op) \
+ template <typename T1, typename T2> \
+ inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2, \
+ const char* exprtext) { \
+ using U1 = CheckOpStreamType<T1>; \
+ using U2 = CheckOpStreamType<T2>; \
+ return ABSL_PREDICT_TRUE(v1 op v2) \
+ ? nullptr \
+ : MakeCheckOpString<U1, U2>(v1, v2, exprtext); \
+ } \
+ inline constexpr ::std::string* name##Impl(int v1, int v2, \
+ const char* exprtext) { \
+ return name##Impl<int, int>(v1, v2, exprtext); \
+ }
+
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
+#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
+
+std::string* CheckstrcmptrueImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2,
+ const char* exprtext);
+
+// `CHECK_EQ` and friends want to pass their arguments by reference, however
+// this winds up exposing lots of cases where people have defined and
+// initialized static const data members but never declared them (i.e. in a .cc
+// file), meaning they are not referenceable. This function avoids that problem
+// for integers (the most common cases) by overloading for every primitive
+// integer type, even the ones we discourage, and returning them by value.
+template <typename T>
+inline constexpr const T& GetReferenceableValue(const T& t) {
+ return t;
+}
+inline constexpr char GetReferenceableValue(char t) { return t; }
+inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
+ return t;
+}
+inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
+inline constexpr short GetReferenceableValue(short t) { return t; } // NOLINT
+inline constexpr unsigned short GetReferenceableValue( // NOLINT
+ unsigned short t) { // NOLINT
+ return t;
+}
+inline constexpr int GetReferenceableValue(int t) { return t; }
+inline constexpr unsigned int GetReferenceableValue(unsigned int t) {
+ return t;
+}
+inline constexpr long GetReferenceableValue(long t) { return t; } // NOLINT
+inline constexpr unsigned long GetReferenceableValue( // NOLINT
+ unsigned long t) { // NOLINT
+ return t;
+}
+inline constexpr long long GetReferenceableValue(long long t) { // NOLINT
+ return t;
+}
+inline constexpr unsigned long long GetReferenceableValue( // NOLINT
+ unsigned long long t) { // NOLINT
+ return t;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CHECK_OP_H_
diff --git a/abseil-cpp/absl/log/internal/conditions.cc b/abseil-cpp/absl/log/internal/conditions.cc
new file mode 100644
index 0000000..a9f4966
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/conditions.cc
@@ -0,0 +1,83 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/conditions.h"
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/cycleclock.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// The following code behaves like AtomicStatsCounter::LossyAdd() for
+// speed since it is fine to lose occasional updates.
+// Returns old value of *counter.
+uint32_t LossyIncrement(std::atomic<uint32_t>* counter) {
+ const uint32_t value = counter->load(std::memory_order_relaxed);
+ counter->store(value + 1, std::memory_order_relaxed);
+ return value;
+}
+
+} // namespace
+
+bool LogEveryNState::ShouldLog(int n) {
+ return n > 0 && (LossyIncrement(&counter_) % static_cast<uint32_t>(n)) == 0;
+}
+
+bool LogFirstNState::ShouldLog(int n) {
+ const uint32_t counter_value = counter_.load(std::memory_order_relaxed);
+ if (static_cast<int64_t>(counter_value) < n) {
+ counter_.store(counter_value + 1, std::memory_order_relaxed);
+ return true;
+ }
+ return false;
+}
+
+bool LogEveryPow2State::ShouldLog() {
+ const uint32_t new_value = LossyIncrement(&counter_) + 1;
+ return (new_value & (new_value - 1)) == 0;
+}
+
+bool LogEveryNSecState::ShouldLog(double seconds) {
+ using absl::base_internal::CycleClock;
+ LossyIncrement(&counter_);
+ const int64_t now_cycles = CycleClock::Now();
+ int64_t next_cycles = next_log_time_cycles_.load(std::memory_order_relaxed);
+#if defined(__myriad2__)
+ // myriad2 does not have 8-byte compare and exchange. Use a racy version that
+ // is "good enough" but will over-log in the face of concurrent logging.
+ if (now_cycles > next_cycles) {
+ next_log_time_cycles_.store(now_cycles + seconds * CycleClock::Frequency(),
+ std::memory_order_relaxed);
+ return true;
+ }
+ return false;
+#else
+ do {
+ if (now_cycles <= next_cycles) return false;
+ } while (!next_log_time_cycles_.compare_exchange_weak(
+ next_cycles, now_cycles + seconds * CycleClock::Frequency(),
+ std::memory_order_relaxed, std::memory_order_relaxed));
+ return true;
+#endif
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/conditions.h b/abseil-cpp/absl/log/internal/conditions.h
new file mode 100644
index 0000000..f576d65
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/conditions.h
@@ -0,0 +1,228 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/conditions.h
+// -----------------------------------------------------------------------------
+//
+// This file contains implementation of conditional log statements, like LOG_IF
+// including all the ABSL_LOG_INTERNAL_..._CONDITION_... macros and
+// various condition classes like LogEveryNState.
+
+#ifndef ABSL_LOG_INTERNAL_CONDITIONS_H_
+#define ABSL_LOG_INTERNAL_CONDITIONS_H_
+
+#if defined(_WIN32) || defined(__hexagon__)
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/voidify.h"
+
+// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
+// temporary `LogMessage` instantiation followed by zero or more streamed
+// expressions. This definition is tricky to read correctly. It evaluates to
+// either
+//
+// (void)0;
+//
+// or
+//
+// ::absl::log_internal::Voidify() &&
+// ::absl::log_internal::LogMessage(...) << "the user's message";
+//
+// If the condition is evaluable at compile time, as is often the case, it
+// compiles away to just one side or the other.
+//
+// Although this is not used anywhere a statement (e.g. `if`) could not go,
+// the ternary expression does a better job avoiding spurious diagnostics
+// (dangling else, missing switch case) and preserving noreturn semantics (e.g.
+// on `LOG(FATAL)`) without requiring braces.
+//
+// The `switch` ensures that this expansion is the begnning of a statement (as
+// opposed to an expression) and prevents shenanigans like
+// `AFunction(LOG(INFO))` and `decltype(LOG(INFO))`. The apparently-redundant
+// `default` case makes the condition more amenable to Clang dataflow analysis.
+#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
+ switch (0) \
+ case 0: \
+ default: \
+ !(condition) ? (void)0 : ::absl::log_internal::Voidify()&&
+
+// `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
+// `ABSL_LOG_INTERNAL_CONDITION` but adds to that a series of variable
+// declarations, including a local static object which stores the state needed
+// to implement the stateful macros like `LOG_EVERY_N`.
+//
+// `for`-loops are used to declare scoped variables without braces (to permit
+// streaming into the macro's expansion) and without the dangling-`else`
+// problems/diagnostics that come with `if`.
+//
+// Two more variables are declared in separate `for`-loops:
+//
+// * `COUNTER` implements a streamable token whose value when streamed is the
+// number of times execution has passed through the macro.
+// * A boolean flag is used to prevent any of the `for`-loops from ever actually
+// looping.
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition) \
+ for (bool absl_log_internal_stateful_condition_do_log(condition); \
+ absl_log_internal_stateful_condition_do_log; \
+ absl_log_internal_stateful_condition_do_log = false) \
+ ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...) \
+ for (static ::absl::log_internal::Log##kind##State \
+ absl_log_internal_stateful_condition_state; \
+ absl_log_internal_stateful_condition_do_log && \
+ absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \
+ absl_log_internal_stateful_condition_do_log = false) \
+ for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED = \
+ absl_log_internal_stateful_condition_state.counter(); \
+ absl_log_internal_stateful_condition_do_log; \
+ absl_log_internal_stateful_condition_do_log = false)
+
+// `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
+// macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
+// `ABSL_MIN_LOG_LEVEL`) into a single boolean expression. We could chain
+// ternary operators instead, however some versions of Clang sometimes issue
+// spurious diagnostics after such expressions due to a control flow analysis
+// bug.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kInfo >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kWarning >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kError >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ ((condition) \
+ ? (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? true \
+ : (::absl::log_internal::AbortQuietly(), false)) \
+ : false))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ ((condition) \
+ ? (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? true \
+ : (::absl::log_internal::ExitQuietly(), false)) \
+ : false))
+
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
+ for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+ log_internal_severity_loop = 0) \
+ for (const absl::LogSeverity log_internal_severity = \
+ ::absl::NormalizeLogSeverity(severity); \
+ log_internal_severity_loop; log_internal_severity_loop = 0) \
+ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && \
+ (log_internal_severity >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \
+ (log_internal_severity == ::absl::LogSeverity::kFatal && \
+ (::absl::log_internal::AbortQuietly(), false))))
+#else // ndef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
+ for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+ log_internal_severity_loop = 0) \
+ for (const absl::LogSeverity log_internal_severity = \
+ ::absl::NormalizeLogSeverity(severity); \
+ log_internal_severity_loop; log_internal_severity_loop = 0) \
+ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#endif // ndef ABSL_MIN_LOG_LEVEL
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Stateful condition class name should be "Log" + name + "State".
+class LogEveryNState final {
+ public:
+ bool ShouldLog(int n);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogFirstNState final {
+ public:
+ bool ShouldLog(int n);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryPow2State final {
+ public:
+ bool ShouldLog();
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryNSecState final {
+ public:
+ bool ShouldLog(double seconds);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+ // Cycle count according to CycleClock that we should next log at.
+ std::atomic<int64_t> next_log_time_cycles_{0};
+};
+
+// Helper routines to abort the application quietly
+
+ABSL_ATTRIBUTE_NORETURN inline void AbortQuietly() { abort(); }
+ABSL_ATTRIBUTE_NORETURN inline void ExitQuietly() { _exit(1); }
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CONDITIONS_H_
diff --git a/abseil-cpp/absl/log/internal/config.h b/abseil-cpp/absl/log/internal/config.h
new file mode 100644
index 0000000..379e9ab
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/config.h
@@ -0,0 +1,45 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/config.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_CONFIG_H_
+#define ABSL_LOG_INTERNAL_CONFIG_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <cstdint>
+#else
+#include <sys/types.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#ifdef _WIN32
+using Tid = uint32_t;
+#else
+using Tid = pid_t;
+#endif
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CONFIG_H_
diff --git a/abseil-cpp/absl/log/internal/flags.h b/abseil-cpp/absl/log/internal/flags.h
new file mode 100644
index 0000000..0c5e81e
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/flags.h
@@ -0,0 +1,53 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_flags.h
+// -----------------------------------------------------------------------------
+//
+// This header declares set of flags which can be used to configure Abseil
+// Logging library behaviour at runtime.
+
+#ifndef ABSL_LOG_INTERNAL_FLAGS_H_
+#define ABSL_LOG_INTERNAL_FLAGS_H_
+
+#include <string>
+
+#include "absl/flags/declare.h"
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// These flags should not be used in C++ code to access logging library
+// configuration knobs. Use interfaces defined in absl/log/globals.h
+// instead. It is still ok to use these flags on a command line.
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Log messages at this severity or above are sent to stderr in *addition* to
+// logfiles. Defaults to `ERROR`. See log_severity.h for numeric values of
+// severity levels.
+ABSL_DECLARE_FLAG(int, stderrthreshold);
+
+// Log messages at this severity or above are logged; others are discarded.
+// Defaults to `INFO`, i.e. log all severities. See log_severity.h for numeric
+// values of severity levels.
+ABSL_DECLARE_FLAG(int, minloglevel);
+
+// If specified in the form file:linenum, any messages logged from a matching
+// location will also include a backtrace.
+ABSL_DECLARE_FLAG(std::string, log_backtrace_at);
+
+// If true, the log prefix (severity, date, time, PID, etc.) is prepended to
+// each message logged. Defaults to true.
+ABSL_DECLARE_FLAG(bool, log_prefix);
+
+#endif // ABSL_LOG_INTERNAL_FLAGS_H_
diff --git a/abseil-cpp/absl/log/internal/globals.cc b/abseil-cpp/absl/log/internal/globals.cc
new file mode 100644
index 0000000..359858f
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/globals.cc
@@ -0,0 +1,145 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/globals.h"
+
+#include <atomic>
+#include <cstdio>
+
+#if defined(__EMSCRIPTEN__)
+#include <emscripten/console.h>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// Keeps track of whether Logging initialization is finalized.
+// Log messages generated before that will go to stderr.
+ABSL_CONST_INIT std::atomic<bool> logging_initialized(false);
+
+// The TimeZone used for logging. This may only be set once.
+ABSL_CONST_INIT std::atomic<absl::TimeZone*> timezone_ptr{nullptr};
+
+// If true, the logging library will symbolize stack in fatal messages
+ABSL_CONST_INIT std::atomic<bool> symbolize_stack_trace(true);
+
+// Specifies maximum number of stack frames to report in fatal messages.
+ABSL_CONST_INIT std::atomic<int> max_frames_in_stack_trace(64);
+
+ABSL_CONST_INIT std::atomic<bool> exit_on_dfatal(true);
+ABSL_CONST_INIT std::atomic<bool> suppress_sigabort_trace(false);
+} // namespace
+
+bool IsInitialized() {
+ return logging_initialized.load(std::memory_order_acquire);
+}
+
+void SetInitialized() {
+ logging_initialized.store(true, std::memory_order_release);
+}
+
+void WriteToStderr(absl::string_view message, absl::LogSeverity severity) {
+ if (message.empty()) return;
+#if defined(__EMSCRIPTEN__)
+ // In WebAssembly, bypass filesystem emulation via fwrite.
+ // Skip a trailing newline character as emscripten_errn adds one itself.
+ const auto message_minus_newline = absl::StripSuffix(message, "\n");
+ // emscripten_errn was introduced in 3.1.41 but broken in standalone mode
+ // until 3.1.43.
+#if ABSL_INTERNAL_EMSCRIPTEN_VERSION >= 3001043
+ emscripten_errn(message_minus_newline.data(), message_minus_newline.size());
+#else
+ std::string null_terminated_message(message_minus_newline);
+ _emscripten_err(null_terminated_message.c_str());
+#endif
+#else
+ // Avoid using std::cerr from this module since we may get called during
+ // exit code, and cerr may be partially or fully destroyed by then.
+ std::fwrite(message.data(), message.size(), 1, stderr);
+#endif
+
+#if defined(_WIN64) || defined(_WIN32) || defined(_WIN16)
+ // C99 requires stderr to not be fully-buffered by default (7.19.3.7), but
+ // MS CRT buffers it anyway, so we must `fflush` to ensure the string hits
+ // the console/file before the program dies (and takes the libc buffers
+ // with it).
+ // https://docs.microsoft.com/en-us/cpp/c-runtime-library/stream-i-o
+ if (severity >= absl::LogSeverity::kWarning) {
+ std::fflush(stderr);
+ }
+#else
+ // Avoid unused parameter warning in this branch.
+ (void)severity;
+#endif
+}
+
+void SetTimeZone(absl::TimeZone tz) {
+ absl::TimeZone* expected = nullptr;
+ absl::TimeZone* new_tz = new absl::TimeZone(tz);
+ // timezone_ptr can only be set once, otherwise new_tz is leaked.
+ if (!timezone_ptr.compare_exchange_strong(expected, new_tz,
+ std::memory_order_release,
+ std::memory_order_relaxed)) {
+ ABSL_RAW_LOG(FATAL,
+ "absl::log_internal::SetTimeZone() has already been called");
+ }
+}
+
+const absl::TimeZone* TimeZone() {
+ return timezone_ptr.load(std::memory_order_acquire);
+}
+
+bool ShouldSymbolizeLogStackTrace() {
+ return symbolize_stack_trace.load(std::memory_order_acquire);
+}
+
+void EnableSymbolizeLogStackTrace(bool on_off) {
+ symbolize_stack_trace.store(on_off, std::memory_order_release);
+}
+
+int MaxFramesInLogStackTrace() {
+ return max_frames_in_stack_trace.load(std::memory_order_acquire);
+}
+
+void SetMaxFramesInLogStackTrace(int max_num_frames) {
+ max_frames_in_stack_trace.store(max_num_frames, std::memory_order_release);
+}
+
+bool ExitOnDFatal() { return exit_on_dfatal.load(std::memory_order_acquire); }
+
+void SetExitOnDFatal(bool on_off) {
+ exit_on_dfatal.store(on_off, std::memory_order_release);
+}
+
+bool SuppressSigabortTrace() {
+ return suppress_sigabort_trace.load(std::memory_order_acquire);
+}
+
+bool SetSuppressSigabortTrace(bool on_off) {
+ return suppress_sigabort_trace.exchange(on_off);
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/globals.h b/abseil-cpp/absl/log/internal/globals.h
new file mode 100644
index 0000000..27bc0d0
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/globals.h
@@ -0,0 +1,101 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/globals.h
+// -----------------------------------------------------------------------------
+//
+// This header file contains various global objects and static helper routines
+// use in logging implementation.
+
+#ifndef ABSL_LOG_INTERNAL_GLOBALS_H_
+#define ABSL_LOG_INTERNAL_GLOBALS_H_
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// IsInitialized returns true if the logging library is initialized.
+// This function is async-signal-safe
+bool IsInitialized();
+
+// SetLoggingInitialized is called once after logging initialization is done.
+void SetInitialized();
+
+// Unconditionally write a `message` to stderr. If `severity` exceeds kInfo
+// we also flush the stderr stream.
+void WriteToStderr(absl::string_view message, absl::LogSeverity severity);
+
+// Set the TimeZone used for human-friendly times (for example, the log message
+// prefix) printed by the logging library. This may only be called once.
+void SetTimeZone(absl::TimeZone tz);
+
+// Returns the TimeZone used for human-friendly times (for example, the log
+// message prefix) printed by the logging library Returns nullptr prior to
+// initialization.
+const absl::TimeZone* TimeZone();
+
+// Returns true if stack traces emitted by the logging library should be
+// symbolized. This function is async-signal-safe.
+bool ShouldSymbolizeLogStackTrace();
+
+// Enables or disables symbolization of stack traces emitted by the
+// logging library. This function is async-signal-safe.
+void EnableSymbolizeLogStackTrace(bool on_off);
+
+// Returns the maximum number of frames that appear in stack traces
+// emitted by the logging library. This function is async-signal-safe.
+int MaxFramesInLogStackTrace();
+
+// Sets the maximum number of frames that appear in stack traces emitted by
+// the logging library. This function is async-signal-safe.
+void SetMaxFramesInLogStackTrace(int max_num_frames);
+
+// Determines whether we exit the program for a LOG(DFATAL) message in
+// debug mode. It does this by skipping the call to Fail/FailQuietly.
+// This is intended for testing only.
+//
+// This can have some effects on LOG(FATAL) as well. Failure messages
+// are always allocated (rather than sharing a buffer), the crash
+// reason is not recorded, the "gwq" status message is not updated,
+// and the stack trace is not recorded. The LOG(FATAL) *will* still
+// exit the program. Since this function is used only in testing,
+// these differences are acceptable.
+//
+// Additionally, LOG(LEVEL(FATAL)) is indistinguishable from LOG(DFATAL) and
+// will not terminate the program if SetExitOnDFatal(false) has been called.
+bool ExitOnDFatal();
+
+// SetExitOnDFatal() sets the ExitOnDFatal() status
+void SetExitOnDFatal(bool on_off);
+
+// Determines if the logging library should suppress logging of stacktraces in
+// the `SIGABRT` handler, typically because we just logged a stacktrace as part
+// of `LOG(FATAL)` and are about to send ourselves a `SIGABRT` to end the
+// program.
+bool SuppressSigabortTrace();
+
+// Sets the SuppressSigabortTrace() status and returns the previous state.
+bool SetSuppressSigabortTrace(bool on_off);
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_GLOBALS_H_
diff --git a/abseil-cpp/absl/log/internal/log_format.cc b/abseil-cpp/absl/log/internal/log_format.cc
new file mode 100644
index 0000000..23cef88
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_format.cc
@@ -0,0 +1,205 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_format.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <winsock2.h> // For timeval
+#else
+#include <sys/time.h>
+#endif
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/append_truncated.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// This templated function avoids compiler warnings about tautological
+// comparisons when log_internal::Tid is unsigned. It can be replaced with a
+// constexpr if once the minimum C++ version Abseil supports is C++17.
+template <typename T>
+inline std::enable_if_t<!std::is_signed<T>::value>
+PutLeadingWhitespace(T tid, char*& p) {
+ if (tid < 10) *p++ = ' ';
+ if (tid < 100) *p++ = ' ';
+ if (tid < 1000) *p++ = ' ';
+ if (tid < 10000) *p++ = ' ';
+ if (tid < 100000) *p++ = ' ';
+ if (tid < 1000000) *p++ = ' ';
+}
+
+template <typename T>
+inline std::enable_if_t<std::is_signed<T>::value>
+PutLeadingWhitespace(T tid, char*& p) {
+ if (tid >= 0 && tid < 10) *p++ = ' ';
+ if (tid > -10 && tid < 100) *p++ = ' ';
+ if (tid > -100 && tid < 1000) *p++ = ' ';
+ if (tid > -1000 && tid < 10000) *p++ = ' ';
+ if (tid > -10000 && tid < 100000) *p++ = ' ';
+ if (tid > -100000 && tid < 1000000) *p++ = ' ';
+}
+
+// The fields before the filename are all fixed-width except for the thread ID,
+// which is of bounded width.
+size_t FormatBoundedFields(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::Span<char>& buf) {
+ constexpr size_t kBoundedFieldsMaxLen =
+ sizeof("SMMDD HH:MM:SS.NNNNNN ") +
+ (1 + std::numeric_limits<log_internal::Tid>::digits10 + 1) - sizeof("");
+ if (ABSL_PREDICT_FALSE(buf.size() < kBoundedFieldsMaxLen)) {
+ // We don't bother trying to truncate these fields if the buffer is too
+ // short (or almost too short) because it would require doing a lot more
+ // length checking (slow) and it should never happen. A 15kB buffer should
+ // be enough for anyone. Instead we mark `buf` full without writing
+ // anything.
+ buf.remove_suffix(buf.size());
+ return 0;
+ }
+
+ // We can't call absl::LocalTime(), localtime_r(), or anything else here that
+ // isn't async-signal-safe. We can only use the time zone if it has already
+ // been loaded.
+ const absl::TimeZone* tz = absl::log_internal::TimeZone();
+ if (ABSL_PREDICT_FALSE(tz == nullptr)) {
+ // If a time zone hasn't been set yet because we are logging before the
+ // logging library has been initialized, we fallback to a simpler, slower
+ // method. Just report the raw Unix time in seconds. We cram this into the
+ // normal time format for the benefit of parsers.
+ auto tv = absl::ToTimeval(timestamp);
+ int snprintf_result = absl::SNPrintF(
+ buf.data(), buf.size(), "%c0000 00:00:%02d.%06d %7d ",
+ absl::LogSeverityName(severity)[0], static_cast<int>(tv.tv_sec),
+ static_cast<int>(tv.tv_usec), static_cast<int>(tid));
+ if (snprintf_result >= 0) {
+ buf.remove_prefix(static_cast<size_t>(snprintf_result));
+ return static_cast<size_t>(snprintf_result);
+ }
+ return 0;
+ }
+
+ char* p = buf.data();
+ *p++ = absl::LogSeverityName(severity)[0];
+ const absl::TimeZone::CivilInfo ci = tz->At(timestamp);
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.month()), p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.day()), p);
+ p += 2;
+ *p++ = ' ';
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.hour()), p);
+ p += 2;
+ *p++ = ':';
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.minute()),
+ p);
+ p += 2;
+ *p++ = ':';
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(ci.cs.second()),
+ p);
+ p += 2;
+ *p++ = '.';
+ const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond);
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 10000), p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs / 100 % 100),
+ p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<uint32_t>(usecs % 100), p);
+ p += 2;
+ *p++ = ' ';
+ PutLeadingWhitespace(tid, p);
+ p = absl::numbers_internal::FastIntToBuffer(tid, p);
+ *p++ = ' ';
+ const size_t bytes_formatted = static_cast<size_t>(p - buf.data());
+ buf.remove_prefix(bytes_formatted);
+ return bytes_formatted;
+}
+
+size_t FormatLineNumber(int line, absl::Span<char>& buf) {
+ constexpr size_t kLineFieldMaxLen =
+ sizeof(":] ") + (1 + std::numeric_limits<int>::digits10 + 1) - sizeof("");
+ if (ABSL_PREDICT_FALSE(buf.size() < kLineFieldMaxLen)) {
+ // As above, we don't bother trying to truncate this if the buffer is too
+ // short and it should never happen.
+ buf.remove_suffix(buf.size());
+ return 0;
+ }
+ char* p = buf.data();
+ *p++ = ':';
+ p = absl::numbers_internal::FastIntToBuffer(line, p);
+ *p++ = ']';
+ *p++ = ' ';
+ const size_t bytes_formatted = static_cast<size_t>(p - buf.data());
+ buf.remove_prefix(bytes_formatted);
+ return bytes_formatted;
+}
+
+} // namespace
+
+std::string FormatLogMessage(absl::LogSeverity severity,
+ absl::CivilSecond civil_second,
+ absl::Duration subsecond, log_internal::Tid tid,
+ absl::string_view basename, int line,
+ PrefixFormat format, absl::string_view message) {
+ return absl::StrFormat(
+ "%c%02d%02d %02d:%02d:%02d.%06d %7d %s:%d] %s%s",
+ absl::LogSeverityName(severity)[0], civil_second.month(),
+ civil_second.day(), civil_second.hour(), civil_second.minute(),
+ civil_second.second(), absl::ToInt64Microseconds(subsecond), tid,
+ basename, line, format == PrefixFormat::kRaw ? "RAW: " : "", message);
+}
+
+// This method is fairly hot, and the library always passes a huge `buf`, so we
+// save some bounds-checking cycles by not trying to do precise truncation.
+// Truncating at a field boundary is probably a better UX anyway.
+//
+// The prefix is written in three parts, each of which does a single
+// bounds-check and truncation:
+// 1. severity, timestamp, and thread ID
+// 2. filename
+// 3. line number and bracket
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::string_view basename,
+ int line, PrefixFormat format, absl::Span<char>& buf) {
+ auto prefix_size = FormatBoundedFields(severity, timestamp, tid, buf);
+ prefix_size += log_internal::AppendTruncated(basename, buf);
+ prefix_size += FormatLineNumber(line, buf);
+ if (format == PrefixFormat::kRaw)
+ prefix_size += log_internal::AppendTruncated("RAW: ", buf);
+ return prefix_size;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/log_format.h b/abseil-cpp/absl/log/internal/log_format.h
new file mode 100644
index 0000000..95a45ed
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_format.h
@@ -0,0 +1,78 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_format.h
+// -----------------------------------------------------------------------------
+//
+// This file declares routines implementing formatting of log message and log
+// prefix.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+#define ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+enum class PrefixFormat {
+ kNotRaw,
+ kRaw,
+};
+
+// Formats log message based on provided data.
+std::string FormatLogMessage(absl::LogSeverity severity,
+ absl::CivilSecond civil_second,
+ absl::Duration subsecond, log_internal::Tid tid,
+ absl::string_view basename, int line,
+ PrefixFormat format, absl::string_view message);
+
+// Formats various entry metadata into a text string meant for use as a
+// prefix on a log message string. Writes into `buf`, advances `buf` to point
+// at the remainder of the buffer (i.e. past any written bytes), and returns the
+// number of bytes written.
+//
+// In addition to calling `buf->remove_prefix()` (or the equivalent), this
+// function may also do `buf->remove_suffix(buf->size())` in cases where no more
+// bytes (i.e. no message data) should be written into the buffer. For example,
+// if the prefix ought to be:
+// I0926 09:00:00.000000 1234567 foo.cc:123]
+// `buf` is too small, the function might fill the whole buffer:
+// I0926 09:00:00.000000 1234
+// (note the apparrently incorrect thread ID), or it might write less:
+// I0926 09:00:00.000000
+// In this case, it might also empty `buf` prior to returning to prevent
+// message data from being written into the space where a reader would expect to
+// see a thread ID.
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::string_view basename,
+ int line, PrefixFormat format, absl::Span<char>& buf);
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_LOG_FORMAT_H_
diff --git a/abseil-cpp/absl/log/internal/log_impl.h b/abseil-cpp/absl/log/internal/log_impl.h
new file mode 100644
index 0000000..9326780
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_impl.h
@@ -0,0 +1,216 @@
+// Copyright 2022 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_
+#define ABSL_LOG_INTERNAL_LOG_IMPL_H_
+
+#include "absl/log/internal/conditions.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/strip.h"
+
+// ABSL_LOG()
+#define ABSL_LOG_INTERNAL_LOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+// ABSL_PLOG()
+#define ABSL_LOG_INTERNAL_PLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+// ABSL_DLOG()
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#else
+#define ABSL_LOG_INTERNAL_DLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#endif
+
+#define ABSL_LOG_INTERNAL_LOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#define ABSL_LOG_INTERNAL_PLOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#else
+#define ABSL_LOG_INTERNAL_DLOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false && (condition)) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#endif
+
+// ABSL_LOG_EVERY_N
+#define ABSL_LOG_INTERNAL_LOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+// ABSL_LOG_FIRST_N
+#define ABSL_LOG_INTERNAL_LOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+// ABSL_LOG_EVERY_POW_2
+#define ABSL_LOG_INTERNAL_LOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+// ABSL_LOG_EVERY_N_SEC
+#define ABSL_LOG_INTERNAL_LOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryNSec, n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#else // def NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_EVERY_N_SEC_IMPL(severity, n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#endif // def NDEBUG
+
+#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_LOG_IF_FIRST_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_LOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
+ n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
+ n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_IF_FIRST_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_LOG_INTERNAL_PLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
+ n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
+ n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#ifndef NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
+ n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryNSec, \
+ n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#else // def NDEBUG
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
+ EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_FIRST_N_IMPL(severity, condition, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
+ FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
+ EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_LOG_INTERNAL_DLOG_IF_EVERY_N_SEC_IMPL(severity, condition, \
+ n_seconds) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, false && (condition))( \
+ EveryNSec, n_seconds) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#endif // def NDEBUG
+
+#endif // ABSL_LOG_INTERNAL_LOG_IMPL_H_
diff --git a/abseil-cpp/absl/log/internal/log_message.cc b/abseil-cpp/absl/log/internal/log_message.cc
new file mode 100644
index 0000000..10ac245
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_message.cc
@@ -0,0 +1,633 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_message.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <array>
+#include <atomic>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <tuple>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/strerror.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/debugging/internal/examine_stack.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/append_truncated.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/internal/log_format.h"
+#include "absl/log/internal/log_sink_set.h"
+#include "absl/log/internal/proto.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/log_sink_registry.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
+ // Default - Do nothing
+}
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// message `logging.proto.Event`
+enum EventTag : uint8_t {
+ kValue = 7,
+};
+
+// message `logging.proto.Value`
+enum ValueTag : uint8_t {
+ kString = 1,
+ kStringLiteral = 6,
+};
+
+// Decodes a `logging.proto.Value` from `buf` and writes a string representation
+// into `dst`. The string representation will be truncated if `dst` is not
+// large enough to hold it. Returns false if `dst` has size zero or one (i.e.
+// sufficient only for a nul-terminator) and no decoded data could be written.
+// This function may or may not write a nul-terminator into `dst`, and it may or
+// may not truncate the data it writes in order to do make space for that nul
+// terminator. In any case, `dst` will be advanced to point at the byte where
+// subsequent writes should begin.
+bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
+ if (dst.size() <= 1) return false;
+ ProtoField field;
+ while (field.DecodeFrom(&buf)) {
+ switch (field.tag()) {
+ case ValueTag::kString:
+ case ValueTag::kStringLiteral:
+ if (field.type() == WireType::kLengthDelimited)
+ if (log_internal::AppendTruncated(field.string_value(), dst) <
+ field.string_value().size())
+ return false;
+ }
+ }
+ return true;
+}
+
+absl::string_view Basename(absl::string_view filepath) {
+#ifdef _WIN32
+ size_t path = filepath.find_last_of("/\\");
+#else
+ size_t path = filepath.find_last_of('/');
+#endif
+ if (path != filepath.npos) filepath.remove_prefix(path + 1);
+ return filepath;
+}
+
+void WriteToString(const char* data, void* str) {
+ reinterpret_cast<std::string*>(str)->append(data);
+}
+void WriteToStream(const char* data, void* os) {
+ auto* cast_os = static_cast<std::ostream*>(os);
+ *cast_os << data;
+}
+} // namespace
+
+struct LogMessage::LogMessageData final {
+ LogMessageData(const char* file, int line, absl::LogSeverity severity,
+ absl::Time timestamp);
+ LogMessageData(const LogMessageData&) = delete;
+ LogMessageData& operator=(const LogMessageData&) = delete;
+
+ // `LogEntry` sent to `LogSink`s; contains metadata.
+ absl::LogEntry entry;
+
+ // true => this was first fatal msg
+ bool first_fatal;
+ // true => all failures should be quiet
+ bool fail_quietly;
+ // true => PLOG was requested
+ bool is_perror;
+
+ // Extra `LogSink`s to log to, in addition to `global_sinks`.
+ absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
+ // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
+ // non-sink targets (e.g. stderr, log files).
+ bool extra_sinks_only;
+
+ std::ostream manipulated; // ostream with IO manipulators applied
+
+ // A `logging.proto.Event` proto message is built into `encoded_buf`.
+ std::array<char, kLogMessageBufferSize> encoded_buf;
+ // `encoded_remaining` is the suffix of `encoded_buf` that has not been filled
+ // yet. If a datum to be encoded does not fit into `encoded_remaining` and
+ // cannot be truncated to fit, the size of `encoded_remaining` will be zeroed
+ // to prevent encoding of any further data. Note that in this case its data()
+ // pointer will not point past the end of `encoded_buf`.
+ absl::Span<char> encoded_remaining;
+
+ // A formatted string message is built in `string_buf`.
+ std::array<char, kLogMessageBufferSize> string_buf;
+
+ void FinalizeEncodingAndFormat();
+};
+
+LogMessage::LogMessageData::LogMessageData(const char* file, int line,
+ absl::LogSeverity severity,
+ absl::Time timestamp)
+ : extra_sinks_only(false),
+ manipulated(nullptr),
+ // This `absl::MakeSpan` silences spurious -Wuninitialized from GCC:
+ encoded_remaining(absl::MakeSpan(encoded_buf)) {
+ // Legacy defaults for LOG's ostream:
+ manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
+ entry.full_filename_ = file;
+ entry.base_filename_ = Basename(file);
+ entry.line_ = line;
+ entry.prefix_ = absl::ShouldPrependLogPrefix();
+ entry.severity_ = absl::NormalizeLogSeverity(severity);
+ entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+ entry.timestamp_ = timestamp;
+ entry.tid_ = absl::base_internal::GetCachedTID();
+}
+
+void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
+ // Note that `encoded_remaining` may have zero size without pointing past the
+ // end of `encoded_buf`, so the difference between `data()` pointers is used
+ // to compute the size of `encoded_data`.
+ absl::Span<const char> encoded_data(
+ encoded_buf.data(),
+ static_cast<size_t>(encoded_remaining.data() - encoded_buf.data()));
+ // `string_remaining` is the suffix of `string_buf` that has not been filled
+ // yet.
+ absl::Span<char> string_remaining(string_buf);
+ // We may need to write a newline and nul-terminator at the end of the decoded
+ // string data. Rather than worry about whether those should overwrite the
+ // end of the string (if the buffer is full) or be appended, we avoid writing
+ // into the last two bytes so we always have space to append.
+ string_remaining.remove_suffix(2);
+ entry.prefix_len_ =
+ entry.prefix() ? log_internal::FormatLogPrefix(
+ entry.log_severity(), entry.timestamp(), entry.tid(),
+ entry.source_basename(), entry.source_line(),
+ log_internal::ThreadIsLoggingToLogSink()
+ ? PrefixFormat::kRaw
+ : PrefixFormat::kNotRaw,
+ string_remaining)
+ : 0;
+ // Decode data from `encoded_buf` until we run out of data or we run out of
+ // `string_remaining`.
+ ProtoField field;
+ while (field.DecodeFrom(&encoded_data)) {
+ switch (field.tag()) {
+ case EventTag::kValue:
+ if (field.type() != WireType::kLengthDelimited) continue;
+ if (PrintValue(string_remaining, field.bytes_value())) continue;
+ break;
+ }
+ break;
+ }
+ auto chars_written =
+ static_cast<size_t>(string_remaining.data() - string_buf.data());
+ string_buf[chars_written++] = '\n';
+ string_buf[chars_written++] = '\0';
+ entry.text_message_with_prefix_and_newline_and_nul_ =
+ absl::MakeSpan(string_buf).subspan(0, chars_written);
+}
+
+LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
+ : data_(absl::make_unique<LogMessageData>(file, line, severity,
+ absl::Now())) {
+ data_->first_fatal = false;
+ data_->is_perror = false;
+ data_->fail_quietly = false;
+
+ // This logs a backtrace even if the location is subsequently changed using
+ // AtLocation. This quirk, and the behavior when AtLocation is called twice,
+ // are fixable but probably not worth fixing.
+ LogBacktraceIfNeeded();
+}
+
+LogMessage::LogMessage(const char* file, int line, InfoTag)
+ : LogMessage(file, line, absl::LogSeverity::kInfo) {}
+LogMessage::LogMessage(const char* file, int line, WarningTag)
+ : LogMessage(file, line, absl::LogSeverity::kWarning) {}
+LogMessage::LogMessage(const char* file, int line, ErrorTag)
+ : LogMessage(file, line, absl::LogSeverity::kError) {}
+
+LogMessage::~LogMessage() {
+#ifdef ABSL_MIN_LOG_LEVEL
+ if (data_->entry.log_severity() <
+ static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
+ data_->entry.log_severity() < absl::LogSeverity::kFatal) {
+ return;
+ }
+#endif
+ Flush();
+}
+
+LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
+ data_->entry.full_filename_ = file;
+ data_->entry.base_filename_ = Basename(file);
+ data_->entry.line_ = line;
+ LogBacktraceIfNeeded();
+ return *this;
+}
+
+LogMessage& LogMessage::NoPrefix() {
+ data_->entry.prefix_ = false;
+ return *this;
+}
+
+LogMessage& LogMessage::WithVerbosity(int verbose_level) {
+ if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
+ data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+ } else {
+ data_->entry.verbose_level_ = std::max(0, verbose_level);
+ }
+ return *this;
+}
+
+LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
+ data_->entry.timestamp_ = timestamp;
+ return *this;
+}
+
+LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
+ data_->entry.tid_ = tid;
+ return *this;
+}
+
+LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
+ data_->entry.full_filename_ = entry.full_filename_;
+ data_->entry.base_filename_ = entry.base_filename_;
+ data_->entry.line_ = entry.line_;
+ data_->entry.prefix_ = entry.prefix_;
+ data_->entry.severity_ = entry.severity_;
+ data_->entry.verbose_level_ = entry.verbose_level_;
+ data_->entry.timestamp_ = entry.timestamp_;
+ data_->entry.tid_ = entry.tid_;
+ return *this;
+}
+
+LogMessage& LogMessage::WithPerror() {
+ data_->is_perror = true;
+ return *this;
+}
+
+LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
+ ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+ data_->extra_sinks.push_back(sink);
+ return *this;
+}
+
+LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
+ ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+ data_->extra_sinks.clear();
+ data_->extra_sinks.push_back(sink);
+ data_->extra_sinks_only = true;
+ return *this;
+}
+
+#ifdef __ELF__
+extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
+extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
+#endif
+
+void LogMessage::FailWithoutStackTrace() {
+ // Now suppress repeated trace logging:
+ log_internal::SetSuppressSigabortTrace(true);
+#if defined _DEBUG && defined COMPILER_MSVC
+ // When debugging on windows, avoid the obnoxious dialog.
+ __debugbreak();
+#endif
+
+#ifdef __ELF__
+ // For b/8737634, flush coverage if we are in coverage mode.
+ if (&__gcov_dump != nullptr) {
+ __gcov_dump();
+ } else if (&__gcov_flush != nullptr) {
+ __gcov_flush();
+ }
+#endif
+
+ abort();
+}
+
+void LogMessage::FailQuietly() {
+ // _exit. Calling abort() would trigger all sorts of death signal handlers
+ // and a detailed stack trace. Calling exit() would trigger the onexit
+ // handlers, including the heap-leak checker, which is guaranteed to fail in
+ // this case: we probably just new'ed the std::string that we logged.
+ // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
+ // of the program quickly, and it doesn't make much sense for FailQuietly to
+ // offer different guarantees about exit behavior than Fail does. (And as a
+ // consequence for QCHECK and CHECK to offer different exit behaviors)
+ _exit(1);
+}
+
+LogMessage& LogMessage::operator<<(const std::string& v) {
+ CopyToEncodedBuffer<StringType::kNotLiteral>(v);
+ return *this;
+}
+
+LogMessage& LogMessage::operator<<(absl::string_view v) {
+ CopyToEncodedBuffer<StringType::kNotLiteral>(v);
+ return *this;
+}
+LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
+ OstreamView view(*data_);
+ data_->manipulated << m;
+ return *this;
+}
+LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
+ OstreamView view(*data_);
+ data_->manipulated << m;
+ return *this;
+}
+template LogMessage& LogMessage::operator<<(const char& v);
+template LogMessage& LogMessage::operator<<(const signed char& v);
+template LogMessage& LogMessage::operator<<(const unsigned char& v);
+template LogMessage& LogMessage::operator<<(const short& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned short& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const int& v);
+template LogMessage& LogMessage::operator<<(const unsigned int& v);
+template LogMessage& LogMessage::operator<<(const long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const long long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(
+ const unsigned long long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(void* const& v);
+template LogMessage& LogMessage::operator<<(const void* const& v);
+template LogMessage& LogMessage::operator<<(const float& v);
+template LogMessage& LogMessage::operator<<(const double& v);
+template LogMessage& LogMessage::operator<<(const bool& v);
+
+void LogMessage::Flush() {
+ if (data_->entry.log_severity() < absl::MinLogLevel()) return;
+
+ if (data_->is_perror) {
+ InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
+ << " [" << errno_saver_() << "]";
+ }
+
+ // Have we already seen a fatal message?
+ ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
+ if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+ absl::log_internal::ExitOnDFatal()) {
+ // Exactly one LOG(FATAL) message is responsible for aborting the process,
+ // even if multiple threads LOG(FATAL) concurrently.
+ bool expected_seen_fatal = false;
+ if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
+ std::memory_order_relaxed)) {
+ data_->first_fatal = true;
+ }
+ }
+
+ data_->FinalizeEncodingAndFormat();
+ data_->entry.encoding_ =
+ absl::string_view(data_->encoded_buf.data(),
+ static_cast<size_t>(data_->encoded_remaining.data() -
+ data_->encoded_buf.data()));
+ SendToLog();
+}
+
+void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
+
+LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
+ : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) {
+ // This constructor sets the `streambuf` up so that streaming into an attached
+ // ostream encodes string data in-place. To do that, we write appropriate
+ // headers into the buffer using a copy of the buffer view so that we can
+ // decide not to keep them later if nothing is ever streamed in. We don't
+ // know how much data we'll get, but we can use the size of the remaining
+ // buffer as an upper bound and fill in the right size once we know it.
+ message_start_ =
+ EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
+ &encoded_remaining_copy_);
+ string_start_ =
+ EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
+ &encoded_remaining_copy_);
+ setp(encoded_remaining_copy_.data(),
+ encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
+ data_.manipulated.rdbuf(this);
+}
+
+LogMessage::OstreamView::~OstreamView() {
+ data_.manipulated.rdbuf(nullptr);
+ if (!string_start_.data()) {
+ // The second field header didn't fit. Whether the first one did or not, we
+ // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
+ // size of `data_->encoded_remaining` so that no more data are encoded.
+ data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size());
+ return;
+ }
+ const absl::Span<const char> contents(pbase(),
+ static_cast<size_t>(pptr() - pbase()));
+ if (contents.empty()) return;
+ encoded_remaining_copy_.remove_prefix(contents.size());
+ EncodeMessageLength(string_start_, &encoded_remaining_copy_);
+ EncodeMessageLength(message_start_, &encoded_remaining_copy_);
+ data_.encoded_remaining = encoded_remaining_copy_;
+}
+
+std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
+
+bool LogMessage::IsFatal() const {
+ return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+ absl::log_internal::ExitOnDFatal();
+}
+
+void LogMessage::PrepareToDie() {
+ // If we log a FATAL message, flush all the log destinations, then toss
+ // a signal for others to catch. We leave the logs in a state that
+ // someone else can use them (as long as they flush afterwards)
+ if (data_->first_fatal) {
+ // Notify observers about the upcoming fatal error.
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
+ }
+
+ if (!data_->fail_quietly) {
+ // Log the message first before we start collecting stack trace.
+ log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+ data_->extra_sinks_only);
+
+ // `DumpStackTrace` generates an empty string under MSVC.
+ // Adding the constant prefix here simplifies testing.
+ data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
+ debugging_internal::DumpStackTrace(
+ 0, log_internal::MaxFramesInLogStackTrace(),
+ log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
+ &data_->entry.stacktrace_);
+ }
+}
+
+void LogMessage::Die() {
+ absl::FlushLogSinks();
+
+ if (data_->fail_quietly) {
+ FailQuietly();
+ } else {
+ FailWithoutStackTrace();
+ }
+}
+
+void LogMessage::SendToLog() {
+ if (IsFatal()) PrepareToDie();
+ // Also log to all registered sinks, even if OnlyLogToStderr() is set.
+ log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+ data_->extra_sinks_only);
+ if (IsFatal()) Die();
+}
+
+void LogMessage::LogBacktraceIfNeeded() {
+ if (!absl::log_internal::IsInitialized()) return;
+
+ if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
+ data_->entry.source_line()))
+ return;
+ OstreamView view(*data_);
+ view.stream() << " (stacktrace:\n";
+ debugging_internal::DumpStackTrace(
+ 1, log_internal::MaxFramesInLogStackTrace(),
+ log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
+ &view.stream());
+ view.stream() << ") ";
+}
+
+// Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
+// containing the specified string data using a `Value` field appropriate to
+// `str_type`. Truncates `str` if necessary, but emits nothing and marks the
+// buffer full if even the field headers do not fit.
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBuffer(absl::string_view str) {
+ auto encoded_remaining_copy = data_->encoded_remaining;
+ auto start = EncodeMessageStart(
+ EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + str.size(),
+ &encoded_remaining_copy);
+ // If the `logging.proto.Event.value` field header did not fit,
+ // `EncodeMessageStart` will have zeroed `encoded_remaining_copy`'s size and
+ // `EncodeStringTruncate` will fail too.
+ if (EncodeStringTruncate(str_type == StringType::kLiteral
+ ? ValueTag::kStringLiteral
+ : ValueTag::kString,
+ str, &encoded_remaining_copy)) {
+ // The string may have been truncated, but the field header fit.
+ EncodeMessageLength(start, &encoded_remaining_copy);
+ data_->encoded_remaining = encoded_remaining_copy;
+ } else {
+ // The field header(s) did not fit; zero `encoded_remaining` so we don't
+ // write anything else later.
+ data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
+ }
+}
+template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
+ absl::string_view str);
+template void LogMessage::CopyToEncodedBuffer<
+ LogMessage::StringType::kNotLiteral>(absl::string_view str);
+template <LogMessage::StringType str_type>
+void LogMessage::CopyToEncodedBuffer(char ch, size_t num) {
+ auto encoded_remaining_copy = data_->encoded_remaining;
+ auto value_start = EncodeMessageStart(
+ EventTag::kValue, BufferSizeFor(WireType::kLengthDelimited) + num,
+ &encoded_remaining_copy);
+ auto str_start = EncodeMessageStart(str_type == StringType::kLiteral
+ ? ValueTag::kStringLiteral
+ : ValueTag::kString,
+ num, &encoded_remaining_copy);
+ if (str_start.data()) {
+ // The field headers fit.
+ log_internal::AppendTruncated(ch, num, encoded_remaining_copy);
+ EncodeMessageLength(str_start, &encoded_remaining_copy);
+ EncodeMessageLength(value_start, &encoded_remaining_copy);
+ data_->encoded_remaining = encoded_remaining_copy;
+ } else {
+ // The field header(s) did not fit; zero `encoded_remaining` so we don't
+ // write anything else later.
+ data_->encoded_remaining.remove_suffix(data_->encoded_remaining.size());
+ }
+}
+template void LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(
+ char ch, size_t num);
+template void LogMessage::CopyToEncodedBuffer<
+ LogMessage::StringType::kNotLiteral>(char ch, size_t num);
+
+LogMessageFatal::LogMessageFatal(const char* file, int line)
+ : LogMessage(file, line, absl::LogSeverity::kFatal) {}
+
+LogMessageFatal::LogMessageFatal(const char* file, int line,
+ absl::string_view failure_msg)
+ : LogMessage(file, line, absl::LogSeverity::kFatal) {
+ *this << "Check failed: " << failure_msg << " ";
+}
+
+// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+// disable msvc's warning about the d'tor never returning.
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+LogMessageFatal::~LogMessageFatal() {
+ Flush();
+ FailWithoutStackTrace();
+}
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(pop)
+#endif
+
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line)
+ : LogMessage(file, line, absl::LogSeverity::kFatal) {
+ SetFailQuietly();
+}
+
+LogMessageQuietlyFatal::LogMessageQuietlyFatal(const char* file, int line,
+ absl::string_view failure_msg)
+ : LogMessage(file, line, absl::LogSeverity::kFatal) {
+ SetFailQuietly();
+ *this << "Check failed: " << failure_msg << " ";
+}
+
+// ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+// disable msvc's warning about the d'tor never returning.
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+LogMessageQuietlyFatal::~LogMessageQuietlyFatal() {
+ Flush();
+ FailQuietly();
+}
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(pop)
+#endif
+
+} // namespace log_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/log_message.h b/abseil-cpp/absl/log/internal/log_message.h
new file mode 100644
index 0000000..4693772
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_message.h
@@ -0,0 +1,377 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_message.h
+// -----------------------------------------------------------------------------
+//
+// This file declares `class absl::log_internal::LogMessage`. This class more or
+// less represents a particular log message. LOG/CHECK macros create a
+// temporary instance of `LogMessage` and then stream values to it. At the end
+// of the LOG/CHECK statement, LogMessage instance goes out of scope and
+// `~LogMessage` directs the message to the registered log sinks.
+// Heap-allocation of `LogMessage` is unsupported. Construction outside of a
+// `LOG` macro is unsupported.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+
+#include <ios>
+#include <memory>
+#include <ostream>
+#include <streambuf>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/errno_saver.h"
+#include "absl/base/log_severity.h"
+#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"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+constexpr int kLogMessageBufferSize = 15000;
+
+class LogMessage {
+ public:
+ struct InfoTag {};
+ struct WarningTag {};
+ struct ErrorTag {};
+
+ // Used for `LOG`.
+ LogMessage(const char* file, int line,
+ absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
+ // These constructors are slightly smaller/faster to call; the severity is
+ // curried into the function pointer.
+ LogMessage(const char* file, int line,
+ InfoTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+ LogMessage(const char* file, int line,
+ WarningTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+ LogMessage(const char* file, int line,
+ ErrorTag) ABSL_ATTRIBUTE_COLD ABSL_ATTRIBUTE_NOINLINE;
+ LogMessage(const LogMessage&) = delete;
+ LogMessage& operator=(const LogMessage&) = delete;
+ ~LogMessage() ABSL_ATTRIBUTE_COLD;
+
+ // Overrides the location inferred from the callsite. The string pointed to
+ // by `file` must be valid until the end of the statement.
+ LogMessage& AtLocation(absl::string_view file, int line);
+ // Omits the prefix from this line. The prefix includes metadata about the
+ // logged data such as source code location and timestamp.
+ LogMessage& NoPrefix();
+ // Sets the verbosity field of the logged message as if it was logged by
+ // `VLOG(verbose_level)`. Unlike `VLOG`, this method does not affect
+ // evaluation of the statement when the specified `verbose_level` has been
+ // disabled. The only effect is on `absl::LogSink` implementations which
+ // make use of the `absl::LogSink::verbosity()` value. The value
+ // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
+ // not verbose.
+ LogMessage& WithVerbosity(int verbose_level);
+ // Uses the specified timestamp instead of one collected in the constructor.
+ LogMessage& WithTimestamp(absl::Time timestamp);
+ // Uses the specified thread ID instead of one collected in the constructor.
+ LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
+ // Copies all metadata (but no data) from the specified `absl::LogEntry`.
+ LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
+ // Appends to the logged message a colon, a space, a textual description of
+ // the current value of `errno` (as by strerror(3)), and the numerical value
+ // of `errno`.
+ LogMessage& WithPerror();
+ // Sends this message to `*sink` in addition to whatever other sinks it would
+ // otherwise have been sent to. `sink` must not be null.
+ LogMessage& ToSinkAlso(absl::LogSink* sink);
+ // Sends this message to `*sink` and no others. `sink` must not be null.
+ LogMessage& ToSinkOnly(absl::LogSink* sink);
+
+ // Don't call this method from outside this library.
+ LogMessage& InternalStream() { return *this; }
+
+ // By-value overloads for small, common types let us overlook common failures
+ // to define globals and static data members (i.e. in a .cc file).
+ // clang-format off
+ // The CUDA toolchain cannot handle these <<<'s:
+ LogMessage& operator<<(char v) { return operator<< <char>(v); }
+ LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
+ LogMessage& operator<<(unsigned char v) {
+ return operator<< <unsigned char>(v);
+ }
+ LogMessage& operator<<(signed short v) { // NOLINT
+ return operator<< <signed short>(v); // NOLINT
+ }
+ LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
+ LogMessage& operator<<(signed long v) { // NOLINT
+ return operator<< <signed long>(v); // NOLINT
+ }
+ LogMessage& operator<<(signed long long v) { // NOLINT
+ return operator<< <signed long long>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned short v) { // NOLINT
+ return operator<< <unsigned short>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned int v) {
+ return operator<< <unsigned int>(v);
+ }
+ LogMessage& operator<<(unsigned long v) { // NOLINT
+ return operator<< <unsigned long>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned long long v) { // NOLINT
+ return operator<< <unsigned long long>(v); // NOLINT
+ }
+ LogMessage& operator<<(void* v) { return operator<< <void*>(v); }
+ LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); }
+ LogMessage& operator<<(float v) { return operator<< <float>(v); }
+ LogMessage& operator<<(double v) { return operator<< <double>(v); }
+ LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
+ // clang-format on
+
+ // These overloads are more efficient since no `ostream` is involved.
+ LogMessage& operator<<(const std::string& v);
+ LogMessage& operator<<(absl::string_view v);
+
+ // Handle stream manipulators e.g. std::endl.
+ LogMessage& operator<<(std::ostream& (*m)(std::ostream& os));
+ LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os));
+
+ // Literal strings. This allows us to record C string literals as literals in
+ // the logging.proto.Value.
+ //
+ // Allow this overload to be inlined to prevent generating instantiations of
+ // this template for every value of `SIZE` encountered in each source code
+ // file. That significantly increases linker input sizes. Inlining is cheap
+ // because the argument to this overload is almost always a string literal so
+ // the call to `strlen` can be replaced at compile time. The overload for
+ // `char[]` below should not be inlined. The compiler typically does not have
+ // the string at compile time and cannot replace the call to `strlen` so
+ // inlining it increases the binary size. See the discussion on
+ // cl/107527369.
+ template <int SIZE>
+ LogMessage& operator<<(const char (&buf)[SIZE]);
+
+ // This prevents non-const `char[]` arrays from looking like literals.
+ template <int SIZE>
+ LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
+
+ // 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
+ // because it breaks logging of non-integer bitfield types (i.e., enums).
+
+ protected:
+ // Call `abort()` or similar to perform `LOG(FATAL)` crash. It is assumed
+ // that the caller has already generated and written the trace as appropriate.
+ ABSL_ATTRIBUTE_NORETURN static void FailWithoutStackTrace();
+
+ // Similar to `FailWithoutStackTrace()`, but without `abort()`. Terminates
+ // the process with an error exit code.
+ ABSL_ATTRIBUTE_NORETURN static void FailQuietly();
+
+ // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
+ // This might as well be inlined into `~LogMessage` except that
+ // `~LogMessageFatal` needs to call it early.
+ void Flush();
+
+ // After this is called, failures are done as quiet as possible for this log
+ // message.
+ void SetFailQuietly();
+
+ private:
+ struct LogMessageData; // Opaque type containing message state
+ friend class AsLiteralImpl;
+ friend class StringifySink;
+
+ // This streambuf writes directly into the structured logging buffer so that
+ // arbitrary types can be encoded as string data (using
+ // `operator<<(std::ostream &, ...)` without any extra allocation or copying.
+ // Space is reserved before the data to store the length field, which is
+ // filled in by `~OstreamView`.
+ class OstreamView final : public std::streambuf {
+ public:
+ explicit OstreamView(LogMessageData& message_data);
+ ~OstreamView() override;
+ OstreamView(const OstreamView&) = delete;
+ OstreamView& operator=(const OstreamView&) = delete;
+ std::ostream& stream();
+
+ private:
+ LogMessageData& data_;
+ absl::Span<char> encoded_remaining_copy_;
+ absl::Span<char> message_start_;
+ absl::Span<char> string_start_;
+ };
+
+ enum class StringType {
+ kLiteral,
+ kNotLiteral,
+ };
+ template <StringType str_type>
+ void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE;
+ template <StringType str_type>
+ void CopyToEncodedBuffer(char ch, size_t num) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Returns `true` if the message is fatal or enabled debug-fatal.
+ bool IsFatal() const;
+
+ // Records some tombstone-type data in anticipation of `Die`.
+ void PrepareToDie();
+ void Die();
+
+ void SendToLog();
+
+ // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
+ void LogBacktraceIfNeeded();
+
+ // This should be the first data member so that its initializer captures errno
+ // before any other initializers alter it (e.g. with calls to new) and so that
+ // no other destructors run afterward an alter it (e.g. with calls to delete).
+ absl::base_internal::ErrnoSaver errno_saver_;
+
+ // We keep the data in a separate struct so that each instance of `LogMessage`
+ // uses less stack space.
+ std::unique_ptr<LogMessageData> data_;
+};
+
+// 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_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(ch,
+ count);
+ }
+
+ void Append(absl::string_view v) {
+ message_.CopyToEncodedBuffer<LogMessage::StringType::kNotLiteral>(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,
+ typename std::enable_if<!strings_internal::HasAbslStringify<T>::value,
+ int>::type>
+LogMessage& LogMessage::operator<<(const T& v) {
+ OstreamView view(*data_);
+ view.stream() << log_internal::NullGuard<T>().Guard(v);
+ return *this;
+}
+
+template <int SIZE>
+LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
+ CopyToEncodedBuffer<StringType::kLiteral>(buf);
+ return *this;
+}
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <int SIZE>
+LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
+ CopyToEncodedBuffer<StringType::kNotLiteral>(buf);
+ return *this;
+}
+// We instantiate these specializations in the library's TU to save space in
+// other TUs. Since the template is marked `ABSL_ATTRIBUTE_NOINLINE` we will be
+// emitting a function call either way.
+extern template LogMessage& LogMessage::operator<<(const char& v);
+extern template LogMessage& LogMessage::operator<<(const signed char& v);
+extern template LogMessage& LogMessage::operator<<(const unsigned char& v);
+extern template LogMessage& LogMessage::operator<<(const short& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+ const unsigned short& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(const int& v);
+extern template LogMessage& LogMessage::operator<<(
+ const unsigned int& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(const long& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+ const unsigned long& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+ const long long& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(
+ const unsigned long long& v); // NOLINT
+extern template LogMessage& LogMessage::operator<<(void* const& v);
+extern template LogMessage& LogMessage::operator<<(const void* const& v);
+extern template LogMessage& LogMessage::operator<<(const float& v);
+extern template LogMessage& LogMessage::operator<<(const double& v);
+extern template LogMessage& LogMessage::operator<<(const bool& v);
+
+extern template void LogMessage::CopyToEncodedBuffer<
+ LogMessage::StringType::kLiteral>(absl::string_view str);
+extern template void LogMessage::CopyToEncodedBuffer<
+ LogMessage::StringType::kNotLiteral>(absl::string_view str);
+extern template void
+LogMessage::CopyToEncodedBuffer<LogMessage::StringType::kLiteral>(char ch,
+ size_t num);
+extern template void LogMessage::CopyToEncodedBuffer<
+ LogMessage::StringType::kNotLiteral>(char ch, size_t num);
+
+// `LogMessageFatal` ensures the process will exit in failure after logging this
+// message.
+class LogMessageFatal final : public LogMessage {
+ public:
+ LogMessageFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+ LogMessageFatal(const char* file, int line,
+ absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+ ABSL_ATTRIBUTE_NORETURN ~LogMessageFatal();
+};
+
+class LogMessageQuietlyFatal final : public LogMessage {
+ public:
+ LogMessageQuietlyFatal(const char* file, int line) ABSL_ATTRIBUTE_COLD;
+ LogMessageQuietlyFatal(const char* file, int line,
+ absl::string_view failure_msg) ABSL_ATTRIBUTE_COLD;
+ ABSL_ATTRIBUTE_NORETURN ~LogMessageQuietlyFatal();
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalOnFatalLogMessage)(const absl::LogEntry&);
+
+#endif // ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
diff --git a/abseil-cpp/absl/log/internal/log_sink_set.cc b/abseil-cpp/absl/log/internal/log_sink_set.cc
new file mode 100644
index 0000000..b7cbe36
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_sink_set.cc
@@ -0,0 +1,296 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_sink_set.h"
+
+#ifndef ABSL_HAVE_THREAD_LOCAL
+#include <pthread.h>
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <algorithm>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/cleanup/cleanup.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// Returns a mutable reference to a thread-local variable that should be true if
+// a globally-registered `LogSink`'s `Send()` is currently being invoked on this
+// thread.
+bool& ThreadIsLoggingStatus() {
+#ifdef ABSL_HAVE_THREAD_LOCAL
+ ABSL_CONST_INIT thread_local bool thread_is_logging = false;
+ return thread_is_logging;
+#else
+ ABSL_CONST_INIT static pthread_key_t thread_is_logging_key;
+ static const bool unused = [] {
+ if (pthread_key_create(&thread_is_logging_key, [](void* data) {
+ delete reinterpret_cast<bool*>(data);
+ })) {
+ perror("pthread_key_create failed!");
+ abort();
+ }
+ return true;
+ }();
+ (void)unused; // Fixes -wunused-variable warning
+ bool* thread_is_logging_ptr =
+ reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));
+
+ if (ABSL_PREDICT_FALSE(!thread_is_logging_ptr)) {
+ thread_is_logging_ptr = new bool{false};
+ if (pthread_setspecific(thread_is_logging_key, thread_is_logging_ptr)) {
+ perror("pthread_setspecific failed");
+ abort();
+ }
+ }
+ return *thread_is_logging_ptr;
+#endif
+}
+
+class StderrLogSink final : public LogSink {
+ public:
+ ~StderrLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ if (entry.log_severity() < absl::StderrThreshold() &&
+ absl::log_internal::IsInitialized()) {
+ return;
+ }
+
+ ABSL_CONST_INIT static absl::once_flag warn_if_not_initialized;
+ absl::call_once(warn_if_not_initialized, []() {
+ if (absl::log_internal::IsInitialized()) return;
+ const char w[] =
+ "WARNING: All log messages before absl::InitializeLog() is called"
+ " are written to STDERR\n";
+ absl::log_internal::WriteToStderr(w, absl::LogSeverity::kWarning);
+ });
+
+ if (!entry.stacktrace().empty()) {
+ absl::log_internal::WriteToStderr(entry.stacktrace(),
+ entry.log_severity());
+ } else {
+ // TODO(b/226937039): do this outside else condition once we avoid
+ // ReprintFatalMessage
+ absl::log_internal::WriteToStderr(
+ entry.text_message_with_prefix_and_newline(), entry.log_severity());
+ }
+ }
+};
+
+#if defined(__ANDROID__)
+class AndroidLogSink final : public LogSink {
+ public:
+ ~AndroidLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ const int level = AndroidLogLevel(entry);
+ const char* const tag = GetAndroidNativeTag();
+ __android_log_write(level, tag,
+ entry.text_message_with_prefix_and_newline_c_str());
+ if (entry.log_severity() == absl::LogSeverity::kFatal)
+ __android_log_write(ANDROID_LOG_FATAL, tag, "terminating.\n");
+ }
+
+ private:
+ static int AndroidLogLevel(const absl::LogEntry& entry) {
+ switch (entry.log_severity()) {
+ case absl::LogSeverity::kFatal:
+ return ANDROID_LOG_FATAL;
+ case absl::LogSeverity::kError:
+ return ANDROID_LOG_ERROR;
+ case absl::LogSeverity::kWarning:
+ return ANDROID_LOG_WARN;
+ default:
+ if (entry.verbosity() >= 2) return ANDROID_LOG_VERBOSE;
+ if (entry.verbosity() == 1) return ANDROID_LOG_DEBUG;
+ return ANDROID_LOG_INFO;
+ }
+ }
+};
+#endif // !defined(__ANDROID__)
+
+#if defined(_WIN32)
+class WindowsDebuggerLogSink final : public LogSink {
+ public:
+ ~WindowsDebuggerLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ if (entry.log_severity() < absl::StderrThreshold() &&
+ absl::log_internal::IsInitialized()) {
+ return;
+ }
+ ::OutputDebugStringA(entry.text_message_with_prefix_and_newline_c_str());
+ }
+};
+#endif // !defined(_WIN32)
+
+class GlobalLogSinkSet final {
+ public:
+ GlobalLogSinkSet() {
+#if defined(__myriad2__) || defined(__Fuchsia__)
+ // myriad2 and Fuchsia do not log to stderr by default.
+#else
+ static StderrLogSink* stderr_log_sink = new StderrLogSink;
+ AddLogSink(stderr_log_sink);
+#endif
+#ifdef __ANDROID__
+ static AndroidLogSink* android_log_sink = new AndroidLogSink;
+ AddLogSink(android_log_sink);
+#endif
+#if defined(_WIN32)
+ static WindowsDebuggerLogSink* debugger_log_sink =
+ new WindowsDebuggerLogSink;
+ AddLogSink(debugger_log_sink);
+#endif // !defined(_WIN32)
+ }
+
+ void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only)
+ ABSL_LOCKS_EXCLUDED(guard_) {
+ SendToSinks(entry, extra_sinks);
+
+ if (!extra_sinks_only) {
+ if (ThreadIsLoggingToLogSink()) {
+ absl::log_internal::WriteToStderr(
+ entry.text_message_with_prefix_and_newline(), entry.log_severity());
+ } else {
+ absl::ReaderMutexLock global_sinks_lock(&guard_);
+ ThreadIsLoggingStatus() = true;
+ // Ensure the "thread is logging" status is reverted upon leaving the
+ // scope even in case of exceptions.
+ auto status_cleanup =
+ absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+ SendToSinks(entry, absl::MakeSpan(sinks_));
+ }
+ }
+ }
+
+ void AddLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+ {
+ absl::WriterMutexLock global_sinks_lock(&guard_);
+ auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+ if (pos == sinks_.end()) {
+ sinks_.push_back(sink);
+ return;
+ }
+ }
+ ABSL_INTERNAL_LOG(FATAL, "Duplicate log sinks are not supported");
+ }
+
+ void RemoveLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+ {
+ absl::WriterMutexLock global_sinks_lock(&guard_);
+ auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+ if (pos != sinks_.end()) {
+ sinks_.erase(pos);
+ return;
+ }
+ }
+ ABSL_INTERNAL_LOG(FATAL, "Mismatched log sink being removed");
+ }
+
+ void FlushLogSinks() ABSL_LOCKS_EXCLUDED(guard_) {
+ if (ThreadIsLoggingToLogSink()) {
+ // The thread_local condition demonstrates that we're already holding the
+ // lock in order to iterate over `sinks_` for dispatch. The thread-safety
+ // annotations don't know this, so we use `ABSL_NO_THREAD_SAFETY_ANALYSIS`
+ guard_.AssertReaderHeld();
+ FlushLogSinksLocked();
+ } else {
+ absl::ReaderMutexLock global_sinks_lock(&guard_);
+ // In case if LogSink::Flush overload decides to log
+ ThreadIsLoggingStatus() = true;
+ // Ensure the "thread is logging" status is reverted upon leaving the
+ // scope even in case of exceptions.
+ auto status_cleanup =
+ absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+ FlushLogSinksLocked();
+ }
+ }
+
+ private:
+ void FlushLogSinksLocked() ABSL_SHARED_LOCKS_REQUIRED(guard_) {
+ for (absl::LogSink* sink : sinks_) {
+ sink->Flush();
+ }
+ }
+
+ // Helper routine for LogToSinks.
+ static void SendToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> sinks) {
+ for (absl::LogSink* sink : sinks) {
+ sink->Send(entry);
+ }
+ }
+
+ using LogSinksSet = std::vector<absl::LogSink*>;
+ absl::Mutex guard_;
+ LogSinksSet sinks_ ABSL_GUARDED_BY(guard_);
+};
+
+// Returns reference to the global LogSinks set.
+GlobalLogSinkSet& GlobalSinks() {
+ static GlobalLogSinkSet* global_sinks = new GlobalLogSinkSet;
+ return *global_sinks;
+}
+
+} // namespace
+
+bool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); }
+
+void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only) {
+ log_internal::GlobalSinks().LogToSinks(entry, extra_sinks, extra_sinks_only);
+}
+
+void AddLogSink(absl::LogSink* sink) {
+ log_internal::GlobalSinks().AddLogSink(sink);
+}
+
+void RemoveLogSink(absl::LogSink* sink) {
+ log_internal::GlobalSinks().RemoveLogSink(sink);
+}
+
+void FlushLogSinks() { log_internal::GlobalSinks().FlushLogSinks(); }
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/log_sink_set.h b/abseil-cpp/absl/log/internal/log_sink_set.h
new file mode 100644
index 0000000..88ab073
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/log_sink_set.h
@@ -0,0 +1,54 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_sink_set.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+#define ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+
+#include "absl/base/config.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Returns true if a globally-registered `LogSink`'s `Send()` is currently
+// being invoked on this thread.
+bool ThreadIsLoggingToLogSink();
+
+// This function may log to two sets of sinks:
+//
+// * If `extra_sinks_only` is true, it will dispatch only to `extra_sinks`.
+// `LogMessage::ToSinkAlso` and `LogMessage::ToSinkOnly` are used to attach
+// extra sinks to the entry.
+// * Otherwise it will also log to the global sinks set. This set is managed
+// by `absl::AddLogSink` and `absl::RemoveLogSink`.
+void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only);
+
+// Implementation for operations with log sink set.
+void AddLogSink(absl::LogSink* sink);
+void RemoveLogSink(absl::LogSink* sink);
+void FlushLogSinks();
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
diff --git a/abseil-cpp/absl/log/internal/nullguard.cc b/abseil-cpp/absl/log/internal/nullguard.cc
new file mode 100644
index 0000000..3296c01
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/nullguard.cc
@@ -0,0 +1,35 @@
+// Copyright 2023 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/nullguard.h"
+
+#include <array>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+ABSL_CONST_INIT ABSL_DLL const std::array<char, 7> kCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+ABSL_CONST_INIT ABSL_DLL const std::array<signed char, 7> kSignedCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+ABSL_CONST_INIT ABSL_DLL const std::array<unsigned char, 7> kUnsignedCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/nullguard.h b/abseil-cpp/absl/log/internal/nullguard.h
new file mode 100644
index 0000000..623943c
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/nullguard.h
@@ -0,0 +1,88 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullguard.h
+// -----------------------------------------------------------------------------
+//
+// NullGuard exists such that NullGuard<T>::Guard(v) returns v, unless passed a
+// nullptr_t, or a null char* or const char*, in which case it returns "(null)".
+// This allows streaming NullGuard<T>::Guard(v) to an output stream without
+// hitting undefined behavior for null values.
+
+#ifndef ABSL_LOG_INTERNAL_NULLGUARD_H_
+#define ABSL_LOG_INTERNAL_NULLGUARD_H_
+
+#include <array>
+#include <cstddef>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+ABSL_CONST_INIT ABSL_DLL extern const std::array<char, 7> kCharNull;
+ABSL_CONST_INIT ABSL_DLL extern const std::array<signed char, 7>
+ kSignedCharNull;
+ABSL_CONST_INIT ABSL_DLL extern const std::array<unsigned char, 7>
+ kUnsignedCharNull;
+
+template <typename T>
+struct NullGuard final {
+ static const T& Guard(const T& v) { return v; }
+};
+template <>
+struct NullGuard<char*> final {
+ static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
+};
+template <>
+struct NullGuard<const char*> final {
+ static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
+};
+template <>
+struct NullGuard<signed char*> final {
+ static const signed char* Guard(const signed char* v) {
+ return v ? v : kSignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<const signed char*> final {
+ static const signed char* Guard(const signed char* v) {
+ return v ? v : kSignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<unsigned char*> final {
+ static const unsigned char* Guard(const unsigned char* v) {
+ return v ? v : kUnsignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<const unsigned char*> final {
+ static const unsigned char* Guard(const unsigned char* v) {
+ return v ? v : kUnsignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<std::nullptr_t> final {
+ static const char* Guard(const std::nullptr_t&) { return kCharNull.data(); }
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_NULLGUARD_H_
diff --git a/abseil-cpp/absl/log/internal/nullstream.h b/abseil-cpp/absl/log/internal/nullstream.h
new file mode 100644
index 0000000..9266852
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/nullstream.h
@@ -0,0 +1,136 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullstream.h
+// -----------------------------------------------------------------------------
+//
+// Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal`
+// implement a subset of the `LogMessage` API and are used instead when logging
+// of messages has been disabled.
+
+#ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_
+#define ABSL_LOG_INTERNAL_NULLSTREAM_H_
+
+#ifdef _WIN32
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <ios>
+#include <ostream>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// A `NullStream` implements the API of `LogMessage` (a few methods and
+// `operator<<`) but does nothing. All methods are defined inline so the
+// compiler can eliminate the whole instance and discard anything that's
+// streamed in.
+class NullStream {
+ public:
+ NullStream& AtLocation(absl::string_view, int) { return *this; }
+ template <typename SourceLocationType>
+ NullStream& AtLocation(SourceLocationType) {
+ return *this;
+ }
+ NullStream& NoPrefix() { return *this; }
+ NullStream& WithVerbosity(int) { return *this; }
+ template <typename TimeType>
+ NullStream& WithTimestamp(TimeType) {
+ return *this;
+ }
+ template <typename Tid>
+ NullStream& WithThreadID(Tid) {
+ return *this;
+ }
+ template <typename LogEntryType>
+ NullStream& WithMetadataFrom(const LogEntryType&) {
+ return *this;
+ }
+ NullStream& WithPerror() { return *this; }
+ template <typename LogSinkType>
+ NullStream& ToSinkAlso(LogSinkType*) {
+ return *this;
+ }
+ template <typename LogSinkType>
+ NullStream& ToSinkOnly(LogSinkType*) {
+ return *this;
+ }
+ template <typename LogSinkType>
+ NullStream& OutputToSink(LogSinkType*, bool) {
+ return *this;
+ }
+ NullStream& InternalStream() { return *this; }
+};
+template <typename T>
+inline NullStream& operator<<(NullStream& str, const T&) {
+ return str;
+}
+inline NullStream& operator<<(NullStream& str,
+ std::ostream& (*)(std::ostream& os)) {
+ return str;
+}
+inline NullStream& operator<<(NullStream& str,
+ std::ios_base& (*)(std::ios_base& os)) {
+ return str;
+}
+
+// `NullStreamMaybeFatal` implements the process termination semantics of
+// `LogMessage`, which is used for `DFATAL` severity and expression-defined
+// severity e.g. `LOG(LEVEL(HowBadIsIt()))`. Like `LogMessage`, it terminates
+// the process when destroyed if the passed-in severity equals `FATAL`.
+class NullStreamMaybeFatal final : public NullStream {
+ public:
+ explicit NullStreamMaybeFatal(absl::LogSeverity severity)
+ : fatal_(severity == absl::LogSeverity::kFatal) {}
+ ~NullStreamMaybeFatal() {
+ if (fatal_) {
+ _exit(1);
+ }
+ }
+
+ private:
+ bool fatal_;
+};
+
+// `NullStreamFatal` implements the process termination semantics of
+// `LogMessageFatal`, which means it always terminates the process. `DFATAL`
+// and expression-defined severity use `NullStreamMaybeFatal` above.
+class NullStreamFatal final : public NullStream {
+ public:
+ NullStreamFatal() = default;
+ // ABSL_ATTRIBUTE_NORETURN doesn't seem to work on destructors with msvc, so
+ // disable msvc's warning about the d'tor never returning.
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(push)
+#pragma warning(disable : 4722)
+#endif
+ ABSL_ATTRIBUTE_NORETURN ~NullStreamFatal() { _exit(1); }
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma warning(pop)
+#endif
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_GLOBALS_H_
diff --git a/abseil-cpp/absl/log/internal/proto.cc b/abseil-cpp/absl/log/internal/proto.cc
new file mode 100644
index 0000000..eb699ae
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/proto.cc
@@ -0,0 +1,220 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/proto.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+void EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) {
+ for (size_t s = 0; s < size; s++) {
+ (*buf)[s] = static_cast<char>((value & 0x7f) | (s + 1 == size ? 0 : 0x80));
+ value >>= 7;
+ }
+ buf->remove_prefix(size);
+}
+constexpr uint64_t MakeTagType(uint64_t tag, WireType type) {
+ return tag << 3 | static_cast<uint64_t>(type);
+}
+} // namespace
+
+bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kVarint);
+ const size_t tag_type_size = VarintSize(tag_type);
+ const size_t value_size = VarintSize(value);
+ if (tag_type_size + value_size > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(value, value_size, buf);
+ return true;
+}
+
+bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::k64Bit);
+ const size_t tag_type_size = VarintSize(tag_type);
+ if (tag_type_size + sizeof(value) > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ for (size_t s = 0; s < sizeof(value); s++) {
+ (*buf)[s] = static_cast<char>(value & 0xff);
+ value >>= 8;
+ }
+ buf->remove_prefix(sizeof(value));
+ return true;
+}
+
+bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::k32Bit);
+ const size_t tag_type_size = VarintSize(tag_type);
+ if (tag_type_size + sizeof(value) > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ for (size_t s = 0; s < sizeof(value); s++) {
+ (*buf)[s] = static_cast<char>(value & 0xff);
+ value >>= 8;
+ }
+ buf->remove_prefix(sizeof(value));
+ return true;
+}
+
+bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ uint64_t length = value.size();
+ const size_t length_size = VarintSize(length);
+ if (tag_type_size + length_size + value.size() > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(length, length_size, buf);
+ memcpy(buf->data(), value.data(), value.size());
+ buf->remove_prefix(value.size());
+ return true;
+}
+
+bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ uint64_t length = value.size();
+ const size_t length_size =
+ VarintSize(std::min<uint64_t>(length, buf->size()));
+ if (tag_type_size + length_size <= buf->size() &&
+ tag_type_size + length_size + value.size() > buf->size()) {
+ value.remove_suffix(tag_type_size + length_size + value.size() -
+ buf->size());
+ length = value.size();
+ }
+ if (tag_type_size + length_size + value.size() > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(length, length_size, buf);
+ memcpy(buf->data(), value.data(), value.size());
+ buf->remove_prefix(value.size());
+ return true;
+}
+
+ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(
+ uint64_t tag, uint64_t max_size, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ max_size = std::min<uint64_t>(max_size, buf->size());
+ const size_t length_size = VarintSize(max_size);
+ if (tag_type_size + length_size > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return absl::Span<char>();
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ const absl::Span<char> ret = buf->subspan(0, length_size);
+ EncodeRawVarint(0, length_size, buf);
+ return ret;
+}
+
+void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {
+ if (!msg.data()) return;
+ assert(buf->data() >= msg.data());
+ if (buf->data() < msg.data()) return;
+ EncodeRawVarint(
+ static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),
+ msg.size(), &msg);
+}
+
+namespace {
+uint64_t DecodeVarint(absl::Span<const char> *buf) {
+ uint64_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)
+ << 7 * s;
+ if (!((*buf)[s++] & 0x80)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+
+uint64_t Decode64Bit(absl::Span<const char> *buf) {
+ uint64_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))
+ << 8 * s;
+ if (++s == sizeof(value)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+
+uint32_t Decode32Bit(absl::Span<const char> *buf) {
+ uint32_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))
+ << 8 * s;
+ if (++s == sizeof(value)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+} // namespace
+
+bool ProtoField::DecodeFrom(absl::Span<const char> *data) {
+ if (data->empty()) return false;
+ const uint64_t tag_type = DecodeVarint(data);
+ tag_ = tag_type >> 3;
+ type_ = static_cast<WireType>(tag_type & 0x07);
+ switch (type_) {
+ case WireType::kVarint:
+ value_ = DecodeVarint(data);
+ break;
+ case WireType::k64Bit:
+ value_ = Decode64Bit(data);
+ break;
+ case WireType::kLengthDelimited: {
+ value_ = DecodeVarint(data);
+ data_ = data->subspan(
+ 0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));
+ data->remove_prefix(data_.size());
+ break;
+ }
+ case WireType::k32Bit:
+ value_ = Decode32Bit(data);
+ break;
+ }
+ return true;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/proto.h b/abseil-cpp/absl/log/internal/proto.h
new file mode 100644
index 0000000..c8d14ac
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/proto.h
@@ -0,0 +1,288 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// -----------------------------------------------------------------------------
+// File: internal/proto.h
+// -----------------------------------------------------------------------------
+//
+// Declares functions for serializing and deserializing data to and from memory
+// buffers in protocol buffer wire format. This library takes no steps to
+// ensure that the encoded data matches with any message specification.
+
+#ifndef ABSL_LOG_INTERNAL_PROTO_H_
+#define ABSL_LOG_INTERNAL_PROTO_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// absl::Span<char> represents a view into the available space in a mutable
+// buffer during encoding. Encoding functions shrink the span as they go so
+// that the same view can be passed to a series of Encode functions. If the
+// data do not fit, nothing is encoded, the view is set to size zero (so that
+// all subsequent encode calls fail), and false is returned. Otherwise true is
+// returned.
+
+// In particular, attempting to encode a series of data into an insufficient
+// buffer has consistent and efficient behavior without any caller-side error
+// checking. Individual values will be encoded in their entirety or not at all
+// (unless one of the `Truncate` functions is used). Once a value is omitted
+// because it does not fit, no subsequent values will be encoded to preserve
+// ordering; the decoded sequence will be a prefix of the original sequence.
+
+// There are two ways to encode a message-typed field:
+//
+// * Construct its contents in a separate buffer and use `EncodeBytes` to copy
+// it into the primary buffer with type, tag, and length.
+// * Use `EncodeMessageStart` to write type and tag fields and reserve space for
+// the length field, then encode the contents directly into the buffer, then
+// use `EncodeMessageLength` to write the actual length into the reserved
+// bytes. This works fine if the actual length takes fewer bytes to encode
+// than were reserved, although you don't get your extra bytes back.
+// This approach will always produce a valid encoding, but your protocol may
+// require that the whole message field by omitted if the buffer is too small
+// to contain all desired subfields. In this case, operate on a copy of the
+// buffer view and assign back only if everything fit, i.e. if the last
+// `Encode` call returned true.
+
+// Encodes the specified integer as a varint field and returns true if it fits.
+// Used for int32_t, int64_t, uint32_t, uint64_t, bool, and enum field types.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf);
+inline bool EncodeVarint(uint64_t tag, int64_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool EncodeVarint(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool EncodeVarint(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a varint field using ZigZag encoding and
+// returns true if it fits.
+// Used for sint32 and sint64 field types.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+inline bool EncodeVarintZigZag(uint64_t tag, int64_t value,
+ absl::Span<char> *buf) {
+ if (value < 0)
+ return EncodeVarint(tag, 2 * static_cast<uint64_t>(-(value + 1)) + 1, buf);
+ return EncodeVarint(tag, 2 * static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a 64-bit field and returns true if it fits.
+// Used for fixed64 and sfixed64 field types.
+// Consumes up to kMaxVarintSize + 8 bytes (18).
+bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf);
+inline bool Encode64Bit(uint64_t tag, int64_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool Encode64Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool Encode64Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified double as a 64-bit field and returns true if it fits.
+// Used for double field type.
+// Consumes up to kMaxVarintSize + 8 bytes (18).
+inline bool EncodeDouble(uint64_t tag, double value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, absl::bit_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a 32-bit field and returns true if it fits.
+// Used for fixed32 and sfixed32 field types.
+// Consumes up to kMaxVarintSize + 4 bytes (14).
+bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf);
+inline bool Encode32Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return Encode32Bit(tag, static_cast<uint32_t>(value), buf);
+}
+
+// Encodes the specified float as a 32-bit field and returns true if it fits.
+// Used for float field type.
+// Consumes up to kMaxVarintSize + 4 bytes (14).
+inline bool EncodeFloat(uint64_t tag, float value, absl::Span<char> *buf) {
+ return Encode32Bit(tag, absl::bit_cast<uint32_t>(value), buf);
+}
+
+// Encodes the specified bytes as a length-delimited field and returns true if
+// they fit.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf);
+
+// Encodes as many of the specified bytes as will fit as a length-delimited
+// field and returns true as long as the field header (`tag_type` and `length`)
+// fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf);
+
+// Encodes the specified string as a length-delimited field and returns true if
+// it fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+inline bool EncodeString(uint64_t tag, absl::string_view value,
+ absl::Span<char> *buf) {
+ return EncodeBytes(tag, value, buf);
+}
+
+// Encodes as much of the specified string as will fit as a length-delimited
+// field and returns true as long as the field header (`tag_type` and `length`)
+// fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+inline bool EncodeStringTruncate(uint64_t tag, absl::string_view value,
+ absl::Span<char> *buf) {
+ return EncodeBytesTruncate(tag, value, buf);
+}
+
+// Encodes the header for a length-delimited field containing up to `max_size`
+// bytes or the number remaining in the buffer, whichever is less. If the
+// header fits, a non-nullptr `Span` is returned; this must be passed to
+// `EncodeMessageLength` after all contents are encoded to finalize the length
+// field. If the header does not fit, a nullptr `Span` is returned which is
+// safe to pass to `EncodeMessageLength` but need not be.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(uint64_t tag,
+ uint64_t max_size,
+ absl::Span<char> *buf);
+
+// Finalizes the length field in `msg` so that it encompasses all data encoded
+// since the call to `EncodeMessageStart` which returned `msg`. Does nothing if
+// `msg` is a `nullptr` `Span`.
+void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf);
+
+enum class WireType : uint64_t {
+ kVarint = 0,
+ k64Bit = 1,
+ kLengthDelimited = 2,
+ k32Bit = 5,
+};
+
+constexpr size_t VarintSize(uint64_t value) {
+ return value < 128 ? 1 : 1 + VarintSize(value >> 7);
+}
+constexpr size_t MinVarintSize() {
+ return VarintSize((std::numeric_limits<uint64_t>::min)());
+}
+constexpr size_t MaxVarintSize() {
+ return VarintSize((std::numeric_limits<uint64_t>::max)());
+}
+
+constexpr uint64_t MaxVarintForSize(size_t size) {
+ return size >= 10 ? (std::numeric_limits<uint64_t>::max)()
+ : (static_cast<uint64_t>(1) << size * 7) - 1;
+}
+
+// `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to
+// store encoded fields of the specified WireTypes regardless of tag numbers and
+// data values. This only makes sense for `WireType::kLengthDelimited` if you
+// add in the length of the contents yourself, e.g. for string and bytes fields
+// by adding the lengths of any encoded strings to the return value or for
+// submessage fields by enumerating the fields you may encode into their
+// contents.
+constexpr size_t BufferSizeFor() { return 0; }
+template <typename... T>
+constexpr size_t BufferSizeFor(WireType type, T... tail) {
+ // tag_type + data + ...
+ return MaxVarintSize() +
+ (type == WireType::kVarint ? MaxVarintSize() : //
+ type == WireType::k64Bit ? 8 : //
+ type == WireType::k32Bit ? 4 : MaxVarintSize()) + //
+ BufferSizeFor(tail...);
+}
+
+// absl::Span<const char> represents a view into the un-processed space in a
+// buffer during decoding. Decoding functions shrink the span as they go so
+// that the same view can be decoded iteratively until all data are processed.
+// In general, if the buffer is exhausted but additional bytes are expected by
+// the decoder, it will return values as if the additional bytes were zeros.
+// Length-delimited fields are an exception - if the encoded length field
+// indicates more data bytes than are available in the buffer, the `bytes_value`
+// and `string_value` accessors will return truncated views.
+
+class ProtoField final {
+ public:
+ // Consumes bytes from `data` and returns true if there were any bytes to
+ // decode.
+ bool DecodeFrom(absl::Span<const char> *data);
+ uint64_t tag() const { return tag_; }
+ WireType type() const { return type_; }
+
+ // These value accessors will return nonsense if the data were not encoded in
+ // the corresponding wiretype from the corresponding C++ (or other language)
+ // type.
+
+ double double_value() const { return absl::bit_cast<double>(value_); }
+ float float_value() const {
+ return absl::bit_cast<float>(static_cast<uint32_t>(value_));
+ }
+ int32_t int32_value() const { return static_cast<int32_t>(value_); }
+ int64_t int64_value() const { return static_cast<int64_t>(value_); }
+ int32_t sint32_value() const {
+ if (value_ % 2) return static_cast<int32_t>(0 - ((value_ - 1) / 2) - 1);
+ return static_cast<int32_t>(value_ / 2);
+ }
+ int64_t sint64_value() const {
+ if (value_ % 2) return 0 - ((value_ - 1) / 2) - 1;
+ return value_ / 2;
+ }
+ uint32_t uint32_value() const { return static_cast<uint32_t>(value_); }
+ uint64_t uint64_value() const { return value_; }
+ bool bool_value() const { return value_ != 0; }
+ // To decode an enum, call int32_value() and cast to the appropriate type.
+ // Note that the official C++ proto compiler treats enum fields with values
+ // that do not correspond to a defined enumerator as unknown fields.
+
+ // To decode fields within a submessage field, call
+ // `DecodeNextField(field.BytesValue())`.
+ absl::Span<const char> bytes_value() const { return data_; }
+ absl::string_view string_value() const {
+ const auto data = bytes_value();
+ return absl::string_view(data.data(), data.size());
+ }
+ // Returns the encoded length of a length-delimited field. This equals
+ // `bytes_value().size()` except when the latter has been truncated due to
+ // buffer underrun.
+ uint64_t encoded_length() const { return value_; }
+
+ private:
+ uint64_t tag_;
+ WireType type_;
+ // For `kTypeVarint`, `kType64Bit`, and `kType32Bit`, holds the decoded value.
+ // For `kTypeLengthDelimited`, holds the decoded length.
+ uint64_t value_;
+ absl::Span<const char> data_;
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_PROTO_H_
diff --git a/abseil-cpp/absl/log/internal/stderr_log_sink_test.cc b/abseil-cpp/absl/log/internal/stderr_log_sink_test.cc
new file mode 100644
index 0000000..763690d
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/stderr_log_sink_test.cc
@@ -0,0 +1,105 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdlib.h>
+
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log.h"
+
+namespace {
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+
+auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment(
+ new absl::log_internal::LogTestEnvironment);
+
+MATCHER_P2(HasSubstrTimes, substr, expected_count, "") {
+ int count = 0;
+ std::string::size_type pos = 0;
+ std::string needle(substr);
+ while ((pos = arg.find(needle, pos)) != std::string::npos) {
+ ++count;
+ pos += needle.size();
+ }
+
+ return count == expected_count;
+}
+
+TEST(StderrLogSinkDeathTest, InfoMessagesInStderr) {
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+ LOG(INFO) << "INFO message";
+ exit(1);
+ },
+ "INFO message");
+}
+
+TEST(StderrLogSinkDeathTest, WarningMessagesInStderr) {
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+ LOG(WARNING) << "WARNING message";
+ exit(1);
+ },
+ "WARNING message");
+}
+
+TEST(StderrLogSinkDeathTest, ErrorMessagesInStderr) {
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+ LOG(ERROR) << "ERROR message";
+ exit(1);
+ },
+ "ERROR message");
+}
+
+TEST(StderrLogSinkDeathTest, FatalMessagesInStderr) {
+ char message[] = "FATAL message";
+ char stacktrace[] = "*** Check failure stack trace: ***";
+
+ int expected_count = 1;
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+ LOG(FATAL) << message;
+ },
+ AllOf(HasSubstrTimes(message, expected_count), HasSubstr(stacktrace)));
+}
+
+TEST(StderrLogSinkDeathTest, SecondaryFatalMessagesInStderr) {
+ auto MessageGen = []() -> std::string {
+ LOG(FATAL) << "Internal failure";
+ return "External failure";
+ };
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ {
+ absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfo);
+ LOG(FATAL) << MessageGen();
+ },
+ "Internal failure");
+}
+
+} // namespace
diff --git a/abseil-cpp/absl/log/internal/strip.h b/abseil-cpp/absl/log/internal/strip.h
new file mode 100644
index 0000000..adc86ff
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/strip.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/strip.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_STRIP_H_
+#define ABSL_LOG_INTERNAL_STRIP_H_
+
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/nullstream.h"
+
+// `ABSL_LOGGING_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or
+// to a related object with a compatible API but different behavior. This set
+// of defines comes in three flavors: vanilla, plus two variants that strip some
+// logging in subtly different ways for subtly different reasons (see below).
+#if defined(STRIP_LOG) && STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+ ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+ ::absl::log_internal::NullStreamMaybeFatal(log_internal_severity)
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+ ABSL_LOGGING_INTERNAL_LOG_QFATAL
+#else // !defined(STRIP_LOG) || !STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO \
+ ::absl::log_internal::LogMessage( \
+ __FILE__, __LINE__, ::absl::log_internal::LogMessage::InfoTag{})
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING \
+ ::absl::log_internal::LogMessage( \
+ __FILE__, __LINE__, ::absl::log_internal::LogMessage::WarningTag{})
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR \
+ ::absl::log_internal::LogMessage( \
+ __FILE__, __LINE__, ::absl::log_internal::LogMessage::ErrorTag{})
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL \
+ ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL \
+ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, log_internal_severity)
+// These special cases dispatch to special-case constructors that allow us to
+// avoid an extra function call and shrink non-LTO binaries by a percent or so.
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) \
+ ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__, failure_message)
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__, \
+ failure_message)
+#endif // !defined(STRIP_LOG) || !STRIP_LOG
+
+#endif // ABSL_LOG_INTERNAL_STRIP_H_
diff --git a/abseil-cpp/absl/log/internal/structured.h b/abseil-cpp/absl/log/internal/structured.h
new file mode 100644
index 0000000..5223dbc
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/structured.h
@@ -0,0 +1,58 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/structured.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_STRUCTURED_H_
+#define ABSL_LOG_INTERNAL_STRUCTURED_H_
+
+#include <ostream>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class ABSL_MUST_USE_RESULT AsLiteralImpl final {
+ public:
+ explicit AsLiteralImpl(absl::string_view str) : str_(str) {}
+ AsLiteralImpl(const AsLiteralImpl&) = default;
+ AsLiteralImpl& operator=(const AsLiteralImpl&) = default;
+
+ private:
+ absl::string_view str_;
+
+ friend std::ostream& operator<<(std::ostream& os, AsLiteralImpl as_literal) {
+ return os << as_literal.str_;
+ }
+ void AddToMessage(log_internal::LogMessage& m) {
+ m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);
+ }
+ friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,
+ AsLiteralImpl as_literal) {
+ as_literal.AddToMessage(m);
+ return m;
+ }
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_STRUCTURED_H_
diff --git a/abseil-cpp/absl/log/internal/test_actions.cc b/abseil-cpp/absl/log/internal/test_actions.cc
new file mode 100644
index 0000000..bdfd637
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_actions.cc
@@ -0,0 +1,75 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/test_actions.h"
+
+#include <cassert>
+#include <iostream>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+void WriteToStderrWithFilename::operator()(const absl::LogEntry& entry) const {
+ std::cerr << message << " (file: " << entry.source_filename() << ")\n";
+}
+
+void WriteEntryToStderr::operator()(const absl::LogEntry& entry) const {
+ if (!message.empty()) std::cerr << message << "\n";
+
+ const std::string source_filename = absl::CHexEscape(entry.source_filename());
+ const std::string source_basename = absl::CHexEscape(entry.source_basename());
+ const std::string text_message = absl::CHexEscape(entry.text_message());
+ const std::string encoded_message = absl::CHexEscape(entry.encoded_message());
+ std::string encoded_message_str;
+ std::cerr << "LogEntry{\n" //
+ << " source_filename: \"" << source_filename << "\"\n" //
+ << " source_basename: \"" << source_basename << "\"\n" //
+ << " source_line: " << entry.source_line() << "\n" //
+ << " prefix: " << (entry.prefix() ? "true\n" : "false\n") //
+ << " log_severity: " << entry.log_severity() << "\n" //
+ << " timestamp: " << entry.timestamp() << "\n" //
+ << " text_message: \"" << text_message << "\"\n" //
+ << " verbosity: " << entry.verbosity() << "\n" //
+ << " encoded_message (raw): \"" << encoded_message << "\"\n" //
+ << encoded_message_str //
+ << "}\n";
+}
+
+void WriteEntryToStderr::operator()(absl::LogSeverity severity,
+ absl::string_view filename,
+ absl::string_view log_message) const {
+ if (!message.empty()) std::cerr << message << "\n";
+ const std::string source_filename = absl::CHexEscape(filename);
+ const std::string text_message = absl::CHexEscape(log_message);
+ std::cerr << "LogEntry{\n" //
+ << " source_filename: \"" << source_filename << "\"\n" //
+ << " log_severity: " << severity << "\n" //
+ << " text_message: \"" << text_message << "\"\n" //
+ << "}\n";
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/test_actions.h b/abseil-cpp/absl/log/internal/test_actions.h
new file mode 100644
index 0000000..649a050
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_actions.h
@@ -0,0 +1,90 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_actions.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's actions used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+#define ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// These actions are used by the child process in a death test.
+//
+// Expectations set in the child cannot cause test failure in the parent
+// directly. Instead, the child can use these actions with
+// `EXPECT_CALL`/`WillOnce` and `ON_CALL`/`WillByDefault` (for unexpected calls)
+// to write messages to stderr that the parent can match against.
+struct WriteToStderr final {
+ explicit WriteToStderr(absl::string_view m) : message(m) {}
+ std::string message;
+
+ template <typename... Args>
+ void operator()(const Args&...) const {
+ std::cerr << message << std::endl;
+ }
+};
+
+struct WriteToStderrWithFilename final {
+ explicit WriteToStderrWithFilename(absl::string_view m) : message(m) {}
+
+ std::string message;
+
+ void operator()(const absl::LogEntry& entry) const;
+};
+
+struct WriteEntryToStderr final {
+ explicit WriteEntryToStderr(absl::string_view m) : message(m) {}
+
+ std::string message = "";
+
+ void operator()(const absl::LogEntry& entry) const;
+ void operator()(absl::LogSeverity, absl::string_view,
+ absl::string_view) const;
+};
+
+// See the documentation for `DeathTestValidateExpectations` above.
+// `DeathTestExpectedLogging` should be used once in a given death test, and the
+// applicable severity level is the one that should be passed to
+// `DeathTestValidateExpectations`.
+inline WriteEntryToStderr DeathTestExpectedLogging() {
+ return WriteEntryToStderr{"Mock received expected entry:"};
+}
+
+// `DeathTestUnexpectedLogging` should be used zero or more times to mark
+// messages that should not hit the logs as the process dies.
+inline WriteEntryToStderr DeathTestUnexpectedLogging() {
+ return WriteEntryToStderr{"Mock received unexpected entry:"};
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
diff --git a/abseil-cpp/absl/log/internal/test_helpers.cc b/abseil-cpp/absl/log/internal/test_helpers.cc
new file mode 100644
index 0000000..bfcc967
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_helpers.cc
@@ -0,0 +1,82 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "absl/log/internal/test_helpers.h"
+
+#ifdef __Fuchsia__
+#include <zircon/syscalls.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+#include "absl/log/initialize.h"
+#include "absl/log/internal/globals.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Returns false if the specified severity level is disabled by
+// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.
+bool LoggingEnabledAt(absl::LogSeverity severity) {
+ return severity >= kAbslMinLogLevel && severity >= absl::MinLogLevel();
+}
+
+// -----------------------------------------------------------------------------
+// Googletest Death Test Predicates
+// -----------------------------------------------------------------------------
+
+#if GTEST_HAS_DEATH_TEST
+
+bool DiedOfFatal(int exit_status) {
+#if defined(_WIN32)
+ // Depending on NDEBUG and (configuration?) MSVC's abort either results
+ // in error code 3 (SIGABRT) or error code 0x80000003 (breakpoint
+ // triggered).
+ return ::testing::ExitedWithCode(3)(exit_status & 0x7fffffff);
+#elif defined(__Fuchsia__)
+ // The Fuchsia death test implementation kill()'s the process when it detects
+ // an exception, so it should exit with the corresponding code. See
+ // FuchsiaDeathTest::Wait().
+ return ::testing::ExitedWithCode(ZX_TASK_RETCODE_SYSCALL_KILL)(exit_status);
+#elif defined(__ANDROID__) && defined(__aarch64__)
+ // These are all run under a qemu config that eats died-due-to-signal exit
+ // statuses.
+ return true;
+#else
+ return ::testing::KilledBySignal(SIGABRT)(exit_status);
+#endif
+}
+
+bool DiedOfQFatal(int exit_status) {
+ return ::testing::ExitedWithCode(1)(exit_status);
+}
+
+#endif
+
+// -----------------------------------------------------------------------------
+// Helper for Log initialization in test
+// -----------------------------------------------------------------------------
+
+void LogTestEnvironment::SetUp() {
+ if (!absl::log_internal::IsInitialized()) {
+ absl::InitializeLog();
+ }
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/test_helpers.h b/abseil-cpp/absl/log/internal/test_helpers.h
new file mode 100644
index 0000000..714bc7b
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_helpers.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_helpers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares testing helpers for the logging library.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+#define ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// `ABSL_MIN_LOG_LEVEL` can't be used directly since it is not always defined.
+constexpr auto kAbslMinLogLevel =
+#ifdef ABSL_MIN_LOG_LEVEL
+ static_cast<absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL);
+#else
+ absl::LogSeverityAtLeast::kInfo;
+#endif
+
+// Returns false if the specified severity level is disabled by
+// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.
+bool LoggingEnabledAt(absl::LogSeverity severity);
+
+// -----------------------------------------------------------------------------
+// Googletest Death Test Predicates
+// -----------------------------------------------------------------------------
+
+#if GTEST_HAS_DEATH_TEST
+
+bool DiedOfFatal(int exit_status);
+bool DiedOfQFatal(int exit_status);
+
+#endif
+
+// -----------------------------------------------------------------------------
+// Helper for Log initialization in test
+// -----------------------------------------------------------------------------
+
+class LogTestEnvironment : public ::testing::Environment {
+ public:
+ ~LogTestEnvironment() override = default;
+
+ void SetUp() override;
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_HELPERS_H_
diff --git a/abseil-cpp/absl/log/internal/test_matchers.cc b/abseil-cpp/absl/log/internal/test_matchers.cc
new file mode 100644
index 0000000..8c6515c
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_matchers.cc
@@ -0,0 +1,217 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/test_matchers.h"
+
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Ge;
+using ::testing::HasSubstr;
+using ::testing::MakeMatcher;
+using ::testing::Matcher;
+using ::testing::MatcherInterface;
+using ::testing::MatchResultListener;
+using ::testing::Not;
+using ::testing::Property;
+using ::testing::ResultOf;
+using ::testing::Truly;
+
+class AsStringImpl final
+ : public MatcherInterface<absl::string_view> {
+ public:
+ explicit AsStringImpl(
+ const Matcher<const std::string&>& str_matcher)
+ : str_matcher_(str_matcher) {}
+ bool MatchAndExplain(
+ absl::string_view actual,
+ MatchResultListener* listener) const override {
+ return str_matcher_.MatchAndExplain(std::string(actual), listener);
+ }
+ void DescribeTo(std::ostream* os) const override {
+ return str_matcher_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ return str_matcher_.DescribeNegationTo(os);
+ }
+
+ private:
+ const Matcher<const std::string&> str_matcher_;
+};
+
+class MatchesOstreamImpl final
+ : public MatcherInterface<absl::string_view> {
+ public:
+ explicit MatchesOstreamImpl(std::string expected)
+ : expected_(std::move(expected)) {}
+ bool MatchAndExplain(absl::string_view actual,
+ MatchResultListener*) const override {
+ return actual == expected_;
+ }
+ void DescribeTo(std::ostream* os) const override {
+ *os << "matches the contents of the ostringstream, which are \""
+ << expected_ << "\"";
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not match the contents of the ostringstream, which are \""
+ << expected_ << "\"";
+ }
+
+ private:
+ const std::string expected_;
+};
+} // namespace
+
+Matcher<absl::string_view> AsString(
+ const Matcher<const std::string&>& str_matcher) {
+ return MakeMatcher(new AsStringImpl(str_matcher));
+}
+
+Matcher<const absl::LogEntry&> SourceFilename(
+ const Matcher<absl::string_view>& source_filename) {
+ return Property("source_filename", &absl::LogEntry::source_filename,
+ source_filename);
+}
+
+Matcher<const absl::LogEntry&> SourceBasename(
+ const Matcher<absl::string_view>& source_basename) {
+ return Property("source_basename", &absl::LogEntry::source_basename,
+ source_basename);
+}
+
+Matcher<const absl::LogEntry&> SourceLine(
+ const Matcher<int>& source_line) {
+ return Property("source_line", &absl::LogEntry::source_line, source_line);
+}
+
+Matcher<const absl::LogEntry&> Prefix(
+ const Matcher<bool>& prefix) {
+ return Property("prefix", &absl::LogEntry::prefix, prefix);
+}
+
+Matcher<const absl::LogEntry&> LogSeverity(
+ const Matcher<absl::LogSeverity>& log_severity) {
+ return Property("log_severity", &absl::LogEntry::log_severity, log_severity);
+}
+
+Matcher<const absl::LogEntry&> Timestamp(
+ const Matcher<absl::Time>& timestamp) {
+ return Property("timestamp", &absl::LogEntry::timestamp, timestamp);
+}
+
+Matcher<const absl::LogEntry&> TimestampInMatchWindow() {
+ return Property("timestamp", &absl::LogEntry::timestamp,
+ AllOf(Ge(absl::Now()), Truly([](absl::Time arg) {
+ return arg <= absl::Now();
+ })));
+}
+
+Matcher<const absl::LogEntry&> ThreadID(
+ const Matcher<absl::LogEntry::tid_t>& tid) {
+ return Property("tid", &absl::LogEntry::tid, tid);
+}
+
+Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
+ const Matcher<absl::string_view>&
+ text_message_with_prefix_and_newline) {
+ return Property("text_message_with_prefix_and_newline",
+ &absl::LogEntry::text_message_with_prefix_and_newline,
+ text_message_with_prefix_and_newline);
+}
+
+Matcher<const absl::LogEntry&> TextMessageWithPrefix(
+ const Matcher<absl::string_view>& text_message_with_prefix) {
+ return Property("text_message_with_prefix",
+ &absl::LogEntry::text_message_with_prefix,
+ text_message_with_prefix);
+}
+
+Matcher<const absl::LogEntry&> TextMessage(
+ const Matcher<absl::string_view>& text_message) {
+ return Property("text_message", &absl::LogEntry::text_message, text_message);
+}
+
+Matcher<const absl::LogEntry&> TextPrefix(
+ const Matcher<absl::string_view>& text_prefix) {
+ return ResultOf(
+ [](const absl::LogEntry& entry) {
+ absl::string_view msg = entry.text_message_with_prefix();
+ msg.remove_suffix(entry.text_message().size());
+ return msg;
+ },
+ text_prefix);
+}
+Matcher<const absl::LogEntry&> RawEncodedMessage(
+ const Matcher<absl::string_view>& raw_encoded_message) {
+ return Property("encoded_message", &absl::LogEntry::encoded_message,
+ raw_encoded_message);
+}
+
+Matcher<const absl::LogEntry&> Verbosity(
+ const Matcher<int>& verbosity) {
+ return Property("verbosity", &absl::LogEntry::verbosity, verbosity);
+}
+
+Matcher<const absl::LogEntry&> Stacktrace(
+ const Matcher<absl::string_view>& stacktrace) {
+ return Property("stacktrace", &absl::LogEntry::stacktrace, stacktrace);
+}
+
+Matcher<absl::string_view> MatchesOstream(
+ const std::ostringstream& stream) {
+ return MakeMatcher(new MatchesOstreamImpl(stream.str()));
+}
+
+// We need to validate what is and isn't logged as the process dies due to
+// `FATAL`, `QFATAL`, `CHECK`, etc., but assertions inside a death test
+// subprocess don't directly affect the pass/fail status of the parent process.
+// Instead, we use the mock actions `DeathTestExpectedLogging` and
+// `DeathTestUnexpectedLogging` to write specific phrases to `stderr` that we
+// can validate in the parent process using this matcher.
+Matcher<const std::string&> DeathTestValidateExpectations() {
+ if (log_internal::LoggingEnabledAt(absl::LogSeverity::kFatal)) {
+ return Matcher<const std::string&>(
+ AllOf(HasSubstr("Mock received expected entry"),
+ Not(HasSubstr("Mock received unexpected entry"))));
+ }
+ // If `FATAL` logging is disabled, neither message should have been written.
+ return Matcher<const std::string&>(
+ AllOf(Not(HasSubstr("Mock received expected entry")),
+ Not(HasSubstr("Mock received unexpected entry"))));
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/abseil-cpp/absl/log/internal/test_matchers.h b/abseil-cpp/absl/log/internal/test_matchers.h
new file mode 100644
index 0000000..fc653a9
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/test_matchers.h
@@ -0,0 +1,94 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_matchers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's matchers used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+#define ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+
+#include <iosfwd>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+// In some configurations, Googletest's string matchers (e.g.
+// `::testing::EndsWith`) need help to match `absl::string_view`.
+::testing::Matcher<absl::string_view> AsString(
+ const ::testing::Matcher<const std::string&>& str_matcher);
+
+// These matchers correspond to the components of `absl::LogEntry`.
+::testing::Matcher<const absl::LogEntry&> SourceFilename(
+ const ::testing::Matcher<absl::string_view>& source_filename);
+::testing::Matcher<const absl::LogEntry&> SourceBasename(
+ const ::testing::Matcher<absl::string_view>& source_basename);
+// Be careful with this one; multi-line statements using `__LINE__` evaluate
+// differently on different platforms. In particular, the MSVC implementation
+// of `EXPECT_DEATH` returns the line number of the macro expansion to all lines
+// within the code block that's expected to die.
+::testing::Matcher<const absl::LogEntry&> SourceLine(
+ const ::testing::Matcher<int>& source_line);
+::testing::Matcher<const absl::LogEntry&> Prefix(
+ const ::testing::Matcher<bool>& prefix);
+::testing::Matcher<const absl::LogEntry&> LogSeverity(
+ const ::testing::Matcher<absl::LogSeverity>& log_severity);
+::testing::Matcher<const absl::LogEntry&> Timestamp(
+ const ::testing::Matcher<absl::Time>& timestamp);
+// Matches if the `LogEntry`'s timestamp falls after the instantiation of this
+// matcher and before its execution, as is normal when used with EXPECT_CALL.
+::testing::Matcher<const absl::LogEntry&> TimestampInMatchWindow();
+::testing::Matcher<const absl::LogEntry&> ThreadID(
+ const ::testing::Matcher<absl::LogEntry::tid_t>&);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
+ const ::testing::Matcher<absl::string_view>&
+ text_message_with_prefix_and_newline);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(
+ const ::testing::Matcher<absl::string_view>& text_message_with_prefix);
+::testing::Matcher<const absl::LogEntry&> TextMessage(
+ const ::testing::Matcher<absl::string_view>& text_message);
+::testing::Matcher<const absl::LogEntry&> TextPrefix(
+ const ::testing::Matcher<absl::string_view>& text_prefix);
+::testing::Matcher<const absl::LogEntry&> Verbosity(
+ const ::testing::Matcher<int>& verbosity);
+::testing::Matcher<const absl::LogEntry&> Stacktrace(
+ const ::testing::Matcher<absl::string_view>& stacktrace);
+// Behaves as `Eq(stream.str())`, but produces better failure messages.
+::testing::Matcher<absl::string_view> MatchesOstream(
+ const std::ostringstream& stream);
+::testing::Matcher<const std::string&> DeathTestValidateExpectations();
+
+::testing::Matcher<const absl::LogEntry&> RawEncodedMessage(
+ const ::testing::Matcher<absl::string_view>& raw_encoded_message);
+#define ENCODED_MESSAGE(message_matcher) ::testing::_
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
diff --git a/abseil-cpp/absl/log/internal/voidify.h b/abseil-cpp/absl/log/internal/voidify.h
new file mode 100644
index 0000000..8f62da2
--- /dev/null
+++ b/abseil-cpp/absl/log/internal/voidify.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/voidify.h
+// -----------------------------------------------------------------------------
+//
+// This class is used to explicitly ignore values in the conditional logging
+// macros. This avoids compiler warnings like "value computed is not used" and
+// "statement has no effect".
+
+#ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_
+#define ABSL_LOG_INTERNAL_VOIDIFY_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class Voidify final {
+ public:
+ // This has to be an operator with a precedence lower than << but higher than
+ // ?:
+ template <typename T>
+ void operator&&(const T&) const&& {}
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_VOIDIFY_H_