diff --git a/weight/_dep/abseil-cpp/absl/log/internal/BUILD.bazel b/weight/_dep/abseil-cpp/absl/log/internal/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..1be134998ab1ae61e3c97600cc7dafa1ac72d23b --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/BUILD.bazel @@ -0,0 +1,471 @@ +# +# 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__", + ], + features = [ + "header_modules", + "layering_check", + "parse_headers", + ], +) + +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", + "//absl/log:absl_vlog_is_on", + ], +) + +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:no_destructor", + "//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", + ], +) + +cc_library( + name = "fnmatch", + srcs = ["fnmatch.cc"], + hdrs = ["fnmatch.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + "//absl/strings", + ], +) + +cc_library( + name = "vlog_config", + srcs = ["vlog_config.cc"], + hdrs = ["vlog_config.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = ["//absl/log:__subpackages__"], + deps = [ + "//absl/base", + "//absl/base:config", + "//absl/base:core_headers", + "//absl/base:no_destructor", + "//absl/log/internal:fnmatch", + "//absl/memory", + "//absl/strings", + "//absl/synchronization", + "//absl/types:optional", + ], +) + +cc_binary( + name = "vlog_config_benchmark", + testonly = 1, + srcs = ["vlog_config_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = [ + "benchmark", + ], + visibility = ["//visibility:private"], + deps = [ + ":vlog_config", + "//absl/base:config", + "//absl/base:core_headers", + "//absl/container:layout", + "//absl/memory", + "//absl/random:distributions", + "//absl/strings", + "@com_github_google_benchmark//:benchmark_main", + ], +) + +# 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", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "fnmatch_test", + srcs = ["fnmatch_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":fnmatch", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + +cc_test( + name = "fnmatch_benchmark", + srcs = ["fnmatch_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = ["benchmark"], + deps = [ + ":fnmatch", + "@com_github_google_benchmark//:benchmark_main", + ], +) diff --git a/weight/_dep/abseil-cpp/absl/log/internal/check_impl.h b/weight/_dep/abseil-cpp/absl/log/internal/check_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..00f25f80ba252ef0629099119b671a4b90eca8c8 --- /dev/null +++ b/weight/_dep/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/weight/_dep/abseil-cpp/absl/log/internal/check_op.cc b/weight/_dep/abseil-cpp/absl/log/internal/check_op.cc new file mode 100644 index 0000000000000000000000000000000000000000..f4b67647a6fbe24a88c1dfabee781fe1f933a224 --- /dev/null +++ b/weight/_dep/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 + +#ifdef _MSC_VER +#define strcasecmp _stricmp +#else +#include // for strcasecmp, but msvc does not have this header +#endif + +#include +#include + +#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/weight/_dep/abseil-cpp/absl/log/internal/conditions.cc b/weight/_dep/abseil-cpp/absl/log/internal/conditions.cc new file mode 100644 index 0000000000000000000000000000000000000000..a9f4966f5dd33e9298069362c1809fb9f7be9489 --- /dev/null +++ b/weight/_dep/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 +#include + +#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* 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(n)) == 0; +} + +bool LogFirstNState::ShouldLog(int n) { + const uint32_t counter_value = counter_.load(std::memory_order_relaxed); + if (static_cast(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/weight/_dep/abseil-cpp/absl/log/internal/conditions.h b/weight/_dep/abseil-cpp/absl/log/internal/conditions.h new file mode 100644 index 0000000000000000000000000000000000000000..645f3c23ea553d06d6561c0c9a135fbce5963dc8 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/conditions.h @@ -0,0 +1,239 @@ +// 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 +#else +#include +#endif +#include + +#include +#include + +#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 beginning 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_STATELESS_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_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_##type##_CONDITION( \ + (ABSL_ASSUME(absl::kLogDebugFatal == absl::LogSeverity::kError || \ + absl::kLogDebugFatal == absl::LogSeverity::kFatal), \ + (condition) && \ + (::absl::kLogDebugFatal >= \ + static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ + (::absl::kLogDebugFatal == ::absl::LogSeverity::kFatal && \ + (::absl::log_internal::AbortQuietly(), false))))) + +#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ + for (int absl_log_internal_severity_loop = 1; \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ + for (const absl::LogSeverity absl_log_internal_severity = \ + ::absl::NormalizeLogSeverity(severity); \ + absl_log_internal_severity_loop; absl_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) && \ + (absl_log_internal_severity >= \ + static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \ + (absl_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_DFATAL(type, condition) \ + ABSL_LOG_INTERNAL_##type##_CONDITION(condition) +#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \ + for (int absl_log_internal_severity_loop = 1; \ + absl_log_internal_severity_loop; absl_log_internal_severity_loop = 0) \ + for (const absl::LogSeverity absl_log_internal_severity = \ + ::absl::NormalizeLogSeverity(severity); \ + absl_log_internal_severity_loop; absl_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 counter_{0}; +}; + +class LogFirstNState final { + public: + bool ShouldLog(int n); + uint32_t counter() { return counter_.load(std::memory_order_relaxed); } + + private: + std::atomic counter_{0}; +}; + +class LogEveryPow2State final { + public: + bool ShouldLog(); + uint32_t counter() { return counter_.load(std::memory_order_relaxed); } + + private: + std::atomic counter_{0}; +}; + +class LogEveryNSecState final { + public: + bool ShouldLog(double seconds); + uint32_t counter() { return counter_.load(std::memory_order_relaxed); } + + private: + std::atomic counter_{0}; + // Cycle count according to CycleClock that we should next log at. + std::atomic 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/weight/_dep/abseil-cpp/absl/log/internal/config.h b/weight/_dep/abseil-cpp/absl/log/internal/config.h new file mode 100644 index 0000000000000000000000000000000000000000..379e9ab974c392fcb33f440b8ff5a9d682cd7f21 --- /dev/null +++ b/weight/_dep/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 +#else +#include +#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/weight/_dep/abseil-cpp/absl/log/internal/flags.h b/weight/_dep/abseil-cpp/absl/log/internal/flags.h new file mode 100644 index 0000000000000000000000000000000000000000..c4539785ad35d98e9f48e82cc574da37928fca1a --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/flags.h @@ -0,0 +1,59 @@ +// 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 + +#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 +// `LogSink`s. 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); + +// Global log verbosity level. Default is 0. +ABSL_DECLARE_FLAG(int, v); + +// Per-module log verbosity level. By default is empty and is unused. +ABSL_DECLARE_FLAG(std::string, vmodule); + +#endif // ABSL_LOG_INTERNAL_FLAGS_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.cc b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.cc new file mode 100644 index 0000000000000000000000000000000000000000..26e1e57fe43450ed5ca4d736b88df35b8fee9db5 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.cc @@ -0,0 +1,73 @@ +// 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/fnmatch.h" + +#include + +#include "absl/base/config.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { +bool FNMatch(absl::string_view pattern, absl::string_view str) { + bool in_wildcard_match = false; + while (true) { + if (pattern.empty()) { + // `pattern` is exhausted; succeed if all of `str` was consumed matching + // it. + return in_wildcard_match || str.empty(); + } + if (str.empty()) { + // `str` is exhausted; succeed if `pattern` is empty or all '*'s. + return pattern.find_first_not_of('*') == pattern.npos; + } + switch (pattern.front()) { + case '*': + pattern.remove_prefix(1); + in_wildcard_match = true; + break; + case '?': + pattern.remove_prefix(1); + str.remove_prefix(1); + break; + default: + if (in_wildcard_match) { + absl::string_view fixed_portion = pattern; + const size_t end = fixed_portion.find_first_of("*?"); + if (end != fixed_portion.npos) { + fixed_portion = fixed_portion.substr(0, end); + } + const size_t match = str.find(fixed_portion); + if (match == str.npos) { + return false; + } + pattern.remove_prefix(fixed_portion.size()); + str.remove_prefix(match + fixed_portion.size()); + in_wildcard_match = false; + } else { + if (pattern.front() != str.front()) { + return false; + } + pattern.remove_prefix(1); + str.remove_prefix(1); + } + break; + } + } +} +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.h b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.h new file mode 100644 index 0000000000000000000000000000000000000000..4ea147cc6f7a24ab54e8a660186f9b84458159ce --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch.h @@ -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. + +#ifndef ABSL_LOG_INTERNAL_FNMATCH_H_ +#define ABSL_LOG_INTERNAL_FNMATCH_H_ + +#include "absl/base/config.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { +// Like POSIX `fnmatch`, but: +// * accepts `string_view` +// * does not allocate any dynamic memory +// * only supports * and ? wildcards and not bracket expressions [...] +// * wildcards may match / +// * no backslash-escaping +bool FNMatch(absl::string_view pattern, absl::string_view str); +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_FNMATCH_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_benchmark.cc b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_benchmark.cc new file mode 100644 index 0000000000000000000000000000000000000000..f062ba20d45c72eeb34b3a119ea788d65fdc384b --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_benchmark.cc @@ -0,0 +1,29 @@ +// 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/fnmatch.h" +#include "benchmark/benchmark.h" + +namespace { +void BM_FNMatch(benchmark::State& state) { + while (state.KeepRunning()) { + bool ret = + absl::log_internal::FNMatch("*?*asdf*?*we???asdf**asdf*we", + "QWERFASVWERASDFWEDFASDasdfQWERGFWASDERREWF" + "weHOOasdf@#$%TW#ZSERasdfQW#REGTZSERERwe"); + benchmark::DoNotOptimize(ret); + } +} +BENCHMARK(BM_FNMatch); +} // namespace diff --git a/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_test.cc b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..e16a64ece169b6d988b1c448f93779a234f5da84 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/fnmatch_test.cc @@ -0,0 +1,59 @@ +// 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/fnmatch.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace { +using ::testing::IsFalse; +using ::testing::IsTrue; + +TEST(FNMatchTest, Works) { + using absl::log_internal::FNMatch; + EXPECT_THAT(FNMatch("foo", "foo"), IsTrue()); + EXPECT_THAT(FNMatch("foo", "bar"), IsFalse()); + EXPECT_THAT(FNMatch("foo", "fo"), IsFalse()); + EXPECT_THAT(FNMatch("foo", "foo2"), IsFalse()); + EXPECT_THAT(FNMatch("bar/foo.ext", "bar/foo.ext"), IsTrue()); + EXPECT_THAT(FNMatch("*ba*r/fo*o.ext*", "bar/foo.ext"), IsTrue()); + EXPECT_THAT(FNMatch("bar/foo.ext", "bar/baz.ext"), IsFalse()); + EXPECT_THAT(FNMatch("bar/foo.ext", "bar/foo"), IsFalse()); + EXPECT_THAT(FNMatch("bar/foo.ext", "bar/foo.ext.zip"), IsFalse()); + EXPECT_THAT(FNMatch("ba?/*.ext", "bar/foo.ext"), IsTrue()); + EXPECT_THAT(FNMatch("ba?/*.ext", "baZ/FOO.ext"), IsTrue()); + EXPECT_THAT(FNMatch("ba?/*.ext", "barr/foo.ext"), IsFalse()); + EXPECT_THAT(FNMatch("ba?/*.ext", "bar/foo.ext2"), IsFalse()); + EXPECT_THAT(FNMatch("ba?/*", "bar/foo.ext2"), IsTrue()); + EXPECT_THAT(FNMatch("ba?/*", "bar/"), IsTrue()); + EXPECT_THAT(FNMatch("ba?/?", "bar/"), IsFalse()); + EXPECT_THAT(FNMatch("ba?/*", "bar"), IsFalse()); + EXPECT_THAT(FNMatch("?x", "zx"), IsTrue()); + EXPECT_THAT(FNMatch("*b", "aab"), IsTrue()); + EXPECT_THAT(FNMatch("a*b", "aXb"), IsTrue()); + EXPECT_THAT(FNMatch("", ""), IsTrue()); + EXPECT_THAT(FNMatch("", "a"), IsFalse()); + EXPECT_THAT(FNMatch("ab*", "ab"), IsTrue()); + EXPECT_THAT(FNMatch("ab**", "ab"), IsTrue()); + EXPECT_THAT(FNMatch("ab*?", "ab"), IsFalse()); + EXPECT_THAT(FNMatch("*", "bbb"), IsTrue()); + EXPECT_THAT(FNMatch("*", ""), IsTrue()); + EXPECT_THAT(FNMatch("?", ""), IsFalse()); + EXPECT_THAT(FNMatch("***", "**p"), IsTrue()); + EXPECT_THAT(FNMatch("**", "*"), IsTrue()); + EXPECT_THAT(FNMatch("*?", "*"), IsTrue()); +} + +} // namespace diff --git a/weight/_dep/abseil-cpp/absl/log/internal/globals.cc b/weight/_dep/abseil-cpp/absl/log/internal/globals.cc new file mode 100644 index 0000000000000000000000000000000000000000..359858f15ef06a9ba76f39b7462e90f0c91eb6d5 --- /dev/null +++ b/weight/_dep/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 +#include + +#if defined(__EMSCRIPTEN__) +#include +#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 logging_initialized(false); + +// The TimeZone used for logging. This may only be set once. +ABSL_CONST_INIT std::atomic timezone_ptr{nullptr}; + +// If true, the logging library will symbolize stack in fatal messages +ABSL_CONST_INIT std::atomic symbolize_stack_trace(true); + +// Specifies maximum number of stack frames to report in fatal messages. +ABSL_CONST_INIT std::atomic max_frames_in_stack_trace(64); + +ABSL_CONST_INIT std::atomic exit_on_dfatal(true); +ABSL_CONST_INIT std::atomic 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/weight/_dep/abseil-cpp/absl/log/internal/globals.h b/weight/_dep/abseil-cpp/absl/log/internal/globals.h new file mode 100644 index 0000000000000000000000000000000000000000..27bc0d09847dc77ffbf5ae1ca509ffd67bb0baf0 --- /dev/null +++ b/weight/_dep/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/weight/_dep/abseil-cpp/absl/log/internal/log_format.cc b/weight/_dep/abseil-cpp/absl/log/internal/log_format.cc new file mode 100644 index 0000000000000000000000000000000000000000..23cef88a24c9dfbe377d2849e723f342ca4e1b52 --- /dev/null +++ b/weight/_dep/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 + +#ifdef _MSC_VER +#include // For timeval +#else +#include +#endif + +#include +#include +#include +#include +#include + +#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 +inline std::enable_if_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 +inline std::enable_if_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& buf) { + constexpr size_t kBoundedFieldsMaxLen = + sizeof("SMMDD HH:MM:SS.NNNNNN ") + + (1 + std::numeric_limits::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(tv.tv_sec), + static_cast(tv.tv_usec), static_cast(tid)); + if (snprintf_result >= 0) { + buf.remove_prefix(static_cast(snprintf_result)); + return static_cast(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(ci.cs.month()), p); + p += 2; + absl::numbers_internal::PutTwoDigits(static_cast(ci.cs.day()), p); + p += 2; + *p++ = ' '; + absl::numbers_internal::PutTwoDigits(static_cast(ci.cs.hour()), p); + p += 2; + *p++ = ':'; + absl::numbers_internal::PutTwoDigits(static_cast(ci.cs.minute()), + p); + p += 2; + *p++ = ':'; + absl::numbers_internal::PutTwoDigits(static_cast(ci.cs.second()), + p); + p += 2; + *p++ = '.'; + const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond); + absl::numbers_internal::PutTwoDigits(static_cast(usecs / 10000), p); + p += 2; + absl::numbers_internal::PutTwoDigits(static_cast(usecs / 100 % 100), + p); + p += 2; + absl::numbers_internal::PutTwoDigits(static_cast(usecs % 100), p); + p += 2; + *p++ = ' '; + PutLeadingWhitespace(tid, p); + p = absl::numbers_internal::FastIntToBuffer(tid, p); + *p++ = ' '; + const size_t bytes_formatted = static_cast(p - buf.data()); + buf.remove_prefix(bytes_formatted); + return bytes_formatted; +} + +size_t FormatLineNumber(int line, absl::Span& buf) { + constexpr size_t kLineFieldMaxLen = + sizeof(":] ") + (1 + std::numeric_limits::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(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& 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/weight/_dep/abseil-cpp/absl/log/internal/log_format.h b/weight/_dep/abseil-cpp/absl/log/internal/log_format.h new file mode 100644 index 0000000000000000000000000000000000000000..95a45edf6102fce8da4fe5cf838cbf349b22dbc9 --- /dev/null +++ b/weight/_dep/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 + +#include + +#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& buf); + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_LOG_FORMAT_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/internal/log_impl.h b/weight/_dep/abseil-cpp/absl/log/internal/log_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..99de6dbb24c6e90dfb7d0cfcc31bd8f7e7bbc863 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/log_impl.h @@ -0,0 +1,282 @@ +// 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/absl_vlog_is_on.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 + +// The `switch` ensures that this expansion is the begnning of a statement (as +// opposed to an expression). The use of both `case 0` and `default` is to +// suppress a compiler warning. +#define ABSL_LOG_INTERNAL_VLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) + +#ifndef NDEBUG +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) +#else +#define ABSL_LOG_INTERNAL_DVLOG_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_LOG_IF_IMPL( \ + _INFO, false && ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + .WithVerbosity(absl_logging_internal_verbose_level) +#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_VLOG_EVERY_N_IMPL(verbose_level, n) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_FIRST_N_IMPL(verbose_level, n) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (FirstN, n) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_EVERY_POW_2_IMPL(verbose_level) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryPow2) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream().WithVerbosity( \ + absl_logging_internal_verbose_level) + +#define ABSL_LOG_INTERNAL_VLOG_EVERY_N_SEC_IMPL(verbose_level, n_seconds) \ + switch (const int absl_logging_internal_verbose_level = (verbose_level)) \ + case 0: \ + default: \ + ABSL_LOG_INTERNAL_CONDITION_INFO( \ + STATEFUL, ABSL_VLOG_IS_ON(absl_logging_internal_verbose_level)) \ + (EveryNSec, n_seconds) ABSL_LOGGING_INTERNAL_LOG_INFO.InternalStream() \ + .WithVerbosity(absl_logging_internal_verbose_level) + +#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/weight/_dep/abseil-cpp/absl/log/internal/log_message.cc b/weight/_dep/abseil-cpp/absl/log/internal/log_message.cc new file mode 100644 index 0000000000000000000000000000000000000000..10ac245373a036f343bf759868a78b3b489843e4 --- /dev/null +++ b/weight/_dep/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 +#include +#include +#include + +#ifndef _WIN32 +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#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& dst, absl::Span 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(str)->append(data); +} +void WriteToStream(const char* data, void* os) { + auto* cast_os = static_cast(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 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 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 encoded_remaining; + + // A formatted string message is built in `string_buf`. + std::array 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 encoded_data( + encoded_buf.data(), + static_cast(encoded_remaining.data() - encoded_buf.data())); + // `string_remaining` is the suffix of `string_buf` that has not been filled + // yet. + absl::Span 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(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(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_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(v); + return *this; +} + +LogMessage& LogMessage::operator<<(absl::string_view v) { + CopyToEncodedBuffer(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 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(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 contents(pbase(), + static_cast(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 +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( + absl::string_view str); +template void LogMessage::CopyToEncodedBuffer< + LogMessage::StringType::kNotLiteral>(absl::string_view str); +template +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( + 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/weight/_dep/abseil-cpp/absl/log/internal/log_message.h b/weight/_dep/abseil-cpp/absl/log/internal/log_message.h new file mode 100644 index 0000000000000000000000000000000000000000..4ecb8a149880d39286327ebf63a51dd8ab4dabda --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/log_message.h @@ -0,0 +1,375 @@ +// 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 +#include +#include +#include +#include + +#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/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<< (v); } + LogMessage& operator<<(signed char v) { return operator<< (v); } + LogMessage& operator<<(unsigned char v) { + return operator<< (v); + } + LogMessage& operator<<(signed short v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(signed int v) { return operator<< (v); } + LogMessage& operator<<(signed long v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(signed long long v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(unsigned short v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(unsigned int v) { + return operator<< (v); + } + LogMessage& operator<<(unsigned long v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(unsigned long long v) { // NOLINT + return operator<< (v); // NOLINT + } + LogMessage& operator<<(void* v) { return operator<< (v); } + LogMessage& operator<<(const void* v) { return operator<< (v); } + LogMessage& operator<<(float v) { return operator<< (v); } + LogMessage& operator<<(double v) { return operator<< (v); } + LogMessage& operator<<(bool v) { return operator<< (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 + LogMessage& operator<<(const char (&buf)[SIZE]); + + // This prevents non-const `char[]` arrays from looking like literals. + template + LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE; + + // Types that support `AbslStringify()` are serialized that way. + template ::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 ::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 encoded_remaining_copy_; + absl::Span message_start_; + absl::Span string_start_; + }; + + enum class StringType { + kLiteral, + kNotLiteral, + }; + template + void CopyToEncodedBuffer(absl::string_view str) ABSL_ATTRIBUTE_NOINLINE; + template + 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 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(ch, + count); + } + + void Append(absl::string_view v) { + message_.CopyToEncodedBuffer(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 ::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 ::value, int>::type> +LogMessage& LogMessage::operator<<(const T& v) { + OstreamView view(*data_); + view.stream() << log_internal::NullGuard().Guard(v); + return *this; +} + +template +LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) { + CopyToEncodedBuffer(buf); + return *this; +} + +// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` +template +LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) { + CopyToEncodedBuffer(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(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/weight/_dep/abseil-cpp/absl/log/internal/log_sink_set.cc b/weight/_dep/abseil-cpp/absl/log/internal/log_sink_set.cc new file mode 100644 index 0000000000000000000000000000000000000000..3d5c69952c24d991014bad3ef28c20524ca4e252 --- /dev/null +++ b/weight/_dep/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 +#endif + +#ifdef __ANDROID__ +#include +#endif + +#ifdef _WIN32 +#include +#endif + +#include +#include + +#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/no_destructor.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(data); + })) { + perror("pthread_key_create failed!"); + abort(); + } + return true; + }(); + (void)unused; // Fixes -wunused-variable warning + bool* thread_is_logging_ptr = + reinterpret_cast(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 absl::NoDestructor stderr_log_sink; + AddLogSink(stderr_log_sink.get()); +#endif +#ifdef __ANDROID__ + static absl::NoDestructor android_log_sink; + AddLogSink(android_log_sink.get()); +#endif +#if defined(_WIN32) + static absl::NoDestructor debugger_log_sink; + AddLogSink(debugger_log_sink.get()); +#endif // !defined(_WIN32) + } + + void LogToSinks(const absl::LogEntry& entry, + absl::Span 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 sinks) { + for (absl::LogSink* sink : sinks) { + sink->Send(entry); + } + } + + using LogSinksSet = std::vector; + absl::Mutex guard_; + LogSinksSet sinks_ ABSL_GUARDED_BY(guard_); +}; + +// Returns reference to the global LogSinks set. +GlobalLogSinkSet& GlobalSinks() { + static absl::NoDestructor global_sinks; + return *global_sinks; +} + +} // namespace + +bool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); } + +void LogToSinks(const absl::LogEntry& entry, + absl::Span 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/weight/_dep/abseil-cpp/absl/log/internal/log_sink_set.h b/weight/_dep/abseil-cpp/absl/log/internal/log_sink_set.h new file mode 100644 index 0000000000000000000000000000000000000000..88ab073bbd0969947021c070579fcc94ab54dee6 --- /dev/null +++ b/weight/_dep/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 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/weight/_dep/abseil-cpp/absl/log/internal/nullguard.cc b/weight/_dep/abseil-cpp/absl/log/internal/nullguard.cc new file mode 100644 index 0000000000000000000000000000000000000000..3296c0142ea7ce34a16630715484140331852731 --- /dev/null +++ b/weight/_dep/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 + +#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 kCharNull{ + {'(', 'n', 'u', 'l', 'l', ')', '\0'}}; +ABSL_CONST_INIT ABSL_DLL const std::array kSignedCharNull{ + {'(', 'n', 'u', 'l', 'l', ')', '\0'}}; +ABSL_CONST_INIT ABSL_DLL const std::array kUnsignedCharNull{ + {'(', 'n', 'u', 'l', 'l', ')', '\0'}}; + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/weight/_dep/abseil-cpp/absl/log/internal/nullguard.h b/weight/_dep/abseil-cpp/absl/log/internal/nullguard.h new file mode 100644 index 0000000000000000000000000000000000000000..623943c512bcf06ed530223d2ccabf59f61a3fe5 --- /dev/null +++ b/weight/_dep/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::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::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 +#include + +#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 kCharNull; +ABSL_CONST_INIT ABSL_DLL extern const std::array + kSignedCharNull; +ABSL_CONST_INIT ABSL_DLL extern const std::array + kUnsignedCharNull; + +template +struct NullGuard final { + static const T& Guard(const T& v) { return v; } +}; +template <> +struct NullGuard final { + static const char* Guard(const char* v) { return v ? v : kCharNull.data(); } +}; +template <> +struct NullGuard final { + static const char* Guard(const char* v) { return v ? v : kCharNull.data(); } +}; +template <> +struct NullGuard final { + static const signed char* Guard(const signed char* v) { + return v ? v : kSignedCharNull.data(); + } +}; +template <> +struct NullGuard final { + static const signed char* Guard(const signed char* v) { + return v ? v : kSignedCharNull.data(); + } +}; +template <> +struct NullGuard final { + static const unsigned char* Guard(const unsigned char* v) { + return v ? v : kUnsignedCharNull.data(); + } +}; +template <> +struct NullGuard final { + static const unsigned char* Guard(const unsigned char* v) { + return v ? v : kUnsignedCharNull.data(); + } +}; +template <> +struct NullGuard 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/weight/_dep/abseil-cpp/absl/log/internal/nullstream.h b/weight/_dep/abseil-cpp/absl/log/internal/nullstream.h new file mode 100644 index 0000000000000000000000000000000000000000..9266852eb98decdb2ecf049b00cdfc2e30cb72db --- /dev/null +++ b/weight/_dep/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 +#else +#include +#endif +#include +#include + +#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 + NullStream& AtLocation(SourceLocationType) { + return *this; + } + NullStream& NoPrefix() { return *this; } + NullStream& WithVerbosity(int) { return *this; } + template + NullStream& WithTimestamp(TimeType) { + return *this; + } + template + NullStream& WithThreadID(Tid) { + return *this; + } + template + NullStream& WithMetadataFrom(const LogEntryType&) { + return *this; + } + NullStream& WithPerror() { return *this; } + template + NullStream& ToSinkAlso(LogSinkType*) { + return *this; + } + template + NullStream& ToSinkOnly(LogSinkType*) { + return *this; + } + template + NullStream& OutputToSink(LogSinkType*, bool) { + return *this; + } + NullStream& InternalStream() { return *this; } +}; +template +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/weight/_dep/abseil-cpp/absl/log/internal/proto.cc b/weight/_dep/abseil-cpp/absl/log/internal/proto.cc new file mode 100644 index 0000000000000000000000000000000000000000..eb699ae8e77b6f29d995a0633f02df87af808202 --- /dev/null +++ b/weight/_dep/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 +#include +#include +#include +#include + +#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 *buf) { + for (size_t s = 0; s < size; s++) { + (*buf)[s] = static_cast((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(type); +} +} // namespace + +bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span *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 *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(value & 0xff); + value >>= 8; + } + buf->remove_prefix(sizeof(value)); + return true; +} + +bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span *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(value & 0xff); + value >>= 8; + } + buf->remove_prefix(sizeof(value)); + return true; +} + +bool EncodeBytes(uint64_t tag, absl::Span value, + absl::Span *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 value, + absl::Span *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(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 EncodeMessageStart( + uint64_t tag, uint64_t max_size, absl::Span *buf) { + const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited); + const size_t tag_type_size = VarintSize(tag_type); + max_size = std::min(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(); + } + EncodeRawVarint(tag_type, tag_type_size, buf); + const absl::Span ret = buf->subspan(0, length_size); + EncodeRawVarint(0, length_size, buf); + return ret; +} + +void EncodeMessageLength(absl::Span msg, const absl::Span *buf) { + if (!msg.data()) return; + assert(buf->data() >= msg.data()); + if (buf->data() < msg.data()) return; + EncodeRawVarint( + static_cast(buf->data() - (msg.data() + msg.size())), + msg.size(), &msg); +} + +namespace { +uint64_t DecodeVarint(absl::Span *buf) { + uint64_t value = 0; + size_t s = 0; + while (s < buf->size()) { + value |= static_cast(static_cast((*buf)[s]) & 0x7f) + << 7 * s; + if (!((*buf)[s++] & 0x80)) break; + } + buf->remove_prefix(s); + return value; +} + +uint64_t Decode64Bit(absl::Span *buf) { + uint64_t value = 0; + size_t s = 0; + while (s < buf->size()) { + value |= static_cast(static_cast((*buf)[s])) + << 8 * s; + if (++s == sizeof(value)) break; + } + buf->remove_prefix(s); + return value; +} + +uint32_t Decode32Bit(absl::Span *buf) { + uint32_t value = 0; + size_t s = 0; + while (s < buf->size()) { + value |= static_cast(static_cast((*buf)[s])) + << 8 * s; + if (++s == sizeof(value)) break; + } + buf->remove_prefix(s); + return value; +} +} // namespace + +bool ProtoField::DecodeFrom(absl::Span *data) { + if (data->empty()) return false; + const uint64_t tag_type = DecodeVarint(data); + tag_ = tag_type >> 3; + type_ = static_cast(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(std::min(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/weight/_dep/abseil-cpp/absl/log/internal/proto.h b/weight/_dep/abseil-cpp/absl/log/internal/proto.h new file mode 100644 index 0000000000000000000000000000000000000000..c8d14acc4715124cc3629ed15b3360e9e1e5dcfa --- /dev/null +++ b/weight/_dep/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 +#include +#include + +#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 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 *buf); +inline bool EncodeVarint(uint64_t tag, int64_t value, absl::Span *buf) { + return EncodeVarint(tag, static_cast(value), buf); +} +inline bool EncodeVarint(uint64_t tag, uint32_t value, absl::Span *buf) { + return EncodeVarint(tag, static_cast(value), buf); +} +inline bool EncodeVarint(uint64_t tag, int32_t value, absl::Span *buf) { + return EncodeVarint(tag, static_cast(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 *buf) { + if (value < 0) + return EncodeVarint(tag, 2 * static_cast(-(value + 1)) + 1, buf); + return EncodeVarint(tag, 2 * static_cast(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 *buf); +inline bool Encode64Bit(uint64_t tag, int64_t value, absl::Span *buf) { + return Encode64Bit(tag, static_cast(value), buf); +} +inline bool Encode64Bit(uint64_t tag, uint32_t value, absl::Span *buf) { + return Encode64Bit(tag, static_cast(value), buf); +} +inline bool Encode64Bit(uint64_t tag, int32_t value, absl::Span *buf) { + return Encode64Bit(tag, static_cast(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 *buf) { + return Encode64Bit(tag, absl::bit_cast(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 *buf); +inline bool Encode32Bit(uint64_t tag, int32_t value, absl::Span *buf) { + return Encode32Bit(tag, static_cast(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 *buf) { + return Encode32Bit(tag, absl::bit_cast(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 value, + absl::Span *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 value, + absl::Span *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 *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 *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 EncodeMessageStart(uint64_t tag, + uint64_t max_size, + absl::Span *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 msg, const absl::Span *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::min)()); +} +constexpr size_t MaxVarintSize() { + return VarintSize((std::numeric_limits::max)()); +} + +constexpr uint64_t MaxVarintForSize(size_t size) { + return size >= 10 ? (std::numeric_limits::max)() + : (static_cast(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 +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 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 *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(value_); } + float float_value() const { + return absl::bit_cast(static_cast(value_)); + } + int32_t int32_value() const { return static_cast(value_); } + int64_t int64_value() const { return static_cast(value_); } + int32_t sint32_value() const { + if (value_ % 2) return static_cast(0 - ((value_ - 1) / 2) - 1); + return static_cast(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(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 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 data_; +}; + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_PROTO_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/internal/stderr_log_sink_test.cc b/weight/_dep/abseil-cpp/absl/log/internal/stderr_log_sink_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..763690d1b326480cb219caec3b25f87bf46740e4 --- /dev/null +++ b/weight/_dep/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 + +#include + +#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/weight/_dep/abseil-cpp/absl/log/internal/strip.h b/weight/_dep/abseil-cpp/absl/log/internal/strip.h new file mode 100644 index 0000000000000000000000000000000000000000..f8d27869392e3006b0e2f5980e91effcf1c63ee2 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/strip.h @@ -0,0 +1,72 @@ +// 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(absl_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__, \ + absl_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/weight/_dep/abseil-cpp/absl/log/internal/structured.h b/weight/_dep/abseil-cpp/absl/log/internal/structured.h new file mode 100644 index 0000000000000000000000000000000000000000..5223dbc310539272a12df01ae1cf630701aa0cb7 --- /dev/null +++ b/weight/_dep/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 + +#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(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/weight/_dep/abseil-cpp/absl/log/internal/test_actions.cc b/weight/_dep/abseil-cpp/absl/log/internal/test_actions.cc new file mode 100644 index 0000000000000000000000000000000000000000..bdfd63778c69e9b77e8854750cd49618f93702f2 --- /dev/null +++ b/weight/_dep/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 +#include +#include +#include + +#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/weight/_dep/abseil-cpp/absl/log/internal/test_actions.h b/weight/_dep/abseil-cpp/absl/log/internal/test_actions.h new file mode 100644 index 0000000000000000000000000000000000000000..649a050521bbcad69ceffa55834472f9a358e04d --- /dev/null +++ b/weight/_dep/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 +#include +#include + +#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 + 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/weight/_dep/abseil-cpp/absl/log/internal/test_helpers.cc b/weight/_dep/abseil-cpp/absl/log/internal/test_helpers.cc new file mode 100644 index 0000000000000000000000000000000000000000..bfcc9679607647870cd51c505e3d1a413bbb644f --- /dev/null +++ b/weight/_dep/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 +#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/weight/_dep/abseil-cpp/absl/log/internal/test_helpers.h b/weight/_dep/abseil-cpp/absl/log/internal/test_helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..714bc7bddcbdc173d4108a4507cbbfab5eb06e3c --- /dev/null +++ b/weight/_dep/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_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/weight/_dep/abseil-cpp/absl/log/internal/test_matchers.cc b/weight/_dep/abseil-cpp/absl/log/internal/test_matchers.cc new file mode 100644 index 0000000000000000000000000000000000000000..8c6515c4bc9cfb789e31de31190e73162e1c36bd --- /dev/null +++ b/weight/_dep/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 +#include +#include +#include +#include + +#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 { + public: + explicit AsStringImpl( + const Matcher& 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 str_matcher_; +}; + +class MatchesOstreamImpl final + : public MatcherInterface { + 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 AsString( + const Matcher& str_matcher) { + return MakeMatcher(new AsStringImpl(str_matcher)); +} + +Matcher SourceFilename( + const Matcher& source_filename) { + return Property("source_filename", &absl::LogEntry::source_filename, + source_filename); +} + +Matcher SourceBasename( + const Matcher& source_basename) { + return Property("source_basename", &absl::LogEntry::source_basename, + source_basename); +} + +Matcher SourceLine( + const Matcher& source_line) { + return Property("source_line", &absl::LogEntry::source_line, source_line); +} + +Matcher Prefix( + const Matcher& prefix) { + return Property("prefix", &absl::LogEntry::prefix, prefix); +} + +Matcher LogSeverity( + const Matcher& log_severity) { + return Property("log_severity", &absl::LogEntry::log_severity, log_severity); +} + +Matcher Timestamp( + const Matcher& timestamp) { + return Property("timestamp", &absl::LogEntry::timestamp, timestamp); +} + +Matcher TimestampInMatchWindow() { + return Property("timestamp", &absl::LogEntry::timestamp, + AllOf(Ge(absl::Now()), Truly([](absl::Time arg) { + return arg <= absl::Now(); + }))); +} + +Matcher ThreadID( + const Matcher& tid) { + return Property("tid", &absl::LogEntry::tid, tid); +} + +Matcher TextMessageWithPrefixAndNewline( + const Matcher& + 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 TextMessageWithPrefix( + const Matcher& text_message_with_prefix) { + return Property("text_message_with_prefix", + &absl::LogEntry::text_message_with_prefix, + text_message_with_prefix); +} + +Matcher TextMessage( + const Matcher& text_message) { + return Property("text_message", &absl::LogEntry::text_message, text_message); +} + +Matcher TextPrefix( + const Matcher& 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 RawEncodedMessage( + const Matcher& raw_encoded_message) { + return Property("encoded_message", &absl::LogEntry::encoded_message, + raw_encoded_message); +} + +Matcher Verbosity( + const Matcher& verbosity) { + return Property("verbosity", &absl::LogEntry::verbosity, verbosity); +} + +Matcher Stacktrace( + const Matcher& stacktrace) { + return Property("stacktrace", &absl::LogEntry::stacktrace, stacktrace); +} + +Matcher 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 DeathTestValidateExpectations() { + if (log_internal::LoggingEnabledAt(absl::LogSeverity::kFatal)) { + return Matcher( + 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( + AllOf(Not(HasSubstr("Mock received expected entry")), + Not(HasSubstr("Mock received unexpected entry")))); +} + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/weight/_dep/abseil-cpp/absl/log/internal/test_matchers.h b/weight/_dep/abseil-cpp/absl/log/internal/test_matchers.h new file mode 100644 index 0000000000000000000000000000000000000000..fc653a91bc3e656a920b9adb01e4f8ca398f1ea6 --- /dev/null +++ b/weight/_dep/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 +#include +#include + +#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 AsString( + const ::testing::Matcher& str_matcher); + +// These matchers correspond to the components of `absl::LogEntry`. +::testing::Matcher SourceFilename( + const ::testing::Matcher& source_filename); +::testing::Matcher SourceBasename( + const ::testing::Matcher& 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 SourceLine( + const ::testing::Matcher& source_line); +::testing::Matcher Prefix( + const ::testing::Matcher& prefix); +::testing::Matcher LogSeverity( + const ::testing::Matcher& log_severity); +::testing::Matcher Timestamp( + const ::testing::Matcher& 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 TimestampInMatchWindow(); +::testing::Matcher ThreadID( + const ::testing::Matcher&); +::testing::Matcher TextMessageWithPrefixAndNewline( + const ::testing::Matcher& + text_message_with_prefix_and_newline); +::testing::Matcher TextMessageWithPrefix( + const ::testing::Matcher& text_message_with_prefix); +::testing::Matcher TextMessage( + const ::testing::Matcher& text_message); +::testing::Matcher TextPrefix( + const ::testing::Matcher& text_prefix); +::testing::Matcher Verbosity( + const ::testing::Matcher& verbosity); +::testing::Matcher Stacktrace( + const ::testing::Matcher& stacktrace); +// Behaves as `Eq(stream.str())`, but produces better failure messages. +::testing::Matcher MatchesOstream( + const std::ostringstream& stream); +::testing::Matcher DeathTestValidateExpectations(); + +::testing::Matcher RawEncodedMessage( + const ::testing::Matcher& 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/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.cc b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.cc new file mode 100644 index 0000000000000000000000000000000000000000..b5788500410cba0484d7c8c5539f17bb75c17968 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.cc @@ -0,0 +1,340 @@ +// 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/vlog_config.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/const_init.h" +#include "absl/base/internal/spinlock.h" +#include "absl/base/no_destructor.h" +#include "absl/base/optimization.h" +#include "absl/base/thread_annotations.h" +#include "absl/log/internal/fnmatch.h" +#include "absl/memory/memory.h" +#include "absl/strings/numbers.h" +#include "absl/strings/str_split.h" +#include "absl/strings/string_view.h" +#include "absl/strings/strip.h" +#include "absl/synchronization/mutex.h" +#include "absl/types/optional.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +namespace { +bool ModuleIsPath(absl::string_view module_pattern) { +#ifdef _WIN32 + return module_pattern.find_first_of("/\\") != module_pattern.npos; +#else + return module_pattern.find('/') != module_pattern.npos; +#endif +} +} // namespace + +bool VLogSite::SlowIsEnabled(int stale_v, int level) { + if (ABSL_PREDICT_TRUE(stale_v != kUninitialized)) { + // Because of the prerequisites to this function, we know that stale_v is + // either uninitialized or >= level. If it's not uninitialized, that means + // it must be >= level, thus we should log. + return true; + } + stale_v = log_internal::RegisterAndInitialize(this); + return ABSL_PREDICT_FALSE(stale_v >= level); +} + +bool VLogSite::SlowIsEnabled0(int stale_v) { return SlowIsEnabled(stale_v, 0); } +bool VLogSite::SlowIsEnabled1(int stale_v) { return SlowIsEnabled(stale_v, 1); } +bool VLogSite::SlowIsEnabled2(int stale_v) { return SlowIsEnabled(stale_v, 2); } +bool VLogSite::SlowIsEnabled3(int stale_v) { return SlowIsEnabled(stale_v, 3); } +bool VLogSite::SlowIsEnabled4(int stale_v) { return SlowIsEnabled(stale_v, 4); } +bool VLogSite::SlowIsEnabled5(int stale_v) { return SlowIsEnabled(stale_v, 5); } + +namespace { +struct VModuleInfo final { + std::string module_pattern; + bool module_is_path; // i.e. it contains a path separator. + int vlog_level; + + // Allocates memory. + VModuleInfo(absl::string_view module_pattern_arg, bool module_is_path_arg, + int vlog_level_arg) + : module_pattern(std::string(module_pattern_arg)), + module_is_path(module_is_path_arg), + vlog_level(vlog_level_arg) {} +}; + +// `mutex` guards all of the data structures that aren't lock-free. +// To avoid problems with the heap checker which calls into `VLOG`, `mutex` must +// be a `SpinLock` that prevents fiber scheduling instead of a `Mutex`. +ABSL_CONST_INIT absl::base_internal::SpinLock mutex( + absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY); + +// `GetUpdateSitesMutex()` serializes updates to all of the sites (i.e. those in +// `site_list_head`) themselves. +absl::Mutex* GetUpdateSitesMutex() { + // Chromium requires no global destructors, so we can't use the + // absl::kConstInit idiom since absl::Mutex as a non-trivial destructor. + static absl::NoDestructor update_sites_mutex ABSL_ACQUIRED_AFTER( + mutex); + return update_sites_mutex.get(); +} + +ABSL_CONST_INIT int global_v ABSL_GUARDED_BY(mutex) = 0; +// `site_list_head` is the head of a singly-linked list. Traversal, insertion, +// and reads are atomic, so no locks are required, but updates to existing +// elements are guarded by `GetUpdateSitesMutex()`. +ABSL_CONST_INIT std::atomic site_list_head{nullptr}; +ABSL_CONST_INIT std::vector* vmodule_info ABSL_GUARDED_BY(mutex) + ABSL_PT_GUARDED_BY(mutex){nullptr}; + +// Only used for lisp. +ABSL_CONST_INIT std::vector>* update_callbacks + ABSL_GUARDED_BY(GetUpdateSitesMutex()) + ABSL_PT_GUARDED_BY(GetUpdateSitesMutex()){nullptr}; + +// Allocates memory. +std::vector& get_vmodule_info() + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + if (!vmodule_info) vmodule_info = new std::vector; + return *vmodule_info; +} + +// Does not allocate or take locks. +int VLogLevel(absl::string_view file, const std::vector* infos, + int current_global_v) { + // `infos` is null during a call to `VLOG` prior to setting `vmodule` (e.g. by + // parsing flags). We can't allocate in `VLOG`, so we treat null as empty + // here and press on. + if (!infos || infos->empty()) return current_global_v; + // Get basename for file + absl::string_view basename = file; + { + const size_t sep = basename.rfind('/'); + if (sep != basename.npos) { + basename.remove_prefix(sep + 1); +#ifdef _WIN32 + } else { + const size_t sep = basename.rfind('\\'); + if (sep != basename.npos) basename.remove_prefix(sep + 1); +#endif + } + } + + absl::string_view stem = file, stem_basename = basename; + { + const size_t sep = stem_basename.find('.'); + if (sep != stem_basename.npos) { + stem.remove_suffix(stem_basename.size() - sep); + stem_basename.remove_suffix(stem_basename.size() - sep); + } + if (absl::ConsumeSuffix(&stem_basename, "-inl")) { + stem.remove_suffix(absl::string_view("-inl").size()); + } + } + for (const auto& info : *infos) { + if (info.module_is_path) { + // If there are any slashes in the pattern, try to match the full + // name. + if (FNMatch(info.module_pattern, stem)) { + return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + } + } else if (FNMatch(info.module_pattern, stem_basename)) { + return info.vlog_level == kUseFlag ? current_global_v : info.vlog_level; + } + } + + return current_global_v; +} + +// Allocates memory. +int AppendVModuleLocked(absl::string_view module_pattern, int log_level) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + for (const auto& info : get_vmodule_info()) { + if (FNMatch(info.module_pattern, module_pattern)) { + // This is a memory optimization to avoid storing patterns that will never + // match due to exit early semantics. Primarily optimized for our own unit + // tests. + return info.vlog_level; + } + } + bool module_is_path = ModuleIsPath(module_pattern); + get_vmodule_info().emplace_back(std::string(module_pattern), module_is_path, + log_level); + return global_v; +} + +// Allocates memory. +int PrependVModuleLocked(absl::string_view module_pattern, int log_level) + ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex) { + absl::optional old_log_level; + for (const auto& info : get_vmodule_info()) { + if (FNMatch(info.module_pattern, module_pattern)) { + old_log_level = info.vlog_level; + break; + } + } + bool module_is_path = ModuleIsPath(module_pattern); + auto iter = get_vmodule_info().emplace(get_vmodule_info().cbegin(), + std::string(module_pattern), + module_is_path, log_level); + + // This is a memory optimization to avoid storing patterns that will never + // match due to exit early semantics. Primarily optimized for our own unit + // tests. + get_vmodule_info().erase( + std::remove_if(++iter, get_vmodule_info().end(), + [module_pattern](const VModuleInfo& info) { + return FNMatch(info.module_pattern, module_pattern); + }), + get_vmodule_info().cend()); + return old_log_level.value_or(global_v); +} +} // namespace + +int VLogLevel(absl::string_view file) ABSL_LOCKS_EXCLUDED(mutex) { + absl::base_internal::SpinLockHolder l(&mutex); + return VLogLevel(file, vmodule_info, global_v); +} + +int RegisterAndInitialize(VLogSite* v) ABSL_LOCKS_EXCLUDED(mutex) { + // std::memory_order_seq_cst is overkill in this function, but given that this + // path is intended to be slow, it's not worth the brain power to relax that. + VLogSite* h = site_list_head.load(std::memory_order_seq_cst); + + VLogSite* old = nullptr; + if (v->next_.compare_exchange_strong(old, h, std::memory_order_seq_cst, + std::memory_order_seq_cst)) { + // Multiple threads may attempt to register this site concurrently. + // By successfully setting `v->next` this thread commits to being *the* + // thread that installs `v` in the list. + while (!site_list_head.compare_exchange_weak( + h, v, std::memory_order_seq_cst, std::memory_order_seq_cst)) { + v->next_.store(h, std::memory_order_seq_cst); + } + } + + int old_v = VLogSite::kUninitialized; + int new_v = VLogLevel(v->file_); + // No loop, if someone else set this, we should respect their evaluation of + // `VLogLevel`. This may mean we return a stale `v`, but `v` itself will + // always arrive at the freshest value. Otherwise, we could be writing a + // stale value and clobbering the fresher one. + if (v->v_.compare_exchange_strong(old_v, new_v, std::memory_order_seq_cst, + std::memory_order_seq_cst)) { + return new_v; + } + return old_v; +} + +void UpdateVLogSites() ABSL_UNLOCK_FUNCTION(mutex) + ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) { + std::vector infos = get_vmodule_info(); + int current_global_v = global_v; + // We need to grab `GetUpdateSitesMutex()` before we release `mutex` to ensure + // that updates are not interleaved (resulting in an inconsistent final state) + // and to ensure that the final state in the sites matches the final state of + // `vmodule_info`. We unlock `mutex` to ensure that uninitialized sites don't + // have to wait on all updates in order to acquire `mutex` and initialize + // themselves. + absl::MutexLock ul(GetUpdateSitesMutex()); + mutex.Unlock(); + VLogSite* n = site_list_head.load(std::memory_order_seq_cst); + // Because sites are added to the list in the order they are executed, there + // tend to be clusters of entries with the same file. + const char* last_file = nullptr; + int last_file_level = 0; + while (n != nullptr) { + if (n->file_ != last_file) { + last_file = n->file_; + last_file_level = VLogLevel(n->file_, &infos, current_global_v); + } + n->v_.store(last_file_level, std::memory_order_seq_cst); + n = n->next_.load(std::memory_order_seq_cst); + } + if (update_callbacks) { + for (auto& cb : *update_callbacks) { + cb(); + } + } +} + +void UpdateVModule(absl::string_view vmodule) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + std::vector> glob_levels; + for (absl::string_view glob_level : absl::StrSplit(vmodule, ',')) { + const size_t eq = glob_level.rfind('='); + if (eq == glob_level.npos) continue; + const absl::string_view glob = glob_level.substr(0, eq); + int level; + if (!absl::SimpleAtoi(glob_level.substr(eq + 1), &level)) continue; + glob_levels.emplace_back(glob, level); + } + mutex.Lock(); // Unlocked by UpdateVLogSites(). + get_vmodule_info().clear(); + for (const auto& it : glob_levels) { + const absl::string_view glob = it.first; + const int level = it.second; + AppendVModuleLocked(glob, level); + } + UpdateVLogSites(); +} + +int UpdateGlobalVLogLevel(int v) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + mutex.Lock(); // Unlocked by UpdateVLogSites(). + const int old_global_v = global_v; + if (v == global_v) { + mutex.Unlock(); + return old_global_v; + } + global_v = v; + UpdateVLogSites(); + return old_global_v; +} + +int PrependVModule(absl::string_view module_pattern, int log_level) + ABSL_LOCKS_EXCLUDED(mutex, GetUpdateSitesMutex()) { + mutex.Lock(); // Unlocked by UpdateVLogSites(). + int old_v = PrependVModuleLocked(module_pattern, log_level); + UpdateVLogSites(); + return old_v; +} + +void OnVLogVerbosityUpdate(std::function cb) + ABSL_LOCKS_EXCLUDED(GetUpdateSitesMutex()) { + absl::MutexLock ul(GetUpdateSitesMutex()); + if (!update_callbacks) + update_callbacks = new std::vector>; + update_callbacks->push_back(std::move(cb)); +} + +VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v) { + return site_list_head.exchange(v, std::memory_order_seq_cst); +} + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.h b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.h new file mode 100644 index 0000000000000000000000000000000000000000..b6e322c4688e30a8aefb7ca9c15d53eaaadab46d --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config.h @@ -0,0 +1,163 @@ +// 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. +// +// ----------------------------------------------------------------------------- +// vlog_config.h +// ----------------------------------------------------------------------------- +// +// This header file defines `VLogSite`, a public primitive that represents +// a callsite for the `VLOG` family of macros and related libraries. +// It also declares and defines multiple internal utilities used to implement +// `VLOG`, such as `VLogSiteManager`. + +#ifndef ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ +#define ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ + +// IWYU pragma: private, include "absl/log/log.h" + +#include +#include +#include +#include +#include + +#include "absl/base/attributes.h" +#include "absl/base/config.h" +#include "absl/base/optimization.h" +#include "absl/base/thread_annotations.h" +#include "absl/strings/string_view.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { + +class SyntheticBinary; +class VLogSite; + +int RegisterAndInitialize(VLogSite* v); +void UpdateVLogSites(); +constexpr int kUseFlag = (std::numeric_limits::min)(); + +// Represents a unique callsite for a `VLOG()` or `VLOG_IS_ON()` call. +// +// Libraries that provide `VLOG`-like functionality should use this to +// efficiently handle --vmodule. +// +// VLogSite objects must not be destroyed until the program exits. Doing so will +// probably yield nasty segfaults in VLogSiteManager::UpdateLogSites(). The +// recommendation is to make all such objects function-local statics. +class VLogSite final { + public: + // `f` must not be destroyed until the program exits. + explicit constexpr VLogSite(const char* f) + : file_(f), v_(kUninitialized), next_(nullptr) {} + VLogSite(const VLogSite&) = delete; + VLogSite& operator=(const VLogSite&) = delete; + + // Inlining the function yields a ~3x performance improvement at the cost of a + // 1.5x code size increase at the call site. + // Takes locks but does not allocate memory. + ABSL_ATTRIBUTE_ALWAYS_INLINE + bool IsEnabled(int level) { + int stale_v = v_.load(std::memory_order_relaxed); + if (ABSL_PREDICT_TRUE(level > stale_v)) { + return false; + } + + // We put everything other than the fast path, i.e. vlogging is initialized + // but not on, behind an out-of-line function to reduce code size. + // "level" is almost always a call-site constant, so we can save a bit + // of code space by special-casing for a few common levels. +#if ABSL_HAVE_BUILTIN(__builtin_constant_p) || defined(__GNUC__) + if (__builtin_constant_p(level)) { + if (level == 0) return SlowIsEnabled0(stale_v); + if (level == 1) return SlowIsEnabled1(stale_v); + if (level == 2) return SlowIsEnabled2(stale_v); + if (level == 3) return SlowIsEnabled3(stale_v); + if (level == 4) return SlowIsEnabled4(stale_v); + if (level == 5) return SlowIsEnabled5(stale_v); + } +#endif + return SlowIsEnabled(stale_v, level); + } + + private: + friend int log_internal::RegisterAndInitialize(VLogSite* v); + friend void log_internal::UpdateVLogSites(); + friend class log_internal::SyntheticBinary; + static constexpr int kUninitialized = (std::numeric_limits::max)(); + + // SlowIsEnabled performs slower checks to determine whether a log site is + // enabled. Because it is expected to be called somewhat rarely + // (comparatively), it is not inlined to save on code size. + // + // Prerequisites to calling SlowIsEnabled: + // 1) stale_v is uninitialized OR + // 2) stale_v is initialized and >= level (meaning we must log). + // Takes locks but does not allocate memory. + ABSL_ATTRIBUTE_NOINLINE + bool SlowIsEnabled(int stale_v, int level); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled0(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled1(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled2(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled3(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled4(int stale_v); + ABSL_ATTRIBUTE_NOINLINE bool SlowIsEnabled5(int stale_v); + + // This object is too size-sensitive to use absl::string_view. + const char* const file_; + std::atomic v_; + std::atomic next_; +}; +static_assert(std::is_trivially_destructible::value, + "VLogSite must be trivially destructible"); + +// Returns the current verbose log level of `file`. +// Does not allocate memory. +int VLogLevel(absl::string_view file); + +// Registers a site `v` to get updated as `vmodule` and `v` change. Also +// initializes the site based on their current values, and returns that result. +// Does not allocate memory. +int RegisterAndInitialize(VLogSite* v); + +// Allocates memory. +void UpdateVLogSites(); + +// Completely overwrites the saved value of `vmodule`. +// Allocates memory. +void UpdateVModule(absl::string_view vmodule); + +// Updates the global verbosity level to `v` and returns the prior value. +// Allocates memory. +int UpdateGlobalVLogLevel(int v); + +// Atomically prepends `module_pattern=log_level` to the start of vmodule. +// Returns the prior value for `module_pattern` if there was an exact match and +// `global_v` otherwise. +// Allocates memory. +int PrependVModule(absl::string_view module_pattern, int log_level); + +// Registers `on_update` to be called whenever `v` or `vmodule` change. +// Allocates memory. +void OnVLogVerbosityUpdate(std::function cb); + +// Does not allocate memory. +VLogSite* SetVModuleListHeadForTestOnly(VLogSite* v); + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_VLOG_CONFIG_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/internal/vlog_config_benchmark.cc b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config_benchmark.cc new file mode 100644 index 0000000000000000000000000000000000000000..9004e2ee5e1c37ccc649ec8201f852c81e2cc7da --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/internal/vlog_config_benchmark.cc @@ -0,0 +1,187 @@ +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/base/config.h" +#include "absl/container/internal/layout.h" +#include "absl/log/internal/vlog_config.h" +#include "absl/memory/memory.h" +#include "absl/random/distributions.h" +#include "absl/strings/str_cat.h" +#include "benchmark/benchmark.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace log_internal { +// Performance of `UpdateLogSites` depends upon the number and organization of +// `VLogSite`s in the program. We can synthesize some on the heap to mimic +// their layout and linkage in static data. +class SyntheticBinary { + public: + explicit SyntheticBinary(const size_t num_tus, + const size_t max_extra_static_data_bytes_per_tu, + const size_t max_sites_per_tu, + const int num_shuffles) { + per_tu_data_.reserve(num_tus); + auto sites = absl::make_unique(num_tus * max_sites_per_tu); + for (size_t i = 0; i < num_tus; i++) { + const std::string filename = + absl::StrCat("directory-", i / 100, "/subdirectory-", i % 100 / 10, + "/file-", i % 10, ".cc"); + container_internal::Layout layout( + filename.size() + 1, + absl::LogUniform(bitgen_, 1, max_sites_per_tu), + absl::LogUniform(bitgen_, 0, + max_extra_static_data_bytes_per_tu)); + auto buf = absl::make_unique(layout.AllocSize()); + layout.PoisonPadding(buf.get()); + memcpy(layout.Pointer<0>(buf.get()), filename.c_str(), + filename.size() + 1); + for (VLogSite &site : layout.Slice<1>(buf.get())) { + sites[num_sites_++] = + new (&site) VLogSite(layout.Pointer<0>(buf.get())); + // The last one is a dangling pointer but will be fixed below. + site.next_.store(&site + 1, std::memory_order_seq_cst); + } + num_extra_static_data_bytes_ += layout.Size<2>(); + per_tu_data_.push_back(PerTU{layout, std::move(buf)}); + } + // Now link the files together back-to-front into a circular list. + for (size_t i = 0; i < num_tus; i++) { + auto &tu = per_tu_data_[i]; + auto &next_tu = per_tu_data_[(i + 1) % num_tus]; + tu.layout.Slice<1>(tu.buf.get()) + .back() + .next_.store(next_tu.layout.Pointer<1>(next_tu.buf.get()), + std::memory_order_seq_cst); + } + // Now do some shufflin'. + auto new_sites = absl::make_unique(num_sites_); + for (int shuffle_num = 0; shuffle_num < num_shuffles; shuffle_num++) { + // Each shuffle cuts the ring into three pieces and rearranges them. + const size_t cut_a = absl::Uniform(bitgen_, size_t{0}, num_sites_); + const size_t cut_b = absl::Uniform(bitgen_, size_t{0}, num_sites_); + const size_t cut_c = absl::Uniform(bitgen_, size_t{0}, num_sites_); + if (cut_a == cut_b || cut_b == cut_c || cut_a == cut_c) continue; + // The same cuts, sorted: + const size_t cut_1 = std::min({cut_a, cut_b, cut_c}); + const size_t cut_3 = std::max({cut_a, cut_b, cut_c}); + const size_t cut_2 = cut_a ^ cut_b ^ cut_c ^ cut_1 ^ cut_3; + VLogSite *const tmp = sites[cut_1]->next_.load(std::memory_order_seq_cst); + sites[cut_1]->next_.store( + sites[cut_2]->next_.load(std::memory_order_seq_cst), + std::memory_order_seq_cst); + sites[cut_2]->next_.store( + sites[cut_3]->next_.load(std::memory_order_seq_cst), + std::memory_order_seq_cst); + sites[cut_3]->next_.store(tmp, std::memory_order_seq_cst); + memcpy(&new_sites[0], &sites[0], sizeof(VLogSite *) * (cut_1 + 1)); + memcpy(&new_sites[cut_1 + 1], &sites[cut_2 + 1], + sizeof(VLogSite *) * (cut_3 - cut_2)); + memcpy(&new_sites[cut_1 + 1 + cut_3 - cut_2], &sites[cut_1 + 1], + sizeof(VLogSite *) * (cut_2 - cut_1)); + memcpy(&new_sites[cut_3 + 1], &sites[cut_3 + 1], + sizeof(VLogSite *) * (num_sites_ - cut_3 - 1)); + sites.swap(new_sites); + } + const char *last_file = nullptr; + for (size_t i = 0; i < num_sites_; i++) { + if (sites[i]->file_ == last_file) continue; + last_file = sites[i]->file_; + num_new_files_++; + } + absl::log_internal::SetVModuleListHeadForTestOnly(sites[0]); + sites[num_tus - 1]->next_.store(nullptr, std::memory_order_seq_cst); + } + ~SyntheticBinary() { + static_assert(std::is_trivially_destructible::value, ""); + absl::log_internal::SetVModuleListHeadForTestOnly(nullptr); + } + + size_t num_sites() const { return num_sites_; } + size_t num_new_files() const { return num_new_files_; } + size_t num_extra_static_data_bytes() const { + return num_extra_static_data_bytes_; + } + + private: + struct PerTU { + container_internal::Layout layout; + std::unique_ptr buf; + }; + + std::mt19937 bitgen_; + std::vector per_tu_data_; + size_t num_sites_ = 0; + size_t num_new_files_ = 0; + size_t num_extra_static_data_bytes_ = 0; +}; + +namespace { +void BM_UpdateVModuleEmpty(benchmark::State& state) { + SyntheticBinary bin(static_cast(state.range(0)), 10 * 1024 * 1024, + 256, state.range(1)); + for (auto s : state) { + absl::log_internal::UpdateVModule(""); + } + state.SetItemsProcessed(static_cast(bin.num_new_files())); +} +BENCHMARK(BM_UpdateVModuleEmpty) + ->ArgPair(100, 200) + ->ArgPair(1000, 2000) + ->ArgPair(10000, 20000); + +void BM_UpdateVModuleShort(benchmark::State& state) { + SyntheticBinary bin(static_cast(state.range(0)), 10 * 1024 * 1024, + 256, state.range(1)); + for (auto s : state) { + absl::log_internal::UpdateVModule("directory2/*=4"); + } + state.SetItemsProcessed(static_cast(bin.num_new_files())); +} +BENCHMARK(BM_UpdateVModuleShort) + ->ArgPair(100, 200) + ->ArgPair(1000, 2000) + ->ArgPair(10000, 20000); + +void BM_UpdateVModuleLong(benchmark::State& state) { + SyntheticBinary bin(static_cast(state.range(0)), 10 * 1024 * 1024, + 256, state.range(1)); + for (auto s : state) { + absl::log_internal::UpdateVModule( + "d?r?c?o?y2/*=4,d?*r?*c?**o?*y1/*=2,d?*rc?**o?*y3/*=2,," + "d?*r?*c?**o?*1/*=1,d?*r?**o?*y1/*=2,d?*r???***y1/*=7," + "d?*r?**o?*y1/aaa=6"); + } + state.SetItemsProcessed(static_cast(bin.num_new_files())); +} +BENCHMARK(BM_UpdateVModuleLong) + ->ArgPair(100, 200) + ->ArgPair(1000, 2000) + ->ArgPair(10000, 20000); +} // namespace +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl diff --git a/weight/_dep/abseil-cpp/absl/log/internal/voidify.h b/weight/_dep/abseil-cpp/absl/log/internal/voidify.h new file mode 100644 index 0000000000000000000000000000000000000000..8f62da20a0483708f374fff00e49d6b9e9e212d1 --- /dev/null +++ b/weight/_dep/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 + void operator&&(const T&) const&& {} +}; + +} // namespace log_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_LOG_INTERNAL_VOIDIFY_H_ diff --git a/weight/_dep/abseil-cpp/absl/log/scoped_mock_log_test.cc b/weight/_dep/abseil-cpp/absl/log/scoped_mock_log_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..42736939e15379eb001b222a1aa313d2625d47ff --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/scoped_mock_log_test.cc @@ -0,0 +1,295 @@ +// +// 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/scoped_mock_log.h" + +#include +#include // NOLINT(build/c++11) + +#include "gmock/gmock.h" +#include "gtest/gtest-spi.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/internal/test_matchers.h" +#include "absl/log/log.h" +#include "absl/memory/memory.h" +#include "absl/strings/match.h" +#include "absl/strings/string_view.h" +#include "absl/synchronization/barrier.h" +#include "absl/synchronization/notification.h" + +namespace { + +using ::testing::_; +using ::testing::AnyNumber; +using ::testing::Eq; +using ::testing::HasSubstr; +using ::testing::InSequence; +using ::testing::Lt; +using ::testing::Truly; +using absl::log_internal::SourceBasename; +using absl::log_internal::SourceFilename; +using absl::log_internal::SourceLine; +using absl::log_internal::TextMessageWithPrefix; +using absl::log_internal::ThreadID; + +auto* test_env ABSL_ATTRIBUTE_UNUSED = ::testing::AddGlobalTestEnvironment( + new absl::log_internal::LogTestEnvironment); + +#if GTEST_HAS_DEATH_TEST +TEST(ScopedMockLogDeathTest, + StartCapturingLogsCannotBeCalledWhenAlreadyCapturing) { + EXPECT_DEATH( + { + absl::ScopedMockLog log; + log.StartCapturingLogs(); + log.StartCapturingLogs(); + }, + "StartCapturingLogs"); +} + +TEST(ScopedMockLogDeathTest, StopCapturingLogsCannotBeCalledWhenNotCapturing) { + EXPECT_DEATH( + { + absl::ScopedMockLog log; + log.StopCapturingLogs(); + }, + "StopCapturingLogs"); +} + +TEST(ScopedMockLogDeathTest, FailsCheckIfStartCapturingLogsIsNeverCalled) { + EXPECT_DEATH({ absl::ScopedMockLog log; }, + "Did you forget to call StartCapturingLogs"); +} +#endif + +// Tests that ScopedMockLog intercepts LOG()s when it's alive. +TEST(ScopedMockLogTest, LogMockCatchAndMatchStrictExpectations) { + absl::ScopedMockLog log; + + // The following expectations must match in the order they appear. + InSequence s; + EXPECT_CALL(log, + Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger.")); + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2); + EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!")); + + log.StartCapturingLogs(); + LOG(WARNING) << "Danger."; + LOG(INFO) << "Working..."; + LOG(INFO) << "Working..."; + LOG(ERROR) << "Bad!!"; +} + +TEST(ScopedMockLogTest, LogMockCatchAndMatchSendExpectations) { + absl::ScopedMockLog log; + + EXPECT_CALL( + log, + Send(AllOf(SourceFilename(Eq("/my/very/very/very_long_source_file.cc")), + SourceBasename(Eq("very_long_source_file.cc")), + SourceLine(Eq(777)), ThreadID(Eq(absl::LogEntry::tid_t{1234})), + TextMessageWithPrefix(Truly([](absl::string_view msg) { + return absl::EndsWith( + msg, " very_long_source_file.cc:777] Info message"); + }))))); + + log.StartCapturingLogs(); + LOG(INFO) + .AtLocation("/my/very/very/very_long_source_file.cc", 777) + .WithThreadID(1234) + << "Info message"; +} + +TEST(ScopedMockLogTest, ScopedMockLogCanBeNice) { + absl::ScopedMockLog log; + + InSequence s; + EXPECT_CALL(log, + Log(absl::LogSeverity::kWarning, HasSubstr(__FILE__), "Danger.")); + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Working...")).Times(2); + EXPECT_CALL(log, Log(absl::LogSeverity::kError, _, "Bad!!")); + + log.StartCapturingLogs(); + + // Any number of these are OK. + LOG(INFO) << "Info message."; + // Any number of these are OK. + LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger "; + + LOG(WARNING) << "Danger."; + + // Any number of these are OK. + LOG(INFO) << "Info message."; + // Any number of these are OK. + LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger "; + + LOG(INFO) << "Working..."; + + // Any number of these are OK. + LOG(INFO) << "Info message."; + // Any number of these are OK. + LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger "; + + LOG(INFO) << "Working..."; + + // Any number of these are OK. + LOG(INFO) << "Info message."; + // Any number of these are OK. + LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger "; + + LOG(ERROR) << "Bad!!"; + + // Any number of these are OK. + LOG(INFO) << "Info message."; + // Any number of these are OK. + LOG(WARNING).AtLocation("SomeOtherFile.cc", 100) << "Danger "; +} + +// Tests that ScopedMockLog generates a test failure if a message is logged +// that is not expected (here, that means ERROR or FATAL). +TEST(ScopedMockLogTest, RejectsUnexpectedLogs) { + EXPECT_NONFATAL_FAILURE( + { + absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected); + // Any INFO and WARNING messages are permitted. + EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kError), _, _)) + .Times(AnyNumber()); + log.StartCapturingLogs(); + LOG(INFO) << "Ignored"; + LOG(WARNING) << "Ignored"; + LOG(ERROR) << "Should not be ignored"; + }, + "Should not be ignored"); +} + +TEST(ScopedMockLogTest, CapturesLogsAfterStartCapturingLogs) { + absl::SetStderrThreshold(absl::LogSeverityAtLeast::kInfinity); + absl::ScopedMockLog log; + + // The ScopedMockLog object shouldn't see these LOGs, as it hasn't + // started capturing LOGs yet. + LOG(INFO) << "Ignored info"; + LOG(WARNING) << "Ignored warning"; + LOG(ERROR) << "Ignored error"; + + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info")); + log.StartCapturingLogs(); + + // Only this LOG will be seen by the ScopedMockLog. + LOG(INFO) << "Expected info"; +} + +TEST(ScopedMockLogTest, DoesNotCaptureLogsAfterStopCapturingLogs) { + absl::ScopedMockLog log; + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, "Expected info")); + + log.StartCapturingLogs(); + + // This LOG should be seen by the ScopedMockLog. + LOG(INFO) << "Expected info"; + + log.StopCapturingLogs(); + + // The ScopedMockLog object shouldn't see these LOGs, as it has + // stopped capturing LOGs. + LOG(INFO) << "Ignored info"; + LOG(WARNING) << "Ignored warning"; + LOG(ERROR) << "Ignored error"; +} + +// Tests that all messages are intercepted regardless of issuing thread. The +// purpose of this test is NOT to exercise thread-safety. +TEST(ScopedMockLogTest, LogFromMultipleThreads) { + absl::ScopedMockLog log; + + // We don't establish an order to expectations here, since the threads may + // execute their log statements in different order. + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 1")); + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread 2")); + + log.StartCapturingLogs(); + + absl::Barrier barrier(2); + std::thread thread1([&barrier]() { + barrier.Block(); + LOG(INFO) << "Thread 1"; + }); + std::thread thread2([&barrier]() { + barrier.Block(); + LOG(INFO) << "Thread 2"; + }); + + thread1.join(); + thread2.join(); +} + +// Tests that no sequence will be imposed on two LOG message expectations from +// different threads. This test would actually deadlock if replaced to two LOG +// statements from the same thread. +TEST(ScopedMockLogTest, NoSequenceWithMultipleThreads) { + absl::ScopedMockLog log; + + absl::Barrier barrier(2); + EXPECT_CALL(log, Log(absl::LogSeverity::kInfo, _, _)) + .Times(2) + .WillRepeatedly([&barrier]() { barrier.Block(); }); + + log.StartCapturingLogs(); + + std::thread thread1([]() { LOG(INFO) << "Thread 1"; }); + std::thread thread2([]() { LOG(INFO) << "Thread 2"; }); + + thread1.join(); + thread2.join(); +} + +TEST(ScopedMockLogTsanTest, + ScopedMockLogCanBeDeletedWhenAnotherThreadIsLogging) { + auto log = absl::make_unique(); + EXPECT_CALL(*log, Log(absl::LogSeverity::kInfo, __FILE__, "Thread log")) + .Times(AnyNumber()); + + log->StartCapturingLogs(); + + absl::Notification logging_started; + + std::thread thread([&logging_started]() { + for (int i = 0; i < 100; ++i) { + if (i == 50) logging_started.Notify(); + LOG(INFO) << "Thread log"; + } + }); + + logging_started.WaitForNotification(); + log.reset(); + thread.join(); +} + +TEST(ScopedMockLogTest, AsLocalSink) { + absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected); + + EXPECT_CALL(log, Log(_, _, "two")); + EXPECT_CALL(log, Log(_, _, "three")); + + LOG(INFO) << "one"; + LOG(INFO).ToSinkOnly(&log.UseAsLocalSink()) << "two"; + LOG(INFO).ToSinkAlso(&log.UseAsLocalSink()) << "three"; +} + +} // namespace diff --git a/weight/_dep/abseil-cpp/absl/log/stripping_test.cc b/weight/_dep/abseil-cpp/absl/log/stripping_test.cc new file mode 100644 index 0000000000000000000000000000000000000000..271fae1d8dc2903de46435253606b2222fc66bca --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/stripping_test.cc @@ -0,0 +1,502 @@ +// +// 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. +// +// Tests for stripping of literal strings. +// --------------------------------------- +// +// When a `LOG` statement can be trivially proved at compile time to never fire, +// e.g. due to `ABSL_MIN_LOG_LEVEL`, `NDEBUG`, or some explicit condition, data +// streamed in can be dropped from the compiled program completely if they are +// not used elsewhere. This most commonly affects string literals, which users +// often want to strip to reduce binary size and/or redact information about +// their program's internals (e.g. in a release build). +// +// These tests log strings and then validate whether they appear in the compiled +// binary. This is done by opening the file corresponding to the running test +// and running a simple string search on its contents. The strings to be logged +// and searched for must be unique, and we must take care not to emit them into +// the binary in any other place, e.g. when searching for them. The latter is +// accomplished by computing them using base64; the source string appears in the +// binary but the target string is computed at runtime. + +#include + +#if defined(__MACH__) +#include +#elif defined(_WIN32) +#include +#include +#endif + +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/internal/strerror.h" +#include "absl/base/log_severity.h" +#include "absl/flags/internal/program_name.h" +#include "absl/log/check.h" +#include "absl/log/internal/test_helpers.h" +#include "absl/log/log.h" +#include "absl/status/status.h" +#include "absl/strings/escaping.h" +#include "absl/strings/str_format.h" +#include "absl/strings/string_view.h" + +// Set a flag that controls whether we actually execute fatal statements, but +// prevent the compiler from optimizing it out. +static volatile bool kReallyDie = false; + +namespace { +using ::testing::_; +using ::testing::Eq; +using ::testing::NotNull; + +using absl::log_internal::kAbslMinLogLevel; + +std::string Base64UnescapeOrDie(absl::string_view data) { + std::string decoded; + CHECK(absl::Base64Unescape(data, &decoded)); + return decoded; +} + +// ----------------------------------------------------------------------------- +// A Googletest matcher which searches the running binary for a given string +// ----------------------------------------------------------------------------- + +// This matcher is used to validate that literal strings streamed into +// `LOG` statements that ought to be compiled out (e.g. `LOG_IF(INFO, false)`) +// do not appear in the binary. +// +// Note that passing the string to be sought directly to `FileHasSubstr()` all +// but forces its inclusion in the binary regardless of the logging library's +// behavior. For example: +// +// LOG_IF(INFO, false) << "you're the man now dog"; +// // This will always pass: +// // EXPECT_THAT(fp, FileHasSubstr("you're the man now dog")); +// // So use this instead: +// EXPECT_THAT(fp, FileHasSubstr( +// Base64UnescapeOrDie("eW91J3JlIHRoZSBtYW4gbm93IGRvZw=="))); + +class FileHasSubstrMatcher final : public ::testing::MatcherInterface { + public: + explicit FileHasSubstrMatcher(absl::string_view needle) : needle_(needle) {} + + bool MatchAndExplain( + FILE* fp, ::testing::MatchResultListener* listener) const override { + std::string buf( + std::max(needle_.size() * 2, 163840000), '\0'); + size_t buf_start_offset = 0; // The file offset of the byte at `buf[0]`. + size_t buf_data_size = 0; // The number of bytes of `buf` which contain + // data. + + ::fseek(fp, 0, SEEK_SET); + while (true) { + // Fill the buffer to capacity or EOF: + while (buf_data_size < buf.size()) { + const size_t ret = fread(&buf[buf_data_size], sizeof(char), + buf.size() - buf_data_size, fp); + if (ret == 0) break; + buf_data_size += ret; + } + if (ferror(fp)) { + *listener << "error reading file"; + return false; + } + const absl::string_view haystack(&buf[0], buf_data_size); + const auto off = haystack.find(needle_); + if (off != haystack.npos) { + *listener << "string found at offset " << buf_start_offset + off; + return true; + } + if (feof(fp)) { + *listener << "string not found"; + return false; + } + // Copy the end of `buf` to the beginning so we catch matches that span + // buffer boundaries. `buf` and `buf_data_size` are always large enough + // that these ranges don't overlap. + memcpy(&buf[0], &buf[buf_data_size - needle_.size()], needle_.size()); + buf_start_offset += buf_data_size - needle_.size(); + buf_data_size = needle_.size(); + } + } + void DescribeTo(std::ostream* os) const override { + *os << "contains the string \"" << needle_ << "\" (base64(\"" + << Base64UnescapeOrDie(needle_) << "\"))"; + } + + void DescribeNegationTo(std::ostream* os) const override { + *os << "does not "; + DescribeTo(os); + } + + private: + std::string needle_; +}; + +class StrippingTest : public ::testing::Test { + protected: + void SetUp() override { +#ifndef NDEBUG + // Non-optimized builds don't necessarily eliminate dead code at all, so we + // don't attempt to validate stripping against such builds. + GTEST_SKIP() << "StrippingTests skipped since this build is not optimized"; +#elif defined(__EMSCRIPTEN__) + // These tests require a way to examine the running binary and look for + // strings; there's no portable way to do that. + GTEST_SKIP() + << "StrippingTests skipped since this platform is not optimized"; +#endif + } + + // Opens this program's executable file. Returns `nullptr` and writes to + // `stderr` on failure. + std::unique_ptr> OpenTestExecutable() { +#if defined(__linux__) + std::unique_ptr> fp( + fopen("/proc/self/exe", "rb"), [](FILE* fp) { fclose(fp); }); + if (!fp) { + const std::string err = absl::base_internal::StrError(errno); + absl::FPrintF(stderr, "Failed to open /proc/self/exe: %s\n", err); + } + return fp; +#elif defined(__Fuchsia__) + // TODO(b/242579714): We need to restore the test coverage on this platform. + std::unique_ptr> fp( + fopen(absl::StrCat("/pkg/bin/", + absl::flags_internal::ShortProgramInvocationName()) + .c_str(), + "rb"), + [](FILE* fp) { fclose(fp); }); + if (!fp) { + const std::string err = absl::base_internal::StrError(errno); + absl::FPrintF(stderr, "Failed to open /pkg/bin/: %s\n", err); + } + return fp; +#elif defined(__MACH__) + uint32_t size = 0; + int ret = _NSGetExecutablePath(nullptr, &size); + if (ret != -1) { + absl::FPrintF(stderr, + "Failed to get executable path: " + "_NSGetExecutablePath(nullptr) returned %d\n", + ret); + return nullptr; + } + std::string path(size, '\0'); + ret = _NSGetExecutablePath(&path[0], &size); + if (ret != 0) { + absl::FPrintF( + stderr, + "Failed to get executable path: _NSGetExecutablePath(buffer) " + "returned %d\n", + ret); + return nullptr; + } + std::unique_ptr> fp( + fopen(path.c_str(), "rb"), [](FILE* fp) { fclose(fp); }); + if (!fp) { + const std::string err = absl::base_internal::StrError(errno); + absl::FPrintF(stderr, "Failed to open executable at %s: %s\n", path, err); + } + return fp; +#elif defined(_WIN32) + std::basic_string path(4096, _T('\0')); + while (true) { + const uint32_t ret = ::GetModuleFileName(nullptr, &path[0], + static_cast(path.size())); + if (ret == 0) { + absl::FPrintF( + stderr, + "Failed to get executable path: GetModuleFileName(buffer) " + "returned 0\n"); + return nullptr; + } + if (ret < path.size()) break; + path.resize(path.size() * 2, _T('\0')); + } + std::unique_ptr> fp( + _tfopen(path.c_str(), _T("rb")), [](FILE* fp) { fclose(fp); }); + if (!fp) absl::FPrintF(stderr, "Failed to open executable\n"); + return fp; +#else + absl::FPrintF(stderr, + "OpenTestExecutable() unimplemented on this platform\n"); + return nullptr; +#endif + } + + ::testing::Matcher FileHasSubstr(absl::string_view needle) { + return MakeMatcher(new FileHasSubstrMatcher(needle)); + } +}; + +// This tests whether out methodology for testing stripping works on this +// platform by looking for one string that definitely ought to be there and one +// that definitely ought not to. If this fails, none of the `StrippingTest`s +// are going to produce meaningful results. +TEST_F(StrippingTest, Control) { + constexpr char kEncodedPositiveControl[] = + "U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w="; + const std::string encoded_negative_control = + absl::Base64Escape("StrippingTest.NegativeControl"); + + // Verify this mainly so we can encode other strings and know definitely they + // won't encode to `kEncodedPositiveControl`. + EXPECT_THAT(Base64UnescapeOrDie("U3RyaXBwaW5nVGVzdC5Qb3NpdGl2ZUNvbnRyb2w="), + Eq("StrippingTest.PositiveControl")); + + auto exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + EXPECT_THAT(exe.get(), FileHasSubstr(kEncodedPositiveControl)); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(encoded_negative_control))); +} + +TEST_F(StrippingTest, Literal) { + // We need to load a copy of the needle string into memory (so we can search + // for it) without leaving it lying around in plaintext in the executable file + // as would happen if we used a literal. We might (or might not) leave it + // lying around later; that's what the tests are for! + const std::string needle = absl::Base64Escape("StrippingTest.Literal"); + LOG(INFO) << "U3RyaXBwaW5nVGVzdC5MaXRlcmFs"; + auto exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle))); + } +} + +TEST_F(StrippingTest, LiteralInExpression) { + // We need to load a copy of the needle string into memory (so we can search + // for it) without leaving it lying around in plaintext in the executable file + // as would happen if we used a literal. We might (or might not) leave it + // lying around later; that's what the tests are for! + const std::string needle = + absl::Base64Escape("StrippingTest.LiteralInExpression"); + LOG(INFO) << absl::StrCat("secret: ", + "U3RyaXBwaW5nVGVzdC5MaXRlcmFsSW5FeHByZXNzaW9u"); + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + if (absl::LogSeverity::kInfo >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle))); + } +} + +TEST_F(StrippingTest, Fatal) { + // We need to load a copy of the needle string into memory (so we can search + // for it) without leaving it lying around in plaintext in the executable file + // as would happen if we used a literal. We might (or might not) leave it + // lying around later; that's what the tests are for! + const std::string needle = absl::Base64Escape("StrippingTest.Fatal"); + // We don't care if the LOG statement is actually executed, we're just + // checking that it's stripped. + if (kReallyDie) LOG(FATAL) << "U3RyaXBwaW5nVGVzdC5GYXRhbA=="; + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle))); + } +} + +TEST_F(StrippingTest, DFatal) { + // We need to load a copy of the needle string into memory (so we can search + // for it) without leaving it lying around in plaintext in the executable file + // as would happen if we used a literal. We might (or might not) leave it + // lying around later; that's what the tests are for! + const std::string needle = absl::Base64Escape("StrippingTest.DFatal"); + // We don't care if the LOG statement is actually executed, we're just + // checking that it's stripped. + if (kReallyDie) LOG(DFATAL) << "U3RyaXBwaW5nVGVzdC5ERmF0YWw="; + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + // `DFATAL` can be `ERROR` or `FATAL`, and a compile-time optimizer doesn't + // know which, because `absl::kLogDebugFatal` is declared `extern` and defined + // in another TU. Link-time optimization might do better. We have six cases: + // | `AMLL` is-> | `<=ERROR` | `FATAL` | `>FATAL` | + // | ------------------- | --------- | ------- | -------- | + // | `DFATAL` is `ERROR` | present | ? | stripped | + // | `DFATAL` is `FATAL` | present | present | stripped | + + // These constexpr variables are used to suppress unreachable code warnings + // in the if-else statements below. + + // "present" in the table above: `DFATAL` exceeds `ABSL_MIN_LOG_LEVEL`, so + // `DFATAL` statements should not be stripped (and they should be logged + // when executed, but that's a different testsuite). + constexpr bool kExpectPresent = absl::kLogDebugFatal >= kAbslMinLogLevel; + + // "stripped" in the table above: even though the compiler may not know + // which value `DFATAL` has, it should be able to strip it since both + // possible values ought to be stripped. + constexpr bool kExpectStripped = kAbslMinLogLevel > absl::LogSeverity::kFatal; + + if (kExpectPresent) { + EXPECT_THAT(exe.get(), FileHasSubstr(needle)); + } else if (kExpectStripped) { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle))); + } else { + // "?" in the table above; may or may not be stripped depending on whether + // any link-time optimization is done. Either outcome is ok. + } +} + +TEST_F(StrippingTest, Level) { + const std::string needle = absl::Base64Escape("StrippingTest.Level"); + volatile auto severity = absl::LogSeverity::kWarning; + // Ensure that `severity` is not a compile-time constant to prove that + // stripping works regardless: + LOG(LEVEL(severity)) << "U3RyaXBwaW5nVGVzdC5MZXZlbA=="; + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + // This can't be stripped at compile-time because it might evaluate to a + // level that shouldn't be stripped. + EXPECT_THAT(exe.get(), FileHasSubstr(needle)); + } else { +#if (defined(_MSC_VER) && !defined(__clang__)) || defined(__APPLE__) + // Dead code elimination misses this case. +#else + // All levels should be stripped, so it doesn't matter what the severity + // winds up being. + EXPECT_THAT(exe.get(), Not(FileHasSubstr(needle))); +#endif + } +} + +TEST_F(StrippingTest, Check) { + // Here we also need a variable name with enough entropy that it's unlikely to + // appear in the binary by chance. `volatile` keeps the tautological + // comparison (and the rest of the `CHECK`) from being optimized away. + const std::string var_needle = absl::Base64Escape("StrippingTestCheckVar"); + const std::string msg_needle = absl::Base64Escape("StrippingTest.Check"); + volatile int U3RyaXBwaW5nVGVzdENoZWNrVmFy = 0xCAFE; + // We don't care if the CHECK is actually executed, just that stripping works. + // Hiding it behind `kReallyDie` works around some overly aggressive + // optimizations in older versions of MSVC. + if (kReallyDie) { + CHECK(U3RyaXBwaW5nVGVzdENoZWNrVmFy != U3RyaXBwaW5nVGVzdENoZWNrVmFy) + << "U3RyaXBwaW5nVGVzdC5DaGVjaw=="; + } + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle)); + EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle))); + } +} + +TEST_F(StrippingTest, CheckOp) { + // See `StrippingTest.Check` for some hairy implementation notes. + const std::string var_needle1 = + absl::Base64Escape("StrippingTestCheckOpVar1"); + const std::string var_needle2 = + absl::Base64Escape("StrippingTestCheckOpVar2"); + const std::string msg_needle = absl::Base64Escape("StrippingTest.CheckOp"); + volatile int U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIx = 0xFEED; + volatile int U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIy = 0xCAFE; + if (kReallyDie) { + CHECK_EQ(U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIx, U3RyaXBwaW5nVGVzdENoZWNrT3BWYXIy) + << "U3RyaXBwaW5nVGVzdC5DaGVja09w"; + } + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle1)); + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle2)); + EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle1))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle2))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle))); + } +} + +TEST_F(StrippingTest, CheckStrOp) { + // See `StrippingTest.Check` for some hairy implementation notes. + const std::string var_needle1 = + absl::Base64Escape("StrippingTestCheckStrOpVar1"); + const std::string var_needle2 = + absl::Base64Escape("StrippingTestCheckStrOpVar2"); + const std::string msg_needle = absl::Base64Escape("StrippingTest.CheckStrOp"); + const char *volatile U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIx = "FEED"; + const char *volatile U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIy = "CAFE"; + if (kReallyDie) { + CHECK_STREQ(U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIx, + U3RyaXBwaW5nVGVzdENoZWNrU3RyT3BWYXIy) + << "U3RyaXBwaW5nVGVzdC5DaGVja1N0ck9w"; + } + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle1)); + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle2)); + EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle1))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle2))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle))); + } +} + +TEST_F(StrippingTest, CheckOk) { + // See `StrippingTest.Check` for some hairy implementation notes. + const std::string var_needle = absl::Base64Escape("StrippingTestCheckOkVar1"); + const std::string msg_needle = absl::Base64Escape("StrippingTest.CheckOk"); + volatile bool x = false; + auto U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx = absl::OkStatus(); + if (x) { + U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx = + absl::InvalidArgumentError("Stripping this is not my job!"); + } + if (kReallyDie) { + CHECK_OK(U3RyaXBwaW5nVGVzdENoZWNrT2tWYXIx) + << "U3RyaXBwaW5nVGVzdC5DaGVja09r"; + } + + std::unique_ptr> exe = OpenTestExecutable(); + ASSERT_THAT(exe, NotNull()); + + if (absl::LogSeverity::kFatal >= kAbslMinLogLevel) { + EXPECT_THAT(exe.get(), FileHasSubstr(var_needle)); + EXPECT_THAT(exe.get(), FileHasSubstr(msg_needle)); + } else { + EXPECT_THAT(exe.get(), Not(FileHasSubstr(var_needle))); + EXPECT_THAT(exe.get(), Not(FileHasSubstr(msg_needle))); + } +} + +} // namespace diff --git a/weight/_dep/abseil-cpp/absl/log/vlog_is_on.h b/weight/_dep/abseil-cpp/absl/log/vlog_is_on.h new file mode 100644 index 0000000000000000000000000000000000000000..789865138033439021c95d6562a130272f1b816d --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/log/vlog_is_on.h @@ -0,0 +1,72 @@ +// 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/vlog_is_on.h +// ----------------------------------------------------------------------------- +// +// This header defines the `VLOG_IS_ON()` macro that controls the +// variable-verbosity conditional logging. +// +// It's used by `VLOG` in log.h, or it can also be used directly like this: +// +// if (VLOG_IS_ON(2)) { +// foo_server.RecomputeStatisticsExpensive(); +// LOG(INFO) << foo_server.LastStatisticsAsString(); +// } +// +// Each source file has an effective verbosity level that's a non-negative +// integer computed from the `--vmodule` and `--v` flags. +// `VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity +// level is greater than or equal to `n`. +// +// `--vmodule` takes a comma-delimited list of key=value pairs. Each key is a +// pattern matched against filenames, and the values give the effective severity +// level applied to matching files. '?' and '*' characters in patterns are +// interpreted as single-character and zero-or-more-character wildcards. +// Patterns including a slash character are matched against full pathnames, +// while those without are matched against basenames only. One suffix (i.e. the +// last . and everything after it) is stripped from each filename prior to +// matching, as is the special suffix "-inl". +// +// Files are matched against globs in `--vmodule` in order, and the first match +// determines the verbosity level. +// +// Files which do not match any pattern in `--vmodule` use the value of `--v` as +// their effective verbosity level. The default is 0. +// +// SetVLOGLevel helper function is provided to do limited dynamic control over +// V-logging by appending to `--vmodule`. Because these go at the beginning of +// the list, they take priority over any globs previously added. +// +// Resetting --vmodule will override all previous modifications to `--vmodule`, +// including via SetVLOGLevel. + +#ifndef ABSL_LOG_VLOG_IS_ON_H_ +#define ABSL_LOG_VLOG_IS_ON_H_ + +#include "absl/log/absl_vlog_is_on.h" // IWYU pragma: export + +// IWYU pragma: private, include "absl/log/log.h" + +// Each VLOG_IS_ON call site gets its own VLogSite that registers with the +// global linked list of sites to asynchronously update its verbosity level on +// changes to --v or --vmodule. The verbosity can also be set by manually +// calling SetVLOGLevel. +// +// VLOG_IS_ON is not async signal safe, but it is guaranteed not to allocate +// new memory. +#define VLOG_IS_ON(verbose_level) ABSL_VLOG_IS_ON(verbose_level) + +#endif // ABSL_LOG_VLOG_IS_ON_H_ diff --git a/weight/_dep/abseil-cpp/absl/memory/BUILD.bazel b/weight/_dep/abseil-cpp/absl/memory/BUILD.bazel new file mode 100644 index 0000000000000000000000000000000000000000..4573f17d26ef52e59d9c2a4318a40154e85754c7 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/memory/BUILD.bazel @@ -0,0 +1,60 @@ +# +# Copyright 2019 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 = ["//visibility:public"], + features = [ + "header_modules", + "layering_check", + "parse_headers", + ], +) + +licenses(["notice"]) + +cc_library( + name = "memory", + hdrs = ["memory.h"], + copts = ABSL_DEFAULT_COPTS, + defines = select({ + "//conditions:default": [], + }), + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:core_headers", + "//absl/meta:type_traits", + ], +) + +cc_test( + name = "memory_test", + srcs = ["memory_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":memory", + "//absl/base:core_headers", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/weight/_dep/abseil-cpp/absl/memory/CMakeLists.txt b/weight/_dep/abseil-cpp/absl/memory/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c5ed4b4255851376c42fbb4452ae71bafba2a399 --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/memory/CMakeLists.txt @@ -0,0 +1,41 @@ +# +# Copyright 2017 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. +# + +absl_cc_library( + NAME + memory + HDRS + "memory.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::core_headers + absl::meta + PUBLIC +) + +absl_cc_test( + NAME + memory_test + SRCS + "memory_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::memory + absl::core_headers + GTest::gmock_main +) diff --git a/weight/_dep/abseil-cpp/absl/memory/memory.h b/weight/_dep/abseil-cpp/absl/memory/memory.h new file mode 100644 index 0000000000000000000000000000000000000000..3508135c3338bbb2c2d8b4aed5904b8b4b931d1b --- /dev/null +++ b/weight/_dep/abseil-cpp/absl/memory/memory.h @@ -0,0 +1,278 @@ +// Copyright 2017 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: memory.h +// ----------------------------------------------------------------------------- +// +// This header file contains utility functions for managing the creation and +// conversion of smart pointers. This file is an extension to the C++ +// standard library header file. + +#ifndef ABSL_MEMORY_MEMORY_H_ +#define ABSL_MEMORY_MEMORY_H_ + +#include +#include +#include +#include +#include +#include + +#include "absl/base/macros.h" +#include "absl/meta/type_traits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// ----------------------------------------------------------------------------- +// Function Template: WrapUnique() +// ----------------------------------------------------------------------------- +// +// Adopts ownership from a raw pointer and transfers it to the returned +// `std::unique_ptr`, whose type is deduced. Because of this deduction, *do not* +// specify the template type `T` when calling `WrapUnique`. +// +// Example: +// X* NewX(int, int); +// auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr. +// +// Do not call WrapUnique with an explicit type, as in +// `WrapUnique(NewX(1, 2))`. The purpose of WrapUnique is to automatically +// deduce the pointer type. If you wish to make the type explicit, just use +// `std::unique_ptr` directly. +// +// auto x = std::unique_ptr(NewX(1, 2)); +// - or - +// std::unique_ptr x(NewX(1, 2)); +// +// While `absl::WrapUnique` is useful for capturing the output of a raw +// pointer factory, prefer 'absl::make_unique(args...)' over +// 'absl::WrapUnique(new T(args...))'. +// +// auto x = WrapUnique(new X(1, 2)); // works, but nonideal. +// auto x = make_unique(1, 2); // safer, standard, avoids raw 'new'. +// +// Note that `absl::WrapUnique(p)` is valid only if `delete p` is a valid +// expression. In particular, `absl::WrapUnique()` cannot wrap pointers to +// arrays, functions or void, and it must not be used to capture pointers +// obtained from array-new expressions (even though that would compile!). +template +std::unique_ptr WrapUnique(T* ptr) { + static_assert(!std::is_array::value, "array types are unsupported"); + static_assert(std::is_object::value, "non-object types are unsupported"); + return std::unique_ptr(ptr); +} + +// ----------------------------------------------------------------------------- +// Function Template: make_unique() +// ----------------------------------------------------------------------------- +// +// Creates a `std::unique_ptr<>`, while avoiding issues creating temporaries +// during the construction process. `absl::make_unique<>` also avoids redundant +// type declarations, by avoiding the need to explicitly use the `new` operator. +// +// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique +// +// For more background on why `std::unique_ptr(new T(a,b))` is problematic, +// see Herb Sutter's explanation on +// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/]. +// (In general, reviewers should treat `new T(a,b)` with scrutiny.) +// +// Historical note: Abseil once provided a C++11 compatible implementation of +// the C++14's `std::make_unique`. Now that C++11 support has been sunsetted, +// `absl::make_unique` simply uses the STL-provided implementation. New code +// should use `std::make_unique`. +using std::make_unique; + +// ----------------------------------------------------------------------------- +// Function Template: RawPtr() +// ----------------------------------------------------------------------------- +// +// Extracts the raw pointer from a pointer-like value `ptr`. `absl::RawPtr` is +// useful within templates that need to handle a complement of raw pointers, +// `std::nullptr_t`, and smart pointers. +template +auto RawPtr(T&& ptr) -> decltype(std::addressof(*ptr)) { + // ptr is a forwarding reference to support Ts with non-const operators. + return (ptr != nullptr) ? std::addressof(*ptr) : nullptr; +} +inline std::nullptr_t RawPtr(std::nullptr_t) { return nullptr; } + +// ----------------------------------------------------------------------------- +// Function Template: ShareUniquePtr() +// ----------------------------------------------------------------------------- +// +// Adopts a `std::unique_ptr` rvalue and returns a `std::shared_ptr` of deduced +// type. Ownership (if any) of the held value is transferred to the returned +// shared pointer. +// +// Example: +// +// auto up = absl::make_unique(10); +// auto sp = absl::ShareUniquePtr(std::move(up)); // shared_ptr +// CHECK_EQ(*sp, 10); +// CHECK(up == nullptr); +// +// Note that this conversion is correct even when T is an array type, and more +// generally it works for *any* deleter of the `unique_ptr` (single-object +// deleter, array deleter, or any custom deleter), since the deleter is adopted +// by the shared pointer as well. The deleter is copied (unless it is a +// reference). +// +// Implements the resolution of [LWG 2415](http://wg21.link/lwg2415), by which a +// null shared pointer does not attempt to call the deleter. +template +std::shared_ptr ShareUniquePtr(std::unique_ptr&& ptr) { + return ptr ? std::shared_ptr(std::move(ptr)) : std::shared_ptr(); +} + +// ----------------------------------------------------------------------------- +// Function Template: WeakenPtr() +// ----------------------------------------------------------------------------- +// +// Creates a weak pointer associated with a given shared pointer. The returned +// value is a `std::weak_ptr` of deduced type. +// +// Example: +// +// auto sp = std::make_shared(10); +// auto wp = absl::WeakenPtr(sp); +// CHECK_EQ(sp.get(), wp.lock().get()); +// sp.reset(); +// CHECK(wp.lock() == nullptr); +// +template +std::weak_ptr WeakenPtr(const std::shared_ptr& ptr) { + return std::weak_ptr(ptr); +} + +// ----------------------------------------------------------------------------- +// Class Template: pointer_traits +// ----------------------------------------------------------------------------- +// +// Historical note: Abseil once provided an implementation of +// `std::pointer_traits` for platforms that had not yet provided it. Those +// platforms are no longer supported. New code should simply use +// `std::pointer_traits`. +using std::pointer_traits; + +// ----------------------------------------------------------------------------- +// Class Template: allocator_traits +// ----------------------------------------------------------------------------- +// +// Historical note: Abseil once provided an implementation of +// `std::allocator_traits` for platforms that had not yet provided it. Those +// platforms are no longer supported. New code should simply use +// `std::allocator_traits`. +using std::allocator_traits; + +namespace memory_internal { + +// ExtractOr::type evaluates to E if possible. Otherwise, D. +template