aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp/absl
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2023-03-05 12:50:38 +0300
committerthegeorg <thegeorg@yandex-team.com>2023-03-05 12:50:38 +0300
commitdc697e5cf6f0cd4d1ff44614a4b1c09a50583d94 (patch)
tree151bc18c91b9bb7e7b26791e4d49d387a43f798b /contrib/restricted/abseil-cpp/absl
parentab17e559a95ccff2508caeca81d07daafaabf92b (diff)
downloadydb-dc697e5cf6f0cd4d1ff44614a4b1c09a50583d94.tar.gz
Update contrib/restricted/abseil-cpp to 20230125.0
Diffstat (limited to 'contrib/restricted/abseil-cpp/absl')
-rw-r--r--contrib/restricted/abseil-cpp/absl/CMakeLists.txt1
-rw-r--r--contrib/restricted/abseil-cpp/absl/algorithm/container.h113
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/attributes.h58
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/config.h49
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/cycleclock.h21
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/cycleclock_config.h55
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/direct_mmap.h3
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.h2
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc16
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h47
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/spinlock.cc6
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/spinlock_win32.inc5
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/strerror.cc8
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc24
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h9
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h43
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h62
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/macros.h25
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/optimization.h64
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/options.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/policy_checks.h28
-rw-r--r--contrib/restricted/abseil-cpp/absl/cleanup/cleanup.h140
-rw-r--r--contrib/restricted/abseil-cpp/absl/cleanup/internal/cleanup.h100
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/fixed_array.h12
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h7
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/inlined_vector.h84
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/common.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h132
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h14
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_traits.h59
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.cc55
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h60
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h142
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc159
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h1002
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/crc32c.cc99
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/crc32c.h183
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc256
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h57
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc468
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc.h91
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h269
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc32c.h39
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc32c_inline.h72
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc130
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.h159
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_internal.h179
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h119
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc75
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc434
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc93
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc725
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_arm_intrinsics.h79
-rw-r--r--contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h180
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc21
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc2
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc105
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h2
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.cc25
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/examine_stack.cc14
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc20
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc2
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc125
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc9
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc41
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/vdso_support.cc5
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/leak_check.h2
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/symbolize_darwin.inc5
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc212
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/symbolize_win32.inc13
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/internal/parse.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc10
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/marshalling.h2
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/parse.cc87
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/internal/city.cc20
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/internal/hash.h22
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc17
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/CMakeLists.darwin.txt46
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux-aarch64.txt47
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux.txt47
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/CMakeLists.txt15
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/die_if_null.cc32
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/die_if_null.h76
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/flags.cc112
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/globals.cc148
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/globals.h165
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/initialize.cc34
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/initialize.h45
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/append_truncated.h47
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc118
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/check_op.h392
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc83
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/conditions.h222
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/config.h45
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/flags.h53
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/globals.cc125
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/globals.h101
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc203
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_format.h78
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h212
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc618
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_message.h355
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc296
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.h54
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc35
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/nullguard.h88
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/nullstream.h134
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/proto.cc220
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/proto.h288
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/strip.h71
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/voidify.h44
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log.h308
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_entry.cc29
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_entry.h220
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_sink.cc23
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_sink.h64
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h61
-rw-r--r--contrib/restricted/abseil-cpp/absl/memory/memory.h472
-rw-r--r--contrib/restricted/abseil-cpp/absl/meta/type_traits.h116
-rw-r--r--contrib/restricted/abseil-cpp/absl/numeric/bits.h5
-rw-r--r--contrib/restricted/abseil-cpp/absl/numeric/int128.cc18
-rw-r--r--contrib/restricted/abseil-cpp/absl/profiling/internal/sample_recorder.h20
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/fast_uniform_bits.h3
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/pool_urbg.cc18
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/seed_material.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h1
-rw-r--r--contrib/restricted/abseil-cpp/absl/status/status.cc31
-rw-r--r--contrib/restricted/abseil-cpp/absl/status/status.h4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/CMakeLists.darwin.txt10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux-aarch64.txt10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux.txt10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/ascii.cc10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/charconv.cc630
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord.cc132
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord.h151
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord_buffer.h13
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/escaping.cc135
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/escaping.h43
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h26
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h396
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.cc12
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.h40
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc10
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.cc16
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.h9
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions.h22
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc13
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.h14
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cordz_statistics.h8
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc93
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h34
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc22
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h16
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h55
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc15
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc21
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h45
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc159
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h155
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc5
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h7
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h336
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h351
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc3
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h6
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc396
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc219
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h111
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h3
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc28
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.h57
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/numbers.cc65
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_cat.cc15
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_cat.h53
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/str_format.h80
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/string_view.cc12
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/string_view.h13
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/substitute.cc14
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/substitute.h66
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/internal/futex.h37
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/internal/graphcycles.cc68
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/internal/kernel_timeout.h30
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc159
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/mutex.h131
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/notification.cc1
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/notification.h1
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/civil_time.cc26
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/civil_time.h25
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/clock.cc26
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/duration.cc14
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/format.cc3
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc2
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc31
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc13
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc71
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/time.cc4
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/time.h411
-rw-r--r--contrib/restricted/abseil-cpp/absl/types/internal/span.h49
-rw-r--r--contrib/restricted/abseil-cpp/absl/types/internal/variant.h68
-rw-r--r--contrib/restricted/abseil-cpp/absl/types/span.h36
209 files changed, 15058 insertions, 3500 deletions
diff --git a/contrib/restricted/abseil-cpp/absl/CMakeLists.txt b/contrib/restricted/abseil-cpp/absl/CMakeLists.txt
index f6aaf30d40..18625818a1 100644
--- a/contrib/restricted/abseil-cpp/absl/CMakeLists.txt
+++ b/contrib/restricted/abseil-cpp/absl/CMakeLists.txt
@@ -13,6 +13,7 @@ add_subdirectory(debugging)
add_subdirectory(flags)
add_subdirectory(functional)
add_subdirectory(hash)
+add_subdirectory(log)
add_subdirectory(memory)
add_subdirectory(meta)
add_subdirectory(numeric)
diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/container.h b/contrib/restricted/abseil-cpp/absl/algorithm/container.h
index 26b1952923..c7782d4f03 100644
--- a/contrib/restricted/abseil-cpp/absl/algorithm/container.h
+++ b/contrib/restricted/abseil-cpp/absl/algorithm/container.h
@@ -77,9 +77,8 @@ using ContainerIterPairType =
decltype(std::make_pair(ContainerIter<C1>(), ContainerIter<C2>()));
template <typename C>
-using ContainerDifferenceType =
- decltype(std::distance(std::declval<ContainerIter<C>>(),
- std::declval<ContainerIter<C>>()));
+using ContainerDifferenceType = decltype(std::distance(
+ std::declval<ContainerIter<C>>(), std::declval<ContainerIter<C>>()));
template <typename C>
using ContainerPointerType =
@@ -97,10 +96,14 @@ using ContainerPointerType =
// These are meant for internal use only.
template <typename C>
-ContainerIter<C> c_begin(C& c) { return begin(c); }
+ContainerIter<C> c_begin(C& c) {
+ return begin(c);
+}
template <typename C>
-ContainerIter<C> c_end(C& c) { return end(c); }
+ContainerIter<C> c_end(C& c) {
+ return end(c);
+}
template <typename T>
struct IsUnorderedContainer : std::false_type {};
@@ -343,8 +346,8 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
// return the first element where two ordered containers differ. Applies `==` to
// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2>
-container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2) {
+container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(C1& c1,
+ C2& c2) {
auto first1 = container_algorithm_internal::c_begin(c1);
auto last1 = container_algorithm_internal::c_end(c1);
auto first2 = container_algorithm_internal::c_begin(c2);
@@ -365,8 +368,8 @@ c_mismatch(C1& c1, C2& c2) {
// the function's test condition. Applies `pred`to the first N elements of `c1`
// and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2, typename BinaryPredicate>
-container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
+container_algorithm_internal::ContainerIterPairType<C1, C2> c_mismatch(
+ C1& c1, C2& c2, BinaryPredicate pred) {
auto first1 = container_algorithm_internal::c_begin(c1);
auto last1 = container_algorithm_internal::c_end(c1);
auto first2 = container_algorithm_internal::c_begin(c2);
@@ -655,11 +658,10 @@ OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value,
// some condition, and return the results within an iterator.
template <typename C, typename OutputIterator, typename Pred, typename T>
OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred,
- T&& new_value) {
+ const T& new_value) {
return std::replace_copy_if(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), result,
- std::forward<Pred>(pred),
- std::forward<T>(new_value));
+ std::forward<Pred>(pred), new_value);
}
// c_fill()
@@ -667,9 +669,9 @@ OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred,
// Container-based version of the <algorithm> `std::fill()` function to fill a
// container with some value.
template <typename C, typename T>
-void c_fill(C& c, T&& value) {
+void c_fill(C& c, const T& value) {
std::fill(container_algorithm_internal::c_begin(c),
- container_algorithm_internal::c_end(c), std::forward<T>(value));
+ container_algorithm_internal::c_end(c), value);
}
// c_fill_n()
@@ -677,9 +679,8 @@ void c_fill(C& c, T&& value) {
// Container-based version of the <algorithm> `std::fill_n()` function to fill
// the first N elements in a container with some value.
template <typename C, typename Size, typename T>
-void c_fill_n(C& c, Size n, T&& value) {
- std::fill_n(container_algorithm_internal::c_begin(c), n,
- std::forward<T>(value));
+void c_fill_n(C& c, Size n, const T& value) {
+ std::fill_n(container_algorithm_internal::c_begin(c), n, value);
}
// c_generate()
@@ -716,10 +717,11 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
// copy a container's elements while removing any elements matching the given
// `value`.
template <typename C, typename OutputIterator, typename T>
-OutputIterator c_remove_copy(const C& c, OutputIterator result, T&& value) {
+OutputIterator c_remove_copy(const C& c, OutputIterator result,
+ const T& value) {
return std::remove_copy(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c), result,
- std::forward<T>(value));
+ value);
}
// c_remove_copy_if()
@@ -1064,20 +1066,19 @@ void c_nth_element(
// which does not compare less than `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
- Sequence& sequence, T&& value) {
+ Sequence& sequence, const T& value) {
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value));
+ container_algorithm_internal::c_end(sequence), value);
}
// Overload of c_lower_bound() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
- Sequence& sequence, T&& value, LessThan&& comp) {
+ Sequence& sequence, const T& value, LessThan&& comp) {
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ container_algorithm_internal::c_end(sequence), value,
+ std::forward<LessThan>(comp));
}
// c_upper_bound()
@@ -1087,20 +1088,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
// which is greater than `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
- Sequence& sequence, T&& value) {
+ Sequence& sequence, const T& value) {
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value));
+ container_algorithm_internal::c_end(sequence), value);
}
// Overload of c_upper_bound() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
- Sequence& sequence, T&& value, LessThan&& comp) {
+ Sequence& sequence, const T& value, LessThan&& comp) {
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ container_algorithm_internal::c_end(sequence), value,
+ std::forward<LessThan>(comp));
}
// c_equal_range()
@@ -1110,20 +1110,19 @@ container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
// sorted container which compare equal to `value`.
template <typename Sequence, typename T>
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
-c_equal_range(Sequence& sequence, T&& value) {
+c_equal_range(Sequence& sequence, const T& value) {
return std::equal_range(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value));
+ container_algorithm_internal::c_end(sequence), value);
}
// Overload of c_equal_range() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
-c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
+c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) {
return std::equal_range(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ container_algorithm_internal::c_end(sequence), value,
+ std::forward<LessThan>(comp));
}
// c_binary_search()
@@ -1132,20 +1131,19 @@ c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
// to test if any element in the sorted container contains a value equivalent to
// 'value'.
template <typename Sequence, typename T>
-bool c_binary_search(Sequence&& sequence, T&& value) {
+bool c_binary_search(Sequence&& sequence, const T& value) {
return std::binary_search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<T>(value));
+ value);
}
// Overload of c_binary_search() for performing a `comp` comparison other than
// the default `operator<`.
template <typename Sequence, typename T, typename LessThan>
-bool c_binary_search(Sequence&& sequence, T&& value, LessThan&& comp) {
+bool c_binary_search(Sequence&& sequence, const T& value, LessThan&& comp) {
return std::binary_search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<T>(value),
- std::forward<LessThan>(comp));
+ value, std::forward<LessThan>(comp));
}
//------------------------------------------------------------------------------
@@ -1560,8 +1558,8 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// smallest and largest values, respectively, using `operator<` to make the
// comparisons.
template <typename C>
-container_algorithm_internal::ContainerIterPairType<C, C>
-c_minmax_element(C& c) {
+container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
+ C& c) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c));
}
@@ -1569,8 +1567,8 @@ c_minmax_element(C& c) {
// Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`.
template <typename C, typename LessThan>
-container_algorithm_internal::ContainerIterPairType<C, C>
-c_minmax_element(C& c, LessThan&& comp) {
+container_algorithm_internal::ContainerIterPairType<C, C> c_minmax_element(
+ C& c, LessThan&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
std::forward<LessThan>(comp));
@@ -1588,7 +1586,8 @@ c_minmax_element(C& c, LessThan&& comp) {
// that capital letters ("A-Z") have ASCII values less than lowercase letters
// ("a-z").
template <typename Sequence1, typename Sequence2>
-bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
+bool c_lexicographical_compare(const Sequence1& sequence1,
+ const Sequence2& sequence2) {
return std::lexicographical_compare(
container_algorithm_internal::c_begin(sequence1),
container_algorithm_internal::c_end(sequence1),
@@ -1599,8 +1598,8 @@ bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
// Overload of c_lexicographical_compare() for performing a lexicographical
// comparison using a `comp` operator instead of `operator<`.
template <typename Sequence1, typename Sequence2, typename LessThan>
-bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2,
- LessThan&& comp) {
+bool c_lexicographical_compare(const Sequence1& sequence1,
+ const Sequence2& sequence2, LessThan&& comp) {
return std::lexicographical_compare(
container_algorithm_internal::c_begin(sequence1),
container_algorithm_internal::c_end(sequence1),
@@ -1655,18 +1654,18 @@ bool c_prev_permutation(C& c, LessThan&& comp) {
// c_iota()
//
-// Container-based version of the <algorithm> `std::iota()` function
+// Container-based version of the <numeric> `std::iota()` function
// to compute successive values of `value`, as if incremented with `++value`
// after each element is written. and write them to the container.
template <typename Sequence, typename T>
-void c_iota(Sequence& sequence, T&& value) {
+void c_iota(Sequence& sequence, const T& value) {
std::iota(container_algorithm_internal::c_begin(sequence),
- container_algorithm_internal::c_end(sequence),
- std::forward<T>(value));
+ container_algorithm_internal::c_end(sequence), value);
}
+
// c_accumulate()
//
-// Container-based version of the <algorithm> `std::accumulate()` function
+// Container-based version of the <numeric> `std::accumulate()` function
// to accumulate the element values of a container to `init` and return that
// accumulation by value.
//
@@ -1693,7 +1692,7 @@ decay_t<T> c_accumulate(const Sequence& sequence, T&& init,
// c_inner_product()
//
-// Container-based version of the <algorithm> `std::inner_product()` function
+// Container-based version of the <numeric> `std::inner_product()` function
// to compute the cumulative inner product of container element pairs.
//
// Note: Due to a language technicality this function has return type
@@ -1724,7 +1723,7 @@ decay_t<T> c_inner_product(const Sequence1& factors1, const Sequence2& factors2,
// c_adjacent_difference()
//
-// Container-based version of the <algorithm> `std::adjacent_difference()`
+// Container-based version of the <numeric> `std::adjacent_difference()`
// function to compute the difference between each element and the one preceding
// it and write it to an iterator.
template <typename InputSequence, typename OutputIt>
@@ -1747,7 +1746,7 @@ OutputIt c_adjacent_difference(const InputSequence& input,
// c_partial_sum()
//
-// Container-based version of the <algorithm> `std::partial_sum()` function
+// Container-based version of the <numeric> `std::partial_sum()` function
// to compute the partial sum of the elements in a sequence and write them
// to an iterator. The partial sum is the sum of all element values so far in
// the sequence.
diff --git a/contrib/restricted/abseil-cpp/absl/base/attributes.h b/contrib/restricted/abseil-cpp/absl/base/attributes.h
index e4e7a3d843..b7826e7766 100644
--- a/contrib/restricted/abseil-cpp/absl/base/attributes.h
+++ b/contrib/restricted/abseil-cpp/absl/base/attributes.h
@@ -716,26 +716,9 @@
#define ABSL_CONST_INIT
#endif
-// ABSL_ATTRIBUTE_PURE_FUNCTION
-//
-// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
-// functions. A function is pure if its return value is only a function of its
-// arguments. The pure attribute prohibits a function from modifying the state
-// of the program that is observable by means other than inspecting the
-// function's return value. Declaring such functions with the pure attribute
-// allows the compiler to avoid emitting some calls in repeated invocations of
-// the function with the same argument values.
-//
-// Example:
-//
-// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
-#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
-#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
-#elif ABSL_HAVE_ATTRIBUTE(pure)
-#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
-#else
+// These annotations are not available yet due to fear of breaking code.
#define ABSL_ATTRIBUTE_PURE_FUNCTION
-#endif
+#define ABSL_ATTRIBUTE_CONST_FUNCTION
// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
// parameter or implicit object parameter is retained by the return value of the
@@ -759,4 +742,41 @@
#define ABSL_ATTRIBUTE_LIFETIME_BOUND
#endif
+// ABSL_ATTRIBUTE_TRIVIAL_ABI
+// Indicates that a type is "trivially relocatable" -- meaning it can be
+// relocated without invoking the constructor/destructor, using a form of move
+// elision.
+//
+// From a memory safety point of view, putting aside destructor ordering, it's
+// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location
+// can change over the course of its lifetime: if a constructor can be run one
+// place, and then the object magically teleports to another place where some
+// methods are run, and then the object teleports to yet another place where it
+// is destroyed. This is notably not true for self-referential types, where the
+// move-constructor must keep the self-reference up to date. If the type changed
+// location without invoking the move constructor, it would have a dangling
+// self-reference.
+//
+// The use of this teleporting machinery means that the number of paired
+// move/destroy operations can change, and so it is a bad idea to apply this to
+// a type meant to count the number of moves.
+//
+// Warning: applying this can, rarely, break callers. Objects passed by value
+// will be destroyed at the end of the call, instead of the end of the
+// full-expression containing the call. In addition, it changes the ABI
+// of functions accepting this type by value (e.g. to pass in registers).
+//
+// See also the upstream documentation:
+// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi
+//
+#if ABSL_HAVE_CPP_ATTRIBUTE(clang::trivial_abi)
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI [[clang::trivial_abi]]
+#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
+#elif ABSL_HAVE_ATTRIBUTE(trivial_abi)
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI __attribute__((trivial_abi))
+#define ABSL_HAVE_ATTRIBUTE_TRIVIAL_ABI 1
+#else
+#define ABSL_ATTRIBUTE_TRIVIAL_ABI
+#endif
+
#endif // ABSL_BASE_ATTRIBUTES_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/config.h b/contrib/restricted/abseil-cpp/absl/base/config.h
index ca140fa55f..2899fb3041 100644
--- a/contrib/restricted/abseil-cpp/absl/base/config.h
+++ b/contrib/restricted/abseil-cpp/absl/base/config.h
@@ -111,8 +111,8 @@
//
// LTS releases can be obtained from
// https://github.com/abseil/abseil-cpp/releases.
-#define ABSL_LTS_RELEASE_VERSION 20220623
-#define ABSL_LTS_RELEASE_PATCH_LEVEL 1
+#define ABSL_LTS_RELEASE_VERSION 20230125
+#define ABSL_LTS_RELEASE_PATCH_LEVEL 0
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
@@ -243,6 +243,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \
+ (defined(__clang__) && __clang_major__ >= 15) || \
(!defined(__clang__) && defined(__GLIBCXX__) && \
ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8))
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
@@ -264,15 +265,27 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
+ (defined(__clang__) && __clang_major__ >= 15) || \
(!defined(__clang__) && \
((ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && defined(__GLIBCXX__)) || \
(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(8, 2) && \
defined(_LIBCPP_VERSION)))) || \
- (defined(_MSC_VER) && !defined(__NVCC__))
+ (defined(_MSC_VER) && !defined(__NVCC__) && !defined(__clang__))
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
#endif
+// ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE
+//
+// Checks whether `std::is_trivially_copyable<T>` is supported.
+//
+// Notes: Clang 15+ with libc++ supports these features, GCC hasn't been tested.
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
+#error ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE cannot be directly set
+#elif defined(__clang__) && (__clang_major__ >= 15)
+#define ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE 1
+#endif
+
// ABSL_HAVE_THREAD_LOCAL
//
// Checks whether C++11's `thread_local` storage duration specifier is
@@ -741,6 +754,18 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_DLL
#endif // defined(_MSC_VER)
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_TEST_DLL)
+#define ABSL_TEST_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_TEST_DLL)
+#define ABSL_TEST_DLL __declspec(dllimport)
+#else
+#define ABSL_TEST_DLL
+#endif
+#else
+#define ABSL_TEST_DLL
+#endif // defined(_MSC_VER)
+
// ABSL_HAVE_MEMORY_SANITIZER
//
// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
@@ -899,10 +924,26 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// ABSL_INTERNAL_HAVE_ARM_NEON is used for compile-time detection of NEON (ARM
// SIMD).
+//
+// If __CUDA_ARCH__ is defined, then we are compiling CUDA code in device mode.
+// In device mode, NEON intrinsics are not available, regardless of host
+// platform.
+// https://llvm.org/docs/CompileCudaWithLLVM.html#detecting-clang-vs-nvcc-from-code
#ifdef ABSL_INTERNAL_HAVE_ARM_NEON
#error ABSL_INTERNAL_HAVE_ARM_NEON cannot be directly set
-#elif defined(__ARM_NEON)
+#elif defined(__ARM_NEON) && !defined(__CUDA_ARCH__)
#define ABSL_INTERNAL_HAVE_ARM_NEON 1
#endif
+// ABSL_HAVE_CONSTANT_EVALUATED is used for compile-time detection of
+// constant evaluation support through `absl::is_constant_evaluated`.
+#ifdef ABSL_HAVE_CONSTANT_EVALUATED
+#error ABSL_HAVE_CONSTANT_EVALUATED cannot be directly set
+#endif
+#ifdef __cpp_lib_is_constant_evaluated
+#define ABSL_HAVE_CONSTANT_EVALUATED 1
+#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
+#define ABSL_HAVE_CONSTANT_EVALUATED 1
+#endif
+
#endif // ABSL_BASE_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock.h b/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock.h
index 9704e388f0..cbfdf57998 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock.h
@@ -47,6 +47,7 @@
#include "absl/base/attributes.h"
#include "absl/base/config.h"
+#include "absl/base/internal/cycleclock_config.h"
#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
@@ -76,25 +77,9 @@ class CycleClock {
#if ABSL_USE_UNSCALED_CYCLECLOCK
static CycleClockSourceFunc LoadCycleClockSource();
-#ifdef NDEBUG
-#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
- // Not debug mode and the UnscaledCycleClock frequency is the CPU
- // frequency. Scale the CycleClock to prevent overflow if someone
- // tries to represent the time as cycles since the Unix epoch.
- static constexpr int32_t kShift = 1;
-#else
- // Not debug mode and the UnscaledCycleClock isn't operating at the
- // raw CPU frequency. There is no need to do any scaling, so don't
- // needlessly sacrifice precision.
- static constexpr int32_t kShift = 0;
-#endif
-#else // NDEBUG
- // In debug mode use a different shift to discourage depending on a
- // particular shift value.
- static constexpr int32_t kShift = 2;
-#endif // NDEBUG
+ static constexpr int32_t kShift = kCycleClockShift;
+ static constexpr double kFrequencyScale = kCycleClockFrequencyScale;
- static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
ABSL_CONST_INIT static std::atomic<CycleClockSourceFunc> cycle_clock_source_;
#endif // ABSL_USE_UNSCALED_CYCLECLOC
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock_config.h b/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock_config.h
new file mode 100644
index 0000000000..191112b58e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/cycleclock_config.h
@@ -0,0 +1,55 @@
+// 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_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
+#define ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/inline_variable.h"
+#include "absl/base/internal/unscaledcycleclock_config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+#ifdef NDEBUG
+#ifdef ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
+// Not debug mode and the UnscaledCycleClock frequency is the CPU
+// frequency. Scale the CycleClock to prevent overflow if someone
+// tries to represent the time as cycles since the Unix epoch.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 1);
+#else
+// Not debug mode and the UnscaledCycleClock isn't operating at the
+// raw CPU frequency. There is no need to do any scaling, so don't
+// needlessly sacrifice precision.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 0);
+#endif
+#else // NDEBUG
+// In debug mode use a different shift to discourage depending on a
+// particular shift value.
+ABSL_INTERNAL_INLINE_CONSTEXPR(int32_t, kCycleClockShift, 2);
+#endif // NDEBUG
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(double, kCycleClockFrequencyScale,
+ 1.0 / (1 << kCycleClockShift));
+#endif // ABSL_USE_UNSCALED_CYCLECLOC
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/direct_mmap.h b/contrib/restricted/abseil-cpp/absl/base/internal/direct_mmap.h
index e492bb004b..815b8d23ba 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/direct_mmap.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/direct_mmap.h
@@ -97,7 +97,8 @@ inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
#ifdef __BIONIC__
// SYS_mmap2 has problems on Android API level <= 16.
// Workaround by invoking __mmap2() instead.
- return __mmap2(start, length, prot, flags, fd, offset / pagesize);
+ return __mmap2(start, length, prot, flags, fd,
+ static_cast<size_t>(offset / pagesize));
#else
return reinterpret_cast<void*>(
syscall(SYS_mmap2, start, length, prot, flags, fd,
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h
index 130d8c2476..df933faff5 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
-#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
+#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
#include <type_traits>
@@ -104,4 +104,4 @@
#endif // __cpp_inline_variables
-#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_EMULATION_H_
+#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc
index 229ab9162d..662167b08a 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.cc
@@ -332,7 +332,7 @@ size_t GetPageSize() {
#elif defined(__wasm__) || defined(__asmjs__)
return getpagesize();
#else
- return sysconf(_SC_PAGESIZE);
+ return static_cast<size_t>(sysconf(_SC_PAGESIZE));
#endif
}
@@ -364,7 +364,7 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value)
}
// L < meta_data_arena->mu
-LowLevelAlloc::Arena *LowLevelAlloc::NewArena(int32_t flags) {
+LowLevelAlloc::Arena *LowLevelAlloc::NewArena(uint32_t flags) {
Arena *meta_data_arena = DefaultArena();
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if ((flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.h b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.h
index db91951c82..eabb14a9b4 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/low_level_alloc.h
@@ -103,7 +103,7 @@ class LowLevelAlloc {
// the provided flags. For example, the call NewArena(kAsyncSignalSafe)
// is itself async-signal-safe, as well as generatating an arena that provides
// async-signal-safe Alloc/Free.
- static Arena *NewArena(int32_t flags);
+ static Arena *NewArena(uint32_t flags);
// Destroys an arena allocated by NewArena and returns true,
// provided no allocated blocks remain in the arena.
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc
index 54e71a3f88..6273e8471b 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.cc
@@ -72,7 +72,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace raw_logging_internal {
+namespace raw_log_internal {
namespace {
// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
@@ -89,12 +89,14 @@ constexpr char kTruncated[] = " ... (message truncated)\n";
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
ABSL_PRINTF_ATTRIBUTE(3, 0);
bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
- int n = vsnprintf(*buf, *size, format, ap);
+ if (*size < 0)
+ return false;
+ int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
bool result = true;
if (n < 0 || n > *size) {
result = false;
if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
- n = *size - sizeof(kTruncated); // room for truncation message
+ n = *size - static_cast<int>(sizeof(kTruncated));
} else {
n = 0; // no room for truncation message
}
@@ -116,9 +118,11 @@ constexpr int kLogBufSize = 3000;
bool DoRawLog(char** buf, int* size, const char* format, ...)
ABSL_PRINTF_ATTRIBUTE(3, 4);
bool DoRawLog(char** buf, int* size, const char* format, ...) {
+ if (*size < 0)
+ return false;
va_list ap;
va_start(ap, format);
- int n = vsnprintf(*buf, *size, format, ap);
+ int n = vsnprintf(*buf, static_cast<size_t>(*size), format, ap);
va_end(ap);
if (n < 0 || n > *size) return false;
*size -= n;
@@ -206,7 +210,7 @@ void AsyncSignalSafeWriteToStderr(const char* s, size_t len) {
#elif defined(ABSL_HAVE_POSIX_WRITE)
write(STDERR_FILENO, s, len);
#elif defined(ABSL_HAVE_RAW_IO)
- _write(/* stderr */ 2, s, len);
+ _write(/* stderr */ 2, s, static_cast<unsigned>(len));
#else
// stderr logging unsupported on this platform
(void) s;
@@ -244,6 +248,6 @@ void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
}
-} // namespace raw_logging_internal
+} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h
index 0747c9df7c..c7b889cd8a 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/raw_logging.h
@@ -43,12 +43,11 @@
#define ABSL_RAW_LOG(severity, ...) \
do { \
- constexpr const char* absl_raw_logging_internal_basename = \
- ::absl::raw_logging_internal::Basename(__FILE__, \
- sizeof(__FILE__) - 1); \
- ::absl::raw_logging_internal::RawLog(ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_basename, \
- __LINE__, __VA_ARGS__); \
+ constexpr const char* absl_raw_log_internal_basename = \
+ ::absl::raw_log_internal::Basename(__FILE__, sizeof(__FILE__) - 1); \
+ ::absl::raw_log_internal::RawLog(ABSL_RAW_LOG_INTERNAL_##severity, \
+ absl_raw_log_internal_basename, __LINE__, \
+ __VA_ARGS__); \
} while (0)
// Similar to CHECK(condition) << message, but for low-level modules:
@@ -72,14 +71,14 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message) \
- do { \
- constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
- ::absl::raw_logging_internal::internal_log_function( \
- ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_filename, __LINE__, message); \
- if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
- ABSL_INTERNAL_UNREACHABLE; \
+#define ABSL_INTERNAL_LOG(severity, message) \
+ do { \
+ constexpr const char* absl_raw_log_internal_filename = __FILE__; \
+ ::absl::raw_log_internal::internal_log_function( \
+ ABSL_RAW_LOG_INTERNAL_##severity, absl_raw_log_internal_filename, \
+ __LINE__, message); \
+ if (ABSL_RAW_LOG_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
+ ABSL_UNREACHABLE(); \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
@@ -91,16 +90,16 @@
} \
} while (0)
-#define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
-#define ABSL_RAW_LOGGING_INTERNAL_WARNING ::absl::LogSeverity::kWarning
-#define ABSL_RAW_LOGGING_INTERNAL_ERROR ::absl::LogSeverity::kError
-#define ABSL_RAW_LOGGING_INTERNAL_FATAL ::absl::LogSeverity::kFatal
-#define ABSL_RAW_LOGGING_INTERNAL_LEVEL(severity) \
+#define ABSL_RAW_LOG_INTERNAL_INFO ::absl::LogSeverity::kInfo
+#define ABSL_RAW_LOG_INTERNAL_WARNING ::absl::LogSeverity::kWarning
+#define ABSL_RAW_LOG_INTERNAL_ERROR ::absl::LogSeverity::kError
+#define ABSL_RAW_LOG_INTERNAL_FATAL ::absl::LogSeverity::kFatal
+#define ABSL_RAW_LOG_INTERNAL_LEVEL(severity) \
::absl::NormalizeLogSeverity(severity)
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace raw_logging_internal {
+namespace raw_log_internal {
// Helper function to implement ABSL_RAW_LOG
// Logs format... at "severity" level, reporting it
@@ -130,7 +129,7 @@ constexpr const char* Basename(const char* fname, int offset) {
// TODO(gfalcon): Come up with a better name for this method.
bool RawLoggingFullySupported();
-// Function type for a raw_logging customization hook for suppressing messages
+// Function type for a raw_log customization hook for suppressing messages
// by severity, and for writing custom prefixes on non-suppressed messages.
//
// The installed hook is called for every raw log invocation. The message will
@@ -139,7 +138,7 @@ bool RawLoggingFullySupported();
// also provided with an output buffer, where it can write a custom log message
// prefix.
//
-// The raw_logging system does not allocate memory or grab locks. User-provided
+// The raw_log system does not allocate memory or grab locks. User-provided
// hooks must avoid these operations, and must not throw exceptions.
//
// 'severity' is the severity level of the message being written.
@@ -152,7 +151,7 @@ using LogFilterAndPrefixHook = bool (*)(absl::LogSeverity severity,
const char* file, int line, char** buf,
int* buf_size);
-// Function type for a raw_logging customization hook called to abort a process
+// Function type for a raw_log customization hook called to abort a process
// when a FATAL message is logged. If the provided AbortHook() returns, the
// logging system will call abort().
//
@@ -189,7 +188,7 @@ void RegisterLogFilterAndPrefixHook(LogFilterAndPrefixHook func);
void RegisterAbortHook(AbortHook func);
void RegisterInternalLogFunction(InternalLogFunction func);
-} // namespace raw_logging_internal
+} // namespace raw_log_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.cc b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.cc
index 9b5ed6e472..381b913b29 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.cc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.cc
@@ -178,7 +178,7 @@ void SpinLock::SlowUnlock(uint32_t lock_value) {
// reserve a unitary wait time to represent that a waiter exists without our
// own acquisition having been contended.
if ((lock_value & kWaitTimeMask) != kSpinLockSleeper) {
- const uint64_t wait_cycles = DecodeWaitCycles(lock_value);
+ const int64_t wait_cycles = DecodeWaitCycles(lock_value);
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
submit_profile_data(this, wait_cycles);
ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
@@ -220,9 +220,9 @@ uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
return clamped;
}
-uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
+int64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
// Cast to uint32_t first to ensure bits [63:32] are cleared.
- const uint64_t scaled_wait_time =
+ const int64_t scaled_wait_time =
static_cast<uint32_t>(lock_value & kWaitTimeMask);
return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);
}
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h
index 6d8d8dddd4..09ba5824b1 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock.h
@@ -29,10 +29,8 @@
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_H_
-#include <stdint.h>
-#include <sys/types.h>
-
#include <atomic>
+#include <cstdint>
#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
@@ -41,8 +39,6 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/tsan_mutex_interface.h"
-#include "absl/base/macros.h"
-#include "absl/base/port.h"
#include "absl/base/thread_annotations.h"
namespace absl {
@@ -137,7 +133,7 @@ class ABSL_LOCKABLE SpinLock {
int64_t wait_end_time);
// Extract number of wait cycles in a lock value.
- static uint64_t DecodeWaitCycles(uint32_t lock_value);
+ static int64_t DecodeWaitCycles(uint32_t lock_value);
// Provide access to protected method above. Use for testing only.
friend struct SpinLockTest;
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock_win32.inc b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock_win32.inc
index 9d224813a5..934c2016fb 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/spinlock_win32.inc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/spinlock_win32.inc
@@ -27,7 +27,10 @@ void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
} else if (loop == 1) {
Sleep(0);
} else {
- Sleep(absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000);
+ // SpinLockSuggestedDelayNS() always returns a positive integer, so this
+ // static_cast is safe.
+ Sleep(static_cast<DWORD>(
+ absl::base_internal::SpinLockSuggestedDelayNS(loop) / 1000000));
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/strerror.cc b/contrib/restricted/abseil-cpp/absl/base/internal/strerror.cc
index 0d6226fd0a..de91c05e07 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/strerror.cc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/strerror.cc
@@ -66,8 +66,8 @@ constexpr int kSysNerr = 135;
std::array<std::string, kSysNerr>* NewStrErrorTable() {
auto* table = new std::array<std::string, kSysNerr>;
- for (int i = 0; i < static_cast<int>(table->size()); ++i) {
- (*table)[i] = StrErrorInternal(i);
+ for (size_t i = 0; i < table->size(); ++i) {
+ (*table)[i] = StrErrorInternal(static_cast<int>(i));
}
return table;
}
@@ -77,8 +77,8 @@ std::array<std::string, kSysNerr>* NewStrErrorTable() {
std::string StrError(int errnum) {
absl::base_internal::ErrnoSaver errno_saver;
static const auto* table = NewStrErrorTable();
- if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
- return (*table)[errnum];
+ if (errnum >= 0 && static_cast<size_t>(errnum) < table->size()) {
+ return (*table)[static_cast<size_t>(errnum)];
}
return StrErrorInternal(errnum);
}
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc b/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc
index 44a6746c8e..ed612c8cc7 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/sysinfo.cc
@@ -117,7 +117,7 @@ int Win32NumCPUs() {
}
}
free(info);
- return logicalProcessorCount;
+ return static_cast<int>(logicalProcessorCount);
}
#endif
@@ -128,7 +128,7 @@ static int GetNumCPUs() {
#if defined(__myriad2__)
return 1;
#elif defined(_WIN32)
- const unsigned hardware_concurrency = Win32NumCPUs();
+ const int hardware_concurrency = Win32NumCPUs();
return hardware_concurrency ? hardware_concurrency : 1;
#elif defined(_AIX)
return sysconf(_SC_NPROCESSORS_ONLN);
@@ -136,7 +136,7 @@ static int GetNumCPUs() {
// Other possibilities:
// - Read /sys/devices/system/cpu/online and use cpumask_parse()
// - sysconf(_SC_NPROCESSORS_ONLN)
- return std::thread::hardware_concurrency();
+ return static_cast<int>(std::thread::hardware_concurrency());
#endif
}
@@ -189,12 +189,15 @@ static double GetNominalCPUFrequency() {
// and the memory location pointed to by value is set to the value read.
static bool ReadLongFromFile(const char *file, long *value) {
bool ret = false;
- int fd = open(file, O_RDONLY);
+ int fd = open(file, O_RDONLY | O_CLOEXEC);
if (fd != -1) {
char line[1024];
char *err;
memset(line, '\0', sizeof(line));
- int len = read(fd, line, sizeof(line) - 1);
+ ssize_t len;
+ do {
+ len = read(fd, line, sizeof(line) - 1);
+ } while (len < 0 && errno == EINTR);
if (len <= 0) {
ret = false;
} else {
@@ -376,7 +379,7 @@ pid_t GetTID() {
#endif
pid_t GetTID() {
- return syscall(SYS_gettid);
+ return static_cast<pid_t>(syscall(SYS_gettid));
}
#elif defined(__akaros__)
@@ -429,11 +432,11 @@ static constexpr int kBitsPerWord = 32; // tid_array is uint32_t.
// Returns the TID to tid_array.
static void FreeTID(void *v) {
intptr_t tid = reinterpret_cast<intptr_t>(v);
- int word = tid / kBitsPerWord;
+ intptr_t word = tid / kBitsPerWord;
uint32_t mask = ~(1u << (tid % kBitsPerWord));
absl::base_internal::SpinLockHolder lock(&tid_lock);
assert(0 <= word && static_cast<size_t>(word) < tid_array->size());
- (*tid_array)[word] &= mask;
+ (*tid_array)[static_cast<size_t>(word)] &= mask;
}
static void InitGetTID() {
@@ -455,7 +458,7 @@ pid_t GetTID() {
intptr_t tid = reinterpret_cast<intptr_t>(pthread_getspecific(tid_key));
if (tid != 0) {
- return tid;
+ return static_cast<pid_t>(tid);
}
int bit; // tid_array[word] = 1u << bit;
@@ -476,7 +479,8 @@ pid_t GetTID() {
while (bit < kBitsPerWord && (((*tid_array)[word] >> bit) & 1) != 0) {
++bit;
}
- tid = (word * kBitsPerWord) + bit;
+ tid =
+ static_cast<intptr_t>((word * kBitsPerWord) + static_cast<size_t>(bit));
(*tid_array)[word] |= 1u << bit; // Mark the TID as allocated.
}
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h b/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h
index 4dab6a9c15..8c5c67e0df 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/thread_annotations.h
@@ -38,6 +38,13 @@
#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
+// ABSL_LEGACY_THREAD_ANNOTATIONS is a *temporary* compatibility macro that can
+// be defined on the compile command-line to restore the legacy spellings of the
+// thread annotations macros/functions. The macros in this file are available
+// under ABSL_ prefixed spellings in absl/base/thread_annotations.h. This macro
+// and the legacy spellings will be removed in the future.
+#ifdef ABSL_LEGACY_THREAD_ANNOTATIONS
+
#if defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
#else
@@ -268,4 +275,6 @@ inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
} // namespace thread_safety_analysis
+#endif // defined(ABSL_LEGACY_THREAD_ANNOTATIONS)
+
#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h
index 659694b326..463acbc74e 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/thread_identity.h
@@ -134,6 +134,10 @@ struct PerThreadSynch {
// The instances of this class are allocated in NewThreadIdentity() with an
// alignment of PerThreadSynch::kAlignment.
+//
+// NOTE: The layout of fields in this structure is critical, please do not
+// add, remove, or modify the field placements without fully auditing the
+// layout.
struct ThreadIdentity {
// Must be the first member. The Mutex implementation requires that
// the PerThreadSynch object associated with each thread is
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h
index 2cbeae317a..cc1276ba08 100644
--- a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock.h
@@ -42,48 +42,11 @@
#include <TargetConditionals.h>
#endif
-#include "absl/base/port.h"
-
-// The following platforms have an implementation of a hardware counter.
-#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
- defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
- defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
-#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
-#else
-#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
-#endif
-
-// The following platforms often disable access to the hardware
-// counter (through a sandbox) even if the underlying hardware has a
-// usable counter. The CycleTimer interface also requires a *scaled*
-// CycleClock that runs at atleast 1 MHz. We've found some Android
-// ARM64 devices where this is not the case, so we disable it by
-// default on Android ARM64.
-#if defined(__native_client__) || (defined(__APPLE__)) || \
- (defined(__ANDROID__) && defined(__aarch64__))
-#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
-#else
-#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
-#endif
-
-// UnscaledCycleClock is an optional internal feature.
-// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
-// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
-#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
-#define ABSL_USE_UNSCALED_CYCLECLOCK \
- (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
- ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
-#endif
+#include "absl/base/config.h"
+#include "absl/base/internal/unscaledcycleclock_config.h"
#if ABSL_USE_UNSCALED_CYCLECLOCK
-// This macro can be used to test if UnscaledCycleClock::Frequency()
-// is NominalCPUFrequency() on a particular platform.
-#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
- defined(_M_IX86) || defined(_M_X64))
-#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace time_internal {
@@ -119,7 +82,7 @@ class UnscaledCycleClock {
inline int64_t UnscaledCycleClock::Now() {
uint64_t low, high;
__asm__ volatile("rdtsc" : "=a"(low), "=d"(high));
- return (high << 32) | low;
+ return static_cast<int64_t>((high << 32) | low);
}
#endif
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h
new file mode 100644
index 0000000000..24b324ac99
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/unscaledcycleclock_config.h
@@ -0,0 +1,62 @@
+// 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_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
+#define ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
+
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+// The following platforms have an implementation of a hardware counter.
+#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
+ defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
+#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
+#else
+#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
+#endif
+
+// The following platforms often disable access to the hardware
+// counter (through a sandbox) even if the underlying hardware has a
+// usable counter. The CycleTimer interface also requires a *scaled*
+// CycleClock that runs at atleast 1 MHz. We've found some Android
+// ARM64 devices where this is not the case, so we disable it by
+// default on Android ARM64.
+#if defined(__native_client__) || (defined(__APPLE__)) || \
+ (defined(__ANDROID__) && defined(__aarch64__))
+#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
+#else
+#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 1
+#endif
+
+// UnscaledCycleClock is an optional internal feature.
+// Use "#if ABSL_USE_UNSCALED_CYCLECLOCK" to test for its presence.
+// Can be overridden at compile-time via -DABSL_USE_UNSCALED_CYCLECLOCK=0|1
+#if !defined(ABSL_USE_UNSCALED_CYCLECLOCK)
+#define ABSL_USE_UNSCALED_CYCLECLOCK \
+ (ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION && \
+ ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT)
+#endif
+
+#if ABSL_USE_UNSCALED_CYCLECLOCK
+// This macro can be used to test if UnscaledCycleClock::Frequency()
+// is NominalCPUFrequency() on a particular platform.
+#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
+ defined(_M_IX86) || defined(_M_X64))
+#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
+#endif
+#endif
+
+#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/macros.h b/contrib/restricted/abseil-cpp/absl/base/macros.h
index 3e085a916b..f33cd1927b 100644
--- a/contrib/restricted/abseil-cpp/absl/base/macros.h
+++ b/contrib/restricted/abseil-cpp/absl/base/macros.h
@@ -103,17 +103,11 @@ ABSL_NAMESPACE_END
// aborts the program in release mode (when NDEBUG is defined). The
// implementation should abort the program as quickly as possible and ideally it
// should not be possible to ignore the abort request.
-#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \
- ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
- (defined(__GNUC__) && !defined(__clang__))
-#define ABSL_INTERNAL_HARDENING_ABORT() \
- do { \
- __builtin_trap(); \
- __builtin_unreachable(); \
+#define ABSL_INTERNAL_HARDENING_ABORT() \
+ do { \
+ ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
} while (false)
-#else
-#define ABSL_INTERNAL_HARDENING_ABORT() abort()
-#endif
// ABSL_HARDENING_ASSERT()
//
@@ -144,15 +138,4 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
-// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
-// reaches one has undefined behavior, and the compiler may optimize
-// accordingly.
-#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
-#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define ABSL_INTERNAL_UNREACHABLE __assume(0)
-#else
-#define ABSL_INTERNAL_UNREACHABLE
-#endif
-
#endif // ABSL_BASE_MACROS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/optimization.h b/contrib/restricted/abseil-cpp/absl/base/optimization.h
index db5cc0975f..ad0121ad3b 100644
--- a/contrib/restricted/abseil-cpp/absl/base/optimization.h
+++ b/contrib/restricted/abseil-cpp/absl/base/optimization.h
@@ -91,6 +91,7 @@
#define ABSL_CACHELINE_SIZE 64
#endif
#endif
+#endif
#ifndef ABSL_CACHELINE_SIZE
// A reasonable default guess. Note that overestimates tend to waste more
@@ -141,12 +142,11 @@
// the generated machine code.
// 3) Prefer applying this attribute to individual variables. Avoid
// applying it to types. This tends to localize the effect.
+#if defined(__clang__) || defined(__GNUC__)
#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
#elif defined(_MSC_VER)
-#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
#else
-#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED
#endif
@@ -181,6 +181,53 @@
#define ABSL_PREDICT_TRUE(x) (x)
#endif
+// `ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL()` aborts the program in the fastest
+// possible way, with no attempt at logging. One use is to implement hardening
+// aborts with ABSL_OPTION_HARDENED. Since this is an internal symbol, it
+// should not be used directly outside of Abseil.
+#if ABSL_HAVE_BUILTIN(__builtin_trap) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() __builtin_trap()
+#else
+#define ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL() abort()
+#endif
+
+// `ABSL_INTERNAL_UNREACHABLE_IMPL()` is the platform specific directive to
+// indicate that a statement is unreachable, and to allow the compiler to
+// optimize accordingly. Clients should use `ABSL_UNREACHABLE()`, which is
+// defined below.
+#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() std::unreachable()
+#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_unreachable()
+#elif ABSL_HAVE_BUILTIN(__builtin_assume)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __builtin_assume(false)
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_UNREACHABLE_IMPL() __assume(false)
+#else
+#define ABSL_INTERNAL_UNREACHABLE_IMPL()
+#endif
+
+// `ABSL_UNREACHABLE()` is an unreachable statement. A program which reaches
+// one has undefined behavior, and the compiler may optimize accordingly.
+#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+// Abort in hardened mode to avoid dangerous undefined behavior.
+#define ABSL_UNREACHABLE() \
+ do { \
+ ABSL_INTERNAL_IMMEDIATE_ABORT_IMPL(); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
+ } while (false)
+#else
+// The assert only fires in debug mode to aid in debugging.
+// When NDEBUG is defined, reaching ABSL_UNREACHABLE() is undefined behavior.
+#define ABSL_UNREACHABLE() \
+ do { \
+ /* NOLINTNEXTLINE: misc-static-assert */ \
+ assert(false && "ABSL_UNREACHABLE reached"); \
+ ABSL_INTERNAL_UNREACHABLE_IMPL(); \
+ } while (false)
+#endif
+
// ABSL_ASSUME(cond)
//
// Informs the compiler that a condition is always true and that it can assume
@@ -209,18 +256,23 @@
#define ABSL_ASSUME(cond) assert(cond)
#elif ABSL_HAVE_BUILTIN(__builtin_assume)
#define ABSL_ASSUME(cond) __builtin_assume(cond)
+#elif defined(_MSC_VER)
+#define ABSL_ASSUME(cond) __assume(cond)
+#elif defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
+#define ABSL_ASSUME(cond) \
+ do { \
+ if (!(cond)) std::unreachable(); \
+ } while (false)
#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
#define ABSL_ASSUME(cond) \
do { \
if (!(cond)) __builtin_unreachable(); \
- } while (0)
-#elif defined(_MSC_VER)
-#define ABSL_ASSUME(cond) __assume(cond)
+ } while (false)
#else
#define ABSL_ASSUME(cond) \
do { \
static_cast<void>(false && (cond)); \
- } while (0)
+ } while (false)
#endif
// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
diff --git a/contrib/restricted/abseil-cpp/absl/base/options.h b/contrib/restricted/abseil-cpp/absl/base/options.h
index bc59847042..b6de636d9b 100644
--- a/contrib/restricted/abseil-cpp/absl/base/options.h
+++ b/contrib/restricted/abseil-cpp/absl/base/options.h
@@ -67,12 +67,6 @@
#ifndef ABSL_BASE_OPTIONS_H_
#define ABSL_BASE_OPTIONS_H_
-// Include a standard library header to allow configuration based on the
-// standard library in use.
-#ifdef __cplusplus
-#include <ciso646>
-#endif
-
// -----------------------------------------------------------------------------
// Type Compatibility Options
// -----------------------------------------------------------------------------
@@ -206,7 +200,7 @@
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
-#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20220623
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20230125
// ABSL_OPTION_HARDENED
//
diff --git a/contrib/restricted/abseil-cpp/absl/base/policy_checks.h b/contrib/restricted/abseil-cpp/absl/base/policy_checks.h
index 06b3243916..b8cd4c9440 100644
--- a/contrib/restricted/abseil-cpp/absl/base/policy_checks.h
+++ b/contrib/restricted/abseil-cpp/absl/base/policy_checks.h
@@ -44,17 +44,17 @@
// Toolchain Check
// -----------------------------------------------------------------------------
-// We support MSVC++ 14.0 update 2 and later.
+// We support Visual Studio 2017 (MSVC++ 15.0) and later.
// This minimum will go up.
-#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023918 && !defined(__clang__)
-#error "This package requires Visual Studio 2015 Update 2 or higher."
+#if defined(_MSC_VER) && _MSC_VER < 1910 && !defined(__clang__)
+#error "This package requires Visual Studio 2017 (MSVC++ 15.0) or higher."
#endif
-// We support gcc 4.7 and later.
+// We support GCC 7 and later.
// This minimum will go up.
#if defined(__GNUC__) && !defined(__clang__)
-#if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
-#error "This package requires gcc 4.7 or higher."
+#if __GNUC__ < 7
+#error "This package requires GCC 7 or higher."
#endif
#endif
@@ -69,13 +69,15 @@
// C++ Version Check
// -----------------------------------------------------------------------------
-// Enforce C++11 as the minimum. Note that Visual Studio has not
-// advanced __cplusplus despite being good enough for our purposes, so
-// so we exempt it from the check.
-#if defined(__cplusplus) && !defined(_MSC_VER)
-#if __cplusplus < 201103L
-#error "C++ versions less than C++11 are not supported."
-#endif
+// Enforce C++14 as the minimum.
+#if defined(_MSVC_LANG)
+#if _MSVC_LANG < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif // _MSVC_LANG < 201402L
+#elif defined(__cplusplus)
+#if __cplusplus < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif // __cplusplus < 201402L
#endif
// -----------------------------------------------------------------------------
diff --git a/contrib/restricted/abseil-cpp/absl/cleanup/cleanup.h b/contrib/restricted/abseil-cpp/absl/cleanup/cleanup.h
new file mode 100644
index 0000000000..960ccd080e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/cleanup/cleanup.h
@@ -0,0 +1,140 @@
+// Copyright 2021 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: cleanup.h
+// -----------------------------------------------------------------------------
+//
+// `absl::Cleanup` implements the scope guard idiom, invoking the contained
+// callback's `operator()() &&` on scope exit.
+//
+// Example:
+//
+// ```
+// absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
+// FILE* source_file = fopen(source_path, "r");
+// if (source_file == nullptr) {
+// return absl::NotFoundError("No source file"); // No cleanups execute
+// }
+//
+// // C++17 style cleanup using class template argument deduction
+// absl::Cleanup source_closer = [source_file] { fclose(source_file); };
+//
+// FILE* sink_file = fopen(sink_path, "w");
+// if (sink_file == nullptr) {
+// return absl::NotFoundError("No sink file"); // First cleanup executes
+// }
+//
+// // C++11 style cleanup using the factory function
+// auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
+//
+// Data data;
+// while (ReadData(source_file, &data)) {
+// if (!data.IsGood()) {
+// absl::Status result = absl::FailedPreconditionError("Read bad data");
+// return result; // Both cleanups execute
+// }
+// SaveData(sink_file, &data);
+// }
+//
+// return absl::OkStatus(); // Both cleanups execute
+// }
+// ```
+//
+// Methods:
+//
+// `std::move(cleanup).Cancel()` will prevent the callback from executing.
+//
+// `std::move(cleanup).Invoke()` will execute the callback early, before
+// destruction, and prevent the callback from executing in the destructor.
+//
+// Usage:
+//
+// `absl::Cleanup` is not an interface type. It is only intended to be used
+// within the body of a function. It is not a value type and instead models a
+// control flow construct. Check out `defer` in Golang for something similar.
+
+#ifndef ABSL_CLEANUP_CLEANUP_H_
+#define ABSL_CLEANUP_CLEANUP_H_
+
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+#include "absl/cleanup/internal/cleanup.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename Arg, typename Callback = void()>
+class ABSL_MUST_USE_RESULT Cleanup final {
+ static_assert(cleanup_internal::WasDeduced<Arg>(),
+ "Explicit template parameters are not supported.");
+
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
+ "Callbacks that return values are not supported.");
+
+ public:
+ Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT
+
+ Cleanup(Cleanup&& other) = default;
+
+ void Cancel() && {
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
+ storage_.DestroyCallback();
+ }
+
+ void Invoke() && {
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
+ storage_.InvokeCallback();
+ storage_.DestroyCallback();
+ }
+
+ ~Cleanup() {
+ if (storage_.IsCallbackEngaged()) {
+ storage_.InvokeCallback();
+ storage_.DestroyCallback();
+ }
+ }
+
+ private:
+ cleanup_internal::Storage<Callback> storage_;
+};
+
+// `absl::Cleanup c = /* callback */;`
+//
+// C++17 type deduction API for creating an instance of `absl::Cleanup`
+#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+template <typename Callback>
+Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
+#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+
+// `auto c = absl::MakeCleanup(/* callback */);`
+//
+// C++11 type deduction API for creating an instance of `absl::Cleanup`
+template <typename... Args, typename Callback>
+absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
+ static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
+ "Explicit template parameters are not supported.");
+
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
+ "Callbacks that return values are not supported.");
+
+ return {std::move(callback)};
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CLEANUP_CLEANUP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/cleanup/internal/cleanup.h b/contrib/restricted/abseil-cpp/absl/cleanup/internal/cleanup.h
new file mode 100644
index 0000000000..2783fcb7c1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/cleanup/internal/cleanup.h
@@ -0,0 +1,100 @@
+// Copyright 2021 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_CLEANUP_INTERNAL_CLEANUP_H_
+#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
+
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/base/macros.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace cleanup_internal {
+
+struct Tag {};
+
+template <typename Arg, typename... Args>
+constexpr bool WasDeduced() {
+ return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
+ (sizeof...(Args) == 0);
+}
+
+template <typename Callback>
+constexpr bool ReturnsVoid() {
+ return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
+}
+
+template <typename Callback>
+class Storage {
+ public:
+ Storage() = delete;
+
+ explicit Storage(Callback callback) {
+ // Placement-new into a character buffer is used for eager destruction when
+ // the cleanup is invoked or cancelled. To ensure this optimizes well, the
+ // behavior is implemented locally instead of using an absl::optional.
+ ::new (GetCallbackBuffer()) Callback(std::move(callback));
+ is_callback_engaged_ = true;
+ }
+
+ Storage(Storage&& other) {
+ ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());
+
+ ::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));
+ is_callback_engaged_ = true;
+
+ other.DestroyCallback();
+ }
+
+ Storage(const Storage& other) = delete;
+
+ Storage& operator=(Storage&& other) = delete;
+
+ Storage& operator=(const Storage& other) = delete;
+
+ void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); }
+
+ Callback& GetCallback() {
+ return *reinterpret_cast<Callback*>(GetCallbackBuffer());
+ }
+
+ bool IsCallbackEngaged() const { return is_callback_engaged_; }
+
+ void DestroyCallback() {
+ is_callback_engaged_ = false;
+ GetCallback().~Callback();
+ }
+
+ void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
+ std::move(GetCallback())();
+ }
+
+ private:
+ bool is_callback_engaged_;
+ alignas(Callback) char callback_buffer_[sizeof(Callback)];
+};
+
+} // namespace cleanup_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/fixed_array.h b/contrib/restricted/abseil-cpp/absl/container/fixed_array.h
index 2aefae3bde..b67379cfe7 100644
--- a/contrib/restricted/abseil-cpp/absl/container/fixed_array.h
+++ b/contrib/restricted/abseil-cpp/absl/container/fixed_array.h
@@ -62,11 +62,10 @@ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
// A `FixedArray` provides a run-time fixed-size array, allocating a small array
// inline for efficiency.
//
-// Most users should not specify an `inline_elements` argument and let
-// `FixedArray` automatically determine the number of elements
-// to store inline based on `sizeof(T)`. If `inline_elements` is specified, the
-// `FixedArray` implementation will use inline storage for arrays with a
-// length <= `inline_elements`.
+// Most users should not specify the `N` template parameter and let `FixedArray`
+// automatically determine the number of elements to store inline based on
+// `sizeof(T)`. If `N` is specified, the `FixedArray` implementation will use
+// inline storage for arrays with a length <= `N`.
//
// Note that a `FixedArray` constructed with a `size_type` argument will
// default-initialize its values by leaving trivially constructible types
@@ -471,6 +470,9 @@ class FixedArray {
return n <= inline_elements;
}
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+ ABSL_ATTRIBUTE_NOINLINE
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
StorageElement* InitializeData() {
if (UsingInlinedStorage(size())) {
InlinedStorage::AnnotateConstruct(size());
diff --git a/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h
index 4938c703b7..f5376f991a 100644
--- a/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h
+++ b/contrib/restricted/abseil-cpp/absl/container/flat_hash_set.h
@@ -474,13 +474,6 @@ struct FlatHashSetPolicy {
absl::allocator_traits<Allocator>::destroy(*alloc, slot);
}
- template <class Allocator>
- static void transfer(Allocator* alloc, slot_type* new_slot,
- slot_type* old_slot) {
- construct(alloc, new_slot, std::move(*old_slot));
- destroy(alloc, old_slot);
- }
-
static T& element(slot_type* slot) { return *slot; }
template <class F, class... Args>
diff --git a/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h b/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h
index bc1c4a776c..7058f375e7 100644
--- a/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h
+++ b/contrib/restricted/abseil-cpp/absl/container/inlined_vector.h
@@ -52,6 +52,7 @@
#include "absl/base/port.h"
#include "absl/container/internal/inlined_vector.h"
#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -77,6 +78,8 @@ class InlinedVector {
using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;
template <typename TheA>
using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<TheA>;
+ template <typename TheA>
+ using IsMoveAssignOk = inlined_vector_internal::IsMoveAssignOk<TheA>;
template <typename TheA, typename Iterator>
using IteratorValueAdapter =
@@ -94,6 +97,12 @@ class InlinedVector {
using DisableIfAtLeastForwardIterator = absl::enable_if_t<
!inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+ using MemcpyPolicy = typename Storage::MemcpyPolicy;
+ using ElementwiseAssignPolicy = typename Storage::ElementwiseAssignPolicy;
+ using ElementwiseConstructPolicy =
+ typename Storage::ElementwiseConstructPolicy;
+ using MoveAssignmentPolicy = typename Storage::MoveAssignmentPolicy;
+
public:
using allocator_type = A;
using value_type = inlined_vector_internal::ValueType<A>;
@@ -275,8 +284,10 @@ class InlinedVector {
size_type max_size() const noexcept {
// One bit of the size storage is used to indicate whether the inlined
// vector contains allocated memory. As a result, the maximum size that the
- // inlined vector can express is half of the max for `size_type`.
- return (std::numeric_limits<size_type>::max)() / 2;
+ // inlined vector can express is the minimum of the limit of how many
+ // objects we can allocate and std::numeric_limits<size_type>::max() / 2.
+ return (std::min)(AllocatorTraits<A>::max_size(storage_.GetAllocator()),
+ (std::numeric_limits<size_type>::max)() / 2);
}
// `InlinedVector::capacity()`
@@ -484,18 +495,7 @@ class InlinedVector {
// unspecified state.
InlinedVector& operator=(InlinedVector&& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
- if (IsMemcpyOk<A>::value || other.storage_.GetIsAllocated()) {
- inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
- storage_.GetAllocator(), data(), size());
- storage_.DeallocateIfAllocated();
- storage_.MemcpyFrom(other.storage_);
-
- other.storage_.SetInlinedSize(0);
- } else {
- storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
- MoveIterator<A>(other.storage_.GetInlinedData())),
- other.size());
- }
+ MoveAssignment(MoveAssignmentPolicy{}, std::move(other));
}
return *this;
@@ -624,9 +624,9 @@ class InlinedVector {
ABSL_HARDENING_ASSERT(pos <= end());
if (ABSL_PREDICT_TRUE(first != last)) {
- return storage_.Insert(pos,
- IteratorValueAdapter<A, ForwardIterator>(first),
- std::distance(first, last));
+ return storage_.Insert(
+ pos, IteratorValueAdapter<A, ForwardIterator>(first),
+ static_cast<size_type>(std::distance(first, last)));
} else {
return const_cast<iterator>(pos);
}
@@ -643,7 +643,7 @@ class InlinedVector {
ABSL_HARDENING_ASSERT(pos >= begin());
ABSL_HARDENING_ASSERT(pos <= end());
- size_type index = std::distance(cbegin(), pos);
+ size_type index = static_cast<size_type>(std::distance(cbegin(), pos));
for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
insert(data() + i, *first);
}
@@ -661,10 +661,22 @@ class InlinedVector {
ABSL_HARDENING_ASSERT(pos <= end());
value_type dealias(std::forward<Args>(args)...);
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2
+ // It appears that GCC thinks that since `pos` is a const pointer and may
+ // point to uninitialized memory at this point, a warning should be
+ // issued. But `pos` is actually only used to compute an array index to
+ // write to.
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
return storage_.Insert(pos,
IteratorValueAdapter<A, MoveIterator<A>>(
MoveIterator<A>(std::addressof(dealias))),
1);
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
}
// `InlinedVector::emplace_back(...)`
@@ -771,6 +783,42 @@ class InlinedVector {
template <typename H, typename TheT, size_t TheN, typename TheA>
friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
+ void MoveAssignment(MemcpyPolicy, InlinedVector&& other) {
+ inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
+ storage_.GetAllocator(), data(), size());
+ storage_.DeallocateIfAllocated();
+ storage_.MemcpyFrom(other.storage_);
+
+ other.storage_.SetInlinedSize(0);
+ }
+
+ void MoveAssignment(ElementwiseAssignPolicy, InlinedVector&& other) {
+ if (other.storage_.GetIsAllocated()) {
+ MoveAssignment(MemcpyPolicy{}, std::move(other));
+ } else {
+ storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
+ MoveIterator<A>(other.storage_.GetInlinedData())),
+ other.size());
+ }
+ }
+
+ void MoveAssignment(ElementwiseConstructPolicy, InlinedVector&& other) {
+ if (other.storage_.GetIsAllocated()) {
+ MoveAssignment(MemcpyPolicy{}, std::move(other));
+ } else {
+ inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
+ storage_.GetAllocator(), data(), size());
+ storage_.DeallocateIfAllocated();
+
+ IteratorValueAdapter<A, MoveIterator<A>> other_values(
+ MoveIterator<A>(other.storage_.GetInlinedData()));
+ inlined_vector_internal::ConstructElements<A>(
+ storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
+ other.storage_.GetSize());
+ storage_.SetInlinedSize(other.storage_.GetSize());
+ }
+ }
+
Storage storage_;
};
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/common.h b/contrib/restricted/abseil-cpp/absl/container/internal/common.h
index 416d9aa32e..9239bb4d09 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/common.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/common.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_H_
-#define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+#ifndef ABSL_CONTAINER_INTERNAL_COMMON_H_
+#define ABSL_CONTAINER_INTERNAL_COMMON_H_
#include <cassert>
#include <type_traits>
@@ -204,4 +204,4 @@ struct InsertReturnType {
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+#endif // ABSL_CONTAINER_INTERNAL_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h b/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h
new file mode 100644
index 0000000000..b42c9a482e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/common_policy_traits.h
@@ -0,0 +1,132 @@
+// 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_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
+#define ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
+
+#include <cstddef>
+#include <cstring>
+#include <memory>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// Defines how slots are initialized/destroyed/moved.
+template <class Policy, class = void>
+struct common_policy_traits {
+ // The actual object stored in the container.
+ using slot_type = typename Policy::slot_type;
+ using reference = decltype(Policy::element(std::declval<slot_type*>()));
+ using value_type = typename std::remove_reference<reference>::type;
+
+ // PRECONDITION: `slot` is UNINITIALIZED
+ // POSTCONDITION: `slot` is INITIALIZED
+ template <class Alloc, class... Args>
+ static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
+ Policy::construct(alloc, slot, std::forward<Args>(args)...);
+ }
+
+ // PRECONDITION: `slot` is INITIALIZED
+ // POSTCONDITION: `slot` is UNINITIALIZED
+ template <class Alloc>
+ static void destroy(Alloc* alloc, slot_type* slot) {
+ Policy::destroy(alloc, slot);
+ }
+
+ // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
+ // allocator inside `old_slot` to `new_slot` can be transferred.
+ //
+ // OPTIONAL: defaults to:
+ //
+ // clone(new_slot, std::move(*old_slot));
+ // destroy(old_slot);
+ //
+ // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
+ // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
+ // UNINITIALIZED
+ template <class Alloc>
+ static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
+ transfer_impl(alloc, new_slot, old_slot, Rank0{});
+ }
+
+ // PRECONDITION: `slot` is INITIALIZED
+ // POSTCONDITION: `slot` is INITIALIZED
+ // Note: we use remove_const_t so that the two overloads have different args
+ // in the case of sets with explicitly const value_types.
+ template <class P = Policy>
+ static auto element(absl::remove_const_t<slot_type>* slot)
+ -> decltype(P::element(slot)) {
+ return P::element(slot);
+ }
+ template <class P = Policy>
+ static auto element(const slot_type* slot) -> decltype(P::element(slot)) {
+ return P::element(slot);
+ }
+
+ static constexpr bool transfer_uses_memcpy() {
+ return std::is_same<decltype(transfer_impl<std::allocator<char>>(
+ nullptr, nullptr, nullptr, Rank0{})),
+ std::true_type>::value;
+ }
+
+ private:
+ // To rank the overloads below for overload resoltion. Rank0 is preferred.
+ struct Rank2 {};
+ struct Rank1 : Rank2 {};
+ struct Rank0 : Rank1 {};
+
+ // Use auto -> decltype as an enabler.
+ template <class Alloc, class P = Policy>
+ static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
+ slot_type* old_slot, Rank0)
+ -> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
+ P::transfer(alloc, new_slot, old_slot);
+ }
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ // This overload returns true_type for the trait below.
+ // The conditional_t is to make the enabler type dependent.
+ template <class Alloc,
+ typename = std::enable_if_t<absl::is_trivially_relocatable<
+ std::conditional_t<false, Alloc, value_type>>::value>>
+ static std::true_type transfer_impl(Alloc*, slot_type* new_slot,
+ slot_type* old_slot, Rank1) {
+ // TODO(b/247130232): remove casts after fixing warnings.
+ // TODO(b/251814870): remove casts after fixing warnings.
+ std::memcpy(
+ static_cast<void*>(std::launder(
+ const_cast<std::remove_const_t<value_type>*>(&element(new_slot)))),
+ static_cast<const void*>(&element(old_slot)), sizeof(value_type));
+ return {};
+ }
+#endif
+
+ template <class Alloc>
+ static void transfer_impl(Alloc* alloc, slot_type* new_slot,
+ slot_type* old_slot, Rank2) {
+ construct(alloc, new_slot, std::move(element(old_slot)));
+ destroy(alloc, old_slot);
+ }
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_COMMON_POLICY_TRAITS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h b/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h
index 00e9f6d703..bfa4ff93d7 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/container_memory.h
@@ -17,6 +17,7 @@
#include <cassert>
#include <cstddef>
+#include <cstring>
#include <memory>
#include <new>
#include <tuple>
@@ -340,7 +341,8 @@ template <class K, class V>
struct map_slot_policy {
using slot_type = map_slot_type<K, V>;
using value_type = std::pair<const K, V>;
- using mutable_value_type = std::pair<K, V>;
+ using mutable_value_type =
+ std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
private:
static void emplace(slot_type* slot) {
@@ -424,6 +426,16 @@ struct map_slot_policy {
static void transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
emplace(new_slot);
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ if (absl::is_trivially_relocatable<value_type>()) {
+ // TODO(b/247130232,b/251814870): remove casts after fixing warnings.
+ std::memcpy(static_cast<void*>(std::launder(&new_slot->value)),
+ static_cast<const void*>(&old_slot->value),
+ sizeof(value_type));
+ return;
+ }
+#endif
+
if (kMutableKeys::value) {
absl::allocator_traits<Allocator>::construct(
*alloc, &new_slot->mutable_value, std::move(old_slot->mutable_value));
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_traits.h b/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_traits.h
index 46c97b18a2..164ec12316 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_traits.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_traits.h
@@ -21,6 +21,7 @@
#include <type_traits>
#include <utility>
+#include "absl/container/internal/common_policy_traits.h"
#include "absl/meta/type_traits.h"
namespace absl {
@@ -29,7 +30,7 @@ namespace container_internal {
// Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void>
-struct hash_policy_traits {
+struct hash_policy_traits : common_policy_traits<Policy> {
// The type of the keys stored in the hashtable.
using key_type = typename Policy::key_type;
@@ -87,43 +88,6 @@ struct hash_policy_traits {
// Defaults to false if not provided by the policy.
using constant_iterators = ConstantIteratorsImpl<>;
- // PRECONDITION: `slot` is UNINITIALIZED
- // POSTCONDITION: `slot` is INITIALIZED
- template <class Alloc, class... Args>
- static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
- Policy::construct(alloc, slot, std::forward<Args>(args)...);
- }
-
- // PRECONDITION: `slot` is INITIALIZED
- // POSTCONDITION: `slot` is UNINITIALIZED
- template <class Alloc>
- static void destroy(Alloc* alloc, slot_type* slot) {
- Policy::destroy(alloc, slot);
- }
-
- // Transfers the `old_slot` to `new_slot`. Any memory allocated by the
- // allocator inside `old_slot` to `new_slot` can be transferred.
- //
- // OPTIONAL: defaults to:
- //
- // clone(new_slot, std::move(*old_slot));
- // destroy(old_slot);
- //
- // PRECONDITION: `new_slot` is UNINITIALIZED and `old_slot` is INITIALIZED
- // POSTCONDITION: `new_slot` is INITIALIZED and `old_slot` is
- // UNINITIALIZED
- template <class Alloc>
- static void transfer(Alloc* alloc, slot_type* new_slot, slot_type* old_slot) {
- transfer_impl(alloc, new_slot, old_slot, 0);
- }
-
- // PRECONDITION: `slot` is INITIALIZED
- // POSTCONDITION: `slot` is INITIALIZED
- template <class P = Policy>
- static auto element(slot_type* slot) -> decltype(P::element(slot)) {
- return P::element(slot);
- }
-
// Returns the amount of memory owned by `slot`, exclusive of `sizeof(*slot)`.
//
// If `slot` is nullptr, returns the constant amount of memory owned by any
@@ -174,8 +138,8 @@ struct hash_policy_traits {
// Used for node handle manipulation.
template <class P = Policy>
static auto mutable_key(slot_type* slot)
- -> decltype(P::apply(ReturnKey(), element(slot))) {
- return P::apply(ReturnKey(), element(slot));
+ -> decltype(P::apply(ReturnKey(), hash_policy_traits::element(slot))) {
+ return P::apply(ReturnKey(), hash_policy_traits::element(slot));
}
// Returns the "value" (as opposed to the "key") portion of the element. Used
@@ -184,21 +148,6 @@ struct hash_policy_traits {
static auto value(T* elem) -> decltype(P::value(elem)) {
return P::value(elem);
}
-
- private:
- // Use auto -> decltype as an enabler.
- template <class Alloc, class P = Policy>
- static auto transfer_impl(Alloc* alloc, slot_type* new_slot,
- slot_type* old_slot, int)
- -> decltype((void)P::transfer(alloc, new_slot, old_slot)) {
- P::transfer(alloc, new_slot, old_slot);
- }
- template <class Alloc>
- static void transfer_impl(Alloc* alloc, slot_type* new_slot,
- slot_type* old_slot, char) {
- construct(alloc, new_slot, std::move(element(old_slot)));
- destroy(alloc, old_slot);
- }
};
} // namespace container_internal
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.cc b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
index efc1be5866..6b6d349150 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
@@ -14,6 +14,7 @@
#include "absl/container/internal/hashtablez_sampler.h"
+#include <algorithm>
#include <atomic>
#include <cassert>
#include <cmath>
@@ -158,6 +159,43 @@ void UnsampleSlow(HashtablezInfo* info) {
GlobalHashtablezSampler().Unregister(info);
}
+void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
+#ifdef ABSL_INTERNAL_HAVE_SSE2
+ total_probe_length /= 16;
+#else
+ total_probe_length /= 8;
+#endif
+ info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
+ info->num_erases.store(0, std::memory_order_relaxed);
+ // There is only one concurrent writer, so `load` then `store` is sufficient
+ // instead of using `fetch_add`.
+ info->num_rehashes.store(
+ 1 + info->num_rehashes.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+}
+
+void RecordReservationSlow(HashtablezInfo* info, size_t target_capacity) {
+ info->max_reserve.store(
+ (std::max)(info->max_reserve.load(std::memory_order_relaxed),
+ target_capacity),
+ std::memory_order_relaxed);
+}
+
+void RecordClearedReservationSlow(HashtablezInfo* info) {
+ info->max_reserve.store(0, std::memory_order_relaxed);
+}
+
+void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
+ size_t capacity) {
+ info->size.store(size, std::memory_order_relaxed);
+ info->capacity.store(capacity, std::memory_order_relaxed);
+ if (size == 0) {
+ // This is a clear, reset the total/num_erases too.
+ info->total_probe_length.store(0, std::memory_order_relaxed);
+ info->num_erases.store(0, std::memory_order_relaxed);
+ }
+}
+
void RecordInsertSlow(HashtablezInfo* info, size_t hash,
size_t distance_from_desired) {
// SwissTables probe in groups of 16, so scale this to count items probes and
@@ -180,6 +218,14 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
info->size.fetch_add(1, std::memory_order_relaxed);
}
+void RecordEraseSlow(HashtablezInfo* info) {
+ info->size.fetch_sub(1, std::memory_order_relaxed);
+ // There is only one concurrent writer, so `load` then `store` is sufficient
+ // instead of using `fetch_add`.
+ info->num_erases.store(1 + info->num_erases.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+}
+
void SetHashtablezConfigListener(HashtablezConfigListener l) {
g_hashtablez_config_listener.store(l, std::memory_order_release);
}
@@ -215,21 +261,20 @@ void SetHashtablezSampleParameterInternal(int32_t rate) {
}
}
-int32_t GetHashtablezMaxSamples() {
+size_t GetHashtablezMaxSamples() {
return GlobalHashtablezSampler().GetMaxSamples();
}
-void SetHashtablezMaxSamples(int32_t max) {
+void SetHashtablezMaxSamples(size_t max) {
SetHashtablezMaxSamplesInternal(max);
TriggerHashtablezConfigListener();
}
-void SetHashtablezMaxSamplesInternal(int32_t max) {
+void SetHashtablezMaxSamplesInternal(size_t max) {
if (max > 0) {
GlobalHashtablezSampler().SetMaxSamples(max);
} else {
- ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld",
- static_cast<long long>(max)); // NOLINT(runtime/int)
+ ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: 0");
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h
index d4016d8a9f..d8fd8f34f9 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hashtablez_sampler.h
@@ -95,55 +95,19 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
size_t inline_element_size; // How big is the slot?
};
-inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
-#ifdef ABSL_INTERNAL_HAVE_SSE2
- total_probe_length /= 16;
-#else
- total_probe_length /= 8;
-#endif
- info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
- info->num_erases.store(0, std::memory_order_relaxed);
- // There is only one concurrent writer, so `load` then `store` is sufficient
- // instead of using `fetch_add`.
- info->num_rehashes.store(
- 1 + info->num_rehashes.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
-}
+void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length);
-inline void RecordReservationSlow(HashtablezInfo* info,
- size_t target_capacity) {
- info->max_reserve.store(
- (std::max)(info->max_reserve.load(std::memory_order_relaxed),
- target_capacity),
- std::memory_order_relaxed);
-}
+void RecordReservationSlow(HashtablezInfo* info, size_t target_capacity);
-inline void RecordClearedReservationSlow(HashtablezInfo* info) {
- info->max_reserve.store(0, std::memory_order_relaxed);
-}
+void RecordClearedReservationSlow(HashtablezInfo* info);
-inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
- size_t capacity) {
- info->size.store(size, std::memory_order_relaxed);
- info->capacity.store(capacity, std::memory_order_relaxed);
- if (size == 0) {
- // This is a clear, reset the total/num_erases too.
- info->total_probe_length.store(0, std::memory_order_relaxed);
- info->num_erases.store(0, std::memory_order_relaxed);
- }
-}
+void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
+ size_t capacity);
void RecordInsertSlow(HashtablezInfo* info, size_t hash,
size_t distance_from_desired);
-inline void RecordEraseSlow(HashtablezInfo* info) {
- info->size.fetch_sub(1, std::memory_order_relaxed);
- // There is only one concurrent writer, so `load` then `store` is sufficient
- // instead of using `fetch_add`.
- info->num_erases.store(
- 1 + info->num_erases.load(std::memory_order_relaxed),
- std::memory_order_relaxed);
-}
+void RecordEraseSlow(HashtablezInfo* info);
struct SamplingState {
int64_t next_sample;
@@ -165,7 +129,10 @@ class HashtablezInfoHandle {
public:
explicit HashtablezInfoHandle() : info_(nullptr) {}
explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}
- ~HashtablezInfoHandle() {
+
+ // We do not have a destructor. Caller is responsible for calling Unregister
+ // before destroying the handle.
+ void Unregister() {
if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
UnsampleSlow(info_);
}
@@ -230,6 +197,7 @@ class HashtablezInfoHandle {
explicit HashtablezInfoHandle() = default;
explicit HashtablezInfoHandle(std::nullptr_t) {}
+ inline void Unregister() {}
inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
inline void RecordRehash(size_t /*total_probe_length*/) {}
inline void RecordReservation(size_t /*target_capacity*/) {}
@@ -281,9 +249,9 @@ void SetHashtablezSampleParameter(int32_t rate);
void SetHashtablezSampleParameterInternal(int32_t rate);
// Sets a soft max for the number of samples that will be kept.
-int32_t GetHashtablezMaxSamples();
-void SetHashtablezMaxSamples(int32_t max);
-void SetHashtablezMaxSamplesInternal(int32_t max);
+size_t GetHashtablezMaxSamples();
+void SetHashtablezMaxSamples(size_t max);
+void SetHashtablezMaxSamplesInternal(size_t max);
// Configuration override.
// This allows process-wide sampling without depending on order of
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h b/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h
index 54c92a0106..0398f53008 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/inlined_vector.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
-#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+#ifndef ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
+#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
#include <algorithm>
#include <cstddef>
@@ -83,6 +83,11 @@ using IsMemcpyOk =
absl::is_trivially_copy_assignable<ValueType<A>>,
absl::is_trivially_destructible<ValueType<A>>>;
+template <typename A>
+using IsMoveAssignOk = std::is_move_assignable<ValueType<A>>;
+template <typename A>
+using IsSwapOk = absl::type_traits_internal::IsSwappable<ValueType<A>>;
+
template <typename T>
struct TypeIdentity {
using type = T;
@@ -120,8 +125,8 @@ struct DestroyAdapter<A, /* IsTriviallyDestructible */ true> {
template <typename A>
struct Allocation {
- Pointer<A> data;
- SizeType<A> capacity;
+ Pointer<A> data = nullptr;
+ SizeType<A> capacity = 0;
};
template <typename A,
@@ -297,6 +302,20 @@ class ConstructionTransaction {
template <typename T, size_t N, typename A>
class Storage {
public:
+ struct MemcpyPolicy {};
+ struct ElementwiseAssignPolicy {};
+ struct ElementwiseSwapPolicy {};
+ struct ElementwiseConstructPolicy {};
+
+ using MoveAssignmentPolicy = absl::conditional_t<
+ IsMemcpyOk<A>::value, MemcpyPolicy,
+ absl::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,
+ ElementwiseConstructPolicy>>;
+ using SwapPolicy = absl::conditional_t<
+ IsMemcpyOk<A>::value, MemcpyPolicy,
+ absl::conditional_t<IsSwapOk<A>::value, ElementwiseSwapPolicy,
+ ElementwiseConstructPolicy>>;
+
static SizeType<A> NextCapacity(SizeType<A> current_capacity) {
return current_capacity * 2;
}
@@ -360,7 +379,9 @@ class Storage {
return data_.allocated.allocated_capacity;
}
- SizeType<A> GetInlinedCapacity() const { return static_cast<SizeType<A>>(N); }
+ SizeType<A> GetInlinedCapacity() const {
+ return static_cast<SizeType<A>>(kOptimalInlinedSize);
+ }
StorageView<A> MakeStorageView() {
return GetIsAllocated() ? StorageView<A>{GetAllocatedData(), GetSize(),
@@ -464,8 +485,15 @@ class Storage {
SizeType<A> allocated_capacity;
};
+ // `kOptimalInlinedSize` is an automatically adjusted inlined capacity of the
+ // `InlinedVector`. Sometimes, it is possible to increase the capacity (from
+ // the user requested `N`) without increasing the size of the `InlinedVector`.
+ static constexpr size_t kOptimalInlinedSize =
+ (std::max)(N, sizeof(Allocated) / sizeof(ValueType<A>));
+
struct Inlined {
- alignas(ValueType<A>) char inlined_data[sizeof(ValueType<A>[N])];
+ alignas(ValueType<A>) char inlined_data[sizeof(
+ ValueType<A>[kOptimalInlinedSize])];
};
union Data {
@@ -473,6 +501,13 @@ class Storage {
Inlined inlined;
};
+ void SwapN(ElementwiseSwapPolicy, Storage* other, SizeType<A> n);
+ void SwapN(ElementwiseConstructPolicy, Storage* other, SizeType<A> n);
+
+ void SwapInlinedElements(MemcpyPolicy, Storage* other);
+ template <typename NotMemcpyPolicy>
+ void SwapInlinedElements(NotMemcpyPolicy, Storage* other);
+
template <typename... Args>
ABSL_ATTRIBUTE_NOINLINE Reference<A> EmplaceBackSlow(Args&&... args);
@@ -641,8 +676,8 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
SizeType<A> insert_count) -> Iterator<A> {
StorageView<A> storage_view = MakeStorageView();
- SizeType<A> insert_index =
- std::distance(ConstIterator<A>(storage_view.data), pos);
+ auto insert_index = static_cast<SizeType<A>>(
+ std::distance(ConstIterator<A>(storage_view.data), pos));
SizeType<A> insert_end_index = insert_index + insert_count;
SizeType<A> new_size = storage_view.size + insert_count;
@@ -784,9 +819,9 @@ auto Storage<T, N, A>::Erase(ConstIterator<A> from, ConstIterator<A> to)
-> Iterator<A> {
StorageView<A> storage_view = MakeStorageView();
- SizeType<A> erase_size = std::distance(from, to);
- SizeType<A> erase_index =
- std::distance(ConstIterator<A>(storage_view.data), from);
+ auto erase_size = static_cast<SizeType<A>>(std::distance(from, to));
+ auto erase_index = static_cast<SizeType<A>>(
+ std::distance(ConstIterator<A>(storage_view.data), from));
SizeType<A> erase_end_index = erase_index + erase_size;
IteratorValueAdapter<A, MoveIterator<A>> move_values(
@@ -886,26 +921,7 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
if (GetIsAllocated() && other_storage_ptr->GetIsAllocated()) {
swap(data_.allocated, other_storage_ptr->data_.allocated);
} else if (!GetIsAllocated() && !other_storage_ptr->GetIsAllocated()) {
- Storage* small_ptr = this;
- Storage* large_ptr = other_storage_ptr;
- if (small_ptr->GetSize() > large_ptr->GetSize()) swap(small_ptr, large_ptr);
-
- for (SizeType<A> i = 0; i < small_ptr->GetSize(); ++i) {
- swap(small_ptr->GetInlinedData()[i], large_ptr->GetInlinedData()[i]);
- }
-
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(large_ptr->GetInlinedData() + small_ptr->GetSize()));
-
- ConstructElements<A>(large_ptr->GetAllocator(),
- small_ptr->GetInlinedData() + small_ptr->GetSize(),
- move_values,
- large_ptr->GetSize() - small_ptr->GetSize());
-
- DestroyAdapter<A>::DestroyElements(
- large_ptr->GetAllocator(),
- large_ptr->GetInlinedData() + small_ptr->GetSize(),
- large_ptr->GetSize() - small_ptr->GetSize());
+ SwapInlinedElements(SwapPolicy{}, other_storage_ptr);
} else {
Storage* allocated_ptr = this;
Storage* inlined_ptr = other_storage_ptr;
@@ -941,6 +957,68 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
swap(GetAllocator(), other_storage_ptr->GetAllocator());
}
+template <typename T, size_t N, typename A>
+void Storage<T, N, A>::SwapN(ElementwiseSwapPolicy, Storage* other,
+ SizeType<A> n) {
+ std::swap_ranges(GetInlinedData(), GetInlinedData() + n,
+ other->GetInlinedData());
+}
+
+template <typename T, size_t N, typename A>
+void Storage<T, N, A>::SwapN(ElementwiseConstructPolicy, Storage* other,
+ SizeType<A> n) {
+ Pointer<A> a = GetInlinedData();
+ Pointer<A> b = other->GetInlinedData();
+ // see note on allocators in `SwapInlinedElements`.
+ A& allocator_a = GetAllocator();
+ A& allocator_b = other->GetAllocator();
+ for (SizeType<A> i = 0; i < n; ++i, ++a, ++b) {
+ ValueType<A> tmp(std::move(*a));
+
+ AllocatorTraits<A>::destroy(allocator_a, a);
+ AllocatorTraits<A>::construct(allocator_b, a, std::move(*b));
+
+ AllocatorTraits<A>::destroy(allocator_b, b);
+ AllocatorTraits<A>::construct(allocator_a, b, std::move(tmp));
+ }
+}
+
+template <typename T, size_t N, typename A>
+void Storage<T, N, A>::SwapInlinedElements(MemcpyPolicy, Storage* other) {
+ Data tmp = data_;
+ data_ = other->data_;
+ other->data_ = tmp;
+}
+
+template <typename T, size_t N, typename A>
+template <typename NotMemcpyPolicy>
+void Storage<T, N, A>::SwapInlinedElements(NotMemcpyPolicy policy,
+ Storage* other) {
+ // Note: `destroy` needs to use pre-swap allocator while `construct` -
+ // post-swap allocator. Allocators will be swaped later on outside of
+ // `SwapInlinedElements`.
+ Storage* small_ptr = this;
+ Storage* large_ptr = other;
+ if (small_ptr->GetSize() > large_ptr->GetSize()) {
+ std::swap(small_ptr, large_ptr);
+ }
+
+ auto small_size = small_ptr->GetSize();
+ auto diff = large_ptr->GetSize() - small_size;
+ SwapN(policy, other, small_size);
+
+ IteratorValueAdapter<A, MoveIterator<A>> move_values(
+ MoveIterator<A>(large_ptr->GetInlinedData() + small_size));
+
+ ConstructElements<A>(large_ptr->GetAllocator(),
+ small_ptr->GetInlinedData() + small_size, move_values,
+ diff);
+
+ DestroyAdapter<A>::DestroyElements(large_ptr->GetAllocator(),
+ large_ptr->GetInlinedData() + small_size,
+ diff);
+}
+
// End ignore "array-bounds"
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
@@ -950,4 +1028,4 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc
index c63a2e02d1..3677ac595e 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.cc
@@ -16,6 +16,7 @@
#include <atomic>
#include <cstddef>
+#include <cstring>
#include "absl/base/config.h"
@@ -25,11 +26,14 @@ namespace container_internal {
// A single block of empty control bytes for tables without any slots allocated.
// This enables removing a branch in the hot path of find().
-alignas(16) ABSL_CONST_INIT ABSL_DLL const ctrl_t kEmptyGroup[16] = {
+// We have 17 bytes because there may be a generation counter. Any constant is
+// fine for the generation counter.
+alignas(16) ABSL_CONST_INIT ABSL_DLL const ctrl_t kEmptyGroup[17] = {
ctrl_t::kSentinel, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
- ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty};
+ ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
+ static_cast<ctrl_t>(0)};
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
constexpr size_t Group::kWidth;
@@ -63,8 +67,155 @@ void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());
ctrl[capacity] = ctrl_t::kSentinel;
}
-// Extern template instantiotion for inline function.
-template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
+// Extern template instantiation for inline function.
+template FindInfo find_first_non_full(const CommonFields&, size_t);
+
+FindInfo find_first_non_full_outofline(const CommonFields& common,
+ size_t hash) {
+ return find_first_non_full(common, hash);
+}
+
+// Return address of the ith slot in slots where each slot occupies slot_size.
+static inline void* SlotAddress(void* slot_array, size_t slot,
+ size_t slot_size) {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot_array) +
+ (slot * slot_size));
+}
+
+// Return the address of the slot just after slot assuming each slot
+// has the specified size.
+static inline void* NextSlot(void* slot, size_t slot_size) {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) + slot_size);
+}
+
+// Return the address of the slot just before slot assuming each slot
+// has the specified size.
+static inline void* PrevSlot(void* slot, size_t slot_size) {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(slot) - slot_size);
+}
+
+void DropDeletesWithoutResize(CommonFields& common,
+ const PolicyFunctions& policy, void* tmp_space) {
+ void* set = &common;
+ void* slot_array = common.slots_;
+ const size_t capacity = common.capacity_;
+ assert(IsValidCapacity(capacity));
+ assert(!is_small(capacity));
+ // Algorithm:
+ // - mark all DELETED slots as EMPTY
+ // - mark all FULL slots as DELETED
+ // - for each slot marked as DELETED
+ // hash = Hash(element)
+ // target = find_first_non_full(hash)
+ // if target is in the same group
+ // mark slot as FULL
+ // else if target is EMPTY
+ // transfer element to target
+ // mark slot as EMPTY
+ // mark target as FULL
+ // else if target is DELETED
+ // swap current element with target element
+ // mark target as FULL
+ // repeat procedure for current slot with moved from element (target)
+ ctrl_t* ctrl = common.control_;
+ ConvertDeletedToEmptyAndFullToDeleted(ctrl, capacity);
+ auto hasher = policy.hash_slot;
+ auto transfer = policy.transfer;
+ const size_t slot_size = policy.slot_size;
+
+ size_t total_probe_length = 0;
+ void* slot_ptr = SlotAddress(slot_array, 0, slot_size);
+ for (size_t i = 0; i != capacity;
+ ++i, slot_ptr = NextSlot(slot_ptr, slot_size)) {
+ assert(slot_ptr == SlotAddress(slot_array, i, slot_size));
+ if (!IsDeleted(ctrl[i])) continue;
+ const size_t hash = (*hasher)(set, slot_ptr);
+ const FindInfo target = find_first_non_full(common, hash);
+ const size_t new_i = target.offset;
+ total_probe_length += target.probe_length;
+
+ // Verify if the old and new i fall within the same group wrt the hash.
+ // If they do, we don't need to move the object as it falls already in the
+ // best probe we can.
+ const size_t probe_offset = probe(common, hash).offset();
+ const auto probe_index = [probe_offset, capacity](size_t pos) {
+ return ((pos - probe_offset) & capacity) / Group::kWidth;
+ };
+
+ // Element doesn't move.
+ if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
+ SetCtrl(common, i, H2(hash), slot_size);
+ continue;
+ }
+
+ void* new_slot_ptr = SlotAddress(slot_array, new_i, slot_size);
+ if (IsEmpty(ctrl[new_i])) {
+ // Transfer element to the empty spot.
+ // SetCtrl poisons/unpoisons the slots so we have to call it at the
+ // right time.
+ SetCtrl(common, new_i, H2(hash), slot_size);
+ (*transfer)(set, new_slot_ptr, slot_ptr);
+ SetCtrl(common, i, ctrl_t::kEmpty, slot_size);
+ } else {
+ assert(IsDeleted(ctrl[new_i]));
+ SetCtrl(common, new_i, H2(hash), slot_size);
+ // Until we are done rehashing, DELETED marks previously FULL slots.
+
+ // Swap i and new_i elements.
+ (*transfer)(set, tmp_space, new_slot_ptr);
+ (*transfer)(set, new_slot_ptr, slot_ptr);
+ (*transfer)(set, slot_ptr, tmp_space);
+
+ // repeat the processing of the ith slot
+ --i;
+ slot_ptr = PrevSlot(slot_ptr, slot_size);
+ }
+ }
+ ResetGrowthLeft(common);
+ common.infoz().RecordRehash(total_probe_length);
+}
+
+void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size) {
+ assert(IsFull(*it) && "erasing a dangling iterator");
+ --c.size_;
+ const auto index = static_cast<size_t>(it - c.control_);
+ const size_t index_before = (index - Group::kWidth) & c.capacity_;
+ const auto empty_after = Group(it).MaskEmpty();
+ const auto empty_before = Group(c.control_ + index_before).MaskEmpty();
+
+ // We count how many consecutive non empties we have to the right and to the
+ // left of `it`. If the sum is >= kWidth then there is at least one probe
+ // window that might have seen a full group.
+ bool was_never_full = empty_before && empty_after &&
+ static_cast<size_t>(empty_after.TrailingZeros()) +
+ empty_before.LeadingZeros() <
+ Group::kWidth;
+
+ SetCtrl(c, index, was_never_full ? ctrl_t::kEmpty : ctrl_t::kDeleted,
+ slot_size);
+ c.growth_left() += (was_never_full ? 1 : 0);
+ c.infoz().RecordErase();
+}
+
+void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
+ bool reuse) {
+ c.size_ = 0;
+ if (reuse) {
+ ResetCtrl(c, policy.slot_size);
+ c.infoz().RecordStorageChanged(0, c.capacity_);
+ } else {
+ void* set = &c;
+ (*policy.dealloc)(set, policy, c.control_, c.slots_, c.capacity_);
+ c.control_ = EmptyGroup();
+ c.set_generation_ptr(EmptyGeneration());
+ c.slots_ = nullptr;
+ c.capacity_ = 0;
+ c.growth_left() = 0;
+ c.infoz().RecordClearedReservation();
+ assert(c.size_ == 0);
+ c.infoz().RecordStorageChanged(0, 0);
+ }
+}
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h
index ea912f8305..61ef196d47 100644
--- a/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -186,6 +186,7 @@
#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
#include "absl/base/internal/prefetch.h"
+#include "absl/base/internal/raw_logging.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/container/internal/common.h"
@@ -219,6 +220,29 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
+#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
+#error ABSL_SWISSTABLE_ENABLE_GENERATIONS cannot be directly set
+#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_MEMORY_SANITIZER)
+// When compiled in sanitizer mode, we add generation integers to the backing
+// array and iterators. In the backing array, we store the generation between
+// the control bytes and the slots. When iterators are dereferenced, we assert
+// that the container has not been mutated in a way that could cause iterator
+// invalidation since the iterator was initialized.
+#define ABSL_SWISSTABLE_ENABLE_GENERATIONS
+#endif
+
+// We use uint8_t so we don't need to worry about padding.
+using GenerationType = uint8_t;
+
+#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
+constexpr bool SwisstableGenerationsEnabled() { return true; }
+constexpr size_t NumGenerationBytes() { return sizeof(GenerationType); }
+#else
+constexpr bool SwisstableGenerationsEnabled() { return false; }
+constexpr size_t NumGenerationBytes() { return 0; }
+#endif
+
template <typename AllocType>
void SwapAlloc(AllocType& lhs, AllocType& rhs,
std::true_type /* propagate_on_container_swap */) {
@@ -451,7 +475,7 @@ static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
"ctrl_t::kDeleted must be -2 to make the implementation of "
"ConvertSpecialToEmptyAndFullToDeleted efficient");
-ABSL_DLL extern const ctrl_t kEmptyGroup[16];
+ABSL_DLL extern const ctrl_t kEmptyGroup[17];
// Returns a pointer to a control byte group that can be used by empty tables.
inline ctrl_t* EmptyGroup() {
@@ -460,6 +484,12 @@ inline ctrl_t* EmptyGroup() {
return const_cast<ctrl_t*>(kEmptyGroup);
}
+// Returns a pointer to the generation byte at the end of the empty group, if it
+// exists.
+inline GenerationType* EmptyGeneration() {
+ return reinterpret_cast<GenerationType*>(EmptyGroup() + 16);
+}
+
// Mixes a randomly generated per-process seed with `hash` and `ctrl` to
// randomize insertion order within groups.
bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl);
@@ -545,7 +575,7 @@ struct GroupSse2Impl {
// Returns a bitmask representing the positions of slots that match hash.
BitMask<uint32_t, kWidth> Match(h2_t hash) const {
- auto match = _mm_set1_epi8(hash);
+ auto match = _mm_set1_epi8(static_cast<char>(hash));
return BitMask<uint32_t, kWidth>(
static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
}
@@ -557,7 +587,7 @@ struct GroupSse2Impl {
return NonIterableBitMask<uint32_t, kWidth>(
static_cast<uint32_t>(_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl))));
#else
- auto match = _mm_set1_epi8(static_cast<h2_t>(ctrl_t::kEmpty));
+ auto match = _mm_set1_epi8(static_cast<char>(ctrl_t::kEmpty));
return NonIterableBitMask<uint32_t, kWidth>(
static_cast<uint32_t>(_mm_movemask_epi8(_mm_cmpeq_epi8(match, ctrl))));
#endif
@@ -565,14 +595,14 @@ struct GroupSse2Impl {
// Returns a bitmask representing the positions of empty or deleted slots.
NonIterableBitMask<uint32_t, kWidth> MaskEmptyOrDeleted() const {
- auto special = _mm_set1_epi8(static_cast<uint8_t>(ctrl_t::kSentinel));
+ auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
return NonIterableBitMask<uint32_t, kWidth>(static_cast<uint32_t>(
_mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl))));
}
// Returns the number of trailing empty or deleted elements in the group.
uint32_t CountLeadingEmptyOrDeleted() const {
- auto special = _mm_set1_epi8(static_cast<uint8_t>(ctrl_t::kSentinel));
+ auto special = _mm_set1_epi8(static_cast<char>(ctrl_t::kSentinel));
return TrailingZeros(static_cast<uint32_t>(
_mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
}
@@ -612,9 +642,9 @@ struct GroupAArch64Impl {
NonIterableBitMask<uint64_t, kWidth, 3> MaskEmpty() const {
uint64_t mask =
- vget_lane_u64(vreinterpret_u64_u8(
- vceq_s8(vdup_n_s8(static_cast<h2_t>(ctrl_t::kEmpty)),
- vreinterpret_s8_u8(ctrl))),
+ vget_lane_u64(vreinterpret_u64_u8(vceq_s8(
+ vdup_n_s8(static_cast<int8_t>(ctrl_t::kEmpty)),
+ vreinterpret_s8_u8(ctrl))),
0);
return NonIterableBitMask<uint64_t, kWidth, 3>(mask);
}
@@ -629,13 +659,16 @@ struct GroupAArch64Impl {
}
uint32_t CountLeadingEmptyOrDeleted() const {
- uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(ctrl), 0);
- // ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
- // kDeleted. We lower all other bits and count number of trailing zeros.
+ uint64_t mask =
+ vget_lane_u64(vreinterpret_u64_u8(vcle_s8(
+ vdup_n_s8(static_cast<int8_t>(ctrl_t::kSentinel)),
+ vreinterpret_s8_u8(ctrl))),
+ 0);
+ // Similar to MaskEmptyorDeleted() but we invert the logic to invert the
+ // produced bitfield. We then count number of trailing zeros.
// Clang and GCC optimize countr_zero to rbit+clz without any check for 0,
// so we should be fine.
- constexpr uint64_t bits = 0x0101010101010101ULL;
- return countr_zero((mask | ~(mask >> 7)) & bits) >> 3;
+ return static_cast<uint32_t>(countr_zero(mask)) >> 3;
}
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
@@ -693,7 +726,8 @@ struct GroupPortableImpl {
// ctrl | ~(ctrl >> 7) will have the lowest bit set to zero for kEmpty and
// kDeleted. We lower all other bits and count number of trailing zeros.
constexpr uint64_t bits = 0x0101010101010101ULL;
- return countr_zero((ctrl | ~(ctrl >> 7)) & bits) >> 3;
+ return static_cast<uint32_t>(countr_zero((ctrl | ~(ctrl >> 7)) & bits) >>
+ 3);
}
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
@@ -715,6 +749,192 @@ using Group = GroupAArch64Impl;
using Group = GroupPortableImpl;
#endif
+class CommonFieldsGenerationInfoEnabled {
+ // A sentinel value for reserved_growth_ indicating that we just ran out of
+ // reserved growth on the last insertion. When reserve is called and then
+ // insertions take place, reserved_growth_'s state machine is N, ..., 1,
+ // kReservedGrowthJustRanOut, 0.
+ static constexpr size_t kReservedGrowthJustRanOut =
+ (std::numeric_limits<size_t>::max)();
+
+ public:
+ CommonFieldsGenerationInfoEnabled() = default;
+ CommonFieldsGenerationInfoEnabled(CommonFieldsGenerationInfoEnabled&& that)
+ : reserved_growth_(that.reserved_growth_), generation_(that.generation_) {
+ that.reserved_growth_ = 0;
+ that.generation_ = EmptyGeneration();
+ }
+ CommonFieldsGenerationInfoEnabled& operator=(
+ CommonFieldsGenerationInfoEnabled&&) = default;
+
+ // Whether we should rehash on insert in order to detect bugs of using invalid
+ // references. We rehash on the first insertion after reserved_growth_ reaches
+ // 0 after a call to reserve.
+ // TODO(b/254649633): we could potentially do a rehash with low probability
+ // whenever reserved_growth_ is zero.
+ bool should_rehash_for_bug_detection_on_insert() const {
+ return reserved_growth_ == kReservedGrowthJustRanOut;
+ }
+ void maybe_increment_generation_on_insert() {
+ if (reserved_growth_ == kReservedGrowthJustRanOut) reserved_growth_ = 0;
+
+ if (reserved_growth_ > 0) {
+ if (--reserved_growth_ == 0) reserved_growth_ = kReservedGrowthJustRanOut;
+ } else {
+ ++*generation_;
+ }
+ }
+ void reset_reserved_growth(size_t reservation, size_t size) {
+ reserved_growth_ = reservation - size;
+ }
+ size_t reserved_growth() const { return reserved_growth_; }
+ void set_reserved_growth(size_t r) { reserved_growth_ = r; }
+ GenerationType generation() const { return *generation_; }
+ void set_generation(GenerationType g) { *generation_ = g; }
+ GenerationType* generation_ptr() const { return generation_; }
+ void set_generation_ptr(GenerationType* g) { generation_ = g; }
+
+ private:
+ // The number of insertions remaining that are guaranteed to not rehash due to
+ // a prior call to reserve. Note: we store reserved growth rather than
+ // reservation size because calls to erase() decrease size_ but don't decrease
+ // reserved growth.
+ size_t reserved_growth_ = 0;
+ // Pointer to the generation counter, which is used to validate iterators and
+ // is stored in the backing array between the control bytes and the slots.
+ // Note that we can't store the generation inside the container itself and
+ // keep a pointer to the container in the iterators because iterators must
+ // remain valid when the container is moved.
+ // Note: we could derive this pointer from the control pointer, but it makes
+ // the code more complicated, and there's a benefit in having the sizes of
+ // raw_hash_set in sanitizer mode and non-sanitizer mode a bit more different,
+ // which is that tests are less likely to rely on the size remaining the same.
+ GenerationType* generation_ = EmptyGeneration();
+};
+
+class CommonFieldsGenerationInfoDisabled {
+ public:
+ CommonFieldsGenerationInfoDisabled() = default;
+ CommonFieldsGenerationInfoDisabled(CommonFieldsGenerationInfoDisabled&&) =
+ default;
+ CommonFieldsGenerationInfoDisabled& operator=(
+ CommonFieldsGenerationInfoDisabled&&) = default;
+
+ bool should_rehash_for_bug_detection_on_insert() const { return false; }
+ void maybe_increment_generation_on_insert() {}
+ void reset_reserved_growth(size_t, size_t) {}
+ size_t reserved_growth() const { return 0; }
+ void set_reserved_growth(size_t) {}
+ GenerationType generation() const { return 0; }
+ void set_generation(GenerationType) {}
+ GenerationType* generation_ptr() const { return nullptr; }
+ void set_generation_ptr(GenerationType*) {}
+};
+
+class HashSetIteratorGenerationInfoEnabled {
+ public:
+ HashSetIteratorGenerationInfoEnabled() = default;
+ explicit HashSetIteratorGenerationInfoEnabled(
+ const GenerationType* generation_ptr)
+ : generation_ptr_(generation_ptr), generation_(*generation_ptr) {}
+
+ GenerationType generation() const { return generation_; }
+ void reset_generation() { generation_ = *generation_ptr_; }
+ const GenerationType* generation_ptr() const { return generation_ptr_; }
+ void set_generation_ptr(const GenerationType* ptr) { generation_ptr_ = ptr; }
+
+ private:
+ const GenerationType* generation_ptr_ = EmptyGeneration();
+ GenerationType generation_ = *generation_ptr_;
+};
+
+class HashSetIteratorGenerationInfoDisabled {
+ public:
+ HashSetIteratorGenerationInfoDisabled() = default;
+ explicit HashSetIteratorGenerationInfoDisabled(const GenerationType*) {}
+
+ GenerationType generation() const { return 0; }
+ void reset_generation() {}
+ const GenerationType* generation_ptr() const { return nullptr; }
+ void set_generation_ptr(const GenerationType*) {}
+};
+
+#ifdef ABSL_SWISSTABLE_ENABLE_GENERATIONS
+using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoEnabled;
+using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoEnabled;
+#else
+using CommonFieldsGenerationInfo = CommonFieldsGenerationInfoDisabled;
+using HashSetIteratorGenerationInfo = HashSetIteratorGenerationInfoDisabled;
+#endif
+
+// CommonFields hold the fields in raw_hash_set that do not depend
+// on template parameters. This allows us to conveniently pass all
+// of this state to helper functions as a single argument.
+class CommonFields : public CommonFieldsGenerationInfo {
+ public:
+ CommonFields() = default;
+
+ // Not copyable
+ CommonFields(const CommonFields&) = delete;
+ CommonFields& operator=(const CommonFields&) = delete;
+
+ // Movable
+ CommonFields(CommonFields&& that)
+ : CommonFieldsGenerationInfo(
+ std::move(static_cast<CommonFieldsGenerationInfo&&>(that))),
+ // Explicitly copying fields into "this" and then resetting "that"
+ // fields generates less code then calling absl::exchange per field.
+ control_(that.control_),
+ slots_(that.slots_),
+ size_(that.size_),
+ capacity_(that.capacity_),
+ compressed_tuple_(that.growth_left(), std::move(that.infoz())) {
+ that.control_ = EmptyGroup();
+ that.slots_ = nullptr;
+ that.size_ = 0;
+ that.capacity_ = 0;
+ that.growth_left() = 0;
+ }
+ CommonFields& operator=(CommonFields&&) = default;
+
+ // The number of slots we can still fill without needing to rehash.
+ size_t& growth_left() { return compressed_tuple_.template get<0>(); }
+
+ HashtablezInfoHandle& infoz() { return compressed_tuple_.template get<1>(); }
+ const HashtablezInfoHandle& infoz() const {
+ return compressed_tuple_.template get<1>();
+ }
+
+ void reset_reserved_growth(size_t reservation) {
+ CommonFieldsGenerationInfo::reset_reserved_growth(reservation, size_);
+ }
+
+ // TODO(b/259599413): Investigate removing some of these fields:
+ // - control/slots can be derived from each other
+ // - size can be moved into the slot array
+
+ // The control bytes (and, also, a pointer to the base of the backing array).
+ //
+ // This contains `capacity + 1 + NumClonedBytes()` entries, even
+ // when the table is empty (hence EmptyGroup).
+ ctrl_t* control_ = EmptyGroup();
+
+ // The beginning of the slots, located at `SlotOffset()` bytes after
+ // `control`. May be null for empty tables.
+ void* slots_ = nullptr;
+
+ // The number of filled slots.
+ size_t size_ = 0;
+
+ // The total number of available slots.
+ size_t capacity_ = 0;
+
+ // Bundle together growth_left and HashtablezInfoHandle to ensure EBO for
+ // HashtablezInfoHandle when sampling is turned off.
+ absl::container_internal::CompressedTuple<size_t, HashtablezInfoHandle>
+ compressed_tuple_{0u, HashtablezInfoHandle{}};
+};
+
// Returns he number of "cloned control bytes".
//
// This is the number of control bytes that are present both at the beginning
@@ -730,6 +950,12 @@ class raw_hash_set;
// A valid capacity is a non-zero integer `2^m - 1`.
inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
+// Returns the next valid capacity after `n`.
+inline size_t NextCapacity(size_t n) {
+ assert(IsValidCapacity(n) || n == 0);
+ return n * 2 + 1;
+}
+
// Applies the following mapping to every byte in the control array:
// * kDeleted -> kEmpty
// * kEmpty -> kEmpty
@@ -795,15 +1021,69 @@ size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
return 0;
}
-#define ABSL_INTERNAL_ASSERT_IS_FULL(ctrl, msg) \
- ABSL_HARDENING_ASSERT((ctrl != nullptr && IsFull(*ctrl)) && msg)
+#define ABSL_INTERNAL_ASSERT_IS_FULL(ctrl, generation, generation_ptr, \
+ operation) \
+ do { \
+ ABSL_HARDENING_ASSERT( \
+ (ctrl != nullptr) && operation \
+ " called on invalid iterator. The iterator might be an end() " \
+ "iterator or may have been default constructed."); \
+ if (SwisstableGenerationsEnabled() && generation != *generation_ptr) \
+ ABSL_INTERNAL_LOG(FATAL, operation \
+ " called on invalidated iterator. The table could " \
+ "have rehashed since this iterator was initialized."); \
+ ABSL_HARDENING_ASSERT( \
+ (IsFull(*ctrl)) && operation \
+ " called on invalid iterator. The element might have been erased or " \
+ "the table might have rehashed."); \
+ } while (0)
+
+// Note that for comparisons, null/end iterators are valid.
+inline void AssertIsValidForComparison(const ctrl_t* ctrl,
+ GenerationType generation,
+ const GenerationType* generation_ptr) {
+ ABSL_HARDENING_ASSERT((ctrl == nullptr || IsFull(*ctrl)) &&
+ "Invalid iterator comparison. The element might have "
+ "been erased or the table might have rehashed.");
+ if (SwisstableGenerationsEnabled() && generation != *generation_ptr) {
+ ABSL_INTERNAL_LOG(FATAL,
+ "Invalid iterator comparison. The table could have "
+ "rehashed since this iterator was initialized.");
+ }
+}
+
+// If the two iterators come from the same container, then their pointers will
+// interleave such that ctrl_a <= ctrl_b < slot_a <= slot_b or vice/versa.
+// Note: we take slots by reference so that it's not UB if they're uninitialized
+// as long as we don't read them (when ctrl is null).
+inline bool AreItersFromSameContainer(const ctrl_t* ctrl_a,
+ const ctrl_t* ctrl_b,
+ const void* const& slot_a,
+ const void* const& slot_b) {
+ // If either control byte is null, then we can't tell.
+ if (ctrl_a == nullptr || ctrl_b == nullptr) return true;
+ const void* low_slot = slot_a;
+ const void* hi_slot = slot_b;
+ if (ctrl_a > ctrl_b) {
+ std::swap(ctrl_a, ctrl_b);
+ std::swap(low_slot, hi_slot);
+ }
+ return ctrl_b < low_slot && low_slot <= hi_slot;
+}
-inline void AssertIsValid(ctrl_t* ctrl) {
+// Asserts that two iterators come from the same container.
+// Note: we take slots by reference so that it's not UB if they're uninitialized
+// as long as we don't read them (when ctrl is null).
+// TODO(b/254649633): when generations are enabled, we can detect more cases of
+// different containers by comparing the pointers to the generations - this
+// can cover cases of end iterators that we would otherwise miss.
+inline void AssertSameContainer(const ctrl_t* ctrl_a, const ctrl_t* ctrl_b,
+ const void* const& slot_a,
+ const void* const& slot_b) {
ABSL_HARDENING_ASSERT(
- (ctrl == nullptr || IsFull(*ctrl)) &&
- "Invalid operation on iterator. The element might have "
- "been erased, the table might have rehashed, or this may "
- "be an end() iterator.");
+ AreItersFromSameContainer(ctrl_a, ctrl_b, slot_a, slot_b) &&
+ "Invalid iterator comparison. The iterators may be from different "
+ "containers or the container might have rehashed.");
}
struct FindInfo {
@@ -825,9 +1105,10 @@ struct FindInfo {
// `ShouldInsertBackwards()` for small tables.
inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
-// Begins a probing operation on `ctrl`, using `hash`.
-inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, size_t hash,
- size_t capacity) {
+// Begins a probing operation on `common.control`, using `hash`.
+inline probe_seq<Group::kWidth> probe(const CommonFields& common, size_t hash) {
+ const ctrl_t* ctrl = common.control_;
+ const size_t capacity = common.capacity_;
return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
}
@@ -839,9 +1120,9 @@ inline probe_seq<Group::kWidth> probe(const ctrl_t* ctrl, size_t hash,
// NOTE: this function must work with tables having both empty and deleted
// slots in the same group. Such tables appear during `erase()`.
template <typename = void>
-inline FindInfo find_first_non_full(const ctrl_t* ctrl, size_t hash,
- size_t capacity) {
- auto seq = probe(ctrl, hash, capacity);
+inline FindInfo find_first_non_full(const CommonFields& common, size_t hash) {
+ auto seq = probe(common, hash);
+ const ctrl_t* ctrl = common.control_;
while (true) {
Group g{ctrl + seq.offset()};
auto mask = g.MaskEmptyOrDeleted();
@@ -851,55 +1132,75 @@ inline FindInfo find_first_non_full(const ctrl_t* ctrl, size_t hash,
// In debug build we will randomly insert in either the front or back of
// the group.
// TODO(kfm,sbenza): revisit after we do unconditional mixing
- if (!is_small(capacity) && ShouldInsertBackwards(hash, ctrl)) {
+ if (!is_small(common.capacity_) && ShouldInsertBackwards(hash, ctrl)) {
return {seq.offset(mask.HighestBitSet()), seq.index()};
}
#endif
return {seq.offset(mask.LowestBitSet()), seq.index()};
}
seq.next();
- assert(seq.index() <= capacity && "full table!");
+ assert(seq.index() <= common.capacity_ && "full table!");
}
}
// Extern template for inline function keep possibility of inlining.
// When compiler decided to not inline, no symbols will be added to the
// corresponding translation unit.
-extern template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
+extern template FindInfo find_first_non_full(const CommonFields&, size_t);
+
+// Non-inlined version of find_first_non_full for use in less
+// performance critical routines.
+FindInfo find_first_non_full_outofline(const CommonFields&, size_t);
+
+inline void ResetGrowthLeft(CommonFields& common) {
+ common.growth_left() = CapacityToGrowth(common.capacity_) - common.size_;
+}
// Sets `ctrl` to `{kEmpty, kSentinel, ..., kEmpty}`, marking the entire
// array as marked as empty.
-inline void ResetCtrl(size_t capacity, ctrl_t* ctrl, const void* slot,
- size_t slot_size) {
+inline void ResetCtrl(CommonFields& common, size_t slot_size) {
+ const size_t capacity = common.capacity_;
+ ctrl_t* ctrl = common.control_;
std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
capacity + 1 + NumClonedBytes());
ctrl[capacity] = ctrl_t::kSentinel;
- SanitizerPoisonMemoryRegion(slot, slot_size * capacity);
+ SanitizerPoisonMemoryRegion(common.slots_, slot_size * capacity);
+ ResetGrowthLeft(common);
}
// Sets `ctrl[i]` to `h`.
//
// Unlike setting it directly, this function will perform bounds checks and
// mirror the value to the cloned tail if necessary.
-inline void SetCtrl(size_t i, ctrl_t h, size_t capacity, ctrl_t* ctrl,
- const void* slot, size_t slot_size) {
+inline void SetCtrl(const CommonFields& common, size_t i, ctrl_t h,
+ size_t slot_size) {
+ const size_t capacity = common.capacity_;
assert(i < capacity);
- auto* slot_i = static_cast<const char*>(slot) + i * slot_size;
+ auto* slot_i = static_cast<const char*>(common.slots_) + i * slot_size;
if (IsFull(h)) {
SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
} else {
SanitizerPoisonMemoryRegion(slot_i, slot_size);
}
+ ctrl_t* ctrl = common.control_;
ctrl[i] = h;
ctrl[((i - NumClonedBytes()) & capacity) + (NumClonedBytes() & capacity)] = h;
}
// Overload for setting to an occupied `h2_t` rather than a special `ctrl_t`.
-inline void SetCtrl(size_t i, h2_t h, size_t capacity, ctrl_t* ctrl,
- const void* slot, size_t slot_size) {
- SetCtrl(i, static_cast<ctrl_t>(h), capacity, ctrl, slot, slot_size);
+inline void SetCtrl(const CommonFields& common, size_t i, h2_t h,
+ size_t slot_size) {
+ SetCtrl(common, i, static_cast<ctrl_t>(h), slot_size);
+}
+
+// Given the capacity of a table, computes the offset (from the start of the
+// backing allocation) of the generation counter (if it exists).
+inline size_t GenerationOffset(size_t capacity) {
+ assert(IsValidCapacity(capacity));
+ const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
+ return num_control_bytes;
}
// Given the capacity of a table, computes the offset (from the start of the
@@ -907,7 +1208,8 @@ inline void SetCtrl(size_t i, h2_t h, size_t capacity, ctrl_t* ctrl,
inline size_t SlotOffset(size_t capacity, size_t slot_align) {
assert(IsValidCapacity(capacity));
const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
- return (num_control_bytes + slot_align - 1) & (~slot_align + 1);
+ return (num_control_bytes + NumGenerationBytes() + slot_align - 1) &
+ (~slot_align + 1);
}
// Given the capacity of a table, computes the total size of the backing
@@ -916,6 +1218,91 @@ inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) {
return SlotOffset(capacity, slot_align) + capacity * slot_size;
}
+template <typename Alloc, size_t SizeOfSlot, size_t AlignOfSlot>
+ABSL_ATTRIBUTE_NOINLINE void InitializeSlots(CommonFields& c, Alloc alloc) {
+ assert(c.capacity_);
+ // Folks with custom allocators often make unwarranted assumptions about the
+ // behavior of their classes vis-a-vis trivial destructability and what
+ // calls they will or won't make. Avoid sampling for people with custom
+ // allocators to get us out of this mess. This is not a hard guarantee but
+ // a workaround while we plan the exact guarantee we want to provide.
+ const size_t sample_size =
+ (std::is_same<Alloc, std::allocator<char>>::value && c.slots_ == nullptr)
+ ? SizeOfSlot
+ : 0;
+
+ const size_t cap = c.capacity_;
+ char* mem = static_cast<char*>(
+ Allocate<AlignOfSlot>(&alloc, AllocSize(cap, SizeOfSlot, AlignOfSlot)));
+ const GenerationType old_generation = c.generation();
+ c.set_generation_ptr(
+ reinterpret_cast<GenerationType*>(mem + GenerationOffset(cap)));
+ c.set_generation(old_generation + 1);
+ c.control_ = reinterpret_cast<ctrl_t*>(mem);
+ c.slots_ = mem + SlotOffset(cap, AlignOfSlot);
+ ResetCtrl(c, SizeOfSlot);
+ if (sample_size) {
+ c.infoz() = Sample(sample_size);
+ }
+ c.infoz().RecordStorageChanged(c.size_, cap);
+}
+
+// PolicyFunctions bundles together some information for a particular
+// raw_hash_set<T, ...> instantiation. This information is passed to
+// type-erased functions that want to do small amounts of type-specific
+// work.
+struct PolicyFunctions {
+ size_t slot_size;
+
+ // Return the hash of the pointed-to slot.
+ size_t (*hash_slot)(void* set, void* slot);
+
+ // Transfer the contents of src_slot to dst_slot.
+ void (*transfer)(void* set, void* dst_slot, void* src_slot);
+
+ // Deallocate the specified backing store which is sized for n slots.
+ void (*dealloc)(void* set, const PolicyFunctions& policy, ctrl_t* ctrl,
+ void* slot_array, size_t n);
+};
+
+// ClearBackingArray clears the backing array, either modifying it in place,
+// or creating a new one based on the value of "reuse".
+// REQUIRES: c.capacity > 0
+void ClearBackingArray(CommonFields& c, const PolicyFunctions& policy,
+ bool reuse);
+
+// Type-erased version of raw_hash_set::erase_meta_only.
+void EraseMetaOnly(CommonFields& c, ctrl_t* it, size_t slot_size);
+
+// Function to place in PolicyFunctions::dealloc for raw_hash_sets
+// that are using std::allocator. This allows us to share the same
+// function body for raw_hash_set instantiations that have the
+// same slot alignment.
+template <size_t AlignOfSlot>
+ABSL_ATTRIBUTE_NOINLINE void DeallocateStandard(void*,
+ const PolicyFunctions& policy,
+ ctrl_t* ctrl, void* slot_array,
+ size_t n) {
+ // Unpoison before returning the memory to the allocator.
+ SanitizerUnpoisonMemoryRegion(slot_array, policy.slot_size * n);
+
+ std::allocator<char> alloc;
+ Deallocate<AlignOfSlot>(&alloc, ctrl,
+ AllocSize(n, policy.slot_size, AlignOfSlot));
+}
+
+// For trivially relocatable types we use memcpy directly. This allows us to
+// share the same function body for raw_hash_set instantiations that have the
+// same slot size as long as they are relocatable.
+template <size_t SizeOfSlot>
+ABSL_ATTRIBUTE_NOINLINE void TransferRelocatable(void*, void* dst, void* src) {
+ memcpy(dst, src, SizeOfSlot);
+}
+
+// Type-erased version of raw_hash_set::drop_deletes_without_resize.
+void DropDeletesWithoutResize(CommonFields& common,
+ const PolicyFunctions& policy, void* tmp_space);
+
// A SwissTable.
//
// Policy: a policy defines how to perform different operations on
@@ -1016,7 +1403,7 @@ class raw_hash_set {
static_assert(std::is_same<const_pointer, const value_type*>::value,
"Allocators with custom pointer types are not supported");
- class iterator {
+ class iterator : private HashSetIteratorGenerationInfo {
friend class raw_hash_set;
public:
@@ -1032,22 +1419,22 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator.
reference operator*() const {
- ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
- "operator*() called on invalid iterator.");
+ ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_, generation(), generation_ptr(),
+ "operator*()");
return PolicyTraits::element(slot_);
}
// PRECONDITION: not an end() iterator.
pointer operator->() const {
- ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
- "operator-> called on invalid iterator.");
+ ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_, generation(), generation_ptr(),
+ "operator->");
return &operator*();
}
// PRECONDITION: not an end() iterator.
iterator& operator++() {
- ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_,
- "operator++ called on invalid iterator.");
+ ABSL_INTERNAL_ASSERT_IS_FULL(ctrl_, generation(), generation_ptr(),
+ "operator++");
++ctrl_;
++slot_;
skip_empty_or_deleted();
@@ -1061,8 +1448,9 @@ class raw_hash_set {
}
friend bool operator==(const iterator& a, const iterator& b) {
- AssertIsValid(a.ctrl_);
- AssertIsValid(b.ctrl_);
+ AssertSameContainer(a.ctrl_, b.ctrl_, a.slot_, b.slot_);
+ AssertIsValidForComparison(a.ctrl_, a.generation(), a.generation_ptr());
+ AssertIsValidForComparison(b.ctrl_, b.generation(), b.generation_ptr());
return a.ctrl_ == b.ctrl_;
}
friend bool operator!=(const iterator& a, const iterator& b) {
@@ -1070,16 +1458,23 @@ class raw_hash_set {
}
private:
- iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {
+ iterator(ctrl_t* ctrl, slot_type* slot,
+ const GenerationType* generation_ptr)
+ : HashSetIteratorGenerationInfo(generation_ptr),
+ ctrl_(ctrl),
+ slot_(slot) {
// This assumption helps the compiler know that any non-end iterator is
// not equal to any end iterator.
ABSL_ASSUME(ctrl != nullptr);
}
+ // For end() iterators.
+ explicit iterator(const GenerationType* generation_ptr)
+ : HashSetIteratorGenerationInfo(generation_ptr) {}
// Fixes up `ctrl_` to point to a full by advancing it and `slot_` until
// they reach one.
//
- // If a sentinel is reached, we null both of them out instead.
+ // If a sentinel is reached, we null `ctrl_` out instead.
void skip_empty_or_deleted() {
while (IsEmptyOrDeleted(*ctrl_)) {
uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
@@ -1107,9 +1502,9 @@ class raw_hash_set {
using pointer = typename raw_hash_set::const_pointer;
using difference_type = typename raw_hash_set::difference_type;
- const_iterator() {}
+ const_iterator() = default;
// Implicit construction from iterator.
- const_iterator(iterator i) : inner_(std::move(i)) {}
+ const_iterator(iterator i) : inner_(std::move(i)) {} // NOLINT
reference operator*() const { return *inner_; }
pointer operator->() const { return inner_.operator->(); }
@@ -1128,8 +1523,10 @@ class raw_hash_set {
}
private:
- const_iterator(const ctrl_t* ctrl, const slot_type* slot)
- : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot)) {}
+ const_iterator(const ctrl_t* ctrl, const slot_type* slot,
+ const GenerationType* gen)
+ : inner_(const_cast<ctrl_t*>(ctrl), const_cast<slot_type*>(slot), gen) {
+ }
iterator inner_;
};
@@ -1137,18 +1534,20 @@ class raw_hash_set {
using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
using insert_return_type = InsertReturnType<iterator, node_type>;
+ // Note: can't use `= default` due to non-default noexcept (causes
+ // problems for some compilers). NOLINTNEXTLINE
raw_hash_set() noexcept(
std::is_nothrow_default_constructible<hasher>::value&&
std::is_nothrow_default_constructible<key_equal>::value&&
std::is_nothrow_default_constructible<allocator_type>::value) {}
- explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(),
- const key_equal& eq = key_equal(),
- const allocator_type& alloc = allocator_type())
- : ctrl_(EmptyGroup()),
- settings_(0, HashtablezInfoHandle(), hash, eq, alloc) {
+ ABSL_ATTRIBUTE_NOINLINE explicit raw_hash_set(
+ size_t bucket_count, const hasher& hash = hasher(),
+ const key_equal& eq = key_equal(),
+ const allocator_type& alloc = allocator_type())
+ : settings_(CommonFields{}, hash, eq, alloc) {
if (bucket_count) {
- capacity_ = NormalizeCapacity(bucket_count);
+ common().capacity_ = NormalizeCapacity(bucket_count);
initialize_slots();
}
}
@@ -1255,45 +1654,30 @@ class raw_hash_set {
// than a full `insert`.
for (const auto& v : that) {
const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
- auto target = find_first_non_full(ctrl_, hash, capacity_);
- SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
- sizeof(slot_type));
+ auto target = find_first_non_full_outofline(common(), hash);
+ SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
emplace_at(target.offset, v);
+ common().maybe_increment_generation_on_insert();
infoz().RecordInsert(hash, target.probe_length);
}
- size_ = that.size();
+ common().size_ = that.size();
growth_left() -= that.size();
}
- raw_hash_set(raw_hash_set&& that) noexcept(
+ ABSL_ATTRIBUTE_NOINLINE raw_hash_set(raw_hash_set&& that) noexcept(
std::is_nothrow_copy_constructible<hasher>::value&&
std::is_nothrow_copy_constructible<key_equal>::value&&
std::is_nothrow_copy_constructible<allocator_type>::value)
- : ctrl_(absl::exchange(that.ctrl_, EmptyGroup())),
- slots_(absl::exchange(that.slots_, nullptr)),
- size_(absl::exchange(that.size_, 0)),
- capacity_(absl::exchange(that.capacity_, 0)),
- // Hash, equality and allocator are copied instead of moved because
- // `that` must be left valid. If Hash is std::function<Key>, moving it
- // would create a nullptr functor that cannot be called.
- settings_(absl::exchange(that.growth_left(), 0),
- absl::exchange(that.infoz(), HashtablezInfoHandle()),
+ : // Hash, equality and allocator are copied instead of moved because
+ // `that` must be left valid. If Hash is std::function<Key>, moving it
+ // would create a nullptr functor that cannot be called.
+ settings_(absl::exchange(that.common(), CommonFields{}),
that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
raw_hash_set(raw_hash_set&& that, const allocator_type& a)
- : ctrl_(EmptyGroup()),
- slots_(nullptr),
- size_(0),
- capacity_(0),
- settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(),
- a) {
+ : settings_(CommonFields{}, that.hash_ref(), that.eq_ref(), a) {
if (a == that.alloc_ref()) {
- std::swap(ctrl_, that.ctrl_);
- std::swap(slots_, that.slots_);
- std::swap(size_, that.size_);
- std::swap(capacity_, that.capacity_);
- std::swap(growth_left(), that.growth_left());
- std::swap(infoz(), that.infoz());
+ std::swap(common(), that.common());
} else {
reserve(that.size());
// Note: this will copy elements of dense_set and unordered_set instead of
@@ -1317,30 +1701,43 @@ class raw_hash_set {
std::is_nothrow_move_assignable<key_equal>::value) {
// TODO(sbenza): We should only use the operations from the noexcept clause
// to make sure we actually adhere to that contract.
+ // NOLINTNEXTLINE: not returning *this for performance.
return move_assign(
std::move(that),
typename AllocTraits::propagate_on_container_move_assignment());
}
- ~raw_hash_set() { destroy_slots(); }
+ ~raw_hash_set() {
+ const size_t cap = capacity();
+ if (!cap) return;
+ destroy_slots();
+
+ // Unpoison before returning the memory to the allocator.
+ SanitizerUnpoisonMemoryRegion(slot_array(), sizeof(slot_type) * cap);
+ Deallocate<alignof(slot_type)>(
+ &alloc_ref(), control(),
+ AllocSize(cap, sizeof(slot_type), alignof(slot_type)));
+
+ infoz().Unregister();
+ }
iterator begin() {
auto it = iterator_at(0);
it.skip_empty_or_deleted();
return it;
}
- iterator end() { return {}; }
+ iterator end() { return iterator(common().generation_ptr()); }
const_iterator begin() const {
return const_cast<raw_hash_set*>(this)->begin();
}
- const_iterator end() const { return {}; }
+ const_iterator end() const { return iterator(common().generation_ptr()); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
bool empty() const { return !size(); }
- size_t size() const { return size_; }
- size_t capacity() const { return capacity_; }
+ size_t size() const { return common().size_; }
+ size_t capacity() const { return common().capacity_; }
size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
ABSL_ATTRIBUTE_REINITIALIZES void clear() {
@@ -1351,22 +1748,26 @@ class raw_hash_set {
// compared to destruction of the elements of the container. So we pick the
// largest bucket_count() threshold for which iteration is still fast and
// past that we simply deallocate the array.
- if (capacity_ > 127) {
+ const size_t cap = capacity();
+ if (cap == 0) {
+ // Already guaranteed to be empty; so nothing to do.
+ } else {
destroy_slots();
+ ClearBackingArray(common(), GetPolicyFunctions(),
+ /*reuse=*/cap < 128);
+ }
+ common().set_reserved_growth(0);
+ }
- infoz().RecordClearedReservation();
- } else if (capacity_) {
- for (size_t i = 0; i != capacity_; ++i) {
- if (IsFull(ctrl_[i])) {
- PolicyTraits::destroy(&alloc_ref(), slots_ + i);
- }
+ inline void destroy_slots() {
+ const size_t cap = capacity();
+ const ctrl_t* ctrl = control();
+ slot_type* slot = slot_array();
+ for (size_t i = 0; i != cap; ++i) {
+ if (IsFull(ctrl[i])) {
+ PolicyTraits::destroy(&alloc_ref(), slot + i);
}
- size_ = 0;
- ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
- reset_growth_left();
}
- assert(empty());
- infoz().RecordStorageChanged(0, capacity_);
}
// This overload kicks in when the argument is an rvalue of insertable and
@@ -1554,7 +1955,7 @@ class raw_hash_set {
iterator lazy_emplace(const key_arg<K>& key, F&& f) {
auto res = find_or_prepare_insert(key);
if (res.second) {
- slot_type* slot = slots_ + res.first;
+ slot_type* slot = slot_array() + res.first;
std::forward<F>(f)(constructor(&alloc_ref(), &slot));
assert(!slot);
}
@@ -1596,8 +1997,8 @@ class raw_hash_set {
// This overload is necessary because otherwise erase<K>(const K&) would be
// a better match if non-const iterator is passed as an argument.
void erase(iterator it) {
- ABSL_INTERNAL_ASSERT_IS_FULL(it.ctrl_,
- "erase() called on invalid iterator.");
+ ABSL_INTERNAL_ASSERT_IS_FULL(it.ctrl_, it.generation(), it.generation_ptr(),
+ "erase()");
PolicyTraits::destroy(&alloc_ref(), it.slot_);
erase_meta_only(it);
}
@@ -1632,7 +2033,8 @@ class raw_hash_set {
node_type extract(const_iterator position) {
ABSL_INTERNAL_ASSERT_IS_FULL(position.inner_.ctrl_,
- "extract() called on invalid iterator.");
+ position.inner_.generation(),
+ position.inner_.generation_ptr(), "extract()");
auto node =
CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
erase_meta_only(position);
@@ -1652,24 +2054,18 @@ class raw_hash_set {
IsNoThrowSwappable<allocator_type>(
typename AllocTraits::propagate_on_container_swap{})) {
using std::swap;
- swap(ctrl_, that.ctrl_);
- swap(slots_, that.slots_);
- swap(size_, that.size_);
- swap(capacity_, that.capacity_);
- swap(growth_left(), that.growth_left());
+ swap(common(), that.common());
swap(hash_ref(), that.hash_ref());
swap(eq_ref(), that.eq_ref());
- swap(infoz(), that.infoz());
SwapAlloc(alloc_ref(), that.alloc_ref(),
typename AllocTraits::propagate_on_container_swap{});
}
void rehash(size_t n) {
- if (n == 0 && capacity_ == 0) return;
- if (n == 0 && size_ == 0) {
- destroy_slots();
- infoz().RecordStorageChanged(0, 0);
- infoz().RecordClearedReservation();
+ if (n == 0 && capacity() == 0) return;
+ if (n == 0 && size() == 0) {
+ ClearBackingArray(common(), GetPolicyFunctions(),
+ /*reuse=*/false);
return;
}
@@ -1677,7 +2073,7 @@ class raw_hash_set {
// power-of-2-minus-1, so bitor is good enough.
auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
// n == 0 unconditionally rehashes as per the standard.
- if (n == 0 || m > capacity_) {
+ if (n == 0 || m > capacity()) {
resize(m);
// This is after resize, to ensure that we have completed the allocation
@@ -1695,6 +2091,7 @@ class raw_hash_set {
// and have potentially sampled the hashtable.
infoz().RecordReservation(n);
}
+ common().reset_reserved_growth(n);
}
// Extension API: support for heterogeneous keys.
@@ -1722,9 +2119,9 @@ class raw_hash_set {
// Avoid probing if we won't be able to prefetch the addresses received.
#ifdef ABSL_INTERNAL_HAVE_PREFETCH
prefetch_heap_block();
- auto seq = probe(ctrl_, hash_ref()(key), capacity_);
- base_internal::PrefetchT0(ctrl_ + seq.offset());
- base_internal::PrefetchT0(slots_ + seq.offset());
+ auto seq = probe(common(), hash_ref()(key));
+ base_internal::PrefetchT0(control() + seq.offset());
+ base_internal::PrefetchT0(slot_array() + seq.offset());
#endif // ABSL_INTERNAL_HAVE_PREFETCH
}
@@ -1737,18 +2134,20 @@ class raw_hash_set {
// called heterogeneous key support.
template <class K = key_type>
iterator find(const key_arg<K>& key, size_t hash) {
- auto seq = probe(ctrl_, hash, capacity_);
+ auto seq = probe(common(), hash);
+ slot_type* slot_ptr = slot_array();
+ const ctrl_t* ctrl = control();
while (true) {
- Group g{ctrl_ + seq.offset()};
+ Group g{ctrl + seq.offset()};
for (uint32_t i : g.Match(H2(hash))) {
if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
EqualElement<K>{key, eq_ref()},
- PolicyTraits::element(slots_ + seq.offset(i)))))
+ PolicyTraits::element(slot_ptr + seq.offset(i)))))
return iterator_at(seq.offset(i));
}
if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return end();
seq.next();
- assert(seq.index() <= capacity_ && "full table!");
+ assert(seq.index() <= capacity() && "full table!");
}
}
template <class K = key_type>
@@ -1786,9 +2185,9 @@ class raw_hash_set {
return {it, it};
}
- size_t bucket_count() const { return capacity_; }
+ size_t bucket_count() const { return capacity(); }
float load_factor() const {
- return capacity_ ? static_cast<double>(size()) / capacity_ : 0.0;
+ return capacity() ? static_cast<double>(size()) / capacity() : 0.0;
}
float max_load_factor() const { return 1.0f; }
void max_load_factor(float) {
@@ -1875,7 +2274,8 @@ class raw_hash_set {
std::pair<iterator, bool> operator()(const K& key, Args&&...) && {
auto res = s.find_or_prepare_insert(key);
if (res.second) {
- PolicyTraits::transfer(&s.alloc_ref(), s.slots_ + res.first, &slot);
+ PolicyTraits::transfer(&s.alloc_ref(), s.slot_array() + res.first,
+ &slot);
} else if (do_destroy) {
PolicyTraits::destroy(&s.alloc_ref(), &slot);
}
@@ -1891,102 +2291,43 @@ class raw_hash_set {
// This merely updates the pertinent control byte. This can be used in
// conjunction with Policy::transfer to move the object to another place.
void erase_meta_only(const_iterator it) {
- assert(IsFull(*it.inner_.ctrl_) && "erasing a dangling iterator");
- --size_;
- const size_t index = static_cast<size_t>(it.inner_.ctrl_ - ctrl_);
- const size_t index_before = (index - Group::kWidth) & capacity_;
- const auto empty_after = Group(it.inner_.ctrl_).MaskEmpty();
- const auto empty_before = Group(ctrl_ + index_before).MaskEmpty();
-
- // We count how many consecutive non empties we have to the right and to the
- // left of `it`. If the sum is >= kWidth then there is at least one probe
- // window that might have seen a full group.
- bool was_never_full =
- empty_before && empty_after &&
- static_cast<size_t>(empty_after.TrailingZeros() +
- empty_before.LeadingZeros()) < Group::kWidth;
-
- SetCtrl(index, was_never_full ? ctrl_t::kEmpty : ctrl_t::kDeleted,
- capacity_, ctrl_, slots_, sizeof(slot_type));
- growth_left() += was_never_full;
- infoz().RecordErase();
+ EraseMetaOnly(common(), it.inner_.ctrl_, sizeof(slot_type));
}
// Allocates a backing array for `self` and initializes its control bytes.
- // This reads `capacity_` and updates all other fields based on the result of
+ // This reads `capacity` and updates all other fields based on the result of
// the allocation.
//
- // This does not free the currently held array; `capacity_` must be nonzero.
- void initialize_slots() {
- assert(capacity_);
- // Folks with custom allocators often make unwarranted assumptions about the
- // behavior of their classes vis-a-vis trivial destructability and what
- // calls they will or wont make. Avoid sampling for people with custom
- // allocators to get us out of this mess. This is not a hard guarantee but
- // a workaround while we plan the exact guarantee we want to provide.
- //
+ // This does not free the currently held array; `capacity` must be nonzero.
+ inline void initialize_slots() {
// People are often sloppy with the exact type of their allocator (sometimes
// it has an extra const or is missing the pair, but rebinds made it work
- // anyway). To avoid the ambiguity, we work off SlotAlloc which we have
- // bound more carefully.
- if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value &&
- slots_ == nullptr) {
- infoz() = Sample(sizeof(slot_type));
- }
-
- char* mem = static_cast<char*>(Allocate<alignof(slot_type)>(
- &alloc_ref(),
- AllocSize(capacity_, sizeof(slot_type), alignof(slot_type))));
- ctrl_ = reinterpret_cast<ctrl_t*>(mem);
- slots_ = reinterpret_cast<slot_type*>(
- mem + SlotOffset(capacity_, alignof(slot_type)));
- ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
- reset_growth_left();
- infoz().RecordStorageChanged(size_, capacity_);
- }
-
- // Destroys all slots in the backing array, frees the backing array, and
- // clears all top-level book-keeping data.
- //
- // This essentially implements `map = raw_hash_set();`.
- void destroy_slots() {
- if (!capacity_) return;
- for (size_t i = 0; i != capacity_; ++i) {
- if (IsFull(ctrl_[i])) {
- PolicyTraits::destroy(&alloc_ref(), slots_ + i);
- }
- }
-
- // Unpoison before returning the memory to the allocator.
- SanitizerUnpoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
- Deallocate<alignof(slot_type)>(
- &alloc_ref(), ctrl_,
- AllocSize(capacity_, sizeof(slot_type), alignof(slot_type)));
- ctrl_ = EmptyGroup();
- slots_ = nullptr;
- size_ = 0;
- capacity_ = 0;
- growth_left() = 0;
+ // anyway).
+ using CharAlloc =
+ typename absl::allocator_traits<Alloc>::template rebind_alloc<char>;
+ InitializeSlots<CharAlloc, sizeof(slot_type), alignof(slot_type)>(
+ common(), CharAlloc(alloc_ref()));
}
- void resize(size_t new_capacity) {
+ ABSL_ATTRIBUTE_NOINLINE void resize(size_t new_capacity) {
assert(IsValidCapacity(new_capacity));
- auto* old_ctrl = ctrl_;
- auto* old_slots = slots_;
- const size_t old_capacity = capacity_;
- capacity_ = new_capacity;
+ auto* old_ctrl = control();
+ auto* old_slots = slot_array();
+ const size_t old_capacity = common().capacity_;
+ common().capacity_ = new_capacity;
initialize_slots();
+ auto* new_slots = slot_array();
size_t total_probe_length = 0;
for (size_t i = 0; i != old_capacity; ++i) {
if (IsFull(old_ctrl[i])) {
size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
PolicyTraits::element(old_slots + i));
- auto target = find_first_non_full(ctrl_, hash, capacity_);
+ auto target = find_first_non_full(common(), hash);
size_t new_i = target.offset;
total_probe_length += target.probe_length;
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
- PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
+ SetCtrl(common(), new_i, H2(hash), sizeof(slot_type));
+ PolicyTraits::transfer(&alloc_ref(), new_slots + new_i, old_slots + i);
}
}
if (old_capacity) {
@@ -2002,70 +2343,10 @@ class raw_hash_set {
// Prunes control bytes to remove as many tombstones as possible.
//
// See the comment on `rehash_and_grow_if_necessary()`.
- void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
- assert(IsValidCapacity(capacity_));
- assert(!is_small(capacity_));
- // Algorithm:
- // - mark all DELETED slots as EMPTY
- // - mark all FULL slots as DELETED
- // - for each slot marked as DELETED
- // hash = Hash(element)
- // target = find_first_non_full(hash)
- // if target is in the same group
- // mark slot as FULL
- // else if target is EMPTY
- // transfer element to target
- // mark slot as EMPTY
- // mark target as FULL
- // else if target is DELETED
- // swap current element with target element
- // mark target as FULL
- // repeat procedure for current slot with moved from element (target)
- ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
- alignas(slot_type) unsigned char raw[sizeof(slot_type)];
- size_t total_probe_length = 0;
- slot_type* slot = reinterpret_cast<slot_type*>(&raw);
- for (size_t i = 0; i != capacity_; ++i) {
- if (!IsDeleted(ctrl_[i])) continue;
- const size_t hash = PolicyTraits::apply(
- HashElement{hash_ref()}, PolicyTraits::element(slots_ + i));
- const FindInfo target = find_first_non_full(ctrl_, hash, capacity_);
- const size_t new_i = target.offset;
- total_probe_length += target.probe_length;
-
- // Verify if the old and new i fall within the same group wrt the hash.
- // If they do, we don't need to move the object as it falls already in the
- // best probe we can.
- const size_t probe_offset = probe(ctrl_, hash, capacity_).offset();
- const auto probe_index = [probe_offset, this](size_t pos) {
- return ((pos - probe_offset) & capacity_) / Group::kWidth;
- };
-
- // Element doesn't move.
- if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
- SetCtrl(i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
- continue;
- }
- if (IsEmpty(ctrl_[new_i])) {
- // Transfer element to the empty spot.
- // SetCtrl poisons/unpoisons the slots so we have to call it at the
- // right time.
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
- PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slots_ + i);
- SetCtrl(i, ctrl_t::kEmpty, capacity_, ctrl_, slots_, sizeof(slot_type));
- } else {
- assert(IsDeleted(ctrl_[new_i]));
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
- // Until we are done rehashing, DELETED marks previously FULL slots.
- // Swap i and new_i elements.
- PolicyTraits::transfer(&alloc_ref(), slot, slots_ + i);
- PolicyTraits::transfer(&alloc_ref(), slots_ + i, slots_ + new_i);
- PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slot);
- --i; // repeat
- }
- }
- reset_growth_left();
- infoz().RecordRehash(total_probe_length);
+ inline void drop_deletes_without_resize() {
+ // Stack-allocate space for swapping elements.
+ alignas(slot_type) unsigned char tmp[sizeof(slot_type)];
+ DropDeletesWithoutResize(common(), GetPolicyFunctions(), tmp);
}
// Called whenever the table *might* need to conditionally grow.
@@ -2074,14 +2355,13 @@ class raw_hash_set {
// growth is unnecessary, because vacating tombstones is beneficial for
// performance in the long-run.
void rehash_and_grow_if_necessary() {
- if (capacity_ == 0) {
- resize(1);
- } else if (capacity_ > Group::kWidth &&
- // Do these calcuations in 64-bit to avoid overflow.
- size() * uint64_t{32} <= capacity_ * uint64_t{25}) {
+ const size_t cap = capacity();
+ if (cap > Group::kWidth &&
+ // Do these calcuations in 64-bit to avoid overflow.
+ size() * uint64_t{32} <= cap* uint64_t{25}) {
// Squash DELETED without growing if there is enough capacity.
//
- // Rehash in place if the current size is <= 25/32 of capacity_.
+ // Rehash in place if the current size is <= 25/32 of capacity.
// Rationale for such a high factor: 1) drop_deletes_without_resize() is
// faster than resize, and 2) it takes quite a bit of work to add
// tombstones. In the worst case, seems to take approximately 4
@@ -2099,8 +2379,8 @@ class raw_hash_set {
//
// Here is output of an experiment using the BM_CacheInSteadyState
// benchmark running the old case (where we rehash-in-place only if we can
- // reclaim at least 7/16*capacity_) vs. this code (which rehashes in place
- // if we can recover 3/32*capacity_).
+ // reclaim at least 7/16*capacity) vs. this code (which rehashes in place
+ // if we can recover 3/32*capacity).
//
// Note that although in the worst-case number of rehashes jumped up from
// 15 to 190, but the number of operations per second is almost the same.
@@ -2123,23 +2403,24 @@ class raw_hash_set {
drop_deletes_without_resize();
} else {
// Otherwise grow the container.
- resize(capacity_ * 2 + 1);
+ resize(NextCapacity(cap));
}
}
bool has_element(const value_type& elem) const {
size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem);
- auto seq = probe(ctrl_, hash, capacity_);
+ auto seq = probe(common(), hash);
+ const ctrl_t* ctrl = control();
while (true) {
- Group g{ctrl_ + seq.offset()};
+ Group g{ctrl + seq.offset()};
for (uint32_t i : g.Match(H2(hash))) {
- if (ABSL_PREDICT_TRUE(PolicyTraits::element(slots_ + seq.offset(i)) ==
- elem))
+ if (ABSL_PREDICT_TRUE(
+ PolicyTraits::element(slot_array() + seq.offset(i)) == elem))
return true;
}
if (ABSL_PREDICT_TRUE(g.MaskEmpty())) return false;
seq.next();
- assert(seq.index() <= capacity_ && "full table!");
+ assert(seq.index() <= capacity() && "full table!");
}
return false;
}
@@ -2164,18 +2445,19 @@ class raw_hash_set {
std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
prefetch_heap_block();
auto hash = hash_ref()(key);
- auto seq = probe(ctrl_, hash, capacity_);
+ auto seq = probe(common(), hash);
+ const ctrl_t* ctrl = control();
while (true) {
- Group g{ctrl_ + seq.offset()};
+ Group g{ctrl + seq.offset()};
for (uint32_t i : g.Match(H2(hash))) {
if (ABSL_PREDICT_TRUE(PolicyTraits::apply(
EqualElement<K>{key, eq_ref()},
- PolicyTraits::element(slots_ + seq.offset(i)))))
+ PolicyTraits::element(slot_array() + seq.offset(i)))))
return {seq.offset(i), false};
}
if (ABSL_PREDICT_TRUE(g.MaskEmpty())) break;
seq.next();
- assert(seq.index() <= capacity_ && "full table!");
+ assert(seq.index() <= capacity() && "full table!");
}
return {prepare_insert(hash), true};
}
@@ -2185,16 +2467,24 @@ class raw_hash_set {
//
// REQUIRES: At least one non-full slot available.
size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
- auto target = find_first_non_full(ctrl_, hash, capacity_);
- if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
- !IsDeleted(ctrl_[target.offset]))) {
+ const bool rehash_for_bug_detection =
+ common().should_rehash_for_bug_detection_on_insert();
+ if (rehash_for_bug_detection) {
+ // Move to a different heap allocation in order to detect bugs.
+ const size_t cap = capacity();
+ resize(growth_left() > 0 ? cap : NextCapacity(cap));
+ }
+ auto target = find_first_non_full(common(), hash);
+ if (!rehash_for_bug_detection &&
+ ABSL_PREDICT_FALSE(growth_left() == 0 &&
+ !IsDeleted(control()[target.offset]))) {
rehash_and_grow_if_necessary();
- target = find_first_non_full(ctrl_, hash, capacity_);
+ target = find_first_non_full(common(), hash);
}
- ++size_;
- growth_left() -= IsEmpty(ctrl_[target.offset]);
- SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
- sizeof(slot_type));
+ ++common().size_;
+ growth_left() -= IsEmpty(control()[target.offset]);
+ SetCtrl(common(), target.offset, H2(hash), sizeof(slot_type));
+ common().maybe_increment_generation_on_insert();
infoz().RecordInsert(hash, target.probe_length);
return target.offset;
}
@@ -2209,7 +2499,7 @@ class raw_hash_set {
// POSTCONDITION: *m.iterator_at(i) == value_type(forward<Args>(args)...).
template <class... Args>
void emplace_at(size_t i, Args&&... args) {
- PolicyTraits::construct(&alloc_ref(), slots_ + i,
+ PolicyTraits::construct(&alloc_ref(), slot_array() + i,
std::forward<Args>(args)...);
assert(PolicyTraits::apply(FindElement{*this}, *iterator_at(i)) ==
@@ -2217,16 +2507,16 @@ class raw_hash_set {
"constructed value does not match the lookup key");
}
- iterator iterator_at(size_t i) { return {ctrl_ + i, slots_ + i}; }
- const_iterator iterator_at(size_t i) const { return {ctrl_ + i, slots_ + i}; }
+ iterator iterator_at(size_t i) {
+ return {control() + i, slot_array() + i, common().generation_ptr()};
+ }
+ const_iterator iterator_at(size_t i) const {
+ return {control() + i, slot_array() + i, common().generation_ptr()};
+ }
private:
friend struct RawHashSetTestOnlyAccess;
- void reset_growth_left() {
- growth_left() = CapacityToGrowth(capacity()) - size_;
- }
-
// The number of slots we can still fill without needing to rehash.
//
// This is stored separately due to tombstones: we do not include tombstones
@@ -2237,49 +2527,76 @@ class raw_hash_set {
// side-effect.
//
// See `CapacityToGrowth()`.
- size_t& growth_left() { return settings_.template get<0>(); }
+ size_t& growth_left() { return common().growth_left(); }
// Prefetch the heap-allocated memory region to resolve potential TLB misses.
// This is intended to overlap with execution of calculating the hash for a
// key.
- void prefetch_heap_block() const {
- base_internal::PrefetchT2(ctrl_);
- }
+ void prefetch_heap_block() const { base_internal::PrefetchT2(control()); }
+
+ CommonFields& common() { return settings_.template get<0>(); }
+ const CommonFields& common() const { return settings_.template get<0>(); }
- HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
+ ctrl_t* control() const { return common().control_; }
+ slot_type* slot_array() const {
+ return static_cast<slot_type*>(common().slots_);
+ }
+ HashtablezInfoHandle& infoz() { return common().infoz(); }
- hasher& hash_ref() { return settings_.template get<2>(); }
- const hasher& hash_ref() const { return settings_.template get<2>(); }
- key_equal& eq_ref() { return settings_.template get<3>(); }
- const key_equal& eq_ref() const { return settings_.template get<3>(); }
- allocator_type& alloc_ref() { return settings_.template get<4>(); }
+ hasher& hash_ref() { return settings_.template get<1>(); }
+ const hasher& hash_ref() const { return settings_.template get<1>(); }
+ key_equal& eq_ref() { return settings_.template get<2>(); }
+ const key_equal& eq_ref() const { return settings_.template get<2>(); }
+ allocator_type& alloc_ref() { return settings_.template get<3>(); }
const allocator_type& alloc_ref() const {
- return settings_.template get<4>();
+ return settings_.template get<3>();
}
- // TODO(alkis): Investigate removing some of these fields:
- // - ctrl/slots can be derived from each other
- // - size can be moved into the slot array
+ // Make type-specific functions for this type's PolicyFunctions struct.
+ static size_t hash_slot_fn(void* set, void* slot) {
+ auto* h = static_cast<raw_hash_set*>(set);
+ return PolicyTraits::apply(
+ HashElement{h->hash_ref()},
+ PolicyTraits::element(static_cast<slot_type*>(slot)));
+ }
+ static void transfer_slot_fn(void* set, void* dst, void* src) {
+ auto* h = static_cast<raw_hash_set*>(set);
+ PolicyTraits::transfer(&h->alloc_ref(), static_cast<slot_type*>(dst),
+ static_cast<slot_type*>(src));
+ }
+ // Note: dealloc_fn will only be used if we have a non-standard allocator.
+ static void dealloc_fn(void* set, const PolicyFunctions&, ctrl_t* ctrl,
+ void* slot_mem, size_t n) {
+ auto* h = static_cast<raw_hash_set*>(set);
- // The control bytes (and, also, a pointer to the base of the backing array).
- //
- // This contains `capacity_ + 1 + NumClonedBytes()` entries, even
- // when the table is empty (hence EmptyGroup).
- ctrl_t* ctrl_ = EmptyGroup();
- // The beginning of the slots, located at `SlotOffset()` bytes after
- // `ctrl_`. May be null for empty tables.
- slot_type* slots_ = nullptr;
+ // Unpoison before returning the memory to the allocator.
+ SanitizerUnpoisonMemoryRegion(slot_mem, sizeof(slot_type) * n);
- // The number of filled slots.
- size_t size_ = 0;
+ Deallocate<alignof(slot_type)>(
+ &h->alloc_ref(), ctrl,
+ AllocSize(n, sizeof(slot_type), alignof(slot_type)));
+ }
+
+ static const PolicyFunctions& GetPolicyFunctions() {
+ static constexpr PolicyFunctions value = {
+ sizeof(slot_type),
+ &raw_hash_set::hash_slot_fn,
+ PolicyTraits::transfer_uses_memcpy()
+ ? TransferRelocatable<sizeof(slot_type)>
+ : &raw_hash_set::transfer_slot_fn,
+ (std::is_same<SlotAlloc, std::allocator<slot_type>>::value
+ ? &DeallocateStandard<alignof(slot_type)>
+ : &raw_hash_set::dealloc_fn),
+ };
+ return value;
+ }
- // The total number of available slots.
- size_t capacity_ = 0;
- absl::container_internal::CompressedTuple<size_t /* growth_left */,
- HashtablezInfoHandle, hasher,
- key_equal, allocator_type>
- settings_{0u, HashtablezInfoHandle{}, hasher{}, key_equal{},
- allocator_type{}};
+ // Bundle together CommonFields plus other objects which might be empty.
+ // CompressedTuple will ensure that sizeof is not affected by any of the empty
+ // fields that occur after CommonFields.
+ absl::container_internal::CompressedTuple<CommonFields, hasher, key_equal,
+ allocator_type>
+ settings_{CommonFields{}, hasher{}, key_equal{}, allocator_type{}};
};
// Erases all elements that satisfy the predicate `pred` from the container `c`.
@@ -2307,14 +2624,15 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
const typename Set::key_type& key) {
size_t num_probes = 0;
size_t hash = set.hash_ref()(key);
- auto seq = probe(set.ctrl_, hash, set.capacity_);
+ auto seq = probe(set.common(), hash);
+ const ctrl_t* ctrl = set.control();
while (true) {
- container_internal::Group g{set.ctrl_ + seq.offset()};
+ container_internal::Group g{ctrl + seq.offset()};
for (uint32_t i : g.Match(container_internal::H2(hash))) {
if (Traits::apply(
typename Set::template EqualElement<typename Set::key_type>{
key, set.eq_ref()},
- Traits::element(set.slots_ + seq.offset(i))))
+ Traits::element(set.slot_array() + seq.offset(i))))
return num_probes;
++num_probes;
}
@@ -2325,7 +2643,7 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
}
static size_t AllocatedByteSize(const Set& c) {
- size_t capacity = c.capacity_;
+ size_t capacity = c.capacity();
if (capacity == 0) return 0;
size_t m = AllocSize(capacity, sizeof(Slot), alignof(Slot));
@@ -2333,9 +2651,10 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
if (per_slot != ~size_t{}) {
m += per_slot * c.size();
} else {
+ const ctrl_t* ctrl = c.control();
for (size_t i = 0; i != capacity; ++i) {
- if (container_internal::IsFull(c.ctrl_[i])) {
- m += Traits::space_used(c.slots_ + i);
+ if (container_internal::IsFull(ctrl[i])) {
+ m += Traits::space_used(c.slot_array() + i);
}
}
}
@@ -2360,6 +2679,7 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
ABSL_NAMESPACE_END
} // namespace absl
+#undef ABSL_SWISSTABLE_ENABLE_GENERATIONS
#undef ABSL_INTERNAL_ASSERT_IS_FULL
#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc b/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc
new file mode 100644
index 0000000000..468c1b3b3e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc
@@ -0,0 +1,99 @@
+// 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/crc/crc32c.h"
+
+#include <cstdint>
+
+#include "absl/crc/internal/crc.h"
+#include "absl/crc/internal/crc32c.h"
+#include "absl/crc/internal/crc_memcpy.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace {
+
+const crc_internal::CRC* CrcEngine() {
+ static const crc_internal::CRC* engine = crc_internal::CRC::Crc32c();
+ return engine;
+}
+
+constexpr uint32_t kCRC32Xor = 0xffffffffU;
+
+} // namespace
+
+namespace crc_internal {
+
+crc32c_t UnextendCrc32cByZeroes(crc32c_t initial_crc, size_t length) {
+ uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;
+ CrcEngine()->UnextendByZeroes(&crc, length);
+ return static_cast<crc32c_t>(crc ^ kCRC32Xor);
+}
+
+// Called by `absl::ExtendCrc32c()` on strings with size > 64 or when hardware
+// CRC32C support is missing.
+crc32c_t ExtendCrc32cInternal(crc32c_t initial_crc,
+ absl::string_view buf_to_add) {
+ uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;
+ CrcEngine()->Extend(&crc, buf_to_add.data(), buf_to_add.size());
+ return static_cast<crc32c_t>(crc ^ kCRC32Xor);
+}
+
+} // namespace crc_internal
+
+crc32c_t ComputeCrc32c(absl::string_view buf) {
+ return ExtendCrc32c(crc32c_t{0}, buf);
+}
+
+crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length) {
+ uint32_t crc = static_cast<uint32_t>(initial_crc) ^ kCRC32Xor;
+ CrcEngine()->ExtendByZeroes(&crc, length);
+ return static_cast<crc32c_t>(crc ^ kCRC32Xor);
+}
+
+crc32c_t ConcatCrc32c(crc32c_t lhs_crc, crc32c_t rhs_crc, size_t rhs_len) {
+ uint32_t result = static_cast<uint32_t>(lhs_crc);
+ CrcEngine()->ExtendByZeroes(&result, rhs_len);
+ return crc32c_t{result ^ static_cast<uint32_t>(rhs_crc)};
+}
+
+crc32c_t RemoveCrc32cPrefix(crc32c_t crc_a, crc32c_t crc_ab, size_t length_b) {
+ return ConcatCrc32c(crc_a, crc_ab, length_b);
+}
+
+crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,
+ crc32c_t initial_crc) {
+ return static_cast<crc32c_t>(
+ crc_internal::Crc32CAndCopy(dest, src, count, initial_crc, false));
+}
+
+// Remove a Suffix of given size from a buffer
+//
+// Given a CRC32C of an existing buffer, `full_string_crc`; the CRC32C of a
+// suffix of that buffer to remove, `suffix_crc`; and suffix buffer's length,
+// `suffix_len` return the CRC32C of the buffer with suffix removed
+//
+// This operation has a runtime cost of O(log(`suffix_len`))
+crc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc,
+ size_t suffix_len) {
+ uint32_t result = static_cast<uint32_t>(full_string_crc) ^
+ static_cast<uint32_t>(suffix_crc);
+ CrcEngine()->UnextendByZeroes(&result, suffix_len);
+ return crc32c_t{result};
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/crc32c.h b/contrib/restricted/abseil-cpp/absl/crc/crc32c.h
new file mode 100644
index 0000000000..ba09e52a01
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/crc32c.h
@@ -0,0 +1,183 @@
+// 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: crc32c.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for computing CRC32C values as checksums
+// for arbitrary sequences of bytes provided as a string buffer.
+//
+// The API includes the basic functions for computing such CRC32C values and
+// some utility functions for performing more efficient mathematical
+// computations using an existing checksum.
+#ifndef ABSL_CRC_CRC32C_H_
+#define ABSL_CRC_CRC32C_H_
+
+#include <cstdint>
+#include <ostream>
+
+#include "absl/crc/internal/crc32c_inline.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+//-----------------------------------------------------------------------------
+// crc32c_t
+//-----------------------------------------------------------------------------
+
+// `crc32c_t` defines a strongly-typed integer for holding a CRC32C value.
+//
+// Some operators are intentionally omitted. Only equality operators are defined
+// so that `crc32c_t` can be directly compared. Methods for putting `crc32c_t`
+// directly into a set are omitted because this is bug-prone due to checksum
+// collisions. Use an explicit conversion to the `uint32_t` space for operations
+// that treat `crc32c_t` as an integer.
+class crc32c_t final {
+ public:
+ crc32c_t() = default;
+ constexpr explicit crc32c_t(uint32_t crc) : crc_(crc) {}
+
+ crc32c_t(const crc32c_t&) = default;
+ crc32c_t& operator=(const crc32c_t&) = default;
+
+ explicit operator uint32_t() const { return crc_; }
+
+ friend bool operator==(crc32c_t lhs, crc32c_t rhs) {
+ return static_cast<uint32_t>(lhs) == static_cast<uint32_t>(rhs);
+ }
+
+ friend bool operator!=(crc32c_t lhs, crc32c_t rhs) { return !(lhs == rhs); }
+
+ private:
+ uint32_t crc_;
+};
+
+namespace crc_internal {
+// Non-inline code path for `absl::ExtendCrc32c()`. Do not call directly.
+// Call `absl::ExtendCrc32c()` (defined below) instead.
+crc32c_t ExtendCrc32cInternal(crc32c_t initial_crc,
+ absl::string_view buf_to_add);
+} // namespace crc_internal
+
+// -----------------------------------------------------------------------------
+// CRC32C Computation Functions
+// -----------------------------------------------------------------------------
+
+// ComputeCrc32c()
+//
+// Returns the CRC32C value of the provided string.
+crc32c_t ComputeCrc32c(absl::string_view buf);
+
+// ExtendCrc32c()
+//
+// Computes a CRC32C value from an `initial_crc` CRC32C value including the
+// `buf_to_add` bytes of an additional buffer. Using this function is more
+// efficient than computing a CRC32C value for the combined buffer from
+// scratch.
+//
+// Note: `ExtendCrc32c` with an initial_crc of 0 is equivalent to
+// `ComputeCrc32c`.
+//
+// This operation has a runtime cost of O(`buf_to_add.size()`)
+inline crc32c_t ExtendCrc32c(crc32c_t initial_crc,
+ absl::string_view buf_to_add) {
+ // Approximately 75% of calls have size <= 64.
+ if (buf_to_add.size() <= 64) {
+ uint32_t crc = static_cast<uint32_t>(initial_crc);
+ if (crc_internal::ExtendCrc32cInline(&crc, buf_to_add.data(),
+ buf_to_add.size())) {
+ return crc32c_t{crc};
+ }
+ }
+ return crc_internal::ExtendCrc32cInternal(initial_crc, buf_to_add);
+}
+
+// ExtendCrc32cByZeroes()
+//
+// Computes a CRC32C value for a buffer with an `initial_crc` CRC32C value,
+// where `length` bytes with a value of 0 are appended to the buffer. Using this
+// function is more efficient than computing a CRC32C value for the combined
+// buffer from scratch.
+//
+// This operation has a runtime cost of O(log(`length`))
+crc32c_t ExtendCrc32cByZeroes(crc32c_t initial_crc, size_t length);
+
+// MemcpyCrc32c()
+//
+// Copies `src` to `dest` using `memcpy()` semantics, returning the CRC32C
+// value of the copied buffer.
+//
+// Using `MemcpyCrc32c()` is potentially faster than performing the `memcpy()`
+// and `ComputeCrc32c()` operations separately.
+crc32c_t MemcpyCrc32c(void* dest, const void* src, size_t count,
+ crc32c_t initial_crc = crc32c_t{0});
+
+// -----------------------------------------------------------------------------
+// CRC32C Arithmetic Functions
+// -----------------------------------------------------------------------------
+
+// The following functions perform arithmetic on CRC32C values, which are
+// generally more efficient than recalculating any given result's CRC32C value.
+
+// ConcatCrc32c()
+//
+// Calculates the CRC32C value of two buffers with known CRC32C values
+// concatenated together.
+//
+// Given a buffer with CRC32C value `crc1` and a buffer with
+// CRC32C value `crc2` and length, `crc2_length`, returns the CRC32C value of
+// the concatenation of these two buffers.
+//
+// This operation has a runtime cost of O(log(`crc2_length`)).
+crc32c_t ConcatCrc32c(crc32c_t crc1, crc32c_t crc2, size_t crc2_length);
+
+// RemoveCrc32cPrefix()
+//
+// Calculates the CRC32C value of an existing buffer with a series of bytes
+// (the prefix) removed from the beginning of that buffer.
+//
+// Given the CRC32C value of an existing buffer, `full_string_crc`; The CRC32C
+// value of a prefix of that buffer, `prefix_crc`; and the length of the buffer
+// with the prefix removed, `remaining_string_length` , return the CRC32C
+// value of the buffer with the prefix removed.
+//
+// This operation has a runtime cost of O(log(`remaining_string_length`)).
+crc32c_t RemoveCrc32cPrefix(crc32c_t prefix_crc, crc32c_t full_string_crc,
+ size_t remaining_string_length);
+// RemoveCrc32cSuffix()
+//
+// Calculates the CRC32C value of an existing buffer with a series of bytes
+// (the suffix) removed from the end of that buffer.
+//
+// Given a CRC32C value of an existing buffer `full_string_crc`, the CRC32C
+// value of the suffix to remove `suffix_crc`, and the length of that suffix
+// `suffix_len`, returns the CRC32C value of the buffer with suffix removed.
+//
+// This operation has a runtime cost of O(log(`suffix_len`))
+crc32c_t RemoveCrc32cSuffix(crc32c_t full_string_crc, crc32c_t suffix_crc,
+ size_t suffix_length);
+
+// operator<<
+//
+// Streams the CRC32C value `crc` to the stream `os`.
+inline std::ostream& operator<<(std::ostream& os, crc32c_t crc) {
+ return os << static_cast<uint32_t>(crc);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_CRC32C_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc
new file mode 100644
index 0000000000..d61b7018d1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc
@@ -0,0 +1,256 @@
+// 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/crc/internal/cpu_detect.h"
+
+#include <cstdint>
+#include <string>
+
+#include "absl/base/config.h"
+
+#if defined(__aarch64__) && defined(__linux__)
+#include <asm/hwcap.h>
+#include <sys/auxv.h>
+#endif
+
+#if defined(_WIN32) || defined(_WIN64)
+#include <intrin.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+#if defined(__x86_64__) || defined(_M_X64)
+
+namespace {
+
+#if !defined(_WIN32) && !defined(_WIN64)
+// MSVC defines this function for us.
+// https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex
+static void __cpuid(int cpu_info[4], int info_type) {
+ __asm__ volatile("cpuid \n\t"
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
+ "=d"(cpu_info[3])
+ : "a"(info_type), "c"(0));
+}
+#endif // !defined(_WIN32) && !defined(_WIN64)
+
+enum class Vendor {
+ kUnknown,
+ kIntel,
+ kAmd,
+};
+
+Vendor GetVendor() {
+ // Get the vendor string (issue CPUID with eax = 0).
+ int cpu_info[4];
+ __cpuid(cpu_info, 0);
+
+ std::string vendor;
+ vendor.append(reinterpret_cast<char*>(&cpu_info[1]), 4);
+ vendor.append(reinterpret_cast<char*>(&cpu_info[3]), 4);
+ vendor.append(reinterpret_cast<char*>(&cpu_info[2]), 4);
+ if (vendor == "GenuineIntel") {
+ return Vendor::kIntel;
+ } else if (vendor == "AuthenticAMD") {
+ return Vendor::kAmd;
+ } else {
+ return Vendor::kUnknown;
+ }
+}
+
+CpuType GetIntelCpuType() {
+ // To get general information and extended features we send eax = 1 and
+ // ecx = 0 to cpuid. The response is returned in eax, ebx, ecx and edx.
+ // (See Intel 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 2A: Instruction Set Reference, A-M CPUID).
+ // https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2a-manual.html
+ // https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex
+ int cpu_info[4];
+ __cpuid(cpu_info, 1);
+
+ // Response in eax bits as follows:
+ // 0-3 (stepping id)
+ // 4-7 (model number),
+ // 8-11 (family code),
+ // 12-13 (processor type),
+ // 16-19 (extended model)
+ // 20-27 (extended family)
+
+ int family = (cpu_info[0] >> 8) & 0x0f;
+ int model_num = (cpu_info[0] >> 4) & 0x0f;
+ int ext_family = (cpu_info[0] >> 20) & 0xff;
+ int ext_model_num = (cpu_info[0] >> 16) & 0x0f;
+
+ int brand_id = cpu_info[1] & 0xff;
+
+ // Process the extended family and model info if necessary
+ if (family == 0x0f) {
+ family += ext_family;
+ }
+
+ if (family == 0x0f || family == 0x6) {
+ model_num += (ext_model_num << 4);
+ }
+
+ switch (brand_id) {
+ case 0: // no brand ID, so parse CPU family/model
+ switch (family) {
+ case 6: // Most PentiumIII processors are in this category
+ switch (model_num) {
+ case 0x2c: // Westmere: Gulftown
+ return CpuType::kIntelWestmere;
+ case 0x2d: // Sandybridge
+ return CpuType::kIntelSandybridge;
+ case 0x3e: // Ivybridge
+ return CpuType::kIntelIvybridge;
+ case 0x3c: // Haswell (client)
+ case 0x3f: // Haswell
+ return CpuType::kIntelHaswell;
+ case 0x4f: // Broadwell
+ case 0x56: // BroadwellDE
+ return CpuType::kIntelBroadwell;
+ case 0x55: // Skylake Xeon
+ if ((cpu_info[0] & 0x0f) < 5) { // stepping < 5 is skylake
+ return CpuType::kIntelSkylakeXeon;
+ } else { // stepping >= 5 is cascadelake
+ return CpuType::kIntelCascadelakeXeon;
+ }
+ case 0x5e: // Skylake (client)
+ return CpuType::kIntelSkylake;
+ default:
+ return CpuType::kUnknown;
+ }
+ default:
+ return CpuType::kUnknown;
+ }
+ default:
+ return CpuType::kUnknown;
+ }
+}
+
+CpuType GetAmdCpuType() {
+ // To get general information and extended features we send eax = 1 and
+ // ecx = 0 to cpuid. The response is returned in eax, ebx, ecx and edx.
+ // (See Intel 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 2A: Instruction Set Reference, A-M CPUID).
+ // https://learn.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex
+ int cpu_info[4];
+ __cpuid(cpu_info, 1);
+
+ // Response in eax bits as follows:
+ // 0-3 (stepping id)
+ // 4-7 (model number),
+ // 8-11 (family code),
+ // 12-13 (processor type),
+ // 16-19 (extended model)
+ // 20-27 (extended family)
+
+ int family = (cpu_info[0] >> 8) & 0x0f;
+ int model_num = (cpu_info[0] >> 4) & 0x0f;
+ int ext_family = (cpu_info[0] >> 20) & 0xff;
+ int ext_model_num = (cpu_info[0] >> 16) & 0x0f;
+
+ if (family == 0x0f) {
+ family += ext_family;
+ model_num += (ext_model_num << 4);
+ }
+
+ switch (family) {
+ case 0x17:
+ switch (model_num) {
+ case 0x0: // Stepping Ax
+ case 0x1: // Stepping Bx
+ return CpuType::kAmdNaples;
+ case 0x30: // Stepping Ax
+ case 0x31: // Stepping Bx
+ return CpuType::kAmdRome;
+ default:
+ return CpuType::kUnknown;
+ }
+ break;
+ case 0x19:
+ switch (model_num) {
+ case 0x1: // Stepping B0
+ return CpuType::kAmdMilan;
+ default:
+ return CpuType::kUnknown;
+ }
+ break;
+ default:
+ return CpuType::kUnknown;
+ }
+}
+
+} // namespace
+
+CpuType GetCpuType() {
+ switch (GetVendor()) {
+ case Vendor::kIntel:
+ return GetIntelCpuType();
+ case Vendor::kAmd:
+ return GetAmdCpuType();
+ default:
+ return CpuType::kUnknown;
+ }
+}
+
+bool SupportsArmCRC32PMULL() { return false; }
+
+#elif defined(__aarch64__) && defined(__linux__)
+
+#ifndef HWCAP_CPUID
+#define HWCAP_CPUID (1 << 11)
+#endif
+
+#define ABSL_INTERNAL_AARCH64_ID_REG_READ(id, val) \
+ asm("mrs %0, " #id : "=r"(val))
+
+CpuType GetCpuType() {
+ // MIDR_EL1 is not visible to EL0, however the access will be emulated by
+ // linux if AT_HWCAP has HWCAP_CPUID set.
+ //
+ // This method will be unreliable on heterogeneous computing systems (ex:
+ // big.LITTLE) since the value of MIDR_EL1 will change based on the calling
+ // thread.
+ uint64_t hwcaps = getauxval(AT_HWCAP);
+ if (hwcaps & HWCAP_CPUID) {
+ uint64_t midr = 0;
+ ABSL_INTERNAL_AARCH64_ID_REG_READ(MIDR_EL1, midr);
+ uint32_t implementer = (midr >> 24) & 0xff;
+ uint32_t part_number = (midr >> 4) & 0xfff;
+ if (implementer == 0x41 && part_number == 0xd0c) {
+ return CpuType::kArmNeoverseN1;
+ }
+ }
+ return CpuType::kUnknown;
+}
+
+bool SupportsArmCRC32PMULL() {
+ uint64_t hwcaps = getauxval(AT_HWCAP);
+ return (hwcaps & HWCAP_CRC32) && (hwcaps & HWCAP_PMULL);
+}
+
+#else
+
+CpuType GetCpuType() { return CpuType::kUnknown; }
+
+bool SupportsArmCRC32PMULL() { return false; }
+
+#endif
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h
new file mode 100644
index 0000000000..6054f6960d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.h
@@ -0,0 +1,57 @@
+// 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_CRC_INTERNAL_CPU_DETECT_H_
+#define ABSL_CRC_INTERNAL_CPU_DETECT_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+// Enumeration of architectures that we have special-case tuning parameters for.
+// This set may change over time.
+enum class CpuType {
+ kUnknown,
+ kIntelHaswell,
+ kAmdRome,
+ kAmdNaples,
+ kAmdMilan,
+ kIntelCascadelakeXeon,
+ kIntelSkylakeXeon,
+ kIntelBroadwell,
+ kIntelSkylake,
+ kIntelIvybridge,
+ kIntelSandybridge,
+ kIntelWestmere,
+ kArmNeoverseN1,
+};
+
+// Returns the type of host CPU this code is running on. Returns kUnknown if
+// the host CPU is of unknown type, or if detection otherwise fails.
+CpuType GetCpuType();
+
+// Returns whether the host CPU supports the CPU features needed for our
+// accelerated implementations. The CpuTypes enumerated above apart from
+// kUnknown support the required features. On unknown CPUs, we can use
+// this to see if it's safe to use hardware acceleration, though without any
+// tuning.
+bool SupportsArmCRC32PMULL();
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CPU_DETECT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc
new file mode 100644
index 0000000000..bb8936e373
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc
@@ -0,0 +1,468 @@
+// 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.
+
+// Implementation of CRCs (aka Rabin Fingerprints).
+// Treats the input as a polynomial with coefficients in Z(2),
+// and finds the remainder when divided by an irreducible polynomial
+// of the appropriate length.
+// It handles all CRC sizes from 8 to 128 bits.
+// It's somewhat complicated by having separate implementations optimized for
+// CRC's <=32 bits, <= 64 bits, and <= 128 bits.
+// The input string is prefixed with a "1" bit, and has "degree" "0" bits
+// appended to it before the remainder is found. This ensures that
+// short strings are scrambled somewhat and that strings consisting
+// of all nulls have a non-zero CRC.
+//
+// Uses the "interleaved word-by-word" method from
+// "Everything we know about CRC but afraid to forget" by Andrew Kadatch
+// and Bob Jenkins,
+// http://crcutil.googlecode.com/files/crc-doc.1.0.pdf
+//
+// The idea is to compute kStride CRCs simultaneously, allowing the
+// processor to more effectively use multiple execution units. Each of
+// the CRCs is calculated on one word of data followed by kStride - 1
+// words of zeroes; the CRC starting points are staggered by one word.
+// Assuming a stride of 4 with data words "ABCDABCDABCD", the first
+// CRC is over A000A000A, the second over 0B000B000B, and so on.
+// The CRC of the whole data is then calculated by properly aligning the
+// CRCs by appending zeroes until the data lengths agree then XORing
+// the CRCs.
+
+#include "absl/crc/internal/crc.h"
+
+#include <cstdint>
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/prefetch.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/crc/internal/crc_internal.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+namespace {
+
+// Constants
+#if defined(__i386__) || defined(__x86_64__)
+constexpr bool kNeedAlignedLoads = false;
+#else
+constexpr bool kNeedAlignedLoads = true;
+#endif
+
+// We express the number of zeroes as a number in base ZEROES_BASE. By
+// pre-computing the zero extensions for all possible components of such an
+// expression (numbers in a form a*ZEROES_BASE**b), we can calculate the
+// resulting extension by multiplying the extensions for individual components
+// using log_{ZEROES_BASE}(num_zeroes) polynomial multiplications. The tables of
+// zero extensions contain (ZEROES_BASE - 1) * (log_{ZEROES_BASE}(64)) entries.
+constexpr int ZEROES_BASE_LG = 4; // log_2(ZEROES_BASE)
+constexpr int ZEROES_BASE = (1 << ZEROES_BASE_LG); // must be a power of 2
+
+constexpr uint32_t kCrc32cPoly = 0x82f63b78;
+
+uint32_t ReverseBits(uint32_t bits) {
+ bits = (bits & 0xaaaaaaaau) >> 1 | (bits & 0x55555555u) << 1;
+ bits = (bits & 0xccccccccu) >> 2 | (bits & 0x33333333u) << 2;
+ bits = (bits & 0xf0f0f0f0u) >> 4 | (bits & 0x0f0f0f0fu) << 4;
+ return absl::gbswap_32(bits);
+}
+
+// Polynomial long multiplication mod the polynomial of degree 32.
+void PolyMultiply(uint32_t* val, uint32_t m, uint32_t poly) {
+ uint32_t l = *val;
+ uint32_t result = 0;
+ auto onebit = uint32_t{0x80000000u};
+ for (uint32_t one = onebit; one != 0; one >>= 1) {
+ if ((l & one) != 0) {
+ result ^= m;
+ }
+ if (m & 1) {
+ m = (m >> 1) ^ poly;
+ } else {
+ m >>= 1;
+ }
+ }
+ *val = result;
+}
+} // namespace
+
+void CRCImpl::FillWordTable(uint32_t poly, uint32_t last, int word_size,
+ Uint32By256* t) {
+ for (int j = 0; j != word_size; j++) { // for each byte of extension....
+ t[j][0] = 0; // a zero has no effect
+ for (int i = 128; i != 0; i >>= 1) { // fill in entries for powers of 2
+ if (j == 0 && i == 128) {
+ t[j][i] = last; // top bit in last byte is given
+ } else {
+ // each successive power of two is derived from the previous
+ // one, either in this table, or the last table
+ uint32_t pred;
+ if (i == 128) {
+ pred = t[j - 1][1];
+ } else {
+ pred = t[j][i << 1];
+ }
+ // Advance the CRC by one bit (multiply by X, and take remainder
+ // through one step of polynomial long division)
+ if (pred & 1) {
+ t[j][i] = (pred >> 1) ^ poly;
+ } else {
+ t[j][i] = pred >> 1;
+ }
+ }
+ }
+ // CRCs have the property that CRC(a xor b) == CRC(a) xor CRC(b)
+ // so we can make all the tables for non-powers of two by
+ // xoring previously created entries.
+ for (int i = 2; i != 256; i <<= 1) {
+ for (int k = i + 1; k != (i << 1); k++) {
+ t[j][k] = t[j][i] ^ t[j][k - i];
+ }
+ }
+ }
+}
+
+int CRCImpl::FillZeroesTable(uint32_t poly, Uint32By256* t) {
+ uint32_t inc = 1;
+ inc <<= 31;
+
+ // Extend by one zero bit. We know degree > 1 so (inc & 1) == 0.
+ inc >>= 1;
+
+ // Now extend by 2, 4, and 8 bits, so now `inc` is extended by one zero byte.
+ for (int i = 0; i < 3; ++i) {
+ PolyMultiply(&inc, inc, poly);
+ }
+
+ int j = 0;
+ for (uint64_t inc_len = 1; inc_len != 0; inc_len <<= ZEROES_BASE_LG) {
+ // Every entry in the table adds an additional inc_len zeroes.
+ uint32_t v = inc;
+ for (int a = 1; a != ZEROES_BASE; a++) {
+ t[0][j] = v;
+ PolyMultiply(&v, inc, poly);
+ j++;
+ }
+ inc = v;
+ }
+ ABSL_RAW_CHECK(j <= 256, "");
+ return j;
+}
+
+// Internal version of the "constructor".
+CRCImpl* CRCImpl::NewInternal() {
+ // Find an accelearated implementation first.
+ CRCImpl* result = TryNewCRC32AcceleratedX86ARMCombined();
+
+ // Fall back to generic implementions if no acceleration is available.
+ if (result == nullptr) {
+ result = new CRC32();
+ }
+
+ result->InitTables();
+
+ return result;
+}
+
+// The CRC of the empty string is always the CRC polynomial itself.
+void CRCImpl::Empty(uint32_t* crc) const { *crc = kCrc32cPoly; }
+
+// The 32-bit implementation
+
+void CRC32::InitTables() {
+ // Compute the table for extending a CRC by one byte.
+ Uint32By256* t = new Uint32By256[4];
+ FillWordTable(kCrc32cPoly, kCrc32cPoly, 1, t);
+ for (int i = 0; i != 256; i++) {
+ this->table0_[i] = t[0][i];
+ }
+
+ // Construct a table for updating the CRC by 4 bytes data followed by
+ // 12 bytes of zeroes.
+ //
+ // Note: the data word size could be larger than the CRC size; it might
+ // be slightly faster to use a 64-bit data word, but doing so doubles the
+ // table size.
+ uint32_t last = kCrc32cPoly;
+ const size_t size = 12;
+ for (size_t i = 0; i < size; ++i) {
+ last = (last >> 8) ^ this->table0_[last & 0xff];
+ }
+ FillWordTable(kCrc32cPoly, last, 4, t);
+ for (size_t b = 0; b < 4; ++b) {
+ for (int i = 0; i < 256; ++i) {
+ this->table_[b][i] = t[b][i];
+ }
+ }
+
+ int j = FillZeroesTable(kCrc32cPoly, t);
+ ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->zeroes_)), "");
+ for (int i = 0; i < j; i++) {
+ this->zeroes_[i] = t[0][i];
+ }
+
+ delete[] t;
+
+ // Build up tables for _reversing_ the operation of doing CRC operations on
+ // zero bytes.
+
+ // In C++, extending `crc` by a single zero bit is done by the following:
+ // (A) bool low_bit_set = (crc & 1);
+ // crc >>= 1;
+ // if (low_bit_set) crc ^= kCrc32cPoly;
+ //
+ // In particular note that the high bit of `crc` after this operation will be
+ // set if and only if the low bit of `crc` was set before it. This means that
+ // no information is lost, and the operation can be reversed, as follows:
+ // (B) bool high_bit_set = (crc & 0x80000000u);
+ // if (high_bit_set) crc ^= kCrc32cPoly;
+ // crc <<= 1;
+ // if (high_bit_set) crc ^= 1;
+ //
+ // Or, equivalently:
+ // (C) bool high_bit_set = (crc & 0x80000000u);
+ // crc <<= 1;
+ // if (high_bit_set) crc ^= ((kCrc32cPoly << 1) ^ 1);
+ //
+ // The last observation is, if we store our checksums in variable `rcrc`,
+ // with order of the bits reversed, the inverse operation becomes:
+ // (D) bool low_bit_set = (rcrc & 1);
+ // rcrc >>= 1;
+ // if (low_bit_set) rcrc ^= ReverseBits((kCrc32cPoly << 1) ^ 1)
+ //
+ // This is the same algorithm (A) that we started with, only with a different
+ // polynomial bit pattern. This means that by building up our tables with
+ // this alternate polynomial, we can apply the CRC algorithms to a
+ // bit-reversed CRC checksum to perform inverse zero-extension.
+
+ const uint32_t kCrc32cUnextendPoly =
+ ReverseBits(static_cast<uint32_t>((kCrc32cPoly << 1) ^ 1));
+ FillWordTable(kCrc32cUnextendPoly, kCrc32cUnextendPoly, 1, &reverse_table0_);
+
+ j = FillZeroesTable(kCrc32cUnextendPoly, &reverse_zeroes_);
+ ABSL_RAW_CHECK(j <= static_cast<int>(ABSL_ARRAYSIZE(this->reverse_zeroes_)),
+ "");
+}
+
+void CRC32::Extend(uint32_t* crc, const void* bytes, size_t length) const {
+ const uint8_t* p = static_cast<const uint8_t*>(bytes);
+ const uint8_t* e = p + length;
+ uint32_t l = *crc;
+
+ auto step_one_byte = [this, &p, &l] () {
+ int c = (l & 0xff) ^ *p++;
+ l = this->table0_[c] ^ (l >> 8);
+ };
+
+ if (kNeedAlignedLoads) {
+ // point x at first 4-byte aligned byte in string. this might be past the
+ // end of the string.
+ const uint8_t* x = RoundUp<4>(p);
+ if (x <= e) {
+ // Process bytes until finished or p is 4-byte aligned
+ while (p != x) {
+ step_one_byte();
+ }
+ }
+ }
+
+ const size_t kSwathSize = 16;
+ if (static_cast<size_t>(e - p) >= kSwathSize) {
+ // Load one swath of data into the operating buffers.
+ uint32_t buf0 = absl::little_endian::Load32(p) ^ l;
+ uint32_t buf1 = absl::little_endian::Load32(p + 4);
+ uint32_t buf2 = absl::little_endian::Load32(p + 8);
+ uint32_t buf3 = absl::little_endian::Load32(p + 12);
+ p += kSwathSize;
+
+ // Increment a CRC value by a "swath"; this combines the four bytes
+ // starting at `ptr` and twelve zero bytes, so that four CRCs can be
+ // built incrementally and combined at the end.
+ const auto step_swath = [this](uint32_t crc_in, const std::uint8_t* ptr) {
+ return absl::little_endian::Load32(ptr) ^
+ this->table_[3][crc_in & 0xff] ^
+ this->table_[2][(crc_in >> 8) & 0xff] ^
+ this->table_[1][(crc_in >> 16) & 0xff] ^
+ this->table_[0][crc_in >> 24];
+ };
+
+ // Run one CRC calculation step over all swaths in one 16-byte stride
+ const auto step_stride = [&]() {
+ buf0 = step_swath(buf0, p);
+ buf1 = step_swath(buf1, p + 4);
+ buf2 = step_swath(buf2, p + 8);
+ buf3 = step_swath(buf3, p + 12);
+ p += 16;
+ };
+
+ // Process kStride interleaved swaths through the data in parallel.
+ while ((e - p) > kPrefetchHorizon) {
+ base_internal::PrefetchNta(
+ reinterpret_cast<const void*>(p + kPrefetchHorizon));
+ // Process 64 bytes at a time
+ step_stride();
+ step_stride();
+ step_stride();
+ step_stride();
+ }
+ while (static_cast<size_t>(e - p) >= kSwathSize) {
+ step_stride();
+ }
+
+ // Now advance one word at a time as far as possible. This isn't worth
+ // doing if we have word-advance tables.
+ while (static_cast<size_t>(e - p) >= 4) {
+ buf0 = step_swath(buf0, p);
+ uint32_t tmp = buf0;
+ buf0 = buf1;
+ buf1 = buf2;
+ buf2 = buf3;
+ buf3 = tmp;
+ p += 4;
+ }
+
+ // Combine the results from the different swaths. This is just a CRC
+ // on the data values in the bufX words.
+ auto combine_one_word = [this](uint32_t crc_in, uint32_t w) {
+ w ^= crc_in;
+ for (size_t i = 0; i < 4; ++i) {
+ w = (w >> 8) ^ this->table0_[w & 0xff];
+ }
+ return w;
+ };
+
+ l = combine_one_word(0, buf0);
+ l = combine_one_word(l, buf1);
+ l = combine_one_word(l, buf2);
+ l = combine_one_word(l, buf3);
+ }
+
+ // Process the last few bytes
+ while (p != e) {
+ step_one_byte();
+ }
+
+ *crc = l;
+}
+
+void CRC32::ExtendByZeroesImpl(uint32_t* crc, size_t length,
+ const uint32_t zeroes_table[256],
+ const uint32_t poly_table[256]) const {
+ if (length != 0) {
+ uint32_t l = *crc;
+ // For each ZEROES_BASE_LG bits in length
+ // (after the low-order bits have been removed)
+ // we lookup the appropriate polynomial in the zeroes_ array
+ // and do a polynomial long multiplication (mod the CRC polynomial)
+ // to extend the CRC by the appropriate number of bits.
+ for (int i = 0; length != 0;
+ i += ZEROES_BASE - 1, length >>= ZEROES_BASE_LG) {
+ int c = length & (ZEROES_BASE - 1); // pick next ZEROES_BASE_LG bits
+ if (c != 0) { // if they are not zero,
+ // multiply by entry in table
+ // Build a table to aid in multiplying 2 bits at a time.
+ // It takes too long to build tables for more bits.
+ uint64_t m = zeroes_table[c + i - 1];
+ m <<= 1;
+ uint64_t m2 = m << 1;
+ uint64_t mtab[4] = {0, m, m2, m2 ^ m};
+
+ // Do the multiply one byte at a time.
+ uint64_t result = 0;
+ for (int x = 0; x < 32; x += 8) {
+ // The carry-less multiply.
+ result ^= mtab[l & 3] ^ (mtab[(l >> 2) & 3] << 2) ^
+ (mtab[(l >> 4) & 3] << 4) ^ (mtab[(l >> 6) & 3] << 6);
+ l >>= 8;
+
+ // Reduce modulo the polynomial
+ result = (result >> 8) ^ poly_table[result & 0xff];
+ }
+ l = static_cast<uint32_t>(result);
+ }
+ }
+ *crc = l;
+ }
+}
+
+void CRC32::ExtendByZeroes(uint32_t* crc, size_t length) const {
+ return CRC32::ExtendByZeroesImpl(crc, length, zeroes_, table0_);
+}
+
+void CRC32::UnextendByZeroes(uint32_t* crc, size_t length) const {
+ // See the comment in CRC32::InitTables() for an explanation of the algorithm
+ // below.
+ *crc = ReverseBits(*crc);
+ ExtendByZeroesImpl(crc, length, reverse_zeroes_, reverse_table0_);
+ *crc = ReverseBits(*crc);
+}
+
+void CRC32::Scramble(uint32_t* crc) const {
+ // Rotate by near half the word size plus 1. See the scramble comment in
+ // crc_internal.h for an explanation.
+ constexpr int scramble_rotate = (32 / 2) + 1;
+ *crc = RotateRight<uint32_t>(static_cast<unsigned int>(*crc + kScrambleLo),
+ 32, scramble_rotate) &
+ MaskOfLength<uint32_t>(32);
+}
+
+void CRC32::Unscramble(uint32_t* crc) const {
+ constexpr int scramble_rotate = (32 / 2) + 1;
+ uint64_t rotated = RotateRight<uint32_t>(static_cast<unsigned int>(*crc), 32,
+ 32 - scramble_rotate);
+ *crc = (rotated - kScrambleLo) & MaskOfLength<uint32_t>(32);
+}
+
+// Constructor and destructor for base class CRC.
+CRC::~CRC() {}
+CRC::CRC() {}
+
+// The "constructor" for a CRC32C with a standard polynomial.
+CRC* CRC::Crc32c() {
+ static CRC* singleton = CRCImpl::NewInternal();
+ return singleton;
+}
+
+// This Concat implementation works for arbitrary polynomials.
+void CRC::Concat(uint32_t* px, uint32_t y, size_t ylen) {
+ // https://en.wikipedia.org/wiki/Mathematics_of_cyclic_redundancy_checks
+ // The CRC of a message M is the remainder of polynomial divison modulo G,
+ // where the coefficient arithmetic is performed modulo 2 (so +/- are XOR):
+ // R(x) = M(x) x**n (mod G)
+ // (n is the degree of G)
+ // In practice, we use an initial value A and a bitmask B to get
+ // R = (A ^ B)x**|M| ^ Mx**n ^ B (mod G)
+ // If M is the concatenation of two strings S and T, and Z is the string of
+ // len(T) 0s, then the remainder CRC(ST) can be expressed as:
+ // R = (A ^ B)x**|ST| ^ STx**n ^ B
+ // = (A ^ B)x**|SZ| ^ SZx**n ^ B ^ Tx**n
+ // = CRC(SZ) ^ Tx**n
+ // CRC(Z) = (A ^ B)x**|T| ^ B
+ // CRC(T) = (A ^ B)x**|T| ^ Tx**n ^ B
+ // So R = CRC(SZ) ^ CRC(Z) ^ CRC(T)
+ //
+ // And further, since CRC(SZ) = Extend(CRC(S), Z),
+ // CRC(SZ) ^ CRC(Z) = Extend(CRC(S) ^ CRC(''), Z).
+ uint32_t z;
+ uint32_t t;
+ Empty(&z);
+ t = *px ^ z;
+ ExtendByZeroes(&t, ylen);
+ *px = t ^ y;
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc.h
new file mode 100644
index 0000000000..72515b061d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc.h
@@ -0,0 +1,91 @@
+// 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_CRC_INTERNAL_CRC_H_
+#define ABSL_CRC_INTERNAL_CRC_H_
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+
+// This class implements CRCs (aka Rabin Fingerprints).
+// Treats the input as a polynomial with coefficients in Z(2),
+// and finds the remainder when divided by an primitive polynomial
+// of the appropriate length.
+
+// A polynomial is represented by the bit pattern formed by its coefficients,
+// but with the highest order bit not stored.
+// The highest degree coefficient is stored in the lowest numbered bit
+// in the lowest addressed byte. Thus, in what follows, the highest degree
+// coefficient that is stored is in the low order bit of "lo" or "*lo".
+
+// Hardware acceleration is used when available.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+class CRC {
+ public:
+ virtual ~CRC();
+
+ // Place the CRC of the empty string in "*crc"
+ virtual void Empty(uint32_t* crc) const = 0;
+
+ // If "*crc" is the CRC of bytestring A, place the CRC of
+ // the bytestring formed from the concatenation of A and the "length"
+ // bytes at "bytes" into "*crc".
+ virtual void Extend(uint32_t* crc, const void* bytes,
+ size_t length) const = 0;
+
+ // Equivalent to Extend(crc, bytes, length) where "bytes"
+ // points to an array of "length" zero bytes.
+ virtual void ExtendByZeroes(uint32_t* crc, size_t length) const = 0;
+
+ // Inverse opration of ExtendByZeroes. If `crc` is the CRC value of a string
+ // ending in `length` zero bytes, this returns a CRC value of that string
+ // with those zero bytes removed.
+ virtual void UnextendByZeroes(uint32_t* crc, size_t length) const = 0;
+
+ // If *px is the CRC (as defined by *crc) of some string X,
+ // and y is the CRC of some string Y that is ylen bytes long, set
+ // *px to the CRC of the concatenation of X followed by Y.
+ virtual void Concat(uint32_t* px, uint32_t y, size_t ylen);
+
+ // Apply a non-linear transformation to "*crc" so that
+ // it is safe to CRC the result with the same polynomial without
+ // any reduction of error-detection ability in the outer CRC.
+ // Unscramble() performs the inverse transformation.
+ // It is strongly recommended that CRCs be scrambled before storage or
+ // transmission, and unscrambled at the other end before futher manipulation.
+ virtual void Scramble(uint32_t* crc) const = 0;
+ virtual void Unscramble(uint32_t* crc) const = 0;
+
+ // Crc32c() returns the singleton implementation of CRC for the CRC32C
+ // polynomial. Returns a handle that MUST NOT be destroyed with delete.
+ static CRC* Crc32c();
+
+ protected:
+ CRC(); // Clients may not call constructor; use Crc32c() instead.
+
+ private:
+ CRC(const CRC&) = delete;
+ CRC& operator=(const CRC&) = delete;
+};
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h
new file mode 100644
index 0000000000..fb64398631
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32_x86_arm_combined_simd.h
@@ -0,0 +1,269 @@
+// 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_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
+#define ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+
+// -------------------------------------------------------------------------
+// Many x86 and ARM machines have CRC acceleration hardware.
+// We can do a faster version of Extend() on such machines.
+// We define a translation layer for both x86 and ARM for the ease of use and
+// most performance gains.
+
+// This implementation requires 64-bit CRC instructions (part of SSE 4.2) and
+// PCLMULQDQ instructions. 32-bit builds with SSE 4.2 do exist, so the
+// __x86_64__ condition is necessary.
+#if defined(__x86_64__) && defined(__SSE4_2__) && defined(__PCLMUL__)
+
+#include <x86intrin.h>
+#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD
+
+#elif defined(_MSC_VER) && defined(__AVX__)
+
+// MSVC AVX (/arch:AVX) implies SSE 4.2 and PCLMULQDQ.
+#include <intrin.h>
+#define ABSL_CRC_INTERNAL_HAVE_X86_SIMD
+
+#elif defined(__aarch64__) && defined(__LITTLE_ENDIAN__) && \
+ defined(__ARM_FEATURE_CRC32) && defined(ABSL_INTERNAL_HAVE_ARM_NEON) && \
+ defined(__ARM_FEATURE_CRYPTO)
+
+#include <arm_acle.h>
+#include <arm_neon.h>
+#define ABSL_CRC_INTERNAL_HAVE_ARM_SIMD
+
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \
+ defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
+
+#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)
+using V128 = uint64x2_t;
+#else
+using V128 = __m128i;
+#endif
+
+// Starting with the initial value in |crc|, accumulates a CRC32 value for
+// unsigned integers of different sizes.
+uint32_t CRC32_u8(uint32_t crc, uint8_t v);
+
+uint32_t CRC32_u16(uint32_t crc, uint16_t v);
+
+uint32_t CRC32_u32(uint32_t crc, uint32_t v);
+
+uint32_t CRC32_u64(uint32_t crc, uint64_t v);
+
+// Loads 128 bits of integer data. |src| must be 16-byte aligned.
+V128 V128_Load(const V128* src);
+
+// Load 128 bits of integer data. |src| does not need to be aligned.
+V128 V128_LoadU(const V128* src);
+
+// Polynomially multiplies the high 64 bits of |l| and |r|.
+V128 V128_PMulHi(const V128 l, const V128 r);
+
+// Polynomially multiplies the low 64 bits of |l| and |r|.
+V128 V128_PMulLow(const V128 l, const V128 r);
+
+// Polynomially multiplies the low 64 bits of |r| and high 64 bits of |l|.
+V128 V128_PMul01(const V128 l, const V128 r);
+
+// Polynomially multiplies the low 64 bits of |l| and high 64 bits of |r|.
+V128 V128_PMul10(const V128 l, const V128 r);
+
+// Produces a XOR operation of |l| and |r|.
+V128 V128_Xor(const V128 l, const V128 r);
+
+// Produces an AND operation of |l| and |r|.
+V128 V128_And(const V128 l, const V128 r);
+
+// Sets two 64 bit integers to one 128 bit vector. The order is reverse.
+// dst[63:0] := |r|
+// dst[127:64] := |l|
+V128 V128_From2x64(const uint64_t l, const uint64_t r);
+
+// Shift |l| right by |imm| bytes while shifting in zeros.
+template <int imm>
+V128 V128_ShiftRight(const V128 l);
+
+// Extracts a 32-bit integer from |l|, selected with |imm|.
+template <int imm>
+int V128_Extract32(const V128 l);
+
+// Extracts the low 64 bits from V128.
+int64_t V128_Low64(const V128 l);
+
+// Left-shifts packed 64-bit integers in l by r.
+V128 V128_ShiftLeft64(const V128 l, const V128 r);
+
+#endif
+
+#if defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
+
+inline uint32_t CRC32_u8(uint32_t crc, uint8_t v) {
+ return _mm_crc32_u8(crc, v);
+}
+
+inline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {
+ return _mm_crc32_u16(crc, v);
+}
+
+inline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {
+ return _mm_crc32_u32(crc, v);
+}
+
+inline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {
+ return static_cast<uint32_t>(_mm_crc32_u64(crc, v));
+}
+
+inline V128 V128_Load(const V128* src) { return _mm_load_si128(src); }
+
+inline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); }
+
+inline V128 V128_PMulHi(const V128 l, const V128 r) {
+ return _mm_clmulepi64_si128(l, r, 0x11);
+}
+
+inline V128 V128_PMulLow(const V128 l, const V128 r) {
+ return _mm_clmulepi64_si128(l, r, 0x00);
+}
+
+inline V128 V128_PMul01(const V128 l, const V128 r) {
+ return _mm_clmulepi64_si128(l, r, 0x01);
+}
+
+inline V128 V128_PMul10(const V128 l, const V128 r) {
+ return _mm_clmulepi64_si128(l, r, 0x10);
+}
+
+inline V128 V128_Xor(const V128 l, const V128 r) { return _mm_xor_si128(l, r); }
+
+inline V128 V128_And(const V128 l, const V128 r) { return _mm_and_si128(l, r); }
+
+inline V128 V128_From2x64(const uint64_t l, const uint64_t r) {
+ return _mm_set_epi64x(static_cast<int64_t>(l), static_cast<int64_t>(r));
+}
+
+template <int imm>
+inline V128 V128_ShiftRight(const V128 l) {
+ return _mm_srli_si128(l, imm);
+}
+
+template <int imm>
+inline int V128_Extract32(const V128 l) {
+ return _mm_extract_epi32(l, imm);
+}
+
+inline int64_t V128_Low64(const V128 l) { return _mm_cvtsi128_si64(l); }
+
+inline V128 V128_ShiftLeft64(const V128 l, const V128 r) {
+ return _mm_sll_epi64(l, r);
+}
+
+#elif defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD)
+
+inline uint32_t CRC32_u8(uint32_t crc, uint8_t v) { return __crc32cb(crc, v); }
+
+inline uint32_t CRC32_u16(uint32_t crc, uint16_t v) {
+ return __crc32ch(crc, v);
+}
+
+inline uint32_t CRC32_u32(uint32_t crc, uint32_t v) {
+ return __crc32cw(crc, v);
+}
+
+inline uint32_t CRC32_u64(uint32_t crc, uint64_t v) {
+ return __crc32cd(crc, v);
+}
+
+inline V128 V128_Load(const V128* src) {
+ return vld1q_u64(reinterpret_cast<const uint64_t*>(src));
+}
+
+inline V128 V128_LoadU(const V128* src) {
+ return vld1q_u64(reinterpret_cast<const uint64_t*>(src));
+}
+
+// Using inline assembly as clang does not generate the pmull2 instruction and
+// performance drops by 15-20%.
+// TODO(b/193678732): Investigate why the compiler decides not to generate
+// such instructions and why it becomes so much worse.
+inline V128 V128_PMulHi(const V128 l, const V128 r) {
+ uint64x2_t res;
+ __asm__ __volatile__("pmull2 %0.1q, %1.2d, %2.2d \n\t"
+ : "=w"(res)
+ : "w"(l), "w"(r));
+ return res;
+}
+
+inline V128 V128_PMulLow(const V128 l, const V128 r) {
+ return reinterpret_cast<V128>(vmull_p64(
+ reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(l))),
+ reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(r)))));
+}
+
+inline V128 V128_PMul01(const V128 l, const V128 r) {
+ return reinterpret_cast<V128>(vmull_p64(
+ reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(l))),
+ reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(r)))));
+}
+
+inline V128 V128_PMul10(const V128 l, const V128 r) {
+ return reinterpret_cast<V128>(vmull_p64(
+ reinterpret_cast<poly64_t>(vget_low_p64(vreinterpretq_p64_u64(l))),
+ reinterpret_cast<poly64_t>(vget_high_p64(vreinterpretq_p64_u64(r)))));
+}
+
+inline V128 V128_Xor(const V128 l, const V128 r) { return veorq_u64(l, r); }
+
+inline V128 V128_And(const V128 l, const V128 r) { return vandq_u64(l, r); }
+
+inline V128 V128_From2x64(const uint64_t l, const uint64_t r) {
+ return vcombine_u64(vcreate_u64(r), vcreate_u64(l));
+}
+
+template <int imm>
+inline V128 V128_ShiftRight(const V128 l) {
+ return vreinterpretq_u64_s8(
+ vextq_s8(vreinterpretq_s8_u64(l), vdupq_n_s8(0), imm));
+}
+
+template <int imm>
+inline int V128_Extract32(const V128 l) {
+ return vgetq_lane_s32(vreinterpretq_s32_u64(l), imm);
+}
+
+inline int64_t V128_Low64(const V128 l) {
+ return vgetq_lane_s64(vreinterpretq_s64_u64(l), 0);
+}
+
+inline V128 V128_ShiftLeft64(const V128 l, const V128 r) {
+ return vshlq_u64(l, vreinterpretq_s64_u64(r));
+}
+
+#endif
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC32_X86_ARM_COMBINED_SIMD_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c.h
new file mode 100644
index 0000000000..34027c55e4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c.h
@@ -0,0 +1,39 @@
+// 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_CRC_INTERNAL_CRC32C_H_
+#define ABSL_CRC_INTERNAL_CRC32C_H_
+
+#include "absl/base/config.h"
+#include "absl/crc/crc32c.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+// Modifies a CRC32 value by removing `length` bytes with a value of 0 from
+// the end of the string.
+//
+// This is the inverse operation of ExtendCrc32cByZeroes().
+//
+// This operation has a runtime cost of O(log(`length`))
+//
+// Internal implementation detail, exposed for testing only.
+crc32c_t UnextendCrc32cByZeroes(crc32c_t initial_crc, size_t length);
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC32C_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c_inline.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c_inline.h
new file mode 100644
index 0000000000..6236c10b3b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc32c_inline.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.
+
+#ifndef ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
+#define ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
+
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+#include "absl/crc/internal/crc32_x86_arm_combined_simd.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+// CRC32C implementation optimized for small inputs.
+// Either computes crc and return true, or if there is
+// no hardware support does nothing and returns false.
+inline bool ExtendCrc32cInline(uint32_t* crc, const char* p, size_t n) {
+#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \
+ defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
+ constexpr uint32_t kCrc32Xor = 0xffffffffU;
+ *crc ^= kCrc32Xor;
+ if (n & 1) {
+ *crc = CRC32_u8(*crc, static_cast<uint8_t>(*p));
+ n--;
+ p++;
+ }
+ if (n & 2) {
+ *crc = CRC32_u16(*crc, absl::little_endian::Load16(p));
+ n -= 2;
+ p += 2;
+ }
+ if (n & 4) {
+ *crc = CRC32_u32(*crc, absl::little_endian::Load32(p));
+ n -= 4;
+ p += 4;
+ }
+ while (n) {
+ *crc = CRC32_u64(*crc, absl::little_endian::Load64(p));
+ n -= 8;
+ p += 8;
+ }
+ *crc ^= kCrc32Xor;
+ return true;
+#else
+ // No hardware support, signal the need to fallback.
+ static_cast<void>(crc);
+ static_cast<void>(p);
+ static_cast<void>(n);
+ return false;
+#endif // defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) ||
+ // defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC32C_INLINE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc
new file mode 100644
index 0000000000..d0be0ddd37
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc
@@ -0,0 +1,130 @@
+// 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/crc/internal/crc_cord_state.h"
+
+#include <cassert>
+
+#include "absl/base/config.h"
+#include "absl/numeric/bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+CrcCordState::RefcountedRep* CrcCordState::RefSharedEmptyRep() {
+ static CrcCordState::RefcountedRep* empty = new CrcCordState::RefcountedRep;
+
+ assert(empty->count.load(std::memory_order_relaxed) >= 1);
+ assert(empty->rep.removed_prefix.length == 0);
+ assert(empty->rep.prefix_crc.empty());
+
+ Ref(empty);
+ return empty;
+}
+
+CrcCordState::CrcCordState() : refcounted_rep_(new RefcountedRep) {}
+
+CrcCordState::CrcCordState(const CrcCordState& other)
+ : refcounted_rep_(other.refcounted_rep_) {
+ Ref(refcounted_rep_);
+}
+
+CrcCordState::CrcCordState(CrcCordState&& other)
+ : refcounted_rep_(other.refcounted_rep_) {
+ // Make `other` valid for use after move.
+ other.refcounted_rep_ = RefSharedEmptyRep();
+}
+
+CrcCordState& CrcCordState::operator=(const CrcCordState& other) {
+ if (this != &other) {
+ Unref(refcounted_rep_);
+ refcounted_rep_ = other.refcounted_rep_;
+ Ref(refcounted_rep_);
+ }
+ return *this;
+}
+
+CrcCordState& CrcCordState::operator=(CrcCordState&& other) {
+ if (this != &other) {
+ Unref(refcounted_rep_);
+ refcounted_rep_ = other.refcounted_rep_;
+ // Make `other` valid for use after move.
+ other.refcounted_rep_ = RefSharedEmptyRep();
+ }
+ return *this;
+}
+
+CrcCordState::~CrcCordState() {
+ Unref(refcounted_rep_);
+}
+
+crc32c_t CrcCordState::Checksum() const {
+ if (rep().prefix_crc.empty()) {
+ return absl::crc32c_t{0};
+ }
+ if (IsNormalized()) {
+ return rep().prefix_crc.back().crc;
+ }
+ return absl::RemoveCrc32cPrefix(
+ rep().removed_prefix.crc, rep().prefix_crc.back().crc,
+ rep().prefix_crc.back().length - rep().removed_prefix.length);
+}
+
+CrcCordState::PrefixCrc CrcCordState::NormalizedPrefixCrcAtNthChunk(
+ size_t n) const {
+ assert(n < NumChunks());
+ if (IsNormalized()) {
+ return rep().prefix_crc[n];
+ }
+ size_t length = rep().prefix_crc[n].length - rep().removed_prefix.length;
+ return PrefixCrc(length,
+ absl::RemoveCrc32cPrefix(rep().removed_prefix.crc,
+ rep().prefix_crc[n].crc, length));
+}
+
+void CrcCordState::Normalize() {
+ if (IsNormalized() || rep().prefix_crc.empty()) {
+ return;
+ }
+
+ Rep* r = mutable_rep();
+ for (auto& prefix_crc : r->prefix_crc) {
+ size_t remaining = prefix_crc.length - r->removed_prefix.length;
+ prefix_crc.crc = absl::RemoveCrc32cPrefix(r->removed_prefix.crc,
+ prefix_crc.crc, remaining);
+ prefix_crc.length = remaining;
+ }
+ r->removed_prefix = PrefixCrc();
+}
+
+void CrcCordState::Poison() {
+ Rep* rep = mutable_rep();
+ if (NumChunks() > 0) {
+ for (auto& prefix_crc : rep->prefix_crc) {
+ // This is basically CRC32::Scramble().
+ uint32_t crc = static_cast<uint32_t>(prefix_crc.crc);
+ crc += 0x2e76e41b;
+ crc = absl::rotr(crc, 17);
+ prefix_crc.crc = crc32c_t{crc};
+ }
+ } else {
+ // Add a fake corrupt chunk.
+ rep->prefix_crc.push_back(PrefixCrc(0, crc32c_t{1}));
+ }
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.h
new file mode 100644
index 0000000000..d305424ce6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.h
@@ -0,0 +1,159 @@
+// 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_CRC_INTERNAL_CRC_CORD_STATE_H_
+#define ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_
+
+#include <atomic>
+#include <cstddef>
+#include <deque>
+
+#include "absl/base/config.h"
+#include "absl/crc/crc32c.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+// CrcCordState is a copy-on-write class that holds the chunked CRC32C data
+// that allows CrcCord to perform efficient substring operations. CrcCordState
+// is used as a member variable in CrcCord. When a CrcCord is converted to a
+// Cord, the CrcCordState is shallow-copied into the root node of the Cord. If
+// the converted Cord is modified outside of CrcCord, the CrcCordState is
+// discarded from the Cord. If the Cord is converted back to a CrcCord, and the
+// Cord is still carrying the CrcCordState in its root node, the CrcCord can
+// re-use the CrcCordState, making the construction of the CrcCord cheap.
+//
+// CrcCordState does not try to encapsulate the CRC32C state (CrcCord requires
+// knowledge of how CrcCordState represents the CRC32C state). It does
+// encapsulate the copy-on-write nature of the state.
+class CrcCordState {
+ public:
+ // Constructors.
+ CrcCordState();
+ CrcCordState(const CrcCordState&);
+ CrcCordState(CrcCordState&&);
+
+ // Destructor. Atomically unreferences the data.
+ ~CrcCordState();
+
+ // Copy and move operators.
+ CrcCordState& operator=(const CrcCordState&);
+ CrcCordState& operator=(CrcCordState&&);
+
+ // A (length, crc) pair.
+ struct PrefixCrc {
+ PrefixCrc() = default;
+ PrefixCrc(size_t length_arg, absl::crc32c_t crc_arg)
+ : length(length_arg), crc(crc_arg) {}
+
+ size_t length = 0;
+
+ // TODO(absl-team): Memory stomping often zeros out memory. If this struct
+ // gets overwritten, we could end up with {0, 0}, which is the correct CRC
+ // for a string of length 0. Consider storing a scrambled value and
+ // unscrambling it before verifying it.
+ absl::crc32c_t crc = absl::crc32c_t{0};
+ };
+
+ // The representation of the chunked CRC32C data.
+ struct Rep {
+ // `removed_prefix` is the crc and length of any prefix that has been
+ // removed from the Cord (for example, by calling
+ // `CrcCord::RemovePrefix()`). To get the checkum of any prefix of the cord,
+ // this value must be subtracted from `prefix_crc`. See `Checksum()` for an
+ // example.
+ //
+ // CrcCordState is said to be "normalized" if removed_prefix.length == 0.
+ PrefixCrc removed_prefix;
+
+ // A deque of (length, crc) pairs, representing length and crc of a prefix
+ // of the Cord, before removed_prefix has been subtracted. The lengths of
+ // the prefixes are stored in increasing order. If the Cord is not empty,
+ // the last value in deque is the contains the CRC32C of the entire Cord
+ // when removed_prefix is subtracted from it.
+ std::deque<PrefixCrc> prefix_crc;
+ };
+
+ // Returns a reference to the representation of the chunked CRC32C data.
+ const Rep& rep() const { return refcounted_rep_->rep; }
+
+ // Returns a mutable reference to the representation of the chunked CRC32C
+ // data. Calling this function will copy the data if another instance also
+ // holds a reference to the data, so it is important to call rep() instead if
+ // the data may not be mutated.
+ Rep* mutable_rep() {
+ if (refcounted_rep_->count.load(std::memory_order_acquire) != 1) {
+ RefcountedRep* copy = new RefcountedRep;
+ copy->rep = refcounted_rep_->rep;
+ Unref(refcounted_rep_);
+ refcounted_rep_ = copy;
+ }
+ return &refcounted_rep_->rep;
+ }
+
+ // Returns the CRC32C of the entire Cord.
+ absl::crc32c_t Checksum() const;
+
+ // Returns true if the chunked CRC32C cached is normalized.
+ bool IsNormalized() const { return rep().removed_prefix.length == 0; }
+
+ // Normalizes the chunked CRC32C checksum cache by substracting any removed
+ // prefix from the chunks.
+ void Normalize();
+
+ // Returns the number of cached chunks.
+ size_t NumChunks() const { return rep().prefix_crc.size(); }
+
+ // Helper that returns the (length, crc) of the `n`-th cached chunked.
+ PrefixCrc NormalizedPrefixCrcAtNthChunk(size_t n) const;
+
+ // Poisons all chunks to so that Checksum() will likely be incorrect with high
+ // probability.
+ void Poison();
+
+ private:
+ struct RefcountedRep {
+ std::atomic<int32_t> count{1};
+ Rep rep;
+ };
+
+ // Adds a reference to the shared global empty `RefcountedRep`, and returns a
+ // pointer to the `RefcountedRep`. This is an optimization to avoid unneeded
+ // allocations when the allocation is unlikely to ever be used. The returned
+ // pointer can be `Unref()`ed when it is no longer needed. Since the returned
+ // instance will always have a reference counter greater than 1, attempts to
+ // modify it (by calling `mutable_rep()`) will create a new unshared copy.
+ static RefcountedRep* RefSharedEmptyRep();
+
+ static void Ref(RefcountedRep* r) {
+ assert(r != nullptr);
+ r->count.fetch_add(1, std::memory_order_relaxed);
+ }
+
+ static void Unref(RefcountedRep* r) {
+ assert(r != nullptr);
+ if (r->count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
+ delete r;
+ }
+ }
+
+ RefcountedRep* refcounted_rep_;
+};
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC_CORD_STATE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_internal.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_internal.h
new file mode 100644
index 0000000000..0611b383e4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_internal.h
@@ -0,0 +1,179 @@
+// 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_CRC_INTERNAL_CRC_INTERNAL_H_
+#define ABSL_CRC_INTERNAL_CRC_INTERNAL_H_
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/crc/internal/crc.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace crc_internal {
+
+// Prefetch constants used in some Extend() implementations
+constexpr int kPrefetchHorizon = ABSL_CACHELINE_SIZE * 4; // Prefetch this far
+// Shorter prefetch distance for smaller buffers
+constexpr int kPrefetchHorizonMedium = ABSL_CACHELINE_SIZE * 1;
+static_assert(kPrefetchHorizon >= 64, "CRCPrefetchHorizon less than loop len");
+
+// We require the Scramble() function:
+// - to be reversible (Unscramble() must exist)
+// - to be non-linear in the polynomial's Galois field (so the CRC of a
+// scrambled CRC is not linearly affected by the scrambled CRC, even if
+// using the same polynomial)
+// - not to be its own inverse. Preferably, if X=Scramble^N(X) and N!=0, then
+// N is large.
+// - to be fast.
+// - not to change once defined.
+// We introduce non-linearity in two ways:
+// Addition of a constant.
+// - The carries introduce non-linearity; we use bits of an irrational
+// (phi) to make it unlikely that we introduce no carries.
+// Rotate by a constant number of bits.
+// - We use floor(degree/2)+1, which does not divide the degree, and
+// splits the bits nearly evenly, which makes it less likely the
+// halves will be the same or one will be all zeroes.
+// We do both things to improve the chances of non-linearity in the face of
+// bit patterns with low numbers of bits set, while still being fast.
+// Below is the constant that we add. The bits are the first 128 bits of the
+// fractional part of phi, with a 1 ored into the bottom bit to maximize the
+// cycle length of repeated adds.
+constexpr uint64_t kScrambleHi = (static_cast<uint64_t>(0x4f1bbcdcU) << 32) |
+ static_cast<uint64_t>(0xbfa53e0aU);
+constexpr uint64_t kScrambleLo = (static_cast<uint64_t>(0xf9ce6030U) << 32) |
+ static_cast<uint64_t>(0x2e76e41bU);
+
+class CRCImpl : public CRC { // Implemention of the abstract class CRC
+ public:
+ using Uint32By256 = uint32_t[256];
+
+ CRCImpl() {}
+ ~CRCImpl() override = default;
+
+ // The internal version of CRC::New().
+ static CRCImpl* NewInternal();
+
+ void Empty(uint32_t* crc) const override;
+
+ // Fill in a table for updating a CRC by one word of 'word_size' bytes
+ // [last_lo, last_hi] contains the answer if the last bit in the word
+ // is set.
+ static void FillWordTable(uint32_t poly, uint32_t last, int word_size,
+ Uint32By256* t);
+
+ // Build the table for extending by zeroes, returning the number of entries.
+ // For a in {1, 2, ..., ZEROES_BASE-1}, b in {0, 1, 2, 3, ...},
+ // entry j=a-1+(ZEROES_BASE-1)*b
+ // contains a polynomial Pi such that multiplying
+ // a CRC by Pi mod P, where P is the CRC polynomial, is equivalent to
+ // appending a*2**(ZEROES_BASE_LG*b) zero bytes to the original string.
+ static int FillZeroesTable(uint32_t poly, Uint32By256* t);
+
+ virtual void InitTables() = 0;
+
+ private:
+ CRCImpl(const CRCImpl&) = delete;
+ CRCImpl& operator=(const CRCImpl&) = delete;
+};
+
+// This is the 32-bit implementation. It handles all sizes from 8 to 32.
+class CRC32 : public CRCImpl {
+ public:
+ CRC32() {}
+ ~CRC32() override {}
+
+ void Extend(uint32_t* crc, const void* bytes, size_t length) const override;
+ void ExtendByZeroes(uint32_t* crc, size_t length) const override;
+ void Scramble(uint32_t* crc) const override;
+ void Unscramble(uint32_t* crc) const override;
+ void UnextendByZeroes(uint32_t* crc, size_t length) const override;
+
+ void InitTables() override;
+
+ private:
+ // Common implementation guts for ExtendByZeroes and UnextendByZeroes().
+ //
+ // zeroes_table is a table as returned by FillZeroesTable(), containing
+ // polynomials representing CRCs of strings-of-zeros of various lenghts,
+ // and which can be combined by polynomial multiplication. poly_table is
+ // a table of CRC byte extension values. These tables are determined by
+ // the generator polynomial.
+ //
+ // These will be set to reverse_zeroes_ and reverse_table0_ for Unextend, and
+ // CRC32::zeroes_ and CRC32::table0_ for Extend.
+ void ExtendByZeroesImpl(uint32_t* crc, size_t length,
+ const uint32_t zeroes_table[256],
+ const uint32_t poly_table[256]) const;
+
+ uint32_t table0_[256]; // table of byte extensions
+ uint32_t zeroes_[256]; // table of zero extensions
+
+ // table of 4-byte extensions shifted by 12 bytes of zeroes
+ uint32_t table_[4][256];
+
+ // Reverse lookup tables, using the alternate polynomial used by
+ // UnextendByZeroes().
+ uint32_t reverse_table0_[256]; // table of reverse byte extensions
+ uint32_t reverse_zeroes_[256]; // table of reverse zero extensions
+
+ CRC32(const CRC32&) = delete;
+ CRC32& operator=(const CRC32&) = delete;
+};
+
+// Helpers
+
+// Return a bit mask containing len 1-bits.
+// Requires 0 < len <= sizeof(T)
+template <typename T>
+T MaskOfLength(int len) {
+ // shift 2 by len-1 rather than 1 by len because shifts of wordsize
+ // are undefined.
+ return (T(2) << (len - 1)) - 1;
+}
+
+// Rotate low-order "width" bits of "in" right by "r" bits,
+// setting other bits in word to arbitrary values.
+template <typename T>
+T RotateRight(T in, int width, int r) {
+ return (in << (width - r)) | ((in >> r) & MaskOfLength<T>(width - r));
+}
+
+// RoundUp<N>(p) returns the lowest address >= p aligned to an N-byte
+// boundary. Requires that N is a power of 2.
+template <int alignment>
+const uint8_t* RoundUp(const uint8_t* p) {
+ static_assert((alignment & (alignment - 1)) == 0, "alignment is not 2^n");
+ constexpr uintptr_t mask = alignment - 1;
+ const uintptr_t as_uintptr = reinterpret_cast<uintptr_t>(p);
+ return reinterpret_cast<const uint8_t*>((as_uintptr + mask) & ~mask);
+}
+
+// Return a newly created CRC32AcceleratedX86ARMCombined if we can use Intel's
+// or ARM's CRC acceleration for a given polynomial. Return nullptr otherwise.
+CRCImpl* TryNewCRC32AcceleratedX86ARMCombined();
+
+// Return all possible hardware accelerated implementations. For testing only.
+std::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll();
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC_INTERNAL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h
new file mode 100644
index 0000000000..4909d43366
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy.h
@@ -0,0 +1,119 @@
+// 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_CRC_INTERNAL_CRC_MEMCPY_H_
+#define ABSL_CRC_INTERNAL_CRC_MEMCPY_H_
+
+#include <cstddef>
+#include <memory>
+
+#include "absl/base/config.h"
+#include "absl/crc/crc32c.h"
+
+// Defined if the class AcceleratedCrcMemcpyEngine exists.
+#if defined(__x86_64__) && defined(__SSE4_2__)
+#define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1
+#elif defined(_MSC_VER) && defined(__AVX__)
+#define ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE 1
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+class CrcMemcpyEngine {
+ public:
+ virtual ~CrcMemcpyEngine() = default;
+
+ virtual crc32c_t Compute(void* __restrict dst, const void* __restrict src,
+ std::size_t length, crc32c_t initial_crc) const = 0;
+
+ protected:
+ CrcMemcpyEngine() = default;
+};
+
+class CrcMemcpy {
+ public:
+ static crc32c_t CrcAndCopy(void* __restrict dst, const void* __restrict src,
+ std::size_t length,
+ crc32c_t initial_crc = crc32c_t{0},
+ bool non_temporal = false) {
+ static const ArchSpecificEngines engines = GetArchSpecificEngines();
+ auto* engine = non_temporal ? engines.non_temporal : engines.temporal;
+ return engine->Compute(dst, src, length, initial_crc);
+ }
+
+ // For testing only: get an architecture-specific engine for tests.
+ static std::unique_ptr<CrcMemcpyEngine> GetTestEngine(int vector,
+ int integer);
+
+ private:
+ struct ArchSpecificEngines {
+ CrcMemcpyEngine* temporal;
+ CrcMemcpyEngine* non_temporal;
+ };
+
+ static ArchSpecificEngines GetArchSpecificEngines();
+};
+
+// Fallback CRC-memcpy engine.
+class FallbackCrcMemcpyEngine : public CrcMemcpyEngine {
+ public:
+ FallbackCrcMemcpyEngine() = default;
+ FallbackCrcMemcpyEngine(const FallbackCrcMemcpyEngine&) = delete;
+ FallbackCrcMemcpyEngine operator=(const FallbackCrcMemcpyEngine&) = delete;
+
+ crc32c_t Compute(void* __restrict dst, const void* __restrict src,
+ std::size_t length, crc32c_t initial_crc) const override;
+};
+
+// CRC Non-Temporal-Memcpy engine.
+class CrcNonTemporalMemcpyEngine : public CrcMemcpyEngine {
+ public:
+ CrcNonTemporalMemcpyEngine() = default;
+ CrcNonTemporalMemcpyEngine(const CrcNonTemporalMemcpyEngine&) = delete;
+ CrcNonTemporalMemcpyEngine operator=(const CrcNonTemporalMemcpyEngine&) =
+ delete;
+
+ crc32c_t Compute(void* __restrict dst, const void* __restrict src,
+ std::size_t length, crc32c_t initial_crc) const override;
+};
+
+// CRC Non-Temporal-Memcpy AVX engine.
+class CrcNonTemporalMemcpyAVXEngine : public CrcMemcpyEngine {
+ public:
+ CrcNonTemporalMemcpyAVXEngine() = default;
+ CrcNonTemporalMemcpyAVXEngine(const CrcNonTemporalMemcpyAVXEngine&) = delete;
+ CrcNonTemporalMemcpyAVXEngine operator=(
+ const CrcNonTemporalMemcpyAVXEngine&) = delete;
+
+ crc32c_t Compute(void* __restrict dst, const void* __restrict src,
+ std::size_t length, crc32c_t initial_crc) const override;
+};
+
+// Copy source to destination and return the CRC32C of the data copied. If an
+// accelerated version is available, use the accelerated version, otherwise use
+// the generic fallback version.
+inline crc32c_t Crc32CAndCopy(void* __restrict dst, const void* __restrict src,
+ std::size_t length,
+ crc32c_t initial_crc = crc32c_t{0},
+ bool non_temporal = false) {
+ return CrcMemcpy::CrcAndCopy(dst, src, length, initial_crc, non_temporal);
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_CRC_MEMCPY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc
new file mode 100644
index 0000000000..15b4b05594
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.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 <cstdint>
+#include <memory>
+
+#include "absl/base/config.h"
+#include "absl/crc/crc32c.h"
+#include "absl/crc/internal/crc_memcpy.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+absl::crc32c_t FallbackCrcMemcpyEngine::Compute(void* __restrict dst,
+ const void* __restrict src,
+ std::size_t length,
+ crc32c_t initial_crc) const {
+ constexpr size_t kBlockSize = 8192;
+ absl::crc32c_t crc = initial_crc;
+
+ const char* src_bytes = reinterpret_cast<const char*>(src);
+ char* dst_bytes = reinterpret_cast<char*>(dst);
+
+ // Copy + CRC loop - run 8k chunks until we are out of full chunks. CRC
+ // then copy was found to be slightly more efficient in our test cases.
+ std::size_t offset = 0;
+ for (; offset + kBlockSize < length; offset += kBlockSize) {
+ crc = absl::ExtendCrc32c(crc,
+ absl::string_view(src_bytes + offset, kBlockSize));
+ memcpy(dst_bytes + offset, src_bytes + offset, kBlockSize);
+ }
+
+ // Save some work if length is 0.
+ if (offset < length) {
+ std::size_t final_copy_size = length - offset;
+ crc = absl::ExtendCrc32c(
+ crc, absl::string_view(src_bytes + offset, final_copy_size));
+ memcpy(dst_bytes + offset, src_bytes + offset, final_copy_size);
+ }
+
+ return crc;
+}
+
+// Compile the following only if we don't have
+#ifndef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE
+
+CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() {
+ CrcMemcpy::ArchSpecificEngines engines;
+ engines.temporal = new FallbackCrcMemcpyEngine();
+ engines.non_temporal = new FallbackCrcMemcpyEngine();
+ return engines;
+}
+
+std::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int /*vector*/,
+ int /*integer*/) {
+ return std::make_unique<FallbackCrcMemcpyEngine>();
+}
+
+#endif // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
new file mode 100644
index 0000000000..66f784de45
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
@@ -0,0 +1,434 @@
+// 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.
+
+// Simultaneous memcopy and CRC-32C for x86-64. Uses integer registers because
+// XMM registers do not support the CRC instruction (yet). While copying,
+// compute the running CRC of the data being copied.
+//
+// It is assumed that any CPU running this code has SSE4.2 instructions
+// available (for CRC32C). This file will do nothing if that is not true.
+//
+// The CRC instruction has a 3-byte latency, and we are stressing the ALU ports
+// here (unlike a traditional memcopy, which has almost no ALU use), so we will
+// need to copy in such a way that the CRC unit is used efficiently. We have two
+// regimes in this code:
+// 1. For operations of size < kCrcSmallSize, do the CRC then the memcpy
+// 2. For operations of size > kCrcSmallSize:
+// a) compute an initial CRC + copy on a small amount of data to align the
+// destination pointer on a 16-byte boundary.
+// b) Split the data into 3 main regions and a tail (smaller than 48 bytes)
+// c) Do the copy and CRC of the 3 main regions, interleaving (start with
+// full cache line copies for each region, then move to single 16 byte
+// pieces per region).
+// d) Combine the CRCs with CRC32C::Concat.
+// e) Copy the tail and extend the CRC with the CRC of the tail.
+// This method is not ideal for op sizes between ~1k and ~8k because CRC::Concat
+// takes a significant amount of time. A medium-sized approach could be added
+// using 3 CRCs over fixed-size blocks where the zero-extensions required for
+// CRC32C::Concat can be precomputed.
+
+#ifdef __SSE4_2__
+#include <immintrin.h>
+#endif
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#include <array>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/dynamic_annotations.h"
+#include "absl/base/internal/prefetch.h"
+#include "absl/base/optimization.h"
+#include "absl/crc/crc32c.h"
+#include "absl/crc/internal/cpu_detect.h"
+#include "absl/crc/internal/crc_memcpy.h"
+#include "absl/strings/string_view.h"
+
+#ifdef ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+namespace {
+
+inline crc32c_t ShortCrcCopy(char* dst, const char* src, std::size_t length,
+ crc32c_t crc) {
+ // Small copy: just go 1 byte at a time: being nice to the branch predictor
+ // is more important here than anything else
+ uint32_t crc_uint32 = static_cast<uint32_t>(crc);
+ for (std::size_t i = 0; i < length; i++) {
+ uint8_t data = *reinterpret_cast<const uint8_t*>(src);
+ crc_uint32 = _mm_crc32_u8(crc_uint32, data);
+ *reinterpret_cast<uint8_t*>(dst) = data;
+ ++src;
+ ++dst;
+ }
+ return crc32c_t{crc_uint32};
+}
+
+constexpr size_t kIntLoadsPerVec = sizeof(__m128i) / sizeof(uint64_t);
+
+// Common function for copying the tails of multiple large regions.
+template <size_t vec_regions, size_t int_regions>
+inline void LargeTailCopy(crc32c_t* crcs, char** dst, const char** src,
+ size_t region_size, size_t copy_rounds) {
+ std::array<__m128i, vec_regions> data;
+ std::array<uint64_t, kIntLoadsPerVec * int_regions> int_data;
+
+ while (copy_rounds > 0) {
+ for (size_t i = 0; i < vec_regions; i++) {
+ size_t region = i;
+
+ auto* vsrc =
+ reinterpret_cast<const __m128i*>(*src + region_size * region);
+ auto* vdst = reinterpret_cast<__m128i*>(*dst + region_size * region);
+
+ // Load the blocks, unaligned
+ data[i] = _mm_loadu_si128(vsrc);
+
+ // Store the blocks, aligned
+ _mm_store_si128(vdst, data[i]);
+
+ // Compute the running CRC
+ crcs[region] = crc32c_t{static_cast<uint32_t>(
+ _mm_crc32_u64(static_cast<uint32_t>(crcs[region]),
+ static_cast<uint64_t>(_mm_extract_epi64(data[i], 0))))};
+ crcs[region] = crc32c_t{static_cast<uint32_t>(
+ _mm_crc32_u64(static_cast<uint32_t>(crcs[region]),
+ static_cast<uint64_t>(_mm_extract_epi64(data[i], 1))))};
+ }
+
+ for (size_t i = 0; i < int_regions; i++) {
+ size_t region = vec_regions + i;
+
+ auto* usrc =
+ reinterpret_cast<const uint64_t*>(*src + region_size * region);
+ auto* udst = reinterpret_cast<uint64_t*>(*dst + region_size * region);
+
+ for (size_t j = 0; j < kIntLoadsPerVec; j++) {
+ size_t data_index = i * kIntLoadsPerVec + j;
+
+ int_data[data_index] = *(usrc + j);
+ crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64(
+ static_cast<uint32_t>(crcs[region]), int_data[data_index]))};
+
+ *(udst + j) = int_data[data_index];
+ }
+ }
+
+ // Increment pointers
+ *src += sizeof(__m128i);
+ *dst += sizeof(__m128i);
+ --copy_rounds;
+ }
+}
+
+} // namespace
+
+template <size_t vec_regions, size_t int_regions>
+class AcceleratedCrcMemcpyEngine : public CrcMemcpyEngine {
+ public:
+ AcceleratedCrcMemcpyEngine() = default;
+ AcceleratedCrcMemcpyEngine(const AcceleratedCrcMemcpyEngine&) = delete;
+ AcceleratedCrcMemcpyEngine operator=(const AcceleratedCrcMemcpyEngine&) =
+ delete;
+
+ crc32c_t Compute(void* __restrict dst, const void* __restrict src,
+ std::size_t length, crc32c_t initial_crc) const override;
+};
+
+template <size_t vec_regions, size_t int_regions>
+crc32c_t AcceleratedCrcMemcpyEngine<vec_regions, int_regions>::Compute(
+ void* __restrict dst, const void* __restrict src, std::size_t length,
+ crc32c_t initial_crc) const {
+ constexpr std::size_t kRegions = vec_regions + int_regions;
+ constexpr uint32_t kCrcDataXor = uint32_t{0xffffffff};
+ constexpr std::size_t kBlockSize = sizeof(__m128i);
+ constexpr std::size_t kCopyRoundSize = kRegions * kBlockSize;
+
+ // Number of blocks per cacheline.
+ constexpr std::size_t kBlocksPerCacheLine = ABSL_CACHELINE_SIZE / kBlockSize;
+
+ char* dst_bytes = static_cast<char*>(dst);
+ const char* src_bytes = static_cast<const char*>(src);
+
+ // Make sure that one prefetch per big block is enough to cover the whole
+ // dataset, and we don't prefetch too much.
+ static_assert(ABSL_CACHELINE_SIZE % kBlockSize == 0,
+ "Cache lines are not divided evenly into blocks, may have "
+ "unintended behavior!");
+
+ // Experimentally-determined boundary between a small and large copy.
+ // Below this number, spin-up and concatenation of CRCs takes enough time that
+ // it kills the throughput gains of using 3 regions and wide vectors.
+ constexpr size_t kCrcSmallSize = 256;
+
+ // Experimentally-determined prefetch distance. Main loop copies will
+ // prefeth data 2 cache lines ahead.
+ constexpr std::size_t kPrefetchAhead = 2 * ABSL_CACHELINE_SIZE;
+
+ // Small-size CRC-memcpy : just do CRC + memcpy
+ if (length < kCrcSmallSize) {
+ crc32c_t crc =
+ ExtendCrc32c(initial_crc, absl::string_view(src_bytes, length));
+ memcpy(dst, src, length);
+ return crc;
+ }
+
+ // Start work on the CRC: undo the XOR from the previous calculation or set up
+ // the initial value of the CRC.
+ // initial_crc ^= kCrcDataXor;
+ initial_crc = crc32c_t{static_cast<uint32_t>(initial_crc) ^ kCrcDataXor};
+
+ // Do an initial alignment copy, so we can use aligned store instructions to
+ // the destination pointer. We align the destination pointer because the
+ // penalty for an unaligned load is small compared to the penalty of an
+ // unaligned store on modern CPUs.
+ std::size_t bytes_from_last_aligned =
+ reinterpret_cast<uintptr_t>(dst) & (kBlockSize - 1);
+ if (bytes_from_last_aligned != 0) {
+ std::size_t bytes_for_alignment = kBlockSize - bytes_from_last_aligned;
+
+ // Do the short-sized copy and CRC.
+ initial_crc =
+ ShortCrcCopy(dst_bytes, src_bytes, bytes_for_alignment, initial_crc);
+ src_bytes += bytes_for_alignment;
+ dst_bytes += bytes_for_alignment;
+ length -= bytes_for_alignment;
+ }
+
+ // We are going to do the copy and CRC in kRegions regions to make sure that
+ // we can saturate the CRC unit. The CRCs will be combined at the end of the
+ // run. Copying will use the SSE registers, and we will extract words from
+ // the SSE registers to add to the CRC. Initially, we run the loop one full
+ // cache line per region at a time, in order to insert prefetches.
+
+ // Initialize CRCs for kRegions regions.
+ crc32c_t crcs[kRegions];
+ crcs[0] = initial_crc;
+ for (size_t i = 1; i < kRegions; i++) {
+ crcs[i] = crc32c_t{kCrcDataXor};
+ }
+
+ // Find the number of rounds to copy and the region size. Also compute the
+ // tail size here.
+ size_t copy_rounds = length / kCopyRoundSize;
+
+ // Find the size of each region and the size of the tail.
+ const std::size_t region_size = copy_rounds * kBlockSize;
+ const std::size_t tail_size = length - (kRegions * region_size);
+
+ // Holding registers for data in each region.
+ std::array<__m128i, vec_regions> vec_data;
+ std::array<uint64_t, int_regions * kIntLoadsPerVec> int_data;
+
+ // Main loop.
+ while (copy_rounds > kBlocksPerCacheLine) {
+ // Prefetch kPrefetchAhead bytes ahead of each pointer.
+ for (size_t i = 0; i < kRegions; i++) {
+ absl::base_internal::PrefetchT0(src_bytes + kPrefetchAhead +
+ region_size * i);
+ absl::base_internal::PrefetchT0(dst_bytes + kPrefetchAhead +
+ region_size * i);
+ }
+
+ // Load and store data, computing CRC on the way.
+ for (size_t i = 0; i < kBlocksPerCacheLine; i++) {
+ // Copy and CRC the data for the CRC regions.
+ for (size_t j = 0; j < vec_regions; j++) {
+ // Cycle which regions get vector load/store and integer load/store, to
+ // engage prefetching logic around vector load/stores and save issue
+ // slots by using the integer registers.
+ size_t region = (j + i) % kRegions;
+
+ auto* vsrc =
+ reinterpret_cast<const __m128i*>(src_bytes + region_size * region);
+ auto* vdst =
+ reinterpret_cast<__m128i*>(dst_bytes + region_size * region);
+
+ // Load and CRC data.
+ vec_data[j] = _mm_loadu_si128(vsrc + i);
+ crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64(
+ static_cast<uint32_t>(crcs[region]),
+ static_cast<uint64_t>(_mm_extract_epi64(vec_data[j], 0))))};
+ crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64(
+ static_cast<uint32_t>(crcs[region]),
+ static_cast<uint64_t>(_mm_extract_epi64(vec_data[j], 1))))};
+
+ // Store the data.
+ _mm_store_si128(vdst + i, vec_data[j]);
+ }
+
+ // Preload the partial CRCs for the CLMUL subregions.
+ for (size_t j = 0; j < int_regions; j++) {
+ // Cycle which regions get vector load/store and integer load/store, to
+ // engage prefetching logic around vector load/stores and save issue
+ // slots by using the integer registers.
+ size_t region = (j + vec_regions + i) % kRegions;
+
+ auto* usrc =
+ reinterpret_cast<const uint64_t*>(src_bytes + region_size * region);
+ auto* udst =
+ reinterpret_cast<uint64_t*>(dst_bytes + region_size * region);
+
+ for (size_t k = 0; k < kIntLoadsPerVec; k++) {
+ size_t data_index = j * kIntLoadsPerVec + k;
+
+ // Load and CRC the data.
+ int_data[data_index] = *(usrc + i * kIntLoadsPerVec + k);
+ crcs[region] = crc32c_t{static_cast<uint32_t>(_mm_crc32_u64(
+ static_cast<uint32_t>(crcs[region]), int_data[data_index]))};
+
+ // Store the data.
+ *(udst + i * kIntLoadsPerVec + k) = int_data[data_index];
+ }
+ }
+ }
+
+ // Increment pointers
+ src_bytes += kBlockSize * kBlocksPerCacheLine;
+ dst_bytes += kBlockSize * kBlocksPerCacheLine;
+ copy_rounds -= kBlocksPerCacheLine;
+ }
+
+ // Copy and CRC the tails of each region.
+ LargeTailCopy<vec_regions, int_regions>(crcs, &dst_bytes, &src_bytes,
+ region_size, copy_rounds);
+
+ // Move the source and destination pointers to the end of the region
+ src_bytes += region_size * (kRegions - 1);
+ dst_bytes += region_size * (kRegions - 1);
+
+ // Finalize the first CRCs: XOR the internal CRCs by the XOR mask to undo the
+ // XOR done before doing block copy + CRCs.
+ for (size_t i = 0; i + 1 < kRegions; i++) {
+ crcs[i] = crc32c_t{static_cast<uint32_t>(crcs[i]) ^ kCrcDataXor};
+ }
+
+ // Build a CRC of the first kRegions - 1 regions.
+ crc32c_t full_crc = crcs[0];
+ for (size_t i = 1; i + 1 < kRegions; i++) {
+ full_crc = ConcatCrc32c(full_crc, crcs[i], region_size);
+ }
+
+ // Copy and CRC the tail through the XMM registers.
+ std::size_t tail_blocks = tail_size / kBlockSize;
+ LargeTailCopy<0, 1>(&crcs[kRegions - 1], &dst_bytes, &src_bytes, 0,
+ tail_blocks);
+
+ // Final tail copy for under 16 bytes.
+ crcs[kRegions - 1] =
+ ShortCrcCopy(dst_bytes, src_bytes, tail_size - tail_blocks * kBlockSize,
+ crcs[kRegions - 1]);
+
+ // Finalize and concatenate the final CRC, then return.
+ crcs[kRegions - 1] =
+ crc32c_t{static_cast<uint32_t>(crcs[kRegions - 1]) ^ kCrcDataXor};
+ return ConcatCrc32c(full_crc, crcs[kRegions - 1], region_size + tail_size);
+}
+
+CrcMemcpy::ArchSpecificEngines CrcMemcpy::GetArchSpecificEngines() {
+#ifdef UNDEFINED_BEHAVIOR_SANITIZER
+ // UBSAN does not play nicely with unaligned loads (which we use a lot).
+ // Get the underlying architecture.
+ CpuType cpu_type = GetCpuType();
+ switch (cpu_type) {
+ case CpuType::kUnknown:
+ case CpuType::kAmdRome:
+ case CpuType::kAmdNaples:
+ case CpuType::kIntelCascadelakeXeon:
+ case CpuType::kIntelSkylakeXeon:
+ case CpuType::kIntelSkylake:
+ case CpuType::kIntelBroadwell:
+ case CpuType::kIntelHaswell:
+ case CpuType::kIntelIvybridge:
+ return {
+ .temporal = new FallbackCrcMemcpyEngine(),
+ .non_temporal = new CrcNonTemporalMemcpyAVXEngine(),
+ };
+ // INTEL_SANDYBRIDGE performs better with SSE than AVX.
+ case CpuType::kIntelSandybridge:
+ return {
+ .temporal = new FallbackCrcMemcpyEngine(),
+ .non_temporal = new CrcNonTemporalMemcpyEngine(),
+ };
+ default:
+ return {.temporal = new FallbackCrcMemcpyEngine(),
+ .non_temporal = new FallbackCrcMemcpyEngine()};
+ }
+#else
+ // Get the underlying architecture.
+ CpuType cpu_type = GetCpuType();
+ switch (cpu_type) {
+ // On Zen 2, PEXTRQ uses 2 micro-ops, including one on the vector store port
+ // which data movement from the vector registers to the integer registers
+ // (where CRC32C happens) to crowd the same units as vector stores. As a
+ // result, using that path exclusively causes bottlenecking on this port.
+ // We can avoid this bottleneck by using the integer side of the CPU for
+ // most operations rather than the vector side. We keep a vector region to
+ // engage some of the prefetching logic in the cache hierarchy which seems
+ // to give vector instructions special treatment. These prefetch units see
+ // strided access to each region, and do the right thing.
+ case CpuType::kAmdRome:
+ case CpuType::kAmdNaples:
+ return {
+ .temporal = new AcceleratedCrcMemcpyEngine<1, 2>(),
+ .non_temporal = new CrcNonTemporalMemcpyAVXEngine(),
+ };
+ // PCLMULQDQ is slow and we don't have wide enough issue width to take
+ // advantage of it. For an unknown architecture, don't risk using CLMULs.
+ case CpuType::kIntelCascadelakeXeon:
+ case CpuType::kIntelSkylakeXeon:
+ case CpuType::kIntelSkylake:
+ case CpuType::kIntelBroadwell:
+ case CpuType::kIntelHaswell:
+ case CpuType::kIntelIvybridge:
+ return {
+ .temporal = new AcceleratedCrcMemcpyEngine<3, 0>(),
+ .non_temporal = new CrcNonTemporalMemcpyAVXEngine(),
+ };
+ // INTEL_SANDYBRIDGE performs better with SSE than AVX.
+ case CpuType::kIntelSandybridge:
+ return {
+ .temporal = new AcceleratedCrcMemcpyEngine<3, 0>(),
+ .non_temporal = new CrcNonTemporalMemcpyEngine(),
+ };
+ default:
+ return {.temporal = new FallbackCrcMemcpyEngine(),
+ .non_temporal = new FallbackCrcMemcpyEngine()};
+ }
+#endif // UNDEFINED_BEHAVIOR_SANITIZER
+}
+
+// For testing, allow the user to specify which engine they want.
+std::unique_ptr<CrcMemcpyEngine> CrcMemcpy::GetTestEngine(int vector,
+ int integer) {
+ if (vector == 3 && integer == 0) {
+ return std::make_unique<AcceleratedCrcMemcpyEngine<3, 0>>();
+ } else if (vector == 1 && integer == 2) {
+ return std::make_unique<AcceleratedCrcMemcpyEngine<1, 2>>();
+ }
+ return nullptr;
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_INTERNAL_HAVE_X86_64_ACCELERATED_CRC_MEMCPY_ENGINE
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc
new file mode 100644
index 0000000000..adc867f6b7
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc
@@ -0,0 +1,93 @@
+// 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 <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/crc/crc32c.h"
+#include "absl/crc/internal/crc_memcpy.h"
+#include "absl/crc/internal/non_temporal_memcpy.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+crc32c_t CrcNonTemporalMemcpyEngine::Compute(void* __restrict dst,
+ const void* __restrict src,
+ std::size_t length,
+ crc32c_t initial_crc) const {
+ constexpr size_t kBlockSize = 8192;
+ crc32c_t crc = initial_crc;
+
+ const char* src_bytes = reinterpret_cast<const char*>(src);
+ char* dst_bytes = reinterpret_cast<char*>(dst);
+
+ // Copy + CRC loop - run 8k chunks until we are out of full chunks.
+ std::size_t offset = 0;
+ for (; offset + kBlockSize < length; offset += kBlockSize) {
+ crc = absl::ExtendCrc32c(crc,
+ absl::string_view(src_bytes + offset, kBlockSize));
+ non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,
+ kBlockSize);
+ }
+
+ // Save some work if length is 0.
+ if (offset < length) {
+ std::size_t final_copy_size = length - offset;
+ crc = ExtendCrc32c(crc,
+ absl::string_view(src_bytes + offset, final_copy_size));
+
+ non_temporal_store_memcpy(dst_bytes + offset, src_bytes + offset,
+ final_copy_size);
+ }
+
+ return crc;
+}
+
+crc32c_t CrcNonTemporalMemcpyAVXEngine::Compute(void* __restrict dst,
+ const void* __restrict src,
+ std::size_t length,
+ crc32c_t initial_crc) const {
+ constexpr size_t kBlockSize = 8192;
+ crc32c_t crc = initial_crc;
+
+ const char* src_bytes = reinterpret_cast<const char*>(src);
+ char* dst_bytes = reinterpret_cast<char*>(dst);
+
+ // Copy + CRC loop - run 8k chunks until we are out of full chunks.
+ std::size_t offset = 0;
+ for (; offset + kBlockSize < length; offset += kBlockSize) {
+ crc = ExtendCrc32c(crc, absl::string_view(src_bytes + offset, kBlockSize));
+
+ non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,
+ kBlockSize);
+ }
+
+ // Save some work if length is 0.
+ if (offset < length) {
+ std::size_t final_copy_size = length - offset;
+ crc = ExtendCrc32c(crc,
+ absl::string_view(src_bytes + offset, final_copy_size));
+
+ non_temporal_store_memcpy_avx(dst_bytes + offset, src_bytes + offset,
+ final_copy_size);
+ }
+
+ return crc;
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc
new file mode 100644
index 0000000000..d71191e380
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc
@@ -0,0 +1,725 @@
+// 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.
+
+// Hardware accelerated CRC32 computation on Intel and ARM architecture.
+
+#include <cstddef>
+#include <cstdint>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/dynamic_annotations.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/prefetch.h"
+#include "absl/crc/internal/cpu_detect.h"
+#include "absl/crc/internal/crc.h"
+#include "absl/crc/internal/crc32_x86_arm_combined_simd.h"
+#include "absl/crc/internal/crc_internal.h"
+#include "absl/memory/memory.h"
+#include "absl/numeric/bits.h"
+
+#if defined(ABSL_CRC_INTERNAL_HAVE_ARM_SIMD) || \
+ defined(ABSL_CRC_INTERNAL_HAVE_X86_SIMD)
+#define ABSL_INTERNAL_CAN_USE_SIMD_CRC32C
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+#if defined(ABSL_INTERNAL_CAN_USE_SIMD_CRC32C)
+
+// Implementation details not exported outside of file
+namespace {
+
+// Some machines have CRC acceleration hardware.
+// We can do a faster version of Extend() on such machines.
+class CRC32AcceleratedX86ARMCombined : public CRC32 {
+ public:
+ CRC32AcceleratedX86ARMCombined() {}
+ ~CRC32AcceleratedX86ARMCombined() override {}
+ void ExtendByZeroes(uint32_t* crc, size_t length) const override;
+ uint32_t ComputeZeroConstant(size_t length) const;
+
+ private:
+ CRC32AcceleratedX86ARMCombined(const CRC32AcceleratedX86ARMCombined&) =
+ delete;
+ CRC32AcceleratedX86ARMCombined& operator=(
+ const CRC32AcceleratedX86ARMCombined&) = delete;
+};
+
+// Constants for switching between algorithms.
+// Chosen by comparing speed at different powers of 2.
+constexpr size_t kSmallCutoff = 256;
+constexpr size_t kMediumCutoff = 2048;
+
+#define ABSL_INTERNAL_STEP1(crc) \
+ do { \
+ crc = CRC32_u8(static_cast<uint32_t>(crc), *p++); \
+ } while (0)
+#define ABSL_INTERNAL_STEP2(crc) \
+ do { \
+ crc = \
+ CRC32_u16(static_cast<uint32_t>(crc), absl::little_endian::Load16(p)); \
+ p += 2; \
+ } while (0)
+#define ABSL_INTERNAL_STEP4(crc) \
+ do { \
+ crc = \
+ CRC32_u32(static_cast<uint32_t>(crc), absl::little_endian::Load32(p)); \
+ p += 4; \
+ } while (0)
+#define ABSL_INTERNAL_STEP8(crc, data) \
+ do { \
+ crc = CRC32_u64(static_cast<uint32_t>(crc), \
+ absl::little_endian::Load64(data)); \
+ data += 8; \
+ } while (0)
+#define ABSL_INTERNAL_STEP8BY2(crc0, crc1, p0, p1) \
+ do { \
+ ABSL_INTERNAL_STEP8(crc0, p0); \
+ ABSL_INTERNAL_STEP8(crc1, p1); \
+ } while (0)
+#define ABSL_INTERNAL_STEP8BY3(crc0, crc1, crc2, p0, p1, p2) \
+ do { \
+ ABSL_INTERNAL_STEP8(crc0, p0); \
+ ABSL_INTERNAL_STEP8(crc1, p1); \
+ ABSL_INTERNAL_STEP8(crc2, p2); \
+ } while (0)
+
+namespace {
+
+uint32_t multiply(uint32_t a, uint32_t b) {
+ V128 shifts = V128_From2x64(0, 1);
+ V128 power = V128_From2x64(0, a);
+ V128 crc = V128_From2x64(0, b);
+ V128 res = V128_PMulLow(power, crc);
+
+ // Combine crc values
+ res = V128_ShiftLeft64(res, shifts);
+ return static_cast<uint32_t>(V128_Extract32<1>(res)) ^
+ CRC32_u32(0, static_cast<uint32_t>(V128_Low64(res)));
+}
+
+// Powers of crc32c polynomial, for faster ExtendByZeros.
+// Verified against folly:
+// folly/hash/detail/Crc32CombineDetail.cpp
+constexpr uint32_t kCRC32CPowers[] = {
+ 0x82f63b78, 0x6ea2d55c, 0x18b8ea18, 0x510ac59a, 0xb82be955, 0xb8fdb1e7,
+ 0x88e56f72, 0x74c360a4, 0xe4172b16, 0x0d65762a, 0x35d73a62, 0x28461564,
+ 0xbf455269, 0xe2ea32dc, 0xfe7740e6, 0xf946610b, 0x3c204f8f, 0x538586e3,
+ 0x59726915, 0x734d5309, 0xbc1ac763, 0x7d0722cc, 0xd289cabe, 0xe94ca9bc,
+ 0x05b74f3f, 0xa51e1f42, 0x40000000, 0x20000000, 0x08000000, 0x00800000,
+ 0x00008000, 0x82f63b78, 0x6ea2d55c, 0x18b8ea18, 0x510ac59a, 0xb82be955,
+ 0xb8fdb1e7, 0x88e56f72, 0x74c360a4, 0xe4172b16, 0x0d65762a, 0x35d73a62,
+ 0x28461564, 0xbf455269, 0xe2ea32dc, 0xfe7740e6, 0xf946610b, 0x3c204f8f,
+ 0x538586e3, 0x59726915, 0x734d5309, 0xbc1ac763, 0x7d0722cc, 0xd289cabe,
+ 0xe94ca9bc, 0x05b74f3f, 0xa51e1f42, 0x40000000, 0x20000000, 0x08000000,
+ 0x00800000, 0x00008000,
+};
+
+} // namespace
+
+// Compute a magic constant, so that multiplying by it is the same as
+// extending crc by length zeros.
+uint32_t CRC32AcceleratedX86ARMCombined::ComputeZeroConstant(
+ size_t length) const {
+ // Lowest 2 bits are handled separately in ExtendByZeroes
+ length >>= 2;
+
+ int index = absl::countr_zero(length);
+ uint32_t prev = kCRC32CPowers[index];
+ length &= length - 1;
+
+ while (length) {
+ // For each bit of length, extend by 2**n zeros.
+ index = absl::countr_zero(length);
+ prev = multiply(prev, kCRC32CPowers[index]);
+ length &= length - 1;
+ }
+ return prev;
+}
+
+void CRC32AcceleratedX86ARMCombined::ExtendByZeroes(uint32_t* crc,
+ size_t length) const {
+ uint32_t val = *crc;
+ // Don't bother with multiplication for small length.
+ switch (length & 3) {
+ case 0:
+ break;
+ case 1:
+ val = CRC32_u8(val, 0);
+ break;
+ case 2:
+ val = CRC32_u16(val, 0);
+ break;
+ case 3:
+ val = CRC32_u8(val, 0);
+ val = CRC32_u16(val, 0);
+ break;
+ }
+ if (length > 3) {
+ val = multiply(val, ComputeZeroConstant(length));
+ }
+ *crc = val;
+}
+
+// Taken from Intel paper "Fast CRC Computation for iSCSI Polynomial Using CRC32
+// Instruction"
+// https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/crc-iscsi-polynomial-crc32-instruction-paper.pdf
+// We only need every 4th value, because we unroll loop by 4.
+constexpr uint64_t kClmulConstants[] = {
+ 0x09e4addf8, 0x0ba4fc28e, 0x00d3b6092, 0x09e4addf8, 0x0ab7aff2a,
+ 0x102f9b8a2, 0x0b9e02b86, 0x00d3b6092, 0x1bf2e8b8a, 0x18266e456,
+ 0x0d270f1a2, 0x0ab7aff2a, 0x11eef4f8e, 0x083348832, 0x0dd7e3b0c,
+ 0x0b9e02b86, 0x0271d9844, 0x1b331e26a, 0x06b749fb2, 0x1bf2e8b8a,
+ 0x0e6fc4e6a, 0x0ce7f39f4, 0x0d7a4825c, 0x0d270f1a2, 0x026f6a60a,
+ 0x12ed0daac, 0x068bce87a, 0x11eef4f8e, 0x1329d9f7e, 0x0b3e32c28,
+ 0x0170076fa, 0x0dd7e3b0c, 0x1fae1cc66, 0x010746f3c, 0x086d8e4d2,
+ 0x0271d9844, 0x0b3af077a, 0x093a5f730, 0x1d88abd4a, 0x06b749fb2,
+ 0x0c9c8b782, 0x0cec3662e, 0x1ddffc5d4, 0x0e6fc4e6a, 0x168763fa6,
+ 0x0b0cd4768, 0x19b1afbc4, 0x0d7a4825c, 0x123888b7a, 0x00167d312,
+ 0x133d7a042, 0x026f6a60a, 0x000bcf5f6, 0x19d34af3a, 0x1af900c24,
+ 0x068bce87a, 0x06d390dec, 0x16cba8aca, 0x1f16a3418, 0x1329d9f7e,
+ 0x19fb2a8b0, 0x02178513a, 0x1a0f717c4, 0x0170076fa,
+};
+
+enum class CutoffStrategy {
+ // Use 3 CRC streams to fold into 1.
+ Fold3,
+ // Unroll CRC instructions for 64 bytes.
+ Unroll64CRC,
+};
+
+// Base class for CRC32AcceleratedX86ARMCombinedMultipleStreams containing the
+// methods and data that don't need the template arguments.
+class CRC32AcceleratedX86ARMCombinedMultipleStreamsBase
+ : public CRC32AcceleratedX86ARMCombined {
+ protected:
+ // Update partialCRC with crc of 64 byte block. Calling FinalizePclmulStream
+ // would produce a single crc checksum, but it is expensive. PCLMULQDQ has a
+ // high latency, so we run 4 128-bit partial checksums that can be reduced to
+ // a single value by FinalizePclmulStream later. Computing crc for arbitrary
+ // polynomialas with PCLMULQDQ is described in Intel paper "Fast CRC
+ // Computation for Generic Polynomials Using PCLMULQDQ Instruction"
+ // https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf
+ // We are applying it to CRC32C polynomial.
+ ABSL_ATTRIBUTE_ALWAYS_INLINE void Process64BytesPclmul(
+ const uint8_t* p, V128* partialCRC) const {
+ V128 loopMultiplicands = V128_Load(reinterpret_cast<const V128*>(k1k2));
+
+ V128 partialCRC1 = partialCRC[0];
+ V128 partialCRC2 = partialCRC[1];
+ V128 partialCRC3 = partialCRC[2];
+ V128 partialCRC4 = partialCRC[3];
+
+ V128 tmp1 = V128_PMulHi(partialCRC1, loopMultiplicands);
+ V128 tmp2 = V128_PMulHi(partialCRC2, loopMultiplicands);
+ V128 tmp3 = V128_PMulHi(partialCRC3, loopMultiplicands);
+ V128 tmp4 = V128_PMulHi(partialCRC4, loopMultiplicands);
+ V128 data1 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 0));
+ V128 data2 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 1));
+ V128 data3 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 2));
+ V128 data4 = V128_LoadU(reinterpret_cast<const V128*>(p + 16 * 3));
+ partialCRC1 = V128_PMulLow(partialCRC1, loopMultiplicands);
+ partialCRC2 = V128_PMulLow(partialCRC2, loopMultiplicands);
+ partialCRC3 = V128_PMulLow(partialCRC3, loopMultiplicands);
+ partialCRC4 = V128_PMulLow(partialCRC4, loopMultiplicands);
+ partialCRC1 = V128_Xor(tmp1, partialCRC1);
+ partialCRC2 = V128_Xor(tmp2, partialCRC2);
+ partialCRC3 = V128_Xor(tmp3, partialCRC3);
+ partialCRC4 = V128_Xor(tmp4, partialCRC4);
+ partialCRC1 = V128_Xor(partialCRC1, data1);
+ partialCRC2 = V128_Xor(partialCRC2, data2);
+ partialCRC3 = V128_Xor(partialCRC3, data3);
+ partialCRC4 = V128_Xor(partialCRC4, data4);
+ partialCRC[0] = partialCRC1;
+ partialCRC[1] = partialCRC2;
+ partialCRC[2] = partialCRC3;
+ partialCRC[3] = partialCRC4;
+ }
+
+ // Reduce partialCRC produced by Process64BytesPclmul into a single value,
+ // that represents crc checksum of all the processed bytes.
+ ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t
+ FinalizePclmulStream(V128* partialCRC) const {
+ V128 partialCRC1 = partialCRC[0];
+ V128 partialCRC2 = partialCRC[1];
+ V128 partialCRC3 = partialCRC[2];
+ V128 partialCRC4 = partialCRC[3];
+
+ // Combine 4 vectors of partial crc into a single vector.
+ V128 reductionMultiplicands =
+ V128_Load(reinterpret_cast<const V128*>(k5k6));
+
+ V128 low = V128_PMulLow(reductionMultiplicands, partialCRC1);
+ V128 high = V128_PMulHi(reductionMultiplicands, partialCRC1);
+
+ partialCRC1 = V128_Xor(low, high);
+ partialCRC1 = V128_Xor(partialCRC1, partialCRC2);
+
+ low = V128_PMulLow(reductionMultiplicands, partialCRC3);
+ high = V128_PMulHi(reductionMultiplicands, partialCRC3);
+
+ partialCRC3 = V128_Xor(low, high);
+ partialCRC3 = V128_Xor(partialCRC3, partialCRC4);
+
+ reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k3k4));
+
+ low = V128_PMulLow(reductionMultiplicands, partialCRC1);
+ high = V128_PMulHi(reductionMultiplicands, partialCRC1);
+ V128 fullCRC = V128_Xor(low, high);
+ fullCRC = V128_Xor(fullCRC, partialCRC3);
+
+ // Reduce fullCRC into scalar value.
+ reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k5k6));
+
+ V128 mask = V128_Load(reinterpret_cast<const V128*>(kMask));
+
+ V128 tmp = V128_PMul01(reductionMultiplicands, fullCRC);
+ fullCRC = V128_ShiftRight<8>(fullCRC);
+ fullCRC = V128_Xor(fullCRC, tmp);
+
+ reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(k7k0));
+
+ tmp = V128_ShiftRight<4>(fullCRC);
+ fullCRC = V128_And(fullCRC, mask);
+ fullCRC = V128_PMulLow(reductionMultiplicands, fullCRC);
+ fullCRC = V128_Xor(tmp, fullCRC);
+
+ reductionMultiplicands = V128_Load(reinterpret_cast<const V128*>(kPoly));
+
+ tmp = V128_And(fullCRC, mask);
+ tmp = V128_PMul01(reductionMultiplicands, tmp);
+ tmp = V128_And(tmp, mask);
+ tmp = V128_PMulLow(reductionMultiplicands, tmp);
+
+ fullCRC = V128_Xor(tmp, fullCRC);
+
+ return static_cast<uint64_t>(V128_Extract32<1>(fullCRC));
+ }
+
+ // Update crc with 64 bytes of data from p.
+ ABSL_ATTRIBUTE_ALWAYS_INLINE uint64_t Process64BytesCRC(const uint8_t* p,
+ uint64_t crc) const {
+ for (int i = 0; i < 8; i++) {
+ crc =
+ CRC32_u64(static_cast<uint32_t>(crc), absl::little_endian::Load64(p));
+ p += 8;
+ }
+ return crc;
+ }
+
+ // Generated by crc32c_x86_test --crc32c_generate_constants=true
+ // and verified against constants in linux kernel for S390:
+ // https://github.com/torvalds/linux/blob/master/arch/s390/crypto/crc32le-vx.S
+ alignas(16) static constexpr uint64_t k1k2[2] = {0x0740eef02, 0x09e4addf8};
+ alignas(16) static constexpr uint64_t k3k4[2] = {0x1384aa63a, 0x0ba4fc28e};
+ alignas(16) static constexpr uint64_t k5k6[2] = {0x0f20c0dfe, 0x14cd00bd6};
+ alignas(16) static constexpr uint64_t k7k0[2] = {0x0dd45aab8, 0x000000000};
+ alignas(16) static constexpr uint64_t kPoly[2] = {0x105ec76f0, 0x0dea713f1};
+ alignas(16) static constexpr uint32_t kMask[4] = {~0u, 0u, ~0u, 0u};
+
+ // Medium runs of bytes are broken into groups of kGroupsSmall blocks of same
+ // size. Each group is CRCed in parallel then combined at the end of the
+ // block.
+ static constexpr size_t kGroupsSmall = 3;
+ // For large runs we use up to kMaxStreams blocks computed with CRC
+ // instruction, and up to kMaxStreams blocks computed with PCLMULQDQ, which
+ // are combined in the end.
+ static constexpr size_t kMaxStreams = 3;
+};
+
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+alignas(16) constexpr uint64_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k1k2[2];
+alignas(16) constexpr uint64_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k3k4[2];
+alignas(16) constexpr uint64_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k5k6[2];
+alignas(16) constexpr uint64_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::k7k0[2];
+alignas(16) constexpr uint64_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kPoly[2];
+alignas(16) constexpr uint32_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kMask[4];
+constexpr size_t
+ CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kGroupsSmall;
+constexpr size_t CRC32AcceleratedX86ARMCombinedMultipleStreamsBase::kMaxStreams;
+#endif // ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+
+template <size_t num_crc_streams, size_t num_pclmul_streams,
+ CutoffStrategy strategy>
+class CRC32AcceleratedX86ARMCombinedMultipleStreams
+ : public CRC32AcceleratedX86ARMCombinedMultipleStreamsBase {
+ ABSL_ATTRIBUTE_HOT
+ void Extend(uint32_t* crc, const void* bytes, size_t length) const override {
+ static_assert(num_crc_streams >= 1 && num_crc_streams <= kMaxStreams,
+ "Invalid number of crc streams");
+ static_assert(num_pclmul_streams >= 0 && num_pclmul_streams <= kMaxStreams,
+ "Invalid number of pclmul streams");
+ const uint8_t* p = static_cast<const uint8_t*>(bytes);
+ const uint8_t* e = p + length;
+ uint32_t l = *crc;
+ uint64_t l64;
+
+ // We have dedicated instruction for 1,2,4 and 8 bytes.
+ if (length & 8) {
+ ABSL_INTERNAL_STEP8(l, p);
+ length &= ~size_t{8};
+ }
+ if (length & 4) {
+ ABSL_INTERNAL_STEP4(l);
+ length &= ~size_t{4};
+ }
+ if (length & 2) {
+ ABSL_INTERNAL_STEP2(l);
+ length &= ~size_t{2};
+ }
+ if (length & 1) {
+ ABSL_INTERNAL_STEP1(l);
+ length &= ~size_t{1};
+ }
+ if (length == 0) {
+ *crc = l;
+ return;
+ }
+ // length is now multiple of 16.
+
+ // For small blocks just run simple loop, because cost of combining multiple
+ // streams is significant.
+ if (strategy != CutoffStrategy::Unroll64CRC) {
+ if (length < kSmallCutoff) {
+ while (length >= 16) {
+ ABSL_INTERNAL_STEP8(l, p);
+ ABSL_INTERNAL_STEP8(l, p);
+ length -= 16;
+ }
+ *crc = l;
+ return;
+ }
+ }
+
+ // For medium blocks we run 3 crc streams and combine them as described in
+ // Intel paper above. Running 4th stream doesn't help, because crc
+ // instruction has latency 3 and throughput 1.
+ if (length < kMediumCutoff) {
+ l64 = l;
+ if (strategy == CutoffStrategy::Fold3) {
+ uint64_t l641 = 0;
+ uint64_t l642 = 0;
+ const size_t blockSize = 32;
+ size_t bs = static_cast<size_t>(e - p) / kGroupsSmall / blockSize;
+ const uint8_t* p1 = p + bs * blockSize;
+ const uint8_t* p2 = p1 + bs * blockSize;
+
+ for (size_t i = 0; i + 1 < bs; ++i) {
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ base_internal::PrefetchT0(
+ reinterpret_cast<const char*>(p + kPrefetchHorizonMedium));
+ base_internal::PrefetchT0(
+ reinterpret_cast<const char*>(p1 + kPrefetchHorizonMedium));
+ base_internal::PrefetchT0(
+ reinterpret_cast<const char*>(p2 + kPrefetchHorizonMedium));
+ }
+ // Don't run crc on last 8 bytes.
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY3(l64, l641, l642, p, p1, p2);
+ ABSL_INTERNAL_STEP8BY2(l64, l641, p, p1);
+
+ V128 magic = *(reinterpret_cast<const V128*>(kClmulConstants) + bs - 1);
+
+ V128 tmp = V128_From2x64(0, l64);
+
+ V128 res1 = V128_PMulLow(tmp, magic);
+
+ tmp = V128_From2x64(0, l641);
+
+ V128 res2 = V128_PMul10(tmp, magic);
+ V128 x = V128_Xor(res1, res2);
+ l64 = static_cast<uint64_t>(V128_Low64(x)) ^
+ absl::little_endian::Load64(p2);
+ l64 = CRC32_u64(static_cast<uint32_t>(l642), l64);
+
+ p = p2 + 8;
+ } else if (strategy == CutoffStrategy::Unroll64CRC) {
+ while ((e - p) >= 64) {
+ l64 = Process64BytesCRC(p, l64);
+ p += 64;
+ }
+ }
+ } else {
+ // There is a lot of data, we can ignore combine costs and run all
+ // requested streams (num_crc_streams + num_pclmul_streams),
+ // using prefetch. CRC and PCLMULQDQ use different cpu execution units,
+ // so on some cpus it makes sense to execute both of them for different
+ // streams.
+
+ // Point x at first 8-byte aligned byte in string.
+ const uint8_t* x = RoundUp<8>(p);
+ // Process bytes until p is 8-byte aligned, if that isn't past the end.
+ while (p != x) {
+ ABSL_INTERNAL_STEP1(l);
+ }
+
+ size_t bs = static_cast<size_t>(e - p) /
+ (num_crc_streams + num_pclmul_streams) / 64;
+ const uint8_t* crc_streams[kMaxStreams];
+ const uint8_t* pclmul_streams[kMaxStreams];
+ // We are guaranteed to have at least one crc stream.
+ crc_streams[0] = p;
+ for (size_t i = 1; i < num_crc_streams; i++) {
+ crc_streams[i] = crc_streams[i - 1] + bs * 64;
+ }
+ pclmul_streams[0] = crc_streams[num_crc_streams - 1] + bs * 64;
+ for (size_t i = 1; i < num_pclmul_streams; i++) {
+ pclmul_streams[i] = pclmul_streams[i - 1] + bs * 64;
+ }
+
+ // Per stream crc sums.
+ uint64_t l64_crc[kMaxStreams] = {l};
+ uint64_t l64_pclmul[kMaxStreams] = {0};
+
+ // Peel first iteration, because PCLMULQDQ stream, needs setup.
+ for (size_t i = 0; i < num_crc_streams; i++) {
+ l64_crc[i] = Process64BytesCRC(crc_streams[i], l64_crc[i]);
+ crc_streams[i] += 16 * 4;
+ }
+
+ V128 partialCRC[kMaxStreams][4];
+ for (size_t i = 0; i < num_pclmul_streams; i++) {
+ partialCRC[i][0] = V128_LoadU(
+ reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 0));
+ partialCRC[i][1] = V128_LoadU(
+ reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 1));
+ partialCRC[i][2] = V128_LoadU(
+ reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 2));
+ partialCRC[i][3] = V128_LoadU(
+ reinterpret_cast<const V128*>(pclmul_streams[i] + 16 * 3));
+ pclmul_streams[i] += 16 * 4;
+ }
+
+ for (size_t i = 1; i < bs; i++) {
+ // Prefetch data for next itterations.
+ for (size_t j = 0; j < num_crc_streams; j++) {
+ base_internal::PrefetchT0(
+ reinterpret_cast<const char*>(crc_streams[j] + kPrefetchHorizon));
+ }
+ for (size_t j = 0; j < num_pclmul_streams; j++) {
+ base_internal::PrefetchT0(reinterpret_cast<const char*>(
+ pclmul_streams[j] + kPrefetchHorizon));
+ }
+
+ // We process each stream in 64 byte blocks. This can be written as
+ // for (int i = 0; i < num_pclmul_streams; i++) {
+ // Process64BytesPclmul(pclmul_streams[i], partialCRC[i]);
+ // pclmul_streams[i] += 16 * 4;
+ // }
+ // for (int i = 0; i < num_crc_streams; i++) {
+ // l64_crc[i] = Process64BytesCRC(crc_streams[i], l64_crc[i]);
+ // crc_streams[i] += 16*4;
+ // }
+ // But unrolling and interleaving PCLMULQDQ and CRC blocks manually
+ // gives ~2% performance boost.
+ l64_crc[0] = Process64BytesCRC(crc_streams[0], l64_crc[0]);
+ crc_streams[0] += 16 * 4;
+ if (num_pclmul_streams > 0) {
+ Process64BytesPclmul(pclmul_streams[0], partialCRC[0]);
+ pclmul_streams[0] += 16 * 4;
+ }
+ if (num_crc_streams > 1) {
+ l64_crc[1] = Process64BytesCRC(crc_streams[1], l64_crc[1]);
+ crc_streams[1] += 16 * 4;
+ }
+ if (num_pclmul_streams > 1) {
+ Process64BytesPclmul(pclmul_streams[1], partialCRC[1]);
+ pclmul_streams[1] += 16 * 4;
+ }
+ if (num_crc_streams > 2) {
+ l64_crc[2] = Process64BytesCRC(crc_streams[2], l64_crc[2]);
+ crc_streams[2] += 16 * 4;
+ }
+ if (num_pclmul_streams > 2) {
+ Process64BytesPclmul(pclmul_streams[2], partialCRC[2]);
+ pclmul_streams[2] += 16 * 4;
+ }
+ }
+
+ // PCLMULQDQ based streams require special final step;
+ // CRC based don't.
+ for (size_t i = 0; i < num_pclmul_streams; i++) {
+ l64_pclmul[i] = FinalizePclmulStream(partialCRC[i]);
+ }
+
+ // Combine all streams into single result.
+ uint32_t magic = ComputeZeroConstant(bs * 64);
+ l64 = l64_crc[0];
+ for (size_t i = 1; i < num_crc_streams; i++) {
+ l64 = multiply(static_cast<uint32_t>(l64), magic);
+ l64 ^= l64_crc[i];
+ }
+ for (size_t i = 0; i < num_pclmul_streams; i++) {
+ l64 = multiply(static_cast<uint32_t>(l64), magic);
+ l64 ^= l64_pclmul[i];
+ }
+
+ // Update p.
+ if (num_pclmul_streams > 0) {
+ p = pclmul_streams[num_pclmul_streams - 1];
+ } else {
+ p = crc_streams[num_crc_streams - 1];
+ }
+ }
+ l = static_cast<uint32_t>(l64);
+
+ while ((e - p) >= 16) {
+ ABSL_INTERNAL_STEP8(l, p);
+ ABSL_INTERNAL_STEP8(l, p);
+ }
+ // Process the last few bytes
+ while (p != e) {
+ ABSL_INTERNAL_STEP1(l);
+ }
+
+#undef ABSL_INTERNAL_STEP8BY3
+#undef ABSL_INTERNAL_STEP8BY2
+#undef ABSL_INTERNAL_STEP8
+#undef ABSL_INTERNAL_STEP4
+#undef ABSL_INTERNAL_STEP2
+#undef ABSL_INTERNAL_STEP1
+
+ *crc = l;
+ }
+};
+
+} // namespace
+
+// Intel processors with SSE4.2 have an instruction for one particular
+// 32-bit CRC polynomial: crc32c
+CRCImpl* TryNewCRC32AcceleratedX86ARMCombined() {
+ CpuType type = GetCpuType();
+ switch (type) {
+ case CpuType::kIntelHaswell:
+ case CpuType::kAmdRome:
+ case CpuType::kAmdNaples:
+ case CpuType::kAmdMilan:
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 1, CutoffStrategy::Fold3>();
+ // PCLMULQDQ is fast, use combined PCLMULQDQ + CRC implementation.
+ case CpuType::kIntelCascadelakeXeon:
+ case CpuType::kIntelSkylakeXeon:
+ case CpuType::kIntelBroadwell:
+ case CpuType::kIntelSkylake:
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 2, CutoffStrategy::Fold3>();
+ // PCLMULQDQ is slow, don't use it.
+ case CpuType::kIntelIvybridge:
+ case CpuType::kIntelSandybridge:
+ case CpuType::kIntelWestmere:
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 0, CutoffStrategy::Fold3>();
+ case CpuType::kArmNeoverseN1:
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 1, CutoffStrategy::Unroll64CRC>();
+#if defined(__aarch64__)
+ default:
+ // Not all ARM processors support the needed instructions, so check here
+ // before trying to use an accelerated implementation.
+ if (SupportsArmCRC32PMULL()) {
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 1, CutoffStrategy::Unroll64CRC>();
+ } else {
+ return nullptr;
+ }
+#else
+ default:
+ // Something else, play it safe and assume slow PCLMULQDQ.
+ return new CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 0, CutoffStrategy::Fold3>();
+#endif
+ }
+}
+
+std::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll() {
+ auto ret = std::vector<std::unique_ptr<CRCImpl>>();
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 0, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 1, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 2, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 3, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 0, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 1, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 2, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 3, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 0, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 1, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 2, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 3, CutoffStrategy::Fold3>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 0, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 1, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 2, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 1, 3, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 0, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 1, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 2, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 2, 3, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 0, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 1, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 2, CutoffStrategy::Unroll64CRC>>());
+ ret.push_back(absl::make_unique<CRC32AcceleratedX86ARMCombinedMultipleStreams<
+ 3, 3, CutoffStrategy::Unroll64CRC>>());
+
+ return ret;
+}
+
+#else // !ABSL_INTERNAL_CAN_USE_SIMD_CRC32C
+
+std::vector<std::unique_ptr<CRCImpl>> NewCRC32AcceleratedX86ARMCombinedAll() {
+ return std::vector<std::unique_ptr<CRCImpl>>();
+}
+
+// no hardware acceleration available
+CRCImpl* TryNewCRC32AcceleratedX86ARMCombined() { return nullptr; }
+
+#endif
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_arm_intrinsics.h b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_arm_intrinsics.h
new file mode 100644
index 0000000000..9e5ccfc49d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_arm_intrinsics.h
@@ -0,0 +1,79 @@
+// 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_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_
+#define ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_
+
+#include "absl/base/config.h"
+
+#ifdef __aarch64__
+#include <arm_neon.h>
+
+typedef int64x2_t __m128i; /* 128-bit vector containing integers */
+#define vreinterpretq_m128i_s32(x) vreinterpretq_s64_s32(x)
+#define vreinterpretq_s64_m128i(x) (x)
+
+// Guarantees that every preceding store is globally visible before any
+// subsequent store.
+// https://msdn.microsoft.com/en-us/library/5h2w73d1%28v=vs.90%29.aspx
+static inline __attribute__((always_inline)) void _mm_sfence(void) {
+ __sync_synchronize();
+}
+
+// Load 128-bits of integer data from unaligned memory into dst. This intrinsic
+// may perform better than _mm_loadu_si128 when the data crosses a cache line
+// boundary.
+//
+// dst[127:0] := MEM[mem_addr+127:mem_addr]
+//
+// https://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_mm_lddqu_si128
+#define _mm_lddqu_si128 _mm_loadu_si128
+
+// Loads 128-bit value. :
+// https://msdn.microsoft.com/zh-cn/library/f4k12ae8(v=vs.90).aspx
+static inline __attribute__((always_inline)) __m128i _mm_loadu_si128(
+ const __m128i *p) {
+ return vreinterpretq_m128i_s32(vld1q_s32((const int32_t *)p));
+}
+
+// Stores the data in a to the address p without polluting the caches. If the
+// cache line containing address p is already in the cache, the cache will be
+// updated.
+// https://msdn.microsoft.com/en-us/library/ba08y07y%28v=vs.90%29.aspx
+static inline __attribute__((always_inline)) void _mm_stream_si128(__m128i *p,
+ __m128i a) {
+#if ABSL_HAVE_BUILTIN(__builtin_nontemporal_store)
+ __builtin_nontemporal_store(a, p);
+#else
+ vst1q_s64((int64_t *)p, vreinterpretq_s64_m128i(a));
+#endif
+}
+
+// Sets the 16 signed 8-bit integer values.
+// https://msdn.microsoft.com/en-us/library/x0cx8zd3(v=vs.90).aspx
+static inline __attribute__((always_inline)) __m128i _mm_set_epi8(
+ signed char b15, signed char b14, signed char b13, signed char b12,
+ signed char b11, signed char b10, signed char b9, signed char b8,
+ signed char b7, signed char b6, signed char b5, signed char b4,
+ signed char b3, signed char b2, signed char b1, signed char b0) {
+ int8_t __attribute__((aligned(16)))
+ data[16] = {(int8_t)b0, (int8_t)b1, (int8_t)b2, (int8_t)b3,
+ (int8_t)b4, (int8_t)b5, (int8_t)b6, (int8_t)b7,
+ (int8_t)b8, (int8_t)b9, (int8_t)b10, (int8_t)b11,
+ (int8_t)b12, (int8_t)b13, (int8_t)b14, (int8_t)b15};
+ return (__m128i)vld1q_s8(data);
+}
+#endif // __aarch64__
+
+#endif // ABSL_CRC_INTERNAL_NON_TEMPORAL_ARM_INTRINSICS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h
new file mode 100644
index 0000000000..b3d94badfc
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/crc/internal/non_temporal_memcpy.h
@@ -0,0 +1,180 @@
+// 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_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_
+#define ABSL_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_
+
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+#ifdef __SSE__
+#include <xmmintrin.h>
+#endif
+
+#ifdef __SSE2__
+#include <emmintrin.h>
+#endif
+
+#ifdef __SSE3__
+#include <pmmintrin.h>
+#endif
+
+#ifdef __AVX__
+#include <immintrin.h>
+#endif
+
+#ifdef __aarch64__
+#include "absl/crc/internal/non_temporal_arm_intrinsics.h"
+#endif
+
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace crc_internal {
+
+// This non-temporal memcpy does regular load and non-temporal store memory
+// copy. It is compatible to both 16-byte aligned and unaligned addresses. If
+// data at the destination is not immediately accessed, using non-temporal
+// memcpy can save 1 DRAM load of the destination cacheline.
+constexpr size_t kCacheLineSize = ABSL_CACHELINE_SIZE;
+
+// If the objects overlap, the behavior is undefined.
+inline void *non_temporal_store_memcpy(void *__restrict dst,
+ const void *__restrict src, size_t len) {
+#if defined(__SSE3__) || defined(__aarch64__) || \
+ (defined(_MSC_VER) && defined(__AVX__))
+ // This implementation requires SSE3.
+ // MSVC cannot target SSE3 directly, but when MSVC targets AVX,
+ // SSE3 support is implied.
+ uint8_t *d = reinterpret_cast<uint8_t *>(dst);
+ const uint8_t *s = reinterpret_cast<const uint8_t *>(src);
+
+ // memcpy() the misaligned header. At the end of this if block, <d> is
+ // aligned to a 64-byte cacheline boundary or <len> == 0.
+ if (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1)) {
+ uintptr_t bytes_before_alignment_boundary =
+ kCacheLineSize -
+ (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1));
+ size_t header_len = (std::min)(bytes_before_alignment_boundary, len);
+ assert(bytes_before_alignment_boundary < kCacheLineSize);
+ memcpy(d, s, header_len);
+ d += header_len;
+ s += header_len;
+ len -= header_len;
+ }
+
+ if (len >= kCacheLineSize) {
+ _mm_sfence();
+ __m128i *dst_cacheline = reinterpret_cast<__m128i *>(d);
+ const __m128i *src_cacheline = reinterpret_cast<const __m128i *>(s);
+ constexpr int kOpsPerCacheLine = kCacheLineSize / sizeof(__m128i);
+ size_t loops = len / kCacheLineSize;
+
+ while (len >= kCacheLineSize) {
+ __m128i temp1, temp2, temp3, temp4;
+ temp1 = _mm_lddqu_si128(src_cacheline + 0);
+ temp2 = _mm_lddqu_si128(src_cacheline + 1);
+ temp3 = _mm_lddqu_si128(src_cacheline + 2);
+ temp4 = _mm_lddqu_si128(src_cacheline + 3);
+ _mm_stream_si128(dst_cacheline + 0, temp1);
+ _mm_stream_si128(dst_cacheline + 1, temp2);
+ _mm_stream_si128(dst_cacheline + 2, temp3);
+ _mm_stream_si128(dst_cacheline + 3, temp4);
+ src_cacheline += kOpsPerCacheLine;
+ dst_cacheline += kOpsPerCacheLine;
+ len -= kCacheLineSize;
+ }
+ d += loops * kCacheLineSize;
+ s += loops * kCacheLineSize;
+ _mm_sfence();
+ }
+
+ // memcpy the tail.
+ if (len) {
+ memcpy(d, s, len);
+ }
+ return dst;
+#else
+ // Fallback to regular memcpy.
+ return memcpy(dst, src, len);
+#endif // __SSE3__ || __aarch64__ || (_MSC_VER && __AVX__)
+}
+
+inline void *non_temporal_store_memcpy_avx(void *__restrict dst,
+ const void *__restrict src,
+ size_t len) {
+#ifdef __AVX__
+ uint8_t *d = reinterpret_cast<uint8_t *>(dst);
+ const uint8_t *s = reinterpret_cast<const uint8_t *>(src);
+
+ // memcpy() the misaligned header. At the end of this if block, <d> is
+ // aligned to a 64-byte cacheline boundary or <len> == 0.
+ if (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1)) {
+ uintptr_t bytes_before_alignment_boundary =
+ kCacheLineSize -
+ (reinterpret_cast<uintptr_t>(d) & (kCacheLineSize - 1));
+ size_t header_len = (std::min)(bytes_before_alignment_boundary, len);
+ assert(bytes_before_alignment_boundary < kCacheLineSize);
+ memcpy(d, s, header_len);
+ d += header_len;
+ s += header_len;
+ len -= header_len;
+ }
+
+ if (len >= kCacheLineSize) {
+ _mm_sfence();
+ __m256i *dst_cacheline = reinterpret_cast<__m256i *>(d);
+ const __m256i *src_cacheline = reinterpret_cast<const __m256i *>(s);
+ constexpr int kOpsPerCacheLine = kCacheLineSize / sizeof(__m256i);
+ size_t loops = len / kCacheLineSize;
+
+ while (len >= kCacheLineSize) {
+ __m256i temp1, temp2;
+ temp1 = _mm256_lddqu_si256(src_cacheline + 0);
+ temp2 = _mm256_lddqu_si256(src_cacheline + 1);
+ _mm256_stream_si256(dst_cacheline + 0, temp1);
+ _mm256_stream_si256(dst_cacheline + 1, temp2);
+ src_cacheline += kOpsPerCacheLine;
+ dst_cacheline += kOpsPerCacheLine;
+ len -= kCacheLineSize;
+ }
+ d += loops * kCacheLineSize;
+ s += loops * kCacheLineSize;
+ _mm_sfence();
+ }
+
+ // memcpy the tail.
+ if (len) {
+ memcpy(d, s, len);
+ }
+ return dst;
+#else
+ // Fallback to regular memcpy when AVX is not available.
+ return memcpy(dst, src, len);
+#endif // __AVX__
+}
+
+} // namespace crc_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CRC_INTERNAL_NON_TEMPORAL_MEMCPY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc b/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc
index affade3b66..ef8ab9e5a8 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/failure_signal_handler.cc
@@ -50,7 +50,9 @@
#ifndef _WIN32
#define ABSL_HAVE_SIGACTION
// Apple WatchOS and TVOS don't allow sigaltstack
-#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
+// Apple macOS has sigaltstack, but using it makes backtrace() unusable.
+#if !(defined(TARGET_OS_OSX) && TARGET_OS_OSX) && \
+ !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
!(defined(TARGET_OS_TV) && TARGET_OS_TV) && !defined(__QNX__)
#define ABSL_HAVE_SIGALTSTACK
#endif
@@ -133,10 +135,11 @@ static bool SetupAlternateStackOnce() {
#if defined(__wasm__) || defined (__asjms__)
const size_t page_mask = getpagesize() - 1;
#else
- const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
+ const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1;
#endif
size_t stack_size =
- (std::max<size_t>(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
+ (std::max(static_cast<size_t>(SIGSTKSZ), size_t{65536}) + page_mask) &
+ ~page_mask;
#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
@@ -216,7 +219,7 @@ static void InstallOneFailureHandler(FailureSignalData* data,
#endif
static void WriteToStderr(const char* data) {
- absl::raw_logging_internal::AsyncSignalSafeWriteToStderr(data, strlen(data));
+ absl::raw_log_internal::AsyncSignalSafeWriteToStderr(data, strlen(data));
}
static void WriteSignalMessage(int signo, int cpu,
@@ -289,7 +292,7 @@ static void WriteFailureInfo(int signo, void* ucontext, int cpu,
// some platforms.
static void PortableSleepForSeconds(int seconds) {
#ifdef _WIN32
- Sleep(seconds * 1000);
+ Sleep(static_cast<DWORD>(seconds * 1000));
#else
struct timespec sleep_time;
sleep_time.tv_sec = seconds;
@@ -323,9 +326,9 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
const GetTidType this_tid = absl::base_internal::GetTID();
GetTidType previous_failed_tid = 0;
- if (!failed_tid.compare_exchange_strong(
- previous_failed_tid, static_cast<intptr_t>(this_tid),
- std::memory_order_acq_rel, std::memory_order_relaxed)) {
+ if (!failed_tid.compare_exchange_strong(previous_failed_tid, this_tid,
+ std::memory_order_acq_rel,
+ std::memory_order_relaxed)) {
ABSL_RAW_LOG(
ERROR,
"Signal %d raised at PC=%p while already in AbslFailureSignalHandler()",
@@ -354,7 +357,7 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
if (fsh_options.alarm_on_failure_secs > 0) {
alarm(0); // Cancel any existing alarms.
signal(SIGALRM, ImmediateAbortSignalHandler);
- alarm(fsh_options.alarm_on_failure_secs);
+ alarm(static_cast<unsigned int>(fsh_options.alarm_on_failure_secs));
}
#endif
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc
index 4be6256bfb..91eaa76f8a 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/address_is_readable.cc
@@ -52,7 +52,7 @@ namespace debugging_internal {
bool AddressIsReadable(const void *addr) {
// Align address on 8-byte boundary. On aarch64, checking last
// byte before inaccessible page returned unexpected EFAULT.
- const uintptr_t u_addr = reinterpret_cast<uintptr_t>(addr) & ~7;
+ const uintptr_t u_addr = reinterpret_cast<uintptr_t>(addr) & ~uintptr_t{7};
addr = reinterpret_cast<const void *>(u_addr);
// rt_sigprocmask below will succeed for this input.
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc
index 93ae32796c..f2832915bf 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.cc
@@ -151,12 +151,12 @@ static const AbbrevPair kSubstitutionList[] = {
// State needed for demangling. This struct is copied in almost every stack
// frame, so every byte counts.
typedef struct {
- int mangled_idx; // Cursor of mangled name.
- int out_cur_idx; // Cursor of output string.
- int prev_name_idx; // For constructors/destructors.
- signed int prev_name_length : 16; // For constructors/destructors.
- signed int nest_level : 15; // For nested names.
- unsigned int append : 1; // Append flag.
+ int mangled_idx; // Cursor of mangled name.
+ int out_cur_idx; // Cursor of output string.
+ int prev_name_idx; // For constructors/destructors.
+ unsigned int prev_name_length : 16; // For constructors/destructors.
+ signed int nest_level : 15; // For nested names.
+ unsigned int append : 1; // Append flag.
// Note: for some reason MSVC can't pack "bool append : 1" into the same int
// with the above two fields, so we use an int instead. Amusingly it can pack
// "signed bool" as expected, but relying on that to continue to be a legal
@@ -235,8 +235,8 @@ static size_t StrLen(const char *str) {
}
// Returns true if "str" has at least "n" characters remaining.
-static bool AtLeastNumCharsRemaining(const char *str, int n) {
- for (int i = 0; i < n; ++i) {
+static bool AtLeastNumCharsRemaining(const char *str, size_t n) {
+ for (size_t i = 0; i < n; ++i) {
if (str[i] == '\0') {
return false;
}
@@ -253,18 +253,20 @@ static bool StrPrefix(const char *str, const char *prefix) {
return prefix[i] == '\0'; // Consumed everything in "prefix".
}
-static void InitState(State *state, const char *mangled, char *out,
- int out_size) {
+static void InitState(State* state,
+ const char* mangled,
+ char* out,
+ size_t out_size) {
state->mangled_begin = mangled;
state->out = out;
- state->out_end_idx = out_size;
+ state->out_end_idx = static_cast<int>(out_size);
state->recursion_depth = 0;
state->steps = 0;
state->parse_state.mangled_idx = 0;
state->parse_state.out_cur_idx = 0;
state->parse_state.prev_name_idx = 0;
- state->parse_state.prev_name_length = -1;
+ state->parse_state.prev_name_length = 0;
state->parse_state.nest_level = -1;
state->parse_state.append = true;
}
@@ -356,8 +358,8 @@ static bool ZeroOrMore(ParseFunc parse_func, State *state) {
// Append "str" at "out_cur_idx". If there is an overflow, out_cur_idx is
// set to out_end_idx+1. The output string is ensured to
// always terminate with '\0' as long as there is no overflow.
-static void Append(State *state, const char *const str, const int length) {
- for (int i = 0; i < length; ++i) {
+static void Append(State *state, const char *const str, const size_t length) {
+ for (size_t i = 0; i < length; ++i) {
if (state->parse_state.out_cur_idx + 1 <
state->out_end_idx) { // +1 for '\0'
state->out[state->parse_state.out_cur_idx++] = str[i];
@@ -420,7 +422,7 @@ static bool EndsWith(State *state, const char chr) {
// Append "str" with some tweaks, iff "append" state is true.
static void MaybeAppendWithLength(State *state, const char *const str,
- const int length) {
+ const size_t length) {
if (state->parse_state.append && length > 0) {
// Append a space if the output buffer ends with '<' and "str"
// starts with '<' to avoid <<<.
@@ -432,14 +434,14 @@ static void MaybeAppendWithLength(State *state, const char *const str,
if (state->parse_state.out_cur_idx < state->out_end_idx &&
(IsAlpha(str[0]) || str[0] == '_')) {
state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;
- state->parse_state.prev_name_length = length;
+ state->parse_state.prev_name_length = static_cast<unsigned int>(length);
}
Append(state, str, length);
}
}
// Appends a positive decimal number to the output if appending is enabled.
-static bool MaybeAppendDecimal(State *state, unsigned int val) {
+static bool MaybeAppendDecimal(State *state, int val) {
// Max {32-64}-bit unsigned int is 20 digits.
constexpr size_t kMaxLength = 20;
char buf[kMaxLength];
@@ -451,12 +453,12 @@ static bool MaybeAppendDecimal(State *state, unsigned int val) {
// one-past-the-end and manipulate one character before the pointer.
char *p = &buf[kMaxLength];
do { // val=0 is the only input that should write a leading zero digit.
- *--p = (val % 10) + '0';
+ *--p = static_cast<char>((val % 10) + '0');
val /= 10;
} while (p > buf && val != 0);
// 'p' landed on the last character we set. How convenient.
- Append(state, p, kMaxLength - (p - buf));
+ Append(state, p, kMaxLength - static_cast<size_t>(p - buf));
}
return true;
@@ -466,7 +468,7 @@ static bool MaybeAppendDecimal(State *state, unsigned int val) {
// Returns true so that it can be placed in "if" conditions.
static bool MaybeAppend(State *state, const char *const str) {
if (state->parse_state.append) {
- int length = StrLen(str);
+ size_t length = StrLen(str);
MaybeAppendWithLength(state, str, length);
}
return true;
@@ -521,10 +523,10 @@ static void MaybeCancelLastSeparator(State *state) {
// Returns true if the identifier of the given length pointed to by
// "mangled_cur" is anonymous namespace.
-static bool IdentifierIsAnonymousNamespace(State *state, int length) {
+static bool IdentifierIsAnonymousNamespace(State *state, size_t length) {
// Returns true if "anon_prefix" is a proper prefix of "mangled_cur".
static const char anon_prefix[] = "_GLOBAL__N_";
- return (length > static_cast<int>(sizeof(anon_prefix) - 1) &&
+ return (length > (sizeof(anon_prefix) - 1) &&
StrPrefix(RemainingInput(state), anon_prefix));
}
@@ -542,12 +544,13 @@ static bool ParseUnnamedTypeName(State *state);
static bool ParseNumber(State *state, int *number_out);
static bool ParseFloatNumber(State *state);
static bool ParseSeqId(State *state);
-static bool ParseIdentifier(State *state, int length);
+static bool ParseIdentifier(State *state, size_t length);
static bool ParseOperatorName(State *state, int *arity);
static bool ParseSpecialName(State *state);
static bool ParseCallOffset(State *state);
static bool ParseNVOffset(State *state);
static bool ParseVOffset(State *state);
+static bool ParseAbiTags(State *state);
static bool ParseCtorDtorName(State *state);
static bool ParseDecltype(State *state);
static bool ParseType(State *state);
@@ -601,7 +604,7 @@ static bool ParseSubstitution(State *state, bool accept_std);
//
// Reference:
// - Itanium C++ ABI
-// <https://mentorembedded.github.io/cxx-abi/abi.html#mangling>
+// <https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling>
// <mangled-name> ::= _Z <encoding>
static bool ParseMangledName(State *state) {
@@ -741,17 +744,42 @@ static bool ParsePrefix(State *state) {
return true;
}
-// <unqualified-name> ::= <operator-name>
-// ::= <ctor-dtor-name>
-// ::= <source-name>
-// ::= <local-source-name> // GCC extension; see below.
-// ::= <unnamed-type-name>
+// <unqualified-name> ::= <operator-name> [<abi-tags>]
+// ::= <ctor-dtor-name> [<abi-tags>]
+// ::= <source-name> [<abi-tags>]
+// ::= <local-source-name> [<abi-tags>]
+// ::= <unnamed-type-name> [<abi-tags>]
+//
+// <local-source-name> is a GCC extension; see below.
static bool ParseUnqualifiedName(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
- return (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) ||
- ParseSourceName(state) || ParseLocalSourceName(state) ||
- ParseUnnamedTypeName(state));
+ if (ParseOperatorName(state, nullptr) || ParseCtorDtorName(state) ||
+ ParseSourceName(state) || ParseLocalSourceName(state) ||
+ ParseUnnamedTypeName(state)) {
+ return ParseAbiTags(state);
+ }
+ return false;
+}
+
+// <abi-tags> ::= <abi-tag> [<abi-tags>]
+// <abi-tag> ::= B <source-name>
+static bool ParseAbiTags(State *state) {
+ ComplexityGuard guard(state);
+ if (guard.IsTooComplex()) return false;
+
+ while (ParseOneCharToken(state, 'B')) {
+ ParseState copy = state->parse_state;
+ MaybeAppend(state, "[abi:");
+
+ if (!ParseSourceName(state)) {
+ state->parse_state = copy;
+ return false;
+ }
+ MaybeAppend(state, "]");
+ }
+
+ return true;
}
// <source-name> ::= <positive length number> <identifier>
@@ -760,7 +788,8 @@ static bool ParseSourceName(State *state) {
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
int length = -1;
- if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
+ if (ParseNumber(state, &length) &&
+ ParseIdentifier(state, static_cast<size_t>(length))) {
return true;
}
state->parse_state = copy;
@@ -838,7 +867,7 @@ static bool ParseNumber(State *state, int *number_out) {
uint64_t number = 0;
for (; *p != '\0'; ++p) {
if (IsDigit(*p)) {
- number = number * 10 + (*p - '0');
+ number = number * 10 + static_cast<uint64_t>(*p - '0');
} else {
break;
}
@@ -853,7 +882,7 @@ static bool ParseNumber(State *state, int *number_out) {
state->parse_state.mangled_idx += p - RemainingInput(state);
if (number_out != nullptr) {
// Note: possibly truncate "number".
- *number_out = number;
+ *number_out = static_cast<int>(number);
}
return true;
}
@@ -897,10 +926,10 @@ static bool ParseSeqId(State *state) {
}
// <identifier> ::= <unqualified source code identifier> (of given length)
-static bool ParseIdentifier(State *state, int length) {
+static bool ParseIdentifier(State *state, size_t length) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
- if (length < 0 || !AtLeastNumCharsRemaining(RemainingInput(state), length)) {
+ if (!AtLeastNumCharsRemaining(RemainingInput(state), length)) {
return false;
}
if (IdentifierIsAnonymousNamespace(state, length)) {
@@ -1947,7 +1976,7 @@ static bool Overflowed(const State *state) {
}
// The demangler entry point.
-bool Demangle(const char *mangled, char *out, int out_size) {
+bool Demangle(const char* mangled, char* out, size_t out_size) {
State state;
InitState(&state, mangled, out, out_size);
return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h
index c314d9bc23..e1f156989f 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/demangle.h
@@ -62,7 +62,7 @@ namespace debugging_internal {
// Demangle `mangled`. On success, return true and write the
// demangled symbol name to `out`. Otherwise, return false.
// `out` is modified even if demangling is unsuccessful.
-bool Demangle(const char *mangled, char *out, int out_size);
+bool Demangle(const char* mangled, char* out, size_t out_size);
} // namespace debugging_internal
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
index a9d667143a..42dcd3cde9 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
@@ -91,7 +91,7 @@ int ElfMemImage::GetNumSymbols() const {
return 0;
}
// See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash
- return hash_[1];
+ return static_cast<int>(hash_[1]);
}
const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const {
@@ -105,11 +105,9 @@ const ElfW(Versym) *ElfMemImage::GetVersym(int index) const {
}
const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const {
- ABSL_RAW_CHECK(index < ehdr_->e_phnum, "index out of range");
- return GetTableElement<ElfW(Phdr)>(ehdr_,
- ehdr_->e_phoff,
- ehdr_->e_phentsize,
- index);
+ ABSL_RAW_CHECK(index >= 0 && index < ehdr_->e_phnum, "index out of range");
+ return GetTableElement<ElfW(Phdr)>(ehdr_, ehdr_->e_phoff, ehdr_->e_phentsize,
+ static_cast<size_t>(index));
}
const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const {
@@ -159,7 +157,8 @@ void ElfMemImage::Init(const void *base) {
hash_ = nullptr;
strsize_ = 0;
verdefnum_ = 0;
- link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this.
+ // Sentinel: PT_LOAD .p_vaddr can't possibly be this.
+ link_base_ = ~ElfW(Addr){0}; // NOLINT(readability/braces)
if (!base) {
return;
}
@@ -218,11 +217,11 @@ void ElfMemImage::Init(const void *base) {
}
ptrdiff_t relocation =
base_as_char - reinterpret_cast<const char *>(link_base_);
- ElfW(Dyn) *dynamic_entry =
- reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr +
- relocation);
+ ElfW(Dyn)* dynamic_entry = reinterpret_cast<ElfW(Dyn)*>(
+ static_cast<intptr_t>(dynamic_program_header->p_vaddr) + relocation);
for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
- const auto value = dynamic_entry->d_un.d_val + relocation;
+ const auto value =
+ static_cast<intptr_t>(dynamic_entry->d_un.d_val) + relocation;
switch (dynamic_entry->d_tag) {
case DT_HASH:
hash_ = reinterpret_cast<ElfW(Word) *>(value);
@@ -240,10 +239,10 @@ void ElfMemImage::Init(const void *base) {
verdef_ = reinterpret_cast<ElfW(Verdef) *>(value);
break;
case DT_VERDEFNUM:
- verdefnum_ = dynamic_entry->d_un.d_val;
+ verdefnum_ = static_cast<size_t>(dynamic_entry->d_un.d_val);
break;
case DT_STRSZ:
- strsize_ = dynamic_entry->d_un.d_val;
+ strsize_ = static_cast<size_t>(dynamic_entry->d_un.d_val);
break;
default:
// Unrecognized entries explicitly ignored.
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/examine_stack.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/examine_stack.cc
index 5bdd341e1b..57863228d8 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/examine_stack.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/examine_stack.cc
@@ -278,13 +278,14 @@ void DumpStackTrace(int min_dropped_frames, int max_num_frames,
void* stack_buf[kDefaultDumpStackFramesLimit];
void** stack = stack_buf;
int num_stack = kDefaultDumpStackFramesLimit;
- int allocated_bytes = 0;
+ size_t allocated_bytes = 0;
if (num_stack >= max_num_frames) {
// User requested fewer frames than we already have space for.
num_stack = max_num_frames;
} else {
- const size_t needed_bytes = max_num_frames * sizeof(stack[0]);
+ const size_t needed_bytes =
+ static_cast<size_t>(max_num_frames) * sizeof(stack[0]);
void* p = Allocate(needed_bytes);
if (p != nullptr) { // We got the space.
num_stack = max_num_frames;
@@ -293,12 +294,13 @@ void DumpStackTrace(int min_dropped_frames, int max_num_frames,
}
}
- size_t depth = absl::GetStackTrace(stack, num_stack, min_dropped_frames + 1);
- for (size_t i = 0; i < depth; i++) {
+ int depth = absl::GetStackTrace(stack, num_stack, min_dropped_frames + 1);
+ for (int i = 0; i < depth; i++) {
if (symbolize_stacktrace) {
- DumpPCAndSymbol(writer, writer_arg, stack[i], " ");
+ DumpPCAndSymbol(writer, writer_arg, stack[static_cast<size_t>(i)],
+ " ");
} else {
- DumpPC(writer, writer_arg, stack[i], " ");
+ DumpPC(writer, writer_arg, stack[static_cast<size_t>(i)], " ");
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
index 4f9db9d66b..71cdaf0940 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -19,7 +19,7 @@
#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems
#include "absl/debugging/stacktrace.h"
-static const uintptr_t kUnknownFrameSize = 0;
+static const size_t kUnknownFrameSize = 0;
#if defined(__linux__)
// Returns the address of the VDSO __kernel_rt_sigreturn function, if present.
@@ -65,11 +65,12 @@ static const unsigned char* GetKernelRtSigreturnAddress() {
// Compute the size of a stack frame in [low..high). We assume that
// low < high. Return size of kUnknownFrameSize.
template<typename T>
-static inline uintptr_t ComputeStackFrameSize(const T* low,
- const T* high) {
+static inline size_t ComputeStackFrameSize(const T* low,
+ const T* high) {
const char* low_char_ptr = reinterpret_cast<const char *>(low);
const char* high_char_ptr = reinterpret_cast<const char *>(high);
- return low < high ? high_char_ptr - low_char_ptr : kUnknownFrameSize;
+ return low < high ? static_cast<size_t>(high_char_ptr - low_char_ptr)
+ : kUnknownFrameSize;
}
// Given a pointer to a stack frame, locate and return the calling
@@ -110,15 +111,15 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
}
#endif
- // aarch64 ABI requires stack pointer to be 16-byte-aligned.
- if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 15) != 0)
+ // The frame pointer should be 8-byte aligned.
+ if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 7) != 0)
return nullptr;
// Check frame size. In strict mode, we assume frames to be under
// 100,000 bytes. In non-strict mode, we relax the limit to 1MB.
if (check_frame_size) {
- const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
- const uintptr_t frame_size =
+ const size_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
+ const size_t frame_size =
ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
if (frame_size == kUnknownFrameSize || frame_size > max_size)
return nullptr;
@@ -165,7 +166,8 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
} else {
result[n] = prev_return_address;
if (IS_STACK_FRAMES) {
- sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer);
+ sizes[n] = static_cast<int>(
+ ComputeStackFrameSize(frame_pointer, next_frame_pointer));
}
n++;
}
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
index b2792a1f3a..5fa169a7ec 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -80,7 +80,7 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
if (IS_STACK_FRAMES) {
// No implementation for finding out the stack frame sizes yet.
- memset(sizes, 0, sizeof(*sizes) * result_count);
+ memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count));
}
if (min_dropped_frames != nullptr) {
if (size - skip_count - max_depth > 0) {
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
index 7123b71bc3..20183fa321 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
@@ -30,56 +30,14 @@
#include <cassert>
#include <cstdint>
#include <iostream>
+#include <limits>
+#include <utility>
#include "absl/base/attributes.h"
-#include "absl/debugging/internal/address_is_readable.h"
-#include "absl/debugging/internal/vdso_support.h"
#include "absl/debugging/stacktrace.h"
static const uintptr_t kUnknownFrameSize = 0;
-#if defined(__linux__)
-// Returns the address of the VDSO __kernel_rt_sigreturn function, if present.
-static const unsigned char *GetKernelRtSigreturnAddress() {
- constexpr uintptr_t kImpossibleAddress = 0;
- ABSL_CONST_INIT static std::atomic<uintptr_t> memoized(kImpossibleAddress);
- uintptr_t address = memoized.load(std::memory_order_relaxed);
- if (address != kImpossibleAddress) {
- return reinterpret_cast<const unsigned char *>(address);
- }
-
- address = reinterpret_cast<uintptr_t>(nullptr);
-
-#if ABSL_HAVE_VDSO_SUPPORT
- absl::debugging_internal::VDSOSupport vdso;
- if (vdso.IsPresent()) {
- absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;
- // Symbol versioning pulled from arch/riscv/kernel/vdso/vdso.lds at v5.10.
- auto lookup = [&](int type) {
- return vdso.LookupSymbol("__vdso_rt_sigreturn", "LINUX_4.15", type,
- &symbol_info);
- };
- if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||
- symbol_info.address == nullptr) {
- // Unexpected: VDSO is present, yet the expected symbol is missing or
- // null.
- assert(false && "VDSO is present, but doesn't have expected symbol");
- } else {
- if (reinterpret_cast<uintptr_t>(symbol_info.address) !=
- kImpossibleAddress) {
- address = reinterpret_cast<uintptr_t>(symbol_info.address);
- } else {
- assert(false && "VDSO returned invalid address");
- }
- }
- }
-#endif
-
- memoized.store(address, std::memory_order_relaxed);
- return reinterpret_cast<const unsigned char *>(address);
-}
-#endif // __linux__
-
// Compute the size of a stack frame in [low..high). We assume that low < high.
// Return size of kUnknownFrameSize.
template <typename T>
@@ -96,7 +54,8 @@ static inline uintptr_t ComputeStackFrameSize(const T *low, const T *high) {
template <bool STRICT_UNWINDING, bool WITH_CONTEXT>
ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack.
ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
-static void ** NextStackFrame(void **old_frame_pointer, const void *uc) {
+static void ** NextStackFrame(void **old_frame_pointer, const void *uc,
+ const std::pair<size_t, size_t> range) {
// .
// .
// .
@@ -114,55 +73,43 @@ static void ** NextStackFrame(void **old_frame_pointer, const void *uc) {
// $sp ->| ... |
// +----------------+
void **new_frame_pointer = reinterpret_cast<void **>(old_frame_pointer[-2]);
- bool check_frame_size = true;
-
-#if defined(__linux__)
- if (WITH_CONTEXT && uc != nullptr) {
- // Check to see if next frame's return address is __kernel_rt_sigreturn.
- if (old_frame_pointer[-1] == GetKernelRtSigreturnAddress()) {
- const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);
- // old_frame_pointer is not suitable for unwinding, look at ucontext to
- // discover frame pointer before signal.
- //
- // RISCV ELF psABI has the frame pointer at x8/fp/s0.
- // -- RISCV psABI Table 18.2
- void **const pre_signal_frame_pointer =
- reinterpret_cast<void **>(ucv->uc_mcontext.__gregs[8]);
-
- // Check the alleged frame pointer is actually readable. This is to
- // prevent "double fault" in case we hit the first fault due to stack
- // corruption.
- if (!absl::debugging_internal::AddressIsReadable(
- pre_signal_frame_pointer))
- return nullptr;
-
- // Alleged frame pointer is readable, use it for further unwinding.
- new_frame_pointer = pre_signal_frame_pointer;
-
- // Skip frame size check if we return from a signal. We may be using an
- // alterate stack for signals.
- check_frame_size = false;
- }
- }
-#endif
+ uintptr_t frame_pointer = reinterpret_cast<uintptr_t>(new_frame_pointer);
// The RISCV ELF psABI mandates that the stack pointer is always 16-byte
// aligned.
- // FIXME(abdulras) this doesn't hold for ILP32E which only mandates a 4-byte
+ // TODO(#1236) this doesn't hold for ILP32E which only mandates a 4-byte
// alignment.
- if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 15) != 0)
+ if (frame_pointer & 15)
return nullptr;
+ // If the new frame pointer matches the signal context, avoid terminating
+ // early to deal with alternate signal stacks.
+ if (WITH_CONTEXT)
+ if (const ucontext_t *ucv = static_cast<const ucontext_t *>(uc))
+ // RISCV ELF psABI has the frame pointer at x8/fp/s0.
+ // -- RISCV psABI Table 18.2
+ if (ucv->uc_mcontext.__gregs[8] == frame_pointer)
+ return new_frame_pointer;
+
// Check frame size. In strict mode, we assume frames to be under 100,000
// bytes. In non-strict mode, we relax the limit to 1MB.
- if (check_frame_size) {
- const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
- const uintptr_t frame_size =
- ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
- if (frame_size == kUnknownFrameSize || frame_size > max_size)
+ const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
+ const uintptr_t frame_size =
+ ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
+ if (frame_size == kUnknownFrameSize) {
+ if (STRICT_UNWINDING)
+ return nullptr;
+
+ // In non-strict mode permit non-contiguous stacks (e.g. alternate signal
+ // frame handling).
+ if (reinterpret_cast<uintptr_t>(new_frame_pointer) < range.first ||
+ reinterpret_cast<uintptr_t>(new_frame_pointer) > range.second)
return nullptr;
}
+ if (frame_size > max_size)
+ return nullptr;
+
return new_frame_pointer;
}
@@ -180,6 +127,12 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
#error reading stack pointer not yet supported on this platform
#endif
+ std::pair<size_t, size_t> stack = {
+ // assume that the first page is not the stack.
+ static_cast<size_t>(sysconf(_SC_PAGESIZE)),
+ std::numeric_limits<size_t>::max() - sizeof(void *)
+ };
+
int n = 0;
void *return_address = nullptr;
while (frame_pointer && n < max_depth) {
@@ -190,7 +143,8 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
// non-strict unwinding rules to produce a stack trace that is as complete
// as possible (even if it contains a few bogus entries in some rare cases).
void **next_frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
+ NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,
+ stack);
if (skip_count > 0) {
skip_count--;
@@ -217,7 +171,8 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
num_dropped_frames++;
}
frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
+ NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp,
+ stack);
}
*min_dropped_frames = num_dropped_frames;
}
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
index 1c666c8b56..ef2b973ec3 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -63,11 +63,12 @@ static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
const void*, int* min_dropped_frames) {
- int n = 0;
- if (!RtlCaptureStackBackTrace_fn) {
- // can't find a stacktrace with no function to call
+ USHORT n = 0;
+ if (!RtlCaptureStackBackTrace_fn || skip_count < 0 || max_depth < 0) {
+ // can't get a stacktrace with no function/invalid args
} else {
- n = (int)RtlCaptureStackBackTrace_fn(skip_count + 2, max_depth, result, 0);
+ n = RtlCaptureStackBackTrace_fn(static_cast<ULONG>(skip_count) + 2,
+ static_cast<ULONG>(max_depth), result, 0);
}
if (IS_STACK_FRAMES) {
// No implementation for finding out the stack frame sizes yet.
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
index 1b5d8235a8..7b26464eb4 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -29,14 +29,13 @@
#include <cstdint>
#include <limits>
+#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/debugging/internal/address_is_readable.h"
#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems
#include "absl/debugging/stacktrace.h"
-#include "absl/base/internal/raw_logging.h"
-
using absl::debugging_internal::AddressIsReadable;
#if defined(__linux__) && defined(__i386__)
@@ -113,6 +112,10 @@ static int CountPushInstructions(const unsigned char *const addr) {
// Assume stack frames larger than 100,000 bytes are bogus.
static const int kMaxFrameBytes = 100000;
+// Stack end to use when we don't know the actual stack end
+// (effectively just the end of address space).
+constexpr uintptr_t kUnknownStackEnd =
+ std::numeric_limits<size_t>::max() - sizeof(void *);
// Returns the stack frame pointer from signal context, 0 if unknown.
// vuc is a ucontext_t *. We use void* to avoid the use
@@ -140,13 +143,14 @@ static uintptr_t GetFP(const void *vuc) {
// TODO(bcmills): -momit-leaf-frame-pointer is currently the default
// behavior when building with clang. Talk to the C++ toolchain team about
// fixing that.
- if (bp >= sp && bp - sp <= kMaxFrameBytes) return bp;
+ if (bp >= sp && bp - sp <= kMaxFrameBytes)
+ return static_cast<uintptr_t>(bp);
// If bp isn't a plausible frame pointer, return the stack pointer instead.
// If we're lucky, it points to the start of a stack frame; otherwise, we'll
// get one frame of garbage in the stack trace and fail the sanity check on
// the next iteration.
- return sp;
+ return static_cast<uintptr_t>(sp);
}
#endif
return 0;
@@ -258,8 +262,26 @@ static void **NextStackFrame(void **old_fp, const void *uc,
// With the stack growing downwards, older stack frame must be
// at a greater address that the current one.
if (new_fp_u <= old_fp_u) return nullptr;
- if (new_fp_u - old_fp_u > kMaxFrameBytes) return nullptr;
+ // If we get a very large frame size, it may be an indication that we
+ // guessed frame pointers incorrectly and now risk a paging fault
+ // dereferencing a wrong frame pointer. Or maybe not because large frames
+ // are possible as well. The main stack is assumed to be readable,
+ // so we assume the large frame is legit if we know the real stack bounds
+ // and are within the stack.
+ if (new_fp_u - old_fp_u > kMaxFrameBytes) {
+ if (stack_high < kUnknownStackEnd &&
+ static_cast<size_t>(getpagesize()) < stack_low) {
+ // Stack bounds are known.
+ if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
+ // new_fp_u is not within the known stack.
+ return nullptr;
+ }
+ } else {
+ // Stack bounds are unknown, prefer truncated stack to possible crash.
+ return nullptr;
+ }
+ }
if (stack_low < old_fp_u && old_fp_u <= stack_high) {
// Old BP was in the expected stack region...
if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
@@ -310,8 +332,9 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
int n = 0;
void **fp = reinterpret_cast<void **>(__builtin_frame_address(0));
- size_t stack_low = getpagesize(); // Assume that the first page is not stack.
- size_t stack_high = std::numeric_limits<size_t>::max() - sizeof(void *);
+ // Assume that the first page is not stack.
+ size_t stack_low = static_cast<size_t>(getpagesize());
+ size_t stack_high = kUnknownStackEnd;
while (fp && n < max_depth) {
if (*(fp + 1) == reinterpret_cast<void *>(0)) {
@@ -327,7 +350,9 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
result[n] = *(fp + 1);
if (IS_STACK_FRAMES) {
if (next_fp > fp) {
- sizes[n] = (uintptr_t)next_fp - (uintptr_t)fp;
+ sizes[n] = static_cast<int>(
+ reinterpret_cast<uintptr_t>(next_fp) -
+ reinterpret_cast<uintptr_t>(fp));
} else {
// A frame-size of 0 is used to indicate unknown frame size.
sizes[n] = 0;
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/vdso_support.cc b/contrib/restricted/abseil-cpp/absl/debugging/internal/vdso_support.cc
index 40eb055f69..8a588eaffe 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/internal/vdso_support.cc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/vdso_support.cc
@@ -193,8 +193,9 @@ long VDSOSupport::InitAndGetCPU(unsigned *cpu, // NOLINT(runtime/int)
ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
int GetCPU() {
unsigned cpu;
- int ret_code = (*VDSOSupport::getcpu_fn_)(&cpu, nullptr, nullptr);
- return ret_code == 0 ? cpu : ret_code;
+ long ret_code = // NOLINT(runtime/int)
+ (*VDSOSupport::getcpu_fn_)(&cpu, nullptr, nullptr);
+ return ret_code == 0 ? static_cast<int>(cpu) : static_cast<int>(ret_code);
}
} // namespace debugging_internal
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/leak_check.h b/contrib/restricted/abseil-cpp/absl/debugging/leak_check.h
index eff162f67f..6bd7940623 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/leak_check.h
+++ b/contrib/restricted/abseil-cpp/absl/debugging/leak_check.h
@@ -37,7 +37,7 @@
// not also use AddressSanitizer). To use the mode, simply pass
// `-fsanitize=leak` to both the compiler and linker. Since GCC does not
// currently provide a way of detecting this mode at compile-time, GCC users
-// must also pass -DLEAK_SANIITIZER to the compiler. An example Bazel command
+// must also pass -DLEAK_SANITIZER to the compiler. An example Bazel command
// could be
//
// $ bazel test --copt=-DLEAK_SANITIZER --copt=-fsanitize=leak
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_darwin.inc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_darwin.inc
index 443ce9efc4..cf63d1919b 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_darwin.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_darwin.inc
@@ -83,13 +83,14 @@ bool Symbolize(const void* pc, char* out, int out_size) {
memmove(out, tmp_buf, len + 1);
}
} else {
- strncpy(out, symbol.c_str(), out_size);
+ strncpy(out, symbol.c_str(), static_cast<size_t>(out_size));
}
if (out[out_size - 1] != '\0') {
// strncpy() does not '\0' terminate when it truncates.
static constexpr char kEllipsis[] = "...";
- int ellipsis_size = std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
+ size_t ellipsis_size =
+ std::min(sizeof(kEllipsis) - 1, static_cast<size_t>(out_size) - 1);
memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
out[out_size - 1] = '\0';
}
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc
index 9bfdd9151a..ffb4eecfb9 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_elf.inc
@@ -205,7 +205,8 @@ struct ObjFile {
// PT_LOAD program header describing executable code.
// Normally we expect just one, but SWIFT binaries have two.
- std::array<ElfW(Phdr), 2> phdr;
+ // CUDA binaries have 3 (see cr/473913254 description).
+ std::array<ElfW(Phdr), 4> phdr;
};
// Build 4-way associative cache for symbols. Within each cache line, symbols
@@ -252,21 +253,21 @@ class AddrMap {
public:
AddrMap() : size_(0), allocated_(0), obj_(nullptr) {}
~AddrMap() { base_internal::LowLevelAlloc::Free(obj_); }
- int Size() const { return size_; }
- ObjFile *At(int i) { return &obj_[i]; }
+ size_t Size() const { return size_; }
+ ObjFile *At(size_t i) { return &obj_[i]; }
ObjFile *Add();
void Clear();
private:
- int size_; // count of valid elements (<= allocated_)
- int allocated_; // count of allocated elements
- ObjFile *obj_; // array of allocated_ elements
+ size_t size_; // count of valid elements (<= allocated_)
+ size_t allocated_; // count of allocated elements
+ ObjFile *obj_; // array of allocated_ elements
AddrMap(const AddrMap &) = delete;
AddrMap &operator=(const AddrMap &) = delete;
};
void AddrMap::Clear() {
- for (int i = 0; i != size_; i++) {
+ for (size_t i = 0; i != size_; i++) {
At(i)->~ObjFile();
}
size_ = 0;
@@ -274,7 +275,7 @@ void AddrMap::Clear() {
ObjFile *AddrMap::Add() {
if (size_ == allocated_) {
- int new_allocated = allocated_ * 2 + 50;
+ size_t new_allocated = allocated_ * 2 + 50;
ObjFile *new_obj_ =
static_cast<ObjFile *>(base_internal::LowLevelAlloc::AllocWithArena(
new_allocated * sizeof(*new_obj_), SigSafeArena()));
@@ -300,7 +301,7 @@ class Symbolizer {
private:
char *CopyString(const char *s) {
- int len = strlen(s);
+ size_t len = strlen(s);
char *dst = static_cast<char *>(
base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
ABSL_RAW_CHECK(dst != nullptr, "out of memory");
@@ -321,8 +322,8 @@ class Symbolizer {
FindSymbolResult GetSymbolFromObjectFile(const ObjFile &obj,
const void *const pc,
const ptrdiff_t relocation,
- char *out, int out_size,
- char *tmp_buf, int tmp_buf_size);
+ char *out, size_t out_size,
+ char *tmp_buf, size_t tmp_buf_size);
const char *GetUncachedSymbol(const void *pc);
enum {
@@ -353,11 +354,11 @@ static std::atomic<Symbolizer *> g_cached_symbolizer;
} // namespace
-static int SymbolizerSize() {
+static size_t SymbolizerSize() {
#if defined(__wasm__) || defined(__asmjs__)
- int pagesize = getpagesize();
+ auto pagesize = static_cast<size_t>(getpagesize());
#else
- int pagesize = sysconf(_SC_PAGESIZE);
+ auto pagesize = static_cast<size_t>(sysconf(_SC_PAGESIZE));
#endif
return ((sizeof(Symbolizer) - 1) / pagesize + 1) * pagesize;
}
@@ -429,7 +430,7 @@ static ssize_t ReadPersistent(int fd, void *buf, size_t count) {
if (len == 0) { // Reached EOF.
break;
}
- num_bytes += len;
+ num_bytes += static_cast<size_t>(len);
}
SAFE_ASSERT(num_bytes <= count);
return static_cast<ssize_t>(num_bytes);
@@ -442,8 +443,8 @@ static ssize_t ReadFromOffset(const int fd, void *buf, const size_t count,
const off_t offset) {
off_t off = lseek(fd, offset, SEEK_SET);
if (off == (off_t)-1) {
- ABSL_RAW_LOG(WARNING, "lseek(%d, %ju, SEEK_SET) failed: errno=%d", fd,
- static_cast<uintmax_t>(offset), errno);
+ ABSL_RAW_LOG(WARNING, "lseek(%d, %jd, SEEK_SET) failed: errno=%d", fd,
+ static_cast<intmax_t>(offset), errno);
return -1;
}
return ReadPersistent(fd, buf, count);
@@ -478,29 +479,37 @@ static int FileGetElfType(const int fd) {
// inlined.
static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(
const int fd, ElfW(Half) sh_num, const off_t sh_offset, ElfW(Word) type,
- ElfW(Shdr) * out, char *tmp_buf, int tmp_buf_size) {
+ ElfW(Shdr) * out, char *tmp_buf, size_t tmp_buf_size) {
ElfW(Shdr) *buf = reinterpret_cast<ElfW(Shdr) *>(tmp_buf);
- const int buf_entries = tmp_buf_size / sizeof(buf[0]);
- const int buf_bytes = buf_entries * sizeof(buf[0]);
+ const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);
+ const size_t buf_bytes = buf_entries * sizeof(buf[0]);
- for (int i = 0; i < sh_num;) {
- const ssize_t num_bytes_left = (sh_num - i) * sizeof(buf[0]);
- const ssize_t num_bytes_to_read =
+ for (size_t i = 0; static_cast<int>(i) < sh_num;) {
+ const size_t num_bytes_left =
+ (static_cast<size_t>(sh_num) - i) * sizeof(buf[0]);
+ const size_t num_bytes_to_read =
(buf_bytes > num_bytes_left) ? num_bytes_left : buf_bytes;
- const off_t offset = sh_offset + i * sizeof(buf[0]);
+ const off_t offset = sh_offset + static_cast<off_t>(i * sizeof(buf[0]));
const ssize_t len = ReadFromOffset(fd, buf, num_bytes_to_read, offset);
- if (len % sizeof(buf[0]) != 0) {
+ if (len < 0) {
ABSL_RAW_LOG(
WARNING,
- "Reading %zd bytes from offset %ju returned %zd which is not a "
+ "Reading %zu bytes from offset %ju returned %zd which is negative.",
+ num_bytes_to_read, static_cast<intmax_t>(offset), len);
+ return false;
+ }
+ if (static_cast<size_t>(len) % sizeof(buf[0]) != 0) {
+ ABSL_RAW_LOG(
+ WARNING,
+ "Reading %zu bytes from offset %jd returned %zd which is not a "
"multiple of %zu.",
- num_bytes_to_read, static_cast<uintmax_t>(offset), len,
+ num_bytes_to_read, static_cast<intmax_t>(offset), len,
sizeof(buf[0]));
return false;
}
- const ssize_t num_headers_in_buf = len / sizeof(buf[0]);
+ const size_t num_headers_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_headers_in_buf <= buf_entries);
- for (int j = 0; j < num_headers_in_buf; ++j) {
+ for (size_t j = 0; j < num_headers_in_buf; ++j) {
if (buf[j].sh_type == type) {
*out = buf[j];
return true;
@@ -524,8 +533,8 @@ bool ForEachSection(int fd,
}
ElfW(Shdr) shstrtab;
- off_t shstrtab_offset =
- (elf_header.e_shoff + elf_header.e_shentsize * elf_header.e_shstrndx);
+ off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
+ elf_header.e_shentsize * elf_header.e_shstrndx;
if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) {
return false;
}
@@ -533,22 +542,23 @@ bool ForEachSection(int fd,
for (int i = 0; i < elf_header.e_shnum; ++i) {
ElfW(Shdr) out;
off_t section_header_offset =
- (elf_header.e_shoff + elf_header.e_shentsize * i);
+ static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;
if (!ReadFromOffsetExact(fd, &out, sizeof(out), section_header_offset)) {
return false;
}
- off_t name_offset = shstrtab.sh_offset + out.sh_name;
+ off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out.sh_name;
char header_name[kMaxSectionNameLen];
ssize_t n_read =
ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset);
- if (n_read == -1) {
+ if (n_read < 0) {
return false;
} else if (n_read > kMaxSectionNameLen) {
// Long read?
return false;
}
- absl::string_view name(header_name, strnlen(header_name, n_read));
+ absl::string_view name(header_name,
+ strnlen(header_name, static_cast<size_t>(n_read)));
if (!callback(name, out)) {
break;
}
@@ -575,19 +585,19 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
}
ElfW(Shdr) shstrtab;
- off_t shstrtab_offset =
- (elf_header.e_shoff + elf_header.e_shentsize * elf_header.e_shstrndx);
+ off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
+ elf_header.e_shentsize * elf_header.e_shstrndx;
if (!ReadFromOffsetExact(fd, &shstrtab, sizeof(shstrtab), shstrtab_offset)) {
return false;
}
for (int i = 0; i < elf_header.e_shnum; ++i) {
off_t section_header_offset =
- (elf_header.e_shoff + elf_header.e_shentsize * i);
+ static_cast<off_t>(elf_header.e_shoff) + elf_header.e_shentsize * i;
if (!ReadFromOffsetExact(fd, out, sizeof(*out), section_header_offset)) {
return false;
}
- off_t name_offset = shstrtab.sh_offset + out->sh_name;
+ off_t name_offset = static_cast<off_t>(shstrtab.sh_offset) + out->sh_name;
ssize_t n_read = ReadFromOffset(fd, &header_name, name_len, name_offset);
if (n_read < 0) {
return false;
@@ -645,10 +655,10 @@ static bool InSection(const void *address, const ElfW(Shdr) * section) {
}
static const char *ComputeOffset(const char *base, ptrdiff_t offset) {
- // Note: cast to uintptr_t to avoid undefined behavior when base evaluates to
+ // Note: cast to intptr_t to avoid undefined behavior when base evaluates to
// zero and offset is non-zero.
- return reinterpret_cast<const char *>(
- reinterpret_cast<uintptr_t>(base) + offset);
+ return reinterpret_cast<const char *>(reinterpret_cast<intptr_t>(base) +
+ offset);
}
// Read a symbol table and look for the symbol containing the
@@ -661,18 +671,18 @@ static const char *ComputeOffset(const char *base, ptrdiff_t offset) {
// To keep stack consumption low, we would like this function to not get
// inlined.
static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
- const void *const pc, const int fd, char *out, int out_size,
+ const void *const pc, const int fd, char *out, size_t out_size,
ptrdiff_t relocation, const ElfW(Shdr) * strtab, const ElfW(Shdr) * symtab,
- const ElfW(Shdr) * opd, char *tmp_buf, int tmp_buf_size) {
+ const ElfW(Shdr) * opd, char *tmp_buf, size_t tmp_buf_size) {
if (symtab == nullptr) {
return SYMBOL_NOT_FOUND;
}
// Read multiple symbols at once to save read() calls.
ElfW(Sym) *buf = reinterpret_cast<ElfW(Sym) *>(tmp_buf);
- const int buf_entries = tmp_buf_size / sizeof(buf[0]);
+ const size_t buf_entries = tmp_buf_size / sizeof(buf[0]);
- const int num_symbols = symtab->sh_size / symtab->sh_entsize;
+ const size_t num_symbols = symtab->sh_size / symtab->sh_entsize;
// On platforms using an .opd section (PowerPC & IA64), a function symbol
// has the address of a function descriptor, which contains the real
@@ -687,16 +697,19 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
ElfW(Sym) best_match;
SafeMemZero(&best_match, sizeof(best_match));
bool found_match = false;
- for (int i = 0; i < num_symbols;) {
- off_t offset = symtab->sh_offset + i * symtab->sh_entsize;
- const int num_remaining_symbols = num_symbols - i;
- const int entries_in_chunk = std::min(num_remaining_symbols, buf_entries);
- const int bytes_in_chunk = entries_in_chunk * sizeof(buf[0]);
+ for (size_t i = 0; i < num_symbols;) {
+ off_t offset =
+ static_cast<off_t>(symtab->sh_offset + i * symtab->sh_entsize);
+ const size_t num_remaining_symbols = num_symbols - i;
+ const size_t entries_in_chunk =
+ std::min(num_remaining_symbols, buf_entries);
+ const size_t bytes_in_chunk = entries_in_chunk * sizeof(buf[0]);
const ssize_t len = ReadFromOffset(fd, buf, bytes_in_chunk, offset);
- SAFE_ASSERT(len % sizeof(buf[0]) == 0);
- const ssize_t num_symbols_in_buf = len / sizeof(buf[0]);
+ SAFE_ASSERT(len >= 0);
+ SAFE_ASSERT(static_cast<size_t>(len) % sizeof(buf[0]) == 0);
+ const size_t num_symbols_in_buf = static_cast<size_t>(len) / sizeof(buf[0]);
SAFE_ASSERT(num_symbols_in_buf <= entries_in_chunk);
- for (int j = 0; j < num_symbols_in_buf; ++j) {
+ for (size_t j = 0; j < num_symbols_in_buf; ++j) {
const ElfW(Sym) &symbol = buf[j];
// For a DSO, a symbol address is relocated by the loading address.
@@ -713,7 +726,7 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// about what encoding is being used; we just want the real start address
// of the function.
start_address = reinterpret_cast<const char *>(
- reinterpret_cast<uintptr_t>(start_address) & ~1);
+ reinterpret_cast<uintptr_t>(start_address) & ~1u);
#endif
if (deref_function_descriptor_pointer &&
@@ -726,7 +739,8 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// If pc is inside the .opd section, it points to a function descriptor.
const size_t size = pc_in_opd ? kFunctionDescriptorSize : symbol.st_size;
- const void *const end_address = ComputeOffset(start_address, size);
+ const void *const end_address =
+ ComputeOffset(start_address, static_cast<ptrdiff_t>(size));
if (symbol.st_value != 0 && // Skip null value symbols.
symbol.st_shndx != 0 && // Skip undefined symbols.
#ifdef STT_TLS
@@ -744,16 +758,18 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
}
if (found_match) {
- const size_t off = strtab->sh_offset + best_match.st_name;
+ const off_t off =
+ static_cast<off_t>(strtab->sh_offset) + best_match.st_name;
const ssize_t n_read = ReadFromOffset(fd, out, out_size, off);
if (n_read <= 0) {
// This should never happen.
ABSL_RAW_LOG(WARNING,
- "Unable to read from fd %d at offset %zu: n_read = %zd", fd,
- off, n_read);
+ "Unable to read from fd %d at offset %lld: n_read = %zd", fd,
+ static_cast<long long>(off), n_read);
return SYMBOL_NOT_FOUND;
}
- ABSL_RAW_CHECK(n_read <= out_size, "ReadFromOffset read too much data.");
+ ABSL_RAW_CHECK(static_cast<size_t>(n_read) <= out_size,
+ "ReadFromOffset read too much data.");
// strtab->sh_offset points into .strtab-like section that contains
// NUL-terminated strings: '\0foo\0barbaz\0...".
@@ -761,7 +777,7 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// sh_offset+st_name points to the start of symbol name, but we don't know
// how long the symbol is, so we try to read as much as we have space for,
// and usually over-read (i.e. there is a NUL somewhere before n_read).
- if (memchr(out, '\0', n_read) == nullptr) {
+ if (memchr(out, '\0', static_cast<size_t>(n_read)) == nullptr) {
// Either out_size was too small (n_read == out_size and no NUL), or
// we tried to read past the EOF (n_read < out_size) and .strtab is
// corrupt (missing terminating NUL; should never happen for valid ELF).
@@ -779,7 +795,7 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// See FindSymbol() comment for description of return value.
FindSymbolResult Symbolizer::GetSymbolFromObjectFile(
const ObjFile &obj, const void *const pc, const ptrdiff_t relocation,
- char *out, int out_size, char *tmp_buf, int tmp_buf_size) {
+ char *out, size_t out_size, char *tmp_buf, size_t tmp_buf_size) {
ElfW(Shdr) symtab;
ElfW(Shdr) strtab;
ElfW(Shdr) opd;
@@ -802,13 +818,15 @@ FindSymbolResult Symbolizer::GetSymbolFromObjectFile(
// Consult a regular symbol table, then fall back to the dynamic symbol table.
for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) {
if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum,
- obj.elf_header.e_shoff, symbol_table_type,
+ static_cast<off_t>(obj.elf_header.e_shoff),
+ static_cast<ElfW(Word)>(symbol_table_type),
&symtab, tmp_buf, tmp_buf_size)) {
continue;
}
if (!ReadFromOffsetExact(
obj.fd, &strtab, sizeof(strtab),
- obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
+ static_cast<off_t>(obj.elf_header.e_shoff +
+ symtab.sh_link * sizeof(symtab)))) {
continue;
}
const FindSymbolResult rc =
@@ -833,7 +851,7 @@ class FileDescriptor {
~FileDescriptor() {
if (fd_ >= 0) {
- NO_INTR(close(fd_));
+ close(fd_);
}
}
@@ -850,7 +868,7 @@ class FileDescriptor {
// and snprintf().
class LineReader {
public:
- explicit LineReader(int fd, char *buf, int buf_len)
+ explicit LineReader(int fd, char *buf, size_t buf_len)
: fd_(fd),
buf_len_(buf_len),
buf_(buf),
@@ -878,12 +896,12 @@ class LineReader {
bol_ = eol_ + 1; // Advance to the next line in the buffer.
SAFE_ASSERT(bol_ <= eod_); // "bol_" can point to "eod_".
if (!HasCompleteLine()) {
- const int incomplete_line_length = eod_ - bol_;
+ const auto incomplete_line_length = static_cast<size_t>(eod_ - bol_);
// Move the trailing incomplete line to the beginning.
memmove(buf_, bol_, incomplete_line_length);
// Read text from file and append it.
char *const append_pos = buf_ + incomplete_line_length;
- const int capacity_left = buf_len_ - incomplete_line_length;
+ const size_t capacity_left = buf_len_ - incomplete_line_length;
const ssize_t num_bytes =
ReadPersistent(fd_, append_pos, capacity_left);
if (num_bytes <= 0) { // EOF or error.
@@ -906,7 +924,8 @@ class LineReader {
private:
char *FindLineFeed() const {
- return reinterpret_cast<char *>(memchr(bol_, '\n', eod_ - bol_));
+ return reinterpret_cast<char *>(
+ memchr(bol_, '\n', static_cast<size_t>(eod_ - bol_)));
}
bool BufferIsEmpty() const { return buf_ == eod_; }
@@ -916,7 +935,7 @@ class LineReader {
}
const int fd_;
- const int buf_len_;
+ const size_t buf_len_;
char *const buf_;
char *bol_;
char *eol_;
@@ -934,7 +953,8 @@ static const char *GetHex(const char *start, const char *end,
int ch = *p;
if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') ||
(ch >= 'a' && ch <= 'f')) {
- hex = (hex << 4) | (ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
+ hex = (hex << 4) |
+ static_cast<uint64_t>(ch < 'A' ? ch - '0' : (ch & 0xF) + 9);
} else { // Encountered the first non-hex character.
break;
}
@@ -966,7 +986,7 @@ static bool ShouldUseMapping(const char *const flags) {
static ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap(
bool (*callback)(const char *filename, const void *const start_addr,
const void *const end_addr, uint64_t offset, void *arg),
- void *arg, void *tmp_buf, int tmp_buf_size) {
+ void *arg, void *tmp_buf, size_t tmp_buf_size) {
// Use /proc/self/task/<pid>/maps instead of /proc/self/maps. The latter
// requires kernel to stop all threads, and is significantly slower when there
// are 1000s of threads.
@@ -1081,10 +1101,10 @@ ObjFile *Symbolizer::FindObjFile(const void *const addr, size_t len) {
}
}
- int lo = 0;
- int hi = addr_map_.Size();
+ size_t lo = 0;
+ size_t hi = addr_map_.Size();
while (lo < hi) {
- int mid = (lo + hi) / 2;
+ size_t mid = (lo + hi) / 2;
if (addr < addr_map_.At(mid)->end_addr) {
hi = mid;
} else {
@@ -1106,11 +1126,11 @@ ObjFile *Symbolizer::FindObjFile(const void *const addr, size_t len) {
}
void Symbolizer::ClearAddrMap() {
- for (int i = 0; i != addr_map_.Size(); i++) {
+ for (size_t i = 0; i != addr_map_.Size(); i++) {
ObjFile *o = addr_map_.At(i);
base_internal::LowLevelAlloc::Free(o->filename);
if (o->fd >= 0) {
- NO_INTR(close(o->fd));
+ close(o->fd);
}
}
addr_map_.Clear();
@@ -1126,7 +1146,7 @@ bool Symbolizer::RegisterObjFile(const char *filename,
// Files are supposed to be added in the increasing address order. Make
// sure that's the case.
- int addr_map_size = impl->addr_map_.Size();
+ size_t addr_map_size = impl->addr_map_.Size();
if (addr_map_size != 0) {
ObjFile *old = impl->addr_map_.At(addr_map_size - 1);
if (old->end_addr > end_addr) {
@@ -1170,12 +1190,12 @@ bool Symbolizer::RegisterObjFile(const char *filename,
// where the input symbol is demangled in-place.
// To keep stack consumption low, we would like this function to not
// get inlined.
-static ABSL_ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size,
+static ABSL_ATTRIBUTE_NOINLINE void DemangleInplace(char *out, size_t out_size,
char *tmp_buf,
- int tmp_buf_size) {
+ size_t tmp_buf_size) {
if (Demangle(out, tmp_buf, tmp_buf_size)) {
// Demangling succeeded. Copy to out if the space allows.
- int len = strlen(tmp_buf);
+ size_t len = strlen(tmp_buf);
if (len + 1 <= out_size) { // +1 for '\0'.
SAFE_ASSERT(len < tmp_buf_size);
memmove(out, tmp_buf, len + 1);
@@ -1218,7 +1238,8 @@ const char *Symbolizer::InsertSymbolInCache(const void *const pc,
SymbolCacheLine *line = GetCacheLine(pc);
uint32_t max_age = 0;
- int oldest_index = -1;
+ size_t oldest_index = 0;
+ bool found_oldest_index = false;
for (size_t i = 0; i < ABSL_ARRAYSIZE(line->pc); ++i) {
if (line->pc[i] == nullptr) {
AgeSymbols(line);
@@ -1230,11 +1251,12 @@ const char *Symbolizer::InsertSymbolInCache(const void *const pc,
if (line->age[i] >= max_age) {
max_age = line->age[i];
oldest_index = i;
+ found_oldest_index = true;
}
}
AgeSymbols(line);
- ABSL_RAW_CHECK(oldest_index >= 0, "Corrupt cache");
+ ABSL_RAW_CHECK(found_oldest_index, "Corrupt cache");
base_internal::LowLevelAlloc::Free(line->name[oldest_index]);
line->pc[oldest_index] = pc;
line->name[oldest_index] = CopyString(name);
@@ -1303,7 +1325,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
}
const int phnum = obj->elf_header.e_phnum;
const int phentsize = obj->elf_header.e_phentsize;
- size_t phoff = obj->elf_header.e_phoff;
+ auto phoff = static_cast<off_t>(obj->elf_header.e_phoff);
size_t num_executable_load_segments = 0;
for (int j = 0; j < phnum; j++) {
ElfW(Phdr) phdr;
@@ -1321,8 +1343,9 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
if (num_executable_load_segments < obj->phdr.size()) {
memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
} else {
- ABSL_RAW_LOG(WARNING, "%s: too many executable LOAD segments",
- obj->filename);
+ ABSL_RAW_LOG(
+ WARNING, "%s: too many executable LOAD segments: %zu >= %zu",
+ obj->filename, num_executable_load_segments, obj->phdr.size());
break;
}
}
@@ -1354,7 +1377,7 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) {
//
// For obj->offset > 0, adjust the relocation since a mapping at offset
// X in the file will have a start address of [true relocation]+X.
- relocation = start_addr - obj->offset;
+ relocation = static_cast<ptrdiff_t>(start_addr - obj->offset);
// Note: some binaries have multiple "rx" LOAD segments. We must
// find the right one.
@@ -1529,7 +1552,7 @@ bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset
ret = false;
} else {
// TODO(ckennelly): Move this into a string copy routine.
- int len = strlen(filename);
+ size_t len = strlen(filename);
char *dst = static_cast<char *>(
base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
ABSL_RAW_CHECK(dst != nullptr, "out of memory");
@@ -1585,16 +1608,17 @@ bool Symbolize(const void *pc, char *out, int out_size) {
const char *name = s->GetSymbol(pc);
bool ok = false;
if (name != nullptr && out_size > 0) {
- strncpy(out, name, out_size);
+ strncpy(out, name, static_cast<size_t>(out_size));
ok = true;
- if (out[out_size - 1] != '\0') {
+ if (out[static_cast<size_t>(out_size) - 1] != '\0') {
// strncpy() does not '\0' terminate when it truncates. Do so, with
// trailing ellipsis.
static constexpr char kEllipsis[] = "...";
- int ellipsis_size =
- std::min(implicit_cast<int>(strlen(kEllipsis)), out_size - 1);
- memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
- out[out_size - 1] = '\0';
+ size_t ellipsis_size =
+ std::min(strlen(kEllipsis), static_cast<size_t>(out_size) - 1);
+ memcpy(out + static_cast<size_t>(out_size) - ellipsis_size - 1, kEllipsis,
+ ellipsis_size);
+ out[static_cast<size_t>(out_size) - 1] = '\0';
}
}
debugging_internal::FreeSymbolizer(s);
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_win32.inc b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_win32.inc
index c3df46f606..53a099a181 100644
--- a/contrib/restricted/abseil-cpp/absl/debugging/symbolize_win32.inc
+++ b/contrib/restricted/abseil-cpp/absl/debugging/symbolize_win32.inc
@@ -65,14 +65,15 @@ bool Symbolize(const void* pc, char* out, int out_size) {
if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) {
return false;
}
- strncpy(out, symbol->Name, out_size);
- if (out[out_size - 1] != '\0') {
+ const size_t out_size_t = static_cast<size_t>(out_size);
+ strncpy(out, symbol->Name, out_size_t);
+ if (out[out_size_t - 1] != '\0') {
// strncpy() does not '\0' terminate when it truncates.
static constexpr char kEllipsis[] = "...";
- int ellipsis_size =
- std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
- memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
- out[out_size - 1] = '\0';
+ size_t ellipsis_size =
+ std::min(sizeof(kEllipsis) - 1, out_size_t - 1);
+ memcpy(out + out_size_t - ellipsis_size - 1, kEllipsis, ellipsis_size);
+ out[out_size_t - 1] = '\0';
}
return true;
}
diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc
index 55892d77dd..cc656f9d13 100644
--- a/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc
+++ b/contrib/restricted/abseil-cpp/absl/flags/internal/flag.cc
@@ -406,7 +406,7 @@ template <typename StorageT>
StorageT* FlagImpl::OffsetValue() const {
char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
// The offset is deduced via Flag value type specific op_.
- size_t offset = flags_internal::ValueOffset(op_);
+ ptrdiff_t offset = flags_internal::ValueOffset(op_);
return reinterpret_cast<StorageT*>(p + offset);
}
@@ -486,7 +486,7 @@ bool FlagImpl::ReadOneBool() const {
}
void FlagImpl::ReadSequenceLockedData(void* dst) const {
- int size = Sizeof(op_);
+ size_t size = Sizeof(op_);
// Attempt to read using the sequence lock.
if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
return;
diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/parse.h b/contrib/restricted/abseil-cpp/absl/flags/internal/parse.h
index de706c8984..0a7012fcf5 100644
--- a/contrib/restricted/abseil-cpp/absl/flags/internal/parse.h
+++ b/contrib/restricted/abseil-cpp/absl/flags/internal/parse.h
@@ -52,6 +52,10 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
// command line or specified in flag file present on the original command line.
bool WasPresentOnCommandLine(absl::string_view flag_name);
+// Return existing flags similar to the parameter, in order to help in case of
+// misspellings.
+std::vector<std::string> GetMisspellingHints(absl::string_view flag);
+
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc
index 949709e883..5efc7b07a3 100644
--- a/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc
+++ b/contrib/restricted/abseil-cpp/absl/flags/internal/usage.cc
@@ -17,7 +17,9 @@
#include <stdint.h>
+#include <algorithm>
#include <functional>
+#include <iterator>
#include <map>
#include <ostream>
#include <string>
@@ -33,6 +35,7 @@
#include "absl/flags/internal/program_name.h"
#include "absl/flags/internal/registry.h"
#include "absl/flags/usage_config.h"
+#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
@@ -148,8 +151,7 @@ class FlagHelpPrettyPrinter {
}
// Write the token, ending the string first if necessary/possible.
- if (!new_line &&
- (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
+ if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
EndLine();
new_line = true;
}
@@ -344,7 +346,7 @@ void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
absl::string_view program_usage_message) {
flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) {
- return filter.empty() || filename.find(filter) != absl::string_view::npos;
+ return filter.empty() || absl::StrContains(filename, filter);
};
flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message);
}
@@ -466,7 +468,7 @@ void SetFlagsHelpFormat(HelpFormat format) {
// function.
bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
if (absl::ConsumePrefix(&name, "help")) {
- if (name == "") {
+ if (name.empty()) {
if (value.empty()) {
SetFlagsHelpMode(HelpMode::kImportant);
} else {
diff --git a/contrib/restricted/abseil-cpp/absl/flags/marshalling.h b/contrib/restricted/abseil-cpp/absl/flags/marshalling.h
index b1e2ffa551..325e75e516 100644
--- a/contrib/restricted/abseil-cpp/absl/flags/marshalling.h
+++ b/contrib/restricted/abseil-cpp/absl/flags/marshalling.h
@@ -86,7 +86,7 @@
// }
//
// Using an optional flag in this manner avoids common workarounds for
-// indicating such an unset flag (such as using sentinal values to indicate this
+// indicating such an unset flag (such as using sentinel values to indicate this
// state).
//
// An optional flag also allows a developer to pass a flag in an "unset"
diff --git a/contrib/restricted/abseil-cpp/absl/flags/parse.cc b/contrib/restricted/abseil-cpp/absl/flags/parse.cc
index dd1a6796ca..fa953f558c 100644
--- a/contrib/restricted/abseil-cpp/absl/flags/parse.cc
+++ b/contrib/restricted/abseil-cpp/absl/flags/parse.cc
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <algorithm>
+#include <cstdint>
#include <fstream>
#include <iostream>
#include <iterator>
@@ -30,6 +31,7 @@
#include <windows.h>
#endif
+#include "absl/algorithm/container.h"
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/const_init.h"
@@ -47,7 +49,9 @@
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
#include "absl/strings/ascii.h"
+#include "absl/strings/internal/damerau_levenshtein_distance.h"
#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/synchronization/mutex.h"
@@ -72,6 +76,11 @@ ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
+// Suggesting at most kMaxHints flags in case of misspellings.
+ABSL_CONST_INIT const size_t kMaxHints = 100;
+// Suggesting only flags which have a smaller distance than kMaxDistance.
+ABSL_CONST_INIT const size_t kMaxDistance = 3;
+
struct SpecifiedFlagsCompare {
bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
return a->Name() < b->Name();
@@ -159,14 +168,14 @@ class ArgsList {
// Returns success status: true if parsing successful, false otherwise.
bool ReadFromFlagfile(const std::string& flag_file_name);
- int Size() const { return args_.size() - next_arg_; }
- int FrontIndex() const { return next_arg_; }
+ size_t Size() const { return args_.size() - next_arg_; }
+ size_t FrontIndex() const { return next_arg_; }
absl::string_view Front() const { return args_[next_arg_]; }
void PopFront() { next_arg_++; }
private:
std::vector<std::string> args_;
- int next_arg_;
+ size_t next_arg_;
};
bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
@@ -605,6 +614,55 @@ bool WasPresentOnCommandLine(absl::string_view flag_name) {
// --------------------------------------------------------------------
+struct BestHints {
+ explicit BestHints(uint8_t _max) : best_distance(_max + 1) {}
+ bool AddHint(absl::string_view hint, uint8_t distance) {
+ if (hints.size() >= kMaxHints) return false;
+ if (distance == best_distance) {
+ hints.emplace_back(hint);
+ }
+ if (distance < best_distance) {
+ best_distance = distance;
+ hints = std::vector<std::string>{std::string(hint)};
+ }
+ return true;
+ }
+
+ uint8_t best_distance;
+ std::vector<std::string> hints;
+};
+
+// Return the list of flags with the smallest Damerau-Levenshtein distance to
+// the given flag.
+std::vector<std::string> GetMisspellingHints(const absl::string_view flag) {
+ const size_t maxCutoff = std::min(flag.size() / 2 + 1, kMaxDistance);
+ auto undefok = absl::GetFlag(FLAGS_undefok);
+ BestHints best_hints(static_cast<uint8_t>(maxCutoff));
+ absl::flags_internal::ForEachFlag([&](const CommandLineFlag& f) {
+ if (best_hints.hints.size() >= kMaxHints) return;
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, f.Name(), best_hints.best_distance);
+ best_hints.AddHint(f.Name(), distance);
+ // For boolean flags, also calculate distance to the negated form.
+ if (f.IsOfType<bool>()) {
+ const std::string negated_flag = absl::StrCat("no", f.Name());
+ distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, negated_flag, best_hints.best_distance);
+ best_hints.AddHint(negated_flag, distance);
+ }
+ });
+ // Finally calculate distance to flags in "undefok".
+ absl::c_for_each(undefok, [&](const absl::string_view f) {
+ if (best_hints.hints.size() >= kMaxHints) return;
+ uint8_t distance = strings_internal::CappedDamerauLevenshteinDistance(
+ flag, f, best_hints.best_distance);
+ best_hints.AddHint(absl::StrCat(f, " (undefok)"), distance);
+ });
+ return best_hints.hints;
+}
+
+// --------------------------------------------------------------------
+
std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
ArgvListAction arg_list_act,
UsageFlagsAction usage_flag_act,
@@ -626,7 +684,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
std::vector<char*> output_args;
std::vector<char*> positional_args;
- output_args.reserve(argc);
+ output_args.reserve(static_cast<size_t>(argc));
// This is the list of undefined flags. The element of the list is the pair
// consisting of boolean indicating if flag came from command line (vs from
@@ -755,10 +813,19 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
for (const auto& flag_name : undefined_flag_names) {
if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
-
- flags_internal::ReportUsageError(
- absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
- true);
+ // Verify if flag_name has the "no" already removed
+ std::vector<std::string> flags;
+ if (flag_name.first) flags = GetMisspellingHints(flag_name.second);
+ if (flags.empty()) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
+ true);
+ } else {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Unknown command line flag '", flag_name.second,
+ "'. Did you mean: ", absl::StrJoin(flags, ", "), " ?"),
+ true);
+ }
success = false;
}
@@ -795,8 +862,8 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
// All the remaining arguments are positional.
if (!input_args.empty()) {
- for (int arg_index = input_args.back().FrontIndex(); arg_index < argc;
- ++arg_index) {
+ for (size_t arg_index = input_args.back().FrontIndex();
+ arg_index < static_cast<size_t>(argc); ++arg_index) {
output_args.push_back(argv[arg_index]);
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/city.cc b/contrib/restricted/abseil-cpp/absl/hash/internal/city.cc
index 5460134e57..f0d3196470 100644
--- a/contrib/restricted/abseil-cpp/absl/hash/internal/city.cc
+++ b/contrib/restricted/abseil-cpp/absl/hash/internal/city.cc
@@ -97,7 +97,7 @@ static uint32_t Hash32Len13to24(const char *s, size_t len) {
uint32_t d = Fetch32(s + (len >> 1));
uint32_t e = Fetch32(s);
uint32_t f = Fetch32(s + len - 4);
- uint32_t h = len;
+ uint32_t h = static_cast<uint32_t>(len);
return fmix(Mur(f, Mur(e, Mur(d, Mur(c, Mur(b, Mur(a, h)))))));
}
@@ -106,15 +106,15 @@ static uint32_t Hash32Len0to4(const char *s, size_t len) {
uint32_t b = 0;
uint32_t c = 9;
for (size_t i = 0; i < len; i++) {
- signed char v = s[i];
- b = b * c1 + v;
+ signed char v = static_cast<signed char>(s[i]);
+ b = b * c1 + static_cast<uint32_t>(v);
c ^= b;
}
- return fmix(Mur(b, Mur(len, c)));
+ return fmix(Mur(b, Mur(static_cast<uint32_t>(len), c)));
}
static uint32_t Hash32Len5to12(const char *s, size_t len) {
- uint32_t a = len, b = len * 5, c = 9, d = b;
+ uint32_t a = static_cast<uint32_t>(len), b = a * 5, c = 9, d = b;
a += Fetch32(s);
b += Fetch32(s + len - 4);
c += Fetch32(s + ((len >> 1) & 4));
@@ -129,7 +129,7 @@ uint32_t CityHash32(const char *s, size_t len) {
}
// len > 24
- uint32_t h = len, g = c1 * len, f = g;
+ uint32_t h = static_cast<uint32_t>(len), g = c1 * h, f = g;
uint32_t a0 = Rotate32(Fetch32(s + len - 4) * c1, 17) * c2;
uint32_t a1 = Rotate32(Fetch32(s + len - 8) * c1, 17) * c2;
@@ -230,11 +230,11 @@ static uint64_t HashLen0to16(const char *s, size_t len) {
return HashLen16(len + (a << 3), Fetch32(s + len - 4), mul);
}
if (len > 0) {
- uint8_t a = s[0];
- uint8_t b = s[len >> 1];
- uint8_t c = s[len - 1];
+ uint8_t a = static_cast<uint8_t>(s[0]);
+ uint8_t b = static_cast<uint8_t>(s[len >> 1]);
+ uint8_t c = static_cast<uint8_t>(s[len - 1]);
uint32_t y = static_cast<uint32_t>(a) + (static_cast<uint32_t>(b) << 8);
- uint32_t z = len + (static_cast<uint32_t>(c) << 2);
+ uint32_t z = static_cast<uint32_t>(len) + (static_cast<uint32_t>(c) << 2);
return ShiftMix(y * k2 ^ z * k0) * k2;
}
return k2;
diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h
index 45dfdd4653..ccf4cc1ad5 100644
--- a/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h
+++ b/contrib/restricted/abseil-cpp/absl/hash/internal/hash.h
@@ -49,6 +49,7 @@
#include "absl/hash/internal/city.h"
#include "absl/hash/internal/low_level_hash.h"
#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
@@ -444,7 +445,7 @@ H AbslHashValue(H hash_state, T C::* ptr) {
// On other platforms, we assume that pointers-to-members do not have
// padding.
#ifdef __cpp_lib_has_unique_object_representations
- static_assert(std::has_unique_object_representations_v<T C::*>);
+ static_assert(std::has_unique_object_representations<T C::*>::value);
#endif // __cpp_lib_has_unique_object_representations
return n;
#endif
@@ -1052,7 +1053,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
uint64_t most_significant = low_mem;
uint64_t least_significant = high_mem;
#endif
- return {least_significant, most_significant >> (128 - len * 8)};
+ return {least_significant, most_significant};
}
// Reads 4 to 8 bytes from p. Zero pads to fill uint64_t.
@@ -1183,9 +1184,22 @@ inline uint64_t MixingHashState::CombineContiguousImpl(
}
v = Hash64(first, len);
} else if (len > 8) {
+ // This hash function was constructed by the ML-driven algorithm discovery
+ // using reinforcement learning. We fed the agent lots of inputs from
+ // microbenchmarks, SMHasher, low hamming distance from generated inputs and
+ // picked up the one that was good on micro and macrobenchmarks.
auto p = Read9To16(first, len);
- state = Mix(state, p.first);
- v = p.second;
+ uint64_t lo = p.first;
+ uint64_t hi = p.second;
+ // Rotation by 53 was found to be most often useful when discovering these
+ // hashing algorithms with ML techniques.
+ lo = absl::rotr(lo, 53);
+ state += kMul;
+ lo += state;
+ state ^= hi;
+ uint128 m = state;
+ m *= lo;
+ return static_cast<uint64_t>(m ^ (m >> 64));
} else if (len >= 4) {
v = Read4To8(first, len);
} else if (len > 0) {
diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc b/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc
index 6f9cb9c7bf..c917457a7c 100644
--- a/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc
+++ b/contrib/restricted/abseil-cpp/absl/hash/internal/low_level_hash.cc
@@ -15,7 +15,6 @@
#include "absl/hash/internal/low_level_hash.h"
#include "absl/base/internal/unaligned_access.h"
-#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
namespace absl {
@@ -23,24 +22,13 @@ ABSL_NAMESPACE_BEGIN
namespace hash_internal {
static uint64_t Mix(uint64_t v0, uint64_t v1) {
-#if !defined(__aarch64__)
- // The default bit-mixer uses 64x64->128-bit multiplication.
absl::uint128 p = v0;
p *= v1;
return absl::Uint128Low64(p) ^ absl::Uint128High64(p);
-#else
- // The default bit-mixer above would perform poorly on some ARM microarchs,
- // where calculating a 128-bit product requires a sequence of two
- // instructions with a high combined latency and poor throughput.
- // Instead, we mix bits using only 64-bit arithmetic, which is faster.
- uint64_t p = v0 ^ absl::rotl(v1, 40);
- p *= v1 ^ absl::rotl(v0, 39);
- return p ^ (p >> 11);
-#endif
}
uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
- const uint64_t salt[]) {
+ const uint64_t salt[5]) {
const uint8_t* ptr = static_cast<const uint8_t*>(data);
uint64_t starting_length = static_cast<uint64_t>(len);
uint64_t current_state = seed ^ salt[0];
@@ -106,7 +94,8 @@ uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
} else if (len > 0) {
// If we have at least 1 and at most 3 bytes, read all of the provided
// bits into A, with some adjustments.
- a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]);
+ a = static_cast<uint64_t>((ptr[0] << 16) | (ptr[len >> 1] << 8) |
+ ptr[len - 1]);
b = 0;
} else {
a = 0;
diff --git a/contrib/restricted/abseil-cpp/absl/log/CMakeLists.darwin.txt b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.darwin.txt
new file mode 100644
index 0000000000..c2793a97ea
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.darwin.txt
@@ -0,0 +1,46 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-absl-log)
+target_compile_options(abseil-cpp-absl-log PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-absl-log PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp
+)
+target_link_libraries(abseil-cpp-absl-log PUBLIC
+ contrib-libs-cxxsupp
+ abseil-cpp-absl-base
+ abseil-cpp-absl-container
+ abseil-cpp-absl-debugging
+ abseil-cpp-absl-flags
+ abseil-cpp-absl-hash
+ abseil-cpp-absl-numeric
+ abseil-cpp-absl-profiling
+ abseil-cpp-absl-strings
+ abseil-cpp-absl-synchronization
+ abseil-cpp-absl-time
+ abseil-cpp-absl-types
+)
+target_sources(abseil-cpp-absl-log PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/flags.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/initialize.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_entry.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_sink.cc
+)
diff --git a/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux-aarch64.txt b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux-aarch64.txt
new file mode 100644
index 0000000000..a7743e41a0
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux-aarch64.txt
@@ -0,0 +1,47 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-absl-log)
+target_compile_options(abseil-cpp-absl-log PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-absl-log PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp
+)
+target_link_libraries(abseil-cpp-absl-log PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ abseil-cpp-absl-base
+ abseil-cpp-absl-container
+ abseil-cpp-absl-debugging
+ abseil-cpp-absl-flags
+ abseil-cpp-absl-hash
+ abseil-cpp-absl-numeric
+ abseil-cpp-absl-profiling
+ abseil-cpp-absl-strings
+ abseil-cpp-absl-synchronization
+ abseil-cpp-absl-time
+ abseil-cpp-absl-types
+)
+target_sources(abseil-cpp-absl-log PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/flags.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/initialize.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_entry.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_sink.cc
+)
diff --git a/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux.txt b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux.txt
new file mode 100644
index 0000000000..a7743e41a0
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.linux.txt
@@ -0,0 +1,47 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+
+add_library(abseil-cpp-absl-log)
+target_compile_options(abseil-cpp-absl-log PRIVATE
+ $<IF:$<CXX_COMPILER_ID:MSVC>,,-Wno-everything>
+)
+target_include_directories(abseil-cpp-absl-log PUBLIC
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp
+)
+target_link_libraries(abseil-cpp-absl-log PUBLIC
+ contrib-libs-linux-headers
+ contrib-libs-cxxsupp
+ abseil-cpp-absl-base
+ abseil-cpp-absl-container
+ abseil-cpp-absl-debugging
+ abseil-cpp-absl-flags
+ abseil-cpp-absl-hash
+ abseil-cpp-absl-numeric
+ abseil-cpp-absl-profiling
+ abseil-cpp-absl-strings
+ abseil-cpp-absl-synchronization
+ abseil-cpp-absl-time
+ abseil-cpp-absl-types
+)
+target_sources(abseil-cpp-absl-log PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/flags.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/initialize.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_entry.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/log/log_sink.cc
+)
diff --git a/contrib/restricted/abseil-cpp/absl/log/CMakeLists.txt b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.txt
new file mode 100644
index 0000000000..5bb4faffb4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/CMakeLists.txt
@@ -0,0 +1,15 @@
+
+# This file was generated by the build system used internally in the Yandex monorepo.
+# Only simple modifications are allowed (adding source-files to targets, adding simple properties
+# like target_include_directories). These modifications will be ported to original
+# ya.make files by maintainers. Any complex modifications which can't be ported back to the
+# original buildsystem will not be accepted.
+
+
+if (CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND UNIX AND NOT APPLE AND NOT ANDROID)
+ include(CMakeLists.linux-aarch64.txt)
+elseif (APPLE AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+ include(CMakeLists.darwin.txt)
+elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND UNIX AND NOT APPLE AND NOT ANDROID)
+ include(CMakeLists.linux.txt)
+endif()
diff --git a/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc b/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc
new file mode 100644
index 0000000000..19c6a28ed8
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/die_if_null.cc
@@ -0,0 +1,32 @@
+// 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/die_if_null.h"
+
+#include "absl/base/config.h"
+#include "absl/log/log.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+void DieBecauseNull(const char* file, int line, const char* exprtext) {
+ LOG(FATAL).AtLocation(file, line)
+ << absl::StrCat("Check failed: '", exprtext, "' Must be non-null");
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/die_if_null.h b/contrib/restricted/abseil-cpp/absl/log/die_if_null.h
new file mode 100644
index 0000000000..127a9ac882
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/die_if_null.h
@@ -0,0 +1,76 @@
+// 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/die_if_null.h
+// -----------------------------------------------------------------------------
+//
+// This header declares macro `ABSL_DIE_IF_NULL`.
+
+#ifndef ABSL_LOG_DIE_IF_NULL_H_
+#define ABSL_LOG_DIE_IF_NULL_H_
+
+#include <stdint.h>
+
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+
+// ABSL_DIE_IF_NULL()
+//
+// `ABSL_DIE_IF_NULL` behaves as `CHECK_NE` against `nullptr` but *also*
+// "returns" its argument. It is useful in initializers where statements (like
+// `CHECK_NE`) can't be used. Outside initializers, prefer `CHECK` or
+// `CHECK_NE`. `ABSL_DIE_IF_NULL` works for both raw pointers and (compatible)
+// smart pointers including `std::unique_ptr` and `std::shared_ptr`; more
+// generally, it works for any type that can be compared to nullptr_t. For
+// types that aren't raw pointers, `ABSL_DIE_IF_NULL` returns a reference to
+// its argument, preserving the value category. Example:
+//
+// Foo() : bar_(ABSL_DIE_IF_NULL(MethodReturningUniquePtr())) {}
+//
+// Use `CHECK(ptr)` or `CHECK(ptr != nullptr)` if the returned pointer is
+// unused.
+#define ABSL_DIE_IF_NULL(val) \
+ ::absl::log_internal::DieIfNull(__FILE__, __LINE__, #val, (val))
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Crashes the process after logging `exprtext` annotated at the `file` and
+// `line` location. Called when `ABSL_DIE_IF_NULL` fails. Calling this function
+// generates less code than its implementation would if inlined, for a slight
+// code size reduction each time `ABSL_DIE_IF_NULL` is called.
+ABSL_ATTRIBUTE_NORETURN ABSL_ATTRIBUTE_NOINLINE void DieBecauseNull(
+ const char* file, int line, const char* exprtext);
+
+// Helper for `ABSL_DIE_IF_NULL`.
+template <typename T>
+ABSL_MUST_USE_RESULT T DieIfNull(const char* file, int line,
+ const char* exprtext, T&& t) {
+ if (ABSL_PREDICT_FALSE(t == nullptr)) {
+ // Call a non-inline helper function for a small code size improvement.
+ DieBecauseNull(file, line, exprtext);
+ }
+ return std::forward<T>(t);
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_DIE_IF_NULL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/flags.cc b/contrib/restricted/abseil-cpp/absl/log/flags.cc
new file mode 100644
index 0000000000..b5308881e4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/flags.cc
@@ -0,0 +1,112 @@
+//
+// 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/flags.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <cstdlib>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+void SyncLoggingFlags() {
+ absl::SetFlag(&FLAGS_minloglevel, static_cast<int>(absl::MinLogLevel()));
+ absl::SetFlag(&FLAGS_log_prefix, absl::ShouldPrependLogPrefix());
+}
+
+bool RegisterSyncLoggingFlags() {
+ log_internal::SetLoggingGlobalsListener(&SyncLoggingFlags);
+ return true;
+}
+
+ABSL_ATTRIBUTE_UNUSED const bool unused = RegisterSyncLoggingFlags();
+
+template <typename T>
+T GetFromEnv(const char* varname, T dflt) {
+ const char* val = ::getenv(varname);
+ if (val != nullptr) {
+ std::string err;
+ ABSL_INTERNAL_CHECK(absl::ParseFlag(val, &dflt, &err), err.c_str());
+ }
+ return dflt;
+}
+
+constexpr absl::LogSeverityAtLeast StderrThresholdDefault() {
+ return absl::LogSeverityAtLeast::kError;
+}
+
+} // namespace
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+ABSL_FLAG(int, stderrthreshold,
+ static_cast<int>(absl::log_internal::StderrThresholdDefault()),
+ "Log messages at or above this threshold level are copied to stderr.")
+ .OnUpdate([] {
+ absl::log_internal::RawSetStderrThreshold(
+ static_cast<absl::LogSeverityAtLeast>(
+ absl::GetFlag(FLAGS_stderrthreshold)));
+ });
+
+ABSL_FLAG(int, minloglevel, static_cast<int>(absl::LogSeverityAtLeast::kInfo),
+ "Messages logged at a lower level than this don't actually "
+ "get logged anywhere")
+ .OnUpdate([] {
+ absl::log_internal::RawSetMinLogLevel(
+ static_cast<absl::LogSeverityAtLeast>(
+ absl::GetFlag(FLAGS_minloglevel)));
+ });
+
+ABSL_FLAG(std::string, log_backtrace_at, "",
+ "Emit a backtrace when logging at file:linenum.")
+ .OnUpdate([] {
+ const std::string log_backtrace_at =
+ absl::GetFlag(FLAGS_log_backtrace_at);
+ if (log_backtrace_at.empty()) return;
+
+ const size_t last_colon = log_backtrace_at.rfind(':');
+ if (last_colon == log_backtrace_at.npos) return;
+
+ const absl::string_view file =
+ absl::string_view(log_backtrace_at).substr(0, last_colon);
+ int line;
+ if (absl::SimpleAtoi(
+ absl::string_view(log_backtrace_at).substr(last_colon + 1),
+ &line)) {
+ absl::SetLogBacktraceLocation(file, line);
+ }
+ });
+
+ABSL_FLAG(bool, log_prefix, true,
+ "Prepend the log prefix to the start of each log line")
+ .OnUpdate([] {
+ absl::log_internal::RawEnableLogPrefix(absl::GetFlag(FLAGS_log_prefix));
+ });
diff --git a/contrib/restricted/abseil-cpp/absl/log/globals.cc b/contrib/restricted/abseil-cpp/absl/log/globals.cc
new file mode 100644
index 0000000000..6dfe81f006
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/globals.cc
@@ -0,0 +1,148 @@
+// 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/globals.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/atomic_hook.h"
+#include "absl/base/log_severity.h"
+#include "absl/hash/hash.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+// These atomics represent logging library configuration.
+// Integer types are used instead of absl::LogSeverity to ensure that a
+// lock-free std::atomic is used when possible.
+ABSL_CONST_INIT std::atomic<int> min_log_level{
+ static_cast<int>(absl::LogSeverityAtLeast::kInfo)};
+ABSL_CONST_INIT std::atomic<int> stderrthreshold{
+ static_cast<int>(absl::LogSeverityAtLeast::kError)};
+// We evaluate this value as a hash comparison to avoid having to
+// hold a mutex or make a copy (to access the value of a string-typed flag) in
+// very hot codepath.
+ABSL_CONST_INIT std::atomic<size_t> log_backtrace_at_hash{0};
+ABSL_CONST_INIT std::atomic<bool> prepend_log_prefix{true};
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<log_internal::LoggingGlobalsListener>
+ logging_globals_listener;
+
+size_t HashSiteForLogBacktraceAt(absl::string_view file, int line) {
+ return absl::HashOf(file, line);
+}
+
+void TriggerLoggingGlobalsListener() {
+ auto* listener = logging_globals_listener.Load();
+ if (listener != nullptr) listener();
+}
+
+} // namespace
+
+namespace log_internal {
+
+void RawSetMinLogLevel(absl::LogSeverityAtLeast severity) {
+ min_log_level.store(static_cast<int>(severity), std::memory_order_release);
+}
+
+void RawSetStderrThreshold(absl::LogSeverityAtLeast severity) {
+ stderrthreshold.store(static_cast<int>(severity), std::memory_order_release);
+}
+
+void RawEnableLogPrefix(bool on_off) {
+ prepend_log_prefix.store(on_off, std::memory_order_release);
+}
+
+void SetLoggingGlobalsListener(LoggingGlobalsListener l) {
+ logging_globals_listener.Store(l);
+}
+
+} // namespace log_internal
+
+absl::LogSeverityAtLeast MinLogLevel() {
+ return static_cast<absl::LogSeverityAtLeast>(
+ min_log_level.load(std::memory_order_acquire));
+}
+
+void SetMinLogLevel(absl::LogSeverityAtLeast severity) {
+ log_internal::RawSetMinLogLevel(severity);
+ TriggerLoggingGlobalsListener();
+}
+
+namespace log_internal {
+
+ScopedMinLogLevel::ScopedMinLogLevel(absl::LogSeverityAtLeast severity)
+ : saved_severity_(absl::MinLogLevel()) {
+ absl::SetMinLogLevel(severity);
+}
+ScopedMinLogLevel::~ScopedMinLogLevel() {
+ absl::SetMinLogLevel(saved_severity_);
+}
+
+} // namespace log_internal
+
+absl::LogSeverityAtLeast StderrThreshold() {
+ return static_cast<absl::LogSeverityAtLeast>(
+ stderrthreshold.load(std::memory_order_acquire));
+}
+
+void SetStderrThreshold(absl::LogSeverityAtLeast severity) {
+ log_internal::RawSetStderrThreshold(severity);
+ TriggerLoggingGlobalsListener();
+}
+
+ScopedStderrThreshold::ScopedStderrThreshold(absl::LogSeverityAtLeast severity)
+ : saved_severity_(absl::StderrThreshold()) {
+ absl::SetStderrThreshold(severity);
+}
+
+ScopedStderrThreshold::~ScopedStderrThreshold() {
+ absl::SetStderrThreshold(saved_severity_);
+}
+
+namespace log_internal {
+
+bool ShouldLogBacktraceAt(absl::string_view file, int line) {
+ const size_t flag_hash =
+ log_backtrace_at_hash.load(std::memory_order_acquire);
+
+ return flag_hash != 0 && flag_hash == HashSiteForLogBacktraceAt(file, line);
+}
+
+} // namespace log_internal
+
+void SetLogBacktraceLocation(absl::string_view file, int line) {
+ log_backtrace_at_hash.store(HashSiteForLogBacktraceAt(file, line),
+ std::memory_order_release);
+}
+
+bool ShouldPrependLogPrefix() {
+ return prepend_log_prefix.load(std::memory_order_acquire);
+}
+
+void EnableLogPrefix(bool on_off) {
+ log_internal::RawEnableLogPrefix(on_off);
+ TriggerLoggingGlobalsListener();
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/globals.h b/contrib/restricted/abseil-cpp/absl/log/globals.h
new file mode 100644
index 0000000000..32b87db058
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/globals.h
@@ -0,0 +1,165 @@
+// 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/globals.h
+// -----------------------------------------------------------------------------
+//
+// This header declares global logging library configuration knobs.
+
+#ifndef ABSL_LOG_GLOBALS_H_
+#define ABSL_LOG_GLOBALS_H_
+
+#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
+
+//------------------------------------------------------------------------------
+// Minimum Log Level
+//------------------------------------------------------------------------------
+//
+// Messages logged at or above this severity are directed to all registered log
+// sinks or skipped otherwise. This parameter can also be modified using
+// command line flag --minloglevel.
+// See absl/base/log_severity.h for descriptions of severity levels.
+
+// MinLogLevel()
+//
+// Returns the value of the Minimum Log Level parameter.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast MinLogLevel();
+
+// SetMinLogLevel()
+//
+// Updates the value of Minimum Log Level parameter.
+// This function is async-signal-safe.
+void SetMinLogLevel(absl::LogSeverityAtLeast severity);
+
+namespace log_internal {
+
+// ScopedMinLogLevel
+//
+// RAII type used to temporarily update the Min Log Level parameter.
+class ScopedMinLogLevel final {
+ public:
+ explicit ScopedMinLogLevel(absl::LogSeverityAtLeast severity);
+ ScopedMinLogLevel(const ScopedMinLogLevel&) = delete;
+ ScopedMinLogLevel& operator=(const ScopedMinLogLevel&) = delete;
+ ~ScopedMinLogLevel();
+
+ private:
+ absl::LogSeverityAtLeast saved_severity_;
+};
+
+} // namespace log_internal
+
+//------------------------------------------------------------------------------
+// Stderr Threshold
+//------------------------------------------------------------------------------
+//
+// Messages logged at or above this level are directed to stderr in
+// addition to other registered log sinks. This parameter can also be modified
+// using command line flag --stderrthreshold.
+// See absl/base/log_severity.h for descriptions of severity levels.
+
+// StderrThreshold()
+//
+// Returns the value of the Stderr Threshold parameter.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT absl::LogSeverityAtLeast StderrThreshold();
+
+// SetStderrThreshold()
+//
+// Updates the Stderr Threshold parameter.
+// This function is async-signal-safe.
+void SetStderrThreshold(absl::LogSeverityAtLeast severity);
+inline void SetStderrThreshold(absl::LogSeverity severity) {
+ absl::SetStderrThreshold(static_cast<absl::LogSeverityAtLeast>(severity));
+}
+
+// ScopedStderrThreshold
+//
+// RAII type used to temporarily update the Stderr Threshold parameter.
+class ScopedStderrThreshold final {
+ public:
+ explicit ScopedStderrThreshold(absl::LogSeverityAtLeast severity);
+ ScopedStderrThreshold(const ScopedStderrThreshold&) = delete;
+ ScopedStderrThreshold& operator=(const ScopedStderrThreshold&) = delete;
+ ~ScopedStderrThreshold();
+
+ private:
+ absl::LogSeverityAtLeast saved_severity_;
+};
+
+//------------------------------------------------------------------------------
+// Log Backtrace At
+//------------------------------------------------------------------------------
+//
+// Users can request backtrace to be logged at specific locations, specified
+// by file and line number.
+
+// ShouldLogBacktraceAt()
+//
+// Returns true if we should log a backtrace at the specified location.
+namespace log_internal {
+ABSL_MUST_USE_RESULT bool ShouldLogBacktraceAt(absl::string_view file,
+ int line);
+} // namespace log_internal
+
+// SetLogBacktraceLocation()
+//
+// Sets the location the backtrace should be logged at.
+void SetLogBacktraceLocation(absl::string_view file, int line);
+
+//------------------------------------------------------------------------------
+// Prepend Log Prefix
+//------------------------------------------------------------------------------
+//
+// This option tells the logging library that every logged message
+// should include the prefix (severity, date, time, PID, etc.)
+
+// ShouldPrependLogPrefix()
+//
+// Returns the value of the Prepend Log Prefix option.
+// This function is async-signal-safe.
+ABSL_MUST_USE_RESULT bool ShouldPrependLogPrefix();
+
+// EnableLogPrefix()
+//
+// Updates the value of the Prepend Log Prefix option.
+// This function is async-signal-safe.
+void EnableLogPrefix(bool on_off);
+
+namespace log_internal {
+
+using LoggingGlobalsListener = void (*)();
+void SetLoggingGlobalsListener(LoggingGlobalsListener l);
+
+// Internal implementation for the setter routines. These are used
+// to break circular dependencies between flags and globals. Each "Raw"
+// routine corresponds to the non-"Raw" counterpart and used to set the
+// configuration parameter directly without calling back to the listener.
+void RawSetMinLogLevel(absl::LogSeverityAtLeast severity);
+void RawSetStderrThreshold(absl::LogSeverityAtLeast severity);
+void RawEnableLogPrefix(bool on_off);
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_GLOBALS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/initialize.cc b/contrib/restricted/abseil-cpp/absl/log/initialize.cc
new file mode 100644
index 0000000000..a3f6d6c142
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/initialize.cc
@@ -0,0 +1,34 @@
+// 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/initialize.h"
+
+#include "absl/base/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+void InitializeLog() {
+ // This comes first since it is used by RAW_LOG.
+ absl::log_internal::SetTimeZone(absl::LocalTimeZone());
+
+ // Note that initialization is complete, so logs can now be sent to their
+ // proper destinations rather than stderr.
+ log_internal::SetInitialized();
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/initialize.h b/contrib/restricted/abseil-cpp/absl/log/initialize.h
new file mode 100644
index 0000000000..f600eb606c
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/initialize.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/initialize.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the Abseil Log initialization routine InitializeLog().
+
+#ifndef ABSL_LOG_INITIALIZE_H_
+#define ABSL_LOG_INITIALIZE_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// InitializeLog()
+//
+// Initializes the Abseil logging library.
+//
+// Before this function is called, all log messages are directed only to stderr.
+// After initialization is finished, log messages are directed to all registered
+// `LogSink`s.
+//
+// It is an error to call this function twice.
+//
+// There is no corresponding function to shut down the logging library.
+void InitializeLog();
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INITIALIZE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/append_truncated.h b/contrib/restricted/abseil-cpp/absl/log/internal/append_truncated.h
new file mode 100644
index 0000000000..f0e7912c2a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/append_truncated.h
@@ -0,0 +1,47 @@
+// Copyright 2022 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
+#define ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
+
+#include <cstddef>
+#include <cstring>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+// Copies into `dst` as many bytes of `src` as will fit, then truncates the
+// copied bytes from the front of `dst` and returns the number of bytes written.
+inline size_t AppendTruncated(absl::string_view src, absl::Span<char> &dst) {
+ if (src.size() > dst.size()) src = src.substr(0, dst.size());
+ memcpy(dst.data(), src.data(), src.size());
+ dst.remove_prefix(src.size());
+ return src.size();
+}
+// Likewise, but `n` copies of `c`.
+inline size_t AppendTruncated(char c, size_t n, absl::Span<char> &dst) {
+ if (n > dst.size()) n = dst.size();
+ memset(dst.data(), c, n);
+ dst.remove_prefix(n);
+ return n;
+}
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_APPEND_TRUNCATED_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc
new file mode 100644
index 0000000000..f4b67647a6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.cc
@@ -0,0 +1,118 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/check_op.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#define strcasecmp _stricmp
+#else
+#include <strings.h> // for strcasecmp, but msvc does not have this header
+#endif
+
+#include <sstream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#define ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(x) \
+ template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(bool);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(int64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(uint64_t);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(float);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(double);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(unsigned char);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const std::string&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const absl::string_view&);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const signed char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const unsigned char*);
+ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING(const void*);
+#undef ABSL_LOGGING_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING
+
+CheckOpMessageBuilder::CheckOpMessageBuilder(const char* exprtext) {
+ stream_ << exprtext << " (";
+}
+
+std::ostream& CheckOpMessageBuilder::ForVar2() {
+ stream_ << " vs. ";
+ return stream_;
+}
+
+std::string* CheckOpMessageBuilder::NewString() {
+ stream_ << ")";
+ return new std::string(stream_.str());
+}
+
+void MakeCheckOpValueString(std::ostream& os, const char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const signed char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "signed char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const unsigned char v) {
+ if (v >= 32 && v <= 126) {
+ os << "'" << v << "'";
+ } else {
+ os << "unsigned char value " << int{v};
+ }
+}
+
+void MakeCheckOpValueString(std::ostream& os, const void* p) {
+ if (p == nullptr) {
+ os << "(null)";
+ } else {
+ os << p;
+ }
+}
+
+// Helper functions for string comparisons.
+#define DEFINE_CHECK_STROP_IMPL(name, func, expected) \
+ std::string* Check##func##expected##Impl(const char* s1, const char* s2, \
+ const char* exprtext) { \
+ bool equal = s1 == s2 || (s1 && s2 && !func(s1, s2)); \
+ if (equal == expected) { \
+ return nullptr; \
+ } else { \
+ return new std::string( \
+ absl::StrCat(exprtext, " (", s1, " vs. ", s2, ")")); \
+ } \
+ }
+DEFINE_CHECK_STROP_IMPL(CHECK_STREQ, strcmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRNE, strcmp, false)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASEEQ, strcasecmp, true)
+DEFINE_CHECK_STROP_IMPL(CHECK_STRCASENE, strcasecmp, false)
+#undef DEFINE_CHECK_STROP_IMPL
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h
new file mode 100644
index 0000000000..4907b89bcf
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/check_op.h
@@ -0,0 +1,392 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/check_op.h
+// -----------------------------------------------------------------------------
+//
+// This file declares helpers routines and macros used to implement `CHECK`
+// macros.
+
+#ifndef ABSL_LOG_INTERNAL_CHECK_OP_H_
+#define ABSL_LOG_INTERNAL_CHECK_OP_H_
+
+#include <stdint.h>
+
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/nullguard.h"
+#include "absl/log/internal/nullstream.h"
+#include "absl/log/internal/strip.h"
+
+// `ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL` wraps string literals that
+// should be stripped when `ABSL_MIN_LOG_LEVEL` exceeds `kFatal`.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) \
+ (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? (literal) \
+ : "")
+#else
+#define ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(literal) (literal)
+#endif
+
+#ifdef NDEBUG
+// `NDEBUG` is defined, so `DCHECK_EQ(x, y)` and so on do nothing. However, we
+// still want the compiler to parse `x` and `y`, because we don't want to lose
+// potentially useful errors and warnings.
+#define ABSL_LOG_INTERNAL_DCHECK_NOP(x, y) \
+ while (false && ((void)(x), (void)(y), 0)) \
+ ::absl::log_internal::NullStream().InternalStream()
+#endif
+
+#define ABSL_LOG_INTERNAL_CHECK_OP(name, op, val1, val1_text, val2, val2_text) \
+ while ( \
+ ::std::string* absl_log_internal_check_op_result ABSL_ATTRIBUTE_UNUSED = \
+ ::absl::log_internal::name##Impl( \
+ ::absl::log_internal::GetReferenceableValue(val1), \
+ ::absl::log_internal::GetReferenceableValue(val2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val1_text \
+ " " #op " " val2_text))) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OP(name, op, val1, val1_text, val2, \
+ val2_text) \
+ while (::std::string* absl_log_internal_qcheck_op_result = \
+ ::absl::log_internal::name##Impl( \
+ ::absl::log_internal::GetReferenceableValue(val1), \
+ ::absl::log_internal::GetReferenceableValue(val2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL( \
+ val1_text " " #op " " val2_text))) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_op_result).InternalStream()
+#define ABSL_LOG_INTERNAL_CHECK_STROP(func, op, expected, s1, s1_text, s2, \
+ s2_text) \
+ while (::std::string* absl_log_internal_check_strop_result = \
+ ::absl::log_internal::Check##func##expected##Impl( \
+ (s1), (s2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
+ " " s2_text))) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_strop_result) \
+ .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_STROP(func, op, expected, s1, s1_text, s2, \
+ s2_text) \
+ while (::std::string* absl_log_internal_qcheck_strop_result = \
+ ::absl::log_internal::Check##func##expected##Impl( \
+ (s1), (s2), \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(s1_text " " #op \
+ " " s2_text))) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_qcheck_strop_result) \
+ .InternalStream()
+// This one is tricky:
+// * We must evaluate `val` exactly once, yet we need to do two things with it:
+// evaluate `.ok()` and (sometimes) `.ToString()`.
+// * `val` might be an `absl::Status` or some `absl::StatusOr<T>`.
+// * `val` might be e.g. `ATemporary().GetStatus()`, which may return a
+// reference to a member of `ATemporary` that is only valid until the end of
+// the full expression.
+// * We don't want this file to depend on `absl::Status` `#include`s or linkage,
+// nor do we want to move the definition to status and introduce a dependency
+// in the other direction. We can be assured that callers must already have a
+// `Status` and the necessary `#include`s and linkage.
+// * Callsites should be small and fast (at least when `val.ok()`): one branch,
+// minimal stack footprint.
+// * In particular, the string concat stuff should be out-of-line and emitted
+// in only one TU to save linker input size
+// * We want the `val.ok()` check inline so static analyzers and optimizers can
+// see it.
+// * As usual, no braces so we can stream into the expansion with `operator<<`.
+// * Also as usual, it must expand to a single (partial) statement with no
+// ambiguous-else problems.
+#define ABSL_LOG_INTERNAL_CHECK_OK(val, val_text) \
+ for (::std::pair<const ::absl::Status*, ::std::string*> \
+ absl_log_internal_check_ok_goo; \
+ absl_log_internal_check_ok_goo.first = \
+ ::absl::log_internal::AsStatus(val), \
+ absl_log_internal_check_ok_goo.second = \
+ ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
+ ? nullptr \
+ : ::absl::status_internal::MakeCheckFailString( \
+ absl_log_internal_check_ok_goo.first, \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
+ " is OK")), \
+ !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
+ ABSL_LOG_INTERNAL_CHECK(*absl_log_internal_check_ok_goo.second) \
+ .InternalStream()
+#define ABSL_LOG_INTERNAL_QCHECK_OK(val, val_text) \
+ for (::std::pair<const ::absl::Status*, ::std::string*> \
+ absl_log_internal_check_ok_goo; \
+ absl_log_internal_check_ok_goo.first = \
+ ::absl::log_internal::AsStatus(val), \
+ absl_log_internal_check_ok_goo.second = \
+ ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok()) \
+ ? nullptr \
+ : ::absl::status_internal::MakeCheckFailString( \
+ absl_log_internal_check_ok_goo.first, \
+ ABSL_LOG_INTERNAL_STRIP_STRING_LITERAL(val_text \
+ " is OK")), \
+ !ABSL_PREDICT_TRUE(absl_log_internal_check_ok_goo.first->ok());) \
+ ABSL_LOG_INTERNAL_QCHECK(*absl_log_internal_check_ok_goo.second) \
+ .InternalStream()
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class Status;
+template <typename T>
+class StatusOr;
+
+namespace status_internal {
+std::string* MakeCheckFailString(const absl::Status* status,
+ const char* prefix);
+} // namespace status_internal
+
+namespace log_internal {
+
+// Convert a Status or a StatusOr to its underlying status value.
+//
+// (This implementation does not require a dep on absl::Status to work.)
+inline const absl::Status* AsStatus(const absl::Status& s) { return &s; }
+template <typename T>
+const absl::Status* AsStatus(const absl::StatusOr<T>& s) {
+ return &s.status();
+}
+
+// A helper class for formatting `expr (V1 vs. V2)` in a `CHECK_XX` statement.
+// See `MakeCheckOpString` for sample usage.
+class CheckOpMessageBuilder final {
+ public:
+ // Inserts `exprtext` and ` (` to the stream.
+ explicit CheckOpMessageBuilder(const char* exprtext);
+ ~CheckOpMessageBuilder() = default;
+ // For inserting the first variable.
+ std::ostream& ForVar1() { return stream_; }
+ // For inserting the second variable (adds an intermediate ` vs. `).
+ std::ostream& ForVar2();
+ // Get the result (inserts the closing `)`).
+ std::string* NewString();
+
+ private:
+ std::ostringstream stream_;
+};
+
+// This formats a value for a failing `CHECK_XX` statement. Ordinarily, it uses
+// the definition for `operator<<`, with a few special cases below.
+template <typename T>
+inline void MakeCheckOpValueString(std::ostream& os, const T& v) {
+ os << log_internal::NullGuard<T>::Guard(v);
+}
+
+// Overloads for char types provide readable values for unprintable characters.
+void MakeCheckOpValueString(std::ostream& os, char v);
+void MakeCheckOpValueString(std::ostream& os, signed char v);
+void MakeCheckOpValueString(std::ostream& os, unsigned char v);
+void MakeCheckOpValueString(std::ostream& os, const void* p);
+
+namespace detect_specialization {
+
+// MakeCheckOpString is being specialized for every T and U pair that is being
+// passed to the CHECK_op macros. However, there is a lot of redundancy in these
+// specializations that creates unnecessary library and binary bloat.
+// The number of instantiations tends to be O(n^2) because we have two
+// independent inputs. This technique works by reducing `n`.
+//
+// Most user-defined types being passed to CHECK_op end up being printed as a
+// builtin type. For example, enums tend to be implicitly converted to its
+// underlying type when calling operator<<, and pointers are printed with the
+// `const void*` overload.
+// To reduce the number of instantiations we coerce these values before calling
+// MakeCheckOpString instead of inside it.
+//
+// To detect if this coercion is needed, we duplicate all the relevant
+// operator<< overloads as specified in the standard, just in a different
+// namespace. If the call to `stream << value` becomes ambiguous, it means that
+// one of these overloads is the one selected by overload resolution. We then
+// do overload resolution again just with our overload set to see which one gets
+// selected. That tells us which type to coerce to.
+// If the augmented call was not ambiguous, it means that none of these were
+// selected and we can't coerce the input.
+//
+// As a secondary step to reduce code duplication, we promote integral types to
+// their 64-bit variant. This does not change the printed value, but reduces the
+// number of instantiations even further. Promoting an integer is very cheap at
+// the call site.
+int64_t operator<<(std::ostream&, short value); // NOLINT
+int64_t operator<<(std::ostream&, unsigned short value); // NOLINT
+int64_t operator<<(std::ostream&, int value);
+int64_t operator<<(std::ostream&, unsigned int value);
+int64_t operator<<(std::ostream&, long value); // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long value); // NOLINT
+int64_t operator<<(std::ostream&, long long value); // NOLINT
+uint64_t operator<<(std::ostream&, unsigned long long value); // NOLINT
+float operator<<(std::ostream&, float value);
+double operator<<(std::ostream&, double value);
+long double operator<<(std::ostream&, long double value);
+bool operator<<(std::ostream&, bool value);
+const void* operator<<(std::ostream&, const void* value);
+const void* operator<<(std::ostream&, std::nullptr_t);
+
+// These `char` overloads are specified like this in the standard, so we have to
+// write them exactly the same to ensure the call is ambiguous.
+// If we wrote it in a different way (eg taking std::ostream instead of the
+// template) then one call might have a higher rank than the other and it would
+// not be ambiguous.
+template <typename Traits>
+char operator<<(std::basic_ostream<char, Traits>&, char);
+template <typename Traits>
+signed char operator<<(std::basic_ostream<char, Traits>&, signed char);
+template <typename Traits>
+unsigned char operator<<(std::basic_ostream<char, Traits>&, unsigned char);
+template <typename Traits>
+const char* operator<<(std::basic_ostream<char, Traits>&, const char*);
+template <typename Traits>
+const signed char* operator<<(std::basic_ostream<char, Traits>&,
+ const signed char*);
+template <typename Traits>
+const unsigned char* operator<<(std::basic_ostream<char, Traits>&,
+ const unsigned char*);
+
+// This overload triggers when the call is not ambiguous.
+// It means that T is being printed with some overload not on this list.
+// We keep the value as `const T&`.
+template <typename T, typename = decltype(std::declval<std::ostream&>()
+ << std::declval<const T&>())>
+const T& Detect(int);
+
+// This overload triggers when the call is ambiguous.
+// It means that T is either one from this list or printed as one from this
+// list. Eg an enum that decays to `int` for printing.
+// We ask the overload set to give us the type we want to convert it to.
+template <typename T>
+decltype(detect_specialization::operator<<(std::declval<std::ostream&>(),
+ std::declval<const T&>()))
+Detect(char);
+
+} // namespace detect_specialization
+
+template <typename T>
+using CheckOpStreamType = decltype(detect_specialization::Detect<T>(0));
+
+// Build the error message string. Specify no inlining for code size.
+template <typename T1, typename T2>
+ABSL_ATTRIBUTE_RETURNS_NONNULL std::string* MakeCheckOpString(
+ T1 v1, T2 v2, const char* exprtext) ABSL_ATTRIBUTE_NOINLINE;
+
+template <typename T1, typename T2>
+std::string* MakeCheckOpString(T1 v1, T2 v2, const char* exprtext) {
+ CheckOpMessageBuilder comb(exprtext);
+ MakeCheckOpValueString(comb.ForVar1(), v1);
+ MakeCheckOpValueString(comb.ForVar2(), v2);
+ return comb.NewString();
+}
+
+// Add a few commonly used instantiations as extern to reduce size of objects
+// files.
+#define ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(x) \
+ extern template std::string* MakeCheckOpString(x, x, const char*)
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(bool);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(int64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(uint64_t);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(float);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(double);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(unsigned char);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const std::string&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const absl::string_view&);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const signed char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const unsigned char*);
+ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN(const void*);
+#undef ABSL_LOG_INTERNAL_DEFINE_MAKE_CHECK_OP_STRING_EXTERN
+
+// Helper functions for `ABSL_LOG_INTERNAL_CHECK_OP` macro family. The
+// `(int, int)` override works around the issue that the compiler will not
+// instantiate the template version of the function on values of unnamed enum
+// type.
+#define ABSL_LOG_INTERNAL_CHECK_OP_IMPL(name, op) \
+ template <typename T1, typename T2> \
+ inline constexpr ::std::string* name##Impl(const T1& v1, const T2& v2, \
+ const char* exprtext) { \
+ using U1 = CheckOpStreamType<T1>; \
+ using U2 = CheckOpStreamType<T2>; \
+ return ABSL_PREDICT_TRUE(v1 op v2) \
+ ? nullptr \
+ : MakeCheckOpString<U1, U2>(v1, v2, exprtext); \
+ } \
+ inline constexpr ::std::string* name##Impl(int v1, int v2, \
+ const char* exprtext) { \
+ return name##Impl<int, int>(v1, v2, exprtext); \
+ }
+
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_EQ, ==)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_NE, !=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LE, <=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_LT, <)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GE, >=)
+ABSL_LOG_INTERNAL_CHECK_OP_IMPL(Check_GT, >)
+#undef ABSL_LOG_INTERNAL_CHECK_OP_IMPL
+
+std::string* CheckstrcmptrueImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcmpfalseImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcasecmptrueImpl(const char* s1, const char* s2,
+ const char* exprtext);
+std::string* CheckstrcasecmpfalseImpl(const char* s1, const char* s2,
+ const char* exprtext);
+
+// `CHECK_EQ` and friends want to pass their arguments by reference, however
+// this winds up exposing lots of cases where people have defined and
+// initialized static const data members but never declared them (i.e. in a .cc
+// file), meaning they are not referenceable. This function avoids that problem
+// for integers (the most common cases) by overloading for every primitive
+// integer type, even the ones we discourage, and returning them by value.
+template <typename T>
+inline constexpr const T& GetReferenceableValue(const T& t) {
+ return t;
+}
+inline constexpr char GetReferenceableValue(char t) { return t; }
+inline constexpr unsigned char GetReferenceableValue(unsigned char t) {
+ return t;
+}
+inline constexpr signed char GetReferenceableValue(signed char t) { return t; }
+inline constexpr short GetReferenceableValue(short t) { return t; } // NOLINT
+inline constexpr unsigned short GetReferenceableValue( // NOLINT
+ unsigned short t) { // NOLINT
+ return t;
+}
+inline constexpr int GetReferenceableValue(int t) { return t; }
+inline unsigned int GetReferenceableValue(unsigned int t) { return t; }
+inline constexpr long GetReferenceableValue(long t) { return t; } // NOLINT
+inline constexpr unsigned long GetReferenceableValue( // NOLINT
+ unsigned long t) { // NOLINT
+ return t;
+}
+inline constexpr long long GetReferenceableValue(long long t) { // NOLINT
+ return t;
+}
+inline constexpr unsigned long long GetReferenceableValue( // NOLINT
+ unsigned long long t) { // NOLINT
+ return t;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CHECK_OP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc
new file mode 100644
index 0000000000..a9f4966f5d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.cc
@@ -0,0 +1,83 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/conditions.h"
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/cycleclock.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// The following code behaves like AtomicStatsCounter::LossyAdd() for
+// speed since it is fine to lose occasional updates.
+// Returns old value of *counter.
+uint32_t LossyIncrement(std::atomic<uint32_t>* counter) {
+ const uint32_t value = counter->load(std::memory_order_relaxed);
+ counter->store(value + 1, std::memory_order_relaxed);
+ return value;
+}
+
+} // namespace
+
+bool LogEveryNState::ShouldLog(int n) {
+ return n > 0 && (LossyIncrement(&counter_) % static_cast<uint32_t>(n)) == 0;
+}
+
+bool LogFirstNState::ShouldLog(int n) {
+ const uint32_t counter_value = counter_.load(std::memory_order_relaxed);
+ if (static_cast<int64_t>(counter_value) < n) {
+ counter_.store(counter_value + 1, std::memory_order_relaxed);
+ return true;
+ }
+ return false;
+}
+
+bool LogEveryPow2State::ShouldLog() {
+ const uint32_t new_value = LossyIncrement(&counter_) + 1;
+ return (new_value & (new_value - 1)) == 0;
+}
+
+bool LogEveryNSecState::ShouldLog(double seconds) {
+ using absl::base_internal::CycleClock;
+ LossyIncrement(&counter_);
+ const int64_t now_cycles = CycleClock::Now();
+ int64_t next_cycles = next_log_time_cycles_.load(std::memory_order_relaxed);
+#if defined(__myriad2__)
+ // myriad2 does not have 8-byte compare and exchange. Use a racy version that
+ // is "good enough" but will over-log in the face of concurrent logging.
+ if (now_cycles > next_cycles) {
+ next_log_time_cycles_.store(now_cycles + seconds * CycleClock::Frequency(),
+ std::memory_order_relaxed);
+ return true;
+ }
+ return false;
+#else
+ do {
+ if (now_cycles <= next_cycles) return false;
+ } while (!next_log_time_cycles_.compare_exchange_weak(
+ next_cycles, now_cycles + seconds * CycleClock::Frequency(),
+ std::memory_order_relaxed, std::memory_order_relaxed));
+ return true;
+#endif
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h
new file mode 100644
index 0000000000..b89f1dfd7b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/conditions.h
@@ -0,0 +1,222 @@
+// 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_
+
+#ifdef _WIN32
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/log/internal/voidify.h"
+
+// `ABSL_LOG_INTERNAL_CONDITION` prefixes another macro that expands to a
+// temporary `LogMessage` instantiation followed by zero or more streamed
+// expressions. This definition is tricky to read correctly. It evaluates to
+// either
+//
+// (void)0;
+//
+// or
+//
+// ::absl::log_internal::Voidify() &&
+// ::absl::log_internal::LogMessage(...) << "the user's message";
+//
+// If the condition is evaluable at compile time, as is often the case, it
+// compiles away to just one side or the other.
+//
+// Although this is not used anywhere a statement (e.g. `if`) could not go,
+// the ternary expression does a better job avoiding spurious diagnostics
+// (dangling else, missing switch case) and preserving noreturn semantics (e.g.
+// on `LOG(FATAL)`) without requiring braces.
+#define ABSL_LOG_INTERNAL_STATELESS_CONDITION(condition) \
+ switch (0) \
+ case 0: \
+ !(condition) ? (void)0 : ::absl::log_internal::Voidify()&&
+
+// `ABSL_LOG_INTERNAL_STATEFUL_CONDITION` applies a condition like
+// `ABSL_LOG_INTERNAL_CONDITION` but adds to that a series of variable
+// declarations, including a local static object which stores the state needed
+// to implement the stateful macros like `LOG_EVERY_N`.
+//
+// `for`-loops are used to declare scoped variables without braces (to permit
+// streaming into the macro's expansion) and without the dangling-`else`
+// problems/diagnostics that come with `if`.
+//
+// Two more variables are declared in separate `for`-loops:
+//
+// * `COUNTER` implements a streamable token whose value when streamed is the
+// number of times execution has passed through the macro.
+// * A boolean flag is used to prevent any of the `for`-loops from ever actually
+// looping.
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION(condition) \
+ for (bool absl_log_internal_stateful_condition_do_log(condition); \
+ absl_log_internal_stateful_condition_do_log; \
+ absl_log_internal_stateful_condition_do_log = false) \
+ ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL
+#define ABSL_LOG_INTERNAL_STATEFUL_CONDITION_IMPL(kind, ...) \
+ for (static ::absl::log_internal::Log##kind##State \
+ absl_log_internal_stateful_condition_state; \
+ absl_log_internal_stateful_condition_do_log && \
+ absl_log_internal_stateful_condition_state.ShouldLog(__VA_ARGS__); \
+ absl_log_internal_stateful_condition_do_log = false) \
+ for (const uint32_t COUNTER ABSL_ATTRIBUTE_UNUSED = \
+ absl_log_internal_stateful_condition_state.counter(); \
+ absl_log_internal_stateful_condition_do_log; \
+ absl_log_internal_stateful_condition_do_log = false)
+
+// `ABSL_LOG_INTERNAL_CONDITION_*` serve to combine any conditions from the
+// macro (e.g. `LOG_IF` or `VLOG`) with inherent conditions (e.g.
+// `ABSL_MIN_LOG_LEVEL`) into a single boolean expression. We could chain
+// ternary operators instead, however some versions of Clang sometimes issue
+// spurious diagnostics after such expressions due to a control flow analysis
+// bug.
+#ifdef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kInfo >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kWarning >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && ::absl::LogSeverity::kError >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ ((condition) \
+ ? (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? true \
+ : (::absl::log_internal::AbortQuietly(), false)) \
+ : false))
+// NOTE: Use ternary operators instead of short-circuiting to mitigate
+// https://bugs.llvm.org/show_bug.cgi?id=51928.
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ ((condition) \
+ ? (::absl::LogSeverity::kFatal >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) \
+ ? true \
+ : (::absl::log_internal::ExitQuietly(), false)) \
+ : false))
+
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
+ for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+ log_internal_severity_loop = 0) \
+ for (const absl::LogSeverity log_internal_severity = \
+ ::absl::NormalizeLogSeverity(severity); \
+ log_internal_severity_loop; log_internal_severity_loop = 0) \
+ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION( \
+ (condition) && \
+ (log_internal_severity >= \
+ static_cast<::absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) || \
+ (log_internal_severity == ::absl::LogSeverity::kFatal && \
+ (::absl::log_internal::AbortQuietly(), false))))
+#else // ndef ABSL_MIN_LOG_LEVEL
+#define ABSL_LOG_INTERNAL_CONDITION_INFO(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_WARNING(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_ERROR(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_FATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_QFATAL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL(severity) \
+ for (int log_internal_severity_loop = 1; log_internal_severity_loop; \
+ log_internal_severity_loop = 0) \
+ for (const absl::LogSeverity log_internal_severity = \
+ ::absl::NormalizeLogSeverity(severity); \
+ log_internal_severity_loop; log_internal_severity_loop = 0) \
+ ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL
+#define ABSL_LOG_INTERNAL_CONDITION_LEVEL_IMPL(type, condition) \
+ ABSL_LOG_INTERNAL_##type##_CONDITION(condition)
+#endif // ndef ABSL_MIN_LOG_LEVEL
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Stateful condition class name should be "Log" + name + "State".
+class LogEveryNState final {
+ public:
+ bool ShouldLog(int n);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogFirstNState final {
+ public:
+ bool ShouldLog(int n);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryPow2State final {
+ public:
+ bool ShouldLog();
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+};
+
+class LogEveryNSecState final {
+ public:
+ bool ShouldLog(double seconds);
+ uint32_t counter() { return counter_.load(std::memory_order_relaxed); }
+
+ private:
+ std::atomic<uint32_t> counter_{0};
+ // Cycle count according to CycleClock that we should next log at.
+ std::atomic<int64_t> next_log_time_cycles_{0};
+};
+
+// Helper routines to abort the application quietly
+
+ABSL_ATTRIBUTE_NORETURN inline void AbortQuietly() { abort(); }
+ABSL_ATTRIBUTE_NORETURN inline void ExitQuietly() { _exit(1); }
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CONDITIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/config.h b/contrib/restricted/abseil-cpp/absl/log/internal/config.h
new file mode 100644
index 0000000000..379e9ab974
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/config.h
@@ -0,0 +1,45 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/config.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_CONFIG_H_
+#define ABSL_LOG_INTERNAL_CONFIG_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <cstdint>
+#else
+#include <sys/types.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+#ifdef _WIN32
+using Tid = uint32_t;
+#else
+using Tid = pid_t;
+#endif
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_CONFIG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/flags.h b/contrib/restricted/abseil-cpp/absl/log/internal/flags.h
new file mode 100644
index 0000000000..0c5e81edee
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/flags.h
@@ -0,0 +1,53 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/log_flags.h
+// -----------------------------------------------------------------------------
+//
+// This header declares set of flags which can be used to configure Abseil
+// Logging library behaviour at runtime.
+
+#ifndef ABSL_LOG_INTERNAL_FLAGS_H_
+#define ABSL_LOG_INTERNAL_FLAGS_H_
+
+#include <string>
+
+#include "absl/flags/declare.h"
+
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// These flags should not be used in C++ code to access logging library
+// configuration knobs. Use interfaces defined in absl/log/globals.h
+// instead. It is still ok to use these flags on a command line.
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Log messages at this severity or above are sent to stderr in *addition* to
+// logfiles. Defaults to `ERROR`. See log_severity.h for numeric values of
+// severity levels.
+ABSL_DECLARE_FLAG(int, stderrthreshold);
+
+// Log messages at this severity or above are logged; others are discarded.
+// Defaults to `INFO`, i.e. log all severities. See log_severity.h for numeric
+// values of severity levels.
+ABSL_DECLARE_FLAG(int, minloglevel);
+
+// If specified in the form file:linenum, any messages logged from a matching
+// location will also include a backtrace.
+ABSL_DECLARE_FLAG(std::string, log_backtrace_at);
+
+// If true, the log prefix (severity, date, time, PID, etc.) is prepended to
+// each message logged. Defaults to true.
+ABSL_DECLARE_FLAG(bool, log_prefix);
+
+#endif // ABSL_LOG_INTERNAL_FLAGS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc b/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc
new file mode 100644
index 0000000000..863b047f33
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/globals.cc
@@ -0,0 +1,125 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/globals.h"
+
+#include <atomic>
+#include <cstdio>
+
+#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/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// Keeps track of whether Logging initialization is finalized.
+// Log messages generated before that will go to stderr.
+ABSL_CONST_INIT std::atomic<bool> logging_initialized(false);
+
+// The TimeZone used for logging. This may only be set once.
+ABSL_CONST_INIT std::atomic<absl::TimeZone*> timezone_ptr{nullptr};
+
+// If true, the logging library will symbolize stack in fatal messages
+ABSL_CONST_INIT std::atomic<bool> symbolize_stack_trace(true);
+
+// Specifies maximum number of stack frames to report in fatal messages.
+ABSL_CONST_INIT std::atomic<int> max_frames_in_stack_trace(64);
+
+ABSL_CONST_INIT std::atomic<bool> exit_on_dfatal(true);
+ABSL_CONST_INIT std::atomic<bool> suppress_sigabort_trace(false);
+} // namespace
+
+bool IsInitialized() {
+ return logging_initialized.load(std::memory_order_acquire);
+}
+
+void SetInitialized() {
+ logging_initialized.store(true, std::memory_order_release);
+}
+
+void WriteToStderr(absl::string_view message, absl::LogSeverity severity) {
+ // 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);
+
+#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/contrib/restricted/abseil-cpp/absl/log/internal/globals.h b/contrib/restricted/abseil-cpp/absl/log/internal/globals.h
new file mode 100644
index 0000000000..27bc0d0984
--- /dev/null
+++ b/contrib/restricted/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/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc b/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc
new file mode 100644
index 0000000000..b8cd5ac40e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_format.cc
@@ -0,0 +1,203 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_format.h"
+
+#include <string.h>
+
+#ifdef _MSC_VER
+#include <winsock2.h> // For timeval
+#else
+#include <sys/time.h>
+#endif
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/optimization.h"
+#include "absl/log/internal/append_truncated.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// This templated function avoids compiler warnings about tautological
+// comparisons when log_internal::Tid is unsigned. It can be replaced with a
+// constexpr if once the minimum C++ version Abseil suppports is C++17.
+template <typename T>
+inline std::enable_if_t<!std::is_signed<T>::value>
+PutLeadingWhitespace(T tid, char*& p) {
+ if (tid < 10) *p++ = ' ';
+ if (tid < 100) *p++ = ' ';
+ if (tid < 1000) *p++ = ' ';
+ if (tid < 10000) *p++ = ' ';
+ if (tid < 100000) *p++ = ' ';
+ if (tid < 1000000) *p++ = ' ';
+}
+
+template <typename T>
+inline std::enable_if_t<std::is_signed<T>::value>
+PutLeadingWhitespace(T tid, char*& p) {
+ if (tid >= 0 && tid < 10) *p++ = ' ';
+ if (tid > -10 && tid < 100) *p++ = ' ';
+ if (tid > -100 && tid < 1000) *p++ = ' ';
+ if (tid > -1000 && tid < 10000) *p++ = ' ';
+ if (tid > -10000 && tid < 100000) *p++ = ' ';
+ if (tid > -100000 && tid < 1000000) *p++ = ' ';
+}
+
+// The fields before the filename are all fixed-width except for the thread ID,
+// which is of bounded width.
+size_t FormatBoundedFields(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::Span<char>& buf) {
+ constexpr size_t kBoundedFieldsMaxLen =
+ sizeof("SMMDD HH:MM:SS.NNNNNN ") +
+ (1 + std::numeric_limits<log_internal::Tid>::digits10 + 1) - sizeof("");
+ if (ABSL_PREDICT_FALSE(buf.size() < kBoundedFieldsMaxLen)) {
+ // We don't bother trying to truncate these fields if the buffer is too
+ // short (or almost too short) because it would require doing a lot more
+ // length checking (slow) and it should never happen. A 15kB buffer should
+ // be enough for anyone. Instead we mark `buf` full without writing
+ // anything.
+ buf.remove_suffix(buf.size());
+ return 0;
+ }
+
+ // We can't call absl::LocalTime(), localtime_r(), or anything else here that
+ // isn't async-signal-safe. We can only use the time zone if it has already
+ // been loaded.
+ const absl::TimeZone* tz = absl::log_internal::TimeZone();
+ if (ABSL_PREDICT_FALSE(tz == nullptr)) {
+ // If a time zone hasn't been set yet because we are logging before the
+ // logging library has been initialized, we fallback to a simpler, slower
+ // method. Just report the raw Unix time in seconds. We cram this into the
+ // normal time format for the benefit of parsers.
+ auto tv = absl::ToTimeval(timestamp);
+ int snprintf_result = absl::SNPrintF(
+ buf.data(), buf.size(), "%c0000 00:00:%02d.%06d %7d ",
+ absl::LogSeverityName(severity)[0], static_cast<int>(tv.tv_sec),
+ static_cast<int>(tv.tv_usec), static_cast<int>(tid));
+ if (snprintf_result >= 0) {
+ buf.remove_prefix(static_cast<size_t>(snprintf_result));
+ return static_cast<size_t>(snprintf_result);
+ }
+ return 0;
+ }
+
+ char* p = buf.data();
+ *p++ = absl::LogSeverityName(severity)[0];
+ const absl::TimeZone::CivilInfo ci = tz->At(timestamp);
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(ci.cs.month()), p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(ci.cs.day()), p);
+ p += 2;
+ *p++ = ' ';
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(ci.cs.hour()), p);
+ p += 2;
+ *p++ = ':';
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(ci.cs.minute()), p);
+ p += 2;
+ *p++ = ':';
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(ci.cs.second()), p);
+ p += 2;
+ *p++ = '.';
+ const int64_t usecs = absl::ToInt64Microseconds(ci.subsecond);
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(usecs / 10000), p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(usecs / 100 % 100),
+ p);
+ p += 2;
+ absl::numbers_internal::PutTwoDigits(static_cast<size_t>(usecs % 100), p);
+ p += 2;
+ *p++ = ' ';
+ PutLeadingWhitespace(tid, p);
+ p = absl::numbers_internal::FastIntToBuffer(tid, p);
+ *p++ = ' ';
+ const size_t bytes_formatted = static_cast<size_t>(p - buf.data());
+ buf.remove_prefix(bytes_formatted);
+ return bytes_formatted;
+}
+
+size_t FormatLineNumber(int line, absl::Span<char>& buf) {
+ constexpr size_t kLineFieldMaxLen =
+ sizeof(":] ") + (1 + std::numeric_limits<int>::digits10 + 1) - sizeof("");
+ if (ABSL_PREDICT_FALSE(buf.size() < kLineFieldMaxLen)) {
+ // As above, we don't bother trying to truncate this if the buffer is too
+ // short and it should never happen.
+ buf.remove_suffix(buf.size());
+ return 0;
+ }
+ char* p = buf.data();
+ *p++ = ':';
+ p = absl::numbers_internal::FastIntToBuffer(line, p);
+ *p++ = ']';
+ *p++ = ' ';
+ const size_t bytes_formatted = static_cast<size_t>(p - buf.data());
+ buf.remove_prefix(bytes_formatted);
+ return bytes_formatted;
+}
+
+} // namespace
+
+std::string FormatLogMessage(absl::LogSeverity severity,
+ absl::CivilSecond civil_second,
+ absl::Duration subsecond, log_internal::Tid tid,
+ absl::string_view basename, int line,
+ PrefixFormat format, absl::string_view message) {
+ return absl::StrFormat(
+ "%c%02d%02d %02d:%02d:%02d.%06d %7d %s:%d] %s%s",
+ absl::LogSeverityName(severity)[0], civil_second.month(),
+ civil_second.day(), civil_second.hour(), civil_second.minute(),
+ civil_second.second(), absl::ToInt64Microseconds(subsecond), tid,
+ basename, line, format == PrefixFormat::kRaw ? "RAW: " : "", message);
+}
+
+// This method is fairly hot, and the library always passes a huge `buf`, so we
+// save some bounds-checking cycles by not trying to do precise truncation.
+// Truncating at a field boundary is probably a better UX anyway.
+//
+// The prefix is written in three parts, each of which does a single
+// bounds-check and truncation:
+// 1. severity, timestamp, and thread ID
+// 2. filename
+// 3. line number and bracket
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::string_view basename,
+ int line, PrefixFormat format, absl::Span<char>& buf) {
+ auto prefix_size = FormatBoundedFields(severity, timestamp, tid, buf);
+ prefix_size += log_internal::AppendTruncated(basename, buf);
+ prefix_size += FormatLineNumber(line, buf);
+ if (format == PrefixFormat::kRaw)
+ prefix_size += log_internal::AppendTruncated("RAW: ", buf);
+ return prefix_size;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_format.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_format.h
new file mode 100644
index 0000000000..95a45edf61
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_format.h
@@ -0,0 +1,78 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_format.h
+// -----------------------------------------------------------------------------
+//
+// This file declares routines implementing formatting of log message and log
+// prefix.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+#define ABSL_LOG_INTERNAL_LOG_FORMAT_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/civil_time.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+enum class PrefixFormat {
+ kNotRaw,
+ kRaw,
+};
+
+// Formats log message based on provided data.
+std::string FormatLogMessage(absl::LogSeverity severity,
+ absl::CivilSecond civil_second,
+ absl::Duration subsecond, log_internal::Tid tid,
+ absl::string_view basename, int line,
+ PrefixFormat format, absl::string_view message);
+
+// Formats various entry metadata into a text string meant for use as a
+// prefix on a log message string. Writes into `buf`, advances `buf` to point
+// at the remainder of the buffer (i.e. past any written bytes), and returns the
+// number of bytes written.
+//
+// In addition to calling `buf->remove_prefix()` (or the equivalent), this
+// function may also do `buf->remove_suffix(buf->size())` in cases where no more
+// bytes (i.e. no message data) should be written into the buffer. For example,
+// if the prefix ought to be:
+// I0926 09:00:00.000000 1234567 foo.cc:123]
+// `buf` is too small, the function might fill the whole buffer:
+// I0926 09:00:00.000000 1234
+// (note the apparrently incorrect thread ID), or it might write less:
+// I0926 09:00:00.000000
+// In this case, it might also empty `buf` prior to returning to prevent
+// message data from being written into the space where a reader would expect to
+// see a thread ID.
+size_t FormatLogPrefix(absl::LogSeverity severity, absl::Time timestamp,
+ log_internal::Tid tid, absl::string_view basename,
+ int line, PrefixFormat format, absl::Span<char>& buf);
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_LOG_FORMAT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h
new file mode 100644
index 0000000000..82b5ed84d6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_impl.h
@@ -0,0 +1,212 @@
+// Copyright 2022 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_IMPL_H_
+#define ABSL_LOG_INTERNAL_LOG_IMPL_H_
+
+#include "absl/log/internal/conditions.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/strip.h"
+
+// ABSL_LOG()
+#define ABSL_LOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+// ABSL_PLOG()
+#define ABSL_PLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+// ABSL_DLOG()
+#ifndef NDEBUG
+#define ABSL_DLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, true) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#else
+#define ABSL_DLOG_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, false) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#endif
+
+#define ABSL_LOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#define ABSL_PLOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#ifndef NDEBUG
+#define ABSL_DLOG_IF_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATELESS, condition) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+#else
+#define ABSL_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_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_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_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_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_PLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_PLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(FirstN, n) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_PLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, true)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream() \
+ .WithPerror()
+
+#define ABSL_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_DLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_DLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_DLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, true) \
+ (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_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_DLOG_EVERY_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (EveryN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_DLOG_FIRST_N_IMPL(severity, n) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (FirstN, n) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_DLOG_EVERY_POW_2_IMPL(severity) \
+ ABSL_LOG_INTERNAL_CONDITION_INFO(STATEFUL, false) \
+ (EveryPow2) ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_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_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_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_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_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_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_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_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_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_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_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_DLOG_IF_EVERY_POW_2_IMPL(severity, condition) \
+ ABSL_LOG_INTERNAL_CONDITION##severity(STATEFUL, condition)(EveryPow2) \
+ ABSL_LOGGING_INTERNAL_LOG##severity.InternalStream()
+
+#define ABSL_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_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_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_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_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/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc
new file mode 100644
index 0000000000..bdb10f2a07
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.cc
@@ -0,0 +1,618 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_message.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+#include <algorithm>
+#include <array>
+#include <atomic>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <tuple>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/strerror.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/log_severity.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/debugging/internal/examine_stack.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/append_truncated.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/internal/log_format.h"
+#include "absl/log/internal/log_sink_set.h"
+#include "absl/log/internal/proto.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/log/log_sink_registry.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "absl/types/span.h"
+
+extern "C" ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalOnFatalLogMessage)(const absl::LogEntry&) {
+ // Default - Do nothing
+}
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+namespace {
+// message `logging.proto.Event`
+enum EventTag : uint8_t {
+ kValue = 7,
+};
+
+// message `logging.proto.Value`
+enum ValueTag : uint8_t {
+ kString = 1,
+ kStringLiteral = 6,
+};
+
+// Decodes a `logging.proto.Value` from `buf` and writes a string representation
+// into `dst`. The string representation will be truncated if `dst` is not
+// large enough to hold it. Returns false if `dst` has size zero or one (i.e.
+// sufficient only for a nul-terminator) and no decoded data could be written.
+// This function may or may not write a nul-terminator into `dst`, and it may or
+// may not truncate the data it writes in order to do make space for that nul
+// terminator. In any case, `dst` will be advanced to point at the byte where
+// subsequent writes should begin.
+bool PrintValue(absl::Span<char>& dst, absl::Span<const char> buf) {
+ if (dst.size() <= 1) return false;
+ ProtoField field;
+ while (field.DecodeFrom(&buf)) {
+ switch (field.tag()) {
+ case ValueTag::kString:
+ case ValueTag::kStringLiteral:
+ if (field.type() == WireType::kLengthDelimited)
+ if (log_internal::AppendTruncated(field.string_value(), dst) <
+ field.string_value().size())
+ return false;
+ }
+ }
+ return true;
+}
+
+absl::string_view Basename(absl::string_view filepath) {
+#ifdef _WIN32
+ size_t path = filepath.find_last_of("/\\");
+#else
+ size_t path = filepath.find_last_of('/');
+#endif
+ if (path != filepath.npos) filepath.remove_prefix(path + 1);
+ return filepath;
+}
+
+void WriteToString(const char* data, void* str) {
+ reinterpret_cast<std::string*>(str)->append(data);
+}
+void WriteToStream(const char* data, void* os) {
+ auto* cast_os = static_cast<std::ostream*>(os);
+ *cast_os << data;
+}
+} // namespace
+
+struct LogMessage::LogMessageData final {
+ LogMessageData(const char* file, int line, absl::LogSeverity severity,
+ absl::Time timestamp);
+ LogMessageData(const LogMessageData&) = delete;
+ LogMessageData& operator=(const LogMessageData&) = delete;
+
+ // `LogEntry` sent to `LogSink`s; contains metadata.
+ absl::LogEntry entry;
+
+ // true => this was first fatal msg
+ bool first_fatal;
+ // true => all failures should be quiet
+ bool fail_quietly;
+ // true => PLOG was requested
+ bool is_perror;
+
+ // Extra `LogSink`s to log to, in addition to `global_sinks`.
+ absl::InlinedVector<absl::LogSink*, 16> extra_sinks;
+ // If true, log to `extra_sinks` but not to `global_sinks` or hardcoded
+ // non-sink targets (e.g. stderr, log files).
+ bool extra_sinks_only;
+
+ std::ostream manipulated; // ostream with IO manipulators applied
+
+ // A `logging.proto.Event` proto message is built into `encoded_buf`.
+ std::array<char, kLogMessageBufferSize> encoded_buf;
+ // `encoded_remaining` is the suffix of `encoded_buf` that has not been filled
+ // yet. If a datum to be encoded does not fit into `encoded_remaining` and
+ // cannot be truncated to fit, the size of `encoded_remaining` will be zeroed
+ // to prevent encoding of any further data. Note that in this case its data()
+ // pointer will not point past the end of `encoded_buf`.
+ absl::Span<char> encoded_remaining;
+
+ // A formatted string message is built in `string_buf`.
+ std::array<char, kLogMessageBufferSize> string_buf;
+
+ void FinalizeEncodingAndFormat();
+};
+
+LogMessage::LogMessageData::LogMessageData(const char* file, int line,
+ absl::LogSeverity severity,
+ absl::Time timestamp)
+ : extra_sinks_only(false),
+ manipulated(nullptr),
+ // This `absl::MakeSpan` silences spurious -Wuninitialized from GCC:
+ encoded_remaining(absl::MakeSpan(encoded_buf)) {
+ // Legacy defaults for LOG's ostream:
+ manipulated.setf(std::ios_base::showbase | std::ios_base::boolalpha);
+ entry.full_filename_ = file;
+ entry.base_filename_ = Basename(file);
+ entry.line_ = line;
+ entry.prefix_ = absl::ShouldPrependLogPrefix();
+ entry.severity_ = absl::NormalizeLogSeverity(severity);
+ entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+ entry.timestamp_ = timestamp;
+ entry.tid_ = absl::base_internal::GetCachedTID();
+}
+
+void LogMessage::LogMessageData::FinalizeEncodingAndFormat() {
+ // Note that `encoded_remaining` may have zero size without pointing past the
+ // end of `encoded_buf`, so the difference between `data()` pointers is used
+ // to compute the size of `encoded_data`.
+ absl::Span<const char> encoded_data(
+ encoded_buf.data(),
+ static_cast<size_t>(encoded_remaining.data() - encoded_buf.data()));
+ // `string_remaining` is the suffix of `string_buf` that has not been filled
+ // yet.
+ absl::Span<char> string_remaining(string_buf);
+ // We may need to write a newline and nul-terminator at the end of the decoded
+ // string data. Rather than worry about whether those should overwrite the
+ // end of the string (if the buffer is full) or be appended, we avoid writing
+ // into the last two bytes so we always have space to append.
+ string_remaining.remove_suffix(2);
+ entry.prefix_len_ =
+ entry.prefix() ? log_internal::FormatLogPrefix(
+ entry.log_severity(), entry.timestamp(), entry.tid(),
+ entry.source_basename(), entry.source_line(),
+ log_internal::ThreadIsLoggingToLogSink()
+ ? PrefixFormat::kRaw
+ : PrefixFormat::kNotRaw,
+ string_remaining)
+ : 0;
+ // Decode data from `encoded_buf` until we run out of data or we run out of
+ // `string_remaining`.
+ ProtoField field;
+ while (field.DecodeFrom(&encoded_data)) {
+ switch (field.tag()) {
+ case EventTag::kValue:
+ if (field.type() != WireType::kLengthDelimited) continue;
+ if (PrintValue(string_remaining, field.bytes_value())) continue;
+ break;
+ }
+ break;
+ }
+ auto chars_written =
+ static_cast<size_t>(string_remaining.data() - string_buf.data());
+ string_buf[chars_written++] = '\n';
+ string_buf[chars_written++] = '\0';
+ entry.text_message_with_prefix_and_newline_and_nul_ =
+ absl::MakeSpan(string_buf).subspan(0, chars_written);
+}
+
+LogMessage::LogMessage(const char* file, int line, absl::LogSeverity severity)
+ : data_(absl::make_unique<LogMessageData>(file, line, severity,
+ absl::Now())) {
+ data_->first_fatal = false;
+ data_->is_perror = false;
+ data_->fail_quietly = false;
+
+ // This logs a backtrace even if the location is subsequently changed using
+ // AtLocation. This quirk, and the behavior when AtLocation is called twice,
+ // are fixable but probably not worth fixing.
+ LogBacktraceIfNeeded();
+}
+
+LogMessage::~LogMessage() {
+#ifdef ABSL_MIN_LOG_LEVEL
+ if (data_->entry.log_severity() <
+ static_cast<absl::LogSeverity>(ABSL_MIN_LOG_LEVEL) &&
+ data_->entry.log_severity() < absl::LogSeverity::kFatal) {
+ return;
+ }
+#endif
+ Flush();
+}
+
+LogMessage& LogMessage::AtLocation(absl::string_view file, int line) {
+ data_->entry.full_filename_ = file;
+ data_->entry.base_filename_ = Basename(file);
+ data_->entry.line_ = line;
+ LogBacktraceIfNeeded();
+ return *this;
+}
+
+LogMessage& LogMessage::NoPrefix() {
+ data_->entry.prefix_ = false;
+ return *this;
+}
+
+LogMessage& LogMessage::WithVerbosity(int verbose_level) {
+ if (verbose_level == absl::LogEntry::kNoVerbosityLevel) {
+ data_->entry.verbose_level_ = absl::LogEntry::kNoVerbosityLevel;
+ } else {
+ data_->entry.verbose_level_ = std::max(0, verbose_level);
+ }
+ return *this;
+}
+
+LogMessage& LogMessage::WithTimestamp(absl::Time timestamp) {
+ data_->entry.timestamp_ = timestamp;
+ return *this;
+}
+
+LogMessage& LogMessage::WithThreadID(absl::LogEntry::tid_t tid) {
+ data_->entry.tid_ = tid;
+ return *this;
+}
+
+LogMessage& LogMessage::WithMetadataFrom(const absl::LogEntry& entry) {
+ data_->entry.full_filename_ = entry.full_filename_;
+ data_->entry.base_filename_ = entry.base_filename_;
+ data_->entry.line_ = entry.line_;
+ data_->entry.prefix_ = entry.prefix_;
+ data_->entry.severity_ = entry.severity_;
+ data_->entry.verbose_level_ = entry.verbose_level_;
+ data_->entry.timestamp_ = entry.timestamp_;
+ data_->entry.tid_ = entry.tid_;
+ return *this;
+}
+
+LogMessage& LogMessage::WithPerror() {
+ data_->is_perror = true;
+ return *this;
+}
+
+LogMessage& LogMessage::ToSinkAlso(absl::LogSink* sink) {
+ ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+ data_->extra_sinks.push_back(sink);
+ return *this;
+}
+
+LogMessage& LogMessage::ToSinkOnly(absl::LogSink* sink) {
+ ABSL_INTERNAL_CHECK(sink, "null LogSink*");
+ data_->extra_sinks.clear();
+ data_->extra_sinks.push_back(sink);
+ data_->extra_sinks_only = true;
+ return *this;
+}
+
+#ifdef __ELF__
+extern "C" void __gcov_dump() ABSL_ATTRIBUTE_WEAK;
+extern "C" void __gcov_flush() ABSL_ATTRIBUTE_WEAK;
+#endif
+
+void LogMessage::FailWithoutStackTrace() {
+ // Now suppress repeated trace logging:
+ log_internal::SetSuppressSigabortTrace(true);
+#if defined _DEBUG && defined COMPILER_MSVC
+ // When debugging on windows, avoid the obnoxious dialog.
+ __debugbreak();
+#endif
+
+#ifdef __ELF__
+ // For b/8737634, flush coverage if we are in coverage mode.
+ if (&__gcov_dump != nullptr) {
+ __gcov_dump();
+ } else if (&__gcov_flush != nullptr) {
+ __gcov_flush();
+ }
+#endif
+
+ abort();
+}
+
+void LogMessage::FailQuietly() {
+ // _exit. Calling abort() would trigger all sorts of death signal handlers
+ // and a detailed stack trace. Calling exit() would trigger the onexit
+ // handlers, including the heap-leak checker, which is guaranteed to fail in
+ // this case: we probably just new'ed the std::string that we logged.
+ // Anyway, if you're calling Fail or FailQuietly, you're trying to bail out
+ // of the program quickly, and it doesn't make much sense for FailQuietly to
+ // offer different guarantees about exit behavior than Fail does. (And as a
+ // consequence for QCHECK and CHECK to offer different exit behaviors)
+ _exit(1);
+}
+
+LogMessage& LogMessage::operator<<(const std::string& v) {
+ CopyToEncodedBuffer(v, StringType::kNotLiteral);
+ return *this;
+}
+
+LogMessage& LogMessage::operator<<(absl::string_view v) {
+ CopyToEncodedBuffer(v, StringType::kNotLiteral);
+ return *this;
+}
+LogMessage& LogMessage::operator<<(std::ostream& (*m)(std::ostream& os)) {
+ OstreamView view(*data_);
+ data_->manipulated << m;
+ return *this;
+}
+LogMessage& LogMessage::operator<<(std::ios_base& (*m)(std::ios_base& os)) {
+ OstreamView view(*data_);
+ data_->manipulated << m;
+ return *this;
+}
+template LogMessage& LogMessage::operator<<(const char& v);
+template LogMessage& LogMessage::operator<<(const signed char& v);
+template LogMessage& LogMessage::operator<<(const unsigned char& v);
+template LogMessage& LogMessage::operator<<(const short& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned short& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const int& v);
+template LogMessage& LogMessage::operator<<(const unsigned int& v);
+template LogMessage& LogMessage::operator<<(const long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const unsigned long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(const long long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(
+ const unsigned long long& v); // NOLINT
+template LogMessage& LogMessage::operator<<(void* const& v);
+template LogMessage& LogMessage::operator<<(const void* const& v);
+template LogMessage& LogMessage::operator<<(const float& v);
+template LogMessage& LogMessage::operator<<(const double& v);
+template LogMessage& LogMessage::operator<<(const bool& v);
+
+void LogMessage::Flush() {
+ if (data_->entry.log_severity() < absl::MinLogLevel())
+ return;
+
+ if (data_->is_perror) {
+ InternalStream() << ": " << absl::base_internal::StrError(errno_saver_())
+ << " [" << errno_saver_() << "]";
+ }
+
+ // Have we already seen a fatal message?
+ ABSL_CONST_INIT static std::atomic<bool> seen_fatal(false);
+ if (data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+ absl::log_internal::ExitOnDFatal()) {
+ // Exactly one LOG(FATAL) message is responsible for aborting the process,
+ // even if multiple threads LOG(FATAL) concurrently.
+ bool expected_seen_fatal = false;
+ if (seen_fatal.compare_exchange_strong(expected_seen_fatal, true,
+ std::memory_order_relaxed)) {
+ data_->first_fatal = true;
+ }
+ }
+
+ data_->FinalizeEncodingAndFormat();
+ data_->entry.encoding_ =
+ absl::string_view(data_->encoded_buf.data(),
+ static_cast<size_t>(data_->encoded_remaining.data() -
+ data_->encoded_buf.data()));
+ SendToLog();
+}
+
+void LogMessage::SetFailQuietly() { data_->fail_quietly = true; }
+
+LogMessage::OstreamView::OstreamView(LogMessageData& message_data)
+ : data_(message_data), encoded_remaining_copy_(data_.encoded_remaining) {
+ // This constructor sets the `streambuf` up so that streaming into an attached
+ // ostream encodes string data in-place. To do that, we write appropriate
+ // headers into the buffer using a copy of the buffer view so that we can
+ // decide not to keep them later if nothing is ever streamed in. We don't
+ // know how much data we'll get, but we can use the size of the remaining
+ // buffer as an upper bound and fill in the right size once we know it.
+ message_start_ =
+ EncodeMessageStart(EventTag::kValue, encoded_remaining_copy_.size(),
+ &encoded_remaining_copy_);
+ string_start_ =
+ EncodeMessageStart(ValueTag::kString, encoded_remaining_copy_.size(),
+ &encoded_remaining_copy_);
+ setp(encoded_remaining_copy_.data(),
+ encoded_remaining_copy_.data() + encoded_remaining_copy_.size());
+ data_.manipulated.rdbuf(this);
+}
+
+LogMessage::OstreamView::~OstreamView() {
+ data_.manipulated.rdbuf(nullptr);
+ if (!string_start_.data()) {
+ // The second field header didn't fit. Whether the first one did or not, we
+ // shouldn't commit `encoded_remaining_copy_`, and we also need to zero the
+ // size of `data_->encoded_remaining` so that no more data are encoded.
+ data_.encoded_remaining.remove_suffix(data_.encoded_remaining.size());
+ return;
+ }
+ const absl::Span<const char> contents(pbase(),
+ static_cast<size_t>(pptr() - pbase()));
+ if (contents.empty()) return;
+ encoded_remaining_copy_.remove_prefix(contents.size());
+ EncodeMessageLength(string_start_, &encoded_remaining_copy_);
+ EncodeMessageLength(message_start_, &encoded_remaining_copy_);
+ data_.encoded_remaining = encoded_remaining_copy_;
+}
+
+std::ostream& LogMessage::OstreamView::stream() { return data_.manipulated; }
+
+bool LogMessage::IsFatal() const {
+ return data_->entry.log_severity() == absl::LogSeverity::kFatal &&
+ absl::log_internal::ExitOnDFatal();
+}
+
+void LogMessage::PrepareToDie() {
+ // If we log a FATAL message, flush all the log destinations, then toss
+ // a signal for others to catch. We leave the logs in a state that
+ // someone else can use them (as long as they flush afterwards)
+ if (data_->first_fatal) {
+ // Notify observers about the upcoming fatal error.
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalOnFatalLogMessage)(data_->entry);
+ }
+
+ if (!data_->fail_quietly) {
+ // Log the message first before we start collecting stack trace.
+ log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+ data_->extra_sinks_only);
+
+ // `DumpStackTrace` generates an empty string under MSVC.
+ // Adding the constant prefix here simplifies testing.
+ data_->entry.stacktrace_ = "*** Check failure stack trace: ***\n";
+ debugging_internal::DumpStackTrace(
+ 0, log_internal::MaxFramesInLogStackTrace(),
+ log_internal::ShouldSymbolizeLogStackTrace(), WriteToString,
+ &data_->entry.stacktrace_);
+ }
+}
+
+void LogMessage::Die() {
+ absl::FlushLogSinks();
+
+ if (data_->fail_quietly) {
+ FailQuietly();
+ } else {
+ FailWithoutStackTrace();
+ }
+}
+
+void LogMessage::SendToLog() {
+ if (IsFatal()) PrepareToDie();
+ // Also log to all registered sinks, even if OnlyLogToStderr() is set.
+ log_internal::LogToSinks(data_->entry, absl::MakeSpan(data_->extra_sinks),
+ data_->extra_sinks_only);
+ if (IsFatal()) Die();
+}
+
+void LogMessage::LogBacktraceIfNeeded() {
+ if (!absl::log_internal::IsInitialized()) return;
+
+ if (!absl::log_internal::ShouldLogBacktraceAt(data_->entry.source_basename(),
+ data_->entry.source_line()))
+ return;
+ OstreamView view(*data_);
+ view.stream() << " (stacktrace:\n";
+ debugging_internal::DumpStackTrace(
+ 1, log_internal::MaxFramesInLogStackTrace(),
+ log_internal::ShouldSymbolizeLogStackTrace(), WriteToStream,
+ &view.stream());
+ view.stream() << ") ";
+}
+
+// Encodes into `data_->encoded_remaining` a partial `logging.proto.Event`
+// containing the specified string data using a `Value` field appropriate to
+// `str_type`. Truncates `str` if necessary, but emits nothing and marks the
+// buffer full if even the field headers do not fit.
+void LogMessage::CopyToEncodedBuffer(absl::string_view str,
+ StringType str_type) {
+ 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());
+ }
+}
+void LogMessage::CopyToEncodedBuffer(char ch, size_t num, StringType str_type) {
+ 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());
+ }
+}
+
+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/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h
new file mode 100644
index 0000000000..3744276bfb
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_message.h
@@ -0,0 +1,355 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_message.h
+// -----------------------------------------------------------------------------
+//
+// This file declares `class absl::log_internal::LogMessage`. This class more or
+// less represents a particular log message. LOG/CHECK macros create a
+// temporary instance of `LogMessage` and then stream values to it. At the end
+// of the LOG/CHECK statement, LogMessage instance goes out of scope and
+// `~LogMessage` directs the message to the registered log sinks.
+// Heap-allocation of `LogMessage` is unsupported. Construction outside of a
+// `LOG` macro is unsupported.
+
+#ifndef ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+#define ABSL_LOG_INTERNAL_LOG_MESSAGE_H_
+
+#include <ios>
+#include <memory>
+#include <ostream>
+#include <streambuf>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/errno_saver.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/nullguard.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/strings/internal/has_absl_stringify.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+constexpr int kLogMessageBufferSize = 15000;
+
+class LogMessage {
+ public:
+ // Used for `LOG`.
+ LogMessage(const char* file, int line,
+ absl::LogSeverity severity) ABSL_ATTRIBUTE_COLD;
+ LogMessage(const LogMessage&) = delete;
+ LogMessage& operator=(const LogMessage&) = delete;
+ ~LogMessage() ABSL_ATTRIBUTE_COLD;
+
+ // Overrides the location inferred from the callsite. The string pointed to
+ // by `file` must be valid until the end of the statement.
+ LogMessage& AtLocation(absl::string_view file, int line);
+ // Omits the prefix from this line. The prefix includes metadata about the
+ // logged data such as source code location and timestamp.
+ LogMessage& NoPrefix();
+ // Sets the verbosity field of the logged message as if it was logged by
+ // `VLOG(verbose_level)`. Unlike `VLOG`, this method does not affect
+ // evaluation of the statement when the specified `verbose_level` has been
+ // disabled. The only effect is on `absl::LogSink` implementations which
+ // make use of the `absl::LogSink::verbosity()` value. The value
+ // `absl::LogEntry::kNoVerbosityLevel` can be specified to mark the message
+ // not verbose.
+ LogMessage& WithVerbosity(int verbose_level);
+ // Uses the specified timestamp instead of one collected in the constructor.
+ LogMessage& WithTimestamp(absl::Time timestamp);
+ // Uses the specified thread ID instead of one collected in the constructor.
+ LogMessage& WithThreadID(absl::LogEntry::tid_t tid);
+ // Copies all metadata (but no data) from the specified `absl::LogEntry`.
+ LogMessage& WithMetadataFrom(const absl::LogEntry& entry);
+ // Appends to the logged message a colon, a space, a textual description of
+ // the current value of `errno` (as by strerror(3)), and the numerical value
+ // of `errno`.
+ LogMessage& WithPerror();
+ // Sends this message to `*sink` in addition to whatever other sinks it would
+ // otherwise have been sent to. `sink` must not be null.
+ LogMessage& ToSinkAlso(absl::LogSink* sink);
+ // Sends this message to `*sink` and no others. `sink` must not be null.
+ LogMessage& ToSinkOnly(absl::LogSink* sink);
+
+ // Don't call this method from outside this library.
+ LogMessage& InternalStream() { return *this; }
+
+ // By-value overloads for small, common types let us overlook common failures
+ // to define globals and static data members (i.e. in a .cc file).
+ // clang-format off
+ // The CUDA toolchain cannot handle these <<<'s:
+ LogMessage& operator<<(char v) { return operator<< <char>(v); }
+ LogMessage& operator<<(signed char v) { return operator<< <signed char>(v); }
+ LogMessage& operator<<(unsigned char v) {
+ return operator<< <unsigned char>(v);
+ }
+ LogMessage& operator<<(signed short v) { // NOLINT
+ return operator<< <signed short>(v); // NOLINT
+ }
+ LogMessage& operator<<(signed int v) { return operator<< <signed int>(v); }
+ LogMessage& operator<<(signed long v) { // NOLINT
+ return operator<< <signed long>(v); // NOLINT
+ }
+ LogMessage& operator<<(signed long long v) { // NOLINT
+ return operator<< <signed long long>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned short v) { // NOLINT
+ return operator<< <unsigned short>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned int v) {
+ return operator<< <unsigned int>(v);
+ }
+ LogMessage& operator<<(unsigned long v) { // NOLINT
+ return operator<< <unsigned long>(v); // NOLINT
+ }
+ LogMessage& operator<<(unsigned long long v) { // NOLINT
+ return operator<< <unsigned long long>(v); // NOLINT
+ }
+ LogMessage& operator<<(void* v) { return operator<< <void*>(v); }
+ LogMessage& operator<<(const void* v) { return operator<< <const void*>(v); }
+ LogMessage& operator<<(float v) { return operator<< <float>(v); }
+ LogMessage& operator<<(double v) { return operator<< <double>(v); }
+ LogMessage& operator<<(bool v) { return operator<< <bool>(v); }
+ // clang-format on
+
+ // These overloads are more efficient since no `ostream` is involved.
+ LogMessage& operator<<(const std::string& v);
+ LogMessage& operator<<(absl::string_view v);
+
+ // Handle stream manipulators e.g. std::endl.
+ LogMessage& operator<<(std::ostream& (*m)(std::ostream& os));
+ LogMessage& operator<<(std::ios_base& (*m)(std::ios_base& os));
+
+ // Literal strings. This allows us to record C string literals as literals in
+ // the logging.proto.Value.
+ //
+ // Allow this overload to be inlined to prevent generating instantiations of
+ // this template for every value of `SIZE` encountered in each source code
+ // file. That significantly increases linker input sizes. Inlining is cheap
+ // because the argument to this overload is almost always a string literal so
+ // the call to `strlen` can be replaced at compile time. The overload for
+ // `char[]` below should not be inlined. The compiler typically does not have
+ // the string at compile time and cannot replace the call to `strlen` so
+ // inlining it increases the binary size. See the discussion on
+ // cl/107527369.
+ template <int SIZE>
+ LogMessage& operator<<(const char (&buf)[SIZE]);
+
+ // This prevents non-const `char[]` arrays from looking like literals.
+ template <int SIZE>
+ LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Types that support `AbslStringify()` are serialized that way.
+ template <typename T,
+ typename std::enable_if<
+ strings_internal::HasAbslStringify<T>::value, int>::type = 0>
+ LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Types that don't support `AbslStringify()` but do support streaming into a
+ // `std::ostream&` are serialized that way.
+ template <typename T,
+ typename std::enable_if<
+ !strings_internal::HasAbslStringify<T>::value, int>::type = 0>
+ LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Note: We explicitly do not support `operator<<` for non-const references
+ // because it breaks logging of non-integer bitfield types (i.e., enums).
+
+ protected:
+ // Call `abort()` or similar to perform `LOG(FATAL)` crash. It is assumed
+ // that the caller has already generated and written the trace as appropriate.
+ ABSL_ATTRIBUTE_NORETURN static void FailWithoutStackTrace();
+
+ // Similar to `FailWithoutStackTrace()`, but without `abort()`. Terminates
+ // the process with an error exit code.
+ ABSL_ATTRIBUTE_NORETURN static void FailQuietly();
+
+ // Dispatches the completed `absl::LogEntry` to applicable `absl::LogSink`s.
+ // This might as well be inlined into `~LogMessage` except that
+ // `~LogMessageFatal` needs to call it early.
+ void Flush();
+
+ // After this is called, failures are done as quiet as possible for this log
+ // message.
+ void SetFailQuietly();
+
+ private:
+ struct LogMessageData; // Opaque type containing message state
+ friend class AsLiteralImpl;
+ friend class StringifySink;
+
+ // This streambuf writes directly into the structured logging buffer so that
+ // arbitrary types can be encoded as string data (using
+ // `operator<<(std::ostream &, ...)` without any extra allocation or copying.
+ // Space is reserved before the data to store the length field, which is
+ // filled in by `~OstreamView`.
+ class OstreamView final : public std::streambuf {
+ public:
+ explicit OstreamView(LogMessageData& message_data);
+ ~OstreamView() override;
+ OstreamView(const OstreamView&) = delete;
+ OstreamView& operator=(const OstreamView&) = delete;
+ std::ostream& stream();
+
+ private:
+ LogMessageData& data_;
+ absl::Span<char> encoded_remaining_copy_;
+ absl::Span<char> message_start_;
+ absl::Span<char> string_start_;
+ };
+
+ enum class StringType {
+ kLiteral,
+ kNotLiteral,
+ };
+ void CopyToEncodedBuffer(absl::string_view str,
+ StringType str_type) ABSL_ATTRIBUTE_NOINLINE;
+ void CopyToEncodedBuffer(char ch, size_t num,
+ StringType str_type) ABSL_ATTRIBUTE_NOINLINE;
+
+ // Returns `true` if the message is fatal or enabled debug-fatal.
+ bool IsFatal() const;
+
+ // Records some tombstone-type data in anticipation of `Die`.
+ void PrepareToDie();
+ void Die();
+
+ void SendToLog();
+
+ // Checks `FLAGS_log_backtrace_at` and appends a backtrace if appropriate.
+ void LogBacktraceIfNeeded();
+
+ // This should be the first data member so that its initializer captures errno
+ // before any other initializers alter it (e.g. with calls to new) and so that
+ // no other destructors run afterward an alter it (e.g. with calls to delete).
+ absl::base_internal::ErrnoSaver errno_saver_;
+
+ // We keep the data in a separate struct so that each instance of `LogMessage`
+ // uses less stack space.
+ std::unique_ptr<LogMessageData> data_;
+};
+
+// Helper class so that `AbslStringify()` can modify the LogMessage.
+class StringifySink final {
+ public:
+ explicit StringifySink(LogMessage& message) : message_(message) {}
+
+ void Append(size_t count, char ch) {
+ message_.CopyToEncodedBuffer(ch, count,
+ LogMessage::StringType::kNotLiteral);
+ }
+
+ void Append(absl::string_view v) {
+ message_.CopyToEncodedBuffer(v, LogMessage::StringType::kNotLiteral);
+ }
+
+ // For types that implement `AbslStringify` using `absl::Format()`.
+ friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
+ sink->Append(v);
+ }
+
+ private:
+ LogMessage& message_;
+};
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <typename T,
+ typename std::enable_if<strings_internal::HasAbslStringify<T>::value,
+ int>::type>
+LogMessage& LogMessage::operator<<(const T& v) {
+ StringifySink sink(*this);
+ // Replace with public API.
+ AbslStringify(sink, v);
+ return *this;
+}
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <typename T,
+ typename std::enable_if<!strings_internal::HasAbslStringify<T>::value,
+ int>::type>
+LogMessage& LogMessage::operator<<(const T& v) {
+ OstreamView view(*data_);
+ view.stream() << log_internal::NullGuard<T>().Guard(v);
+ return *this;
+}
+
+template <int SIZE>
+LogMessage& LogMessage::operator<<(const char (&buf)[SIZE]) {
+ CopyToEncodedBuffer(buf, StringType::kLiteral);
+ return *this;
+}
+
+// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE`
+template <int SIZE>
+LogMessage& LogMessage::operator<<(char (&buf)[SIZE]) {
+ CopyToEncodedBuffer(buf, StringType::kNotLiteral);
+ 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);
+
+// `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/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc
new file mode 100644
index 0000000000..f9d030aa22
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.cc
@@ -0,0 +1,296 @@
+//
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/log_sink_set.h"
+
+#ifndef ABSL_HAVE_THREAD_LOCAL
+#include <pthread.h>
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <algorithm>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/cleanup/cleanup.h"
+#include "absl/log/globals.h"
+#include "absl/log/internal/config.h"
+#include "absl/log/internal/globals.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+
+// Returns a mutable reference to a thread-local variable that should be true if
+// a globally-registered `LogSink`'s `Send()` is currently being invoked on this
+// thread.
+bool& ThreadIsLoggingStatus() {
+#ifdef ABSL_HAVE_THREAD_LOCAL
+ ABSL_CONST_INIT thread_local bool thread_is_logging = false;
+ return thread_is_logging;
+#else
+ ABSL_CONST_INIT static pthread_key_t thread_is_logging_key;
+ static const bool unused = [] {
+ if (pthread_key_create(&thread_is_logging_key, [](void* data) {
+ delete reinterpret_cast<bool*>(data);
+ })) {
+ perror("pthread_key_create failed!");
+ abort();
+ }
+ return true;
+ }();
+ (void)unused; // Fixes -wunused-variable warning
+ bool* thread_is_logging_ptr =
+ reinterpret_cast<bool*>(pthread_getspecific(thread_is_logging_key));
+
+ if (ABSL_PREDICT_FALSE(!thread_is_logging_ptr)) {
+ thread_is_logging_ptr = new bool{false};
+ if (pthread_setspecific(thread_is_logging_key, thread_is_logging_ptr)) {
+ perror("pthread_setspecific failed");
+ abort();
+ }
+ }
+ return *thread_is_logging_ptr;
+#endif
+}
+
+class StderrLogSink final : public LogSink {
+ public:
+ ~StderrLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ if (entry.log_severity() < absl::StderrThreshold() &&
+ absl::log_internal::IsInitialized()) {
+ return;
+ }
+
+ ABSL_CONST_INIT static absl::once_flag warn_if_not_initialized;
+ absl::call_once(warn_if_not_initialized, []() {
+ if (absl::log_internal::IsInitialized()) return;
+ const char w[] =
+ "WARNING: All log messages before absl::InitializeLog() is called"
+ " are written to STDERR\n";
+ absl::log_internal::WriteToStderr(w, absl::LogSeverity::kWarning);
+ });
+
+ if (!entry.stacktrace().empty()) {
+ absl::log_internal::WriteToStderr(entry.stacktrace(),
+ entry.log_severity());
+ } else {
+ // TODO(b/226937039): do this outside else condition once we avoid
+ // ReprintFatalMessage
+ absl::log_internal::WriteToStderr(
+ entry.text_message_with_prefix_and_newline(), entry.log_severity());
+ }
+ }
+};
+
+#if defined(__ANDROID__)
+class AndroidLogSink final : public LogSink {
+ public:
+ ~AndroidLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ const int level = AndroidLogLevel(entry);
+ // TODO(b/37587197): make the tag ("native") configurable.
+ __android_log_write(level, "native",
+ entry.text_message_with_prefix_and_newline_c_str());
+ if (entry.log_severity() == absl::LogSeverity::kFatal)
+ __android_log_write(ANDROID_LOG_FATAL, "native", "terminating.\n");
+ }
+
+ private:
+ static int AndroidLogLevel(const absl::LogEntry& entry) {
+ switch (entry.log_severity()) {
+ case absl::LogSeverity::kFatal:
+ return ANDROID_LOG_FATAL;
+ case absl::LogSeverity::kError:
+ return ANDROID_LOG_ERROR;
+ case absl::LogSeverity::kWarning:
+ return ANDROID_LOG_WARN;
+ default:
+ if (entry.verbosity() >= 2) return ANDROID_LOG_VERBOSE;
+ if (entry.verbosity() == 1) return ANDROID_LOG_DEBUG;
+ return ANDROID_LOG_INFO;
+ }
+ }
+};
+#endif // !defined(__ANDROID__)
+
+#if defined(_WIN32)
+class WindowsDebuggerLogSink final : public LogSink {
+ public:
+ ~WindowsDebuggerLogSink() override = default;
+
+ void Send(const absl::LogEntry& entry) override {
+ if (entry.log_severity() < absl::StderrThreshold() &&
+ absl::log_internal::IsInitialized()) {
+ return;
+ }
+ ::OutputDebugStringA(entry.text_message_with_prefix_and_newline_c_str());
+ }
+};
+#endif // !defined(_WIN32)
+
+class GlobalLogSinkSet final {
+ public:
+ GlobalLogSinkSet() {
+#if defined(__myriad2__) || defined(__Fuchsia__)
+ // myriad2 and Fuchsia do not log to stderr by default.
+#else
+ static StderrLogSink* stderr_log_sink = new StderrLogSink;
+ AddLogSink(stderr_log_sink);
+#endif
+#ifdef __ANDROID__
+ static AndroidLogSink* android_log_sink = new AndroidLogSink;
+ AddLogSink(android_log_sink);
+#endif
+#if defined(_WIN32)
+ static WindowsDebuggerLogSink* debugger_log_sink =
+ new WindowsDebuggerLogSink;
+ AddLogSink(debugger_log_sink);
+#endif // !defined(_WIN32)
+ }
+
+ void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only)
+ ABSL_LOCKS_EXCLUDED(guard_) {
+ SendToSinks(entry, extra_sinks);
+
+ if (!extra_sinks_only) {
+ if (ThreadIsLoggingToLogSink()) {
+ absl::log_internal::WriteToStderr(
+ entry.text_message_with_prefix_and_newline(), entry.log_severity());
+ } else {
+ absl::ReaderMutexLock global_sinks_lock(&guard_);
+ ThreadIsLoggingStatus() = true;
+ // Ensure the "thread is logging" status is reverted upon leaving the
+ // scope even in case of exceptions.
+ auto status_cleanup =
+ absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+ SendToSinks(entry, absl::MakeSpan(sinks_));
+ }
+ }
+ }
+
+ void AddLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+ {
+ absl::WriterMutexLock global_sinks_lock(&guard_);
+ auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+ if (pos == sinks_.end()) {
+ sinks_.push_back(sink);
+ return;
+ }
+ }
+ ABSL_INTERNAL_LOG(FATAL, "Duplicate log sinks are not supported");
+ }
+
+ void RemoveLogSink(absl::LogSink* sink) ABSL_LOCKS_EXCLUDED(guard_) {
+ {
+ absl::WriterMutexLock global_sinks_lock(&guard_);
+ auto pos = std::find(sinks_.begin(), sinks_.end(), sink);
+ if (pos != sinks_.end()) {
+ sinks_.erase(pos);
+ return;
+ }
+ }
+ ABSL_INTERNAL_LOG(FATAL, "Mismatched log sink being removed");
+ }
+
+ void FlushLogSinks() ABSL_LOCKS_EXCLUDED(guard_) {
+ if (ThreadIsLoggingToLogSink()) {
+ // The thread_local condition demonstrates that we're already holding the
+ // lock in order to iterate over `sinks_` for dispatch. The thread-safety
+ // annotations don't know this, so we use `ABSL_NO_THREAD_SAFETY_ANALYSIS`
+ guard_.AssertReaderHeld();
+ FlushLogSinksLocked();
+ } else {
+ absl::ReaderMutexLock global_sinks_lock(&guard_);
+ // In case if LogSink::Flush overload decides to log
+ ThreadIsLoggingStatus() = true;
+ // Ensure the "thread is logging" status is reverted upon leaving the
+ // scope even in case of exceptions.
+ auto status_cleanup =
+ absl::MakeCleanup([] { ThreadIsLoggingStatus() = false; });
+ FlushLogSinksLocked();
+ }
+ }
+
+ private:
+ void FlushLogSinksLocked() ABSL_SHARED_LOCKS_REQUIRED(guard_) {
+ for (absl::LogSink* sink : sinks_) {
+ sink->Flush();
+ }
+ }
+
+ // Helper routine for LogToSinks.
+ static void SendToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> sinks) {
+ for (absl::LogSink* sink : sinks) {
+ sink->Send(entry);
+ }
+ }
+
+ using LogSinksSet = std::vector<absl::LogSink*>;
+ absl::Mutex guard_;
+ LogSinksSet sinks_ ABSL_GUARDED_BY(guard_);
+};
+
+// Returns reference to the global LogSinks set.
+GlobalLogSinkSet& GlobalSinks() {
+ static GlobalLogSinkSet* global_sinks = new GlobalLogSinkSet;
+ return *global_sinks;
+}
+
+} // namespace
+
+bool ThreadIsLoggingToLogSink() { return ThreadIsLoggingStatus(); }
+
+void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only) {
+ log_internal::GlobalSinks().LogToSinks(entry, extra_sinks, extra_sinks_only);
+}
+
+void AddLogSink(absl::LogSink* sink) {
+ log_internal::GlobalSinks().AddLogSink(sink);
+}
+
+void RemoveLogSink(absl::LogSink* sink) {
+ log_internal::GlobalSinks().RemoveLogSink(sink);
+}
+
+void FlushLogSinks() { log_internal::GlobalSinks().FlushLogSinks(); }
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.h b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.h
new file mode 100644
index 0000000000..88ab073bbd
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/log_sink_set.h
@@ -0,0 +1,54 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/log_sink_set.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+#define ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
+
+#include "absl/base/config.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// Returns true if a globally-registered `LogSink`'s `Send()` is currently
+// being invoked on this thread.
+bool ThreadIsLoggingToLogSink();
+
+// This function may log to two sets of sinks:
+//
+// * If `extra_sinks_only` is true, it will dispatch only to `extra_sinks`.
+// `LogMessage::ToSinkAlso` and `LogMessage::ToSinkOnly` are used to attach
+// extra sinks to the entry.
+// * Otherwise it will also log to the global sinks set. This set is managed
+// by `absl::AddLogSink` and `absl::RemoveLogSink`.
+void LogToSinks(const absl::LogEntry& entry,
+ absl::Span<absl::LogSink*> extra_sinks, bool extra_sinks_only);
+
+// Implementation for operations with log sink set.
+void AddLogSink(absl::LogSink* sink);
+void RemoveLogSink(absl::LogSink* sink);
+void FlushLogSinks();
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_LOG_SINK_SET_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc b/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc
new file mode 100644
index 0000000000..4f2f9d406b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.cc
@@ -0,0 +1,35 @@
+// Copyright 2023 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/nullguard.h"
+
+#include <array>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+ABSL_DLL ABSL_CONST_INIT const std::array<char, 7> kCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+ABSL_DLL ABSL_CONST_INIT const std::array<signed char, 7> kSignedCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+ABSL_DLL ABSL_CONST_INIT const std::array<unsigned char, 7> kUnsignedCharNull{
+ {'(', 'n', 'u', 'l', 'l', ')', '\0'}};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.h b/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.h
new file mode 100644
index 0000000000..926f61bbdc
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/nullguard.h
@@ -0,0 +1,88 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullguard.h
+// -----------------------------------------------------------------------------
+//
+// NullGuard exists such that NullGuard<T>::Guard(v) returns v, unless passed a
+// nullptr_t, or a null char* or const char*, in which case it returns "(null)".
+// This allows streaming NullGuard<T>::Guard(v) to an output stream without
+// hitting undefined behavior for null values.
+
+#ifndef ABSL_LOG_INTERNAL_NULLGUARD_H_
+#define ABSL_LOG_INTERNAL_NULLGUARD_H_
+
+#include <array>
+#include <cstddef>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+ABSL_DLL ABSL_CONST_INIT extern const std::array<char, 7> kCharNull;
+ABSL_DLL ABSL_CONST_INIT extern const std::array<signed char, 7>
+ kSignedCharNull;
+ABSL_DLL ABSL_CONST_INIT extern const std::array<unsigned char, 7>
+ kUnsignedCharNull;
+
+template <typename T>
+struct NullGuard final {
+ static const T& Guard(const T& v) { return v; }
+};
+template <>
+struct NullGuard<char*> final {
+ static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
+};
+template <>
+struct NullGuard<const char*> final {
+ static const char* Guard(const char* v) { return v ? v : kCharNull.data(); }
+};
+template <>
+struct NullGuard<signed char*> final {
+ static const signed char* Guard(const signed char* v) {
+ return v ? v : kSignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<const signed char*> final {
+ static const signed char* Guard(const signed char* v) {
+ return v ? v : kSignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<unsigned char*> final {
+ static const unsigned char* Guard(const unsigned char* v) {
+ return v ? v : kUnsignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<const unsigned char*> final {
+ static const unsigned char* Guard(const unsigned char* v) {
+ return v ? v : kUnsignedCharNull.data();
+ }
+};
+template <>
+struct NullGuard<std::nullptr_t> final {
+ static const char* Guard(const std::nullptr_t&) { return kCharNull.data(); }
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_NULLGUARD_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/nullstream.h b/contrib/restricted/abseil-cpp/absl/log/internal/nullstream.h
new file mode 100644
index 0000000000..8ed63d5295
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/nullstream.h
@@ -0,0 +1,134 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/nullstream.h
+// -----------------------------------------------------------------------------
+//
+// Classes `NullStream`, `NullStreamMaybeFatal ` and `NullStreamFatal`
+// implement a subset of the `LogMessage` API and are used instead when logging
+// of messages has been disabled.
+
+#ifndef ABSL_LOG_INTERNAL_NULLSTREAM_H_
+#define ABSL_LOG_INTERNAL_NULLSTREAM_H_
+
+#ifdef _WIN32
+#include <cstdlib>
+#else
+#include <unistd.h>
+#endif
+#include <ios>
+#include <ostream>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// A `NullStream` implements the API of `LogMessage` (a few methods and
+// `operator<<`) but does nothing. All methods are defined inline so the
+// compiler can eliminate the whole instance and discard anything that's
+// streamed in.
+class NullStream {
+ public:
+ NullStream& AtLocation(absl::string_view, int) { return *this; }
+ template <typename SourceLocationType>
+ NullStream& AtLocation(SourceLocationType) {
+ return *this;
+ }
+ NullStream& NoPrefix() { return *this; }
+ NullStream& WithVerbosity(int) { return *this; }
+ template <typename TimeType>
+ NullStream& WithTimestamp(TimeType) {
+ return *this;
+ }
+ template <typename Tid>
+ NullStream& WithThreadID(Tid) {
+ return *this;
+ }
+ template <typename LogEntryType>
+ NullStream& WithMetadataFrom(const LogEntryType&) {
+ return *this;
+ }
+ NullStream& WithPerror() { return *this; }
+ template <typename LogSinkType>
+ NullStream& ToSinkAlso(LogSinkType*) {
+ return *this;
+ }
+ template <typename LogSinkType>
+ NullStream& ToSinkOnly(LogSinkType*) {
+ return *this;
+ }
+ template <typename LogSinkType>
+ NullStream& OutputToSink(LogSinkType*, bool) {
+ return *this;
+ }
+ NullStream& InternalStream() { return *this; }
+};
+template <typename T>
+inline NullStream& operator<<(NullStream& str, const T&) {
+ return str;
+}
+inline NullStream& operator<<(NullStream& str,
+ std::ostream& (*)(std::ostream& os)) {
+ return str;
+}
+inline NullStream& operator<<(NullStream& str,
+ std::ios_base& (*)(std::ios_base& os)) {
+ return str;
+}
+
+// `NullStreamMaybeFatal` implements the process termination semantics of
+// `LogMessage`, which is used for `DFATAL` severity and expression-defined
+// severity e.g. `LOG(LEVEL(HowBadIsIt()))`. Like `LogMessage`, it terminates
+// the process when destroyed if the passed-in severity equals `FATAL`.
+class NullStreamMaybeFatal final : public NullStream {
+ public:
+ explicit NullStreamMaybeFatal(absl::LogSeverity severity)
+ : fatal_(severity == absl::LogSeverity::kFatal) {}
+ ~NullStreamMaybeFatal() {
+ if (fatal_) _exit(1);
+ }
+
+ private:
+ bool fatal_;
+};
+
+// `NullStreamFatal` implements the process termination semantics of
+// `LogMessageFatal`, which means it always terminates the process. `DFATAL`
+// and expression-defined severity use `NullStreamMaybeFatal` above.
+class NullStreamFatal final : public NullStream {
+ public:
+ NullStreamFatal() {}
+ // 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/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc b/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc
new file mode 100644
index 0000000000..eb699ae8e7
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/proto.cc
@@ -0,0 +1,220 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/log/internal/proto.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+namespace {
+void EncodeRawVarint(uint64_t value, size_t size, absl::Span<char> *buf) {
+ for (size_t s = 0; s < size; s++) {
+ (*buf)[s] = static_cast<char>((value & 0x7f) | (s + 1 == size ? 0 : 0x80));
+ value >>= 7;
+ }
+ buf->remove_prefix(size);
+}
+constexpr uint64_t MakeTagType(uint64_t tag, WireType type) {
+ return tag << 3 | static_cast<uint64_t>(type);
+}
+} // namespace
+
+bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kVarint);
+ const size_t tag_type_size = VarintSize(tag_type);
+ const size_t value_size = VarintSize(value);
+ if (tag_type_size + value_size > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(value, value_size, buf);
+ return true;
+}
+
+bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::k64Bit);
+ const size_t tag_type_size = VarintSize(tag_type);
+ if (tag_type_size + sizeof(value) > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ for (size_t s = 0; s < sizeof(value); s++) {
+ (*buf)[s] = static_cast<char>(value & 0xff);
+ value >>= 8;
+ }
+ buf->remove_prefix(sizeof(value));
+ return true;
+}
+
+bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::k32Bit);
+ const size_t tag_type_size = VarintSize(tag_type);
+ if (tag_type_size + sizeof(value) > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ for (size_t s = 0; s < sizeof(value); s++) {
+ (*buf)[s] = static_cast<char>(value & 0xff);
+ value >>= 8;
+ }
+ buf->remove_prefix(sizeof(value));
+ return true;
+}
+
+bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ uint64_t length = value.size();
+ const size_t length_size = VarintSize(length);
+ if (tag_type_size + length_size + value.size() > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(length, length_size, buf);
+ memcpy(buf->data(), value.data(), value.size());
+ buf->remove_prefix(value.size());
+ return true;
+}
+
+bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ uint64_t length = value.size();
+ const size_t length_size =
+ VarintSize(std::min<uint64_t>(length, buf->size()));
+ if (tag_type_size + length_size <= buf->size() &&
+ tag_type_size + length_size + value.size() > buf->size()) {
+ value.remove_suffix(tag_type_size + length_size + value.size() -
+ buf->size());
+ length = value.size();
+ }
+ if (tag_type_size + length_size + value.size() > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return false;
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ EncodeRawVarint(length, length_size, buf);
+ memcpy(buf->data(), value.data(), value.size());
+ buf->remove_prefix(value.size());
+ return true;
+}
+
+ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(
+ uint64_t tag, uint64_t max_size, absl::Span<char> *buf) {
+ const uint64_t tag_type = MakeTagType(tag, WireType::kLengthDelimited);
+ const size_t tag_type_size = VarintSize(tag_type);
+ max_size = std::min<uint64_t>(max_size, buf->size());
+ const size_t length_size = VarintSize(max_size);
+ if (tag_type_size + length_size > buf->size()) {
+ buf->remove_suffix(buf->size());
+ return absl::Span<char>();
+ }
+ EncodeRawVarint(tag_type, tag_type_size, buf);
+ const absl::Span<char> ret = buf->subspan(0, length_size);
+ EncodeRawVarint(0, length_size, buf);
+ return ret;
+}
+
+void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf) {
+ if (!msg.data()) return;
+ assert(buf->data() >= msg.data());
+ if (buf->data() < msg.data()) return;
+ EncodeRawVarint(
+ static_cast<uint64_t>(buf->data() - (msg.data() + msg.size())),
+ msg.size(), &msg);
+}
+
+namespace {
+uint64_t DecodeVarint(absl::Span<const char> *buf) {
+ uint64_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]) & 0x7f)
+ << 7 * s;
+ if (!((*buf)[s++] & 0x80)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+
+uint64_t Decode64Bit(absl::Span<const char> *buf) {
+ uint64_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint64_t>(static_cast<unsigned char>((*buf)[s]))
+ << 8 * s;
+ if (++s == sizeof(value)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+
+uint32_t Decode32Bit(absl::Span<const char> *buf) {
+ uint32_t value = 0;
+ size_t s = 0;
+ while (s < buf->size()) {
+ value |= static_cast<uint32_t>(static_cast<unsigned char>((*buf)[s]))
+ << 8 * s;
+ if (++s == sizeof(value)) break;
+ }
+ buf->remove_prefix(s);
+ return value;
+}
+} // namespace
+
+bool ProtoField::DecodeFrom(absl::Span<const char> *data) {
+ if (data->empty()) return false;
+ const uint64_t tag_type = DecodeVarint(data);
+ tag_ = tag_type >> 3;
+ type_ = static_cast<WireType>(tag_type & 0x07);
+ switch (type_) {
+ case WireType::kVarint:
+ value_ = DecodeVarint(data);
+ break;
+ case WireType::k64Bit:
+ value_ = Decode64Bit(data);
+ break;
+ case WireType::kLengthDelimited: {
+ value_ = DecodeVarint(data);
+ data_ = data->subspan(
+ 0, static_cast<size_t>(std::min<uint64_t>(value_, data->size())));
+ data->remove_prefix(data_.size());
+ break;
+ }
+ case WireType::k32Bit:
+ value_ = Decode32Bit(data);
+ break;
+ }
+ return true;
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/proto.h b/contrib/restricted/abseil-cpp/absl/log/internal/proto.h
new file mode 100644
index 0000000000..c8d14acc47
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/proto.h
@@ -0,0 +1,288 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// -----------------------------------------------------------------------------
+// File: internal/proto.h
+// -----------------------------------------------------------------------------
+//
+// Declares functions for serializing and deserializing data to and from memory
+// buffers in protocol buffer wire format. This library takes no steps to
+// ensure that the encoded data matches with any message specification.
+
+#ifndef ABSL_LOG_INTERNAL_PROTO_H_
+#define ABSL_LOG_INTERNAL_PROTO_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// absl::Span<char> represents a view into the available space in a mutable
+// buffer during encoding. Encoding functions shrink the span as they go so
+// that the same view can be passed to a series of Encode functions. If the
+// data do not fit, nothing is encoded, the view is set to size zero (so that
+// all subsequent encode calls fail), and false is returned. Otherwise true is
+// returned.
+
+// In particular, attempting to encode a series of data into an insufficient
+// buffer has consistent and efficient behavior without any caller-side error
+// checking. Individual values will be encoded in their entirety or not at all
+// (unless one of the `Truncate` functions is used). Once a value is omitted
+// because it does not fit, no subsequent values will be encoded to preserve
+// ordering; the decoded sequence will be a prefix of the original sequence.
+
+// There are two ways to encode a message-typed field:
+//
+// * Construct its contents in a separate buffer and use `EncodeBytes` to copy
+// it into the primary buffer with type, tag, and length.
+// * Use `EncodeMessageStart` to write type and tag fields and reserve space for
+// the length field, then encode the contents directly into the buffer, then
+// use `EncodeMessageLength` to write the actual length into the reserved
+// bytes. This works fine if the actual length takes fewer bytes to encode
+// than were reserved, although you don't get your extra bytes back.
+// This approach will always produce a valid encoding, but your protocol may
+// require that the whole message field by omitted if the buffer is too small
+// to contain all desired subfields. In this case, operate on a copy of the
+// buffer view and assign back only if everything fit, i.e. if the last
+// `Encode` call returned true.
+
+// Encodes the specified integer as a varint field and returns true if it fits.
+// Used for int32_t, int64_t, uint32_t, uint64_t, bool, and enum field types.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+bool EncodeVarint(uint64_t tag, uint64_t value, absl::Span<char> *buf);
+inline bool EncodeVarint(uint64_t tag, int64_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool EncodeVarint(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool EncodeVarint(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return EncodeVarint(tag, static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a varint field using ZigZag encoding and
+// returns true if it fits.
+// Used for sint32 and sint64 field types.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+inline bool EncodeVarintZigZag(uint64_t tag, int64_t value,
+ absl::Span<char> *buf) {
+ if (value < 0)
+ return EncodeVarint(tag, 2 * static_cast<uint64_t>(-(value + 1)) + 1, buf);
+ return EncodeVarint(tag, 2 * static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a 64-bit field and returns true if it fits.
+// Used for fixed64 and sfixed64 field types.
+// Consumes up to kMaxVarintSize + 8 bytes (18).
+bool Encode64Bit(uint64_t tag, uint64_t value, absl::Span<char> *buf);
+inline bool Encode64Bit(uint64_t tag, int64_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool Encode64Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+inline bool Encode64Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, static_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified double as a 64-bit field and returns true if it fits.
+// Used for double field type.
+// Consumes up to kMaxVarintSize + 8 bytes (18).
+inline bool EncodeDouble(uint64_t tag, double value, absl::Span<char> *buf) {
+ return Encode64Bit(tag, absl::bit_cast<uint64_t>(value), buf);
+}
+
+// Encodes the specified integer as a 32-bit field and returns true if it fits.
+// Used for fixed32 and sfixed32 field types.
+// Consumes up to kMaxVarintSize + 4 bytes (14).
+bool Encode32Bit(uint64_t tag, uint32_t value, absl::Span<char> *buf);
+inline bool Encode32Bit(uint64_t tag, int32_t value, absl::Span<char> *buf) {
+ return Encode32Bit(tag, static_cast<uint32_t>(value), buf);
+}
+
+// Encodes the specified float as a 32-bit field and returns true if it fits.
+// Used for float field type.
+// Consumes up to kMaxVarintSize + 4 bytes (14).
+inline bool EncodeFloat(uint64_t tag, float value, absl::Span<char> *buf) {
+ return Encode32Bit(tag, absl::bit_cast<uint32_t>(value), buf);
+}
+
+// Encodes the specified bytes as a length-delimited field and returns true if
+// they fit.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+bool EncodeBytes(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf);
+
+// Encodes as many of the specified bytes as will fit as a length-delimited
+// field and returns true as long as the field header (`tag_type` and `length`)
+// fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+bool EncodeBytesTruncate(uint64_t tag, absl::Span<const char> value,
+ absl::Span<char> *buf);
+
+// Encodes the specified string as a length-delimited field and returns true if
+// it fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+inline bool EncodeString(uint64_t tag, absl::string_view value,
+ absl::Span<char> *buf) {
+ return EncodeBytes(tag, value, buf);
+}
+
+// Encodes as much of the specified string as will fit as a length-delimited
+// field and returns true as long as the field header (`tag_type` and `length`)
+// fits.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 + value.size() bytes (20 + value.size()).
+inline bool EncodeStringTruncate(uint64_t tag, absl::string_view value,
+ absl::Span<char> *buf) {
+ return EncodeBytesTruncate(tag, value, buf);
+}
+
+// Encodes the header for a length-delimited field containing up to `max_size`
+// bytes or the number remaining in the buffer, whichever is less. If the
+// header fits, a non-nullptr `Span` is returned; this must be passed to
+// `EncodeMessageLength` after all contents are encoded to finalize the length
+// field. If the header does not fit, a nullptr `Span` is returned which is
+// safe to pass to `EncodeMessageLength` but need not be.
+// Used for string, bytes, message, and packed-repeated field type.
+// Consumes up to kMaxVarintSize * 2 bytes (20).
+ABSL_MUST_USE_RESULT absl::Span<char> EncodeMessageStart(uint64_t tag,
+ uint64_t max_size,
+ absl::Span<char> *buf);
+
+// Finalizes the length field in `msg` so that it encompasses all data encoded
+// since the call to `EncodeMessageStart` which returned `msg`. Does nothing if
+// `msg` is a `nullptr` `Span`.
+void EncodeMessageLength(absl::Span<char> msg, const absl::Span<char> *buf);
+
+enum class WireType : uint64_t {
+ kVarint = 0,
+ k64Bit = 1,
+ kLengthDelimited = 2,
+ k32Bit = 5,
+};
+
+constexpr size_t VarintSize(uint64_t value) {
+ return value < 128 ? 1 : 1 + VarintSize(value >> 7);
+}
+constexpr size_t MinVarintSize() {
+ return VarintSize((std::numeric_limits<uint64_t>::min)());
+}
+constexpr size_t MaxVarintSize() {
+ return VarintSize((std::numeric_limits<uint64_t>::max)());
+}
+
+constexpr uint64_t MaxVarintForSize(size_t size) {
+ return size >= 10 ? (std::numeric_limits<uint64_t>::max)()
+ : (static_cast<uint64_t>(1) << size * 7) - 1;
+}
+
+// `BufferSizeFor` returns a number of bytes guaranteed to be sufficient to
+// store encoded fields of the specified WireTypes regardless of tag numbers and
+// data values. This only makes sense for `WireType::kLengthDelimited` if you
+// add in the length of the contents yourself, e.g. for string and bytes fields
+// by adding the lengths of any encoded strings to the return value or for
+// submessage fields by enumerating the fields you may encode into their
+// contents.
+constexpr size_t BufferSizeFor() { return 0; }
+template <typename... T>
+constexpr size_t BufferSizeFor(WireType type, T... tail) {
+ // tag_type + data + ...
+ return MaxVarintSize() +
+ (type == WireType::kVarint ? MaxVarintSize() : //
+ type == WireType::k64Bit ? 8 : //
+ type == WireType::k32Bit ? 4 : MaxVarintSize()) + //
+ BufferSizeFor(tail...);
+}
+
+// absl::Span<const char> represents a view into the un-processed space in a
+// buffer during decoding. Decoding functions shrink the span as they go so
+// that the same view can be decoded iteratively until all data are processed.
+// In general, if the buffer is exhausted but additional bytes are expected by
+// the decoder, it will return values as if the additional bytes were zeros.
+// Length-delimited fields are an exception - if the encoded length field
+// indicates more data bytes than are available in the buffer, the `bytes_value`
+// and `string_value` accessors will return truncated views.
+
+class ProtoField final {
+ public:
+ // Consumes bytes from `data` and returns true if there were any bytes to
+ // decode.
+ bool DecodeFrom(absl::Span<const char> *data);
+ uint64_t tag() const { return tag_; }
+ WireType type() const { return type_; }
+
+ // These value accessors will return nonsense if the data were not encoded in
+ // the corresponding wiretype from the corresponding C++ (or other language)
+ // type.
+
+ double double_value() const { return absl::bit_cast<double>(value_); }
+ float float_value() const {
+ return absl::bit_cast<float>(static_cast<uint32_t>(value_));
+ }
+ int32_t int32_value() const { return static_cast<int32_t>(value_); }
+ int64_t int64_value() const { return static_cast<int64_t>(value_); }
+ int32_t sint32_value() const {
+ if (value_ % 2) return static_cast<int32_t>(0 - ((value_ - 1) / 2) - 1);
+ return static_cast<int32_t>(value_ / 2);
+ }
+ int64_t sint64_value() const {
+ if (value_ % 2) return 0 - ((value_ - 1) / 2) - 1;
+ return value_ / 2;
+ }
+ uint32_t uint32_value() const { return static_cast<uint32_t>(value_); }
+ uint64_t uint64_value() const { return value_; }
+ bool bool_value() const { return value_ != 0; }
+ // To decode an enum, call int32_value() and cast to the appropriate type.
+ // Note that the official C++ proto compiler treats enum fields with values
+ // that do not correspond to a defined enumerator as unknown fields.
+
+ // To decode fields within a submessage field, call
+ // `DecodeNextField(field.BytesValue())`.
+ absl::Span<const char> bytes_value() const { return data_; }
+ absl::string_view string_value() const {
+ const auto data = bytes_value();
+ return absl::string_view(data.data(), data.size());
+ }
+ // Returns the encoded length of a length-delimited field. This equals
+ // `bytes_value().size()` except when the latter has been truncated due to
+ // buffer underrun.
+ uint64_t encoded_length() const { return value_; }
+
+ private:
+ uint64_t tag_;
+ WireType type_;
+ // For `kTypeVarint`, `kType64Bit`, and `kType32Bit`, holds the decoded value.
+ // For `kTypeLengthDelimited`, holds the decoded length.
+ uint64_t value_;
+ absl::Span<const char> data_;
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_PROTO_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/strip.h b/contrib/restricted/abseil-cpp/absl/log/internal/strip.h
new file mode 100644
index 0000000000..848c38672d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/strip.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/strip.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_INTERNAL_STRIP_H_
+#define ABSL_LOG_INTERNAL_STRIP_H_
+
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/log/internal/nullstream.h"
+
+// `ABSL_LOGGING_INTERNAL_LOG_*` evaluates to a temporary `LogMessage` object or
+// to a related object with a compatible API but different behavior. This set
+// of defines comes in three flavors: vanilla, plus two variants that strip some
+// logging in subtly different ways for subtly different reasons (see below).
+#if defined(STRIP_LOG) && STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR ::absl::log_internal::NullStream()
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL ::absl::log_internal::NullStreamFatal()
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+ ::absl::log_internal::NullStreamMaybeFatal(::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+ ::absl::log_internal::NullStreamMaybeFatal(log_internal_severity)
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) ABSL_LOGGING_INTERNAL_LOG_FATAL
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+ ABSL_LOGGING_INTERNAL_LOG_QFATAL
+#else // !defined(STRIP_LOG) || !STRIP_LOG
+#define ABSL_LOGGING_INTERNAL_LOG_INFO \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+ ::absl::LogSeverity::kInfo)
+#define ABSL_LOGGING_INTERNAL_LOG_WARNING \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+ ::absl::LogSeverity::kWarning)
+#define ABSL_LOGGING_INTERNAL_LOG_ERROR \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, \
+ ::absl::LogSeverity::kError)
+#define ABSL_LOGGING_INTERNAL_LOG_FATAL \
+ ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_QFATAL \
+ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__)
+#define ABSL_LOGGING_INTERNAL_LOG_DFATAL \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, ::absl::kLogDebugFatal)
+#define ABSL_LOGGING_INTERNAL_LOG_LEVEL(severity) \
+ ::absl::log_internal::LogMessage(__FILE__, __LINE__, log_internal_severity)
+// These special cases dispatch to special-case constructors that allow us to
+// avoid an extra function call and shrink non-LTO binaries by a percent or so.
+#define ABSL_LOG_INTERNAL_CHECK(failure_message) \
+ ::absl::log_internal::LogMessageFatal(__FILE__, __LINE__, failure_message)
+#define ABSL_LOG_INTERNAL_QCHECK(failure_message) \
+ ::absl::log_internal::LogMessageQuietlyFatal(__FILE__, __LINE__, \
+ failure_message)
+#endif // !defined(STRIP_LOG) || !STRIP_LOG
+
+#endif // ABSL_LOG_INTERNAL_STRIP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/voidify.h b/contrib/restricted/abseil-cpp/absl/log/internal/voidify.h
new file mode 100644
index 0000000000..8f62da20a0
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/voidify.h
@@ -0,0 +1,44 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/voidify.h
+// -----------------------------------------------------------------------------
+//
+// This class is used to explicitly ignore values in the conditional logging
+// macros. This avoids compiler warnings like "value computed is not used" and
+// "statement has no effect".
+
+#ifndef ABSL_LOG_INTERNAL_VOIDIFY_H_
+#define ABSL_LOG_INTERNAL_VOIDIFY_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class Voidify final {
+ public:
+ // This has to be an operator with a precedence lower than << but higher than
+ // ?:
+ template <typename T>
+ void operator&&(const T&) const&& {}
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_VOIDIFY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/log.h b/contrib/restricted/abseil-cpp/absl/log/log.h
new file mode 100644
index 0000000000..e060a0b69b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log.h
@@ -0,0 +1,308 @@
+// 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.h
+// -----------------------------------------------------------------------------
+//
+// This header declares a family of LOG macros.
+//
+// Basic invocation looks like this:
+//
+// LOG(INFO) << "Found " << num_cookies << " cookies";
+//
+// Most `LOG` macros take a severity level argument. The severity levels are
+// `INFO`, `WARNING`, `ERROR`, and `FATAL`. They are defined
+// in absl/base/log_severity.h.
+// * The `FATAL` severity level terminates the program with a stack trace after
+// logging its message. Error handlers registered with `RunOnFailure`
+// (process_state.h) are run, but exit handlers registered with `atexit(3)`
+// are not.
+// * The `QFATAL` pseudo-severity level is equivalent to `FATAL` but triggers
+// quieter termination messages, e.g. without a full stack trace, and skips
+// running registered error handlers.
+// Some preprocessor shenanigans are used to ensure that e.g. `LOG(INFO)` has
+// the same meaning even if a local symbol or preprocessor macro named `INFO` is
+// defined. To specify a severity level using an expression instead of a
+// literal, use `LEVEL(expr)`.
+// Example:
+//
+// LOG(LEVEL(stale ? absl::LogSeverity::kWarning : absl::LogSeverity::kInfo))
+// << "Cookies are " << days << " days old";
+
+// `LOG` macros evaluate to an unterminated statement. The value at the end of
+// the statement supports some chainable methods:
+//
+// * .AtLocation(absl::string_view file, int line)
+// .AtLocation(absl::SourceLocation loc)
+// Overrides the location inferred from the callsite. The string pointed to
+// by `file` must be valid until the end of the statement.
+// * .NoPrefix()
+// Omits the prefix from this line. The prefix includes metadata about the
+// logged data such as source code location and timestamp.
+// * .WithTimestamp(absl::Time timestamp)
+// Uses the specified timestamp instead of one collected at the time of
+// execution.
+// * .WithThreadID(absl::LogEntry::tid_t tid)
+// Uses the specified thread ID instead of one collected at the time of
+// execution.
+// * .WithMetadataFrom(const absl::LogEntry &entry)
+// Copies all metadata (but no data) from the specified `absl::LogEntry`.
+// This can be used to change the severity of a message, but it has some
+// limitations:
+// * `ABSL_MIN_LOG_LEVEL` is evaluated against the severity passed into
+// `LOG` (or the implicit `FATAL` level of `CHECK`).
+// * `LOG(FATAL)` and `CHECK` terminate the process unconditionally, even if
+// the severity is changed later.
+// `.WithMetadataFrom(entry)` should almost always be used in combination
+// with `LOG(LEVEL(entry.log_severity()))`.
+// * .WithPerror()
+// 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`.
+// * .ToSinkAlso(absl::LogSink* sink)
+// Sends this message to `*sink` in addition to whatever other sinks it
+// would otherwise have been sent to. `sink` must not be null.
+// * .ToSinkOnly(absl::LogSink* sink)
+// Sends this message to `*sink` and no others. `sink` must not be null.
+//
+// No interfaces in this header are async-signal-safe; their use in signal
+// handlers is unsupported and may deadlock your program or eat your lunch.
+//
+// Many logging statements are inherently conditional. For example,
+// `LOG_IF(INFO, !foo)` does nothing if `foo` is true. Even seemingly
+// unconditional statements like `LOG(INFO)` might be disabled at
+// compile-time to minimize binary size or for security reasons.
+//
+// * Except for the condition in a `CHECK` or `QCHECK` statement, programs must
+// not rely on evaluation of expressions anywhere in logging statements for
+// correctness. For example, this is ok:
+//
+// CHECK((fp = fopen("config.ini", "r")) != nullptr);
+//
+// But this is probably not ok:
+//
+// LOG(INFO) << "Server status: " << StartServerAndReturnStatusString();
+//
+// The example below is bad too; the `i++` in the `LOG_IF` condition might
+// not be evaluated, resulting in an infinite loop:
+//
+// for (int i = 0; i < 1000000;)
+// LOG_IF(INFO, i++ % 1000 == 0) << "Still working...";
+//
+// * Except where otherwise noted, conditions which cause a statement not to log
+// also cause expressions not to be evaluated. Programs may rely on this for
+// performance reasons, e.g. by streaming the result of an expensive function
+// call into a `DLOG` or `LOG_EVERY_N` statement.
+// * Care has been taken to ensure that expressions are parsed by the compiler
+// even if they are never evaluated. This means that syntax errors will be
+// caught and variables will be considered used for the purposes of
+// unused-variable diagnostics. For example, this statement won't compile
+// even if `INFO`-level logging has been compiled out:
+//
+// int number_of_cakes = 40;
+// LOG(INFO) << "Number of cakes: " << number_of_cake; // Note the typo!
+//
+// Similarly, this won't produce unused-variable compiler diagnostics even
+// if `INFO`-level logging is compiled out:
+//
+// {
+// char fox_line1[] = "Hatee-hatee-hatee-ho!";
+// LOG_IF(ERROR, false) << "The fox says " << fox_line1;
+// char fox_line2[] = "A-oo-oo-oo-ooo!";
+// LOG(INFO) << "The fox also says " << fox_line2;
+// }
+//
+// This error-checking is not perfect; for example, symbols that have been
+// declared but not defined may not produce link errors if used in logging
+// statements that compile away.
+//
+// Expressions streamed into these macros are formatted using `operator<<` just
+// as they would be if streamed into a `std::ostream`, however it should be
+// noted that their actual type is unspecified.
+//
+// To implement a custom formatting operator for a type you own, there are two
+// options: `AbslStringify()` or `std::ostream& operator<<(std::ostream&, ...)`.
+// It is recommended that users make their types loggable through
+// `AbslStringify()` as it is a universal stringification extension that also
+// enables `absl::StrFormat` and `absl::StrCat` support. If both
+// `AbslStringify()` and `std::ostream& operator<<(std::ostream&, ...)` are
+// defined, `AbslStringify()` will be used.
+//
+// To use the `AbslStringify()` API, define a friend function template in your
+// type's namespace with the following signature:
+//
+// template <typename Sink>
+// void AbslStringify(Sink& sink, const UserDefinedType& value);
+//
+// `Sink` has the same interface as `absl::FormatSink`, but without
+// `PutPaddedString()`.
+//
+// Example:
+//
+// struct Point {
+// template <typename Sink>
+// friend void AbslStringify(Sink& sink, const Point& p) {
+// absl::Format(&sink, "(%v, %v)", p.x, p.y);
+// }
+//
+// int x;
+// int y;
+// };
+//
+// To use `std::ostream& operator<<(std::ostream&, ...)`, define
+// `std::ostream& operator<<(std::ostream&, ...)` in your type's namespace (for
+// ADL) just as you would to stream it to `std::cout`.
+//
+// Currently `AbslStringify()` ignores output manipulators but this is not
+// guaranteed behavior and may be subject to change in the future. If you would
+// like guaranteed behavior regarding output manipulators, please use
+// `std::ostream& operator<<(std::ostream&, ...)` to make custom types loggable
+// instead.
+//
+// Those macros that support streaming honor output manipulators and `fmtflag`
+// changes that output data (e.g. `std::ends`) or control formatting of data
+// (e.g. `std::hex` and `std::fixed`), however flushing such a stream is
+// ignored. The message produced by a log statement is sent to registered
+// `absl::LogSink` instances at the end of the statement; those sinks are
+// responsible for their own flushing (e.g. to disk) semantics.
+//
+// Flag settings are not carried over from one `LOG` statement to the next; this
+// is a bit different than e.g. `std::cout`:
+//
+// LOG(INFO) << std::hex << 0xdeadbeef; // logs "0xdeadbeef"
+// LOG(INFO) << 0xdeadbeef; // logs "3735928559"
+
+#ifndef ABSL_LOG_LOG_H_
+#define ABSL_LOG_LOG_H_
+
+#include "absl/log/internal/log_impl.h"
+
+// LOG()
+//
+// `LOG` takes a single argument which is a severity level. Data streamed in
+// comprise the logged message.
+// Example:
+//
+// LOG(INFO) << "Found " << num_cookies << " cookies";
+#define LOG(severity) ABSL_LOG_IMPL(_##severity)
+
+// PLOG()
+//
+// `PLOG` behaves like `LOG` except that a description of the current state of
+// `errno` is appended to the streamed message.
+#define PLOG(severity) ABSL_PLOG_IMPL(_##severity)
+
+// DLOG()
+//
+// `DLOG` behaves like `LOG` in debug mode (i.e. `#ifndef NDEBUG`). Otherwise
+// it compiles away and does nothing. Note that `DLOG(FATAL)` does not
+// terminate the program if `NDEBUG` is defined.
+#define DLOG(severity) ABSL_DLOG_IMPL(_##severity)
+
+// `LOG_IF` and friends add a second argument which specifies a condition. If
+// the condition is false, nothing is logged.
+// Example:
+//
+// LOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
+#define LOG_IF(severity, condition) ABSL_LOG_IF_IMPL(_##severity, condition)
+#define PLOG_IF(severity, condition) ABSL_PLOG_IF_IMPL(_##severity, condition)
+#define DLOG_IF(severity, condition) ABSL_DLOG_IF_IMPL(_##severity, condition)
+
+// LOG_EVERY_N
+//
+// An instance of `LOG_EVERY_N` increments a hidden zero-initialized counter
+// every time execution passes through it and logs the specified message when
+// the counter's value is a multiple of `n`, doing nothing otherwise. Each
+// instance has its own counter. The counter's value can be logged by streaming
+// the symbol `COUNTER`. `LOG_EVERY_N` is thread-safe.
+// Example:
+//
+// LOG_EVERY_N(WARNING, 1000) << "Got a packet with a bad CRC (" << COUNTER
+// << " total)";
+#define LOG_EVERY_N(severity, n) ABSL_LOG_EVERY_N_IMPL(_##severity, n)
+
+// LOG_FIRST_N
+//
+// `LOG_FIRST_N` behaves like `LOG_EVERY_N` except that the specified message is
+// logged when the counter's value is less than `n`. `LOG_FIRST_N` is
+// thread-safe.
+#define LOG_FIRST_N(severity, n) ABSL_LOG_FIRST_N_IMPL(_##severity, n)
+
+// LOG_EVERY_POW_2
+//
+// `LOG_EVERY_POW_2` behaves like `LOG_EVERY_N` except that the specified
+// message is logged when the counter's value is a power of 2.
+// `LOG_EVERY_POW_2` is thread-safe.
+#define LOG_EVERY_POW_2(severity) ABSL_LOG_EVERY_POW_2_IMPL(_##severity)
+
+// LOG_EVERY_N_SEC
+//
+// An instance of `LOG_EVERY_N_SEC` uses a hidden state variable to log the
+// specified message at most once every `n_seconds`. A hidden counter of
+// executions (whether a message is logged or not) is also maintained and can be
+// logged by streaming the symbol `COUNTER`. `LOG_EVERY_N_SEC` is thread-safe.
+// Example:
+//
+// LOG_EVERY_N_SEC(INFO, 2.5) << "Got " << COUNTER << " cookies so far";
+#define LOG_EVERY_N_SEC(severity, n_seconds) \
+ ABSL_LOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
+
+#define PLOG_EVERY_N(severity, n) ABSL_PLOG_EVERY_N_IMPL(_##severity, n)
+#define PLOG_FIRST_N(severity, n) ABSL_PLOG_FIRST_N_IMPL(_##severity, n)
+#define PLOG_EVERY_POW_2(severity) ABSL_PLOG_EVERY_POW_2_IMPL(_##severity)
+#define PLOG_EVERY_N_SEC(severity, n_seconds) \
+ ABSL_PLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
+
+#define DLOG_EVERY_N(severity, n) ABSL_DLOG_EVERY_N_IMPL(_##severity, n)
+#define DLOG_FIRST_N(severity, n) ABSL_DLOG_FIRST_N_IMPL(_##severity, n)
+#define DLOG_EVERY_POW_2(severity) ABSL_DLOG_EVERY_POW_2_IMPL(_##severity)
+#define DLOG_EVERY_N_SEC(severity, n_seconds) \
+ ABSL_DLOG_EVERY_N_SEC_IMPL(_##severity, n_seconds)
+
+// `LOG_IF_EVERY_N` and friends behave as the corresponding `LOG_EVERY_N`
+// but neither increment a counter nor log a message if condition is false (as
+// `LOG_IF`).
+// Example:
+//
+// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
+// << "th big cookie";
+#define LOG_IF_EVERY_N(severity, condition, n) \
+ ABSL_LOG_IF_EVERY_N_IMPL(_##severity, condition, n)
+#define LOG_IF_FIRST_N(severity, condition, n) \
+ ABSL_LOG_IF_FIRST_N_IMPL(_##severity, condition, n)
+#define LOG_IF_EVERY_POW_2(severity, condition) \
+ ABSL_LOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
+#define LOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
+ ABSL_LOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
+
+#define PLOG_IF_EVERY_N(severity, condition, n) \
+ ABSL_PLOG_IF_EVERY_N_IMPL(_##severity, condition, n)
+#define PLOG_IF_FIRST_N(severity, condition, n) \
+ ABSL_PLOG_IF_FIRST_N_IMPL(_##severity, condition, n)
+#define PLOG_IF_EVERY_POW_2(severity, condition) \
+ ABSL_PLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
+#define PLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
+ ABSL_PLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
+
+#define DLOG_IF_EVERY_N(severity, condition, n) \
+ ABSL_DLOG_IF_EVERY_N_IMPL(_##severity, condition, n)
+#define DLOG_IF_FIRST_N(severity, condition, n) \
+ ABSL_DLOG_IF_FIRST_N_IMPL(_##severity, condition, n)
+#define DLOG_IF_EVERY_POW_2(severity, condition) \
+ ABSL_DLOG_IF_EVERY_POW_2_IMPL(_##severity, condition)
+#define DLOG_IF_EVERY_N_SEC(severity, condition, n_seconds) \
+ ABSL_DLOG_IF_EVERY_N_SEC_IMPL(_##severity, condition, n_seconds)
+
+#endif // ABSL_LOG_LOG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_entry.cc b/contrib/restricted/abseil-cpp/absl/log/log_entry.cc
new file mode 100644
index 0000000000..19c3b3f1be
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_entry.cc
@@ -0,0 +1,29 @@
+//
+// 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/log_entry.h"
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
+constexpr int LogEntry::kNoVerbosityLevel;
+constexpr int LogEntry::kNoVerboseLevel;
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_entry.h b/contrib/restricted/abseil-cpp/absl/log/log_entry.h
new file mode 100644
index 0000000000..9e4ae8eb76
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_entry.h
@@ -0,0 +1,220 @@
+// 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_entry.h
+// -----------------------------------------------------------------------------
+//
+// This header declares `class absl::LogEntry`, which represents a log record as
+// passed to `LogSink::Send`. Data returned by pointer or by reference or by
+// `absl::string_view` must be copied if they are needed after the lifetime of
+// the `absl::LogEntry`.
+
+#ifndef ABSL_LOG_LOG_ENTRY_H_
+#define ABSL_LOG_LOG_ENTRY_H_
+
+#include <cstddef>
+#include <string>
+
+#include "absl/base/attributes.h"
+#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/time.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace log_internal {
+// Test only friend.
+class LogEntryTestPeer;
+class LogMessage;
+} // namespace log_internal
+
+// LogEntry
+//
+// Represents a single entry in a log, i.e., one `LOG` statement or failed
+// `CHECK`.
+//
+// `LogEntry` is thread-compatible.
+class LogEntry final {
+ public:
+ using tid_t = log_internal::Tid;
+
+ // For non-verbose log entries, `verbosity()` returns `kNoVerbosityLevel`.
+ static constexpr int kNoVerbosityLevel = -1;
+ static constexpr int kNoVerboseLevel = -1; // TO BE removed
+
+ // Pass `LogEntry` by reference, and do not store it as its state does not
+ // outlive the call to `LogSink::Send()`.
+ LogEntry(const LogEntry&) = delete;
+ LogEntry& operator=(const LogEntry&) = delete;
+
+ // Source file and line where the log message occurred. Taken from `__FILE__`
+ // and `__LINE__` unless overridden by `LOG(...).AtLocation(...)`.
+ //
+ // Take special care not to use the values returned by `source_filename()` and
+ // `source_basename()` after the lifetime of the entry. This is always
+ // incorrect, but it will often work in practice because they usually point
+ // into a statically allocated character array obtained from `__FILE__`.
+ // Statements like `LOG(INFO).AtLocation(std::string(...), ...)` will expose
+ // the bug. If you need the data later, you must copy them.
+ absl::string_view source_filename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return full_filename_;
+ }
+ absl::string_view source_basename() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return base_filename_;
+ }
+ int source_line() const { return line_; }
+
+ // LogEntry::prefix()
+ //
+ // True unless the metadata prefix was suppressed once by
+ // `LOG(...).NoPrefix()` or globally by `absl::EnableLogPrefix(false)`.
+ // Implies `text_message_with_prefix() == text_message()`.
+ bool prefix() const { return prefix_; }
+
+ // LogEntry::log_severity()
+ //
+ // Returns this entry's severity. For `LOG`, taken from the first argument;
+ // for `CHECK`, always `absl::LogSeverity::kFatal`.
+ absl::LogSeverity log_severity() const { return severity_; }
+
+ // LogEntry::verbosity()
+ //
+ // Returns this entry's verbosity, or `kNoVerbosityLevel` for a non-verbose
+ // entry. Verbosity control is not available outside of Google yet.
+ int verbosity() const { return verbose_level_; }
+
+ // LogEntry::timestamp()
+ //
+ // Returns the time at which this entry was written. Captured during
+ // evaluation of `LOG`, but can be overridden by
+ // `LOG(...).WithTimestamp(...)`.
+ //
+ // Take care not to rely on timestamps increasing monotonically, or even to
+ // rely on timestamps having any particular relationship with reality (since
+ // they can be overridden).
+ absl::Time timestamp() const { return timestamp_; }
+
+ // LogEntry::tid()
+ //
+ // Returns the ID of the thread that wrote this entry. Captured during
+ // evaluation of `LOG`, but can be overridden by `LOG(...).WithThreadID(...)`.
+ //
+ // Take care not to *rely* on reported thread IDs as they can be overridden as
+ // specified above.
+ tid_t tid() const { return tid_; }
+
+ // Text-formatted version of the log message. An underlying buffer holds
+ // these contiguous data:
+ //
+ // * A prefix formed by formatting metadata (timestamp, filename, line number,
+ // etc.)
+ // The prefix may be empty - see `LogEntry::prefix()` - and may rarely be
+ // truncated if the metadata are very long.
+ // * The streamed data
+ // The data may be empty if nothing was streamed, or may be truncated to fit
+ // the buffer.
+ // * A newline
+ // * A nul terminator
+ //
+ // The newline and nul terminator will be present even if the prefix and/or
+ // data are truncated.
+ //
+ // These methods give access to the most commonly useful substrings of the
+ // buffer's contents. Other combinations can be obtained with substring
+ // arithmetic.
+ //
+ // The buffer does not outlive the entry; if you need the data later, you must
+ // copy them.
+ absl::string_view text_message_with_prefix_and_newline() const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return absl::string_view(
+ text_message_with_prefix_and_newline_and_nul_.data(),
+ text_message_with_prefix_and_newline_and_nul_.size() - 1);
+ }
+ absl::string_view text_message_with_prefix() const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return absl::string_view(
+ text_message_with_prefix_and_newline_and_nul_.data(),
+ text_message_with_prefix_and_newline_and_nul_.size() - 2);
+ }
+ absl::string_view text_message_with_newline() const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return absl::string_view(
+ text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
+ text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 1);
+ }
+ absl::string_view text_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return absl::string_view(
+ text_message_with_prefix_and_newline_and_nul_.data() + prefix_len_,
+ text_message_with_prefix_and_newline_and_nul_.size() - prefix_len_ - 2);
+ }
+ const char* text_message_with_prefix_and_newline_c_str() const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return text_message_with_prefix_and_newline_and_nul_.data();
+ }
+
+ // Returns a serialized protobuf holding the operands streamed into this
+ // log message. The message definition is not yet published.
+ //
+ // The buffer does not outlive the entry; if you need the data later, you must
+ // copy them.
+ absl::string_view encoded_message() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return encoding_;
+ }
+
+ // LogEntry::stacktrace()
+ //
+ // Optional stacktrace, e.g. for `FATAL` logs and failed `CHECK`s.
+ //
+ // Fatal entries are dispatched to each sink twice: first with all data and
+ // metadata but no stacktrace, and then with the stacktrace. This is done
+ // because stacktrace collection is sometimes slow and fallible, and it's
+ // critical to log enough information to diagnose the failure even if the
+ // stacktrace collection hangs.
+ //
+ // The buffer does not outlive the entry; if you need the data later, you must
+ // copy them.
+ absl::string_view stacktrace() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return stacktrace_;
+ }
+
+ private:
+ LogEntry() = default;
+
+ absl::string_view full_filename_;
+ absl::string_view base_filename_;
+ int line_;
+ bool prefix_;
+ absl::LogSeverity severity_;
+ int verbose_level_; // >=0 for `VLOG`, etc.; otherwise `kNoVerbosityLevel`.
+ absl::Time timestamp_;
+ tid_t tid_;
+ absl::Span<const char> text_message_with_prefix_and_newline_and_nul_;
+ size_t prefix_len_;
+ absl::string_view encoding_;
+ std::string stacktrace_;
+
+ friend class log_internal::LogEntryTestPeer;
+ friend class log_internal::LogMessage;
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_LOG_ENTRY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_sink.cc b/contrib/restricted/abseil-cpp/absl/log/log_sink.cc
new file mode 100644
index 0000000000..01d7ca8251
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_sink.cc
@@ -0,0 +1,23 @@
+// 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/log_sink.h"
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+void LogSink::KeyFunction() const {}
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_sink.h b/contrib/restricted/abseil-cpp/absl/log/log_sink.h
new file mode 100644
index 0000000000..9bfa6f8624
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_sink.h
@@ -0,0 +1,64 @@
+// 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_sink.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the interface class `absl::LogSink`.
+
+#ifndef ABSL_LOG_LOG_SINK_H_
+#define ABSL_LOG_LOG_SINK_H_
+
+#include "absl/base/config.h"
+#include "absl/log/log_entry.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::LogSink
+//
+// `absl::LogSink` is an interface which can be extended to intercept and
+// process particular messages (with `LOG.ToSinkOnly()` or
+// `LOG.ToSinkAlso()`) or all messages (if registered with
+// `absl::AddLogSink`). Implementations must be thread-safe, and should take
+// care not to take any locks that might be held by the `LOG` caller.
+class LogSink {
+ public:
+ virtual ~LogSink() = default;
+
+ // LogSink::Send()
+ //
+ // `Send` is called synchronously during the log statement.
+ //
+ // It is safe to use `LOG` within an implementation of `Send`. `ToSinkOnly`
+ // and `ToSinkAlso` are safe in general but can be used to create an infinite
+ // loop if you try.
+ virtual void Send(const absl::LogEntry& entry) = 0;
+
+ // LogSink::Flush()
+ //
+ // Sinks that buffer messages should override this method to flush the buffer
+ // and return.
+ virtual void Flush() {}
+
+ private:
+ // https://lld.llvm.org/missingkeyfunction.html#missing-key-function
+ virtual void KeyFunction() const final; // NOLINT(readability/inheritance)
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_LOG_SINK_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h b/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h
new file mode 100644
index 0000000000..bf76cceeae
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_sink_registry.h
@@ -0,0 +1,61 @@
+// 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_sink_registry.h
+// -----------------------------------------------------------------------------
+//
+// This header declares APIs to operate on global set of registered log sinks.
+
+#ifndef ABSL_LOG_LOG_SINK_REGISTRY_H_
+#define ABSL_LOG_LOG_SINK_REGISTRY_H_
+
+#include "absl/base/config.h"
+#include "absl/log/internal/log_sink_set.h"
+#include "absl/log/log_sink.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// AddLogSink(), RemoveLogSink()
+//
+// Adds or removes a `absl::LogSink` as a consumer of logging data.
+//
+// These functions are thread-safe.
+//
+// It is an error to attempt to add a sink that's already registered or to
+// attempt to remove one that isn't.
+//
+// To avoid unbounded recursion, dispatch to registered `absl::LogSink`s is
+// disabled per-thread while running the `Send()` method of registered
+// `absl::LogSink`s. Affected messages are dispatched to a special internal
+// sink instead which writes them to `stderr`.
+//
+// Do not call these inside `absl::LogSink::Send`.
+inline void AddLogSink(absl::LogSink* sink) { log_internal::AddLogSink(sink); }
+inline void RemoveLogSink(absl::LogSink* sink) {
+ log_internal::RemoveLogSink(sink);
+}
+
+// FlushLogSinks()
+//
+// Calls `absl::LogSink::Flush` on all registered sinks.
+//
+// Do not call this inside `absl::LogSink::Send`.
+inline void FlushLogSinks() { log_internal::FlushLogSinks(); }
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_LOG_SINK_REGISTRY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/memory/memory.h b/contrib/restricted/abseil-cpp/absl/memory/memory.h
index 7a5063ee69..3508135c33 100644
--- a/contrib/restricted/abseil-cpp/absl/memory/memory.h
+++ b/contrib/restricted/abseil-cpp/absl/memory/memory.h
@@ -75,31 +75,6 @@ std::unique_ptr<T> WrapUnique(T* ptr) {
return std::unique_ptr<T>(ptr);
}
-namespace memory_internal {
-
-// Traits to select proper overload and return type for `absl::make_unique<>`.
-template <typename T>
-struct MakeUniqueResult {
- using scalar = std::unique_ptr<T>;
-};
-template <typename T>
-struct MakeUniqueResult<T[]> {
- using array = std::unique_ptr<T[]>;
-};
-template <typename T, size_t N>
-struct MakeUniqueResult<T[N]> {
- using invalid = void;
-};
-
-} // namespace memory_internal
-
-// gcc 4.8 has __cplusplus at 201301 but the libstdc++ shipped with it doesn't
-// define make_unique. Other supported compilers either just define __cplusplus
-// as 201103 but have make_unique (msvc), or have make_unique whenever
-// __cplusplus > 201103 (clang).
-#if defined(__cpp_lib_make_unique)
-using std::make_unique;
-#else
// -----------------------------------------------------------------------------
// Function Template: make_unique<T>()
// -----------------------------------------------------------------------------
@@ -108,82 +83,18 @@ using std::make_unique;
// during the construction process. `absl::make_unique<>` also avoids redundant
// type declarations, by avoiding the need to explicitly use the `new` operator.
//
-// This implementation of `absl::make_unique<>` is designed for C++11 code and
-// will be replaced in C++14 by the equivalent `std::make_unique<>` abstraction.
-// `absl::make_unique<>` is designed to be 100% compatible with
-// `std::make_unique<>` so that the eventual migration will involve a simple
-// rename operation.
+// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique
//
// For more background on why `std::unique_ptr<T>(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.)
//
-// Example usage:
-//
-// auto p = make_unique<X>(args...); // 'p' is a std::unique_ptr<X>
-// auto pa = make_unique<X[]>(5); // 'pa' is a std::unique_ptr<X[]>
-//
-// Three overloads of `absl::make_unique` are required:
-//
-// - For non-array T:
-//
-// Allocates a T with `new T(std::forward<Args> args...)`,
-// forwarding all `args` to T's constructor.
-// Returns a `std::unique_ptr<T>` owning that object.
-//
-// - For an array of unknown bounds T[]:
-//
-// `absl::make_unique<>` will allocate an array T of type U[] with
-// `new U[n]()` and return a `std::unique_ptr<U[]>` owning that array.
-//
-// Note that 'U[n]()' is different from 'U[n]', and elements will be
-// value-initialized. Note as well that `std::unique_ptr` will perform its
-// own destruction of the array elements upon leaving scope, even though
-// the array [] does not have a default destructor.
-//
-// NOTE: an array of unknown bounds T[] may still be (and often will be)
-// initialized to have a size, and will still use this overload. E.g:
-//
-// auto my_array = absl::make_unique<int[]>(10);
-//
-// - For an array of known bounds T[N]:
-//
-// `absl::make_unique<>` is deleted (like with `std::make_unique<>`) as
-// this overload is not useful.
-//
-// NOTE: an array of known bounds T[N] is not considered a useful
-// construction, and may cause undefined behavior in templates. E.g:
-//
-// auto my_array = absl::make_unique<int[10]>();
-//
-// In those cases, of course, you can still use the overload above and
-// simply initialize it to its desired size:
-//
-// auto my_array = absl::make_unique<int[]>(10);
-
-// `absl::make_unique` overload for non-array types.
-template <typename T, typename... Args>
-typename memory_internal::MakeUniqueResult<T>::scalar make_unique(
- Args&&... args) {
- return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
-}
-
-// `absl::make_unique` overload for an array T[] of unknown bounds.
-// The array allocation needs to use the `new T[size]` form and cannot take
-// element constructor arguments. The `std::unique_ptr` will manage destructing
-// these array elements.
-template <typename T>
-typename memory_internal::MakeUniqueResult<T>::array make_unique(size_t n) {
- return std::unique_ptr<T>(new typename absl::remove_extent_t<T>[n]());
-}
-
-// `absl::make_unique` overload for an array T[N] of known bounds.
-// This construction will be rejected.
-template <typename T, typename... Args>
-typename memory_internal::MakeUniqueResult<T>::invalid make_unique(
- Args&&... /* args */) = delete;
-#endif
+// 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()
@@ -247,6 +158,26 @@ std::weak_ptr<T> WeakenPtr(const std::shared_ptr<T>& ptr) {
return std::weak_ptr<T>(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<E, O, D>::type evaluates to E<O> if possible. Otherwise, D.
@@ -264,357 +195,6 @@ struct ExtractOr<Extract, Obj, Default, void_t<Extract<Obj>>> {
template <template <typename> class Extract, typename Obj, typename Default>
using ExtractOrT = typename ExtractOr<Extract, Obj, Default, void>::type;
-// Extractors for the features of allocators.
-template <typename T>
-using GetPointer = typename T::pointer;
-
-template <typename T>
-using GetConstPointer = typename T::const_pointer;
-
-template <typename T>
-using GetVoidPointer = typename T::void_pointer;
-
-template <typename T>
-using GetConstVoidPointer = typename T::const_void_pointer;
-
-template <typename T>
-using GetDifferenceType = typename T::difference_type;
-
-template <typename T>
-using GetSizeType = typename T::size_type;
-
-template <typename T>
-using GetPropagateOnContainerCopyAssignment =
- typename T::propagate_on_container_copy_assignment;
-
-template <typename T>
-using GetPropagateOnContainerMoveAssignment =
- typename T::propagate_on_container_move_assignment;
-
-template <typename T>
-using GetPropagateOnContainerSwap = typename T::propagate_on_container_swap;
-
-template <typename T>
-using GetIsAlwaysEqual = typename T::is_always_equal;
-
-template <typename T>
-struct GetFirstArg;
-
-template <template <typename...> class Class, typename T, typename... Args>
-struct GetFirstArg<Class<T, Args...>> {
- using type = T;
-};
-
-template <typename Ptr, typename = void>
-struct ElementType {
- using type = typename GetFirstArg<Ptr>::type;
-};
-
-template <typename T>
-struct ElementType<T, void_t<typename T::element_type>> {
- using type = typename T::element_type;
-};
-
-template <typename T, typename U>
-struct RebindFirstArg;
-
-template <template <typename...> class Class, typename T, typename... Args,
- typename U>
-struct RebindFirstArg<Class<T, Args...>, U> {
- using type = Class<U, Args...>;
-};
-
-template <typename T, typename U, typename = void>
-struct RebindPtr {
- using type = typename RebindFirstArg<T, U>::type;
-};
-
-template <typename T, typename U>
-struct RebindPtr<T, U, void_t<typename T::template rebind<U>>> {
- using type = typename T::template rebind<U>;
-};
-
-template <typename T, typename U>
-constexpr bool HasRebindAlloc(...) {
- return false;
-}
-
-template <typename T, typename U>
-constexpr bool HasRebindAlloc(typename T::template rebind<U>::other*) {
- return true;
-}
-
-template <typename T, typename U, bool = HasRebindAlloc<T, U>(nullptr)>
-struct RebindAlloc {
- using type = typename RebindFirstArg<T, U>::type;
-};
-
-template <typename T, typename U>
-struct RebindAlloc<T, U, true> {
- using type = typename T::template rebind<U>::other;
-};
-
-} // namespace memory_internal
-
-// -----------------------------------------------------------------------------
-// Class Template: pointer_traits
-// -----------------------------------------------------------------------------
-//
-// An implementation of C++11's std::pointer_traits.
-//
-// Provided for portability on toolchains that have a working C++11 compiler,
-// but the standard library is lacking in C++11 support. For example, some
-// version of the Android NDK.
-//
-
-template <typename Ptr>
-struct pointer_traits {
- using pointer = Ptr;
-
- // element_type:
- // Ptr::element_type if present. Otherwise T if Ptr is a template
- // instantiation Template<T, Args...>
- using element_type = typename memory_internal::ElementType<Ptr>::type;
-
- // difference_type:
- // Ptr::difference_type if present, otherwise std::ptrdiff_t
- using difference_type =
- memory_internal::ExtractOrT<memory_internal::GetDifferenceType, Ptr,
- std::ptrdiff_t>;
-
- // rebind:
- // Ptr::rebind<U> if exists, otherwise Template<U, Args...> if Ptr is a
- // template instantiation Template<T, Args...>
- template <typename U>
- using rebind = typename memory_internal::RebindPtr<Ptr, U>::type;
-
- // pointer_to:
- // Calls Ptr::pointer_to(r)
- static pointer pointer_to(element_type& r) { // NOLINT(runtime/references)
- return Ptr::pointer_to(r);
- }
-};
-
-// Specialization for T*.
-template <typename T>
-struct pointer_traits<T*> {
- using pointer = T*;
- using element_type = T;
- using difference_type = std::ptrdiff_t;
-
- template <typename U>
- using rebind = U*;
-
- // pointer_to:
- // Calls std::addressof(r)
- static pointer pointer_to(
- element_type& r) noexcept { // NOLINT(runtime/references)
- return std::addressof(r);
- }
-};
-
-// -----------------------------------------------------------------------------
-// Class Template: allocator_traits
-// -----------------------------------------------------------------------------
-//
-// A C++11 compatible implementation of C++17's std::allocator_traits.
-//
-#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-using std::allocator_traits;
-#else // __cplusplus >= 201703L
-template <typename Alloc>
-struct allocator_traits {
- using allocator_type = Alloc;
-
- // value_type:
- // Alloc::value_type
- using value_type = typename Alloc::value_type;
-
- // pointer:
- // Alloc::pointer if present, otherwise value_type*
- using pointer = memory_internal::ExtractOrT<memory_internal::GetPointer,
- Alloc, value_type*>;
-
- // const_pointer:
- // Alloc::const_pointer if present, otherwise
- // absl::pointer_traits<pointer>::rebind<const value_type>
- using const_pointer =
- memory_internal::ExtractOrT<memory_internal::GetConstPointer, Alloc,
- typename absl::pointer_traits<pointer>::
- template rebind<const value_type>>;
-
- // void_pointer:
- // Alloc::void_pointer if present, otherwise
- // absl::pointer_traits<pointer>::rebind<void>
- using void_pointer = memory_internal::ExtractOrT<
- memory_internal::GetVoidPointer, Alloc,
- typename absl::pointer_traits<pointer>::template rebind<void>>;
-
- // const_void_pointer:
- // Alloc::const_void_pointer if present, otherwise
- // absl::pointer_traits<pointer>::rebind<const void>
- using const_void_pointer = memory_internal::ExtractOrT<
- memory_internal::GetConstVoidPointer, Alloc,
- typename absl::pointer_traits<pointer>::template rebind<const void>>;
-
- // difference_type:
- // Alloc::difference_type if present, otherwise
- // absl::pointer_traits<pointer>::difference_type
- using difference_type = memory_internal::ExtractOrT<
- memory_internal::GetDifferenceType, Alloc,
- typename absl::pointer_traits<pointer>::difference_type>;
-
- // size_type:
- // Alloc::size_type if present, otherwise
- // std::make_unsigned<difference_type>::type
- using size_type = memory_internal::ExtractOrT<
- memory_internal::GetSizeType, Alloc,
- typename std::make_unsigned<difference_type>::type>;
-
- // propagate_on_container_copy_assignment:
- // Alloc::propagate_on_container_copy_assignment if present, otherwise
- // std::false_type
- using propagate_on_container_copy_assignment = memory_internal::ExtractOrT<
- memory_internal::GetPropagateOnContainerCopyAssignment, Alloc,
- std::false_type>;
-
- // propagate_on_container_move_assignment:
- // Alloc::propagate_on_container_move_assignment if present, otherwise
- // std::false_type
- using propagate_on_container_move_assignment = memory_internal::ExtractOrT<
- memory_internal::GetPropagateOnContainerMoveAssignment, Alloc,
- std::false_type>;
-
- // propagate_on_container_swap:
- // Alloc::propagate_on_container_swap if present, otherwise std::false_type
- using propagate_on_container_swap =
- memory_internal::ExtractOrT<memory_internal::GetPropagateOnContainerSwap,
- Alloc, std::false_type>;
-
- // is_always_equal:
- // Alloc::is_always_equal if present, otherwise std::is_empty<Alloc>::type
- using is_always_equal =
- memory_internal::ExtractOrT<memory_internal::GetIsAlwaysEqual, Alloc,
- typename std::is_empty<Alloc>::type>;
-
- // rebind_alloc:
- // Alloc::rebind<T>::other if present, otherwise Alloc<T, Args> if this Alloc
- // is Alloc<U, Args>
- template <typename T>
- using rebind_alloc = typename memory_internal::RebindAlloc<Alloc, T>::type;
-
- // rebind_traits:
- // absl::allocator_traits<rebind_alloc<T>>
- template <typename T>
- using rebind_traits = absl::allocator_traits<rebind_alloc<T>>;
-
- // allocate(Alloc& a, size_type n):
- // Calls a.allocate(n)
- static pointer allocate(Alloc& a, // NOLINT(runtime/references)
- size_type n) {
- return a.allocate(n);
- }
-
- // allocate(Alloc& a, size_type n, const_void_pointer hint):
- // Calls a.allocate(n, hint) if possible.
- // If not possible, calls a.allocate(n)
- static pointer allocate(Alloc& a, size_type n, // NOLINT(runtime/references)
- const_void_pointer hint) {
- return allocate_impl(0, a, n, hint);
- }
-
- // deallocate(Alloc& a, pointer p, size_type n):
- // Calls a.deallocate(p, n)
- static void deallocate(Alloc& a, pointer p, // NOLINT(runtime/references)
- size_type n) {
- a.deallocate(p, n);
- }
-
- // construct(Alloc& a, T* p, Args&&... args):
- // Calls a.construct(p, std::forward<Args>(args)...) if possible.
- // If not possible, calls
- // ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...)
- template <typename T, typename... Args>
- static void construct(Alloc& a, T* p, // NOLINT(runtime/references)
- Args&&... args) {
- construct_impl(0, a, p, std::forward<Args>(args)...);
- }
-
- // destroy(Alloc& a, T* p):
- // Calls a.destroy(p) if possible. If not possible, calls p->~T().
- template <typename T>
- static void destroy(Alloc& a, T* p) { // NOLINT(runtime/references)
- destroy_impl(0, a, p);
- }
-
- // max_size(const Alloc& a):
- // Returns a.max_size() if possible. If not possible, returns
- // std::numeric_limits<size_type>::max() / sizeof(value_type)
- static size_type max_size(const Alloc& a) { return max_size_impl(0, a); }
-
- // select_on_container_copy_construction(const Alloc& a):
- // Returns a.select_on_container_copy_construction() if possible.
- // If not possible, returns a.
- static Alloc select_on_container_copy_construction(const Alloc& a) {
- return select_on_container_copy_construction_impl(0, a);
- }
-
- private:
- template <typename A>
- static auto allocate_impl(int, A& a, // NOLINT(runtime/references)
- size_type n, const_void_pointer hint)
- -> decltype(a.allocate(n, hint)) {
- return a.allocate(n, hint);
- }
- static pointer allocate_impl(char, Alloc& a, // NOLINT(runtime/references)
- size_type n, const_void_pointer) {
- return a.allocate(n);
- }
-
- template <typename A, typename... Args>
- static auto construct_impl(int, A& a, // NOLINT(runtime/references)
- Args&&... args)
- -> decltype(a.construct(std::forward<Args>(args)...)) {
- a.construct(std::forward<Args>(args)...);
- }
-
- template <typename T, typename... Args>
- static void construct_impl(char, Alloc&, T* p, Args&&... args) {
- ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
- }
-
- template <typename A, typename T>
- static auto destroy_impl(int, A& a, // NOLINT(runtime/references)
- T* p) -> decltype(a.destroy(p)) {
- a.destroy(p);
- }
- template <typename T>
- static void destroy_impl(char, Alloc&, T* p) {
- p->~T();
- }
-
- template <typename A>
- static auto max_size_impl(int, const A& a) -> decltype(a.max_size()) {
- return a.max_size();
- }
- static size_type max_size_impl(char, const Alloc&) {
- return (std::numeric_limits<size_type>::max)() / sizeof(value_type);
- }
-
- template <typename A>
- static auto select_on_container_copy_construction_impl(int, const A& a)
- -> decltype(a.select_on_container_copy_construction()) {
- return a.select_on_container_copy_construction();
- }
- static Alloc select_on_container_copy_construction_impl(char,
- const Alloc& a) {
- return a;
- }
-};
-#endif // __cplusplus >= 201703L
-
-namespace memory_internal {
-
// This template alias transforms Alloc::is_nothrow into a metafunction with
// Alloc as a parameter so it can be used with ExtractOrT<>.
template <typename Alloc>
diff --git a/contrib/restricted/abseil-cpp/absl/meta/type_traits.h b/contrib/restricted/abseil-cpp/absl/meta/type_traits.h
index d886cb30a8..b1656c39c8 100644
--- a/contrib/restricted/abseil-cpp/absl/meta/type_traits.h
+++ b/contrib/restricted/abseil-cpp/absl/meta/type_traits.h
@@ -114,18 +114,6 @@ struct VoidTImpl {
using type = void;
};
-// This trick to retrieve a default alignment is necessary for our
-// implementation of aligned_storage_t to be consistent with any implementation
-// of std::aligned_storage.
-template <size_t Len, typename T = std::aligned_storage<Len>>
-struct default_alignment_of_aligned_storage;
-
-template <size_t Len, size_t Align>
-struct default_alignment_of_aligned_storage<Len,
- std::aligned_storage<Len, Align>> {
- static constexpr size_t value = Align;
-};
-
////////////////////////////////
// Library Fundamentals V2 TS //
////////////////////////////////
@@ -298,8 +286,12 @@ struct is_function
// https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html#Type-Traits.
template <typename T>
struct is_trivially_destructible
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
+ : std::is_trivially_destructible<T> {
+#else
: std::integral_constant<bool, __has_trivial_destructor(T) &&
std::is_destructible<T>::value> {
+#endif
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
private:
static constexpr bool compliant = std::is_trivially_destructible<T>::value ==
@@ -347,9 +339,13 @@ struct is_trivially_destructible
// Nontrivially destructible types will cause the expression to be nontrivial.
template <typename T>
struct is_trivially_default_constructible
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
+ : std::is_trivially_default_constructible<T> {
+#else
: std::integral_constant<bool, __has_trivial_constructor(T) &&
std::is_default_constructible<T>::value &&
is_trivially_destructible<T>::value> {
+#endif
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
@@ -381,10 +377,14 @@ struct is_trivially_default_constructible
// expression to be nontrivial.
template <typename T>
struct is_trivially_move_constructible
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
+ : std::is_trivially_move_constructible<T> {
+#else
: std::conditional<
std::is_object<T>::value && !std::is_array<T>::value,
type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
std::is_reference<T>>::type::type {
+#endif
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
!defined( \
ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
@@ -490,9 +490,13 @@ struct is_trivially_move_assignable
// `is_trivially_assignable<T&, const T&>`.
template <typename T>
struct is_trivially_copy_assignable
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+ : std::is_trivially_copy_assignable<T> {
+#else
: std::integral_constant<
bool, __has_trivial_assign(typename std::remove_reference<T>::type) &&
absl::is_copy_assignable<T>::value> {
+#endif
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
private:
static constexpr bool compliant =
@@ -544,6 +548,11 @@ namespace type_traits_internal {
// destructible. Arrays of trivially copyable types are trivially copyable.
//
// We expose this metafunction only for internal use within absl.
+
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_COPYABLE)
+template <typename T>
+struct is_trivially_copyable : std::is_trivially_copyable<T> {};
+#else
template <typename T>
class is_trivially_copyable_impl {
using ExtentsRemoved = typename std::remove_all_extents<T>::type;
@@ -569,6 +578,7 @@ template <typename T>
struct is_trivially_copyable
: std::integral_constant<
bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
+#endif
} // namespace type_traits_internal
// -----------------------------------------------------------------------------
@@ -620,6 +630,21 @@ using remove_extent_t = typename std::remove_extent<T>::type;
template <typename T>
using remove_all_extents_t = typename std::remove_all_extents<T>::type;
+namespace type_traits_internal {
+// This trick to retrieve a default alignment is necessary for our
+// implementation of aligned_storage_t to be consistent with any
+// implementation of std::aligned_storage.
+template <size_t Len, typename T = std::aligned_storage<Len>>
+struct default_alignment_of_aligned_storage;
+
+template <size_t Len, size_t Align>
+struct default_alignment_of_aligned_storage<
+ Len, std::aligned_storage<Len, Align>> {
+ static constexpr size_t value = Align;
+};
+} // namespace type_traits_internal
+
+// TODO(b/260219225): std::aligned_storage(_t) is deprecated in C++23.
template <size_t Len, size_t Align = type_traits_internal::
default_alignment_of_aligned_storage<Len>::value>
using aligned_storage_t = typename std::aligned_storage<Len, Align>::type;
@@ -791,6 +816,73 @@ using swap_internal::Swap;
using swap_internal::StdSwapIsUnconstrained;
} // namespace type_traits_internal
+
+// absl::is_trivially_relocatable<T>
+// Detects whether a type is "trivially relocatable" -- meaning it can be
+// relocated without invoking the constructor/destructor, using a form of move
+// elision.
+//
+// Example:
+//
+// if constexpr (absl::is_trivially_relocatable<T>::value) {
+// memcpy(new_location, old_location, sizeof(T));
+// } else {
+// new(new_location) T(std::move(*old_location));
+// old_location->~T();
+// }
+//
+// Upstream documentation:
+//
+// https://clang.llvm.org/docs/LanguageExtensions.html#:~:text=__is_trivially_relocatable
+//
+#if ABSL_HAVE_BUILTIN(__is_trivially_relocatable)
+template <class T>
+struct is_trivially_relocatable
+ : std::integral_constant<bool, __is_trivially_relocatable(T)> {};
+#else
+template <class T>
+struct is_trivially_relocatable : std::integral_constant<bool, false> {};
+#endif
+
+// absl::is_constant_evaluated()
+//
+// Detects whether the function call occurs within a constant-evaluated context.
+// Returns true if the evaluation of the call occurs within the evaluation of an
+// expression or conversion that is manifestly constant-evaluated; otherwise
+// returns false.
+//
+// This function is implemented in terms of `std::is_constant_evaluated` for
+// c++20 and up. For older c++ versions, the function is implemented in terms
+// of `__builtin_is_constant_evaluated` if available, otherwise the function
+// will fail to compile.
+//
+// Applications can inspect `ABSL_HAVE_CONSTANT_EVALUATED` at compile time
+// to check if this function is supported.
+//
+// Example:
+//
+// constexpr MyClass::MyClass(int param) {
+// #ifdef ABSL_HAVE_CONSTANT_EVALUATED
+// if (!absl::is_constant_evaluated()) {
+// ABSL_LOG(INFO) << "MyClass(" << param << ")";
+// }
+// #endif // ABSL_HAVE_CONSTANT_EVALUATED
+// }
+//
+// Upstream documentation:
+//
+// http://en.cppreference.com/w/cpp/types/is_constant_evaluated
+// http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html#:~:text=__builtin_is_constant_evaluated
+//
+#if defined(ABSL_HAVE_CONSTANT_EVALUATED)
+constexpr bool is_constant_evaluated() noexcept {
+#ifdef __cpp_lib_is_constant_evaluated
+ return std::is_constant_evaluated();
+#elif ABSL_HAVE_BUILTIN(__builtin_is_constant_evaluated)
+ return __builtin_is_constant_evaluated();
+#endif
+}
+#endif // ABSL_HAVE_CONSTANT_EVALUATED
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/numeric/bits.h b/contrib/restricted/abseil-cpp/absl/numeric/bits.h
index 628cdf50f1..df81b9a929 100644
--- a/contrib/restricted/abseil-cpp/absl/numeric/bits.h
+++ b/contrib/restricted/abseil-cpp/absl/numeric/bits.h
@@ -131,10 +131,9 @@ has_single_bit(T x) noexcept {
// fractional part discarded.
template <class T>
ABSL_INTERNAL_CONSTEXPR_CLZ inline
- typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
bit_width(T x) noexcept {
- return std::numeric_limits<T>::digits -
- static_cast<unsigned int>(countl_zero(x));
+ return std::numeric_limits<T>::digits - countl_zero(x);
}
// Returns: If x == 0, 0; otherwise the maximal value y such that
diff --git a/contrib/restricted/abseil-cpp/absl/numeric/int128.cc b/contrib/restricted/abseil-cpp/absl/numeric/int128.cc
index 8261f56dcb..37691cf2f5 100644
--- a/contrib/restricted/abseil-cpp/absl/numeric/int128.cc
+++ b/contrib/restricted/abseil-cpp/absl/numeric/int128.cc
@@ -209,15 +209,16 @@ std::ostream& operator<<(std::ostream& os, uint128 v) {
// Add the requisite padding.
std::streamsize width = os.width(0);
if (static_cast<size_t>(width) > rep.size()) {
+ const size_t count = static_cast<size_t>(width) - rep.size();
std::ios::fmtflags adjustfield = flags & std::ios::adjustfield;
if (adjustfield == std::ios::left) {
- rep.append(width - rep.size(), os.fill());
+ rep.append(count, os.fill());
} else if (adjustfield == std::ios::internal &&
(flags & std::ios::showbase) &&
(flags & std::ios::basefield) == std::ios::hex && v != 0) {
- rep.insert((size_t)2, width - rep.size(), os.fill());
+ rep.insert((size_t)2, count, os.fill());
} else {
- rep.insert((size_t)0, width - rep.size(), os.fill());
+ rep.insert((size_t)0, count, os.fill());
}
}
@@ -306,22 +307,23 @@ std::ostream& operator<<(std::ostream& os, int128 v) {
// Add the requisite padding.
std::streamsize width = os.width(0);
if (static_cast<size_t>(width) > rep.size()) {
+ const size_t count = static_cast<size_t>(width) - rep.size();
switch (flags & std::ios::adjustfield) {
case std::ios::left:
- rep.append(width - rep.size(), os.fill());
+ rep.append(count, os.fill());
break;
case std::ios::internal:
if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) {
- rep.insert((size_t)1, width - rep.size(), os.fill());
+ rep.insert(1u, count, os.fill());
} else if ((flags & std::ios::basefield) == std::ios::hex &&
(flags & std::ios::showbase) && v != 0) {
- rep.insert((size_t)2, width - rep.size(), os.fill());
+ rep.insert((size_t)2, count, os.fill());
} else {
- rep.insert((size_t)0, width - rep.size(), os.fill());
+ rep.insert((size_t)0, count, os.fill());
}
break;
default: // std::ios::right
- rep.insert((size_t)0, width - rep.size(), os.fill());
+ rep.insert((size_t)0, count, os.fill());
break;
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/profiling/internal/sample_recorder.h b/contrib/restricted/abseil-cpp/absl/profiling/internal/sample_recorder.h
index 5f65983bc8..371f6c473f 100644
--- a/contrib/restricted/abseil-cpp/absl/profiling/internal/sample_recorder.h
+++ b/contrib/restricted/abseil-cpp/absl/profiling/internal/sample_recorder.h
@@ -77,8 +77,8 @@ class SampleRecorder {
// samples that have been dropped.
int64_t Iterate(const std::function<void(const T& stack)>& f);
- int32_t GetMaxSamples() const;
- void SetMaxSamples(int32_t max);
+ size_t GetMaxSamples() const;
+ void SetMaxSamples(size_t max);
private:
void PushNew(T* sample);
@@ -88,7 +88,7 @@ class SampleRecorder {
std::atomic<size_t> dropped_samples_;
std::atomic<size_t> size_estimate_;
- std::atomic<int32_t> max_samples_{1 << 20};
+ std::atomic<size_t> max_samples_{1 << 20};
// Intrusive lock free linked lists for tracking samples.
//
@@ -186,7 +186,7 @@ T* SampleRecorder<T>::PopDead(Targs... args) {
template <typename T>
template <typename... Targs>
T* SampleRecorder<T>::Register(Targs&&... args) {
- int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
+ size_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
if (size > max_samples_.load(std::memory_order_relaxed)) {
size_estimate_.fetch_sub(1, std::memory_order_relaxed);
dropped_samples_.fetch_add(1, std::memory_order_relaxed);
@@ -199,6 +199,14 @@ T* SampleRecorder<T>::Register(Targs&&... args) {
sample = new T();
{
absl::MutexLock sample_lock(&sample->init_mu);
+ // If flag initialization happens to occur (perhaps in another thread)
+ // while in this block, it will lock `graveyard_` which is usually always
+ // locked before any sample. This will appear as a lock inversion.
+ // However, this code is run exactly once per sample, and this sample
+ // cannot be accessed until after it is returned from this method. This
+ // means that this lock state can never be recreated, so we can safely
+ // inform the deadlock detector to ignore it.
+ sample->init_mu.ForgetDeadlockInfo();
sample->PrepareForSampling(std::forward<Targs>(args)...);
}
PushNew(sample);
@@ -229,12 +237,12 @@ int64_t SampleRecorder<T>::Iterate(
}
template <typename T>
-void SampleRecorder<T>::SetMaxSamples(int32_t max) {
+void SampleRecorder<T>::SetMaxSamples(size_t max) {
max_samples_.store(max, std::memory_order_release);
}
template <typename T>
-int32_t SampleRecorder<T>::GetMaxSamples() const {
+size_t SampleRecorder<T>::GetMaxSamples() const {
return max_samples_.load(std::memory_order_acquire);
}
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/fast_uniform_bits.h b/contrib/restricted/abseil-cpp/absl/random/internal/fast_uniform_bits.h
index f3a5c00f39..8d8ed04515 100644
--- a/contrib/restricted/abseil-cpp/absl/random/internal/fast_uniform_bits.h
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/fast_uniform_bits.h
@@ -151,7 +151,8 @@ FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
result_type r = static_cast<result_type>(g() - kMin);
for (size_t n = 1; n < kIters; ++n) {
- r = (r << kShift) + static_cast<result_type>(g() - kMin);
+ r = static_cast<result_type>(r << kShift) +
+ static_cast<result_type>(g() - kMin);
}
return r;
}
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/pool_urbg.cc b/contrib/restricted/abseil-cpp/absl/random/internal/pool_urbg.cc
index 725100a415..5aefa7d97b 100644
--- a/contrib/restricted/abseil-cpp/absl/random/internal/pool_urbg.cc
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/pool_urbg.cc
@@ -131,7 +131,7 @@ void RandenPoolEntry::Fill(uint8_t* out, size_t bytes) {
}
// Number of pooled urbg entries.
-static constexpr int kPoolSize = 8;
+static constexpr size_t kPoolSize = 8;
// Shared pool entries.
static absl::once_flag pool_once;
@@ -147,15 +147,15 @@ ABSL_CACHELINE_ALIGNED static RandenPoolEntry* shared_pools[kPoolSize];
// on subsequent runs the order within the same program may be significantly
// different. However, as other thread IDs are not assigned sequentially,
// this is not expected to matter.
-int GetPoolID() {
+size_t GetPoolID() {
static_assert(kPoolSize >= 1,
"At least one urbg instance is required for PoolURBG");
- ABSL_CONST_INIT static std::atomic<int64_t> sequence{0};
+ ABSL_CONST_INIT static std::atomic<uint64_t> sequence{0};
#ifdef ABSL_HAVE_THREAD_LOCAL
- static thread_local int my_pool_id = -1;
- if (ABSL_PREDICT_FALSE(my_pool_id < 0)) {
+ static thread_local size_t my_pool_id = kPoolSize;
+ if (ABSL_PREDICT_FALSE(my_pool_id == kPoolSize)) {
my_pool_id = (sequence++ % kPoolSize);
}
return my_pool_id;
@@ -171,8 +171,8 @@ int GetPoolID() {
// Store the value in the pthread_{get/set}specific. However an uninitialized
// value is 0, so add +1 to distinguish from the null value.
- intptr_t my_pool_id =
- reinterpret_cast<intptr_t>(pthread_getspecific(tid_key));
+ uintptr_t my_pool_id =
+ reinterpret_cast<uintptr_t>(pthread_getspecific(tid_key));
if (ABSL_PREDICT_FALSE(my_pool_id == 0)) {
// No allocated ID, allocate the next value, cache it, and return.
my_pool_id = (sequence++ % kPoolSize) + 1;
@@ -194,7 +194,7 @@ RandenPoolEntry* PoolAlignedAlloc() {
// Not all the platforms that we build for have std::aligned_alloc, however
// since we never free these objects, we can over allocate and munge the
// pointers to the correct alignment.
- intptr_t x = reinterpret_cast<intptr_t>(
+ uintptr_t x = reinterpret_cast<uintptr_t>(
new char[sizeof(RandenPoolEntry) + kAlignment]);
auto y = x % kAlignment;
void* aligned = reinterpret_cast<void*>(y == 0 ? x : (x + kAlignment - y));
@@ -215,7 +215,7 @@ void InitPoolURBG() {
absl::MakeSpan(seed_material))) {
random_internal::ThrowSeedGenException();
}
- for (int i = 0; i < kPoolSize; i++) {
+ for (size_t i = 0; i < kPoolSize; i++) {
shared_pools[i] = PoolAlignedAlloc();
shared_pools[i]->Init(
absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize));
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/seed_material.cc b/contrib/restricted/abseil-cpp/absl/random/internal/seed_material.cc
index c03cad8502..1041302b58 100644
--- a/contrib/restricted/abseil-cpp/absl/random/internal/seed_material.cc
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/seed_material.cc
@@ -173,12 +173,12 @@ bool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {
}
while (success && buffer_size > 0) {
- int bytes_read = read(dev_urandom, buffer, buffer_size);
+ ssize_t bytes_read = read(dev_urandom, buffer, buffer_size);
int read_error = errno;
success = (bytes_read > 0);
if (success) {
buffer += bytes_read;
- buffer_size -= bytes_read;
+ buffer_size -= static_cast<size_t>(bytes_read);
} else if (bytes_read == -1 && read_error == EINTR) {
success = true; // Need to try again.
}
diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h
index 19a4a7aaa0..873eb5c245 100644
--- a/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_internal.h
@@ -14,6 +14,7 @@
#ifndef ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+#include <memory>
#include <string>
#include <utility>
diff --git a/contrib/restricted/abseil-cpp/absl/status/status.cc b/contrib/restricted/abseil-cpp/absl/status/status.cc
index 88e8eda97d..160eb41783 100644
--- a/contrib/restricted/abseil-cpp/absl/status/status.cc
+++ b/contrib/restricted/abseil-cpp/absl/status/status.cc
@@ -16,9 +16,11 @@
#include <errno.h>
#include <cassert>
+#include <utility>
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/strerror.h"
+#include "absl/base/macros.h"
#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
#include "absl/status/status_payload_printer.h"
@@ -77,15 +79,17 @@ std::ostream& operator<<(std::ostream& os, StatusCode code) {
namespace status_internal {
-static int FindPayloadIndexByUrl(const Payloads* payloads,
- absl::string_view type_url) {
- if (payloads == nullptr) return -1;
+static absl::optional<size_t> FindPayloadIndexByUrl(
+ const Payloads* payloads,
+ absl::string_view type_url) {
+ if (payloads == nullptr)
+ return absl::nullopt;
for (size_t i = 0; i < payloads->size(); ++i) {
if ((*payloads)[i].type_url == type_url) return i;
}
- return -1;
+ return absl::nullopt;
}
// Convert canonical code to a value known to this binary.
@@ -119,8 +123,10 @@ absl::StatusCode MapToLocalCode(int value) {
absl::optional<absl::Cord> Status::GetPayload(
absl::string_view type_url) const {
const auto* payloads = GetPayloads();
- int index = status_internal::FindPayloadIndexByUrl(payloads, type_url);
- if (index != -1) return (*payloads)[index].payload;
+ absl::optional<size_t> index =
+ status_internal::FindPayloadIndexByUrl(payloads, type_url);
+ if (index.has_value())
+ return (*payloads)[index.value()].payload;
return absl::nullopt;
}
@@ -135,10 +141,10 @@ void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {
rep->payloads = absl::make_unique<status_internal::Payloads>();
}
- int index =
+ absl::optional<size_t> index =
status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url);
- if (index != -1) {
- (*rep->payloads)[index].payload = std::move(payload);
+ if (index.has_value()) {
+ (*rep->payloads)[index.value()].payload = std::move(payload);
return;
}
@@ -146,10 +152,11 @@ void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {
}
bool Status::ErasePayload(absl::string_view type_url) {
- int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
- if (index != -1) {
+ absl::optional<size_t> index =
+ status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
+ if (index.has_value()) {
PrepareToModify();
- GetPayloads()->erase(GetPayloads()->begin() + index);
+ GetPayloads()->erase(GetPayloads()->begin() + index.value());
if (GetPayloads()->empty() && message().empty()) {
// Special case: If this can be represented inlined, it MUST be
// inlined (EqualsSlow depends on this behavior).
diff --git a/contrib/restricted/abseil-cpp/absl/status/status.h b/contrib/restricted/abseil-cpp/absl/status/status.h
index 9292b83a05..4e8292fc0e 100644
--- a/contrib/restricted/abseil-cpp/absl/status/status.h
+++ b/contrib/restricted/abseil-cpp/absl/status/status.h
@@ -51,10 +51,10 @@
#ifndef ABSL_STATUS_STATUS_H_
#define ABSL_STATUS_STATUS_H_
-#include <iostream>
+#include <ostream>
#include <string>
+#include <utility>
-#include "absl/container/inlined_vector.h"
#include "absl/functional/function_ref.h"
#include "absl/status/internal/status_internal.h"
#include "absl/strings/cord.h"
diff --git a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.darwin.txt b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.darwin.txt
index 574ead4171..e3aa400b95 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.darwin.txt
+++ b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.darwin.txt
@@ -20,6 +20,14 @@ target_link_libraries(abseil-cpp-absl-strings PUBLIC
abseil-cpp-absl-numeric
)
target_sources(abseil-cpp-absl-strings PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/status/statusor.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
@@ -40,6 +48,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -49,6 +58,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/match.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
diff --git a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux-aarch64.txt b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux-aarch64.txt
index 142fd5fd9c..2da01ab774 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux-aarch64.txt
+++ b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux-aarch64.txt
@@ -21,6 +21,14 @@ target_link_libraries(abseil-cpp-absl-strings PUBLIC
abseil-cpp-absl-numeric
)
target_sources(abseil-cpp-absl-strings PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/status/statusor.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
@@ -41,6 +49,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -50,6 +59,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/match.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
diff --git a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux.txt b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux.txt
index 142fd5fd9c..2da01ab774 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux.txt
+++ b/contrib/restricted/abseil-cpp/absl/strings/CMakeLists.linux.txt
@@ -21,6 +21,14 @@ target_link_libraries(abseil-cpp-absl-strings PUBLIC
abseil-cpp-absl-numeric
)
target_sources(abseil-cpp-absl-strings PRIVATE
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/crc32c.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/cpu_detect.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_cord_state.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_fallback.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_memcpy_x86_64.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_non_temporal_memcpy.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/crc/internal/crc_x86_arm_combined.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/status/statusor.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
@@ -41,6 +49,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -50,6 +59,7 @@ target_sources(abseil-cpp-absl-strings PRIVATE
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/output.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
+ ${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/internal/utf8.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/match.cc
${CMAKE_SOURCE_DIR}/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
diff --git a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
index 93bb03e958..868df2d102 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/ascii.cc
@@ -157,13 +157,13 @@ ABSL_DLL const char kToUpper[256] = {
void AsciiStrToLower(std::string* s) {
for (auto& ch : *s) {
- ch = absl::ascii_tolower(ch);
+ ch = absl::ascii_tolower(static_cast<unsigned char>(ch));
}
}
void AsciiStrToUpper(std::string* s) {
for (auto& ch : *s) {
- ch = absl::ascii_toupper(ch);
+ ch = absl::ascii_toupper(static_cast<unsigned char>(ch));
}
}
@@ -183,17 +183,17 @@ void RemoveExtraAsciiWhitespace(std::string* str) {
for (; input_it < input_end; ++input_it) {
if (is_ws) {
// Consecutive whitespace? Keep only the last.
- is_ws = absl::ascii_isspace(*input_it);
+ is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));
if (is_ws) --output_it;
} else {
- is_ws = absl::ascii_isspace(*input_it);
+ is_ws = absl::ascii_isspace(static_cast<unsigned char>(*input_it));
}
*output_it = *input_it;
++output_it;
}
- str->erase(output_it - &(*str)[0]);
+ str->erase(static_cast<size_t>(output_it - &(*str)[0]));
}
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
index fefcfc90a5..69d420bcea 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/charconv.cc
@@ -18,6 +18,7 @@
#include <cassert>
#include <cmath>
#include <cstring>
+#include <limits>
#include "absl/base/casts.h"
#include "absl/numeric/bits.h"
@@ -65,6 +66,14 @@ struct FloatTraits;
template <>
struct FloatTraits<double> {
+ using mantissa_t = uint64_t;
+
+ // The number of bits in the given float type.
+ static constexpr int kTargetBits = 64;
+
+ // The number of exponent bits in the given float type.
+ static constexpr int kTargetExponentBits = 11;
+
// The number of mantissa bits in the given float type. This includes the
// implied high bit.
static constexpr int kTargetMantissaBits = 53;
@@ -83,6 +92,31 @@ struct FloatTraits<double> {
// m * 2**kMinNormalExponent is exactly equal to DBL_MIN.
static constexpr int kMinNormalExponent = -1074;
+ // The IEEE exponent bias. It equals ((1 << (kTargetExponentBits - 1)) - 1).
+ static constexpr int kExponentBias = 1023;
+
+ // The Eisel-Lemire "Shifting to 54/25 Bits" adjustment. It equals (63 - 1 -
+ // kTargetMantissaBits).
+ static constexpr int kEiselLemireShift = 9;
+
+ // The Eisel-Lemire high64_mask. It equals ((1 << kEiselLemireShift) - 1).
+ static constexpr uint64_t kEiselLemireMask = uint64_t{0x1FF};
+
+ // The smallest negative integer N (smallest negative means furthest from
+ // zero) such that parsing 9999999999999999999eN, with 19 nines, is still
+ // positive. Parsing a smaller (more negative) N will produce zero.
+ //
+ // Adjusting the decimal point and exponent, without adjusting the value,
+ // 9999999999999999999eN equals 9.999999999999999999eM where M = N + 18.
+ //
+ // 9999999999999999999, with 19 nines but no decimal point, is the largest
+ // "repeated nines" integer that fits in a uint64_t.
+ static constexpr int kEiselLemireMinInclusiveExp10 = -324 - 18;
+
+ // The smallest positive integer N such that parsing 1eN produces infinity.
+ // Parsing a smaller N will produce something finite.
+ static constexpr int kEiselLemireMaxExclusiveExp10 = 309;
+
static double MakeNan(const char* tagp) {
// Support nan no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
@@ -103,7 +137,7 @@ struct FloatTraits<double> {
// a normal value is made, or it must be less narrow than that, in which case
// `exponent` must be exactly kMinNormalExponent, and a subnormal value is
// made.
- static double Make(uint64_t mantissa, int exponent, bool sign) {
+ static double Make(mantissa_t mantissa, int exponent, bool sign) {
#ifndef ABSL_BIT_PACK_FLOATS
// Support ldexp no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
@@ -116,8 +150,10 @@ struct FloatTraits<double> {
if (mantissa > kMantissaMask) {
// Normal value.
// Adjust by 1023 for the exponent representation bias, and an additional
- // 52 due to the implied decimal point in the IEEE mantissa represenation.
- dbl += uint64_t{exponent + 1023u + kTargetMantissaBits - 1} << 52;
+ // 52 due to the implied decimal point in the IEEE mantissa
+ // representation.
+ dbl += static_cast<uint64_t>(exponent + 1023 + kTargetMantissaBits - 1)
+ << 52;
mantissa &= kMantissaMask;
} else {
// subnormal value
@@ -134,16 +170,27 @@ struct FloatTraits<double> {
// members and methods.
template <>
struct FloatTraits<float> {
+ using mantissa_t = uint32_t;
+
+ static constexpr int kTargetBits = 32;
+ static constexpr int kTargetExponentBits = 8;
static constexpr int kTargetMantissaBits = 24;
static constexpr int kMaxExponent = 104;
static constexpr int kMinNormalExponent = -149;
+ static constexpr int kExponentBias = 127;
+ static constexpr int kEiselLemireShift = 38;
+ static constexpr uint64_t kEiselLemireMask = uint64_t{0x3FFFFFFFFF};
+ static constexpr int kEiselLemireMinInclusiveExp10 = -46 - 18;
+ static constexpr int kEiselLemireMaxExclusiveExp10 = 39;
+
static float MakeNan(const char* tagp) {
// Support nanf no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
using namespace std; // NOLINT
return nanf(tagp);
}
- static float Make(uint32_t mantissa, int exponent, bool sign) {
+
+ static float Make(mantissa_t mantissa, int exponent, bool sign) {
#ifndef ABSL_BIT_PACK_FLOATS
// Support ldexpf no matter which namespace it's in. Some platforms
// incorrectly don't put it in namespace std.
@@ -157,7 +204,8 @@ struct FloatTraits<float> {
// Normal value.
// Adjust by 127 for the exponent representation bias, and an additional
// 23 due to the implied decimal point in the IEEE mantissa represenation.
- flt += uint32_t{exponent + 127u + kTargetMantissaBits - 1} << 23;
+ flt += static_cast<uint32_t>(exponent + 127 + kTargetMantissaBits - 1)
+ << 23;
mantissa &= kMantissaMask;
} else {
// subnormal value
@@ -181,39 +229,45 @@ struct FloatTraits<float> {
//
// 2**63 <= Power10Mantissa(n) < 2**64.
//
+// See the "Table of powers of 10" comment below for a "1e60" example.
+//
// Lookups into the power-of-10 table must first check the Power10Overflow() and
// Power10Underflow() functions, to avoid out-of-bounds table access.
//
-// Indexes into these tables are biased by -kPower10TableMin, and the table has
-// values in the range [kPower10TableMin, kPower10TableMax].
-extern const uint64_t kPower10MantissaTable[];
-extern const int16_t kPower10ExponentTable[];
+// Indexes into these tables are biased by -kPower10TableMinInclusive. Valid
+// indexes range from kPower10TableMinInclusive to kPower10TableMaxExclusive.
+extern const uint64_t kPower10MantissaHighTable[]; // High 64 of 128 bits.
+extern const uint64_t kPower10MantissaLowTable[]; // Low 64 of 128 bits.
-// The smallest allowed value for use with the Power10Mantissa() and
-// Power10Exponent() functions below. (If a smaller exponent is needed in
+// The smallest (inclusive) allowed value for use with the Power10Mantissa()
+// and Power10Exponent() functions below. (If a smaller exponent is needed in
// calculations, the end result is guaranteed to underflow.)
-constexpr int kPower10TableMin = -342;
+constexpr int kPower10TableMinInclusive = -342;
-// The largest allowed value for use with the Power10Mantissa() and
-// Power10Exponent() functions below. (If a smaller exponent is needed in
-// calculations, the end result is guaranteed to overflow.)
-constexpr int kPower10TableMax = 308;
+// The largest (exclusive) allowed value for use with the Power10Mantissa() and
+// Power10Exponent() functions below. (If a larger-or-equal exponent is needed
+// in calculations, the end result is guaranteed to overflow.)
+constexpr int kPower10TableMaxExclusive = 309;
uint64_t Power10Mantissa(int n) {
- return kPower10MantissaTable[n - kPower10TableMin];
+ return kPower10MantissaHighTable[n - kPower10TableMinInclusive];
}
int Power10Exponent(int n) {
- return kPower10ExponentTable[n - kPower10TableMin];
+ // The 217706 etc magic numbers encode the results as a formula instead of a
+ // table. Their equivalence (over the kPower10TableMinInclusive ..
+ // kPower10TableMaxExclusive range) is confirmed by
+ // https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go
+ return (217706 * n >> 16) - 63;
}
// Returns true if n is large enough that 10**n always results in an IEEE
// overflow.
-bool Power10Overflow(int n) { return n > kPower10TableMax; }
+bool Power10Overflow(int n) { return n >= kPower10TableMaxExclusive; }
// Returns true if n is small enough that 10**n times a ParsedFloat mantissa
// always results in an IEEE underflow.
-bool Power10Underflow(int n) { return n < kPower10TableMin; }
+bool Power10Underflow(int n) { return n < kPower10TableMinInclusive; }
// Returns true if Power10Mantissa(n) * 2**Power10Exponent(n) is exactly equal
// to 10**n numerically. Put another way, this returns true if there is no
@@ -242,9 +296,11 @@ struct CalculatedFloat {
// Returns the bit width of the given uint128. (Equivalently, returns 128
// minus the number of leading zero bits.)
-unsigned BitWidth(uint128 value) {
+int BitWidth(uint128 value) {
if (Uint128High64(value) == 0) {
- return static_cast<unsigned>(bit_width(Uint128Low64(value)));
+ // This static_cast is only needed when using a std::bit_width()
+ // implementation that does not have the fix for LWG 3656 applied.
+ return static_cast<int>(bit_width(Uint128Low64(value)));
}
return 128 - countl_zero(Uint128High64(value));
}
@@ -285,14 +341,19 @@ template <typename FloatType>
bool HandleEdgeCase(const strings_internal::ParsedFloat& input, bool negative,
FloatType* value) {
if (input.type == strings_internal::FloatType::kNan) {
- // A bug in both clang and gcc would cause the compiler to optimize away the
- // buffer we are building below. Declaring the buffer volatile avoids the
- // issue, and has no measurable performance impact in microbenchmarks.
+ // A bug in both clang < 7 and gcc would cause the compiler to optimize
+ // away the buffer we are building below. Declaring the buffer volatile
+ // avoids the issue, and has no measurable performance impact in
+ // microbenchmarks.
//
// https://bugs.llvm.org/show_bug.cgi?id=37778
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86113
constexpr ptrdiff_t kNanBufferSize = 128;
+#if defined(__GNUC__) || (defined(__clang__) && __clang_major__ < 7)
volatile char n_char_sequence[kNanBufferSize];
+#else
+ char n_char_sequence[kNanBufferSize];
+#endif
if (input.subrange_begin == nullptr) {
n_char_sequence[0] = '\0';
} else {
@@ -337,8 +398,10 @@ void EncodeResult(const CalculatedFloat& calculated, bool negative,
*value = negative ? -0.0 : 0.0;
return;
}
- *value = FloatTraits<FloatType>::Make(calculated.mantissa,
- calculated.exponent, negative);
+ *value = FloatTraits<FloatType>::Make(
+ static_cast<typename FloatTraits<FloatType>::mantissa_t>(
+ calculated.mantissa),
+ calculated.exponent, negative);
}
// Returns the given uint128 shifted to the right by `shift` bits, and rounds
@@ -519,7 +582,9 @@ CalculatedFloat CalculateFromParsedHexadecimal(
const strings_internal::ParsedFloat& parsed_hex) {
uint64_t mantissa = parsed_hex.mantissa;
int exponent = parsed_hex.exponent;
- auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
+ // This static_cast is only needed when using a std::bit_width()
+ // implementation that does not have the fix for LWG 3656 applied.
+ int mantissa_width = static_cast<int>(bit_width(mantissa));
const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
bool result_exact;
exponent += shift;
@@ -595,6 +660,185 @@ CalculatedFloat CalculateFromParsedDecimal(
binary_exponent);
}
+// As discussed in https://nigeltao.github.io/blog/2020/eisel-lemire.html the
+// primary goal of the Eisel-Lemire algorithm is speed, for 99+% of the cases,
+// not 100% coverage. As long as Eisel-Lemire doesn’t claim false positives,
+// the combined approach (falling back to an alternative implementation when
+// this function returns false) is both fast and correct.
+template <typename FloatType>
+bool EiselLemire(const strings_internal::ParsedFloat& input, bool negative,
+ FloatType* value, std::errc* ec) {
+ uint64_t man = input.mantissa;
+ int exp10 = input.exponent;
+ if (exp10 < FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10) {
+ *value = negative ? -0.0 : 0.0;
+ *ec = std::errc::result_out_of_range;
+ return true;
+ } else if (exp10 >= FloatTraits<FloatType>::kEiselLemireMaxExclusiveExp10) {
+ // Return max (a finite value) consistent with from_chars and DR 3081. For
+ // SimpleAtod and SimpleAtof, post-processing will return infinity.
+ *value = negative ? -std::numeric_limits<FloatType>::max()
+ : std::numeric_limits<FloatType>::max();
+ *ec = std::errc::result_out_of_range;
+ return true;
+ }
+
+ // Assert kPower10TableMinInclusive <= exp10 < kPower10TableMaxExclusive.
+ // Equivalently, !Power10Underflow(exp10) and !Power10Overflow(exp10).
+ static_assert(
+ FloatTraits<FloatType>::kEiselLemireMinInclusiveExp10 >=
+ kPower10TableMinInclusive,
+ "(exp10-kPower10TableMinInclusive) in kPower10MantissaHighTable bounds");
+ static_assert(
+ FloatTraits<FloatType>::kEiselLemireMaxExclusiveExp10 <=
+ kPower10TableMaxExclusive,
+ "(exp10-kPower10TableMinInclusive) in kPower10MantissaHighTable bounds");
+
+ // The terse (+) comments in this function body refer to sections of the
+ // https://nigeltao.github.io/blog/2020/eisel-lemire.html blog post.
+ //
+ // That blog post discusses double precision (11 exponent bits with a -1023
+ // bias, 52 mantissa bits), but the same approach applies to single precision
+ // (8 exponent bits with a -127 bias, 23 mantissa bits). Either way, the
+ // computation here happens with 64-bit values (e.g. man) or 128-bit values
+ // (e.g. x) before finally converting to 64- or 32-bit floating point.
+ //
+ // See also "Number Parsing at a Gigabyte per Second, Software: Practice and
+ // Experience 51 (8), 2021" (https://arxiv.org/abs/2101.11408) for detail.
+
+ // (+) Normalization.
+ int clz = countl_zero(man);
+ man <<= static_cast<unsigned int>(clz);
+ // The 217706 etc magic numbers are from the Power10Exponent function.
+ uint64_t ret_exp2 =
+ static_cast<uint64_t>((217706 * exp10 >> 16) + 64 +
+ FloatTraits<FloatType>::kExponentBias - clz);
+
+ // (+) Multiplication.
+ uint128 x = static_cast<uint128>(man) *
+ static_cast<uint128>(
+ kPower10MantissaHighTable[exp10 - kPower10TableMinInclusive]);
+
+ // (+) Wider Approximation.
+ static constexpr uint64_t high64_mask =
+ FloatTraits<FloatType>::kEiselLemireMask;
+ if (((Uint128High64(x) & high64_mask) == high64_mask) &&
+ (man > (std::numeric_limits<uint64_t>::max() - Uint128Low64(x)))) {
+ uint128 y =
+ static_cast<uint128>(man) *
+ static_cast<uint128>(
+ kPower10MantissaLowTable[exp10 - kPower10TableMinInclusive]);
+ x += Uint128High64(y);
+ // For example, parsing "4503599627370497.5" will take the if-true
+ // branch here (for double precision), since:
+ // - x = 0x8000000000000BFF_FFFFFFFFFFFFFFFF
+ // - y = 0x8000000000000BFF_7FFFFFFFFFFFF400
+ // - man = 0xA000000000000F00
+ // Likewise, when parsing "0.0625" for single precision:
+ // - x = 0x7FFFFFFFFFFFFFFF_FFFFFFFFFFFFFFFF
+ // - y = 0x813FFFFFFFFFFFFF_8A00000000000000
+ // - man = 0x9C40000000000000
+ if (((Uint128High64(x) & high64_mask) == high64_mask) &&
+ ((Uint128Low64(x) + 1) == 0) &&
+ (man > (std::numeric_limits<uint64_t>::max() - Uint128Low64(y)))) {
+ return false;
+ }
+ }
+
+ // (+) Shifting to 54 Bits (or for single precision, to 25 bits).
+ uint64_t msb = Uint128High64(x) >> 63;
+ uint64_t ret_man =
+ Uint128High64(x) >> (msb + FloatTraits<FloatType>::kEiselLemireShift);
+ ret_exp2 -= 1 ^ msb;
+
+ // (+) Half-way Ambiguity.
+ //
+ // For example, parsing "1e+23" will take the if-true branch here (for double
+ // precision), since:
+ // - x = 0x54B40B1F852BDA00_0000000000000000
+ // - ret_man = 0x002A5A058FC295ED
+ // Likewise, when parsing "20040229.0" for single precision:
+ // - x = 0x4C72894000000000_0000000000000000
+ // - ret_man = 0x000000000131CA25
+ if ((Uint128Low64(x) == 0) && ((Uint128High64(x) & high64_mask) == 0) &&
+ ((ret_man & 3) == 1)) {
+ return false;
+ }
+
+ // (+) From 54 to 53 Bits (or for single precision, from 25 to 24 bits).
+ ret_man += ret_man & 1; // Line From54a.
+ ret_man >>= 1; // Line From54b.
+ // Incrementing ret_man (at line From54a) may have overflowed 54 bits (53
+ // bits after the right shift by 1 at line From54b), so adjust for that.
+ //
+ // For example, parsing "9223372036854775807" will take the if-true branch
+ // here (for double precision), since:
+ // - ret_man = 0x0020000000000000 = (1 << 53)
+ // Likewise, when parsing "2147483647.0" for single precision:
+ // - ret_man = 0x0000000001000000 = (1 << 24)
+ if ((ret_man >> FloatTraits<FloatType>::kTargetMantissaBits) > 0) {
+ ret_exp2 += 1;
+ // Conceptually, we need a "ret_man >>= 1" in this if-block to balance
+ // incrementing ret_exp2 in the line immediately above. However, we only
+ // get here when line From54a overflowed (after adding a 1), so ret_man
+ // here is (1 << 53). Its low 53 bits are therefore all zeroes. The only
+ // remaining use of ret_man is to mask it with ((1 << 52) - 1), so only its
+ // low 52 bits matter. A "ret_man >>= 1" would have no effect in practice.
+ //
+ // We omit the "ret_man >>= 1", even if it is cheap (and this if-branch is
+ // rarely taken) and technically 'more correct', so that mutation tests
+ // that would otherwise modify or omit that "ret_man >>= 1" don't complain
+ // that such code mutations have no observable effect.
+ }
+
+ // ret_exp2 is a uint64_t. Zero or underflow means that we're in subnormal
+ // space. max_exp2 (0x7FF for double precision, 0xFF for single precision) or
+ // above means that we're in Inf/NaN space.
+ //
+ // The if block is equivalent to (but has fewer branches than):
+ // if ((ret_exp2 <= 0) || (ret_exp2 >= max_exp2)) { etc }
+ //
+ // For example, parsing "4.9406564584124654e-324" will take the if-true
+ // branch here, since ret_exp2 = -51.
+ static constexpr uint64_t max_exp2 =
+ (1 << FloatTraits<FloatType>::kTargetExponentBits) - 1;
+ if ((ret_exp2 - 1) >= (max_exp2 - 1)) {
+ return false;
+ }
+
+#ifndef ABSL_BIT_PACK_FLOATS
+ if (FloatTraits<FloatType>::kTargetBits == 64) {
+ *value = FloatTraits<FloatType>::Make(
+ (ret_man & 0x000FFFFFFFFFFFFFu) | 0x0010000000000000u,
+ static_cast<int>(ret_exp2) - 1023 - 52, negative);
+ return true;
+ } else if (FloatTraits<FloatType>::kTargetBits == 32) {
+ *value = FloatTraits<FloatType>::Make(
+ (static_cast<uint32_t>(ret_man) & 0x007FFFFFu) | 0x00800000u,
+ static_cast<int>(ret_exp2) - 127 - 23, negative);
+ return true;
+ }
+#else
+ if (FloatTraits<FloatType>::kTargetBits == 64) {
+ uint64_t ret_bits = (ret_exp2 << 52) | (ret_man & 0x000FFFFFFFFFFFFFu);
+ if (negative) {
+ ret_bits |= 0x8000000000000000u;
+ }
+ *value = absl::bit_cast<double>(ret_bits);
+ return true;
+ } else if (FloatTraits<FloatType>::kTargetBits == 32) {
+ uint32_t ret_bits = (static_cast<uint32_t>(ret_exp2) << 23) |
+ (static_cast<uint32_t>(ret_man) & 0x007FFFFFu);
+ if (negative) {
+ ret_bits |= 0x80000000u;
+ }
+ *value = absl::bit_cast<float>(ret_bits);
+ return true;
+ }
+#endif // ABSL_BIT_PACK_FLOATS
+ return false;
+}
+
template <typename FloatType>
from_chars_result FromCharsImpl(const char* first, const char* last,
FloatType& value, chars_format fmt_flags) {
@@ -668,6 +912,12 @@ from_chars_result FromCharsImpl(const char* first, const char* last,
if (HandleEdgeCase(decimal_parse, negative, &value)) {
return result;
}
+ // A nullptr subrange_begin means that the decimal_parse.mantissa is exact
+ // (not truncated), a precondition of the Eisel-Lemire algorithm.
+ if ((decimal_parse.subrange_begin == nullptr) &&
+ EiselLemire<FloatType>(decimal_parse, negative, &value, &result.ec)) {
+ return result;
+ }
CalculatedFloat calculated =
CalculateFromParsedDecimal<FloatType>(decimal_parse);
EncodeResult(calculated, negative, &result, &value);
@@ -688,15 +938,46 @@ from_chars_result from_chars(const char* first, const char* last, float& value,
namespace {
-// Table of powers of 10, from kPower10TableMin to kPower10TableMax.
+// Table of powers of 10, from kPower10TableMinInclusive to
+// kPower10TableMaxExclusive.
+//
+// kPower10MantissaHighTable[i - kPower10TableMinInclusive] stores the 64-bit
+// mantissa. The high bit is always on.
+//
+// kPower10MantissaLowTable extends that 64-bit mantissa to 128 bits.
+//
+// Power10Exponent(i) calculates the power-of-two exponent.
+//
+// For a number i, this gives the unique mantissaHigh and exponent such that
+// (mantissaHigh * 2**exponent) <= 10**i < ((mantissaHigh + 1) * 2**exponent).
+//
+// For example, Python can confirm that the exact hexadecimal value of 1e60 is:
+// >>> a = 1000000000000000000000000000000000000000000000000000000000000
+// >>> hex(a)
+// '0x9f4f2726179a224501d762422c946590d91000000000000000'
+// Adding underscores at every 8th hex digit shows 50 hex digits:
+// '0x9f4f2726_179a2245_01d76242_2c946590_d9100000_00000000_00'.
+// In this case, the high bit of the first hex digit, 9, is coincidentally set,
+// so we do not have to do further shifting to deduce the 128-bit mantissa:
+// - kPower10MantissaHighTable[60 - kP10TMI] = 0x9f4f2726179a2245U
+// - kPower10MantissaLowTable[ 60 - kP10TMI] = 0x01d762422c946590U
+// where kP10TMI is kPower10TableMinInclusive. The low 18 of those 50 hex
+// digits are truncated.
+//
+// 50 hex digits (with the high bit set) is 200 bits and mantissaHigh holds 64
+// bits, so Power10Exponent(60) = 200 - 64 = 136. Again, Python can confirm:
+// >>> b = 0x9f4f2726179a2245
+// >>> ((b+0)<<136) <= a
+// True
+// >>> ((b+1)<<136) <= a
+// False
//
-// kPower10MantissaTable[i - kPower10TableMin] stores the 64-bit mantissa (high
-// bit always on), and kPower10ExponentTable[i - kPower10TableMin] stores the
-// power-of-two exponent. For a given number i, this gives the unique mantissa
-// and exponent such that mantissa * 2**exponent <= 10**i < (mantissa + 1) *
-// 2**exponent.
+// The tables were generated by
+// https://github.com/google/wuffs/blob/315b2e52625ebd7b02d8fac13e3cd85ea374fb80/script/print-mpb-powers-of-10.go
+// after re-formatting its output into two arrays of N uint64_t values (instead
+// of an N element array of uint64_t pairs).
-const uint64_t kPower10MantissaTable[] = {
+const uint64_t kPower10MantissaHighTable[] = {
0xeef453d6923bd65aU, 0x9558b4661b6565f8U, 0xbaaee17fa23ebf76U,
0xe95a99df8ace6f53U, 0x91d8a02bb6c10594U, 0xb64ec836a47146f9U,
0xe3e27a444d8d98b7U, 0x8e6d8c6ab0787f72U, 0xb208ef855c969f4fU,
@@ -916,67 +1197,224 @@ const uint64_t kPower10MantissaTable[] = {
0xb6472e511c81471dU, 0xe3d8f9e563a198e5U, 0x8e679c2f5e44ff8fU,
};
-const int16_t kPower10ExponentTable[] = {
- -1200, -1196, -1193, -1190, -1186, -1183, -1180, -1176, -1173, -1170, -1166,
- -1163, -1160, -1156, -1153, -1150, -1146, -1143, -1140, -1136, -1133, -1130,
- -1127, -1123, -1120, -1117, -1113, -1110, -1107, -1103, -1100, -1097, -1093,
- -1090, -1087, -1083, -1080, -1077, -1073, -1070, -1067, -1063, -1060, -1057,
- -1053, -1050, -1047, -1043, -1040, -1037, -1034, -1030, -1027, -1024, -1020,
- -1017, -1014, -1010, -1007, -1004, -1000, -997, -994, -990, -987, -984,
- -980, -977, -974, -970, -967, -964, -960, -957, -954, -950, -947,
- -944, -940, -937, -934, -931, -927, -924, -921, -917, -914, -911,
- -907, -904, -901, -897, -894, -891, -887, -884, -881, -877, -874,
- -871, -867, -864, -861, -857, -854, -851, -847, -844, -841, -838,
- -834, -831, -828, -824, -821, -818, -814, -811, -808, -804, -801,
- -798, -794, -791, -788, -784, -781, -778, -774, -771, -768, -764,
- -761, -758, -754, -751, -748, -744, -741, -738, -735, -731, -728,
- -725, -721, -718, -715, -711, -708, -705, -701, -698, -695, -691,
- -688, -685, -681, -678, -675, -671, -668, -665, -661, -658, -655,
- -651, -648, -645, -642, -638, -635, -632, -628, -625, -622, -618,
- -615, -612, -608, -605, -602, -598, -595, -592, -588, -585, -582,
- -578, -575, -572, -568, -565, -562, -558, -555, -552, -549, -545,
- -542, -539, -535, -532, -529, -525, -522, -519, -515, -512, -509,
- -505, -502, -499, -495, -492, -489, -485, -482, -479, -475, -472,
- -469, -465, -462, -459, -455, -452, -449, -446, -442, -439, -436,
- -432, -429, -426, -422, -419, -416, -412, -409, -406, -402, -399,
- -396, -392, -389, -386, -382, -379, -376, -372, -369, -366, -362,
- -359, -356, -353, -349, -346, -343, -339, -336, -333, -329, -326,
- -323, -319, -316, -313, -309, -306, -303, -299, -296, -293, -289,
- -286, -283, -279, -276, -273, -269, -266, -263, -259, -256, -253,
- -250, -246, -243, -240, -236, -233, -230, -226, -223, -220, -216,
- -213, -210, -206, -203, -200, -196, -193, -190, -186, -183, -180,
- -176, -173, -170, -166, -163, -160, -157, -153, -150, -147, -143,
- -140, -137, -133, -130, -127, -123, -120, -117, -113, -110, -107,
- -103, -100, -97, -93, -90, -87, -83, -80, -77, -73, -70,
- -67, -63, -60, -57, -54, -50, -47, -44, -40, -37, -34,
- -30, -27, -24, -20, -17, -14, -10, -7, -4, 0, 3,
- 6, 10, 13, 16, 20, 23, 26, 30, 33, 36, 39,
- 43, 46, 49, 53, 56, 59, 63, 66, 69, 73, 76,
- 79, 83, 86, 89, 93, 96, 99, 103, 106, 109, 113,
- 116, 119, 123, 126, 129, 132, 136, 139, 142, 146, 149,
- 152, 156, 159, 162, 166, 169, 172, 176, 179, 182, 186,
- 189, 192, 196, 199, 202, 206, 209, 212, 216, 219, 222,
- 226, 229, 232, 235, 239, 242, 245, 249, 252, 255, 259,
- 262, 265, 269, 272, 275, 279, 282, 285, 289, 292, 295,
- 299, 302, 305, 309, 312, 315, 319, 322, 325, 328, 332,
- 335, 338, 342, 345, 348, 352, 355, 358, 362, 365, 368,
- 372, 375, 378, 382, 385, 388, 392, 395, 398, 402, 405,
- 408, 412, 415, 418, 422, 425, 428, 431, 435, 438, 441,
- 445, 448, 451, 455, 458, 461, 465, 468, 471, 475, 478,
- 481, 485, 488, 491, 495, 498, 501, 505, 508, 511, 515,
- 518, 521, 524, 528, 531, 534, 538, 541, 544, 548, 551,
- 554, 558, 561, 564, 568, 571, 574, 578, 581, 584, 588,
- 591, 594, 598, 601, 604, 608, 611, 614, 617, 621, 624,
- 627, 631, 634, 637, 641, 644, 647, 651, 654, 657, 661,
- 664, 667, 671, 674, 677, 681, 684, 687, 691, 694, 697,
- 701, 704, 707, 711, 714, 717, 720, 724, 727, 730, 734,
- 737, 740, 744, 747, 750, 754, 757, 760, 764, 767, 770,
- 774, 777, 780, 784, 787, 790, 794, 797, 800, 804, 807,
- 810, 813, 817, 820, 823, 827, 830, 833, 837, 840, 843,
- 847, 850, 853, 857, 860, 863, 867, 870, 873, 877, 880,
- 883, 887, 890, 893, 897, 900, 903, 907, 910, 913, 916,
- 920, 923, 926, 930, 933, 936, 940, 943, 946, 950, 953,
- 956, 960,
+const uint64_t kPower10MantissaLowTable[] = {
+ 0x113faa2906a13b3fU, 0x4ac7ca59a424c507U, 0x5d79bcf00d2df649U,
+ 0xf4d82c2c107973dcU, 0x79071b9b8a4be869U, 0x9748e2826cdee284U,
+ 0xfd1b1b2308169b25U, 0xfe30f0f5e50e20f7U, 0xbdbd2d335e51a935U,
+ 0xad2c788035e61382U, 0x4c3bcb5021afcc31U, 0xdf4abe242a1bbf3dU,
+ 0xd71d6dad34a2af0dU, 0x8672648c40e5ad68U, 0x680efdaf511f18c2U,
+ 0x0212bd1b2566def2U, 0x014bb630f7604b57U, 0x419ea3bd35385e2dU,
+ 0x52064cac828675b9U, 0x7343efebd1940993U, 0x1014ebe6c5f90bf8U,
+ 0xd41a26e077774ef6U, 0x8920b098955522b4U, 0x55b46e5f5d5535b0U,
+ 0xeb2189f734aa831dU, 0xa5e9ec7501d523e4U, 0x47b233c92125366eU,
+ 0x999ec0bb696e840aU, 0xc00670ea43ca250dU, 0x380406926a5e5728U,
+ 0xc605083704f5ecf2U, 0xf7864a44c633682eU, 0x7ab3ee6afbe0211dU,
+ 0x5960ea05bad82964U, 0x6fb92487298e33bdU, 0xa5d3b6d479f8e056U,
+ 0x8f48a4899877186cU, 0x331acdabfe94de87U, 0x9ff0c08b7f1d0b14U,
+ 0x07ecf0ae5ee44dd9U, 0xc9e82cd9f69d6150U, 0xbe311c083a225cd2U,
+ 0x6dbd630a48aaf406U, 0x092cbbccdad5b108U, 0x25bbf56008c58ea5U,
+ 0xaf2af2b80af6f24eU, 0x1af5af660db4aee1U, 0x50d98d9fc890ed4dU,
+ 0xe50ff107bab528a0U, 0x1e53ed49a96272c8U, 0x25e8e89c13bb0f7aU,
+ 0x77b191618c54e9acU, 0xd59df5b9ef6a2417U, 0x4b0573286b44ad1dU,
+ 0x4ee367f9430aec32U, 0x229c41f793cda73fU, 0x6b43527578c1110fU,
+ 0x830a13896b78aaa9U, 0x23cc986bc656d553U, 0x2cbfbe86b7ec8aa8U,
+ 0x7bf7d71432f3d6a9U, 0xdaf5ccd93fb0cc53U, 0xd1b3400f8f9cff68U,
+ 0x23100809b9c21fa1U, 0xabd40a0c2832a78aU, 0x16c90c8f323f516cU,
+ 0xae3da7d97f6792e3U, 0x99cd11cfdf41779cU, 0x40405643d711d583U,
+ 0x482835ea666b2572U, 0xda3243650005eecfU, 0x90bed43e40076a82U,
+ 0x5a7744a6e804a291U, 0x711515d0a205cb36U, 0x0d5a5b44ca873e03U,
+ 0xe858790afe9486c2U, 0x626e974dbe39a872U, 0xfb0a3d212dc8128fU,
+ 0x7ce66634bc9d0b99U, 0x1c1fffc1ebc44e80U, 0xa327ffb266b56220U,
+ 0x4bf1ff9f0062baa8U, 0x6f773fc3603db4a9U, 0xcb550fb4384d21d3U,
+ 0x7e2a53a146606a48U, 0x2eda7444cbfc426dU, 0xfa911155fefb5308U,
+ 0x793555ab7eba27caU, 0x4bc1558b2f3458deU, 0x9eb1aaedfb016f16U,
+ 0x465e15a979c1cadcU, 0x0bfacd89ec191ec9U, 0xcef980ec671f667bU,
+ 0x82b7e12780e7401aU, 0xd1b2ecb8b0908810U, 0x861fa7e6dcb4aa15U,
+ 0x67a791e093e1d49aU, 0xe0c8bb2c5c6d24e0U, 0x58fae9f773886e18U,
+ 0xaf39a475506a899eU, 0x6d8406c952429603U, 0xc8e5087ba6d33b83U,
+ 0xfb1e4a9a90880a64U, 0x5cf2eea09a55067fU, 0xf42faa48c0ea481eU,
+ 0xf13b94daf124da26U, 0x76c53d08d6b70858U, 0x54768c4b0c64ca6eU,
+ 0xa9942f5dcf7dfd09U, 0xd3f93b35435d7c4cU, 0xc47bc5014a1a6dafU,
+ 0x359ab6419ca1091bU, 0xc30163d203c94b62U, 0x79e0de63425dcf1dU,
+ 0x985915fc12f542e4U, 0x3e6f5b7b17b2939dU, 0xa705992ceecf9c42U,
+ 0x50c6ff782a838353U, 0xa4f8bf5635246428U, 0x871b7795e136be99U,
+ 0x28e2557b59846e3fU, 0x331aeada2fe589cfU, 0x3ff0d2c85def7621U,
+ 0x0fed077a756b53a9U, 0xd3e8495912c62894U, 0x64712dd7abbbd95cU,
+ 0xbd8d794d96aacfb3U, 0xecf0d7a0fc5583a0U, 0xf41686c49db57244U,
+ 0x311c2875c522ced5U, 0x7d633293366b828bU, 0xae5dff9c02033197U,
+ 0xd9f57f830283fdfcU, 0xd072df63c324fd7bU, 0x4247cb9e59f71e6dU,
+ 0x52d9be85f074e608U, 0x67902e276c921f8bU, 0x00ba1cd8a3db53b6U,
+ 0x80e8a40eccd228a4U, 0x6122cd128006b2cdU, 0x796b805720085f81U,
+ 0xcbe3303674053bb0U, 0xbedbfc4411068a9cU, 0xee92fb5515482d44U,
+ 0x751bdd152d4d1c4aU, 0xd262d45a78a0635dU, 0x86fb897116c87c34U,
+ 0xd45d35e6ae3d4da0U, 0x8974836059cca109U, 0x2bd1a438703fc94bU,
+ 0x7b6306a34627ddcfU, 0x1a3bc84c17b1d542U, 0x20caba5f1d9e4a93U,
+ 0x547eb47b7282ee9cU, 0xe99e619a4f23aa43U, 0x6405fa00e2ec94d4U,
+ 0xde83bc408dd3dd04U, 0x9624ab50b148d445U, 0x3badd624dd9b0957U,
+ 0xe54ca5d70a80e5d6U, 0x5e9fcf4ccd211f4cU, 0x7647c3200069671fU,
+ 0x29ecd9f40041e073U, 0xf468107100525890U, 0x7182148d4066eeb4U,
+ 0xc6f14cd848405530U, 0xb8ada00e5a506a7cU, 0xa6d90811f0e4851cU,
+ 0x908f4a166d1da663U, 0x9a598e4e043287feU, 0x40eff1e1853f29fdU,
+ 0xd12bee59e68ef47cU, 0x82bb74f8301958ceU, 0xe36a52363c1faf01U,
+ 0xdc44e6c3cb279ac1U, 0x29ab103a5ef8c0b9U, 0x7415d448f6b6f0e7U,
+ 0x111b495b3464ad21U, 0xcab10dd900beec34U, 0x3d5d514f40eea742U,
+ 0x0cb4a5a3112a5112U, 0x47f0e785eaba72abU, 0x59ed216765690f56U,
+ 0x306869c13ec3532cU, 0x1e414218c73a13fbU, 0xe5d1929ef90898faU,
+ 0xdf45f746b74abf39U, 0x6b8bba8c328eb783U, 0x066ea92f3f326564U,
+ 0xc80a537b0efefebdU, 0xbd06742ce95f5f36U, 0x2c48113823b73704U,
+ 0xf75a15862ca504c5U, 0x9a984d73dbe722fbU, 0xc13e60d0d2e0ebbaU,
+ 0x318df905079926a8U, 0xfdf17746497f7052U, 0xfeb6ea8bedefa633U,
+ 0xfe64a52ee96b8fc0U, 0x3dfdce7aa3c673b0U, 0x06bea10ca65c084eU,
+ 0x486e494fcff30a62U, 0x5a89dba3c3efccfaU, 0xf89629465a75e01cU,
+ 0xf6bbb397f1135823U, 0x746aa07ded582e2cU, 0xa8c2a44eb4571cdcU,
+ 0x92f34d62616ce413U, 0x77b020baf9c81d17U, 0x0ace1474dc1d122eU,
+ 0x0d819992132456baU, 0x10e1fff697ed6c69U, 0xca8d3ffa1ef463c1U,
+ 0xbd308ff8a6b17cb2U, 0xac7cb3f6d05ddbdeU, 0x6bcdf07a423aa96bU,
+ 0x86c16c98d2c953c6U, 0xe871c7bf077ba8b7U, 0x11471cd764ad4972U,
+ 0xd598e40d3dd89bcfU, 0x4aff1d108d4ec2c3U, 0xcedf722a585139baU,
+ 0xc2974eb4ee658828U, 0x733d226229feea32U, 0x0806357d5a3f525fU,
+ 0xca07c2dcb0cf26f7U, 0xfc89b393dd02f0b5U, 0xbbac2078d443ace2U,
+ 0xd54b944b84aa4c0dU, 0x0a9e795e65d4df11U, 0x4d4617b5ff4a16d5U,
+ 0x504bced1bf8e4e45U, 0xe45ec2862f71e1d6U, 0x5d767327bb4e5a4cU,
+ 0x3a6a07f8d510f86fU, 0x890489f70a55368bU, 0x2b45ac74ccea842eU,
+ 0x3b0b8bc90012929dU, 0x09ce6ebb40173744U, 0xcc420a6a101d0515U,
+ 0x9fa946824a12232dU, 0x47939822dc96abf9U, 0x59787e2b93bc56f7U,
+ 0x57eb4edb3c55b65aU, 0xede622920b6b23f1U, 0xe95fab368e45ecedU,
+ 0x11dbcb0218ebb414U, 0xd652bdc29f26a119U, 0x4be76d3346f0495fU,
+ 0x6f70a4400c562ddbU, 0xcb4ccd500f6bb952U, 0x7e2000a41346a7a7U,
+ 0x8ed400668c0c28c8U, 0x728900802f0f32faU, 0x4f2b40a03ad2ffb9U,
+ 0xe2f610c84987bfa8U, 0x0dd9ca7d2df4d7c9U, 0x91503d1c79720dbbU,
+ 0x75a44c6397ce912aU, 0xc986afbe3ee11abaU, 0xfbe85badce996168U,
+ 0xfae27299423fb9c3U, 0xdccd879fc967d41aU, 0x5400e987bbc1c920U,
+ 0x290123e9aab23b68U, 0xf9a0b6720aaf6521U, 0xf808e40e8d5b3e69U,
+ 0xb60b1d1230b20e04U, 0xb1c6f22b5e6f48c2U, 0x1e38aeb6360b1af3U,
+ 0x25c6da63c38de1b0U, 0x579c487e5a38ad0eU, 0x2d835a9df0c6d851U,
+ 0xf8e431456cf88e65U, 0x1b8e9ecb641b58ffU, 0xe272467e3d222f3fU,
+ 0x5b0ed81dcc6abb0fU, 0x98e947129fc2b4e9U, 0x3f2398d747b36224U,
+ 0x8eec7f0d19a03aadU, 0x1953cf68300424acU, 0x5fa8c3423c052dd7U,
+ 0x3792f412cb06794dU, 0xe2bbd88bbee40bd0U, 0x5b6aceaeae9d0ec4U,
+ 0xf245825a5a445275U, 0xeed6e2f0f0d56712U, 0x55464dd69685606bU,
+ 0xaa97e14c3c26b886U, 0xd53dd99f4b3066a8U, 0xe546a8038efe4029U,
+ 0xde98520472bdd033U, 0x963e66858f6d4440U, 0xdde7001379a44aa8U,
+ 0x5560c018580d5d52U, 0xaab8f01e6e10b4a6U, 0xcab3961304ca70e8U,
+ 0x3d607b97c5fd0d22U, 0x8cb89a7db77c506aU, 0x77f3608e92adb242U,
+ 0x55f038b237591ed3U, 0x6b6c46dec52f6688U, 0x2323ac4b3b3da015U,
+ 0xabec975e0a0d081aU, 0x96e7bd358c904a21U, 0x7e50d64177da2e54U,
+ 0xdde50bd1d5d0b9e9U, 0x955e4ec64b44e864U, 0xbd5af13bef0b113eU,
+ 0xecb1ad8aeacdd58eU, 0x67de18eda5814af2U, 0x80eacf948770ced7U,
+ 0xa1258379a94d028dU, 0x096ee45813a04330U, 0x8bca9d6e188853fcU,
+ 0x775ea264cf55347dU, 0x95364afe032a819dU, 0x3a83ddbd83f52204U,
+ 0xc4926a9672793542U, 0x75b7053c0f178293U, 0x5324c68b12dd6338U,
+ 0xd3f6fc16ebca5e03U, 0x88f4bb1ca6bcf584U, 0x2b31e9e3d06c32e5U,
+ 0x3aff322e62439fcfU, 0x09befeb9fad487c2U, 0x4c2ebe687989a9b3U,
+ 0x0f9d37014bf60a10U, 0x538484c19ef38c94U, 0x2865a5f206b06fb9U,
+ 0xf93f87b7442e45d3U, 0xf78f69a51539d748U, 0xb573440e5a884d1bU,
+ 0x31680a88f8953030U, 0xfdc20d2b36ba7c3dU, 0x3d32907604691b4cU,
+ 0xa63f9a49c2c1b10fU, 0x0fcf80dc33721d53U, 0xd3c36113404ea4a8U,
+ 0x645a1cac083126e9U, 0x3d70a3d70a3d70a3U, 0xccccccccccccccccU,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x0000000000000000U, 0x0000000000000000U,
+ 0x0000000000000000U, 0x4000000000000000U, 0x5000000000000000U,
+ 0xa400000000000000U, 0x4d00000000000000U, 0xf020000000000000U,
+ 0x6c28000000000000U, 0xc732000000000000U, 0x3c7f400000000000U,
+ 0x4b9f100000000000U, 0x1e86d40000000000U, 0x1314448000000000U,
+ 0x17d955a000000000U, 0x5dcfab0800000000U, 0x5aa1cae500000000U,
+ 0xf14a3d9e40000000U, 0x6d9ccd05d0000000U, 0xe4820023a2000000U,
+ 0xdda2802c8a800000U, 0xd50b2037ad200000U, 0x4526f422cc340000U,
+ 0x9670b12b7f410000U, 0x3c0cdd765f114000U, 0xa5880a69fb6ac800U,
+ 0x8eea0d047a457a00U, 0x72a4904598d6d880U, 0x47a6da2b7f864750U,
+ 0x999090b65f67d924U, 0xfff4b4e3f741cf6dU, 0xbff8f10e7a8921a4U,
+ 0xaff72d52192b6a0dU, 0x9bf4f8a69f764490U, 0x02f236d04753d5b4U,
+ 0x01d762422c946590U, 0x424d3ad2b7b97ef5U, 0xd2e0898765a7deb2U,
+ 0x63cc55f49f88eb2fU, 0x3cbf6b71c76b25fbU, 0x8bef464e3945ef7aU,
+ 0x97758bf0e3cbb5acU, 0x3d52eeed1cbea317U, 0x4ca7aaa863ee4bddU,
+ 0x8fe8caa93e74ef6aU, 0xb3e2fd538e122b44U, 0x60dbbca87196b616U,
+ 0xbc8955e946fe31cdU, 0x6babab6398bdbe41U, 0xc696963c7eed2dd1U,
+ 0xfc1e1de5cf543ca2U, 0x3b25a55f43294bcbU, 0x49ef0eb713f39ebeU,
+ 0x6e3569326c784337U, 0x49c2c37f07965404U, 0xdc33745ec97be906U,
+ 0x69a028bb3ded71a3U, 0xc40832ea0d68ce0cU, 0xf50a3fa490c30190U,
+ 0x792667c6da79e0faU, 0x577001b891185938U, 0xed4c0226b55e6f86U,
+ 0x544f8158315b05b4U, 0x696361ae3db1c721U, 0x03bc3a19cd1e38e9U,
+ 0x04ab48a04065c723U, 0x62eb0d64283f9c76U, 0x3ba5d0bd324f8394U,
+ 0xca8f44ec7ee36479U, 0x7e998b13cf4e1ecbU, 0x9e3fedd8c321a67eU,
+ 0xc5cfe94ef3ea101eU, 0xbba1f1d158724a12U, 0x2a8a6e45ae8edc97U,
+ 0xf52d09d71a3293bdU, 0x593c2626705f9c56U, 0x6f8b2fb00c77836cU,
+ 0x0b6dfb9c0f956447U, 0x4724bd4189bd5eacU, 0x58edec91ec2cb657U,
+ 0x2f2967b66737e3edU, 0xbd79e0d20082ee74U, 0xecd8590680a3aa11U,
+ 0xe80e6f4820cc9495U, 0x3109058d147fdcddU, 0xbd4b46f0599fd415U,
+ 0x6c9e18ac7007c91aU, 0x03e2cf6bc604ddb0U, 0x84db8346b786151cU,
+ 0xe612641865679a63U, 0x4fcb7e8f3f60c07eU, 0xe3be5e330f38f09dU,
+ 0x5cadf5bfd3072cc5U, 0x73d9732fc7c8f7f6U, 0x2867e7fddcdd9afaU,
+ 0xb281e1fd541501b8U, 0x1f225a7ca91a4226U, 0x3375788de9b06958U,
+ 0x0052d6b1641c83aeU, 0xc0678c5dbd23a49aU, 0xf840b7ba963646e0U,
+ 0xb650e5a93bc3d898U, 0xa3e51f138ab4cebeU, 0xc66f336c36b10137U,
+ 0xb80b0047445d4184U, 0xa60dc059157491e5U, 0x87c89837ad68db2fU,
+ 0x29babe4598c311fbU, 0xf4296dd6fef3d67aU, 0x1899e4a65f58660cU,
+ 0x5ec05dcff72e7f8fU, 0x76707543f4fa1f73U, 0x6a06494a791c53a8U,
+ 0x0487db9d17636892U, 0x45a9d2845d3c42b6U, 0x0b8a2392ba45a9b2U,
+ 0x8e6cac7768d7141eU, 0x3207d795430cd926U, 0x7f44e6bd49e807b8U,
+ 0x5f16206c9c6209a6U, 0x36dba887c37a8c0fU, 0xc2494954da2c9789U,
+ 0xf2db9baa10b7bd6cU, 0x6f92829494e5acc7U, 0xcb772339ba1f17f9U,
+ 0xff2a760414536efbU, 0xfef5138519684abaU, 0x7eb258665fc25d69U,
+ 0xef2f773ffbd97a61U, 0xaafb550ffacfd8faU, 0x95ba2a53f983cf38U,
+ 0xdd945a747bf26183U, 0x94f971119aeef9e4U, 0x7a37cd5601aab85dU,
+ 0xac62e055c10ab33aU, 0x577b986b314d6009U, 0xed5a7e85fda0b80bU,
+ 0x14588f13be847307U, 0x596eb2d8ae258fc8U, 0x6fca5f8ed9aef3bbU,
+ 0x25de7bb9480d5854U, 0xaf561aa79a10ae6aU, 0x1b2ba1518094da04U,
+ 0x90fb44d2f05d0842U, 0x353a1607ac744a53U, 0x42889b8997915ce8U,
+ 0x69956135febada11U, 0x43fab9837e699095U, 0x94f967e45e03f4bbU,
+ 0x1d1be0eebac278f5U, 0x6462d92a69731732U, 0x7d7b8f7503cfdcfeU,
+ 0x5cda735244c3d43eU, 0x3a0888136afa64a7U, 0x088aaa1845b8fdd0U,
+ 0x8aad549e57273d45U, 0x36ac54e2f678864bU, 0x84576a1bb416a7ddU,
+ 0x656d44a2a11c51d5U, 0x9f644ae5a4b1b325U, 0x873d5d9f0dde1feeU,
+ 0xa90cb506d155a7eaU, 0x09a7f12442d588f2U, 0x0c11ed6d538aeb2fU,
+ 0x8f1668c8a86da5faU, 0xf96e017d694487bcU, 0x37c981dcc395a9acU,
+ 0x85bbe253f47b1417U, 0x93956d7478ccec8eU, 0x387ac8d1970027b2U,
+ 0x06997b05fcc0319eU, 0x441fece3bdf81f03U, 0xd527e81cad7626c3U,
+ 0x8a71e223d8d3b074U, 0xf6872d5667844e49U, 0xb428f8ac016561dbU,
+ 0xe13336d701beba52U, 0xecc0024661173473U, 0x27f002d7f95d0190U,
+ 0x31ec038df7b441f4U, 0x7e67047175a15271U, 0x0f0062c6e984d386U,
+ 0x52c07b78a3e60868U, 0xa7709a56ccdf8a82U, 0x88a66076400bb691U,
+ 0x6acff893d00ea435U, 0x0583f6b8c4124d43U, 0xc3727a337a8b704aU,
+ 0x744f18c0592e4c5cU, 0x1162def06f79df73U, 0x8addcb5645ac2ba8U,
+ 0x6d953e2bd7173692U, 0xc8fa8db6ccdd0437U, 0x1d9c9892400a22a2U,
+ 0x2503beb6d00cab4bU, 0x2e44ae64840fd61dU, 0x5ceaecfed289e5d2U,
+ 0x7425a83e872c5f47U, 0xd12f124e28f77719U, 0x82bd6b70d99aaa6fU,
+ 0x636cc64d1001550bU, 0x3c47f7e05401aa4eU, 0x65acfaec34810a71U,
+ 0x7f1839a741a14d0dU, 0x1ede48111209a050U, 0x934aed0aab460432U,
+ 0xf81da84d5617853fU, 0x36251260ab9d668eU, 0xc1d72b7c6b426019U,
+ 0xb24cf65b8612f81fU, 0xdee033f26797b627U, 0x169840ef017da3b1U,
+ 0x8e1f289560ee864eU, 0xf1a6f2bab92a27e2U, 0xae10af696774b1dbU,
+ 0xacca6da1e0a8ef29U, 0x17fd090a58d32af3U, 0xddfc4b4cef07f5b0U,
+ 0x4abdaf101564f98eU, 0x9d6d1ad41abe37f1U, 0x84c86189216dc5edU,
+ 0x32fd3cf5b4e49bb4U, 0x3fbc8c33221dc2a1U, 0x0fabaf3feaa5334aU,
+ 0x29cb4d87f2a7400eU, 0x743e20e9ef511012U, 0x914da9246b255416U,
+ 0x1ad089b6c2f7548eU, 0xa184ac2473b529b1U, 0xc9e5d72d90a2741eU,
+ 0x7e2fa67c7a658892U, 0xddbb901b98feeab7U, 0x552a74227f3ea565U,
+ 0xd53a88958f87275fU, 0x8a892abaf368f137U, 0x2d2b7569b0432d85U,
+ 0x9c3b29620e29fc73U, 0x8349f3ba91b47b8fU, 0x241c70a936219a73U,
+ 0xed238cd383aa0110U, 0xf4363804324a40aaU, 0xb143c6053edcd0d5U,
+ 0xdd94b7868e94050aU, 0xca7cf2b4191c8326U, 0xfd1c2f611f63a3f0U,
+ 0xbc633b39673c8cecU, 0xd5be0503e085d813U, 0x4b2d8644d8a74e18U,
+ 0xddf8e7d60ed1219eU, 0xcabb90e5c942b503U, 0x3d6a751f3b936243U,
+ 0x0cc512670a783ad4U, 0x27fb2b80668b24c5U, 0xb1f9f660802dedf6U,
+ 0x5e7873f8a0396973U, 0xdb0b487b6423e1e8U, 0x91ce1a9a3d2cda62U,
+ 0x7641a140cc7810fbU, 0xa9e904c87fcb0a9dU, 0x546345fa9fbdcd44U,
+ 0xa97c177947ad4095U, 0x49ed8eabcccc485dU, 0x5c68f256bfff5a74U,
+ 0x73832eec6fff3111U, 0xc831fd53c5ff7eabU, 0xba3e7ca8b77f5e55U,
+ 0x28ce1bd2e55f35ebU, 0x7980d163cf5b81b3U, 0xd7e105bcc332621fU,
+ 0x8dd9472bf3fefaa7U, 0xb14f98f6f0feb951U, 0x6ed1bf9a569f33d3U,
+ 0x0a862f80ec4700c8U, 0xcd27bb612758c0faU, 0x8038d51cb897789cU,
+ 0xe0470a63e6bd56c3U, 0x1858ccfce06cac74U, 0x0f37801e0c43ebc8U,
+ 0xd30560258f54e6baU, 0x47c6b82ef32a2069U, 0x4cdc331d57fa5441U,
+ 0xe0133fe4adf8e952U, 0x58180fddd97723a6U, 0x570f09eaa7ea7648U,
};
} // namespace
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.cc b/contrib/restricted/abseil-cpp/absl/strings/cord.cc
index 85a67a0810..1d33dd8317 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord.cc
@@ -20,6 +20,7 @@
#include <cstdio>
#include <cstdlib>
#include <iomanip>
+#include <ios>
#include <iostream>
#include <limits>
#include <ostream>
@@ -34,6 +35,7 @@
#include "absl/base/port.h"
#include "absl/container/fixed_array.h"
#include "absl/container/inlined_vector.h"
+#include "absl/crc/internal/crc_cord_state.h"
#include "absl/strings/cord_buffer.h"
#include "absl/strings/escaping.h"
#include "absl/strings/internal/cord_data_edge.h"
@@ -166,9 +168,7 @@ constexpr unsigned char Cord::InlineRep::kMaxInline;
inline void Cord::InlineRep::set_data(const char* data, size_t n) {
static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
-
- cord_internal::SmallMemmove<true>(data_.as_chars(), data, n);
- set_inline_size(n);
+ data_.set_inline_data(data, n);
}
inline char* Cord::InlineRep::set_data(size_t n) {
@@ -184,7 +184,7 @@ inline void Cord::InlineRep::reduce_size(size_t n) {
assert(tag >= n);
tag -= n;
memset(data_.as_chars() + tag, 0, n);
- set_inline_size(static_cast<char>(tag));
+ set_inline_size(tag);
}
inline void Cord::InlineRep::remove_prefix(size_t n) {
@@ -419,6 +419,7 @@ Cord& Cord::operator=(absl::string_view src) {
// we keep it here to make diffs easier.
void Cord::InlineRep::AppendArray(absl::string_view src,
MethodIdentifier method) {
+ MaybeRemoveEmptyCrcNode();
if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
size_t appended = 0;
@@ -436,8 +437,8 @@ void Cord::InlineRep::AppendArray(absl::string_view src,
size_t inline_length = inline_size();
if (src.size() <= kMaxInline - inline_length) {
// Append new data to embedded array
- memcpy(data_.as_chars() + inline_length, src.data(), src.size());
set_inline_size(inline_length + src.size());
+ memcpy(data_.as_chars() + inline_length, src.data(), src.size());
return;
}
@@ -478,6 +479,10 @@ inline CordRep* Cord::TakeRep() && {
template <typename C>
inline void Cord::AppendImpl(C&& src) {
auto constexpr method = CordzUpdateTracker::kAppendCord;
+
+ contents_.MaybeRemoveEmptyCrcNode();
+ if (src.empty()) return;
+
if (empty()) {
// Since destination is empty, we can avoid allocating a node,
if (src.contents_.is_tree()) {
@@ -537,18 +542,23 @@ static CordRep::ExtractResult ExtractAppendBuffer(CordRep* rep,
}
}
-static CordBuffer CreateAppendBuffer(InlineData& data, size_t capacity) {
+static CordBuffer CreateAppendBuffer(InlineData& data, size_t block_size,
+ size_t capacity) {
// Watch out for overflow, people can ask for size_t::max().
const size_t size = data.inline_size();
- capacity = (std::min)(std::numeric_limits<size_t>::max() - size, capacity);
- CordBuffer buffer = CordBuffer::CreateWithDefaultLimit(size + capacity);
+ const size_t max_capacity = std::numeric_limits<size_t>::max() - size;
+ capacity = (std::min)(max_capacity, capacity) + size;
+ CordBuffer buffer =
+ block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+ : CordBuffer::CreateWithDefaultLimit(capacity);
cord_internal::SmallMemmove(buffer.data(), data.as_chars(), size);
buffer.SetLength(size);
data = {};
return buffer;
}
-CordBuffer Cord::GetAppendBufferSlowPath(size_t capacity, size_t min_capacity) {
+CordBuffer Cord::GetAppendBufferSlowPath(size_t block_size, size_t capacity,
+ size_t min_capacity) {
auto constexpr method = CordzUpdateTracker::kGetAppendBuffer;
CordRep* tree = contents_.tree();
if (tree != nullptr) {
@@ -558,9 +568,10 @@ CordBuffer Cord::GetAppendBufferSlowPath(size_t capacity, size_t min_capacity) {
contents_.SetTreeOrEmpty(result.tree, scope);
return CordBuffer(result.extracted->flat());
}
- return CordBuffer::CreateWithDefaultLimit(capacity);
+ return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+ : CordBuffer::CreateWithDefaultLimit(capacity);
}
- return CreateAppendBuffer(contents_.data_, capacity);
+ return CreateAppendBuffer(contents_.data_, block_size, capacity);
}
void Cord::Append(const Cord& src) {
@@ -584,6 +595,9 @@ void Cord::Append(T&& src) {
template void Cord::Append(std::string&& src);
void Cord::Prepend(const Cord& src) {
+ contents_.MaybeRemoveEmptyCrcNode();
+ if (src.empty()) return;
+
CordRep* src_tree = src.contents_.tree();
if (src_tree != nullptr) {
CordRep::Ref(src_tree);
@@ -598,16 +612,18 @@ void Cord::Prepend(const Cord& src) {
}
void Cord::PrependArray(absl::string_view src, MethodIdentifier method) {
+ contents_.MaybeRemoveEmptyCrcNode();
if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
+
if (!contents_.is_tree()) {
size_t cur_size = contents_.inline_size();
if (cur_size + src.size() <= InlineRep::kMaxInline) {
// Use embedded storage.
- char data[InlineRep::kMaxInline + 1] = {0};
- memcpy(data, src.data(), src.size());
- memcpy(data + src.size(), contents_.data(), cur_size);
- memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
- contents_.set_inline_size(cur_size + src.size());
+ InlineData data;
+ data.set_inline_size(cur_size + src.size());
+ memcpy(data.as_chars(), src.data(), src.size());
+ memcpy(data.as_chars() + src.size(), contents_.data(), cur_size);
+ contents_.data_ = data;
return;
}
}
@@ -620,8 +636,8 @@ void Cord::AppendPrecise(absl::string_view src, MethodIdentifier method) {
assert(src.size() <= cord_internal::kMaxFlatLength);
if (contents_.remaining_inline_capacity() >= src.size()) {
const size_t inline_length = contents_.inline_size();
- memcpy(contents_.data_.as_chars() + inline_length, src.data(), src.size());
contents_.set_inline_size(inline_length + src.size());
+ memcpy(contents_.data_.as_chars() + inline_length, src.data(), src.size());
} else {
contents_.AppendTree(CordRepFlat::Create(src), method);
}
@@ -631,12 +647,12 @@ void Cord::PrependPrecise(absl::string_view src, MethodIdentifier method) {
assert(!src.empty());
assert(src.size() <= cord_internal::kMaxFlatLength);
if (contents_.remaining_inline_capacity() >= src.size()) {
- const size_t inline_length = contents_.inline_size();
- char data[InlineRep::kMaxInline + 1] = {0};
- memcpy(data, src.data(), src.size());
- memcpy(data + src.size(), contents_.data(), inline_length);
- memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
- contents_.set_inline_size(inline_length + src.size());
+ const size_t cur_size = contents_.inline_size();
+ InlineData data;
+ data.set_inline_size(cur_size + src.size());
+ memcpy(data.as_chars(), src.data(), src.size());
+ memcpy(data.as_chars() + src.size(), contents_.data(), cur_size);
+ contents_.data_ = data;
} else {
contents_.PrependTree(CordRepFlat::Create(src), method);
}
@@ -658,6 +674,7 @@ void Cord::RemovePrefix(size_t n) {
ABSL_INTERNAL_CHECK(n <= size(),
absl::StrCat("Requested prefix size ", n,
" exceeds Cord's size ", size()));
+ contents_.MaybeRemoveEmptyCrcNode();
CordRep* tree = contents_.tree();
if (tree == nullptr) {
contents_.remove_prefix(n);
@@ -688,6 +705,7 @@ void Cord::RemoveSuffix(size_t n) {
ABSL_INTERNAL_CHECK(n <= size(),
absl::StrCat("Requested suffix size ", n,
" exceeds Cord's size ", size()));
+ contents_.MaybeRemoveEmptyCrcNode();
CordRep* tree = contents_.tree();
if (tree == nullptr) {
contents_.reduce_size(n);
@@ -726,6 +744,7 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
}
if (new_size <= InlineRep::kMaxInline) {
+ sub_cord.contents_.set_inline_size(new_size);
char* dest = sub_cord.contents_.data_.as_chars();
Cord::ChunkIterator it = chunk_begin();
it.AdvanceBytes(pos);
@@ -737,7 +756,6 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
++it;
}
cord_internal::SmallMemmove(dest, it->data(), remaining_size);
- sub_cord.contents_.set_inline_size(new_size);
return sub_cord;
}
@@ -835,26 +853,44 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
return absl::string_view(node->external()->base + offset, length);
}
-void Cord::SetExpectedChecksum(uint32_t crc) {
+void Cord::SetCrcCordState(crc_internal::CrcCordState state) {
auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum;
- if (empty()) return;
-
- if (!contents_.is_tree()) {
+ if (empty()) {
+ contents_.MaybeRemoveEmptyCrcNode();
+ CordRep* rep = CordRepCrc::New(nullptr, std::move(state));
+ contents_.EmplaceTree(rep, method);
+ } else if (!contents_.is_tree()) {
CordRep* rep = contents_.MakeFlatWithExtraCapacity(0);
- rep = CordRepCrc::New(rep, crc);
+ rep = CordRepCrc::New(rep, std::move(state));
contents_.EmplaceTree(rep, method);
} else {
const CordzUpdateScope scope(contents_.data_.cordz_info(), method);
- CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), crc);
+ CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), std::move(state));
contents_.SetTree(rep, scope);
}
}
+void Cord::SetExpectedChecksum(uint32_t crc) {
+ // Construct a CrcCordState with a single chunk.
+ crc_internal::CrcCordState state;
+ state.mutable_rep()->prefix_crc.push_back(
+ crc_internal::CrcCordState::PrefixCrc(size(), absl::crc32c_t{crc}));
+ SetCrcCordState(std::move(state));
+}
+
+const crc_internal::CrcCordState* Cord::MaybeGetCrcCordState() const {
+ if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {
+ return nullptr;
+ }
+ return &contents_.tree()->crc()->crc_cord_state;
+}
+
absl::optional<uint32_t> Cord::ExpectedChecksum() const {
if (!contents_.is_tree() || !contents_.tree()->IsCrc()) {
return absl::nullopt;
}
- return contents_.tree()->crc()->crc;
+ return static_cast<uint32_t>(
+ contents_.tree()->crc()->crc_cord_state.Checksum());
}
inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
@@ -922,6 +958,7 @@ inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
}
inline absl::string_view Cord::GetFirstChunk(const Cord& c) {
+ if (c.empty()) return {};
return c.contents_.FindFlatStartPiece();
}
inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {
@@ -1092,7 +1129,7 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
: current_leaf_;
const char* data = payload->IsExternal() ? payload->external()->base
: payload->flat()->Data();
- const size_t offset = current_chunk_.data() - data;
+ const size_t offset = static_cast<size_t>(current_chunk_.data() - data);
auto* tree = CordRepSubstring::Substring(payload, offset, n);
subcord.contents_.EmplaceTree(VerifyTree(tree), method);
@@ -1159,6 +1196,10 @@ absl::string_view Cord::FlattenSlowPath() {
/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
assert(rep != nullptr);
+ if (rep->length == 0) {
+ *fragment = absl::string_view();
+ return true;
+ }
rep = cord_internal::SkipCrcNode(rep);
if (rep->IsFlat()) {
*fragment = absl::string_view(rep->flat()->Data(), rep->length);
@@ -1190,6 +1231,7 @@ absl::string_view Cord::FlattenSlowPath() {
absl::cord_internal::CordRep* rep,
absl::FunctionRef<void(absl::string_view)> callback) {
assert(rep != nullptr);
+ if (rep->length == 0) return;
rep = cord_internal::SkipCrcNode(rep);
if (rep->IsBtree()) {
@@ -1223,8 +1265,12 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
if (include_data) *os << static_cast<void*>(rep);
*os << "]";
*os << " " << std::setw(indent) << "";
- if (rep->IsCrc()) {
- *os << "CRC crc=" << rep->crc()->crc << "\n";
+ bool leaf = false;
+ if (rep == nullptr) {
+ *os << "NULL\n";
+ leaf = true;
+ } else if (rep->IsCrc()) {
+ *os << "CRC crc=" << rep->crc()->crc_cord_state.Checksum() << "\n";
indent += kIndentStep;
rep = rep->crc()->child;
} else if (rep->IsSubstring()) {
@@ -1232,6 +1278,7 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
indent += kIndentStep;
rep = rep->substring()->child;
} else { // Leaf or ring
+ leaf = true;
if (rep->IsExternal()) {
*os << "EXTERNAL [";
if (include_data)
@@ -1245,6 +1292,8 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
} else {
CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os);
}
+ }
+ if (leaf) {
if (stack.empty()) break;
rep = stack.back();
stack.pop_back();
@@ -1290,11 +1339,14 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
node->substring()->child->length,
ReportError(root, node));
} else if (node->IsCrc()) {
- ABSL_INTERNAL_CHECK(node->crc()->child != nullptr,
- ReportError(root, node));
- ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length,
- ReportError(root, node));
- worklist.push_back(node->crc()->child);
+ ABSL_INTERNAL_CHECK(
+ node->crc()->child != nullptr || node->crc()->length == 0,
+ ReportError(root, node));
+ if (node->crc()->child != nullptr) {
+ ABSL_INTERNAL_CHECK(node->crc()->length == node->crc()->child->length,
+ ReportError(root, node));
+ worklist.push_back(node->crc()->child);
+ }
}
} while (!worklist.empty());
return true;
@@ -1302,7 +1354,7 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
std::ostream& operator<<(std::ostream& out, const Cord& cord) {
for (absl::string_view chunk : cord.Chunks()) {
- out.write(chunk.data(), chunk.size());
+ out.write(chunk.data(), static_cast<std::streamsize>(chunk.size()));
}
return out;
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord.h b/contrib/restricted/abseil-cpp/absl/strings/cord.h
index 18d6ab852f..c4a0d5aaae 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord.h
@@ -20,8 +20,7 @@
// structure. A Cord is a string-like sequence of characters optimized for
// specific use cases. Unlike a `std::string`, which stores an array of
// contiguous characters, Cord data is stored in a structure consisting of
-// separate, reference-counted "chunks." (Currently, this implementation is a
-// tree structure, though that implementation may change.)
+// separate, reference-counted "chunks."
//
// Because a Cord consists of these chunks, data can be added to or removed from
// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
@@ -77,6 +76,7 @@
#include "absl/base/macros.h"
#include "absl/base/port.h"
#include "absl/container/inlined_vector.h"
+#include "absl/crc/internal/crc_cord_state.h"
#include "absl/functional/function_ref.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/cord_analysis.h"
@@ -284,6 +284,19 @@ class Cord {
// }
CordBuffer GetAppendBuffer(size_t capacity, size_t min_capacity = 16);
+ // Returns a CordBuffer, re-using potential existing capacity in this cord.
+ //
+ // This function is identical to `GetAppendBuffer`, except that in the case
+ // where a new `CordBuffer` is allocated, it is allocated using the provided
+ // custom limit instead of the default limit. `GetAppendBuffer` will default
+ // to `CordBuffer::CreateWithDefaultLimit(capacity)` whereas this method
+ // will default to `CordBuffer::CreateWithCustomLimit(block_size, capacity)`.
+ // This method is equivalent to `GetAppendBuffer` if `block_size` is zero.
+ // See the documentation for `CreateWithCustomLimit` for more details on the
+ // restrictions and legal values for `block_size`.
+ CordBuffer GetCustomAppendBuffer(size_t block_size, size_t capacity,
+ size_t min_capacity = 16);
+
// Cord::Prepend()
//
// Prepends data to the Cord, which may come from another Cord or other string
@@ -802,7 +815,7 @@ class Cord {
InlineRep& operator=(const InlineRep& src);
InlineRep& operator=(InlineRep&& src) noexcept;
- explicit constexpr InlineRep(cord_internal::InlineData data);
+ explicit constexpr InlineRep(absl::string_view sv, CordRep* rep);
void Swap(InlineRep* rhs);
bool empty() const;
@@ -861,33 +874,14 @@ class Cord {
void PrependTreeToTree(CordRep* tree, MethodIdentifier method);
void PrependTree(CordRep* tree, MethodIdentifier method);
- template <bool has_length>
- void GetAppendRegion(char** region, size_t* size, size_t length);
+ bool IsSame(const InlineRep& other) const { return data_ == other.data_; }
- bool IsSame(const InlineRep& other) const {
- return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
- }
- int BitwiseCompare(const InlineRep& other) const {
- uint64_t x, y;
- // Use memcpy to avoid aliasing issues.
- memcpy(&x, &data_, sizeof(x));
- memcpy(&y, &other.data_, sizeof(y));
- if (x == y) {
- memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
- memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
- if (x == y) return 0;
- }
- return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
- ? -1
- : 1;
- }
void CopyTo(std::string* dst) const {
// memcpy is much faster when operating on a known size. On most supported
// platforms, the small string optimization is large enough that resizing
// to 15 bytes does not cause a memory allocation.
- absl::strings_internal::STLStringResizeUninitialized(dst,
- sizeof(data_) - 1);
- memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
+ absl::strings_internal::STLStringResizeUninitialized(dst, kMaxInline);
+ data_.copy_max_inline_to(&(*dst)[0]);
// erase is faster than resize because the logic for memory allocation is
// not needed.
dst->erase(inline_size());
@@ -932,6 +926,13 @@ class Cord {
void set_inline_size(size_t size) { data_.set_inline_size(size); }
size_t inline_size() const { return data_.inline_size(); }
+ // Empty cords that carry a checksum have a CordRepCrc node with a null
+ // child node. The code can avoid lots of special cases where it would
+ // otherwise transition from tree to inline storage if we just remove the
+ // CordRepCrc node before mutations. Must never be called inside a
+ // CordzUpdateScope since it untracks the cordz info.
+ void MaybeRemoveEmptyCrcNode();
+
cord_internal::InlineData data_;
};
InlineRep contents_;
@@ -980,7 +981,8 @@ class Cord {
void AppendPrecise(absl::string_view src, MethodIdentifier method);
void PrependPrecise(absl::string_view src, MethodIdentifier method);
- CordBuffer GetAppendBufferSlowPath(size_t capacity, size_t min_capacity);
+ CordBuffer GetAppendBufferSlowPath(size_t block_size, size_t capacity,
+ size_t min_capacity);
// Prepends the provided data to this instance. `method` contains the public
// API method for this action which is tracked for Cordz sampling purposes.
@@ -1000,6 +1002,10 @@ class Cord {
});
return H::combine(combiner.finalize(std::move(hash_state)), size());
}
+
+ friend class CrcCord;
+ void SetCrcCordState(crc_internal::CrcCordState state);
+ const crc_internal::CrcCordState* MaybeGetCrcCordState() const;
};
ABSL_NAMESPACE_END
@@ -1016,46 +1022,6 @@ extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
namespace cord_internal {
-// Fast implementation of memmove for up to 15 bytes. This implementation is
-// safe for overlapping regions. If nullify_tail is true, the destination is
-// padded with '\0' up to 16 bytes.
-template <bool nullify_tail = false>
-inline void SmallMemmove(char* dst, const char* src, size_t n) {
- if (n >= 8) {
- assert(n <= 16);
- uint64_t buf1;
- uint64_t buf2;
- memcpy(&buf1, src, 8);
- memcpy(&buf2, src + n - 8, 8);
- if (nullify_tail) {
- memset(dst + 8, 0, 8);
- }
- memcpy(dst, &buf1, 8);
- memcpy(dst + n - 8, &buf2, 8);
- } else if (n >= 4) {
- uint32_t buf1;
- uint32_t buf2;
- memcpy(&buf1, src, 4);
- memcpy(&buf2, src + n - 4, 4);
- if (nullify_tail) {
- memset(dst + 4, 0, 4);
- memset(dst + 8, 0, 8);
- }
- memcpy(dst, &buf1, 4);
- memcpy(dst + n - 4, &buf2, 4);
- } else {
- if (n != 0) {
- dst[0] = src[0];
- dst[n / 2] = src[n / 2];
- dst[n - 1] = src[n - 1];
- }
- if (nullify_tail) {
- memset(dst + 8, 0, 8);
- memset(dst + n, 0, 8);
- }
- }
-}
-
// Does non-template-specific `CordRepExternal` initialization.
// Requires `data` to be non-empty.
void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
@@ -1099,8 +1065,8 @@ Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
return cord;
}
-constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
- : data_(data) {}
+constexpr Cord::InlineRep::InlineRep(absl::string_view sv, CordRep* rep)
+ : data_(sv, rep) {}
inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
: data_(InlineData::kDefaultInit) {
@@ -1179,7 +1145,7 @@ inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
size_t len = data_.inline_size();
auto* result = CordRepFlat::New(len + extra);
result->length = len;
- memcpy(result->Data(), data_.as_chars(), sizeof(data_));
+ data_.copy_max_inline_to(result->Data());
return result;
}
@@ -1241,6 +1207,18 @@ inline void Cord::InlineRep::CopyToArray(char* dst) const {
cord_internal::SmallMemmove(dst, data_.as_chars(), n);
}
+inline void Cord::InlineRep::MaybeRemoveEmptyCrcNode() {
+ CordRep* rep = tree();
+ if (rep == nullptr || ABSL_PREDICT_TRUE(rep->length > 0)) {
+ return;
+ }
+ assert(rep->IsCrc());
+ assert(rep->crc()->child == nullptr);
+ CordzInfo::MaybeUntrackCord(cordz_info());
+ CordRep::Unref(rep);
+ ResetToEmpty();
+}
+
constexpr inline Cord::Cord() noexcept {}
inline Cord::Cord(absl::string_view src)
@@ -1248,13 +1226,12 @@ inline Cord::Cord(absl::string_view src)
template <typename T>
constexpr Cord::Cord(strings_internal::StringConstant<T>)
- : contents_(strings_internal::StringConstant<T>::value.size() <=
+ : contents_(strings_internal::StringConstant<T>::value,
+ strings_internal::StringConstant<T>::value.size() <=
cord_internal::kMaxInline
- ? cord_internal::InlineData(
- strings_internal::StringConstant<T>::value)
- : cord_internal::InlineData(
- &cord_internal::ConstInitExternalStorage<
- strings_internal::StringConstant<T>>::value)) {}
+ ? nullptr
+ : &cord_internal::ConstInitExternalStorage<
+ strings_internal::StringConstant<T>>::value) {}
inline Cord& Cord::operator=(const Cord& x) {
contents_ = x.contents_;
@@ -1290,7 +1267,7 @@ inline size_t Cord::size() const {
return contents_.size();
}
-inline bool Cord::empty() const { return contents_.empty(); }
+inline bool Cord::empty() const { return size() == 0; }
inline size_t Cord::EstimatedMemoryUsage(
CordMemoryAccounting accounting_method) const {
@@ -1360,7 +1337,17 @@ inline void Cord::Prepend(CordBuffer buffer) {
inline CordBuffer Cord::GetAppendBuffer(size_t capacity, size_t min_capacity) {
if (empty()) return CordBuffer::CreateWithDefaultLimit(capacity);
- return GetAppendBufferSlowPath(capacity, min_capacity);
+ return GetAppendBufferSlowPath(0, capacity, min_capacity);
+}
+
+inline CordBuffer Cord::GetCustomAppendBuffer(size_t block_size,
+ size_t capacity,
+ size_t min_capacity) {
+ if (empty()) {
+ return block_size ? CordBuffer::CreateWithCustomLimit(block_size, capacity)
+ : CordBuffer::CreateWithDefaultLimit(capacity);
+ }
+ return GetAppendBufferSlowPath(block_size, capacity, min_capacity);
}
extern template void Cord::Append(std::string&& src);
@@ -1368,7 +1355,7 @@ extern template void Cord::Prepend(std::string&& src);
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
- return contents_.BitwiseCompare(rhs.contents_);
+ return contents_.data_.Compare(rhs.contents_.data_);
}
return CompareImpl(rhs);
@@ -1406,7 +1393,11 @@ inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree) {
inline Cord::ChunkIterator::ChunkIterator(const Cord* cord) {
if (CordRep* tree = cord->contents_.tree()) {
bytes_remaining_ = tree->length;
- InitTree(tree);
+ if (ABSL_PREDICT_TRUE(bytes_remaining_ != 0)) {
+ InitTree(tree);
+ } else {
+ current_chunk_ = {};
+ }
} else {
bytes_remaining_ = cord->contents_.inline_size();
current_chunk_ = {cord->contents_.data(), bytes_remaining_};
@@ -1575,7 +1566,7 @@ inline void Cord::ForEachChunk(
if (rep == nullptr) {
callback(absl::string_view(contents_.data(), contents_.size()));
} else {
- return ForEachChunkAux(rep, callback);
+ ForEachChunkAux(rep, callback);
}
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord_buffer.h b/contrib/restricted/abseil-cpp/absl/strings/cord_buffer.h
index 56a6ce6f6e..15494b31e0 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/cord_buffer.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord_buffer.h
@@ -330,8 +330,7 @@ class CordBuffer {
// Returns the available area of the internal SSO data
absl::Span<char> short_available() {
- assert(is_short());
- const size_t length = (short_rep.raw_size >> 1);
+ const size_t length = short_length();
return absl::Span<char>(short_rep.data + length,
kInlineCapacity - length);
}
@@ -347,7 +346,7 @@ class CordBuffer {
// Returns the length of the internal SSO data.
size_t short_length() const {
assert(is_short());
- return short_rep.raw_size >> 1;
+ return static_cast<size_t>(short_rep.raw_size >> 1);
}
// Sets the length of the internal SSO data.
@@ -412,8 +411,12 @@ class CordBuffer {
// Power2 functions
static bool IsPow2(size_t size) { return absl::has_single_bit(size); }
- static size_t Log2Floor(size_t size) { return absl::bit_width(size) - 1; }
- static size_t Log2Ceil(size_t size) { return absl::bit_width(size - 1); }
+ static size_t Log2Floor(size_t size) {
+ return static_cast<size_t>(absl::bit_width(size) - 1);
+ }
+ static size_t Log2Ceil(size_t size) {
+ return static_cast<size_t>(absl::bit_width(size - 1));
+ }
// Implementation of `CreateWithCustomLimit()`.
// This implementation allows for future memory allocation hints to
diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
index 18b20b83fd..939668466b 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.cc
@@ -42,11 +42,11 @@ constexpr bool kUnescapeNulls = false;
inline bool is_octal_digit(char c) { return ('0' <= c) && (c <= '7'); }
-inline int hex_digit_to_int(char c) {
+inline unsigned int hex_digit_to_int(char c) {
static_assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61,
"Character set must be ASCII.");
- assert(absl::ascii_isxdigit(c));
- int x = static_cast<unsigned char>(c);
+ assert(absl::ascii_isxdigit(static_cast<unsigned char>(c)));
+ unsigned int x = static_cast<unsigned char>(c);
if (x > '9') {
x += 9;
}
@@ -121,27 +121,29 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
case '7': {
// octal digit: 1 to 3 digits
const char* octal_start = p;
- unsigned int ch = *p - '0';
- if (p < last_byte && is_octal_digit(p[1])) ch = ch * 8 + *++p - '0';
+ unsigned int ch = static_cast<unsigned int>(*p - '0'); // digit 1
if (p < last_byte && is_octal_digit(p[1]))
- ch = ch * 8 + *++p - '0'; // now points at last digit
+ ch = ch * 8 + static_cast<unsigned int>(*++p - '0'); // digit 2
+ if (p < last_byte && is_octal_digit(p[1]))
+ ch = ch * 8 + static_cast<unsigned int>(*++p - '0'); // digit 3
if (ch > 0xff) {
if (error) {
*error = "Value of \\" +
- std::string(octal_start, p + 1 - octal_start) +
+ std::string(octal_start,
+ static_cast<size_t>(p + 1 - octal_start)) +
" exceeds 0xff";
}
return false;
}
if ((ch == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
- const ptrdiff_t octal_size = p + 1 - octal_start;
+ const size_t octal_size = static_cast<size_t>(p + 1 - octal_start);
*d++ = '\\';
memmove(d, octal_start, octal_size);
d += octal_size;
break;
}
- *d++ = ch;
+ *d++ = static_cast<char>(ch);
break;
}
case 'x':
@@ -149,32 +151,34 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
if (p >= last_byte) {
if (error) *error = "String cannot end with \\x";
return false;
- } else if (!absl::ascii_isxdigit(p[1])) {
+ } else if (!absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
if (error) *error = "\\x cannot be followed by a non-hex digit";
return false;
}
unsigned int ch = 0;
const char* hex_start = p;
- while (p < last_byte && absl::ascii_isxdigit(p[1]))
+ while (p < last_byte &&
+ absl::ascii_isxdigit(static_cast<unsigned char>(p[1])))
// Arbitrarily many hex digits
ch = (ch << 4) + hex_digit_to_int(*++p);
if (ch > 0xFF) {
if (error) {
*error = "Value of \\" +
- std::string(hex_start, p + 1 - hex_start) +
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start)) +
" exceeds 0xff";
}
return false;
}
if ((ch == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
- const ptrdiff_t hex_size = p + 1 - hex_start;
+ const size_t hex_size = static_cast<size_t>(p + 1 - hex_start);
*d++ = '\\';
memmove(d, hex_start, hex_size);
d += hex_size;
break;
}
- *d++ = ch;
+ *d++ = static_cast<char>(ch);
break;
}
case 'u': {
@@ -184,18 +188,20 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
if (p + 4 >= end) {
if (error) {
*error = "\\u must be followed by 4 hex digits: \\" +
- std::string(hex_start, p + 1 - hex_start);
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start));
}
return false;
}
for (int i = 0; i < 4; ++i) {
// Look one char ahead.
- if (absl::ascii_isxdigit(p[1])) {
+ if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p.
} else {
if (error) {
*error = "\\u must be followed by 4 hex digits: \\" +
- std::string(hex_start, p + 1 - hex_start);
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start));
}
return false;
}
@@ -220,20 +226,22 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
if (p + 8 >= end) {
if (error) {
*error = "\\U must be followed by 8 hex digits: \\" +
- std::string(hex_start, p + 1 - hex_start);
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start));
}
return false;
}
for (int i = 0; i < 8; ++i) {
// Look one char ahead.
- if (absl::ascii_isxdigit(p[1])) {
+ if (absl::ascii_isxdigit(static_cast<unsigned char>(p[1]))) {
// Don't change rune until we're sure this
// is within the Unicode limit, but do advance p.
uint32_t newrune = (rune << 4) + hex_digit_to_int(*++p);
if (newrune > 0x10FFFF) {
if (error) {
*error = "Value of \\" +
- std::string(hex_start, p + 1 - hex_start) +
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start)) +
" exceeds Unicode limit (0x10FFFF)";
}
return false;
@@ -243,7 +251,8 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
} else {
if (error) {
*error = "\\U must be followed by 8 hex digits: \\" +
- std::string(hex_start, p + 1 - hex_start);
+ std::string(hex_start,
+ static_cast<size_t>(p + 1 - hex_start));
}
return false;
}
@@ -291,7 +300,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
error)) {
return false;
}
- dest->erase(dest_size);
+ dest->erase(static_cast<size_t>(dest_size));
return true;
}
@@ -311,7 +320,7 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex,
std::string dest;
bool last_hex_escape = false; // true if last output char was \xNN.
- for (unsigned char c : src) {
+ for (char c : src) {
bool is_hex_escape = false;
switch (c) {
case '\n': dest.append("\\" "n"); break;
@@ -320,28 +329,30 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex,
case '\"': dest.append("\\" "\""); break;
case '\'': dest.append("\\" "'"); break;
case '\\': dest.append("\\" "\\"); break;
- default:
+ default: {
// Note that if we emit \xNN and the src character after that is a hex
// digit then that digit must be escaped too to prevent it being
// interpreted as part of the character code by C.
- if ((!utf8_safe || c < 0x80) &&
- (!absl::ascii_isprint(c) ||
- (last_hex_escape && absl::ascii_isxdigit(c)))) {
+ const unsigned char uc = static_cast<unsigned char>(c);
+ if ((!utf8_safe || uc < 0x80) &&
+ (!absl::ascii_isprint(uc) ||
+ (last_hex_escape && absl::ascii_isxdigit(uc)))) {
if (use_hex) {
dest.append("\\" "x");
- dest.push_back(numbers_internal::kHexChar[c / 16]);
- dest.push_back(numbers_internal::kHexChar[c % 16]);
+ dest.push_back(numbers_internal::kHexChar[uc / 16]);
+ dest.push_back(numbers_internal::kHexChar[uc % 16]);
is_hex_escape = true;
} else {
dest.append("\\");
- dest.push_back(numbers_internal::kHexChar[c / 64]);
- dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
- dest.push_back(numbers_internal::kHexChar[c % 8]);
+ dest.push_back(numbers_internal::kHexChar[uc / 64]);
+ dest.push_back(numbers_internal::kHexChar[(uc % 64) / 8]);
+ dest.push_back(numbers_internal::kHexChar[uc % 8]);
}
} else {
dest.push_back(c);
break;
}
+ }
}
last_hex_escape = is_hex_escape;
}
@@ -350,7 +361,7 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex,
}
/* clang-format off */
-constexpr char c_escaped_len[256] = {
+constexpr unsigned char c_escaped_len[256] = {
4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", '
@@ -375,7 +386,8 @@ constexpr char c_escaped_len[256] = {
// that UTF-8 bytes are not handled specially.
inline size_t CEscapedLength(absl::string_view src) {
size_t escaped_len = 0;
- for (unsigned char c : src) escaped_len += c_escaped_len[c];
+ for (char c : src)
+ escaped_len += c_escaped_len[static_cast<unsigned char>(c)];
return escaped_len;
}
@@ -391,8 +403,8 @@ void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) {
cur_dest_len + escaped_len);
char* append_ptr = &(*dest)[cur_dest_len];
- for (unsigned char c : src) {
- int char_len = c_escaped_len[c];
+ for (char c : src) {
+ size_t char_len = c_escaped_len[static_cast<unsigned char>(c)];
if (char_len == 1) {
*append_ptr++ = c;
} else if (char_len == 2) {
@@ -424,9 +436,9 @@ void CEscapeAndAppendInternal(absl::string_view src, std::string* dest) {
}
} else {
*append_ptr++ = '\\';
- *append_ptr++ = '0' + c / 64;
- *append_ptr++ = '0' + (c % 64) / 8;
- *append_ptr++ = '0' + c % 8;
+ *append_ptr++ = '0' + static_cast<unsigned char>(c) / 64;
+ *append_ptr++ = '0' + (static_cast<unsigned char>(c) % 64) / 8;
+ *append_ptr++ = '0' + static_cast<unsigned char>(c) % 8;
}
}
}
@@ -440,7 +452,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
size_t destidx = 0;
int decode = 0;
int state = 0;
- unsigned int ch = 0;
+ unsigned char ch = 0;
unsigned int temp = 0;
// If "char" is signed by default, using *src as an array index results in
@@ -500,13 +512,13 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
// how to handle those cases.
GET_INPUT(first, 4);
- temp = decode;
+ temp = static_cast<unsigned char>(decode);
GET_INPUT(second, 3);
- temp = (temp << 6) | decode;
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
GET_INPUT(third, 2);
- temp = (temp << 6) | decode;
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
GET_INPUT(fourth, 1);
- temp = (temp << 6) | decode;
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
} else {
// We really did have four good data bytes, so advance four
// characters in the string.
@@ -518,11 +530,11 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
// temp has 24 bits of input, so write that out as three bytes.
if (destidx + 3 > szdest) return false;
- dest[destidx + 2] = temp;
+ dest[destidx + 2] = static_cast<char>(temp);
temp >>= 8;
- dest[destidx + 1] = temp;
+ dest[destidx + 1] = static_cast<char>(temp);
temp >>= 8;
- dest[destidx] = temp;
+ dest[destidx] = static_cast<char>(temp);
destidx += 3;
}
} else {
@@ -583,18 +595,18 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
}
// Each input character gives us six bits of output.
- temp = (temp << 6) | decode;
+ temp = (temp << 6) | static_cast<unsigned char>(decode);
++state;
if (state == 4) {
// If we've accumulated 24 bits of output, write that out as
// three bytes.
if (dest) {
if (destidx + 3 > szdest) return false;
- dest[destidx + 2] = temp;
+ dest[destidx + 2] = static_cast<char>(temp);
temp >>= 8;
- dest[destidx + 1] = temp;
+ dest[destidx + 1] = static_cast<char>(temp);
temp >>= 8;
- dest[destidx] = temp;
+ dest[destidx] = static_cast<char>(temp);
}
destidx += 3;
state = 0;
@@ -619,7 +631,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
if (dest) {
if (destidx + 1 > szdest) return false;
temp >>= 4;
- dest[destidx] = temp;
+ dest[destidx] = static_cast<char>(temp);
}
++destidx;
expected_equals = 2;
@@ -630,9 +642,9 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
if (dest) {
if (destidx + 2 > szdest) return false;
temp >>= 2;
- dest[destidx + 1] = temp;
+ dest[destidx + 1] = static_cast<char>(temp);
temp >>= 8;
- dest[destidx] = temp;
+ dest[destidx] = static_cast<char>(temp);
}
destidx += 2;
expected_equals = 1;
@@ -772,8 +784,7 @@ template <typename String>
bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
const signed char* unbase64) {
// Determine the size of the output string. Base64 encodes every 3 bytes into
- // 4 characters. any leftover chars are added directly for good measure.
- // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
+ // 4 characters. Any leftover chars are added directly for good measure.
const size_t dest_len = 3 * (slen / 4) + (slen % 4);
strings_internal::STLStringResizeUninitialized(dest, dest_len);
@@ -821,9 +832,9 @@ constexpr char kHexValueLenient[256] = {
// or a string. This works because we use the [] operator to access
// individual characters at a time.
template <typename T>
-void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
- for (int i = 0; i < num; i++) {
- to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
+void HexStringToBytesInternal(const char* from, T to, size_t num) {
+ for (size_t i = 0; i < num; i++) {
+ to[i] = static_cast<char>(kHexValueLenient[from[i * 2] & 0xFF] << 4) +
(kHexValueLenient[from[i * 2 + 1] & 0xFF]);
}
}
@@ -831,7 +842,7 @@ void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
// This is a templated function so that T can be either a char* or a
// std::string.
template <typename T>
-void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
+void BytesToHexStringInternal(const unsigned char* src, T dest, size_t num) {
auto dest_ptr = &dest[0];
for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
@@ -876,8 +887,8 @@ std::string Utf8SafeCHexEscape(absl::string_view src) {
// WebSafeBase64Escape() - Google's variation of base64 encoder
//
// Check out
-// http://tools.ietf.org/html/rfc2045 for formal description, but what we
-// care about is that...
+// https://datatracker.ietf.org/doc/html/rfc2045 for formal description, but
+// what we care about is that...
// Take the encoded stuff in groups of 4 characters and turn each
// character into a code 0 to 63 thus:
// A-Z map to 0 to 25
diff --git a/contrib/restricted/abseil-cpp/absl/strings/escaping.h b/contrib/restricted/abseil-cpp/absl/strings/escaping.h
index f5ca26c5da..7c082fef3d 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/escaping.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/escaping.h
@@ -117,35 +117,40 @@ std::string Utf8SafeCEscape(absl::string_view src);
// conversion.
std::string Utf8SafeCHexEscape(absl::string_view src);
-// Base64Unescape()
-//
-// Converts a `src` string encoded in Base64 to its binary equivalent, writing
-// it to a `dest` buffer, returning `true` on success. If `src` contains invalid
-// characters, `dest` is cleared and returns `false`.
-bool Base64Unescape(absl::string_view src, std::string* dest);
-
-// WebSafeBase64Unescape()
-//
-// Converts a `src` string encoded in Base64 to its binary equivalent, writing
-// it to a `dest` buffer, but using '-' instead of '+', and '_' instead of '/'.
-// If `src` contains invalid characters, `dest` is cleared and returns `false`.
-bool WebSafeBase64Unescape(absl::string_view src, std::string* dest);
-
// Base64Escape()
//
-// Encodes a `src` string into a base64-encoded string, with padding characters.
-// This function conforms with RFC 4648 section 4 (base64).
+// Encodes a `src` string into a base64-encoded 'dest' string with padding
+// characters. This function conforms with RFC 4648 section 4 (base64) and RFC
+// 2045. See also CalculateBase64EscapedLen().
void Base64Escape(absl::string_view src, std::string* dest);
std::string Base64Escape(absl::string_view src);
// WebSafeBase64Escape()
//
-// Encodes a `src` string into a base64-like string, using '-' instead of '+'
-// and '_' instead of '/', and without padding. This function conforms with RFC
-// 4648 section 5 (base64url).
+// Encodes a `src` string into a base64 string, like Base64Escape() does, but
+// outputs '-' instead of '+' and '_' instead of '/', and does not pad 'dest'.
+// This function conforms with RFC 4648 section 5 (base64url).
void WebSafeBase64Escape(absl::string_view src, std::string* dest);
std::string WebSafeBase64Escape(absl::string_view src);
+// Base64Unescape()
+//
+// Converts a `src` string encoded in Base64 (RFC 4648 section 4) to its binary
+// equivalent, writing it to a `dest` buffer, returning `true` on success. If
+// `src` contains invalid characters, `dest` is cleared and returns `false`.
+// If padding is included (note that `Base64Escape()` does produce it), it must
+// be correct. In the padding, '=' and '.' are treated identically.
+bool Base64Unescape(absl::string_view src, std::string* dest);
+
+// WebSafeBase64Unescape()
+//
+// Converts a `src` string encoded in "web safe" Base64 (RFC 4648 section 5) to
+// its binary equivalent, writing it to a `dest` buffer. If `src` contains
+// invalid characters, `dest` is cleared and returns `false`. If padding is
+// included (note that `WebSafeBase64Escape()` does not produce it), it must be
+// correct. In the padding, '=' and '.' are treated identically.
+bool WebSafeBase64Unescape(absl::string_view src, std::string* dest);
+
// HexStringToBytes()
//
// Converts an ASCII hex string into bytes, returning binary data of length
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h b/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
index 61484de0b7..70a9034336 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/char_map.h
@@ -73,10 +73,10 @@ class Charmap {
}
// Containing all the chars in the C-string 's'.
- // Note that this is expensively recursive because of the C++11 constexpr
- // formulation. Use only in constexpr initializers.
static constexpr Charmap FromString(const char* s) {
- return *s == 0 ? Charmap() : (Char(*s) | FromString(s + 1));
+ Charmap ret;
+ while (*s) ret = ret | Char(*s++);
+ return ret;
}
// Containing all the chars in the closed interval [lo,hi].
@@ -103,10 +103,9 @@ class Charmap {
constexpr Charmap(uint64_t b0, uint64_t b1, uint64_t b2, uint64_t b3)
: m_{b0, b1, b2, b3} {}
- static constexpr uint64_t RangeForWord(unsigned char lo, unsigned char hi,
- uint64_t word) {
- return OpenRangeFromZeroForWord(hi + 1, word) &
- ~OpenRangeFromZeroForWord(lo, word);
+ static constexpr uint64_t RangeForWord(char lo, char hi, uint64_t word) {
+ return OpenRangeFromZeroForWord(static_cast<unsigned char>(hi) + 1, word) &
+ ~OpenRangeFromZeroForWord(static_cast<unsigned char>(lo), word);
}
// All the chars in the specified word of the range [0, upper).
@@ -119,13 +118,16 @@ class Charmap {
: (~static_cast<uint64_t>(0) >> (64 - upper % 64));
}
- static constexpr uint64_t CharMaskForWord(unsigned char x, uint64_t word) {
- return (x / 64 == word) ? (static_cast<uint64_t>(1) << (x % 64)) : 0;
+ static constexpr uint64_t CharMaskForWord(char x, uint64_t word) {
+ const auto unsigned_x = static_cast<unsigned char>(x);
+ return (unsigned_x / 64 == word)
+ ? (static_cast<uint64_t>(1) << (unsigned_x % 64))
+ : 0;
}
- private:
- void SetChar(unsigned char c) {
- m_[c / 64] |= static_cast<uint64_t>(1) << (c % 64);
+ void SetChar(char c) {
+ const auto unsigned_c = static_cast<unsigned char>(c);
+ m_[unsigned_c / 64] |= static_cast<uint64_t>(1) << (unsigned_c % 64);
}
uint64_t m_[4];
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
index ebf8c0791a..282b639eb2 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_bigint.cc
@@ -242,7 +242,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
// decimal exponent to compensate.
--exponent_adjust;
}
- int digit = (*begin - '0');
+ char digit = (*begin - '0');
--significant_digits;
if (significant_digits == 0 && std::next(begin) != end &&
(digit == 0 || digit == 5)) {
@@ -255,7 +255,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
// 500000...000000000001 to correctly round up, rather than to nearest.
++digit;
}
- queued = 10 * queued + digit;
+ queued = 10 * queued + static_cast<uint32_t>(digit);
++digits_queued;
if (digits_queued == kMaxSmallPowerOfTen) {
MultiplyBy(kTenToNth[kMaxSmallPowerOfTen]);
@@ -341,8 +341,8 @@ std::string BigUnsigned<max_words>::ToString() const {
std::string result;
// Build result in reverse order
while (copy.size() > 0) {
- int next_digit = copy.DivMod<10>();
- result.push_back('0' + next_digit);
+ uint32_t next_digit = copy.DivMod<10>();
+ result.push_back('0' + static_cast<char>(next_digit));
}
if (result.empty()) {
result.push_back('0');
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
index d29acaf462..98823def83 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/charconv_parse.cc
@@ -190,11 +190,11 @@ bool IsDigit<16>(char ch) {
template <>
unsigned ToDigit<10>(char ch) {
- return ch - '0';
+ return static_cast<unsigned>(ch - '0');
}
template <>
unsigned ToDigit<16>(char ch) {
- return kAsciiToInt[static_cast<unsigned char>(ch)];
+ return static_cast<unsigned>(kAsciiToInt[static_cast<unsigned char>(ch)]);
}
template <>
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
index b50fb79a55..63a81f4f16 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_internal.h
@@ -27,9 +27,20 @@
#include "absl/base/internal/invoke.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/compressed_tuple.h"
+#include "absl/container/internal/container_memory.h"
#include "absl/meta/type_traits.h"
#include "absl/strings/string_view.h"
+// We can only add poisoning if we can detect consteval executions.
+#if defined(ABSL_HAVE_CONSTANT_EVALUATED) && \
+ (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_MEMORY_SANITIZER))
+#define ABSL_INTERNAL_CORD_HAVE_SANITIZER 1
+#endif
+
+#define ABSL_CORD_INTERNAL_NO_SANITIZE \
+ ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
@@ -91,6 +102,46 @@ enum Constants {
// Emits a fatal error "Unexpected node type: xyz" and aborts the program.
ABSL_ATTRIBUTE_NORETURN void LogFatalNodeType(CordRep* rep);
+// Fast implementation of memmove for up to 15 bytes. This implementation is
+// safe for overlapping regions. If nullify_tail is true, the destination is
+// padded with '\0' up to 15 bytes.
+template <bool nullify_tail = false>
+inline void SmallMemmove(char* dst, const char* src, size_t n) {
+ if (n >= 8) {
+ assert(n <= 15);
+ uint64_t buf1;
+ uint64_t buf2;
+ memcpy(&buf1, src, 8);
+ memcpy(&buf2, src + n - 8, 8);
+ if (nullify_tail) {
+ memset(dst + 7, 0, 8);
+ }
+ memcpy(dst, &buf1, 8);
+ memcpy(dst + n - 8, &buf2, 8);
+ } else if (n >= 4) {
+ uint32_t buf1;
+ uint32_t buf2;
+ memcpy(&buf1, src, 4);
+ memcpy(&buf2, src + n - 4, 4);
+ if (nullify_tail) {
+ memset(dst + 4, 0, 4);
+ memset(dst + 7, 0, 8);
+ }
+ memcpy(dst, &buf1, 4);
+ memcpy(dst + n - 4, &buf2, 4);
+ } else {
+ if (n != 0) {
+ dst[0] = src[0];
+ dst[n / 2] = src[n / 2];
+ dst[n - 1] = src[n - 1];
+ }
+ if (nullify_tail) {
+ memset(dst + 7, 0, 8);
+ memset(dst + n, 0, 8);
+ }
+ }
+}
+
// Compact class for tracking the reference count and state flags for CordRep
// instances. Data is stored in an atomic int32_t for compactness and speed.
class RefcountAndFlags {
@@ -129,8 +180,9 @@ class RefcountAndFlags {
}
// Returns the current reference count using acquire semantics.
- inline int32_t Get() const {
- return count_.load(std::memory_order_acquire) >> kNumFlags;
+ inline size_t Get() const {
+ return static_cast<size_t>(count_.load(std::memory_order_acquire) >>
+ kNumFlags);
}
// Returns whether the atomic integer is 1.
@@ -224,7 +276,11 @@ struct CordRep {
: length(l), refcount(immortal), tag(EXTERNAL), storage{} {}
// The following three fields have to be less than 32 bytes since
- // that is the smallest supported flat node size.
+ // that is the smallest supported flat node size. Some code optimizations rely
+ // on the specific layout of these fields. Notably: the non-trivial field
+ // `refcount` being preceded by `length`, and being tailed by POD data
+ // members only.
+ // # LINT.IfChange
size_t length;
RefcountAndFlags refcount;
// If tag < FLAT, it represents CordRepKind and indicates the type of node.
@@ -240,6 +296,7 @@ struct CordRep {
// allocate room for these in the derived class, as not all compilers reuse
// padding space from the base class (clang and gcc do, MSVC does not, etc)
uint8_t storage[3];
+ // # LINT.ThenChange(cord_rep_btree.h:copy_raw)
// Returns true if this instance's tag matches the requested type.
constexpr bool IsRing() const { return tag == RING; }
@@ -422,25 +479,25 @@ constexpr char GetOrNull(absl::string_view data, size_t pos) {
return pos < data.size() ? data[pos] : '\0';
}
-// We store cordz_info as 64 bit pointer value in big endian format. This
-// guarantees that the least significant byte of cordz_info matches the last
-// byte of the inline data representation in as_chars_, which holds the inlined
+// We store cordz_info as 64 bit pointer value in little endian format. This
+// guarantees that the least significant byte of cordz_info matches the first
+// byte of the inline data representation in `data`, which holds the inlined
// size or the 'is_tree' bit.
using cordz_info_t = int64_t;
// Assert that the `cordz_info` pointer value perfectly overlaps the last half
-// of `as_chars_` and can hold a pointer value.
+// of `data` and can hold a pointer value.
static_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, "");
static_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), "");
-// BigEndianByte() creates a big endian representation of 'value', i.e.: a big
-// endian value where the last byte in the host's representation holds 'value`,
-// with all other bytes being 0.
-static constexpr cordz_info_t BigEndianByte(unsigned char value) {
+// LittleEndianByte() creates a little endian representation of 'value', i.e.:
+// a little endian value where the first byte in the host's representation
+// holds 'value`, with all other bytes being 0.
+static constexpr cordz_info_t LittleEndianByte(unsigned char value) {
#if defined(ABSL_IS_BIG_ENDIAN)
- return value;
-#else
return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
+#else
+ return value;
#endif
}
@@ -449,38 +506,80 @@ class InlineData {
// DefaultInitType forces the use of the default initialization constructor.
enum DefaultInitType { kDefaultInit };
- // kNullCordzInfo holds the big endian representation of intptr_t(1)
+ // kNullCordzInfo holds the little endian representation of intptr_t(1)
// This is the 'null' / initial value of 'cordz_info'. The null value
// is specifically big endian 1 as with 64-bit pointers, the last
// byte of cordz_info overlaps with the last byte holding the tag.
- static constexpr cordz_info_t kNullCordzInfo = BigEndianByte(1);
-
- constexpr InlineData() : as_chars_{0} {}
- explicit InlineData(DefaultInitType) {}
- explicit constexpr InlineData(CordRep* rep) : as_tree_(rep) {}
- explicit constexpr InlineData(absl::string_view chars)
- : as_chars_{
- GetOrNull(chars, 0), GetOrNull(chars, 1),
- GetOrNull(chars, 2), GetOrNull(chars, 3),
- GetOrNull(chars, 4), GetOrNull(chars, 5),
- GetOrNull(chars, 6), GetOrNull(chars, 7),
- GetOrNull(chars, 8), GetOrNull(chars, 9),
- GetOrNull(chars, 10), GetOrNull(chars, 11),
- GetOrNull(chars, 12), GetOrNull(chars, 13),
- GetOrNull(chars, 14), static_cast<char>((chars.size() << 1))} {}
+ static constexpr cordz_info_t kNullCordzInfo = LittleEndianByte(1);
+
+ // kTagOffset contains the offset of the control byte / tag. This constant is
+ // intended mostly for debugging purposes: do not remove this constant as it
+ // is actively inspected and used by gdb pretty printing code.
+ static constexpr size_t kTagOffset = 0;
+
+ // Implement `~InlineData()` conditionally: we only need this destructor to
+ // unpoison poisoned instances under *SAN, and it will only compile correctly
+ // if the current compiler supports `absl::is_constant_evaluated()`.
+#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
+ ~InlineData() noexcept { unpoison(); }
+#endif
+
+ constexpr InlineData() noexcept { poison_this(); }
+
+ explicit InlineData(DefaultInitType) noexcept : rep_(kDefaultInit) {
+ poison_this();
+ }
+
+ explicit InlineData(CordRep* rep) noexcept : rep_(rep) {
+ ABSL_ASSERT(rep != nullptr);
+ }
+
+ // Explicit constexpr constructor to create a constexpr InlineData
+ // value. Creates an inlined SSO value if `rep` is null, otherwise
+ // creates a tree instance value.
+ constexpr InlineData(absl::string_view sv, CordRep* rep) noexcept
+ : rep_(rep ? Rep(rep) : Rep(sv)) {
+ poison();
+ }
+
+ constexpr InlineData(const InlineData& rhs) noexcept;
+ InlineData& operator=(const InlineData& rhs) noexcept;
+
+ friend bool operator==(const InlineData& lhs, const InlineData& rhs) {
+#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
+ const Rep l = lhs.rep_.SanitizerSafeCopy();
+ const Rep r = rhs.rep_.SanitizerSafeCopy();
+ return memcmp(&l, &r, sizeof(l)) == 0;
+#else
+ return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
+#endif
+ }
+ friend bool operator!=(const InlineData& lhs, const InlineData& rhs) {
+ return !operator==(lhs, rhs);
+ }
+
+ // Poisons the unused inlined SSO data if the current instance
+ // is inlined, else un-poisons the entire instance.
+ constexpr void poison();
+
+ // Un-poisons this instance.
+ constexpr void unpoison();
+
+ // Poisons the current instance. This is used on default initialization.
+ constexpr void poison_this();
// Returns true if the current instance is empty.
// The 'empty value' is an inlined data value of zero length.
- bool is_empty() const { return tag() == 0; }
+ bool is_empty() const { return rep_.tag() == 0; }
// Returns true if the current instance holds a tree value.
- bool is_tree() const { return (tag() & 1) != 0; }
+ bool is_tree() const { return (rep_.tag() & 1) != 0; }
// Returns true if the current instance holds a cordz_info value.
// Requires the current instance to hold a tree value.
bool is_profiled() const {
assert(is_tree());
- return as_tree_.cordz_info != kNullCordzInfo;
+ return rep_.cordz_info() != kNullCordzInfo;
}
// Returns true if either of the provided instances hold a cordz_info value.
@@ -489,7 +588,7 @@ class InlineData {
static bool is_either_profiled(const InlineData& data1,
const InlineData& data2) {
assert(data1.is_tree() && data2.is_tree());
- return (data1.as_tree_.cordz_info | data2.as_tree_.cordz_info) !=
+ return (data1.rep_.cordz_info() | data2.rep_.cordz_info()) !=
kNullCordzInfo;
}
@@ -498,8 +597,8 @@ class InlineData {
// Requires the current instance to hold a tree value.
CordzInfo* cordz_info() const {
assert(is_tree());
- intptr_t info = static_cast<intptr_t>(
- absl::big_endian::ToHost64(static_cast<uint64_t>(as_tree_.cordz_info)));
+ intptr_t info = static_cast<intptr_t>(absl::little_endian::ToHost64(
+ static_cast<uint64_t>(rep_.cordz_info())));
assert(info & 1);
return reinterpret_cast<CordzInfo*>(info - 1);
}
@@ -510,21 +609,21 @@ class InlineData {
void set_cordz_info(CordzInfo* cordz_info) {
assert(is_tree());
uintptr_t info = reinterpret_cast<uintptr_t>(cordz_info) | 1;
- as_tree_.cordz_info =
- static_cast<cordz_info_t>(absl::big_endian::FromHost64(info));
+ rep_.set_cordz_info(
+ static_cast<cordz_info_t>(absl::little_endian::FromHost64(info)));
}
// Resets the current cordz_info to null / empty.
void clear_cordz_info() {
assert(is_tree());
- as_tree_.cordz_info = kNullCordzInfo;
+ rep_.set_cordz_info(kNullCordzInfo);
}
// Returns a read only pointer to the character data inside this instance.
// Requires the current instance to hold inline data.
const char* as_chars() const {
assert(!is_tree());
- return as_chars_;
+ return rep_.as_chars();
}
// Returns a mutable pointer to the character data inside this instance.
@@ -542,20 +641,33 @@ class InlineData {
//
// It's an error to read from the returned pointer without a preceding write
// if the current instance does not hold inline data, i.e.: is_tree() == true.
- char* as_chars() { return as_chars_; }
+ char* as_chars() { return rep_.as_chars(); }
// Returns the tree value of this value.
// Requires the current instance to hold a tree value.
CordRep* as_tree() const {
assert(is_tree());
- return as_tree_.rep;
+ return rep_.tree();
+ }
+
+ void set_inline_data(const char* data, size_t n) {
+ ABSL_ASSERT(n <= kMaxInline);
+ unpoison();
+ rep_.set_tag(static_cast<int8_t>(n << 1));
+ SmallMemmove<true>(rep_.as_chars(), data, n);
+ poison();
+ }
+
+ void copy_max_inline_to(char* dst) const {
+ assert(!is_tree());
+ memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
}
// Initialize this instance to holding the tree value `rep`,
// initializing the cordz_info to null, i.e.: 'not profiled'.
void make_tree(CordRep* rep) {
- as_tree_.rep = rep;
- as_tree_.cordz_info = kNullCordzInfo;
+ unpoison();
+ rep_.make_tree(rep);
}
// Set the tree value of this instance to 'rep`.
@@ -563,54 +675,198 @@ class InlineData {
// Does not affect the value of cordz_info.
void set_tree(CordRep* rep) {
assert(is_tree());
- as_tree_.rep = rep;
+ rep_.set_tree(rep);
}
// Returns the size of the inlined character data inside this instance.
// Requires the current instance to hold inline data.
- size_t inline_size() const {
- assert(!is_tree());
- return tag() >> 1;
- }
+ size_t inline_size() const { return rep_.inline_size(); }
// Sets the size of the inlined character data inside this instance.
// Requires `size` to be <= kMaxInline.
// See the documentation on 'as_chars()' for more information and examples.
void set_inline_size(size_t size) {
- ABSL_ASSERT(size <= kMaxInline);
- tag() = static_cast<char>(size << 1);
+ unpoison();
+ rep_.set_inline_size(size);
+ poison();
+ }
+
+ // Compares 'this' inlined data with rhs. The comparison is a straightforward
+ // lexicographic comparison. `Compare()` returns values as follows:
+ //
+ // -1 'this' InlineData instance is smaller
+ // 0 the InlineData instances are equal
+ // 1 'this' InlineData instance larger
+ int Compare(const InlineData& rhs) const {
+ return Compare(rep_.SanitizerSafeCopy(), rhs.rep_.SanitizerSafeCopy());
}
private:
- // See cordz_info_t for forced alignment and size of `cordz_info` details.
- struct AsTree {
- explicit constexpr AsTree(absl::cord_internal::CordRep* tree)
- : rep(tree), cordz_info(kNullCordzInfo) {}
- // This union uses up extra space so that whether rep is 32 or 64 bits,
- // cordz_info will still start at the eighth byte, and the last
- // byte of cordz_info will still be the last byte of InlineData.
- union {
+ struct Rep {
+ // See cordz_info_t for forced alignment and size of `cordz_info` details.
+ struct AsTree {
+ explicit constexpr AsTree(absl::cord_internal::CordRep* tree)
+ : rep(tree) {}
+ cordz_info_t cordz_info = kNullCordzInfo;
absl::cord_internal::CordRep* rep;
- cordz_info_t unused_aligner;
};
- cordz_info_t cordz_info;
- };
- char& tag() { return reinterpret_cast<char*>(this)[kMaxInline]; }
- char tag() const { return reinterpret_cast<const char*>(this)[kMaxInline]; }
+ explicit Rep(DefaultInitType) {}
+ constexpr Rep() : data{0} {}
+ constexpr Rep(const Rep&) = default;
+ constexpr Rep& operator=(const Rep&) = default;
+
+ explicit constexpr Rep(CordRep* rep) : as_tree(rep) {}
+
+ explicit constexpr Rep(absl::string_view chars)
+ : data{static_cast<char>((chars.size() << 1)),
+ GetOrNull(chars, 0),
+ GetOrNull(chars, 1),
+ GetOrNull(chars, 2),
+ GetOrNull(chars, 3),
+ GetOrNull(chars, 4),
+ GetOrNull(chars, 5),
+ GetOrNull(chars, 6),
+ GetOrNull(chars, 7),
+ GetOrNull(chars, 8),
+ GetOrNull(chars, 9),
+ GetOrNull(chars, 10),
+ GetOrNull(chars, 11),
+ GetOrNull(chars, 12),
+ GetOrNull(chars, 13),
+ GetOrNull(chars, 14)} {}
+
+ // Disable sanitizer as we must always be able to read `tag`.
+ ABSL_CORD_INTERNAL_NO_SANITIZE
+ int8_t tag() const { return reinterpret_cast<const int8_t*>(this)[0]; }
+ void set_tag(int8_t rhs) { reinterpret_cast<int8_t*>(this)[0] = rhs; }
+
+ char* as_chars() { return data + 1; }
+ const char* as_chars() const { return data + 1; }
+
+ bool is_tree() const { return (tag() & 1) != 0; }
+
+ size_t inline_size() const {
+ ABSL_ASSERT(!is_tree());
+ return static_cast<size_t>(tag()) >> 1;
+ }
+
+ void set_inline_size(size_t size) {
+ ABSL_ASSERT(size <= kMaxInline);
+ set_tag(static_cast<int8_t>(size << 1));
+ }
+
+ CordRep* tree() const { return as_tree.rep; }
+ void set_tree(CordRep* rhs) { as_tree.rep = rhs; }
+
+ cordz_info_t cordz_info() const { return as_tree.cordz_info; }
+ void set_cordz_info(cordz_info_t rhs) { as_tree.cordz_info = rhs; }
+
+ void make_tree(CordRep* tree) {
+ as_tree.rep = tree;
+ as_tree.cordz_info = kNullCordzInfo;
+ }
+
+#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
+ Rep SanitizerSafeCopy() const {
+ Rep res;
+ if (is_tree()) {
+ res = *this;
+ } else {
+ res.set_tag(tag());
+ memcpy(res.as_chars(), as_chars(), inline_size());
+ }
+ return res;
+ }
+#else
+ const Rep& SanitizerSafeCopy() const { return *this; }
+#endif
- // If the data has length <= kMaxInline, we store it in `as_chars_`, and
- // store the size in the last char of `as_chars_` shifted left + 1.
- // Else we store it in a tree and store a pointer to that tree in
- // `as_tree_.rep` and store a tag in `tagged_size`.
- union {
- char as_chars_[kMaxInline + 1];
- AsTree as_tree_;
+ // If the data has length <= kMaxInline, we store it in `data`, and
+ // store the size in the first char of `data` shifted left + 1.
+ // Else we store it in a tree and store a pointer to that tree in
+ // `as_tree.rep` with a tagged pointer to make `tag() & 1` non zero.
+ union {
+ char data[kMaxInline + 1];
+ AsTree as_tree;
+ };
};
+
+ // Private implementation of `Compare()`
+ static inline int Compare(const Rep& lhs, const Rep& rhs) {
+ uint64_t x, y;
+ memcpy(&x, lhs.as_chars(), sizeof(x));
+ memcpy(&y, rhs.as_chars(), sizeof(y));
+ if (x == y) {
+ memcpy(&x, lhs.as_chars() + 7, sizeof(x));
+ memcpy(&y, rhs.as_chars() + 7, sizeof(y));
+ if (x == y) {
+ if (lhs.inline_size() == rhs.inline_size()) return 0;
+ return lhs.inline_size() < rhs.inline_size() ? -1 : 1;
+ }
+ }
+ x = absl::big_endian::FromHost64(x);
+ y = absl::big_endian::FromHost64(y);
+ return x < y ? -1 : 1;
+ }
+
+ Rep rep_;
};
static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+#ifdef ABSL_INTERNAL_CORD_HAVE_SANITIZER
+
+constexpr InlineData::InlineData(const InlineData& rhs) noexcept
+ : rep_(rhs.rep_.SanitizerSafeCopy()) {
+ poison();
+}
+
+inline InlineData& InlineData::operator=(const InlineData& rhs) noexcept {
+ unpoison();
+ rep_ = rhs.rep_.SanitizerSafeCopy();
+ poison();
+ return *this;
+}
+
+constexpr void InlineData::poison_this() {
+ if (!absl::is_constant_evaluated()) {
+ container_internal::SanitizerPoisonObject(this);
+ }
+}
+
+constexpr void InlineData::unpoison() {
+ if (!absl::is_constant_evaluated()) {
+ container_internal::SanitizerUnpoisonObject(this);
+ }
+}
+
+constexpr void InlineData::poison() {
+ if (!absl::is_constant_evaluated()) {
+ if (is_tree()) {
+ container_internal::SanitizerUnpoisonObject(this);
+ } else if (const size_t size = inline_size()) {
+ if (size < kMaxInline) {
+ const char* end = rep_.as_chars() + size;
+ container_internal::SanitizerPoisonMemoryRegion(end, kMaxInline - size);
+ }
+ } else {
+ container_internal::SanitizerPoisonObject(this);
+ }
+ }
+}
+
+#else // ABSL_INTERNAL_CORD_HAVE_SANITIZER
+
+constexpr InlineData::InlineData(const InlineData&) noexcept = default;
+inline InlineData& InlineData::operator=(const InlineData&) noexcept = default;
+
+constexpr void InlineData::poison_this() {}
+constexpr void InlineData::unpoison() {}
+constexpr void InlineData::poison() {}
+
+#endif // ABSL_INTERNAL_CORD_HAVE_SANITIZER
+
inline CordRepSubstring* CordRep::substring() {
assert(IsSubstring());
return static_cast<CordRepSubstring*>(this);
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.cc
index cacbf3da30..a86fdc0b4e 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.cc
@@ -17,11 +17,13 @@
#include <cassert>
#include <cstdint>
#include <iostream>
+#include <ostream>
#include <string>
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
+#include "absl/base/optimization.h"
#include "absl/strings/internal/cord_data_edge.h"
#include "absl/strings/internal/cord_internal.h"
#include "absl/strings/internal/cord_rep_consume.h"
@@ -55,8 +57,10 @@ inline bool exhaustive_validation() {
// Prints the entire tree structure or 'rep'. External callers should
// not specify 'depth' and leave it to its default (0) value.
// Rep may be a CordRepBtree tree, or a SUBSTRING / EXTERNAL / FLAT node.
-void DumpAll(const CordRep* rep, bool include_contents, std::ostream& stream,
- int depth = 0) {
+void DumpAll(const CordRep* rep,
+ bool include_contents,
+ std::ostream& stream,
+ size_t depth = 0) {
// Allow for full height trees + substring -> flat / external nodes.
assert(depth <= CordRepBtree::kMaxDepth + 2);
std::string sharing = const_cast<CordRep*>(rep)->refcount.IsOne()
@@ -283,7 +287,7 @@ struct StackOperations {
case CordRepBtree::kSelf:
return result.tree;
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
return result.tree;
}
@@ -499,7 +503,7 @@ OpResult CordRepBtree::SetEdge(bool owned, CordRep* edge, size_t delta) {
// open interval [begin, back) or [begin + 1, end) depending on `edge_type`.
// We conveniently cover both case using a constexpr `shift` being 0 or 1
// as `end :== back + 1`.
- result = {CopyRaw(), kCopied};
+ result = {CopyRaw(length), kCopied};
constexpr int shift = edge_type == kFront ? 1 : 0;
for (CordRep* r : Edges(begin() + shift, back() + shift)) {
CordRep::Ref(r);
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.h
index 2cbc09eca1..4209e51256 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree.h
@@ -95,8 +95,9 @@ class CordRepBtree : public CordRep {
// local stack variable compared to Cord's current near 400 bytes stack use.
// The maximum `height` value of a node is then `kMaxDepth - 1` as node height
// values start with a value of 0 for leaf nodes.
- static constexpr int kMaxDepth = 12;
- static constexpr int kMaxHeight = kMaxDepth - 1;
+ static constexpr size_t kMaxDepth = 12;
+ // See comments on height() for why this is an int and not a size_t.
+ static constexpr int kMaxHeight = static_cast<int>(kMaxDepth - 1);
// `Action` defines the action for unwinding changes done at the btree's leaf
// level that need to be propagated up to the parent node(s). Each operation
@@ -445,9 +446,9 @@ class CordRepBtree : public CordRep {
template <EdgeType edge_type>
static CordRepBtree* NewLeaf(absl::string_view data, size_t extra);
- // Creates a raw copy of this Btree node, copying all properties, but
- // without adding any references to existing edges.
- CordRepBtree* CopyRaw() const;
+ // Creates a raw copy of this Btree node with the specified length, copying
+ // all properties, but without adding any references to existing edges.
+ CordRepBtree* CopyRaw(size_t new_length) const;
// Creates a full copy of this Btree node, adding a reference on all edges.
CordRepBtree* Copy() const;
@@ -665,15 +666,28 @@ inline void CordRepBtree::Unref(absl::Span<CordRep* const> edges) {
}
}
-inline CordRepBtree* CordRepBtree::CopyRaw() const {
- auto* tree = static_cast<CordRepBtree*>(::operator new(sizeof(CordRepBtree)));
- memcpy(static_cast<void*>(tree), this, sizeof(CordRepBtree));
- new (&tree->refcount) RefcountAndFlags;
+inline CordRepBtree* CordRepBtree::CopyRaw(size_t new_length) const {
+ CordRepBtree* tree = new CordRepBtree;
+
+ // `length` and `refcount` are the first members of `CordRepBtree`.
+ // We initialize `length` using the given length, have `refcount` be set to
+ // ref = 1 through its default constructor, and copy all data beyond
+ // 'refcount' which starts with `tag` using a single memcpy: all contents
+ // except `refcount` is trivially copyable, and the compiler does not
+ // efficiently coalesce member-wise copy of these members.
+ // See https://gcc.godbolt.org/z/qY8zsca6z
+ // # LINT.IfChange(copy_raw)
+ tree->length = new_length;
+ uint8_t* dst = &tree->tag;
+ const uint8_t* src = &tag;
+ const ptrdiff_t offset = src - reinterpret_cast<const uint8_t*>(this);
+ memcpy(dst, src, sizeof(CordRepBtree) - static_cast<size_t>(offset));
return tree;
+ // # LINT.ThenChange()
}
inline CordRepBtree* CordRepBtree::Copy() const {
- CordRepBtree* tree = CopyRaw();
+ CordRepBtree* tree = CopyRaw(length);
for (CordRep* rep : Edges()) CordRep::Ref(rep);
return tree;
}
@@ -682,8 +696,7 @@ inline CordRepBtree* CordRepBtree::CopyToEndFrom(size_t begin,
size_t new_length) const {
assert(begin >= this->begin());
assert(begin <= this->end());
- CordRepBtree* tree = CopyRaw();
- tree->length = new_length;
+ CordRepBtree* tree = CopyRaw(new_length);
tree->set_begin(begin);
for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
return tree;
@@ -693,8 +706,7 @@ inline CordRepBtree* CordRepBtree::CopyBeginTo(size_t end,
size_t new_length) const {
assert(end <= capacity());
assert(end >= this->begin());
- CordRepBtree* tree = CopyRaw();
- tree->length = new_length;
+ CordRepBtree* tree = CopyRaw(new_length);
tree->set_end(end);
for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
return tree;
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc
index 9b896a3d09..6ed20c23a7 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc
@@ -90,7 +90,7 @@ CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
// edges that must be skipped.
while (height > 0) {
node = edge->btree();
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
node_[--height] = node;
index = node->begin();
edge = node->Edge(index);
@@ -101,7 +101,7 @@ CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
edge = node->Edge(index);
}
}
- index_[0] = index;
+ index_[0] = static_cast<uint8_t>(index);
return {edge, n};
}
@@ -126,7 +126,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
do {
length -= edge->length;
while (++index == node->end()) {
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
if (++height > height_) {
subtree->set_end(subtree_end);
if (length == 0) return {subtree, 0};
@@ -154,7 +154,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
// edges that must be read, adding 'down' nodes to `subtree`.
while (height > 0) {
node = edge->btree();
- index_[height] = index;
+ index_[height] = static_cast<uint8_t>(index);
node_[--height] = node;
index = node->begin();
edge = node->Edge(index);
@@ -178,7 +178,7 @@ ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
subtree->edges_[subtree_end++] = Substring(edge, 0, length);
}
subtree->set_end(subtree_end);
- index_[0] = index;
+ index_[0] = static_cast<uint8_t>(index);
return {tree, length};
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.cc
index ee14035410..dbe54cc400 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.cc
@@ -16,6 +16,7 @@
#include <cassert>
#include <cstdint>
+#include <utility>
#include "absl/base/config.h"
#include "absl/strings/internal/cord_internal.h"
@@ -24,11 +25,10 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
-CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) {
- assert(child != nullptr);
- if (child->IsCrc()) {
+CordRepCrc* CordRepCrc::New(CordRep* child, crc_internal::CrcCordState state) {
+ if (child != nullptr && child->IsCrc()) {
if (child->refcount.IsOne()) {
- child->crc()->crc = crc;
+ child->crc()->crc_cord_state = std::move(state);
return child->crc();
}
CordRep* old = child;
@@ -37,15 +37,17 @@ CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) {
CordRep::Unref(old);
}
auto* new_cordrep = new CordRepCrc;
- new_cordrep->length = child->length;
+ new_cordrep->length = child != nullptr ? child->length : 0;
new_cordrep->tag = cord_internal::CRC;
new_cordrep->child = child;
- new_cordrep->crc = crc;
+ new_cordrep->crc_cord_state = std::move(state);
return new_cordrep;
}
void CordRepCrc::Destroy(CordRepCrc* node) {
- CordRep::Unref(node->child);
+ if (node->child != nullptr) {
+ CordRep::Unref(node->child);
+ }
delete node;
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.h
index 5294b0d133..379d7a604e 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_crc.h
@@ -20,6 +20,7 @@
#include "absl/base/config.h"
#include "absl/base/optimization.h"
+#include "absl/crc/internal/crc_cord_state.h"
#include "absl/strings/internal/cord_internal.h"
namespace absl {
@@ -34,14 +35,14 @@ namespace cord_internal {
// the contained checksum is the user's responsibility.
struct CordRepCrc : public CordRep {
CordRep* child;
- uint32_t crc;
+ absl::crc_internal::CrcCordState crc_cord_state;
// Consumes `child` and returns a CordRepCrc prefixed tree containing `child`.
// If the specified `child` is itself a CordRepCrc node, then this method
- // either replaces the existing node, or directly updates the crc value in it
+ // either replaces the existing node, or directly updates the crc state in it
// depending on the node being shared or not, i.e.: refcount.IsOne().
- // `child` must not be null. Never returns null.
- static CordRepCrc* New(CordRep* child, uint32_t crc);
+ // `child` must only be null if the Cord is empty. Never returns null.
+ static CordRepCrc* New(CordRep* child, crc_internal::CrcCordState state);
// Destroys (deletes) the provided node. `node` must not be null.
static void Destroy(CordRepCrc* node);
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions.h
index c9ba14508a..ed108bf1b4 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_functions.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_CORDZ_FUNCTIONS_H_
-#define ABSL_STRINGS_CORDZ_FUNCTIONS_H_
+#ifndef ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
+#define ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
#include <stdint.h>
@@ -32,18 +32,10 @@ int32_t get_cordz_mean_interval();
// Sets the sample rate with the average interval between samples.
void set_cordz_mean_interval(int32_t mean_interval);
-// Enable cordz unless any of the following applies:
-// - no thread local support
-// - MSVC build
-// - Android build
-// - Apple build
-// - DLL build
-// Hashtablez is turned off completely in opensource builds.
-// MSVC's static atomics are dynamically initialized in debug mode, which breaks
-// sampling.
-#if defined(ABSL_HAVE_THREAD_LOCAL) && !defined(_MSC_VER) && \
- !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL) && \
- !defined(__ANDROID__) && !defined(__APPLE__)
+// Cordz is only enabled on Linux with thread_local support.
+#if defined(ABSL_INTERNAL_CORDZ_ENABLED)
+#error ABSL_INTERNAL_CORDZ_ENABLED cannot be set directly
+#elif defined(__linux__) && defined(ABSL_HAVE_THREAD_LOCAL)
#define ABSL_INTERNAL_CORDZ_ENABLED 1
#endif
@@ -82,4 +74,4 @@ inline void cordz_set_next_sample_for_testing(int64_t) {}
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_STRINGS_CORDZ_FUNCTIONS_H_
+#endif // ABSL_STRINGS_INTERNAL_CORDZ_FUNCTIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.h
index 5df53c782a..3c800b433f 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_handle.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_CORDZ_HANDLE_H_
-#define ABSL_STRINGS_CORDZ_HANDLE_H_
+#ifndef ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
+#define ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
#include <atomic>
#include <vector>
@@ -128,4 +128,4 @@ class CordzSnapshot : public CordzHandle {
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_STRINGS_CORDZ_HANDLE_H_
+#endif // ABSL_STRINGS_INTERNAL_CORDZ_HANDLE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
index dac3fd8b1b..530f33bed4 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.cc
@@ -35,7 +35,7 @@ namespace cord_internal {
using ::absl::base_internal::SpinLockHolder;
#ifdef ABSL_INTERNAL_NEED_REDUNDANT_CONSTEXPR_DECL
-constexpr int CordzInfo::kMaxStackDepth;
+constexpr size_t CordzInfo::kMaxStackDepth;
#endif
ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
@@ -291,7 +291,7 @@ CordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {
: src->method_;
}
-int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
+size_t CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
assert(stack);
if (src == nullptr) return 0;
if (src->parent_stack_depth_) {
@@ -302,11 +302,14 @@ int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
return src->stack_depth_;
}
-CordzInfo::CordzInfo(CordRep* rep, const CordzInfo* src,
+CordzInfo::CordzInfo(CordRep* rep,
+ const CordzInfo* src,
MethodIdentifier method)
: rep_(rep),
- stack_depth_(absl::GetStackTrace(stack_, /*max_depth=*/kMaxStackDepth,
- /*skip_count=*/1)),
+ stack_depth_(
+ static_cast<size_t>(absl::GetStackTrace(stack_,
+ /*max_depth=*/kMaxStackDepth,
+ /*skip_count=*/1))),
parent_stack_depth_(FillParentStack(src, parent_stack_)),
method_(method),
parent_method_(GetParentMethod(src)),
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.h
index 026d5b9981..17eaa91c77 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_info.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_STRINGS_CORDZ_INFO_H_
-#define ABSL_STRINGS_CORDZ_INFO_H_
+#ifndef ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
+#define ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
#include <atomic>
#include <cstdint>
@@ -196,7 +196,7 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
std::atomic<CordzInfo*> head ABSL_GUARDED_BY(mutex){nullptr};
};
- static constexpr int kMaxStackDepth = 64;
+ static constexpr size_t kMaxStackDepth = 64;
explicit CordzInfo(CordRep* rep, const CordzInfo* src,
MethodIdentifier method);
@@ -216,7 +216,7 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
// `stack_` depending on `parent_stack_` being empty, returning the size of
// the parent stack.
// Returns 0 if `src` is null.
- static int FillParentStack(const CordzInfo* src, void** stack);
+ static size_t FillParentStack(const CordzInfo* src, void** stack);
void ODRCheck() const {
#ifndef NDEBUG
@@ -244,8 +244,8 @@ class ABSL_LOCKABLE CordzInfo : public CordzHandle {
void* stack_[kMaxStackDepth];
void* parent_stack_[kMaxStackDepth];
- const int stack_depth_;
- const int parent_stack_depth_;
+ const size_t stack_depth_;
+ const size_t parent_stack_depth_;
const MethodIdentifier method_;
const MethodIdentifier parent_method_;
CordzUpdateTracker update_tracker_;
@@ -295,4 +295,4 @@ inline CordRep* CordzInfo::RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_) {
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_STRINGS_CORDZ_INFO_H_
+#endif // ABSL_STRINGS_INTERNAL_CORDZ_INFO_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.h
index 28a1d70ccc..b58022c3f9 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_sample_token.h
@@ -16,8 +16,8 @@
#include "absl/strings/internal/cordz_handle.h"
#include "absl/strings/internal/cordz_info.h"
-#ifndef ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
-#define ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
+#ifndef ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_
+#define ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -94,4 +94,4 @@ class CordzSampleToken : public CordzSnapshot {
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
+#endif // ABSL_STRINGS_INTERNAL_CORDZ_SAMPLE_TOKEN_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_statistics.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_statistics.h
index 5707190577..9f558df494 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_statistics.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cordz_statistics.h
@@ -45,12 +45,12 @@ struct CordzStatistics {
};
// The size of the cord in bytes. This matches the result of Cord::size().
- int64_t size = 0;
+ size_t size = 0;
// The estimated memory used by the sampled cord. This value matches the
// value as reported by Cord::EstimatedMemoryUsage().
// A value of 0 implies the property has not been recorded.
- int64_t estimated_memory_usage = 0;
+ size_t estimated_memory_usage = 0;
// The effective memory used by the sampled cord, inversely weighted by the
// effective indegree of each allocated node. This is a representation of the
@@ -59,14 +59,14 @@ struct CordzStatistics {
// by multiple Cord instances, and for cases where a Cord includes the same
// node multiple times (either directly or indirectly).
// A value of 0 implies the property has not been recorded.
- int64_t estimated_fair_share_memory_usage = 0;
+ size_t estimated_fair_share_memory_usage = 0;
// The total number of nodes referenced by this cord.
// For ring buffer Cords, this includes the 'ring buffer' node.
// For btree Cords, this includes all 'CordRepBtree' tree nodes as well as all
// the substring, flat and external nodes referenced by the tree.
// A value of 0 implies the property has not been recorded.
- int64_t node_count = 0;
+ size_t node_count = 0;
// Detailed node counts per type
NodeCounts node_counts;
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc
new file mode 100644
index 0000000000..a084568fa8
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.cc
@@ -0,0 +1,93 @@
+// 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/strings/internal/damerau_levenshtein_distance.h"
+
+#include <algorithm>
+#include <array>
+#include <numeric>
+
+#include "absl/strings/string_view.h"
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+// Calculate DamerauLevenshtein (adjacent transpositions) distance
+// between two strings,
+// https://en.wikipedia.org/wiki/Damerau%E2%80%93Levenshtein_distance. The
+// algorithm follows the condition that no substring is edited more than once.
+// While this can reduce is larger distance, it's a) a much simpler algorithm
+// and b) more realistic for the case that typographic mistakes should be
+// detected.
+// When the distance is larger than cutoff, or one of the strings has more
+// than MAX_SIZE=100 characters, the code returns min(MAX_SIZE, cutoff) + 1.
+uint8_t CappedDamerauLevenshteinDistance(absl::string_view s1,
+ absl::string_view s2, uint8_t cutoff) {
+ const uint8_t MAX_SIZE = 100;
+ const uint8_t _cutoff = std::min(MAX_SIZE, cutoff);
+ const uint8_t cutoff_plus_1 = static_cast<uint8_t>(_cutoff + 1);
+
+ if (s1.size() > s2.size()) std::swap(s1, s2);
+ if (s1.size() + _cutoff < s2.size() || s2.size() > MAX_SIZE)
+ return cutoff_plus_1;
+
+ if (s1.empty())
+ return static_cast<uint8_t>(s2.size());
+
+ // Lower diagonal bound: y = x - lower_diag
+ const uint8_t lower_diag =
+ _cutoff - static_cast<uint8_t>(s2.size() - s1.size());
+ // Upper diagonal bound: y = x + upper_diag
+ const uint8_t upper_diag = _cutoff;
+
+ // d[i][j] is the number of edits required to convert s1[0, i] to s2[0, j]
+ std::array<std::array<uint8_t, MAX_SIZE + 2>, MAX_SIZE + 2> d;
+ std::iota(d[0].begin(), d[0].begin() + upper_diag + 1, 0);
+ d[0][cutoff_plus_1] = cutoff_plus_1;
+ for (size_t i = 1; i <= s1.size(); ++i) {
+ // Deduce begin of relevant window.
+ size_t j_begin = 1;
+ if (i > lower_diag) {
+ j_begin = i - lower_diag;
+ d[i][j_begin - 1] = cutoff_plus_1;
+ } else {
+ d[i][0] = static_cast<uint8_t>(i);
+ }
+
+ // Deduce end of relevant window.
+ size_t j_end = i + upper_diag;
+ if (j_end > s2.size()) {
+ j_end = s2.size();
+ } else {
+ d[i][j_end + 1] = cutoff_plus_1;
+ }
+
+ for (size_t j = j_begin; j <= j_end; ++j) {
+ const uint8_t deletion_distance = d[i - 1][j] + 1;
+ const uint8_t insertion_distance = d[i][j - 1] + 1;
+ const uint8_t mismatched_tail_cost = s1[i - 1] == s2[j - 1] ? 0 : 1;
+ const uint8_t mismatch_distance = d[i - 1][j - 1] + mismatched_tail_cost;
+ uint8_t transposition_distance = _cutoff + 1;
+ if (i > 1 && j > 1 && s1[i - 1] == s2[j - 2] && s1[i - 2] == s2[j - 1])
+ transposition_distance = d[i - 2][j - 2] + 1;
+ d[i][j] = std::min({cutoff_plus_1, deletion_distance, insertion_distance,
+ mismatch_distance, transposition_distance});
+ }
+ }
+ return d[s1.size()][s2.size()];
+}
+
+} // namespace strings_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h b/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h
new file mode 100644
index 0000000000..7a4bd64462
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/damerau_levenshtein_distance.h
@@ -0,0 +1,34 @@
+// 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_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_
+#define ABSL_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_
+
+#include <cstdint>
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+// Calculate DamerauLevenshtein distance between two strings.
+// When the distance is larger than cutoff, the code just returns cutoff + 1.
+uint8_t CappedDamerauLevenshteinDistance(absl::string_view s1,
+ absl::string_view s2, uint8_t cutoff);
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_DAMERAU_LEVENSHTEIN_DISTANCE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
index cfea096111..8bd0890d60 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.cc
@@ -28,19 +28,11 @@ size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
// Base64 encodes three bytes of input at a time. If the input is not
// divisible by three, we pad as appropriate.
//
- // (from https://tools.ietf.org/html/rfc3548)
- // Special processing is performed if fewer than 24 bits are available
- // at the end of the data being encoded. A full encoding quantum is
- // always completed at the end of a quantity. When fewer than 24 input
- // bits are available in an input group, zero bits are added (on the
- // right) to form an integral number of 6-bit groups. Padding at the
- // end of the data is performed using the '=' character. Since all base
- // 64 input is an integral number of octets, only the following cases
- // can arise:
-
// Base64 encodes each three bytes of input into four bytes of output.
size_t len = (input_len / 3) * 4;
+ // Since all base 64 input is an integral number of octets, only the following
+ // cases can arise:
if (input_len % 3 == 0) {
// (from https://tools.ietf.org/html/rfc3548)
// (1) the final quantum of encoding input is an integral multiple of 24
@@ -83,6 +75,16 @@ size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
char* const limit_dest = dest + szdest;
const unsigned char* const limit_src = src + szsrc;
+ // (from https://tools.ietf.org/html/rfc3548)
+ // Special processing is performed if fewer than 24 bits are available
+ // at the end of the data being encoded. A full encoding quantum is
+ // always completed at the end of a quantity. When fewer than 24 input
+ // bits are available in an input group, zero bits are added (on the
+ // right) to form an integral number of 6-bit groups.
+ //
+ // If do_padding is true, padding at the end of the data is performed. This
+ // output padding uses the '=' character.
+
// Three bytes of data encodes to four characters of cyphertext.
// So we can pump through three-byte chunks atomically.
if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3.
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
index 6a9ce602d9..b04033ffc9 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping.h
@@ -25,19 +25,17 @@ namespace strings_internal {
ABSL_CONST_INIT extern const char kBase64Chars[];
-// Calculates how long a string will be when it is base64 encoded given its
-// length and whether or not the result should be padded.
+// Calculates the length of a Base64 encoding (RFC 4648) of a string of length
+// `input_len`, with or without padding per `do_padding`. Note that 'web-safe'
+// encoding (section 5 of the RFC) does not change this length.
size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);
-// Base64-encodes `src` using the alphabet provided in `base64` and writes the
-// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
-// until its length is a multiple of 3. Returns the length of `dest`.
+// Base64-encodes `src` using the alphabet provided in `base64` (which
+// determines whether to do web-safe encoding or not) and writes the result to
+// `dest`. If `do_padding` is true, `dest` is padded with '=' chars until its
+// length is a multiple of 3. Returns the length of `dest`.
size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
size_t szdest, const char* base64, bool do_padding);
-
-// Base64-encodes `src` using the alphabet provided in `base64` and writes the
-// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
-// until its length is a multiple of 3.
template <typename String>
void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
bool do_padding, const char* base64_chars) {
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h b/contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h
new file mode 100644
index 0000000000..55a0850829
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/has_absl_stringify.h
@@ -0,0 +1,55 @@
+// 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_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_
+#define ABSL_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace strings_internal {
+
+// This is an empty class not intended to be used. It exists so that
+// `HasAbslStringify` can reference a universal class rather than needing to be
+// copied for each new sink.
+class UnimplementedSink {
+ public:
+ void Append(size_t count, char ch);
+
+ void Append(string_view v);
+
+ // Support `absl::Format(&sink, format, args...)`.
+ friend void AbslFormatFlush(UnimplementedSink* sink, absl::string_view v);
+};
+
+template <typename T, typename = void>
+struct HasAbslStringify : std::false_type {};
+
+template <typename T>
+struct HasAbslStringify<
+ T, std::enable_if_t<std::is_void<decltype(AbslStringify(
+ std::declval<strings_internal::UnimplementedSink&>(),
+ std::declval<const T&>()))>::value>> : std::true_type {};
+
+} // namespace strings_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_HAS_ABSL_STRINGIFY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
index 2519c6881e..44996a7549 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/memutil.cc
@@ -54,10 +54,11 @@ size_t memspn(const char* s, size_t slen, const char* accept) {
cont:
c = *p++;
- if (slen-- == 0) return p - 1 - s;
+ if (slen-- == 0)
+ return static_cast<size_t>(p - 1 - s);
for (spanp = accept; (sc = *spanp++) != '\0';)
if (sc == c) goto cont;
- return p - 1 - s;
+ return static_cast<size_t>(p - 1 - s);
}
size_t memcspn(const char* s, size_t slen, const char* reject) {
@@ -68,9 +69,10 @@ size_t memcspn(const char* s, size_t slen, const char* reject) {
while (slen-- != 0) {
c = *p++;
for (spanp = reject; (sc = *spanp++) != '\0';)
- if (sc == c) return p - 1 - s;
+ if (sc == c)
+ return static_cast<size_t>(p - 1 - s);
}
- return p - s;
+ return static_cast<size_t>(p - s);
}
char* mempbrk(const char* s, size_t slen, const char* accept) {
@@ -97,8 +99,9 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
const char* hayend = phaystack + haylen - neelen + 1;
// A static cast is used here to work around the fact that memchr returns
// a void* on Posix-compliant systems and const void* on Windows.
- while ((match = static_cast<const char*>(
- memchr(phaystack, pneedle[0], hayend - phaystack)))) {
+ while (
+ (match = static_cast<const char*>(memchr(
+ phaystack, pneedle[0], static_cast<size_t>(hayend - phaystack))))) {
if (memcmp(match, pneedle, neelen) == 0)
return match;
else
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
index dc6cfe1686..a0e5ec08c2 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -14,20 +14,27 @@
#include "absl/strings/internal/ostringstream.h"
+#include <cassert>
+#include <cstddef>
+#include <ios>
+#include <streambuf>
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
-OStringStream::Buf::int_type OStringStream::overflow(int c) {
- assert(s_);
- if (!Buf::traits_type::eq_int_type(c, Buf::traits_type::eof()))
- s_->push_back(static_cast<char>(c));
+OStringStream::Streambuf::int_type OStringStream::Streambuf::overflow(int c) {
+ assert(str_);
+ if (!std::streambuf::traits_type::eq_int_type(
+ c, std::streambuf::traits_type::eof()))
+ str_->push_back(static_cast<char>(c));
return 1;
}
-std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) {
- assert(s_);
- s_->append(s, static_cast<size_t>(n));
+std::streamsize OStringStream::Streambuf::xsputn(const char* s,
+ std::streamsize n) {
+ assert(str_);
+ str_->append(s, static_cast<size_t>(n));
return n;
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
index d25d60473f..c0e237dbe8 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/ostringstream.h
@@ -16,11 +16,13 @@
#define ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
#include <cassert>
+#include <ios>
#include <ostream>
#include <streambuf>
#include <string>
+#include <utility>
-#include "absl/base/port.h"
+#include "absl/base/config.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -60,26 +62,49 @@ namespace strings_internal {
// strm << 3.14;
//
// Note: flush() has no effect. No reason to call it.
-class OStringStream : private std::basic_streambuf<char>, public std::ostream {
+class OStringStream final : public std::ostream {
public:
// The argument can be null, in which case you'll need to call str(p) with a
// non-null argument before you can write to the stream.
//
// The destructor of OStringStream doesn't use the std::string. It's OK to
// destroy the std::string before the stream.
- explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {}
+ explicit OStringStream(std::string* str)
+ : std::ostream(&buf_), buf_(str) {}
+ OStringStream(OStringStream&& that)
+ : std::ostream(std::move(static_cast<std::ostream&>(that))),
+ buf_(that.buf_) {
+ rdbuf(&buf_);
+ }
+ OStringStream& operator=(OStringStream&& that) {
+ std::ostream::operator=(std::move(static_cast<std::ostream&>(that)));
+ buf_ = that.buf_;
+ rdbuf(&buf_);
+ return *this;
+ }
- std::string* str() { return s_; }
- const std::string* str() const { return s_; }
- void str(std::string* s) { s_ = s; }
+ std::string* str() { return buf_.str(); }
+ const std::string* str() const { return buf_.str(); }
+ void str(std::string* str) { buf_.str(str); }
private:
- using Buf = std::basic_streambuf<char>;
+ class Streambuf final : public std::streambuf {
+ public:
+ explicit Streambuf(std::string* str) : str_(str) {}
+ Streambuf(const Streambuf&) = default;
+ Streambuf& operator=(const Streambuf&) = default;
- Buf::int_type overflow(int c) override;
- std::streamsize xsputn(const char* s, std::streamsize n) override;
+ std::string* str() { return str_; }
+ const std::string* str() const { return str_; }
+ void str(std::string* str) { str_ = str; }
- std::string* s_;
+ protected:
+ int_type overflow(int c) override;
+ std::streamsize xsputn(const char* s, std::streamsize n) override;
+
+ private:
+ std::string* str_;
+ } buf_;
};
} // namespace strings_internal
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
index 02aeeebec7..018dd05235 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -77,7 +77,7 @@ class IntDigits {
v >>= 3;
} while (v);
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// Print the signed or unsigned integer as decimal.
@@ -86,7 +86,8 @@ class IntDigits {
void PrintAsDec(T v) {
static_assert(std::is_integral<T>::value, "");
start_ = storage_;
- size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
+ size_ = static_cast<size_t>(numbers_internal::FastIntToBuffer(v, storage_) -
+ storage_);
}
void PrintAsDec(int128 v) {
@@ -115,7 +116,7 @@ class IntDigits {
if (add_neg) {
*--p = '-';
}
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
start_ = p;
}
@@ -138,7 +139,7 @@ class IntDigits {
++p;
}
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// Print the unsigned integer as hex using uppercase.
@@ -154,7 +155,7 @@ class IntDigits {
v >>= 4;
} while (v);
start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
+ size_ = static_cast<size_t>(storage_ + sizeof(storage_) - p);
}
// The printed value including the '-' sign if available.
@@ -208,10 +209,12 @@ string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
return {};
}
-bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertCharImpl(char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
+ if (conv.width() >= 0)
+ fill = static_cast<size_t>(conv.width());
ReducePadding(1, &fill);
if (!conv.has_left_flag()) sink->Append(fill, ' ');
sink->Append(1, v);
@@ -225,7 +228,8 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
// Print as a sequence of Substrings:
// [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
size_t fill = 0;
- if (conv.width() >= 0) fill = conv.width();
+ if (conv.width() >= 0)
+ fill = static_cast<size_t>(conv.width());
string_view formatted = as_digits.without_neg_or_zero();
ReducePadding(formatted, &fill);
@@ -236,10 +240,9 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
string_view base_indicator = BaseIndicator(as_digits, conv);
ReducePadding(base_indicator, &fill);
- int precision = conv.precision();
- bool precision_specified = precision >= 0;
- if (!precision_specified)
- precision = 1;
+ bool precision_specified = conv.precision() >= 0;
+ size_t precision =
+ precision_specified ? static_cast<size_t>(conv.precision()) : size_t{1};
if (conv.has_alt_flag() &&
conv.conversion_char() == FormatConversionCharInternal::o) {
@@ -247,7 +250,7 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
// "For o conversion, it increases the precision (if necessary) to
// force the first digit of the result to be zero."
if (formatted.empty() || *formatted.begin() != '0') {
- int needed = static_cast<int>(formatted.size()) + 1;
+ size_t needed = formatted.size() + 1;
precision = std::max(precision, needed);
}
}
@@ -275,19 +278,71 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
return true;
}
+template <typename T,
+ typename std::enable_if<(std::is_integral<T>::value &&
+ std::is_signed<T>::value) ||
+ std::is_same<T, int128>::value,
+ int>::type = 0>
+constexpr auto ConvertV(T) {
+ return FormatConversionCharInternal::d;
+}
+
+template <typename T,
+ typename std::enable_if<(std::is_integral<T>::value &&
+ std::is_unsigned<T>::value) ||
+ std::is_same<T, uint128>::value,
+ int>::type = 0>
+constexpr auto ConvertV(T) {
+ return FormatConversionCharInternal::u;
+}
+
+template <typename T>
+bool ConvertFloatArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ conv.set_conversion_char(FormatConversionCharInternal::g);
+ }
+
+ return FormatConversionCharIsFloat(conv.conversion_char()) &&
+ ConvertFloatImpl(v, conv, sink);
+}
+
+inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ if (conv.is_basic()) {
+ sink->Append(v);
+ return true;
+ }
+ return sink->PutPaddedString(v, conv.width(), conv.precision(),
+ conv.has_left_flag());
+}
+
+} // namespace
+
+bool ConvertBoolArg(bool v, FormatSinkImpl *sink) {
+ if (v) {
+ sink->Append("true");
+ } else {
+ sink->Append("false");
+ }
+ return true;
+}
+
template <typename T>
-bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
using U = typename MakeUnsigned<T>::type;
IntDigits as_digits;
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ conv.set_conversion_char(ConvertV(T{}));
+ }
+
// This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
// it to complain about a switch/case type mismatch, even though both are
// FormatConverionChar. Likely this is because at this point
// FormatConversionChar is declared, but not defined.
switch (static_cast<uint8_t>(conv.conversion_char())) {
case static_cast<uint8_t>(FormatConversionCharInternal::c):
- return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+ return ConvertCharImpl(static_cast<char>(v), conv, sink);
case static_cast<uint8_t>(FormatConversionCharInternal::o):
as_digits.PrintAsOct(static_cast<U>(v));
@@ -320,7 +375,7 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
return ConvertFloatImpl(static_cast<double>(v), conv, sink);
default:
- ABSL_ASSUME(false);
+ ABSL_ASSUME(false);
}
if (conv.is_basic()) {
@@ -330,24 +385,37 @@ bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
return ConvertIntImplInnerSlow(as_digits, conv, sink);
}
-template <typename T>
-bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return FormatConversionCharIsFloat(conv.conversion_char()) &&
- ConvertFloatImpl(v, conv, sink);
-}
-
-inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- if (conv.is_basic()) {
- sink->Append(v);
- return true;
- }
- return sink->PutPaddedString(v, conv.width(), conv.precision(),
- conv.has_left_flag());
-}
-
-} // namespace
+template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<signed char>(signed char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<unsigned char>(unsigned char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<short>(short v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<unsigned short>(unsigned short v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<unsigned int>(unsigned int v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<long>(long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<unsigned long>(unsigned long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<long long>(long long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
+template bool ConvertIntArg<unsigned long long>(unsigned long long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink);
// ==================== Strings ====================
StringConvertResult FormatConvertImpl(const std::string &v,
@@ -375,7 +443,7 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
len = std::strlen(v);
} else {
// If precision is set, we look for the NUL-terminator on the valid range.
- len = std::find(v, v + conv.precision(), '\0') - v;
+ len = static_cast<size_t>(std::find(v, v + conv.precision(), '\0') - v);
}
return {ConvertStringArg(string_view(v, len), conv, sink)};
}
@@ -410,19 +478,18 @@ FloatingConvertResult FormatConvertImpl(long double v,
}
// ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(char v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(signed char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(signed char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(unsigned char v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+CharConvertResult FormatConvertImpl(unsigned char v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
index b9dda90901..e4b1662827 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/arg.h
@@ -18,6 +18,7 @@
#include <string.h>
#include <wchar.h>
+#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <limits>
@@ -25,10 +26,12 @@
#include <sstream>
#include <string>
#include <type_traits>
+#include <utility>
#include "absl/base/port.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
+#include "absl/strings/internal/has_absl_stringify.h"
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/string_view.h"
@@ -45,6 +48,24 @@ class FormatConversionSpec;
namespace str_format_internal {
+template <FormatConversionCharSet C>
+struct ArgConvertResult {
+ bool value;
+};
+
+using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::c,
+ FormatConversionCharSetInternal::kNumeric,
+ FormatConversionCharSetInternal::kStar,
+ FormatConversionCharSetInternal::v)>;
+using FloatingConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::kFloating,
+ FormatConversionCharSetInternal::v)>;
+using CharConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::c,
+ FormatConversionCharSetInternal::kNumeric,
+ FormatConversionCharSetInternal::kStar)>;
+
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
@@ -55,7 +76,50 @@ struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
std::declval<FormatSink*>()))>>
: std::true_type {};
-void AbslFormatConvert(); // Stops the lexical name lookup
+// These declarations prevent ADL lookup from continuing in absl namespaces,
+// we are deliberately using these as ADL hooks and want them to consider
+// non-absl namespaces only.
+void AbslFormatConvert();
+void AbslStringify();
+
+template <typename T>
+bool ConvertIntArg(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
+
+// Forward declarations of internal `ConvertIntArg` function template
+// instantiations are here to avoid including the template body in the headers
+// and instantiating it in large numbers of translation units. Explicit
+// instantiations can be found in "absl/strings/internal/str_format/arg.cc"
+extern template bool ConvertIntArg<char>(char v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<signed char>(signed char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<unsigned char>(unsigned char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<short>(short v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<unsigned short>( // NOLINT
+ unsigned short v, FormatConversionSpecImpl conv, // NOLINT
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<int>(int v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<unsigned int>(unsigned int v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<long>( // NOLINT
+ long v, FormatConversionSpecImpl conv, FormatSinkImpl* sink); // NOLINT
+extern template bool ConvertIntArg<unsigned long>(unsigned long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<long long>(long long v, // NOLINT
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+extern template bool ConvertIntArg<unsigned long long>( // NOLINT
+ unsigned long long v, FormatConversionSpecImpl conv, // NOLINT
+ FormatSinkImpl* sink);
+
template <typename T>
auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink)
@@ -72,6 +136,39 @@ auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
}
template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink)
+ -> std::enable_if_t<std::is_enum<T>::value &&
+ std::is_void<decltype(AbslStringify(
+ std::declval<FormatSink&>(), v))>::value,
+ IntegralConvertResult> {
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ using FormatSinkT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+ auto fs = sink->Wrap<FormatSinkT>();
+ AbslStringify(fs, v);
+ return {true};
+ } else {
+ return {ConvertIntArg(
+ static_cast<typename std::underlying_type<T>::type>(v), conv, sink)};
+ }
+}
+
+template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl,
+ FormatSinkImpl* sink)
+ -> std::enable_if_t<!std::is_enum<T>::value &&
+ std::is_void<decltype(AbslStringify(
+ std::declval<FormatSink&>(), v))>::value,
+ ArgConvertResult<FormatConversionCharSetInternal::v>> {
+ using FormatSinkT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+ auto fs = sink->Wrap<FormatSinkT>();
+ AbslStringify(fs, v);
+ return {true};
+}
+
+template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
@@ -96,11 +193,6 @@ struct VoidPtr {
};
template <FormatConversionCharSet C>
-struct ArgConvertResult {
- bool value;
-};
-
-template <FormatConversionCharSet C>
constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
return C;
}
@@ -110,8 +202,8 @@ constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
return C;
}
-using StringConvertResult =
- ArgConvertResult<FormatConversionCharSetInternal::s>;
+using StringConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>;
ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
@@ -173,12 +265,7 @@ StringConvertResult FormatConvertImpl(const AbslCord& value,
return {true};
}
-using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::c,
- FormatConversionCharSetInternal::kNumeric,
- FormatConversionCharSetInternal::kStar)>;
-using FloatingConvertResult =
- ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
+bool ConvertBoolArg(bool v, FormatSinkImpl* sink);
// Floats.
FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
@@ -190,14 +277,14 @@ FloatingConvertResult FormatConvertImpl(long double v,
FormatSinkImpl* sink);
// Chars.
-IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(signed char v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned char v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
+CharConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+CharConvertResult FormatConvertImpl(signed char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+CharConvertResult FormatConvertImpl(unsigned char v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
@@ -228,9 +315,16 @@ IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
IntegralConvertResult FormatConvertImpl(uint128 v,
FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
+
+// This function needs to be a template due to ambiguity regarding type
+// conversions.
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
+ if (conv.conversion_char() == FormatConversionCharInternal::v) {
+ return {ConvertBoolArg(v, sink)};
+ }
+
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
@@ -238,7 +332,8 @@ IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
// FormatArgImpl will use the underlying Convert functions instead.
template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
- !HasUserDefinedConvert<T>::value,
+ !HasUserDefinedConvert<T>::value &&
+ !strings_internal::HasAbslStringify<T>::value,
IntegralConvertResult>::type
FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
@@ -301,11 +396,11 @@ struct FormatArgImplFriend {
template <typename Arg>
constexpr FormatConversionCharSet ArgumentToConv() {
- return absl::str_format_internal::ExtractCharSet(
- decltype(str_format_internal::FormatConvertImpl(
- std::declval<const Arg&>(),
- std::declval<const FormatConversionSpecImpl&>(),
- std::declval<FormatSinkImpl*>())){});
+ using ConvResult = decltype(str_format_internal::FormatConvertImpl(
+ std::declval<const Arg&>(),
+ std::declval<const FormatConversionSpecImpl&>(),
+ std::declval<FormatSinkImpl*>()));
+ return absl::str_format_internal::ExtractCharSet(ConvResult{});
}
// A type-erased handle to a format argument.
@@ -351,7 +446,8 @@ class FormatArgImpl {
template <typename T, typename = void>
struct DecayType {
static constexpr bool kHasUserDefined =
- str_format_internal::HasUserDefinedConvert<T>::value;
+ str_format_internal::HasUserDefinedConvert<T>::value ||
+ strings_internal::HasAbslStringify<T>::value;
using type = typename std::conditional<
!kHasUserDefined && std::is_convertible<T, const char*>::value,
const char*,
@@ -363,6 +459,7 @@ class FormatArgImpl {
struct DecayType<T,
typename std::enable_if<
!str_format_internal::HasUserDefinedConvert<T>::value &&
+ !strings_internal::HasAbslStringify<T>::value &&
std::is_enum<T>::value>::type> {
using type = typename std::underlying_type<T>::type;
};
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
index c988ba8fd2..77a4222337 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.cc
@@ -32,7 +32,8 @@ inline bool BindFromPosition(int position, int* value,
return false;
}
// -1 because positions are 1-based
- return FormatArgImplFriend::ToInt(pack[position - 1], value);
+ return FormatArgImplFriend::ToInt(pack[static_cast<size_t>(position) - 1],
+ value);
}
class ArgContext {
@@ -56,7 +57,7 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
const FormatArgImpl* arg = nullptr;
int arg_position = unbound->arg_position;
if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
- arg = &pack_[arg_position - 1]; // 1-based
+ arg = &pack_[static_cast<size_t>(arg_position - 1)]; // 1-based
if (unbound->flags != Flags::kBasic) {
int width = unbound->width.value();
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
index 80f29654b3..b73c50287c 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/bind.h
@@ -235,9 +235,10 @@ class StreamedWrapper {
private:
template <typename S>
- friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
- const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* out);
+ friend ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::v)>
+ FormatConvertImpl(const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* out);
const T& v_;
};
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
index 4fd19d13ae..eab6ab9d00 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/checker.h
@@ -15,8 +15,11 @@
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
+#include <algorithm>
+
#include "absl/base/attributes.h"
#include "absl/strings/internal/str_format/arg.h"
+#include "absl/strings/internal/str_format/constexpr_parser.h"
#include "absl/strings/internal/str_format/extension.h"
// Compile time check support for entry points.
@@ -36,297 +39,56 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-constexpr bool AllOf() { return true; }
-
-template <typename... T>
-constexpr bool AllOf(bool b, T... t) {
- return b && AllOf(t...);
-}
-
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-constexpr bool ContainsChar(const char* chars, char c) {
- return *chars == c || (*chars && ContainsChar(chars + 1, c));
-}
-
-// A constexpr compatible list of Convs.
-struct ConvList {
- const FormatConversionCharSet* array;
- int count;
-
- // We do the bound check here to avoid having to do it on the callers.
- // Returning an empty FormatConversionCharSet has the same effect as
- // short circuiting because it will never match any conversion.
- constexpr FormatConversionCharSet operator[](int i) const {
- return i < count ? array[i] : FormatConversionCharSet{};
- }
-
- constexpr ConvList without_front() const {
- return count != 0 ? ConvList{array + 1, count - 1} : *this;
- }
-};
-
-template <size_t count>
-struct ConvListT {
- // Make sure the array has size > 0.
- FormatConversionCharSet list[count ? count : 1];
-};
-
-constexpr char GetChar(string_view str, size_t index) {
- return index < str.size() ? str[index] : char{};
-}
-
-constexpr string_view ConsumeFront(string_view str, size_t len = 1) {
- return len <= str.size() ? string_view(str.data() + len, str.size() - len)
- : string_view();
-}
-
-constexpr string_view ConsumeAnyOf(string_view format, const char* chars) {
- return ContainsChar(chars, GetChar(format, 0))
- ? ConsumeAnyOf(ConsumeFront(format), chars)
- : format;
-}
-
-constexpr bool IsDigit(char c) { return c >= '0' && c <= '9'; }
-
-// Helper class for the ParseDigits function.
-// It encapsulates the two return values we need there.
-struct Integer {
- string_view format;
- int value;
-
- // If the next character is a '$', consume it.
- // Otherwise, make `this` an invalid positional argument.
- constexpr Integer ConsumePositionalDollar() const {
- return GetChar(format, 0) == '$' ? Integer{ConsumeFront(format), value}
- : Integer{format, 0};
- }
-};
-
-constexpr Integer ParseDigits(string_view format, int value = 0) {
- return IsDigit(GetChar(format, 0))
- ? ParseDigits(ConsumeFront(format),
- 10 * value + GetChar(format, 0) - '0')
- : Integer{format, value};
-}
-
-// Parse digits for a positional argument.
-// The parsing also consumes the '$'.
-constexpr Integer ParsePositional(string_view format) {
- return ParseDigits(format).ConsumePositionalDollar();
-}
-
-// Parses a single conversion specifier.
-// See ConvParser::Run() for post conditions.
-class ConvParser {
- constexpr ConvParser SetFormat(string_view format) const {
- return ConvParser(format, args_, error_, arg_position_, is_positional_);
- }
-
- constexpr ConvParser SetArgs(ConvList args) const {
- return ConvParser(format_, args, error_, arg_position_, is_positional_);
- }
-
- constexpr ConvParser SetError(bool error) const {
- return ConvParser(format_, args_, error_ || error, arg_position_,
- is_positional_);
- }
-
- constexpr ConvParser SetArgPosition(int arg_position) const {
- return ConvParser(format_, args_, error_, arg_position, is_positional_);
- }
-
- // Consumes the next arg and verifies that it matches `conv`.
- // `error_` is set if there is no next arg or if it doesn't match `conv`.
- constexpr ConvParser ConsumeNextArg(char conv) const {
- return SetArgs(args_.without_front()).SetError(!Contains(args_[0], conv));
- }
-
- // Verify that positional argument `i.value` matches `conv`.
- // `error_` is set if `i.value` is not a valid argument or if it doesn't
- // match.
- constexpr ConvParser VerifyPositional(Integer i, char conv) const {
- return SetFormat(i.format).SetError(!Contains(args_[i.value - 1], conv));
- }
-
- // Parse the position of the arg and store it in `arg_position_`.
- constexpr ConvParser ParseArgPosition(Integer arg) const {
- return SetFormat(arg.format).SetArgPosition(arg.value);
- }
-
- // Consume the flags.
- constexpr ConvParser ParseFlags() const {
- return SetFormat(ConsumeAnyOf(format_, "-+ #0"));
- }
-
- // Consume the width.
- // If it is '*', we verify that it matches `args_`. `error_` is set if it
- // doesn't match.
- constexpr ConvParser ParseWidth() const {
- return IsDigit(GetChar(format_, 0))
- ? SetFormat(ParseDigits(format_).format)
- : GetChar(format_, 0) == '*'
- ? is_positional_
- ? VerifyPositional(
- ParsePositional(ConsumeFront(format_)), '*')
- : SetFormat(ConsumeFront(format_))
- .ConsumeNextArg('*')
- : *this;
- }
-
- // Consume the precision.
- // If it is '*', we verify that it matches `args_`. `error_` is set if it
- // doesn't match.
- constexpr ConvParser ParsePrecision() const {
- return GetChar(format_, 0) != '.'
- ? *this
- : GetChar(format_, 1) == '*'
- ? is_positional_
- ? VerifyPositional(
- ParsePositional(ConsumeFront(format_, 2)), '*')
- : SetFormat(ConsumeFront(format_, 2))
- .ConsumeNextArg('*')
- : SetFormat(ParseDigits(ConsumeFront(format_)).format);
- }
-
- // Consume the length characters.
- constexpr ConvParser ParseLength() const {
- return SetFormat(ConsumeAnyOf(format_, "lLhjztq"));
- }
-
- // Consume the conversion character and verify that it matches `args_`.
- // `error_` is set if it doesn't match.
- constexpr ConvParser ParseConversion() const {
- return is_positional_
- ? VerifyPositional({ConsumeFront(format_), arg_position_},
- GetChar(format_, 0))
- : ConsumeNextArg(GetChar(format_, 0))
- .SetFormat(ConsumeFront(format_));
- }
-
- constexpr ConvParser(string_view format, ConvList args, bool error,
- int arg_position, bool is_positional)
- : format_(format),
- args_(args),
- error_(error),
- arg_position_(arg_position),
- is_positional_(is_positional) {}
-
- public:
- constexpr ConvParser(string_view format, ConvList args, bool is_positional)
- : format_(format),
- args_(args),
- error_(false),
- arg_position_(0),
- is_positional_(is_positional) {}
-
- // Consume the whole conversion specifier.
- // `format()` will be set to the character after the conversion character.
- // `error()` will be set if any of the arguments do not match.
- constexpr ConvParser Run() const {
- return (is_positional_ ? ParseArgPosition(ParsePositional(format_)) : *this)
- .ParseFlags()
- .ParseWidth()
- .ParsePrecision()
- .ParseLength()
- .ParseConversion();
- }
-
- constexpr string_view format() const { return format_; }
- constexpr ConvList args() const { return args_; }
- constexpr bool error() const { return error_; }
- constexpr bool is_positional() const { return is_positional_; }
-
- private:
- string_view format_;
- // Current list of arguments. If we are not in positional mode we will consume
- // from the front.
- ConvList args_;
- bool error_;
- // Holds the argument position of the conversion character, if we are in
- // positional mode. Otherwise, it is unspecified.
- int arg_position_;
- // Whether we are in positional mode.
- // It changes the behavior of '*' and where to find the converted argument.
- bool is_positional_;
-};
-
-// Parses a whole format expression.
-// See FormatParser::Run().
-class FormatParser {
- static constexpr bool FoundPercent(string_view format) {
- return format.empty() ||
- (GetChar(format, 0) == '%' && GetChar(format, 1) != '%');
- }
-
- // We use an inner function to increase the recursion limit.
- // The inner function consumes up to `limit` characters on every run.
- // This increases the limit from 512 to ~512*limit.
- static constexpr string_view ConsumeNonPercentInner(string_view format,
- int limit = 20) {
- return FoundPercent(format) || !limit
- ? format
- : ConsumeNonPercentInner(
- ConsumeFront(format, GetChar(format, 0) == '%' &&
- GetChar(format, 1) == '%'
- ? 2
- : 1),
- limit - 1);
- }
-
- // Consume characters until the next conversion spec %.
- // It skips %%.
- static constexpr string_view ConsumeNonPercent(string_view format) {
- return FoundPercent(format)
- ? format
- : ConsumeNonPercent(ConsumeNonPercentInner(format));
- }
-
- static constexpr bool IsPositional(string_view format) {
- return IsDigit(GetChar(format, 0)) ? IsPositional(ConsumeFront(format))
- : GetChar(format, 0) == '$';
- }
-
- constexpr bool RunImpl(bool is_positional) const {
- // In non-positional mode we require all arguments to be consumed.
- // In positional mode just reaching the end of the format without errors is
- // enough.
- return (format_.empty() && (is_positional || args_.count == 0)) ||
- (!format_.empty() &&
- ValidateArg(
- ConvParser(ConsumeFront(format_), args_, is_positional).Run()));
- }
-
- constexpr bool ValidateArg(ConvParser conv) const {
- return !conv.error() && FormatParser(conv.format(), conv.args())
- .RunImpl(conv.is_positional());
- }
-
- public:
- constexpr FormatParser(string_view format, ConvList args)
- : format_(ConsumeNonPercent(format)), args_(args) {}
-
- // Runs the parser for `format` and `args`.
- // It verifies that the format is valid and that all conversion specifiers
- // match the arguments passed.
- // In non-positional mode it also verfies that all arguments are consumed.
- constexpr bool Run() const {
- return RunImpl(!format_.empty() && IsPositional(ConsumeFront(format_)));
- }
-
- private:
- string_view format_;
- // Current list of arguments.
- // If we are not in positional mode we will consume from the front and will
- // have to be empty in the end.
- ConvList args_;
-};
-
template <FormatConversionCharSet... C>
constexpr bool ValidFormatImpl(string_view format) {
- return FormatParser(format,
- {ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
- .Run();
+ int next_arg = 0;
+ const char* p = format.data();
+ const char* const end = p + format.size();
+ constexpr FormatConversionCharSet
+ kAllowedConvs[(std::max)(sizeof...(C), size_t{1})] = {C...};
+ bool used[(std::max)(sizeof...(C), size_t{1})]{};
+ constexpr int kNumArgs = sizeof...(C);
+ while (p != end) {
+ while (p != end && *p != '%') ++p;
+ if (p == end) {
+ break;
+ }
+ if (p + 1 >= end) return false;
+ if (p[1] == '%') {
+ // %%
+ p += 2;
+ continue;
+ }
+
+ UnboundConversion conv(absl::kConstInit);
+ p = ConsumeUnboundConversion(p + 1, end, &conv, &next_arg);
+ if (p == nullptr) return false;
+ if (conv.arg_position <= 0 || conv.arg_position > kNumArgs) {
+ return false;
+ }
+ if (!Contains(kAllowedConvs[conv.arg_position - 1], conv.conv)) {
+ return false;
+ }
+ used[conv.arg_position - 1] = true;
+ for (auto extra : {conv.width, conv.precision}) {
+ if (extra.is_from_arg()) {
+ int pos = extra.get_from_arg();
+ if (pos <= 0 || pos > kNumArgs) return false;
+ used[pos - 1] = true;
+ if (!Contains(kAllowedConvs[pos - 1], '*')) {
+ return false;
+ }
+ }
+ }
+ }
+ if (sizeof...(C) != 0) {
+ for (bool b : used) {
+ if (!b) return false;
+ }
+ }
+ return true;
}
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h
new file mode 100644
index 0000000000..3dc1776b42
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/constexpr_parser.h
@@ -0,0 +1,351 @@
+// 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_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
+#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
+
+#include <cassert>
+#include <cstdint>
+#include <limits>
+
+#include "absl/base/const_init.h"
+#include "absl/strings/internal/str_format/extension.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace str_format_internal {
+
+enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
+
+// The analyzed properties of a single specified conversion.
+struct UnboundConversion {
+ // This is a user defined default constructor on purpose to skip the
+ // initialization of parts of the object that are not necessary.
+ UnboundConversion() {} // NOLINT
+
+ // This constructor is provided for the static checker. We don't want to do
+ // the unnecessary initialization in the normal case.
+ explicit constexpr UnboundConversion(absl::ConstInitType)
+ : arg_position{}, width{}, precision{} {}
+
+ class InputValue {
+ public:
+ constexpr void set_value(int value) {
+ assert(value >= 0);
+ value_ = value;
+ }
+ constexpr int value() const { return value_; }
+
+ // Marks the value as "from arg". aka the '*' format.
+ // Requires `value >= 1`.
+ // When set, is_from_arg() return true and get_from_arg() returns the
+ // original value.
+ // `value()`'s return value is unspecified in this state.
+ constexpr void set_from_arg(int value) {
+ assert(value > 0);
+ value_ = -value - 1;
+ }
+ constexpr bool is_from_arg() const { return value_ < -1; }
+ constexpr int get_from_arg() const {
+ assert(is_from_arg());
+ return -value_ - 1;
+ }
+
+ private:
+ int value_ = -1;
+ };
+
+ // No need to initialize. It will always be set in the parser.
+ int arg_position;
+
+ InputValue width;
+ InputValue precision;
+
+ Flags flags = Flags::kBasic;
+ LengthMod length_mod = LengthMod::none;
+ FormatConversionChar conv = FormatConversionCharInternal::kNone;
+};
+
+// Helper tag class for the table below.
+// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
+// conversions.
+class ConvTag {
+ public:
+ constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
+ : tag_(static_cast<uint8_t>(conversion_char)) {}
+ constexpr ConvTag(LengthMod length_mod) // NOLINT
+ : tag_(0x80 | static_cast<uint8_t>(length_mod)) {}
+ constexpr ConvTag(Flags flags) // NOLINT
+ : tag_(0xc0 | static_cast<uint8_t>(flags)) {}
+ constexpr ConvTag() : tag_(0xFF) {}
+
+ constexpr bool is_conv() const { return (tag_ & 0x80) == 0; }
+ constexpr bool is_length() const { return (tag_ & 0xC0) == 0x80; }
+ constexpr bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
+
+ constexpr FormatConversionChar as_conv() const {
+ assert(is_conv());
+ assert(!is_length());
+ assert(!is_flags());
+ return static_cast<FormatConversionChar>(tag_);
+ }
+ constexpr LengthMod as_length() const {
+ assert(!is_conv());
+ assert(is_length());
+ assert(!is_flags());
+ return static_cast<LengthMod>(tag_ & 0x3F);
+ }
+ constexpr Flags as_flags() const {
+ assert(!is_conv());
+ assert(!is_length());
+ assert(is_flags());
+ return static_cast<Flags>(tag_ & 0x1F);
+ }
+
+ private:
+ uint8_t tag_;
+};
+
+struct ConvTagHolder {
+ using CC = FormatConversionCharInternal;
+ using LM = LengthMod;
+
+ // Abbreviations to fit in the table below.
+ static constexpr auto kFSign = Flags::kSignCol;
+ static constexpr auto kFAlt = Flags::kAlt;
+ static constexpr auto kFPos = Flags::kShowPos;
+ static constexpr auto kFLeft = Flags::kLeft;
+ static constexpr auto kFZero = Flags::kZero;
+
+ static constexpr ConvTag value[256] = {
+ {}, {}, {}, {}, {}, {}, {}, {}, // 00-07
+ {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 10-17
+ {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
+ kFSign, {}, {}, kFAlt, {}, {}, {}, {}, // !"#$%&'
+ {}, {}, {}, kFPos, {}, kFLeft, {}, {}, // ()*+,-./
+ kFZero, {}, {}, {}, {}, {}, {}, {}, // 01234567
+ {}, {}, {}, {}, {}, {}, {}, {}, // 89:;<=>?
+ {}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG
+ {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
+ {}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW
+ CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
+ {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
+ LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
+ CC::p, LM::q, {}, CC::s, LM::t, CC::u, CC::v, {}, // pqrstuvw
+ CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
+ {}, {}, {}, {}, {}, {}, {}, {}, // 80-87
+ {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 90-97
+ {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
+ {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
+ {}, {}, {}, {}, {}, {}, {}, {}, // a8-af
+ {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
+ {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
+ {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
+ {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
+ {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
+ {}, {}, {}, {}, {}, {}, {}, {}, // d8-df
+ {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
+ {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
+ {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
+ {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
+ };
+};
+
+// Keep a single table for all the conversion chars and length modifiers.
+constexpr ConvTag GetTagForChar(char c) {
+ return ConvTagHolder::value[static_cast<unsigned char>(c)];
+}
+
+constexpr bool CheckFastPathSetting(const UnboundConversion& conv) {
+ bool width_precision_needed =
+ conv.width.value() >= 0 || conv.precision.value() >= 0;
+ if (width_precision_needed && conv.flags == Flags::kBasic) {
+#if defined(__clang__)
+ // Some compilers complain about this in constexpr even when not executed,
+ // so only enable the error dump in clang.
+ fprintf(stderr,
+ "basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
+ "width=%d precision=%d\n",
+ conv.flags == Flags::kBasic ? 1 : 0,
+ FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,
+ FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,
+ FlagsContains(conv.flags, Flags::kSignCol) ? 1 : 0,
+ FlagsContains(conv.flags, Flags::kAlt) ? 1 : 0,
+ FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),
+ conv.precision.value());
+#endif // defined(__clang__)
+ return false;
+ }
+ return true;
+}
+
+constexpr int ParseDigits(char& c, const char*& pos, const char* const end) {
+ int digits = c - '0';
+ // We do not want to overflow `digits` so we consume at most digits10
+ // digits. If there are more digits the parsing will fail later on when the
+ // digit doesn't match the expected characters.
+ int num_digits = std::numeric_limits<int>::digits10;
+ for (;;) {
+ if (ABSL_PREDICT_FALSE(pos == end)) break;
+ c = *pos++;
+ if ('0' > c || c > '9') break;
+ --num_digits;
+ if (ABSL_PREDICT_FALSE(!num_digits)) break;
+ digits = 10 * digits + c - '0';
+ }
+ return digits;
+}
+
+template <bool is_positional>
+constexpr const char* ConsumeConversion(const char* pos, const char* const end,
+ UnboundConversion* conv,
+ int* next_arg) {
+ const char* const original_pos = pos;
+ char c = 0;
+ // Read the next char into `c` and update `pos`. Returns false if there are
+ // no more chars to read.
+#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
+ do { \
+ if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
+ c = *pos++; \
+ } while (0)
+
+ if (is_positional) {
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->arg_position = ParseDigits(c, pos, end);
+ assert(conv->arg_position > 0);
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
+ }
+
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+
+ // We should start with the basic flag on.
+ assert(conv->flags == Flags::kBasic);
+
+ // Any non alpha character makes this conversion not basic.
+ // This includes flags (-+ #0), width (1-9, *) or precision (.).
+ // All conversion characters and length modifiers are alpha characters.
+ if (c < 'A') {
+ while (c <= '0') {
+ auto tag = GetTagForChar(c);
+ if (tag.is_flags()) {
+ conv->flags = conv->flags | tag.as_flags();
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ break;
+ }
+ }
+
+ if (c <= '9') {
+ if (c >= '0') {
+ int maybe_width = ParseDigits(c, pos, end);
+ if (!is_positional && c == '$') {
+ if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
+ // Positional conversion.
+ *next_arg = -1;
+ return ConsumeConversion<true>(original_pos, end, conv, next_arg);
+ }
+ conv->flags = conv->flags | Flags::kNonBasic;
+ conv->width.set_value(maybe_width);
+ } else if (c == '*') {
+ conv->flags = conv->flags | Flags::kNonBasic;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (is_positional) {
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->width.set_from_arg(ParseDigits(c, pos, end));
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->width.set_from_arg(++*next_arg);
+ }
+ }
+ }
+
+ if (c == '.') {
+ conv->flags = conv->flags | Flags::kNonBasic;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if ('0' <= c && c <= '9') {
+ conv->precision.set_value(ParseDigits(c, pos, end));
+ } else if (c == '*') {
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (is_positional) {
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
+ conv->precision.set_from_arg(ParseDigits(c, pos, end));
+ if (c != '$') return nullptr;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->precision.set_from_arg(++*next_arg);
+ }
+ } else {
+ conv->precision.set_value(0);
+ }
+ }
+ }
+
+ auto tag = GetTagForChar(c);
+
+ if (ABSL_PREDICT_FALSE(c == 'v' && conv->flags != Flags::kBasic)) {
+ return nullptr;
+ }
+
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
+ if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
+
+ // It is a length modifier.
+ using str_format_internal::LengthMod;
+ LengthMod length_mod = tag.as_length();
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ if (c == 'h' && length_mod == LengthMod::h) {
+ conv->length_mod = LengthMod::hh;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else if (c == 'l' && length_mod == LengthMod::l) {
+ conv->length_mod = LengthMod::ll;
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
+ } else {
+ conv->length_mod = length_mod;
+ }
+ tag = GetTagForChar(c);
+
+ if (ABSL_PREDICT_FALSE(c == 'v')) return nullptr;
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
+ }
+
+ assert(CheckFastPathSetting(*conv));
+ (void)(&CheckFastPathSetting);
+
+ conv->conv = tag.as_conv();
+ if (!is_positional) conv->arg_position = ++*next_arg;
+ return pos;
+}
+
+// Consume conversion spec prefix (not including '%') of [p, end) if valid.
+// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
+// If valid, it returns the first character following the conversion spec,
+// and the spec part is broken down and returned in 'conv'.
+// If invalid, returns nullptr.
+constexpr const char* ConsumeUnboundConversion(const char* p, const char* end,
+ UnboundConversion* conv,
+ int* next_arg) {
+ if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
+ return ConsumeConversion<false>(p, end, conv, next_arg);
+}
+
+} // namespace str_format_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CONSTEXPR_PARSER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
index f93153d5c0..2a0ceb13d7 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.cc
@@ -58,7 +58,8 @@ constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
bool FormatSinkImpl::PutPaddedString(string_view value, int width,
int precision, bool left) {
size_t space_remaining = 0;
- if (width >= 0) space_remaining = width;
+ if (width >= 0)
+ space_remaining = static_cast<size_t>(width);
size_t n = value.size();
if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
string_view shown(value.data(), n);
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
index 55e8ac882d..603bd49d18 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/extension.h
@@ -169,7 +169,7 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
X_VAL(f) X_SEP X_VAL(F) X_SEP X_VAL(e) X_SEP X_VAL(E) X_SEP \
X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
/* misc */ \
- X_VAL(n) X_SEP X_VAL(p)
+ X_VAL(n) X_SEP X_VAL(p) X_SEP X_VAL(v)
// clang-format on
// This type should not be referenced, it exists only to provide labels
@@ -191,7 +191,7 @@ struct FormatConversionCharInternal {
c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
- n, p, // misc
+ n, p, v, // misc
kNone
};
// clang-format on
@@ -292,6 +292,8 @@ class FormatConversionSpecImpl {
return conv_;
}
+ void set_conversion_char(FormatConversionChar c) { conv_ = c; }
+
// Returns the specified width. If width is unspecfied, it returns a negative
// value.
int width() const { return width_; }
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
index b1c4068475..8e497852bb 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -92,27 +92,30 @@ class StackArray {
// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
// the carry.
+// Requires: `0 <= carry <= 9`
template <typename Int>
-inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
+inline char MultiplyBy10WithCarry(Int* v, char carry) {
using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
- BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
+ BiggerInt tmp =
+ 10 * static_cast<BiggerInt>(*v) + static_cast<BiggerInt>(carry);
*v = static_cast<Int>(tmp);
- return static_cast<Int>(tmp >> (sizeof(Int) * 8));
+ return static_cast<char>(tmp >> (sizeof(Int) * 8));
}
// Calculates `(2^64 * carry + *v) / 10`.
// Stores the quotient in `*v` and returns the remainder.
// Requires: `0 <= carry <= 9`
-inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
+inline char DivideBy10WithCarry(uint64_t* v, char carry) {
constexpr uint64_t divisor = 10;
// 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
+ const uint64_t carry_u64 = static_cast<uint64_t>(carry);
const uint64_t mod = *v % divisor;
- const uint64_t next_carry = chunk_remainder * carry + mod;
- *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
- return next_carry % divisor;
+ const uint64_t next_carry = chunk_remainder * carry_u64 + mod;
+ *v = *v / divisor + carry_u64 * chunk_quotient + next_carry / divisor;
+ return static_cast<char>(next_carry % divisor);
}
using MaxFloatType =
@@ -125,11 +128,11 @@ using MaxFloatType =
//
// Requires `0 <= exp` and `exp <= numeric_limits<MaxFloatType>::max_exponent`.
class BinaryToDecimal {
- static constexpr int ChunksNeeded(int exp) {
+ static constexpr size_t ChunksNeeded(int exp) {
// We will left shift a uint128 by `exp` bits, so we need `128+exp` total
// bits. Round up to 32.
// See constructor for details about adding `10%` to the value.
- return (128 + exp + 31) / 32 * 11 / 10;
+ return static_cast<size_t>((128 + exp + 31) / 32 * 11 / 10);
}
public:
@@ -140,7 +143,7 @@ class BinaryToDecimal {
assert(exp > 0);
assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
static_assert(
- static_cast<int>(StackArray::kMaxCapacity) >=
+ StackArray::kMaxCapacity >=
ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
"");
@@ -149,9 +152,9 @@ class BinaryToDecimal {
[=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
}
- int TotalDigits() const {
- return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
- CurrentDigits().size());
+ size_t TotalDigits() const {
+ return (decimal_end_ - decimal_start_) * kDigitsPerChunk +
+ CurrentDigits().size();
}
// See the current block of digits.
@@ -190,30 +193,31 @@ class BinaryToDecimal {
// the decimal representation is around 7% less efficient in space than the
// binary one. We allocate an extra 10% memory to account for this. See
// ChunksNeeded for this calculation.
- int chunk_index = exp / 32;
+ size_t after_chunk_index = static_cast<size_t>(exp / 32 + 1);
decimal_start_ = decimal_end_ = ChunksNeeded(exp);
const int offset = exp % 32;
// Left shift v by exp bits.
- data_[chunk_index] = static_cast<uint32_t>(v << offset);
+ data_[after_chunk_index - 1] = static_cast<uint32_t>(v << offset);
for (v >>= (32 - offset); v; v >>= 32)
- data_[++chunk_index] = static_cast<uint32_t>(v);
+ data_[++after_chunk_index - 1] = static_cast<uint32_t>(v);
- while (chunk_index >= 0) {
+ while (after_chunk_index > 0) {
// While we have more than one chunk available, go in steps of 1e9.
- // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
- // the variable updated.
+ // `data_[after_chunk_index - 1]` holds the highest non-zero binary chunk,
+ // so keep the variable updated.
uint32_t carry = 0;
- for (int i = chunk_index; i >= 0; --i) {
- uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
- data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
+ for (size_t i = after_chunk_index; i > 0; --i) {
+ uint64_t tmp = uint64_t{data_[i - 1]} + (uint64_t{carry} << 32);
+ data_[i - 1] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
}
// If the highest chunk is now empty, remove it from view.
- if (data_[chunk_index] == 0) --chunk_index;
+ if (data_[after_chunk_index - 1] == 0)
+ --after_chunk_index;
--decimal_start_;
- assert(decimal_start_ != chunk_index);
+ assert(decimal_start_ != after_chunk_index - 1);
data_[decimal_start_] = carry;
}
@@ -225,13 +229,13 @@ class BinaryToDecimal {
}
private:
- static constexpr int kDigitsPerChunk = 9;
+ static constexpr size_t kDigitsPerChunk = 9;
- int decimal_start_;
- int decimal_end_;
+ size_t decimal_start_;
+ size_t decimal_end_;
char digits_[kDigitsPerChunk];
- int size_ = 0;
+ size_t size_ = 0;
absl::Span<uint32_t> data_;
};
@@ -251,25 +255,26 @@ class FractionalDigitGenerator {
static_assert(StackArray::kMaxCapacity >=
(Limits::digits + 128 - Limits::min_exponent + 31) / 32,
"");
- StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
- [=](absl::Span<uint32_t> input) {
- f(FractionalDigitGenerator(input, v, exp));
- });
+ StackArray::RunWithCapacity(
+ static_cast<size_t>((Limits::digits + exp + 31) / 32),
+ [=](absl::Span<uint32_t> input) {
+ f(FractionalDigitGenerator(input, v, exp));
+ });
}
// Returns true if there are any more non-zero digits left.
- bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
+ bool HasMoreDigits() const { return next_digit_ != 0 || after_chunk_index_; }
// Returns true if the remainder digits are greater than 5000...
bool IsGreaterThanHalf() const {
- return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
+ return next_digit_ > 5 || (next_digit_ == 5 && after_chunk_index_);
}
// Returns true if the remainder digits are exactly 5000...
- bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
+ bool IsExactlyHalf() const { return next_digit_ == 5 && !after_chunk_index_; }
struct Digits {
- int digit_before_nine;
- int num_nines;
+ char digit_before_nine;
+ size_t num_nines;
};
// Get the next set of digits.
@@ -288,35 +293,37 @@ class FractionalDigitGenerator {
private:
// Return the next digit.
- int GetOneDigit() {
- if (chunk_index_ < 0) return 0;
+ char GetOneDigit() {
+ if (!after_chunk_index_)
+ return 0;
- uint32_t carry = 0;
- for (int i = chunk_index_; i >= 0; --i) {
- carry = MultiplyBy10WithCarry(&data_[i], carry);
+ char carry = 0;
+ for (size_t i = after_chunk_index_; i > 0; --i) {
+ carry = MultiplyBy10WithCarry(&data_[i - 1], carry);
}
// If the lowest chunk is now empty, remove it from view.
- if (data_[chunk_index_] == 0) --chunk_index_;
+ if (data_[after_chunk_index_ - 1] == 0)
+ --after_chunk_index_;
return carry;
}
FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
- : chunk_index_(exp / 32), data_(data) {
+ : after_chunk_index_(static_cast<size_t>(exp / 32 + 1)), data_(data) {
const int offset = exp % 32;
// Right shift `v` by `exp` bits.
- data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
+ data_[after_chunk_index_ - 1] = static_cast<uint32_t>(v << (32 - offset));
v >>= offset;
// Make sure we don't overflow the data. We already calculated that
// non-zero bits fit, so we might not have space for leading zero bits.
- for (int pos = chunk_index_; v; v >>= 32)
+ for (size_t pos = after_chunk_index_ - 1; v; v >>= 32)
data_[--pos] = static_cast<uint32_t>(v);
// Fill next_digit_, as GetDigits expects it to be populated always.
next_digit_ = GetOneDigit();
}
- int next_digit_;
- int chunk_index_;
+ char next_digit_;
+ size_t after_chunk_index_;
absl::Span<uint32_t> data_;
};
@@ -362,7 +369,7 @@ char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
auto low = static_cast<uint64_t>(v);
while (high != 0) {
- uint64_t carry = DivideBy10WithCarry(&high, 0);
+ char carry = DivideBy10WithCarry(&high, 0);
carry = DivideBy10WithCarry(&low, carry);
*--p = carry + '0';
}
@@ -373,13 +380,15 @@ char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
// shifting.
// Performs rounding if necessary to fit within `precision`.
// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
- int precision) {
+char* PrintFractionalDigitsFast(uint64_t v,
+ char* start,
+ int exp,
+ size_t precision) {
char *p = start;
v <<= (64 - exp);
while (precision > 0) {
if (!v) return p;
- *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
+ *p++ = MultiplyBy10WithCarry(&v, 0) + '0';
--precision;
}
@@ -393,8 +402,6 @@ char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
RoundToEven(p - 1);
}
- assert(precision == 0);
- // Precision can only be zero here.
return p;
}
@@ -402,8 +409,10 @@ char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
// after shifting.
// Performs rounding if necessary to fit within `precision`.
// Returns the pointer to one after the last character written.
-char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
- int precision) {
+char* PrintFractionalDigitsFast(uint128 v,
+ char* start,
+ int exp,
+ size_t precision) {
char *p = start;
v <<= (128 - exp);
auto high = static_cast<uint64_t>(v >> 64);
@@ -412,7 +421,7 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
// While we have digits to print and `low` is not empty, do the long
// multiplication.
while (precision > 0 && low != 0) {
- uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
+ char carry = MultiplyBy10WithCarry(&low, 0);
carry = MultiplyBy10WithCarry(&high, carry);
*p++ = carry + '0';
@@ -424,7 +433,7 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
// above.
while (precision > 0) {
if (!high) return p;
- *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
+ *p++ = MultiplyBy10WithCarry(&high, 0) + '0';
--precision;
}
@@ -438,14 +447,12 @@ char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
RoundToEven(p - 1);
}
- assert(precision == 0);
- // Precision can only be zero here.
return p;
}
struct FormatState {
char sign_char;
- int precision;
+ size_t precision;
const FormatConversionSpecImpl &conv;
FormatSinkImpl *sink;
@@ -455,9 +462,9 @@ struct FormatState {
};
struct Padding {
- int left_spaces;
- int zeros;
- int right_spaces;
+ size_t left_spaces;
+ size_t zeros;
+ size_t right_spaces;
};
Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
@@ -465,7 +472,7 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
static_cast<size_t>(state.conv.width()) <= total_size) {
return {0, 0, 0};
}
- int missing_chars = state.conv.width() - total_size;
+ size_t missing_chars = static_cast<size_t>(state.conv.width()) - total_size;
if (state.conv.has_left_flag()) {
return {0, 0, missing_chars};
} else if (state.conv.has_zero_flag()) {
@@ -475,8 +482,10 @@ Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
}
}
-void FinalPrint(const FormatState &state, absl::string_view data,
- int padding_offset, int trailing_zeros,
+void FinalPrint(const FormatState& state,
+ absl::string_view data,
+ size_t padding_offset,
+ size_t trailing_zeros,
absl::string_view data_postfix) {
if (state.conv.width() < 0) {
// No width specified. Fast-path.
@@ -487,10 +496,10 @@ void FinalPrint(const FormatState &state, absl::string_view data,
return;
}
- auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
- data.size() + data_postfix.size() +
- static_cast<size_t>(trailing_zeros),
- state);
+ auto padding =
+ ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) + data.size() +
+ data_postfix.size() + trailing_zeros,
+ state);
state.sink->Append(padding.left_spaces, ' ');
if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
@@ -547,15 +556,16 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
if (integral_digits_start[-1] != '0') --integral_digits_start;
}
- size_t size = fractional_digits_end - integral_digits_start;
+ size_t size =
+ static_cast<size_t>(fractional_digits_end - integral_digits_start);
// In `alt` mode (flag #) we keep the `.` even if there are no fractional
// digits. In non-alt mode, we strip it.
if (!state.ShouldPrintDot()) --size;
FinalPrint(state, absl::string_view(integral_digits_start, size),
/*padding_offset=*/0,
- static_cast<int>(state.precision - (fractional_digits_end -
- fractional_digits_start)),
+ state.precision - static_cast<size_t>(fractional_digits_end -
+ fractional_digits_start),
/*data_postfix=*/"");
}
@@ -567,21 +577,22 @@ void FormatFFast(Int v, int exp, const FormatState &state) {
void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
const size_t total_digits =
- btd.TotalDigits() +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ btd.TotalDigits() + (state.ShouldPrintDot() ? state.precision + 1 : 0);
const auto padding = ExtraWidthToPadding(
total_digits + (state.sign_char != '\0' ? 1 : 0), state);
state.sink->Append(padding.left_spaces, ' ');
- if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ if (state.sign_char != '\0')
+ state.sink->Append(1, state.sign_char);
state.sink->Append(padding.zeros, '0');
do {
state.sink->Append(btd.CurrentDigits());
} while (btd.AdvanceDigits());
- if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+ if (state.ShouldPrintDot())
+ state.sink->Append(1, '.');
state.sink->Append(state.precision, '0');
state.sink->Append(padding.right_spaces, ' ');
});
@@ -594,8 +605,7 @@ void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
// digits.
void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
const size_t total_digits =
- /* 0 */ 1 +
- (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ /* 0 */ 1 + (state.ShouldPrintDot() ? state.precision + 1 : 0);
auto padding =
ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
padding.zeros += 1;
@@ -606,7 +616,7 @@ void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
if (state.ShouldPrintDot()) state.sink->Append(1, '.');
// Print digits
- int digits_to_go = state.precision;
+ size_t digits_to_go = state.precision;
FractionalDigitGenerator::RunConversion(
v, exp, [&](FractionalDigitGenerator digit_gen) {
@@ -666,7 +676,8 @@ void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
template <typename Int>
void FormatF(Int mantissa, int exp, const FormatState &state) {
if (exp >= 0) {
- const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
+ const int total_bits =
+ static_cast<int>(sizeof(Int) * 8) - LeadingZeros(mantissa) + exp;
// Fallback to the slow stack-based approach if we can't do it in a 64 or
// 128 bit state.
@@ -686,9 +697,9 @@ void FormatF(Int mantissa, int exp, const FormatState &state) {
// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
// bits 4-7.
template <typename Int>
-uint8_t GetNibble(Int n, int nibble_index) {
+uint8_t GetNibble(Int n, size_t nibble_index) {
constexpr Int mask_low_nibble = Int{0xf};
- int shift = nibble_index * 4;
+ int shift = static_cast<int>(nibble_index * 4);
n &= mask_low_nibble << shift;
return static_cast<uint8_t>((n >> shift) & 0xf);
}
@@ -696,9 +707,9 @@ uint8_t GetNibble(Int n, int nibble_index) {
// Add one to the given nibble, applying carry to higher nibbles. Returns true
// if overflow, false otherwise.
template <typename Int>
-bool IncrementNibble(int nibble_index, Int *n) {
- constexpr int kShift = sizeof(Int) * 8 - 1;
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+bool IncrementNibble(size_t nibble_index, Int* n) {
+ constexpr size_t kShift = sizeof(Int) * 8 - 1;
+ constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;
Int before = *n >> kShift;
// Here we essentially want to take the number 1 and move it into the requsted
// nibble, then add it to *n to effectively increment the nibble. However,
@@ -706,28 +717,32 @@ bool IncrementNibble(int nibble_index, Int *n) {
// i.e., if the nibble_index is out of range. So therefore we check for this
// and if we are out of range we just add 0 which leaves *n unchanged, which
// seems like the reasonable thing to do in that case.
- *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
+ *n += ((nibble_index >= kNumNibbles)
+ ? 0
+ : (Int{1} << static_cast<int>(nibble_index * 4)));
Int after = *n >> kShift;
return (before && !after) || (nibble_index >= kNumNibbles);
}
// Return a mask with 1's in the given nibble and all lower nibbles.
template <typename Int>
-Int MaskUpToNibbleInclusive(int nibble_index) {
- constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+Int MaskUpToNibbleInclusive(size_t nibble_index) {
+ constexpr size_t kNumNibbles = sizeof(Int) * 8 / 4;
static const Int ones = ~Int{0};
- return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
+ ++nibble_index;
+ return ones >> static_cast<int>(
+ 4 * (std::max(kNumNibbles, nibble_index) - nibble_index));
}
// Return a mask with 1's below the given nibble.
template <typename Int>
-Int MaskUpToNibbleExclusive(int nibble_index) {
- return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
+Int MaskUpToNibbleExclusive(size_t nibble_index) {
+ return nibble_index == 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
}
template <typename Int>
-Int MoveToNibble(uint8_t nibble, int nibble_index) {
- return Int{nibble} << (4 * nibble_index);
+Int MoveToNibble(uint8_t nibble, size_t nibble_index) {
+ return Int{nibble} << static_cast<int>(4 * nibble_index);
}
// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
@@ -744,10 +759,10 @@ Int MoveToNibble(uint8_t nibble, int nibble_index) {
// a multiple of four. Once again, the goal is to have all fractional digits
// represent real precision.
template <typename Float>
-constexpr int HexFloatLeadingDigitSizeInBits() {
+constexpr size_t HexFloatLeadingDigitSizeInBits() {
return std::numeric_limits<Float>::digits % 4 > 0
- ? std::numeric_limits<Float>::digits % 4
- : 4;
+ ? static_cast<size_t>(std::numeric_limits<Float>::digits % 4)
+ : size_t{4};
}
// This function captures the rounding behavior of glibc for hex float
@@ -757,16 +772,17 @@ constexpr int HexFloatLeadingDigitSizeInBits() {
// point that is not followed by 800000..., it disregards the parity and rounds
// up if > 8 and rounds down if < 8.
template <typename Int>
-bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
+bool HexFloatNeedsRoundUp(Int mantissa,
+ size_t final_nibble_displayed,
uint8_t leading) {
// If the last nibble (hex digit) to be displayed is the lowest on in the
// mantissa then that means that we don't have any further nibbles to inform
// rounding, so don't round.
- if (final_nibble_displayed <= 0) {
+ if (final_nibble_displayed == 0) {
return false;
}
- int rounding_nibble_idx = final_nibble_displayed - 1;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ size_t rounding_nibble_idx = final_nibble_displayed - 1;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
assert(final_nibble_displayed <= kTotalNibbles);
Int mantissa_up_to_rounding_nibble_inclusive =
mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
@@ -793,7 +809,7 @@ struct HexFloatTypeParams {
}
int min_exponent;
- int leading_digit_size_bits;
+ size_t leading_digit_size_bits;
};
// Hex Float Rounding. First check if we need to round; if so, then we do that
@@ -803,10 +819,12 @@ struct HexFloatTypeParams {
template <typename Int>
void FormatARound(bool precision_specified, const FormatState &state,
uint8_t *leading, Int *mantissa, int *exp) {
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
// Index of the last nibble that we could display given precision.
- int final_nibble_displayed =
- precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
+ size_t final_nibble_displayed =
+ precision_specified
+ ? (std::max(kTotalNibbles, state.precision) - state.precision)
+ : 0;
if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
// Need to round up.
bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
@@ -830,9 +848,9 @@ void FormatARound(bool precision_specified, const FormatState &state,
template <typename Int>
void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
Int *mantissa, int *exp) {
- constexpr int kIntBits = sizeof(Int) * 8;
+ constexpr size_t kIntBits = sizeof(Int) * 8;
static const Int kHighIntBit = Int{1} << (kIntBits - 1);
- const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
+ const size_t kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
// Normalize mantissa so that highest bit set is in MSB position, unless we
// get interrupted by the exponent threshold.
while (*mantissa && !(*mantissa & kHighIntBit)) {
@@ -846,18 +864,18 @@ void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
}
// Extract bits for leading digit then shift them away leaving the
// fractional part.
- *leading =
- static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
- *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
- *mantissa <<= kLeadDigitBitsCount;
+ *leading = static_cast<uint8_t>(
+ *mantissa >> static_cast<int>(kIntBits - kLeadDigitBitsCount));
+ *exp -= (*mantissa != 0) ? static_cast<int>(kLeadDigitBitsCount) : *exp;
+ *mantissa <<= static_cast<int>(kLeadDigitBitsCount);
}
template <typename Int>
void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
bool uppercase, const FormatState &state) {
// Int properties.
- constexpr int kIntBits = sizeof(Int) * 8;
- constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ constexpr size_t kIntBits = sizeof(Int) * 8;
+ constexpr size_t kTotalNibbles = sizeof(Int) * 8 / 4;
// Did the user specify a precision explicitly?
const bool precision_specified = state.conv.precision() >= 0;
@@ -903,16 +921,19 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
}
// ============ Fractional Digits ============
- int digits_emitted = 0;
+ size_t digits_emitted = 0;
while (mantissa > 0) {
*digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
mantissa <<= 4;
++digits_emitted;
}
- int trailing_zeros =
- precision_specified ? state.precision - digits_emitted : 0;
- assert(trailing_zeros >= 0);
- auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
+ size_t trailing_zeros = 0;
+ if (precision_specified) {
+ assert(state.precision >= digits_emitted);
+ trailing_zeros = state.precision - digits_emitted;
+ }
+ auto digits_result = string_view(
+ digits_buffer, static_cast<size_t>(digits_iter - digits_buffer));
// =============== Exponent ==================
constexpr size_t kBufSizeForExpDecRepr =
@@ -925,11 +946,11 @@ void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
// ============ Assemble Result ==============
- FinalPrint(state, //
- digits_result, // 0xN.NNN...
- 2, // offset in `data` to start padding if needed.
- trailing_zeros, // num remaining mantissa padding zeros
- exp_buffer); // exponent
+ FinalPrint(state,
+ digits_result, // 0xN.NNN...
+ 2, // offset of any padding
+ static_cast<size_t>(trailing_zeros), // remaining mantissa padding
+ exp_buffer); // exponent
}
char *CopyStringTo(absl::string_view v, char *out) {
@@ -961,10 +982,10 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
int n = snprintf(&space[0], space.size(), fmt, w, p, v);
if (n < 0) return false;
if (static_cast<size_t>(n) < space.size()) {
- result = absl::string_view(space.data(), n);
+ result = absl::string_view(space.data(), static_cast<size_t>(n));
break;
}
- space.resize(n + 1);
+ space.resize(static_cast<size_t>(n) + 1);
}
sink->Append(result);
return true;
@@ -972,13 +993,13 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
// 128-bits in decimal: ceil(128*log(2)/log(10))
// or std::numeric_limits<__uint128_t>::digits10
-constexpr int kMaxFixedPrecision = 39;
+constexpr size_t kMaxFixedPrecision = 39;
-constexpr int kBufferLength = /*sign*/ 1 +
- /*integer*/ kMaxFixedPrecision +
- /*point*/ 1 +
- /*fraction*/ kMaxFixedPrecision +
- /*exponent e+123*/ 5;
+constexpr size_t kBufferLength = /*sign*/ 1 +
+ /*integer*/ kMaxFixedPrecision +
+ /*point*/ 1 +
+ /*fraction*/ kMaxFixedPrecision +
+ /*exponent e+123*/ 5;
struct Buffer {
void push_front(char c) {
@@ -1001,7 +1022,7 @@ struct Buffer {
char last_digit() const { return end[-1] == '.' ? end[-2] : end[-1]; }
- int size() const { return static_cast<int>(end - begin); }
+ size_t size() const { return static_cast<size_t>(end - begin); }
char data[kBufferLength];
char *begin;
@@ -1030,8 +1051,9 @@ bool ConvertNonNumericFloats(char sign_char, Float v,
return false;
}
- return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
- conv.has_left_flag());
+ return sink->PutPaddedString(
+ string_view(text, static_cast<size_t>(ptr - text)), conv.width(), -1,
+ conv.has_left_flag());
}
// Round up the last digit of the value.
@@ -1068,12 +1090,12 @@ void PrintExponent(int exp, char e, Buffer *out) {
}
// Exponent digits.
if (exp > 99) {
- out->push_back(exp / 100 + '0');
- out->push_back(exp / 10 % 10 + '0');
- out->push_back(exp % 10 + '0');
+ out->push_back(static_cast<char>(exp / 100 + '0'));
+ out->push_back(static_cast<char>(exp / 10 % 10 + '0'));
+ out->push_back(static_cast<char>(exp % 10 + '0'));
} else {
- out->push_back(exp / 10 + '0');
- out->push_back(exp % 10 + '0');
+ out->push_back(static_cast<char>(exp / 10 + '0'));
+ out->push_back(static_cast<char>(exp % 10 + '0'));
}
}
@@ -1115,8 +1137,8 @@ Decomposed<Float> Decompose(Float v) {
// In Fixed mode, we add a '.' at the end.
// In Precision mode, we add a '.' after the first digit.
template <FormatStyle mode, typename Int>
-int PrintIntegralDigits(Int digits, Buffer *out) {
- int printed = 0;
+size_t PrintIntegralDigits(Int digits, Buffer* out) {
+ size_t printed = 0;
if (digits) {
for (; digits; digits /= 10) out->push_front(digits % 10 + '0');
printed = out->size();
@@ -1135,10 +1157,10 @@ int PrintIntegralDigits(Int digits, Buffer *out) {
}
// Back out 'extra_digits' digits and round up if necessary.
-bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
- Buffer *out, int *exp_out) {
- if (extra_digits <= 0) return false;
-
+void RemoveExtraPrecision(size_t extra_digits,
+ bool has_leftover_value,
+ Buffer* out,
+ int* exp_out) {
// Back out the extra digits
out->end -= extra_digits;
@@ -1158,15 +1180,17 @@ bool RemoveExtraPrecision(int extra_digits, bool has_leftover_value,
if (needs_to_round_up) {
RoundUp<FormatStyle::Precision>(out, exp_out);
}
- return true;
}
// Print the value into the buffer.
// This will not include the exponent, which will be returned in 'exp_out' for
// Precision mode.
template <typename Int, typename Float, FormatStyle mode>
-bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
- int *exp_out) {
+bool FloatToBufferImpl(Int int_mantissa,
+ int exp,
+ size_t precision,
+ Buffer* out,
+ int* exp_out) {
assert((CanFitMantissa<Float, Int>()));
const int int_bits = std::numeric_limits<Int>::digits;
@@ -1182,14 +1206,16 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
// The value will overflow the Int
return false;
}
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
- int digits_to_zero_pad = precision;
+ size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa << exp, out);
+ size_t digits_to_zero_pad = precision;
if (mode == FormatStyle::Precision) {
- *exp_out = digits_printed - 1;
- digits_to_zero_pad -= digits_printed - 1;
- if (RemoveExtraPrecision(-digits_to_zero_pad, false, out, exp_out)) {
+ *exp_out = static_cast<int>(digits_printed - 1);
+ if (digits_to_zero_pad < digits_printed - 1) {
+ RemoveExtraPrecision(digits_printed - 1 - digits_to_zero_pad, false,
+ out, exp_out);
return true;
}
+ digits_to_zero_pad -= digits_printed - 1;
}
for (; digits_to_zero_pad-- > 0;) out->push_back('0');
return true;
@@ -1203,10 +1229,10 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
const Int mask = (Int{1} << exp) - 1;
// Print the integral part first.
- int digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
+ size_t digits_printed = PrintIntegralDigits<mode>(int_mantissa >> exp, out);
int_mantissa &= mask;
- int fractional_count = precision;
+ size_t fractional_count = precision;
if (mode == FormatStyle::Precision) {
if (digits_printed == 0) {
// Find the first non-zero digit, when in Precision mode.
@@ -1222,20 +1248,21 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
int_mantissa &= mask;
} else {
// We already have a digit, and a '.'
- *exp_out = digits_printed - 1;
- fractional_count -= *exp_out;
- if (RemoveExtraPrecision(-fractional_count, int_mantissa != 0, out,
- exp_out)) {
+ *exp_out = static_cast<int>(digits_printed - 1);
+ if (fractional_count < digits_printed - 1) {
// If we had enough digits, return right away.
// The code below will try to round again otherwise.
+ RemoveExtraPrecision(digits_printed - 1 - fractional_count,
+ int_mantissa != 0, out, exp_out);
return true;
}
+ fractional_count -= digits_printed - 1;
}
}
auto get_next_digit = [&] {
int_mantissa *= 10;
- int digit = static_cast<int>(int_mantissa >> exp);
+ char digit = static_cast<char>(int_mantissa >> exp);
int_mantissa &= mask;
return digit;
};
@@ -1245,7 +1272,7 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
out->push_back(get_next_digit() + '0');
}
- int next_digit = get_next_digit();
+ char next_digit = get_next_digit();
if (next_digit > 5 ||
(next_digit == 5 && (int_mantissa || out->last_digit() % 2 == 1))) {
RoundUp<mode>(out, exp_out);
@@ -1255,24 +1282,25 @@ bool FloatToBufferImpl(Int int_mantissa, int exp, int precision, Buffer *out,
}
template <FormatStyle mode, typename Float>
-bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
- int *exp) {
+bool FloatToBuffer(Decomposed<Float> decomposed,
+ size_t precision,
+ Buffer* out,
+ int* exp) {
if (precision > kMaxFixedPrecision) return false;
// Try with uint64_t.
if (CanFitMantissa<Float, std::uint64_t>() &&
FloatToBufferImpl<std::uint64_t, Float, mode>(
- static_cast<std::uint64_t>(decomposed.mantissa),
- static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
+ static_cast<std::uint64_t>(decomposed.mantissa), decomposed.exponent,
+ precision, out, exp))
return true;
#if defined(ABSL_HAVE_INTRINSIC_INT128)
// If that is not enough, try with __uint128_t.
return CanFitMantissa<Float, __uint128_t>() &&
FloatToBufferImpl<__uint128_t, Float, mode>(
- static_cast<__uint128_t>(decomposed.mantissa),
- static_cast<__uint128_t>(decomposed.exponent), precision, out,
- exp);
+ static_cast<__uint128_t>(decomposed.mantissa), decomposed.exponent,
+ precision, out, exp);
#endif
return false;
}
@@ -1280,12 +1308,15 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
void WriteBufferToSink(char sign_char, absl::string_view str,
const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- int left_spaces = 0, zeros = 0, right_spaces = 0;
- int missing_chars =
- conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
- static_cast<int>(sign_char != 0),
- 0)
- : 0;
+ size_t left_spaces = 0, zeros = 0, right_spaces = 0;
+ size_t missing_chars = 0;
+ if (conv.width() >= 0) {
+ const size_t conv_width_size_t = static_cast<size_t>(conv.width());
+ const size_t existing_chars =
+ str.size() + static_cast<size_t>(sign_char != 0);
+ if (conv_width_size_t > existing_chars)
+ missing_chars = conv_width_size_t - existing_chars;
+ }
if (conv.has_left_flag()) {
right_spaces = missing_chars;
} else if (conv.has_zero_flag()) {
@@ -1321,7 +1352,8 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
return true;
}
- int precision = conv.precision() < 0 ? 6 : conv.precision();
+ size_t precision =
+ conv.precision() < 0 ? 6 : static_cast<size_t>(conv.precision());
int exp = 0;
@@ -1348,12 +1380,12 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
&buffer);
} else if (c == FormatConversionCharInternal::g ||
c == FormatConversionCharInternal::G) {
- precision = std::max(0, precision - 1);
+ precision = std::max(precision, size_t{1}) - 1;
if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
&exp)) {
return FallbackToSnprintf(v, conv, sink);
}
- if (precision + 1 > exp && exp >= -4) {
+ if ((exp < 0 || precision + 1 > static_cast<size_t>(exp)) && exp >= -4) {
if (exp < 0) {
// Have 1.23456, needs 0.00123456
// Move the first digit
@@ -1388,9 +1420,11 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
return false;
}
- WriteBufferToSink(sign_char,
- absl::string_view(buffer.begin, buffer.end - buffer.begin),
- conv, sink);
+ WriteBufferToSink(
+ sign_char,
+ absl::string_view(buffer.begin,
+ static_cast<size_t>(buffer.end - buffer.begin)),
+ conv, sink);
return true;
}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
index 2c9c07dacc..5aaab6983f 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.cc
@@ -31,207 +31,14 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-using CC = FormatConversionCharInternal;
-using LM = LengthMod;
+// Define the array for non-constexpr uses.
+constexpr ConvTag ConvTagHolder::value[256];
-// Abbreviations to fit in the table below.
-constexpr auto f_sign = Flags::kSignCol;
-constexpr auto f_alt = Flags::kAlt;
-constexpr auto f_pos = Flags::kShowPos;
-constexpr auto f_left = Flags::kLeft;
-constexpr auto f_zero = Flags::kZero;
-
-ABSL_CONST_INIT const ConvTag kTags[256] = {
- {}, {}, {}, {}, {}, {}, {}, {}, // 00-07
- {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
- {}, {}, {}, {}, {}, {}, {}, {}, // 10-17
- {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
- f_sign, {}, {}, f_alt, {}, {}, {}, {}, // !"#$%&'
- {}, {}, {}, f_pos, {}, f_left, {}, {}, // ()*+,-./
- f_zero, {}, {}, {}, {}, {}, {}, {}, // 01234567
- {}, {}, {}, {}, {}, {}, {}, {}, // 89:;<=>?
- {}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG
- {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
- {}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW
- CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
- {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
- LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
- CC::p, LM::q, {}, CC::s, LM::t, CC::u, {}, {}, // pqrstuvw
- CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
- {}, {}, {}, {}, {}, {}, {}, {}, // 80-87
- {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
- {}, {}, {}, {}, {}, {}, {}, {}, // 90-97
- {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
- {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
- {}, {}, {}, {}, {}, {}, {}, {}, // a8-af
- {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
- {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
- {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
- {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
- {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
- {}, {}, {}, {}, {}, {}, {}, {}, // d8-df
- {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
- {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
- {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
- {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
-};
-
-namespace {
-
-bool CheckFastPathSetting(const UnboundConversion& conv) {
- bool width_precision_needed =
- conv.width.value() >= 0 || conv.precision.value() >= 0;
- if (width_precision_needed && conv.flags == Flags::kBasic) {
- fprintf(stderr,
- "basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
- "width=%d precision=%d\n",
- conv.flags == Flags::kBasic ? 1 : 0,
- FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kSignCol) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kAlt) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),
- conv.precision.value());
- return false;
- }
- return true;
-}
-
-template <bool is_positional>
-const char *ConsumeConversion(const char *pos, const char *const end,
- UnboundConversion *conv, int *next_arg) {
- const char* const original_pos = pos;
- char c;
- // Read the next char into `c` and update `pos`. Returns false if there are
- // no more chars to read.
-#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
- do { \
- if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
- c = *pos++; \
- } while (0)
-
- const auto parse_digits = [&] {
- int digits = c - '0';
- // We do not want to overflow `digits` so we consume at most digits10
- // digits. If there are more digits the parsing will fail later on when the
- // digit doesn't match the expected characters.
- int num_digits = std::numeric_limits<int>::digits10;
- for (;;) {
- if (ABSL_PREDICT_FALSE(pos == end)) break;
- c = *pos++;
- if (!std::isdigit(c)) break;
- --num_digits;
- if (ABSL_PREDICT_FALSE(!num_digits)) break;
- digits = 10 * digits + c - '0';
- }
- return digits;
- };
-
- if (is_positional) {
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->arg_position = parse_digits();
- assert(conv->arg_position > 0);
- if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
- }
-
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
-
- // We should start with the basic flag on.
- assert(conv->flags == Flags::kBasic);
-
- // Any non alpha character makes this conversion not basic.
- // This includes flags (-+ #0), width (1-9, *) or precision (.).
- // All conversion characters and length modifiers are alpha characters.
- if (c < 'A') {
- while (c <= '0') {
- auto tag = GetTagForChar(c);
- if (tag.is_flags()) {
- conv->flags = conv->flags | tag.as_flags();
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- break;
- }
- }
-
- if (c <= '9') {
- if (c >= '0') {
- int maybe_width = parse_digits();
- if (!is_positional && c == '$') {
- if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
- // Positional conversion.
- *next_arg = -1;
- return ConsumeConversion<true>(original_pos, end, conv, next_arg);
- }
- conv->flags = conv->flags | Flags::kNonBasic;
- conv->width.set_value(maybe_width);
- } else if (c == '*') {
- conv->flags = conv->flags | Flags::kNonBasic;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->width.set_from_arg(parse_digits());
- if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->width.set_from_arg(++*next_arg);
- }
- }
- }
-
- if (c == '.') {
- conv->flags = conv->flags | Flags::kNonBasic;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (std::isdigit(c)) {
- conv->precision.set_value(parse_digits());
- } else if (c == '*') {
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
- conv->precision.set_from_arg(parse_digits());
- if (c != '$') return nullptr;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->precision.set_from_arg(++*next_arg);
- }
- } else {
- conv->precision.set_value(0);
- }
- }
- }
-
- auto tag = GetTagForChar(c);
-
- if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
- if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
-
- // It is a length modifier.
- using str_format_internal::LengthMod;
- LengthMod length_mod = tag.as_length();
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (c == 'h' && length_mod == LengthMod::h) {
- conv->length_mod = LengthMod::hh;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else if (c == 'l' && length_mod == LengthMod::l) {
- conv->length_mod = LengthMod::ll;
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- conv->length_mod = length_mod;
- }
- tag = GetTagForChar(c);
- if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
- }
-
- assert(CheckFastPathSetting(*conv));
- (void)(&CheckFastPathSetting);
-
- conv->conv = tag.as_conv();
- if (!is_positional) conv->arg_position = ++*next_arg;
- return pos;
+ABSL_ATTRIBUTE_NOINLINE const char* ConsumeUnboundConversionNoInline(
+ const char* p, const char* end, UnboundConversion* conv, int* next_arg) {
+ return ConsumeUnboundConversion(p, end, conv, next_arg);
}
-} // namespace
-
std::string LengthModToString(LengthMod v) {
switch (v) {
case LengthMod::h:
@@ -258,12 +65,6 @@ std::string LengthModToString(LengthMod v) {
return "";
}
-const char *ConsumeUnboundConversion(const char *p, const char *end,
- UnboundConversion *conv, int *next_arg) {
- if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
- return ConsumeConversion<false>(p, end, conv, next_arg);
-}
-
struct ParsedFormatBase::ParsedFormatConsumer {
explicit ParsedFormatConsumer(ParsedFormatBase *parsedformat)
: parsed(parsedformat), data_pos(parsedformat->data_.get()) {}
@@ -312,11 +113,11 @@ bool ParsedFormatBase::MatchesConversions(
std::initializer_list<FormatConversionCharSet> convs) const {
std::unordered_set<int> used;
auto add_if_valid_conv = [&](int pos, char c) {
- if (static_cast<size_t>(pos) > convs.size() ||
- !Contains(convs.begin()[pos - 1], c))
- return false;
- used.insert(pos);
- return true;
+ if (static_cast<size_t>(pos) > convs.size() ||
+ !Contains(convs.begin()[pos - 1], c))
+ return false;
+ used.insert(pos);
+ return true;
};
for (const ConversionItem &item : items_) {
if (!item.is_conversion) continue;
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
index 32b91d034d..35b6d49c14 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_format/parser.h
@@ -29,111 +29,18 @@
#include <vector>
#include "absl/strings/internal/str_format/checker.h"
+#include "absl/strings/internal/str_format/constexpr_parser.h"
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
-
std::string LengthModToString(LengthMod v);
-// The analyzed properties of a single specified conversion.
-struct UnboundConversion {
- UnboundConversion() {}
-
- class InputValue {
- public:
- void set_value(int value) {
- assert(value >= 0);
- value_ = value;
- }
- int value() const { return value_; }
-
- // Marks the value as "from arg". aka the '*' format.
- // Requires `value >= 1`.
- // When set, is_from_arg() return true and get_from_arg() returns the
- // original value.
- // `value()`'s return value is unspecfied in this state.
- void set_from_arg(int value) {
- assert(value > 0);
- value_ = -value - 1;
- }
- bool is_from_arg() const { return value_ < -1; }
- int get_from_arg() const {
- assert(is_from_arg());
- return -value_ - 1;
- }
-
- private:
- int value_ = -1;
- };
-
- // No need to initialize. It will always be set in the parser.
- int arg_position;
-
- InputValue width;
- InputValue precision;
-
- Flags flags = Flags::kBasic;
- LengthMod length_mod = LengthMod::none;
- FormatConversionChar conv = FormatConversionCharInternal::kNone;
-};
-
-// Consume conversion spec prefix (not including '%') of [p, end) if valid.
-// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
-// If valid, it returns the first character following the conversion spec,
-// and the spec part is broken down and returned in 'conv'.
-// If invalid, returns nullptr.
-const char* ConsumeUnboundConversion(const char* p, const char* end,
- UnboundConversion* conv, int* next_arg);
-
-// Helper tag class for the table below.
-// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
-// conversions.
-class ConvTag {
- public:
- constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
- : tag_(static_cast<uint8_t>(conversion_char)) {}
- constexpr ConvTag(LengthMod length_mod) // NOLINT
- : tag_(0x80 | static_cast<uint8_t>(length_mod)) {}
- constexpr ConvTag(Flags flags) // NOLINT
- : tag_(0xc0 | static_cast<uint8_t>(flags)) {}
- constexpr ConvTag() : tag_(0xFF) {}
-
- bool is_conv() const { return (tag_ & 0x80) == 0; }
- bool is_length() const { return (tag_ & 0xC0) == 0x80; }
- bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
-
- FormatConversionChar as_conv() const {
- assert(is_conv());
- assert(!is_length());
- assert(!is_flags());
- return static_cast<FormatConversionChar>(tag_);
- }
- LengthMod as_length() const {
- assert(!is_conv());
- assert(is_length());
- assert(!is_flags());
- return static_cast<LengthMod>(tag_ & 0x3F);
- }
- Flags as_flags() const {
- assert(!is_conv());
- assert(!is_length());
- assert(is_flags());
- return static_cast<Flags>(tag_ & 0x1F);
- }
-
- private:
- uint8_t tag_;
-};
-
-extern const ConvTag kTags[256];
-// Keep a single table for all the conversion chars and length modifiers.
-inline ConvTag GetTagForChar(char c) {
- return kTags[static_cast<unsigned char>(c)];
-}
+const char* ConsumeUnboundConversionNoInline(const char* p, const char* end,
+ UnboundConversion* conv,
+ int* next_arg);
// Parse the format string provided in 'src' and pass the identified items into
// 'consumer'.
@@ -155,10 +62,11 @@ bool ParseFormatString(string_view src, Consumer consumer) {
static_cast<const char*>(memchr(p, '%', static_cast<size_t>(end - p)));
if (!percent) {
// We found the last substring.
- return consumer.Append(string_view(p, end - p));
+ return consumer.Append(string_view(p, static_cast<size_t>(end - p)));
}
// We found a percent, so push the text run then process the percent.
- if (ABSL_PREDICT_FALSE(!consumer.Append(string_view(p, percent - p)))) {
+ if (ABSL_PREDICT_FALSE(!consumer.Append(
+ string_view(p, static_cast<size_t>(percent - p))))) {
return false;
}
if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;
@@ -186,10 +94,11 @@ bool ParseFormatString(string_view src, Consumer consumer) {
}
} else if (percent[1] != '%') {
UnboundConversion conv;
- p = ConsumeUnboundConversion(percent + 1, end, &conv, &next_arg);
+ p = ConsumeUnboundConversionNoInline(percent + 1, end, &conv, &next_arg);
if (ABSL_PREDICT_FALSE(p == nullptr)) return false;
if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(
- conv, string_view(percent + 1, p - (percent + 1))))) {
+ conv, string_view(percent + 1,
+ static_cast<size_t>(p - (percent + 1)))))) {
return false;
}
} else {
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
index e766421617..35edf3aa43 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/str_split_internal.h
@@ -132,7 +132,8 @@ class SplitIterator {
const absl::string_view text = splitter_->text();
const absl::string_view d = delimiter_.Find(text, pos_);
if (d.data() == text.data() + text.size()) state_ = kLastState;
- curr_ = text.substr(pos_, d.data() - (text.data() + pos_));
+ curr_ = text.substr(pos_,
+ static_cast<size_t>(d.data() - (text.data() + pos_)));
pos_ += curr_.size() + d.size();
} while (!predicate_(curr_));
return *this;
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc b/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc
new file mode 100644
index 0000000000..7c6995abb1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.cc
@@ -0,0 +1,28 @@
+// 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/strings/internal/stringify_sink.h"
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+void StringifySink::Append(size_t count, char ch) { buffer_.append(count, ch); }
+
+void StringifySink::Append(string_view v) {
+ buffer_.append(v.data(), v.size());
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.h b/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.h
new file mode 100644
index 0000000000..fc3747bb72
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/stringify_sink.h
@@ -0,0 +1,57 @@
+// 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_STRINGS_INTERNAL_STRINGIFY_SINK_H_
+#define ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
+
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace strings_internal {
+class StringifySink {
+ public:
+ void Append(size_t count, char ch);
+
+ void Append(string_view v);
+
+ // Support `absl::Format(&sink, format, args...)`.
+ friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) {
+ sink->Append(v);
+ }
+
+ private:
+ template <typename T>
+ friend string_view ExtractStringification(StringifySink& sink, const T& v);
+
+ std::string buffer_;
+};
+
+template <typename T>
+string_view ExtractStringification(StringifySink& sink, const T& v) {
+ AbslStringify(sink, v);
+ return sink.buffer_;
+}
+
+} // namespace strings_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_STRINGIFY_SINK_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
index e798fc69f7..2987158e07 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/numbers.cc
@@ -190,32 +190,32 @@ char* numbers_internal::FastIntToBuffer(uint32_t i, char* buffer) {
if (i >= 1000) goto lt10_000;
digits = i / 100;
i -= digits * 100;
- *buffer++ = '0' + digits;
+ *buffer++ = '0' + static_cast<char>(digits);
goto lt100;
}
if (i < 1000000) { // 1,000,000
if (i >= 100000) goto lt1_000_000;
digits = i / 10000; // 10,000
i -= digits * 10000;
- *buffer++ = '0' + digits;
+ *buffer++ = '0' + static_cast<char>(digits);
goto lt10_000;
}
if (i < 100000000) { // 100,000,000
if (i >= 10000000) goto lt100_000_000;
digits = i / 1000000; // 1,000,000
i -= digits * 1000000;
- *buffer++ = '0' + digits;
+ *buffer++ = '0' + static_cast<char>(digits);
goto lt1_000_000;
}
// we already know that i < 1,000,000,000
digits = i / 100000000; // 100,000,000
i -= digits * 100000000;
- *buffer++ = '0' + digits;
+ *buffer++ = '0' + static_cast<char>(digits);
goto lt100_000_000;
}
char* numbers_internal::FastIntToBuffer(int32_t i, char* buffer) {
- uint32_t u = i;
+ uint32_t u = static_cast<uint32_t>(i);
if (i < 0) {
*buffer++ = '-';
// We need to do the negation in modular (i.e., "unsigned")
@@ -268,7 +268,7 @@ char* numbers_internal::FastIntToBuffer(uint64_t i, char* buffer) {
}
char* numbers_internal::FastIntToBuffer(int64_t i, char* buffer) {
- uint64_t u = i;
+ uint64_t u = static_cast<uint64_t>(i);
if (i < 0) {
*buffer++ = '-';
u = 0 - u;
@@ -329,7 +329,7 @@ static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
result = Mul32(result, 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5);
expfive -= 13;
}
- constexpr int powers_of_five[13] = {
+ constexpr uint32_t powers_of_five[13] = {
1,
5,
5 * 5,
@@ -404,14 +404,14 @@ static ExpDigits SplitToSix(const double value) {
// we multiply it by 65536 and see if the fractional part is close to 32768.
// (The number doesn't have to be a power of two,but powers of two are faster)
uint64_t d64k = d * 65536;
- int dddddd; // A 6-digit decimal integer.
+ uint32_t dddddd; // A 6-digit decimal integer.
if ((d64k % 65536) == 32767 || (d64k % 65536) == 32768) {
// OK, it's fairly likely that precision was lost above, which is
// not a surprise given only 52 mantissa bits are available. Therefore
// redo the calculation using 128-bit numbers. (64 bits are not enough).
// Start out with digits rounded down; maybe add one below.
- dddddd = static_cast<int>(d64k / 65536);
+ dddddd = static_cast<uint32_t>(d64k / 65536);
// mantissa is a 64-bit integer representing M.mmm... * 2^63. The actual
// value we're representing, of course, is M.mmm... * 2^exp2.
@@ -461,7 +461,7 @@ static ExpDigits SplitToSix(const double value) {
}
} else {
// Here, we are not close to the edge.
- dddddd = static_cast<int>((d64k + 32768) / 65536);
+ dddddd = static_cast<uint32_t>((d64k + 32768) / 65536);
}
if (dddddd == 1000000) {
dddddd = 100000;
@@ -469,7 +469,7 @@ static ExpDigits SplitToSix(const double value) {
}
exp_dig.exponent = exp;
- int two_digits = dddddd / 10000;
+ uint32_t two_digits = dddddd / 10000;
dddddd -= two_digits * 10000;
numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
@@ -499,7 +499,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
if (std::signbit(d)) *out++ = '-';
*out++ = '0';
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
}
if (d < 0) {
*out++ = '-';
@@ -507,7 +507,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
}
if (d > std::numeric_limits<double>::max()) {
strcpy(out, "inf"); // NOLINT(runtime/printf)
- return out + 3 - buffer;
+ return static_cast<size_t>(out + 3 - buffer);
}
auto exp_dig = SplitToSix(d);
@@ -519,7 +519,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
case 5:
memcpy(out, &digits[0], 6), out += 6;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case 4:
memcpy(out, &digits[0], 5), out += 5;
if (digits[5] != '0') {
@@ -527,7 +527,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
*out++ = digits[5];
}
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case 3:
memcpy(out, &digits[0], 4), out += 4;
if ((digits[5] | digits[4]) != '0') {
@@ -536,7 +536,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
if (digits[5] != '0') *out++ = digits[5];
}
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case 2:
memcpy(out, &digits[0], 3), out += 3;
*out++ = '.';
@@ -545,7 +545,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
while (out[-1] == '0') --out;
if (out[-1] == '.') --out;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case 1:
memcpy(out, &digits[0], 2), out += 2;
*out++ = '.';
@@ -554,7 +554,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
while (out[-1] == '0') --out;
if (out[-1] == '.') --out;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case 0:
memcpy(out, &digits[0], 1), out += 1;
*out++ = '.';
@@ -563,7 +563,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
while (out[-1] == '0') --out;
if (out[-1] == '.') --out;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
case -4:
out[2] = '0';
++out;
@@ -582,7 +582,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
out += 6;
while (out[-1] == '0') --out;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
}
assert(exp < -4 || exp >= 6);
out[0] = digits[0];
@@ -601,12 +601,12 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
if (exp > 99) {
int dig1 = exp / 100;
exp -= dig1 * 100;
- *out++ = '0' + dig1;
+ *out++ = '0' + static_cast<char>(dig1);
}
- PutTwoDigits(exp, out);
+ PutTwoDigits(static_cast<uint32_t>(exp), out);
out += 2;
*out = 0;
- return out - buffer;
+ return static_cast<size_t>(out - buffer);
}
namespace {
@@ -642,10 +642,12 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
int base = *base_ptr;
// Consume whitespace.
- while (start < end && absl::ascii_isspace(start[0])) {
+ while (start < end &&
+ absl::ascii_isspace(static_cast<unsigned char>(start[0]))) {
++start;
}
- while (start < end && absl::ascii_isspace(end[-1])) {
+ while (start < end &&
+ absl::ascii_isspace(static_cast<unsigned char>(end[-1]))) {
--end;
}
if (start >= end) {
@@ -694,7 +696,7 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
} else {
return false;
}
- *text = absl::string_view(start, end - start);
+ *text = absl::string_view(start, static_cast<size_t>(end - start));
*base_ptr = base;
return true;
}
@@ -920,17 +922,18 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
const IntType vmax = std::numeric_limits<IntType>::max();
assert(vmax > 0);
assert(base >= 0);
- assert(vmax >= static_cast<IntType>(base));
+ const IntType base_inttype = static_cast<IntType>(base);
+ assert(vmax >= base_inttype);
const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
assert(base < 2 ||
- std::numeric_limits<IntType>::max() / base == vmax_over_base);
+ std::numeric_limits<IntType>::max() / base_inttype == vmax_over_base);
const char* start = text.data();
const char* end = start + text.size();
// loop over digits
for (; start < end; ++start) {
unsigned char c = static_cast<unsigned char>(start[0]);
- int digit = kAsciiToInt[c];
- if (digit >= base) {
+ IntType digit = static_cast<IntType>(kAsciiToInt[c]);
+ if (digit >= base_inttype) {
*value_p = value;
return false;
}
@@ -938,7 +941,7 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
*value_p = vmax;
return false;
}
- value *= base;
+ value *= base_inttype;
if (value > vmax - digit) {
*value_p = vmax;
return false;
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
index f4a77493a4..114a2ff284 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.cc
@@ -17,12 +17,15 @@
#include <assert.h>
#include <algorithm>
+#include <cstddef>
#include <cstdint>
#include <cstring>
+#include <string>
#include "absl/strings/ascii.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/numbers.h"
+#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -56,7 +59,7 @@ AlphaNum::AlphaNum(Dec dec) {
*--writer = '0' + (value % 10);
value /= 10;
}
- *--writer = '0' + value;
+ *--writer = '0' + static_cast<char>(value);
if (neg) *--writer = '-';
ptrdiff_t fillers = writer - minfill;
@@ -73,7 +76,7 @@ AlphaNum::AlphaNum(Dec dec) {
if (add_sign_again) *--writer = '-';
}
- piece_ = absl::string_view(writer, end - writer);
+ piece_ = absl::string_view(writer, static_cast<size_t>(end - writer));
}
// ----------------------------------------------------------------------
@@ -141,12 +144,12 @@ namespace strings_internal {
std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
std::string result;
size_t total_size = 0;
- for (const absl::string_view& piece : pieces) total_size += piece.size();
+ for (absl::string_view piece : pieces) total_size += piece.size();
strings_internal::STLStringResizeUninitialized(&result, total_size);
char* const begin = &result[0];
char* out = begin;
- for (const absl::string_view& piece : pieces) {
+ for (absl::string_view piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
@@ -170,7 +173,7 @@ void AppendPieces(std::string* dest,
std::initializer_list<absl::string_view> pieces) {
size_t old_size = dest->size();
size_t total_size = old_size;
- for (const absl::string_view& piece : pieces) {
+ for (absl::string_view piece : pieces) {
ASSERT_NO_OVERLAP(*dest, piece);
total_size += piece.size();
}
@@ -178,7 +181,7 @@ void AppendPieces(std::string* dest,
char* const begin = &(*dest)[0];
char* out = begin + old_size;
- for (const absl::string_view& piece : pieces) {
+ for (absl::string_view piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
index a94bc5df69..730b4d8c60 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_cat.h
@@ -48,6 +48,40 @@
// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
// a `PadSpec` enum.
//
+// User-defined types can be formatted with the `AbslStringify()` customization
+// point. The API relies on detecting an overload in the user-defined type's
+// namespace of a free (non-member) `AbslStringify()` function as a definition
+// (typically declared as a friend and implemented in-line.
+// with the following signature:
+//
+// class MyClass { ... };
+//
+// template <typename Sink>
+// void AbslStringify(Sink& sink, const MyClass& value);
+//
+// An `AbslStringify()` overload for a type should only be declared in the same
+// file and namespace as said type.
+//
+// Note that `AbslStringify()` also supports use with `absl::StrFormat()` and
+// `absl::Substitute()`.
+//
+// Example:
+//
+// struct Point {
+// // To add formatting support to `Point`, we simply need to add a free
+// // (non-member) function `AbslStringify()`. This method specifies how
+// // Point should be printed when absl::StrCat() is called on it. You can add
+// // such a free function using a friend declaration within the body of the
+// // class. The sink parameter is a templated type to avoid requiring
+// // dependencies.
+// template <typename Sink> friend void AbslStringify(Sink&
+// sink, const Point& p) {
+// absl::Format(&sink, "(%v, %v)", p.x, p.y);
+// }
+//
+// int x;
+// int y;
+// };
// -----------------------------------------------------------------------------
#ifndef ABSL_STRINGS_STR_CAT_H_
@@ -57,9 +91,12 @@
#include <cstdint>
#include <string>
#include <type_traits>
+#include <utility>
#include <vector>
#include "absl/base/port.h"
+#include "absl/strings/internal/has_absl_stringify.h"
+#include "absl/strings/internal/stringify_sink.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
@@ -205,8 +242,10 @@ struct Dec {
// -----------------------------------------------------------------------------
//
// The `AlphaNum` class acts as the main parameter type for `StrCat()` and
-// `StrAppend()`, providing efficient conversion of numeric, boolean, and
-// hexadecimal values (through the `Hex` type) into strings.
+// `StrAppend()`, providing efficient conversion of numeric, boolean, decimal,
+// and hexadecimal values (through the `Dec` and `Hex` types) into strings.
+// `AlphaNum` should only be used as a function parameter. Do not instantiate
+// `AlphaNum` directly as a stack variable.
class AlphaNum {
public:
@@ -255,6 +294,13 @@ class AlphaNum {
: piece_(NullSafeStringView(c_str)) {} // NOLINT(runtime/explicit)
AlphaNum(absl::string_view pc) : piece_(pc) {} // NOLINT(runtime/explicit)
+ template <typename T, typename = typename std::enable_if<
+ strings_internal::HasAbslStringify<T>::value>::type>
+ AlphaNum( // NOLINT(runtime/explicit)
+ const T& v, // NOLINT(runtime/explicit)
+ strings_internal::StringifySink&& sink = {}) // NOLINT(runtime/explicit)
+ : piece_(strings_internal::ExtractStringification(sink, v)) {}
+
template <typename Allocator>
AlphaNum( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
@@ -274,7 +320,8 @@ class AlphaNum {
// This overload matches only scoped enums.
template <typename T,
typename = typename std::enable_if<
- std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
+ std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
+ !strings_internal::HasAbslStringify<T>::value>::type>
AlphaNum(T e) // NOLINT(runtime/explicit)
: AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/str_format.h b/contrib/restricted/abseil-cpp/absl/strings/str_format.h
index 4b05c70c23..3536b70e9d 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/str_format.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/str_format.h
@@ -191,9 +191,9 @@ class FormatCountCapture {
// absl::StrFormat(formatString, "TheVillage", 6);
//
// A format string generally follows the POSIX syntax as used within the POSIX
-// `printf` specification.
+// `printf` specification. (Exceptions are noted below.)
//
-// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
+// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html)
//
// In specific, the `FormatSpec` supports the following type specifiers:
// * `c` for characters
@@ -211,6 +211,10 @@ class FormatCountCapture {
// * `n` for the special case of writing out the number of characters
// written to this point. The resulting value must be captured within an
// `absl::FormatCountCapture` type.
+// * `v` for values using the default format for a deduced type. These deduced
+// types include many of the primitive types denoted here as well as
+// user-defined types containing the proper extensions. (See below for more
+// information.)
//
// Implementation-defined behavior:
// * A null pointer provided to "%s" or "%p" is output as "(nil)".
@@ -239,6 +243,15 @@ class FormatCountCapture {
// "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
// EXPECT_EQ(8, n);
//
+// NOTE: the `v` specifier (for "value") is a type specifier not present in the
+// POSIX specification. %v will format values according to their deduced type.
+// `v` uses `d` for signed integer values, `u` for unsigned integer values, `g`
+// for floating point values, and formats boolean values as "true"/"false"
+// (instead of 1 or 0 for booleans formatted using d). `const char*` is not
+// supported; please use `std:string` and `string_view`. `char` is also not
+// supported due to ambiguity of the type. This specifier does not support
+// modifiers.
+//
// The `FormatSpec` intrinsically supports all of these fundamental C++ types:
//
// * Characters: `char`, `signed char`, `unsigned char`
@@ -570,6 +583,41 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
// StrFormat Extensions
//------------------------------------------------------------------------------
//
+// AbslStringify()
+//
+// A simpler customization API for formatting user-defined types using
+// absl::StrFormat(). The API relies on detecting an overload in the
+// user-defined type's namespace of a free (non-member) `AbslStringify()`
+// function as a friend definition with the following signature:
+//
+// template <typename Sink>
+// void AbslStringify(Sink& sink, const X& value);
+//
+// An `AbslStringify()` overload for a type should only be declared in the same
+// file and namespace as said type.
+//
+// Note that unlike with AbslFormatConvert(), AbslStringify() does not allow
+// customization of allowed conversion characters. AbslStringify() uses `%v` as
+// the underlying conversion specififer. Additionally, AbslStringify() supports
+// use with absl::StrCat while AbslFormatConvert() does not.
+//
+// Example:
+//
+// struct Point {
+// // To add formatting support to `Point`, we simply need to add a free
+// // (non-member) function `AbslStringify()`. This method prints in the
+// // request format using the underlying `%v` specifier. You can add such a
+// // free function using a friend declaration within the body of the class.
+// // The sink parameter is a templated type to avoid requiring dependencies.
+// template <typename Sink>
+// friend void AbslStringify(Sink& sink, const Point& p) {
+// absl::Format(&sink, "(%v, %v)", p.x, p.y);
+// }
+//
+// int x;
+// int y;
+// };
+//
// AbslFormatConvert()
//
// The StrFormat library provides a customization API for formatting
@@ -616,9 +664,9 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
// absl::FormatSink* s) {
// if (spec.conversion_char() == absl::FormatConversionChar::s) {
-// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+// absl::Format(s, "x=%vy=%v", p.x, p.y);
// } else {
-// s->Append(absl::StrCat(p.x, ",", p.y));
+// absl::Format(s, "%v,%v", p.x, p.y);
// }
// return {true};
// }
@@ -637,7 +685,7 @@ enum class FormatConversionChar : uint8_t {
c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
- n, p // misc
+ n, p, v // misc
};
// clang-format on
@@ -757,6 +805,7 @@ enum class FormatConversionCharSet : uint64_t {
// misc
n = str_format_internal::FormatConversionCharToConvInt('n'),
p = str_format_internal::FormatConversionCharToConvInt('p'),
+ v = str_format_internal::FormatConversionCharToConvInt('v'),
// Used for width/precision '*' specification.
kStar = static_cast<uint64_t>(
@@ -771,23 +820,36 @@ enum class FormatConversionCharSet : uint64_t {
// FormatSink
//
-// An abstraction to which conversions write their string data.
+// A format sink is a generic abstraction to which conversions may write their
+// formatted string data. `absl::FormatConvert()` uses this sink to write its
+// formatted string.
//
class FormatSink {
public:
- // Appends `count` copies of `ch`.
+ // FormatSink::Append()
+ //
+ // Appends `count` copies of `ch` to the format sink.
void Append(size_t count, char ch) { sink_->Append(count, ch); }
+ // Overload of FormatSink::Append() for appending the characters of a string
+ // view to a format sink.
void Append(string_view v) { sink_->Append(v); }
- // Appends the first `precision` bytes of `v`. If this is less than
- // `width`, spaces will be appended first (if `left` is false), or
+ // FormatSink::PutPaddedString()
+ //
+ // Appends `precision` number of bytes of `v` to the format sink. If this is
+ // less than `width`, spaces will be appended first (if `left` is false), or
// after (if `left` is true) to ensure the total amount appended is
// at least `width`.
bool PutPaddedString(string_view v, int width, int precision, bool left) {
return sink_->PutPaddedString(v, width, precision, left);
}
+ // Support `absl::Format(&sink, format, args...)`.
+ friend void AbslFormatFlush(FormatSink* sink, absl::string_view v) {
+ sink->Append(v);
+ }
+
private:
friend str_format_internal::FormatSinkImpl;
explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
index adce3be94e..e2261625f9 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.cc
@@ -32,7 +32,7 @@ void WritePadding(std::ostream& o, size_t pad) {
memset(fill_buf, o.fill(), sizeof(fill_buf));
while (pad) {
size_t n = std::min(pad, sizeof(fill_buf));
- o.write(fill_buf, n);
+ o.write(fill_buf, static_cast<std::streamsize>(n));
pad -= n;
}
}
@@ -63,7 +63,7 @@ std::ostream& operator<<(std::ostream& o, string_view piece) {
size_t lpad = 0;
size_t rpad = 0;
if (static_cast<size_t>(o.width()) > piece.size()) {
- size_t pad = o.width() - piece.size();
+ size_t pad = static_cast<size_t>(o.width()) - piece.size();
if ((o.flags() & o.adjustfield) == o.left) {
rpad = pad;
} else {
@@ -71,7 +71,7 @@ std::ostream& operator<<(std::ostream& o, string_view piece) {
}
}
if (lpad) WritePadding(o, lpad);
- o.write(piece.data(), piece.size());
+ o.write(piece.data(), static_cast<std::streamsize>(piece.size()));
if (rpad) WritePadding(o, rpad);
o.width(0);
}
@@ -86,7 +86,7 @@ string_view::size_type string_view::find(string_view s,
}
const char* result =
strings_internal::memmatch(ptr_ + pos, length_ - pos, s.ptr_, s.length_);
- return result ? result - ptr_ : npos;
+ return result ? static_cast<size_type>(result - ptr_) : npos;
}
string_view::size_type string_view::find(char c, size_type pos) const noexcept {
@@ -95,7 +95,7 @@ string_view::size_type string_view::find(char c, size_type pos) const noexcept {
}
const char* result =
static_cast<const char*>(memchr(ptr_ + pos, c, length_ - pos));
- return result != nullptr ? result - ptr_ : npos;
+ return result != nullptr ? static_cast<size_type>(result - ptr_) : npos;
}
string_view::size_type string_view::rfind(string_view s,
@@ -104,7 +104,7 @@ string_view::size_type string_view::rfind(string_view s,
if (s.empty()) return std::min(length_, pos);
const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
- return result != last ? result - ptr_ : npos;
+ return result != last ? static_cast<size_type>(result - ptr_) : npos;
}
// Search range is [0..pos] inclusive. If pos == npos, search everything.
diff --git a/contrib/restricted/abseil-cpp/absl/strings/string_view.h b/contrib/restricted/abseil-cpp/absl/strings/string_view.h
index d0c870696c..01867b6414 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/string_view.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/string_view.h
@@ -65,12 +65,6 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-#if defined(__cplusplus) && __cplusplus >= 201402L
-#define ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR constexpr
-#else
-#define ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -343,7 +337,7 @@ class string_view {
//
// Removes the first `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n) {
+ constexpr void remove_prefix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
ptr_ += n;
length_ -= n;
@@ -353,7 +347,7 @@ class string_view {
//
// Removes the last `n` characters from the `string_view`. Note that the
// underlying string is not changed, only the view.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_suffix(size_type n) {
+ constexpr void remove_suffix(size_type n) {
ABSL_HARDENING_ASSERT(n <= length_);
length_ -= n;
}
@@ -361,7 +355,7 @@ class string_view {
// string_view::swap()
//
// Swaps this `string_view` with another `string_view`.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void swap(string_view& s) noexcept {
+ constexpr void swap(string_view& s) noexcept {
auto t = *this;
*this = s;
s = t;
@@ -680,7 +674,6 @@ std::ostream& operator<<(std::ostream& o, string_view piece);
ABSL_NAMESPACE_END
} // namespace absl
-#undef ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
index 8980b198c2..33a39305db 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
+++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.cc
@@ -40,7 +40,8 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
absl::CEscape(format).c_str());
#endif
return;
- } else if (absl::ascii_isdigit(format[i + 1])) {
+ } else if (absl::ascii_isdigit(
+ static_cast<unsigned char>(format[i + 1]))) {
int index = format[i + 1] - '0';
if (static_cast<size_t>(index) >= num_args) {
#ifndef NDEBUG
@@ -80,7 +81,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
char* target = &(*output)[original_size];
for (size_t i = 0; i < format.size(); i++) {
if (format[i] == '$') {
- if (absl::ascii_isdigit(format[i + 1])) {
+ if (absl::ascii_isdigit(static_cast<unsigned char>(format[i + 1]))) {
const absl::string_view src = args_array[format[i + 1] - '0'];
target = std::copy(src.begin(), src.end(), target);
++i; // Skip next char.
@@ -110,7 +111,8 @@ Arg::Arg(const void* value) {
} while (num != 0);
*--ptr = 'x';
*--ptr = '0';
- piece_ = absl::string_view(ptr, scratch_ + sizeof(scratch_) - ptr);
+ piece_ = absl::string_view(
+ ptr, static_cast<size_t>(scratch_ + sizeof(scratch_) - ptr));
}
}
@@ -132,7 +134,7 @@ Arg::Arg(Hex hex) {
beg = writer;
}
- piece_ = absl::string_view(beg, end - beg);
+ piece_ = absl::string_view(beg, static_cast<size_t>(end - beg));
}
// TODO(jorg): Don't duplicate so much code between here and str_cat.cc
@@ -147,7 +149,7 @@ Arg::Arg(Dec dec) {
*--writer = '0' + (value % 10);
value /= 10;
}
- *--writer = '0' + value;
+ *--writer = '0' + static_cast<char>(value);
if (neg) *--writer = '-';
ptrdiff_t fillers = writer - minfill;
@@ -164,7 +166,7 @@ Arg::Arg(Dec dec) {
if (add_sign_again) *--writer = '-';
}
- piece_ = absl::string_view(writer, end - writer);
+ piece_ = absl::string_view(writer, static_cast<size_t>(end - writer));
}
} // namespace substitute_internal
diff --git a/contrib/restricted/abseil-cpp/absl/strings/substitute.h b/contrib/restricted/abseil-cpp/absl/strings/substitute.h
index 6d2b08abb9..d6a5a690d7 100644
--- a/contrib/restricted/abseil-cpp/absl/strings/substitute.h
+++ b/contrib/restricted/abseil-cpp/absl/strings/substitute.h
@@ -55,6 +55,8 @@
// * bool (Printed as "true" or "false")
// * pointer types other than char* (Printed as "0x<lower case hex string>",
// except that null is printed as "NULL")
+// * user-defined types via the `AbslStringify()` customization point. See the
+// documentation for `absl::StrCat` for an explanation on how to use this.
//
// If an invalid format string is provided, Substitute returns an empty string
// and SubstituteAndAppend does not change the provided output string.
@@ -79,6 +81,7 @@
#include "absl/base/port.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
+#include "absl/strings/internal/stringify_sink.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_split.h"
@@ -102,14 +105,14 @@ class Arg {
// Overloads for string-y things
//
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
- Arg(const char* value) // NOLINT(runtime/explicit)
+ Arg(const char* value) // NOLINT(google-explicit-constructor)
: piece_(absl::NullSafeStringView(value)) {}
template <typename Allocator>
Arg( // NOLINT
const std::basic_string<char, std::char_traits<char>, Allocator>&
value) noexcept
: piece_(value) {}
- Arg(absl::string_view value) // NOLINT(runtime/explicit)
+ Arg(absl::string_view value) // NOLINT(google-explicit-constructor)
: piece_(value) {}
// Overloads for primitives
@@ -119,45 +122,67 @@ class Arg {
// probably using them as 8-bit integers and would probably prefer an integer
// representation. However, we can't really know, so we make the caller decide
// what to do.
- Arg(char value) // NOLINT(runtime/explicit)
+ Arg(char value) // NOLINT(google-explicit-constructor)
: piece_(scratch_, 1) {
scratch_[0] = value;
}
Arg(short value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
Arg(unsigned short value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(int value) // NOLINT(runtime/explicit)
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
+ Arg(int value) // NOLINT(google-explicit-constructor)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(unsigned int value) // NOLINT(runtime/explicit)
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
+ Arg(unsigned int value) // NOLINT(google-explicit-constructor)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
Arg(long value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
Arg(unsigned long value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
Arg(long long value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
Arg(unsigned long long value) // NOLINT(*)
: piece_(scratch_,
- numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
- Arg(float value) // NOLINT(runtime/explicit)
+ static_cast<size_t>(
+ numbers_internal::FastIntToBuffer(value, scratch_) -
+ scratch_)) {}
+ Arg(float value) // NOLINT(google-explicit-constructor)
: piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
}
- Arg(double value) // NOLINT(runtime/explicit)
+ Arg(double value) // NOLINT(google-explicit-constructor)
: piece_(scratch_, numbers_internal::SixDigitsToBuffer(value, scratch_)) {
}
- Arg(bool value) // NOLINT(runtime/explicit)
+ Arg(bool value) // NOLINT(google-explicit-constructor)
: piece_(value ? "true" : "false") {}
- Arg(Hex hex); // NOLINT(runtime/explicit)
- Arg(Dec dec); // NOLINT(runtime/explicit)
+ template <typename T, typename = typename std::enable_if<
+ strings_internal::HasAbslStringify<T>::value>::type>
+ Arg( // NOLINT(google-explicit-constructor)
+ const T& v, strings_internal::StringifySink&& sink = {})
+ : piece_(strings_internal::ExtractStringification(sink, v)) {}
+
+ Arg(Hex hex); // NOLINT(google-explicit-constructor)
+ Arg(Dec dec); // NOLINT(google-explicit-constructor)
// vector<bool>::reference and const_reference require special help to convert
// to `Arg` because it requires two user defined conversions.
@@ -172,13 +197,14 @@ class Arg {
// `void*` values, with the exception of `char*`, are printed as
// "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
- Arg(const void* value); // NOLINT(runtime/explicit)
+ Arg(const void* value); // NOLINT(google-explicit-constructor)
// Normal enums are already handled by the integer formatters.
// This overload matches only scoped enums.
template <typename T,
typename = typename std::enable_if<
- std::is_enum<T>{} && !std::is_convertible<T, int>{}>::type>
+ std::is_enum<T>{} && !std::is_convertible<T, int>{} &&
+ !strings_internal::HasAbslStringify<T>::value>::type>
Arg(T value) // NOLINT(google-explicit-constructor)
: Arg(static_cast<typename std::underlying_type<T>::type>(value)) {}
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/futex.h b/contrib/restricted/abseil-cpp/absl/synchronization/internal/futex.h
index 06fbd6d072..cb97da09ce 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/futex.h
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/futex.h
@@ -87,7 +87,7 @@ class FutexImpl {
public:
static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
KernelTimeout t) {
- int err = 0;
+ long err = 0; // NOLINT(runtime/int)
if (t.has_timeout()) {
// https://locklessinc.com/articles/futex_cheat_sheet/
// Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
@@ -105,41 +105,44 @@ class FutexImpl {
FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
}
if (ABSL_PREDICT_FALSE(err != 0)) {
- err = -errno;
+ return -errno;
}
- return err;
+ return 0;
}
static int WaitBitsetAbsoluteTimeout(std::atomic<int32_t> *v, int32_t val,
int32_t bits,
const struct timespec *abstime) {
- int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
- nullptr, bits);
+ // NOLINTNEXTLINE(runtime/int)
+ long err = syscall(SYS_futex, reinterpret_cast<int32_t*>(v),
+ FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
+ nullptr, bits);
if (ABSL_PREDICT_FALSE(err != 0)) {
- err = -errno;
+ return -errno;
}
- return err;
+ return 0;
}
static int Wake(std::atomic<int32_t> *v, int32_t count) {
- int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
+ // NOLINTNEXTLINE(runtime/int)
+ long err = syscall(SYS_futex, reinterpret_cast<int32_t*>(v),
+ FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
if (ABSL_PREDICT_FALSE(err < 0)) {
- err = -errno;
+ return -errno;
}
- return err;
+ return 0;
}
// FUTEX_WAKE_BITSET
static int WakeBitset(std::atomic<int32_t> *v, int32_t count, int32_t bits) {
- int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
- nullptr, bits);
+ // NOLINTNEXTLINE(runtime/int)
+ long err = syscall(SYS_futex, reinterpret_cast<int32_t*>(v),
+ FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
+ nullptr, bits);
if (ABSL_PREDICT_FALSE(err < 0)) {
- err = -errno;
+ return -errno;
}
- return err;
+ return 0;
}
};
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/contrib/restricted/abseil-cpp/absl/synchronization/internal/graphcycles.cc
index 27fec21681..feec4581fe 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/graphcycles.cc
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/graphcycles.cc
@@ -181,9 +181,9 @@ class NodeSet {
return true;
}
- void erase(uint32_t v) {
+ void erase(int32_t v) {
uint32_t i = FindIndex(v);
- if (static_cast<uint32_t>(table_[i]) == v) {
+ if (table_[i] == v) {
table_[i] = kDel;
}
}
@@ -195,7 +195,7 @@ class NodeSet {
for (int32_t elem, _cursor = 0; (eset).Next(&_cursor, &elem); )
bool Next(int32_t* cursor, int32_t* elem) {
while (static_cast<uint32_t>(*cursor) < table_.size()) {
- int32_t v = table_[*cursor];
+ int32_t v = table_[static_cast<uint32_t>(*cursor)];
(*cursor)++;
if (v >= 0) {
*elem = v;
@@ -210,24 +210,26 @@ class NodeSet {
Vec<int32_t> table_;
uint32_t occupied_; // Count of non-empty slots (includes deleted slots)
- static uint32_t Hash(uint32_t a) { return a * 41; }
+ static uint32_t Hash(int32_t a) { return static_cast<uint32_t>(a * 41); }
// Return index for storing v. May return an empty index or deleted index
- int FindIndex(int32_t v) const {
+ uint32_t FindIndex(int32_t v) const {
// Search starting at hash index.
const uint32_t mask = table_.size() - 1;
uint32_t i = Hash(v) & mask;
- int deleted_index = -1; // If >= 0, index of first deleted element we see
+ uint32_t deleted_index = 0; // index of first deleted element we see
+ bool seen_deleted_element = false;
while (true) {
int32_t e = table_[i];
if (v == e) {
return i;
} else if (e == kEmpty) {
// Return any previously encountered deleted slot.
- return (deleted_index >= 0) ? deleted_index : i;
- } else if (e == kDel && deleted_index < 0) {
+ return seen_deleted_element ? deleted_index : i;
+ } else if (e == kDel && !seen_deleted_element) {
// Keep searching since v might be present later.
deleted_index = i;
+ seen_deleted_element = true;
}
i = (i + 1) & mask; // Linear probing; quadratic is slightly slower.
}
@@ -268,7 +270,7 @@ inline GraphId MakeId(int32_t index, uint32_t version) {
}
inline int32_t NodeIndex(GraphId id) {
- return static_cast<uint32_t>(id.handle & 0xfffffffful);
+ return static_cast<int32_t>(id.handle);
}
inline uint32_t NodeVersion(GraphId id) {
@@ -298,7 +300,7 @@ class PointerMap {
int32_t Find(void* ptr) {
auto masked = base_internal::HidePtr(ptr);
for (int32_t i = table_[Hash(ptr)]; i != -1;) {
- Node* n = (*nodes_)[i];
+ Node* n = (*nodes_)[static_cast<uint32_t>(i)];
if (n->masked_ptr == masked) return i;
i = n->next_hash;
}
@@ -307,7 +309,7 @@ class PointerMap {
void Add(void* ptr, int32_t i) {
int32_t* head = &table_[Hash(ptr)];
- (*nodes_)[i]->next_hash = *head;
+ (*nodes_)[static_cast<uint32_t>(i)]->next_hash = *head;
*head = i;
}
@@ -317,7 +319,7 @@ class PointerMap {
auto masked = base_internal::HidePtr(ptr);
for (int32_t* slot = &table_[Hash(ptr)]; *slot != -1; ) {
int32_t index = *slot;
- Node* n = (*nodes_)[index];
+ Node* n = (*nodes_)[static_cast<uint32_t>(index)];
if (n->masked_ptr == masked) {
*slot = n->next_hash; // Remove n from linked list
n->next_hash = -1;
@@ -358,7 +360,7 @@ struct GraphCycles::Rep {
};
static Node* FindNode(GraphCycles::Rep* rep, GraphId id) {
- Node* n = rep->nodes_[NodeIndex(id)];
+ Node* n = rep->nodes_[static_cast<uint32_t>(NodeIndex(id))];
return (n->version == NodeVersion(id)) ? n : nullptr;
}
@@ -393,7 +395,7 @@ bool GraphCycles::CheckInvariants() const {
ABSL_RAW_LOG(FATAL, "Duplicate occurrence of rank %d", nx->rank);
}
HASH_FOR_EACH(y, nx->out) {
- Node* ny = r->nodes_[y];
+ Node* ny = r->nodes_[static_cast<uint32_t>(y)];
if (nx->rank >= ny->rank) {
ABSL_RAW_LOG(FATAL, "Edge %u->%d has bad rank assignment %d->%d", x, y,
nx->rank, ny->rank);
@@ -406,14 +408,14 @@ bool GraphCycles::CheckInvariants() const {
GraphId GraphCycles::GetId(void* ptr) {
int32_t i = rep_->ptrmap_.Find(ptr);
if (i != -1) {
- return MakeId(i, rep_->nodes_[i]->version);
+ return MakeId(i, rep_->nodes_[static_cast<uint32_t>(i)]->version);
} else if (rep_->free_nodes_.empty()) {
Node* n =
new (base_internal::LowLevelAlloc::AllocWithArena(sizeof(Node), arena))
Node;
n->version = 1; // Avoid 0 since it is used by InvalidGraphId()
n->visited = false;
- n->rank = rep_->nodes_.size();
+ n->rank = static_cast<int32_t>(rep_->nodes_.size());
n->masked_ptr = base_internal::HidePtr(ptr);
n->nstack = 0;
n->priority = 0;
@@ -425,7 +427,7 @@ GraphId GraphCycles::GetId(void* ptr) {
// a permutation of [0,rep_->nodes_.size()-1].
int32_t r = rep_->free_nodes_.back();
rep_->free_nodes_.pop_back();
- Node* n = rep_->nodes_[r];
+ Node* n = rep_->nodes_[static_cast<uint32_t>(r)];
n->masked_ptr = base_internal::HidePtr(ptr);
n->nstack = 0;
n->priority = 0;
@@ -439,12 +441,12 @@ void GraphCycles::RemoveNode(void* ptr) {
if (i == -1) {
return;
}
- Node* x = rep_->nodes_[i];
+ Node* x = rep_->nodes_[static_cast<uint32_t>(i)];
HASH_FOR_EACH(y, x->out) {
- rep_->nodes_[y]->in.erase(i);
+ rep_->nodes_[static_cast<uint32_t>(y)]->in.erase(i);
}
HASH_FOR_EACH(y, x->in) {
- rep_->nodes_[y]->out.erase(i);
+ rep_->nodes_[static_cast<uint32_t>(y)]->out.erase(i);
}
x->in.clear();
x->out.clear();
@@ -520,7 +522,7 @@ bool GraphCycles::InsertEdge(GraphId idx, GraphId idy) {
// Since we do not call Reorder() on this path, clear any visited
// markers left by ForwardDFS.
for (const auto& d : r->deltaf_) {
- r->nodes_[d]->visited = false;
+ r->nodes_[static_cast<uint32_t>(d)]->visited = false;
}
return false;
}
@@ -538,14 +540,14 @@ static bool ForwardDFS(GraphCycles::Rep* r, int32_t n, int32_t upper_bound) {
while (!r->stack_.empty()) {
n = r->stack_.back();
r->stack_.pop_back();
- Node* nn = r->nodes_[n];
+ Node* nn = r->nodes_[static_cast<uint32_t>(n)];
if (nn->visited) continue;
nn->visited = true;
r->deltaf_.push_back(n);
HASH_FOR_EACH(w, nn->out) {
- Node* nw = r->nodes_[w];
+ Node* nw = r->nodes_[static_cast<uint32_t>(w)];
if (nw->rank == upper_bound) {
return false; // Cycle
}
@@ -564,14 +566,14 @@ static void BackwardDFS(GraphCycles::Rep* r, int32_t n, int32_t lower_bound) {
while (!r->stack_.empty()) {
n = r->stack_.back();
r->stack_.pop_back();
- Node* nn = r->nodes_[n];
+ Node* nn = r->nodes_[static_cast<uint32_t>(n)];
if (nn->visited) continue;
nn->visited = true;
r->deltab_.push_back(n);
HASH_FOR_EACH(w, nn->in) {
- Node* nw = r->nodes_[w];
+ Node* nw = r->nodes_[static_cast<uint32_t>(w)];
if (!nw->visited && lower_bound < nw->rank) {
r->stack_.push_back(w);
}
@@ -596,7 +598,7 @@ static void Reorder(GraphCycles::Rep* r) {
// Assign the ranks in order to the collected list.
for (uint32_t i = 0; i < r->list_.size(); i++) {
- r->nodes_[r->list_[i]]->rank = r->merged_[i];
+ r->nodes_[static_cast<uint32_t>(r->list_[i])]->rank = r->merged_[i];
}
}
@@ -604,7 +606,8 @@ static void Sort(const Vec<Node*>& nodes, Vec<int32_t>* delta) {
struct ByRank {
const Vec<Node*>* nodes;
bool operator()(int32_t a, int32_t b) const {
- return (*nodes)[a]->rank < (*nodes)[b]->rank;
+ return (*nodes)[static_cast<uint32_t>(a)]->rank <
+ (*nodes)[static_cast<uint32_t>(b)]->rank;
}
};
ByRank cmp;
@@ -616,8 +619,10 @@ static void MoveToList(
GraphCycles::Rep* r, Vec<int32_t>* src, Vec<int32_t>* dst) {
for (auto& v : *src) {
int32_t w = v;
- v = r->nodes_[w]->rank; // Replace v entry with its rank
- r->nodes_[w]->visited = false; // Prepare for future DFS calls
+ // Replace v entry with its rank
+ v = r->nodes_[static_cast<uint32_t>(w)]->rank;
+ // Prepare for future DFS calls
+ r->nodes_[static_cast<uint32_t>(w)]->visited = false;
dst->push_back(w);
}
}
@@ -647,7 +652,8 @@ int GraphCycles::FindPath(GraphId idx, GraphId idy, int max_path_len,
}
if (path_len < max_path_len) {
- path[path_len] = MakeId(n, rep_->nodes_[n]->version);
+ path[path_len] =
+ MakeId(n, rep_->nodes_[static_cast<uint32_t>(n)]->version);
}
path_len++;
r->stack_.push_back(-1); // Will remove tentative path entry
@@ -656,7 +662,7 @@ int GraphCycles::FindPath(GraphId idx, GraphId idy, int max_path_len,
return path_len;
}
- HASH_FOR_EACH(w, r->nodes_[n]->out) {
+ HASH_FOR_EACH(w, r->nodes_[static_cast<uint32_t>(n)]->out) {
if (seen.insert(w)) {
r->stack_.push_back(w);
}
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/kernel_timeout.h b/contrib/restricted/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
index bbd4d2d70f..f5c2c0ef40 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
@@ -19,8 +19,8 @@
// Constructible from a absl::Time (for a timeout to be respected) or {}
// (for "no timeout".)
// This is a private low-level API for use by a handful of low-level
-// components that are friends of this class. Higher-level components
-// should build APIs based on absl::Time and absl::Duration.
+// components. Higher-level components should build APIs based on
+// absl::Time and absl::Duration.
#ifndef ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
@@ -28,6 +28,7 @@
#include <time.h>
#include <algorithm>
+#include <cstdint>
#include <limits>
#include "absl/base/internal/raw_logging.h"
@@ -38,7 +39,6 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
-class Futex;
class Waiter;
class KernelTimeout {
@@ -60,7 +60,10 @@ class KernelTimeout {
// Convert to parameter for sem_timedwait/futex/similar. Only for approved
// users. Do not call if !has_timeout.
- struct timespec MakeAbsTimespec();
+ struct timespec MakeAbsTimespec() const;
+
+ // Convert to unix epoch nanos. Do not call if !has_timeout.
+ int64_t MakeAbsNanos() const;
private:
// internal rep, not user visible: ns after unix epoch.
@@ -111,7 +114,8 @@ class KernelTimeout {
constexpr uint64_t max_nanos =
(std::numeric_limits<int64_t>::max)() - 999999u;
uint64_t ms_from_now =
- (std::min<uint64_t>(max_nanos, ns_ - now) + 999999u) / 1000000u;
+ ((std::min)(max_nanos, static_cast<uint64_t>(ns_ - now)) + 999999u) /
+ 1000000u;
if (ms_from_now > kInfinite) {
return kInfinite;
}
@@ -119,13 +123,12 @@ class KernelTimeout {
}
return 0;
}
-#endif
- friend class Futex;
friend class Waiter;
+#endif
};
-inline struct timespec KernelTimeout::MakeAbsTimespec() {
+inline struct timespec KernelTimeout::MakeAbsTimespec() const {
int64_t n = ns_;
static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
if (n == 0) {
@@ -149,6 +152,17 @@ inline struct timespec KernelTimeout::MakeAbsTimespec() {
return abstime;
}
+inline int64_t KernelTimeout::MakeAbsNanos() const {
+ if (ns_ == 0) {
+ ABSL_RAW_LOG(
+ ERROR, "Tried to create a timeout from a non-timeout; never do this.");
+ // But we'll try to continue sanely. no-timeout ~= saturated timeout.
+ return (std::numeric_limits<int64_t>::max)();
+ }
+
+ return ns_;
+}
+
} // namespace synchronization_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc
index 52e2455d7d..064ccb744a 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.cc
@@ -36,6 +36,9 @@
#include <algorithm>
#include <atomic>
#include <cinttypes>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
#include <thread> // NOLINT(build/c++11)
#include "absl/base/attributes.h"
@@ -51,6 +54,7 @@
#include "absl/base/internal/sysinfo.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/base/internal/tsan_mutex_interface.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
@@ -134,25 +138,42 @@ enum DelayMode { AGGRESSIVE, GENTLE };
struct ABSL_CACHELINE_ALIGNED MutexGlobals {
absl::once_flag once;
int spinloop_iterations = 0;
- int32_t mutex_sleep_limit[2] = {};
+ int32_t mutex_sleep_spins[2] = {};
+ absl::Duration mutex_sleep_time;
};
+absl::Duration MeasureTimeToYield() {
+ absl::Time before = absl::Now();
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
+ return absl::Now() - before;
+}
+
const MutexGlobals &GetMutexGlobals() {
ABSL_CONST_INIT static MutexGlobals data;
absl::base_internal::LowLevelCallOnce(&data.once, [&]() {
const int num_cpus = absl::base_internal::NumCPUs();
data.spinloop_iterations = num_cpus > 1 ? 1500 : 0;
- // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
+ // If this a uniprocessor, only yield/sleep.
+ // Real-time threads are often unable to yield, so the sleep time needs
+ // to be long enough to keep the calling thread asleep until scheduling
+ // happens.
+ // If this is multiprocessor, allow spinning. If the mode is
// aggressive then spin many times before yielding. If the mode is
// gentle then spin only a few times before yielding. Aggressive spinning
// is used to ensure that an Unlock() call, which must get the spin lock
// for any thread to make progress gets it without undue delay.
if (num_cpus > 1) {
- data.mutex_sleep_limit[AGGRESSIVE] = 5000;
- data.mutex_sleep_limit[GENTLE] = 250;
+ data.mutex_sleep_spins[AGGRESSIVE] = 5000;
+ data.mutex_sleep_spins[GENTLE] = 250;
+ data.mutex_sleep_time = absl::Microseconds(10);
} else {
- data.mutex_sleep_limit[AGGRESSIVE] = 0;
- data.mutex_sleep_limit[GENTLE] = 0;
+ data.mutex_sleep_spins[AGGRESSIVE] = 0;
+ data.mutex_sleep_spins[GENTLE] = 0;
+ data.mutex_sleep_time = MeasureTimeToYield() * 5;
+ data.mutex_sleep_time =
+ std::min(data.mutex_sleep_time, absl::Milliseconds(1));
+ data.mutex_sleep_time =
+ std::max(data.mutex_sleep_time, absl::Microseconds(10));
}
});
return data;
@@ -163,7 +184,8 @@ namespace synchronization_internal {
// Returns the Mutex delay on iteration `c` depending on the given `mode`.
// The returned value should be used as `c` for the next call to `MutexDelay`.
int MutexDelay(int32_t c, int mode) {
- const int32_t limit = GetMutexGlobals().mutex_sleep_limit[mode];
+ const int32_t limit = GetMutexGlobals().mutex_sleep_spins[mode];
+ const absl::Duration sleep_time = GetMutexGlobals().mutex_sleep_time;
if (c < limit) {
// Spin.
c++;
@@ -176,7 +198,7 @@ int MutexDelay(int32_t c, int mode) {
c++;
} else {
// Then wait.
- absl::SleepFor(absl::Microseconds(10));
+ absl::SleepFor(sleep_time);
c = 0;
}
ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
@@ -325,7 +347,7 @@ static struct SynchEvent { // this is a trivial hash table for the events
static SynchEvent *EnsureSynchEvent(std::atomic<intptr_t> *addr,
const char *name, intptr_t bits,
intptr_t lockbit) {
- uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
+ uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;
SynchEvent *e;
// first look for existing SynchEvent struct..
synch_event_mu.Lock();
@@ -378,7 +400,7 @@ static void UnrefSynchEvent(SynchEvent *e) {
// is clear before doing so).
static void ForgetSynchEvent(std::atomic<intptr_t> *addr, intptr_t bits,
intptr_t lockbit) {
- uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
+ uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;
SynchEvent **pe;
SynchEvent *e;
synch_event_mu.Lock();
@@ -402,7 +424,7 @@ static void ForgetSynchEvent(std::atomic<intptr_t> *addr, intptr_t bits,
// "addr", if any. The pointer returned is valid until the UnrefSynchEvent() is
// called.
static SynchEvent *GetSynchEvent(const void *addr) {
- uint32_t h = reinterpret_cast<intptr_t>(addr) % kNSynchEvent;
+ uint32_t h = reinterpret_cast<uintptr_t>(addr) % kNSynchEvent;
SynchEvent *e;
synch_event_mu.Lock();
for (e = synch_event[h];
@@ -430,7 +452,13 @@ static void PostSynchEvent(void *obj, int ev) {
char buffer[ABSL_ARRAYSIZE(pcs) * 24];
int pos = snprintf(buffer, sizeof (buffer), " @");
for (int i = 0; i != n; i++) {
- pos += snprintf(&buffer[pos], sizeof (buffer) - pos, " %p", pcs[i]);
+ int b = snprintf(&buffer[pos], sizeof(buffer) - static_cast<size_t>(pos),
+ " %p", pcs[i]);
+ if (b < 0 ||
+ static_cast<size_t>(b) >= sizeof(buffer) - static_cast<size_t>(pos)) {
+ break;
+ }
+ pos += b;
}
ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
(e == nullptr ? "" : e->name), buffer);
@@ -486,7 +514,8 @@ struct SynchWaitParams {
cvmu(cvmu_arg),
thread(thread_arg),
cv_word(cv_word_arg),
- contention_start_cycles(base_internal::CycleClock::Now()) {}
+ contention_start_cycles(base_internal::CycleClock::Now()),
+ should_submit_contention_data(false) {}
const Mutex::MuHow how; // How this thread needs to wait.
const Condition *cond; // The condition that this thread is waiting for.
@@ -504,6 +533,7 @@ struct SynchWaitParams {
int64_t contention_start_cycles; // Time (in cycles) when this thread started
// to contend for the mutex.
+ bool should_submit_contention_data;
};
struct SynchLocksHeld {
@@ -562,10 +592,15 @@ static SynchLocksHeld *Synch_GetAllLocks() {
void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
if (mu) {
ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
- }
- PerThreadSem::Post(w->thread_identity());
- if (mu) {
+ // We miss synchronization around passing PerThreadSynch between threads
+ // since it happens inside of the Mutex code, so we need to ignore all
+ // accesses to the object.
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ PerThreadSem::Post(w->thread_identity());
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
+ } else {
+ PerThreadSem::Post(w->thread_identity());
}
}
@@ -1120,7 +1155,7 @@ void Mutex::TryRemove(PerThreadSynch *s) {
// if the wait extends past the absolute time specified, even if "s" is still
// on the mutex queue. In this case, remove "s" from the queue and return
// true, otherwise return false.
-ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
+void Mutex::Block(PerThreadSynch *s) {
while (s->state.load(std::memory_order_acquire) == PerThreadSynch::kQueued) {
if (!DecrementSynchSem(this, s, s->waitp->timeout)) {
// After a timeout, we go into a spin loop until we remove ourselves
@@ -1273,15 +1308,17 @@ static char *StackString(void **pcs, int n, char *buf, int maxlen,
char sym[kSymLen];
int len = 0;
for (int i = 0; i != n; i++) {
+ if (len >= maxlen)
+ return buf;
+ size_t count = static_cast<size_t>(maxlen - len);
if (symbolize) {
if (!symbolizer(pcs[i], sym, kSymLen)) {
sym[0] = '\0';
}
- snprintf(buf + len, maxlen - len, "%s\t@ %p %s\n",
- (i == 0 ? "\n" : ""),
- pcs[i], sym);
+ snprintf(buf + len, count, "%s\t@ %p %s\n", (i == 0 ? "\n" : ""), pcs[i],
+ sym);
} else {
- snprintf(buf + len, maxlen - len, " %p", pcs[i]);
+ snprintf(buf + len, count, " %p", pcs[i]);
}
len += strlen(&buf[len]);
}
@@ -1366,12 +1403,12 @@ static GraphId DeadlockCheck(Mutex *mu) {
bool symbolize = number_of_reported_deadlocks <= 2;
ABSL_RAW_LOG(ERROR, "Potential Mutex deadlock: %s",
CurrentStackString(b->buf, sizeof (b->buf), symbolize));
- int len = 0;
+ size_t len = 0;
for (int j = 0; j != all_locks->n; j++) {
void* pr = deadlock_graph->Ptr(all_locks->locks[j].id);
if (pr != nullptr) {
snprintf(b->buf + len, sizeof (b->buf) - len, " %p", pr);
- len += static_cast<int>(strlen(&b->buf[len]));
+ len += strlen(&b->buf[len]);
}
}
ABSL_RAW_LOG(ERROR,
@@ -1467,7 +1504,7 @@ static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {
return false;
}
-ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
+void Mutex::Lock() {
ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
GraphId id = DebugOnlyDeadlockCheck(this);
intptr_t v = mu_.load(std::memory_order_relaxed);
@@ -1485,7 +1522,7 @@ ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
ABSL_TSAN_MUTEX_POST_LOCK(this, 0, 0);
}
-ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderLock() {
+void Mutex::ReaderLock() {
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_read_lock);
GraphId id = DebugOnlyDeadlockCheck(this);
intptr_t v = mu_.load(std::memory_order_relaxed);
@@ -1598,7 +1635,7 @@ bool Mutex::AwaitCommon(const Condition &cond, KernelTimeout t) {
return res;
}
-ABSL_XRAY_LOG_ARGS(1) bool Mutex::TryLock() {
+bool Mutex::TryLock() {
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
intptr_t v = mu_.load(std::memory_order_relaxed);
if ((v & (kMuWriter | kMuReader | kMuEvent)) == 0 && // try fast acquire
@@ -1627,7 +1664,7 @@ ABSL_XRAY_LOG_ARGS(1) bool Mutex::TryLock() {
return false;
}
-ABSL_XRAY_LOG_ARGS(1) bool Mutex::ReaderTryLock() {
+bool Mutex::ReaderTryLock() {
ABSL_TSAN_MUTEX_PRE_LOCK(this,
__tsan_mutex_read_lock | __tsan_mutex_try_lock);
intptr_t v = mu_.load(std::memory_order_relaxed);
@@ -1673,7 +1710,7 @@ ABSL_XRAY_LOG_ARGS(1) bool Mutex::ReaderTryLock() {
return false;
}
-ABSL_XRAY_LOG_ARGS(1) void Mutex::Unlock() {
+void Mutex::Unlock() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
DebugOnlyLockLeave(this);
intptr_t v = mu_.load(std::memory_order_relaxed);
@@ -1725,7 +1762,7 @@ static bool ExactlyOneReader(intptr_t v) {
return (v & kMuMultipleWaitersMask) == 0;
}
-ABSL_XRAY_LOG_ARGS(1) void Mutex::ReaderUnlock() {
+void Mutex::ReaderUnlock() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, __tsan_mutex_read_lock);
DebugOnlyLockLeave(this);
intptr_t v = mu_.load(std::memory_order_relaxed);
@@ -1755,7 +1792,7 @@ static intptr_t ClearDesignatedWakerMask(int flag) {
case 1: // blocked; turn off the designated waker bit
return ~static_cast<intptr_t>(kMuDesig);
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
}
// Conditionally ignores the existence of waiting writers if a reader that has
@@ -1769,7 +1806,7 @@ static intptr_t IgnoreWaitingWritersMask(int flag) {
case 1: // blocked; pretend there are no waiting writers
return ~static_cast<intptr_t>(kMuWrWait);
}
- ABSL_INTERNAL_UNREACHABLE;
+ ABSL_UNREACHABLE();
}
// Internal version of LockWhen(). See LockSlowWithDeadline()
@@ -1790,8 +1827,8 @@ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
// operation tsan considers that we've already released the mutex.
bool res = false;
#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
- const int flags = read_lock ? __tsan_mutex_read_lock : 0;
- const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
+ const uint32_t flags = read_lock ? __tsan_mutex_read_lock : 0;
+ const uint32_t tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
#endif
if (locking) {
// For lock we pretend that we have finished the operation,
@@ -1904,7 +1941,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) {
// Test for either of two situations that should not occur in v:
// kMuWriter and kMuReader
// kMuWrWait and !kMuWait
- const uintptr_t w = v ^ kMuWait;
+ const uintptr_t w = static_cast<uintptr_t>(v ^ kMuWait);
// By flipping that bit, we can now test for:
// kMuWriter and kMuReader in w
// kMuWrWait and kMuWait in w
@@ -2331,21 +2368,26 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
} // end of for(;;)-loop
if (wake_list != kPerThreadSynchNull) {
- int64_t wait_cycles = 0;
+ int64_t total_wait_cycles = 0;
+ int64_t max_wait_cycles = 0;
int64_t now = base_internal::CycleClock::Now();
do {
- // Sample lock contention events only if the waiter was trying to acquire
+ // Profile lock contention events only if the waiter was trying to acquire
// the lock, not waiting on a condition variable or Condition.
if (!wake_list->cond_waiter) {
- wait_cycles += (now - wake_list->waitp->contention_start_cycles);
+ int64_t cycles_waited =
+ (now - wake_list->waitp->contention_start_cycles);
+ total_wait_cycles += cycles_waited;
+ if (max_wait_cycles == 0) max_wait_cycles = cycles_waited;
wake_list->waitp->contention_start_cycles = now;
+ wake_list->waitp->should_submit_contention_data = true;
}
wake_list = Wakeup(wake_list); // wake waiters
} while (wake_list != kPerThreadSynchNull);
- if (wait_cycles > 0) {
- mutex_tracer("slow release", this, wait_cycles);
+ if (total_wait_cycles > 0) {
+ mutex_tracer("slow release", this, total_wait_cycles);
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
- submit_profile_data(wait_cycles);
+ submit_profile_data(total_wait_cycles);
ABSL_TSAN_MUTEX_POST_DIVERT(this, 0);
}
}
@@ -2746,25 +2788,31 @@ static bool Dereference(void *arg) {
return *(static_cast<bool *>(arg));
}
-Condition::Condition() {} // null constructor, used for kTrue only
-const Condition Condition::kTrue;
+ABSL_CONST_INIT const Condition Condition::kTrue;
Condition::Condition(bool (*func)(void *), void *arg)
: eval_(&CallVoidPtrFunction),
- function_(func),
- method_(nullptr),
- arg_(arg) {}
+ arg_(arg) {
+ static_assert(sizeof(&func) <= sizeof(callback_),
+ "An overlarge function pointer passed to Condition.");
+ StoreCallback(func);
+}
bool Condition::CallVoidPtrFunction(const Condition *c) {
- return (*c->function_)(c->arg_);
+ using FunctionPointer = bool (*)(void *);
+ FunctionPointer function_pointer;
+ std::memcpy(&function_pointer, c->callback_, sizeof(function_pointer));
+ return (*function_pointer)(c->arg_);
}
Condition::Condition(const bool *cond)
: eval_(CallVoidPtrFunction),
- function_(Dereference),
- method_(nullptr),
// const_cast is safe since Dereference does not modify arg
- arg_(const_cast<bool *>(cond)) {}
+ arg_(const_cast<bool *>(cond)) {
+ using FunctionPointer = bool (*)(void *);
+ const FunctionPointer dereference = Dereference;
+ StoreCallback(dereference);
+}
bool Condition::Eval() const {
// eval_ == null for kTrue
@@ -2772,14 +2820,15 @@ bool Condition::Eval() const {
}
bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) {
- if (a == nullptr) {
+ // kTrue logic.
+ if (a == nullptr || a->eval_ == nullptr) {
return b == nullptr || b->eval_ == nullptr;
+ } else if (b == nullptr || b->eval_ == nullptr) {
+ return false;
}
- if (b == nullptr || b->eval_ == nullptr) {
- return a->eval_ == nullptr;
- }
- return a->eval_ == b->eval_ && a->function_ == b->function_ &&
- a->arg_ == b->arg_ && a->method_ == b->method_;
+ // Check equality of the representative fields.
+ return a->eval_ == b->eval_ && a->arg_ == b->arg_ &&
+ !memcmp(a->callback_, b->callback_, sizeof(a->callback_));
}
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h
index b69b7089e3..f793cc0e42 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/mutex.h
@@ -60,6 +60,8 @@
#include <atomic>
#include <cstdint>
+#include <cstring>
+#include <iterator>
#include <string>
#include "absl/base/const_init.h"
@@ -612,12 +614,12 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock {
// Condition
// -----------------------------------------------------------------------------
//
-// As noted above, `Mutex` contains a number of member functions which take a
-// `Condition` as an argument; clients can wait for conditions to become `true`
-// before attempting to acquire the mutex. These sections are known as
-// "condition critical" sections. To use a `Condition`, you simply need to
-// construct it, and use within an appropriate `Mutex` member function;
-// everything else in the `Condition` class is an implementation detail.
+// `Mutex` contains a number of member functions which take a `Condition` as an
+// argument; clients can wait for conditions to become `true` before attempting
+// to acquire the mutex. These sections are known as "condition critical"
+// sections. To use a `Condition`, you simply need to construct it, and use
+// within an appropriate `Mutex` member function; everything else in the
+// `Condition` class is an implementation detail.
//
// A `Condition` is specified as a function pointer which returns a boolean.
// `Condition` functions should be pure functions -- their results should depend
@@ -727,7 +729,7 @@ class Condition {
: Condition(obj, static_cast<bool (T::*)() const>(&T::operator())) {}
// A Condition that always returns `true`.
- static const Condition kTrue;
+ ABSL_CONST_INIT static const Condition kTrue;
// Evaluates the condition.
bool Eval() const;
@@ -742,22 +744,54 @@ class Condition {
static bool GuaranteedEqual(const Condition *a, const Condition *b);
private:
- typedef bool (*InternalFunctionType)(void * arg);
- typedef bool (Condition::*InternalMethodType)();
- typedef bool (*InternalMethodCallerType)(void * arg,
- InternalMethodType internal_method);
-
- bool (*eval_)(const Condition*); // Actual evaluator
- InternalFunctionType function_; // function taking pointer returning bool
- InternalMethodType method_; // method returning bool
- void *arg_; // arg of function_ or object of method_
-
- Condition(); // null constructor used only to create kTrue
+ // Sizing an allocation for a method pointer can be subtle. In the Itanium
+ // specifications, a method pointer has a predictable, uniform size. On the
+ // other hand, MSVC ABI, method pointer sizes vary based on the
+ // inheritance of the class. Specifically, method pointers from classes with
+ // multiple inheritance are bigger than those of classes with single
+ // inheritance. Other variations also exist.
+
+#ifndef _MSC_VER
+ // Allocation for a function pointer or method pointer.
+ // The {0} initializer ensures that all unused bytes of this buffer are
+ // always zeroed out. This is necessary, because GuaranteedEqual() compares
+ // all of the bytes, unaware of which bytes are relevant to a given `eval_`.
+ using MethodPtr = bool (Condition::*)();
+ char callback_[sizeof(MethodPtr)] = {0};
+#else
+ // It is well known that the larget MSVC pointer-to-member is 24 bytes. This
+ // may be the largest known pointer-to-member of any platform. For this
+ // reason we will allocate 24 bytes for MSVC platform toolchains.
+ char callback_[24] = {0};
+#endif
+
+ // Function with which to evaluate callbacks and/or arguments.
+ bool (*eval_)(const Condition*) = nullptr;
+
+ // Either an argument for a function call or an object for a method call.
+ void *arg_ = nullptr;
// Various functions eval_ can point to:
static bool CallVoidPtrFunction(const Condition*);
template <typename T> static bool CastAndCallFunction(const Condition* c);
template <typename T> static bool CastAndCallMethod(const Condition* c);
+
+ // Helper methods for storing, validating, and reading callback arguments.
+ template <typename T>
+ inline void StoreCallback(T callback) {
+ static_assert(
+ sizeof(callback) <= sizeof(callback_),
+ "An overlarge pointer was passed as a callback to Condition.");
+ std::memcpy(callback_, &callback, sizeof(callback));
+ }
+
+ template <typename T>
+ inline void ReadCallback(T *callback) const {
+ std::memcpy(callback, callback_, sizeof(*callback));
+ }
+
+ // Used only to create kTrue.
+ constexpr Condition() = default;
};
// -----------------------------------------------------------------------------
@@ -949,56 +983,61 @@ inline CondVar::CondVar() : cv_(0) {}
// static
template <typename T>
bool Condition::CastAndCallMethod(const Condition *c) {
- typedef bool (T::*MemberType)();
- MemberType rm = reinterpret_cast<MemberType>(c->method_);
- T *x = static_cast<T *>(c->arg_);
- return (x->*rm)();
+ T *object = static_cast<T *>(c->arg_);
+ bool (T::*method_pointer)();
+ c->ReadCallback(&method_pointer);
+ return (object->*method_pointer)();
}
// static
template <typename T>
bool Condition::CastAndCallFunction(const Condition *c) {
- typedef bool (*FuncType)(T *);
- FuncType fn = reinterpret_cast<FuncType>(c->function_);
- T *x = static_cast<T *>(c->arg_);
- return (*fn)(x);
+ bool (*function)(T *);
+ c->ReadCallback(&function);
+ T *argument = static_cast<T *>(c->arg_);
+ return (*function)(argument);
}
template <typename T>
inline Condition::Condition(bool (*func)(T *), T *arg)
: eval_(&CastAndCallFunction<T>),
- function_(reinterpret_cast<InternalFunctionType>(func)),
- method_(nullptr),
- arg_(const_cast<void *>(static_cast<const void *>(arg))) {}
+ arg_(const_cast<void *>(static_cast<const void *>(arg))) {
+ static_assert(sizeof(&func) <= sizeof(callback_),
+ "An overlarge function pointer was passed to Condition.");
+ StoreCallback(func);
+}
template <typename T>
inline Condition::Condition(T *object,
bool (absl::internal::identity<T>::type::*method)())
: eval_(&CastAndCallMethod<T>),
- function_(nullptr),
- method_(reinterpret_cast<InternalMethodType>(method)),
- arg_(object) {}
+ arg_(object) {
+ static_assert(sizeof(&method) <= sizeof(callback_),
+ "An overlarge method pointer was passed to Condition.");
+ StoreCallback(method);
+}
template <typename T>
inline Condition::Condition(const T *object,
bool (absl::internal::identity<T>::type::*method)()
const)
: eval_(&CastAndCallMethod<T>),
- function_(nullptr),
- method_(reinterpret_cast<InternalMethodType>(method)),
- arg_(reinterpret_cast<void *>(const_cast<T *>(object))) {}
+ arg_(reinterpret_cast<void *>(const_cast<T *>(object))) {
+ StoreCallback(method);
+}
-// Register a hook for profiling support.
+// Register hooks for profiling support.
//
// The function pointer registered here will be called whenever a mutex is
// contended. The callback is given the cycles for which waiting happened (as
// measured by //absl/base/internal/cycleclock.h, and which may not
// be real "cycle" counts.)
//
-// Calls to this function do not race or block, but there is no ordering
-// guaranteed between calls to this function and call to the provided hook.
-// In particular, the previously registered hook may still be called for some
-// time after this function returns.
+// There is no ordering guarantee between when the hook is registered and when
+// callbacks will begin. Only a single profiler can be installed in a running
+// binary; if this function is called a second time with a different function
+// pointer, the value is ignored (and will cause an assertion failure in debug
+// mode.)
void RegisterMutexProfiler(void (*fn)(int64_t wait_cycles));
// Register a hook for Mutex tracing.
@@ -1011,13 +1050,11 @@ void RegisterMutexProfiler(void (*fn)(int64_t wait_cycles));
//
// The only event name currently sent is "slow release".
//
-// This has the same memory ordering concerns as RegisterMutexProfiler() above.
+// This has the same ordering and single-use limitations as
+// RegisterMutexProfiler() above.
void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
int64_t wait_cycles));
-// TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
-// into a single interface, since they are only ever called in pairs.
-
// Register a hook for CondVar tracing.
//
// The function pointer registered here will be called here on various CondVar
@@ -1028,7 +1065,8 @@ void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
// Events that can be sent are "Wait", "Unwait", "Signal wakeup", and
// "SignalAll wakeup".
//
-// This has the same memory ordering concerns as RegisterMutexProfiler() above.
+// This has the same ordering and single-use limitations as
+// RegisterMutexProfiler() above.
void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv));
// Register a hook for symbolizing stack traces in deadlock detector reports.
@@ -1038,7 +1076,8 @@ void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv));
// false if symbolizing failed, or true if a NUL-terminated symbol was written
// to 'out.'
//
-// This has the same memory ordering concerns as RegisterMutexProfiler() above.
+// This has the same ordering and single-use limitations as
+// RegisterMutexProfiler() above.
//
// DEPRECATED: The default symbolizer function is absl::Symbolize() and the
// ability to register a different hook for symbolizing stack traces will be
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc b/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc
index e91b903822..165ba669fb 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/notification.cc
@@ -16,7 +16,6 @@
#include <atomic>
-#include "absl/base/attributes.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/notification.h b/contrib/restricted/abseil-cpp/absl/synchronization/notification.h
index 4bec2689b9..8986d9a408 100644
--- a/contrib/restricted/abseil-cpp/absl/synchronization/notification.h
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/notification.h
@@ -53,7 +53,6 @@
#include <atomic>
#include "absl/base/attributes.h"
-#include "absl/base/macros.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
diff --git a/contrib/restricted/abseil-cpp/absl/time/civil_time.cc b/contrib/restricted/abseil-cpp/absl/time/civil_time.cc
index 6a231edb2d..65df39d731 100644
--- a/contrib/restricted/abseil-cpp/absl/time/civil_time.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/civil_time.cc
@@ -15,6 +15,7 @@
#include "absl/time/civil_time.h"
#include <cstdlib>
+#include <ostream>
#include <string>
#include "absl/strings/str_cat.h"
@@ -167,6 +168,31 @@ std::ostream& operator<<(std::ostream& os, CivilSecond s) {
return os << FormatCivilTime(s);
}
+bool AbslParseFlag(string_view s, CivilSecond* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+bool AbslParseFlag(string_view s, CivilMinute* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+bool AbslParseFlag(string_view s, CivilHour* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+bool AbslParseFlag(string_view s, CivilDay* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+bool AbslParseFlag(string_view s, CivilMonth* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+bool AbslParseFlag(string_view s, CivilYear* c, std::string*) {
+ return ParseLenientCivilTime(s, c);
+}
+std::string AbslUnparseFlag(CivilSecond c) { return FormatCivilTime(c); }
+std::string AbslUnparseFlag(CivilMinute c) { return FormatCivilTime(c); }
+std::string AbslUnparseFlag(CivilHour c) { return FormatCivilTime(c); }
+std::string AbslUnparseFlag(CivilDay c) { return FormatCivilTime(c); }
+std::string AbslUnparseFlag(CivilMonth c) { return FormatCivilTime(c); }
+std::string AbslUnparseFlag(CivilYear c) { return FormatCivilTime(c); }
+
} // namespace time_internal
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/time/civil_time.h b/contrib/restricted/abseil-cpp/absl/time/civil_time.h
index bb46004434..5855bc73a1 100644
--- a/contrib/restricted/abseil-cpp/absl/time/civil_time.h
+++ b/contrib/restricted/abseil-cpp/absl/time/civil_time.h
@@ -70,8 +70,10 @@
#ifndef ABSL_TIME_CIVIL_TIME_H_
#define ABSL_TIME_CIVIL_TIME_H_
+#include <iosfwd>
#include <string>
+#include "absl/base/config.h"
#include "absl/strings/string_view.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
@@ -530,6 +532,29 @@ std::ostream& operator<<(std::ostream& os, CivilHour h);
std::ostream& operator<<(std::ostream& os, CivilMinute m);
std::ostream& operator<<(std::ostream& os, CivilSecond s);
+// AbslParseFlag()
+//
+// Parses the command-line flag string representation `s` into a civil-time
+// value. Flags must be specified in a format that is valid for
+// `absl::ParseLenientCivilTime()`.
+bool AbslParseFlag(absl::string_view s, CivilSecond* c, std::string* error);
+bool AbslParseFlag(absl::string_view s, CivilMinute* c, std::string* error);
+bool AbslParseFlag(absl::string_view s, CivilHour* c, std::string* error);
+bool AbslParseFlag(absl::string_view s, CivilDay* c, std::string* error);
+bool AbslParseFlag(absl::string_view s, CivilMonth* c, std::string* error);
+bool AbslParseFlag(absl::string_view s, CivilYear* c, std::string* error);
+
+// AbslUnparseFlag()
+//
+// Unparses a civil-time value into a command-line string representation using
+// the format specified by `absl::ParseCivilTime()`.
+std::string AbslUnparseFlag(CivilSecond c);
+std::string AbslUnparseFlag(CivilMinute c);
+std::string AbslUnparseFlag(CivilHour c);
+std::string AbslUnparseFlag(CivilDay c);
+std::string AbslUnparseFlag(CivilMonth c);
+std::string AbslUnparseFlag(CivilYear c);
+
} // namespace time_internal
ABSL_NAMESPACE_END
diff --git a/contrib/restricted/abseil-cpp/absl/time/clock.cc b/contrib/restricted/abseil-cpp/absl/time/clock.cc
index a091efdcb2..2bf53d9c61 100644
--- a/contrib/restricted/abseil-cpp/absl/time/clock.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/clock.cc
@@ -217,9 +217,11 @@ static int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock,
uint64_t elapsed_cycles;
int loops = 0;
do {
- before_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
+ before_cycles =
+ static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());
current_time_nanos_from_system = GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
- after_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
+ after_cycles =
+ static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());
// elapsed_cycles is unsigned, so is large on overflow
elapsed_cycles = after_cycles - before_cycles;
if (elapsed_cycles >= local_approx_syscall_time_in_cycles &&
@@ -316,7 +318,8 @@ int64_t GetCurrentTimeNanos() {
// contribute to register pressure - reading it early before initializing
// the other pieces of the calculation minimizes spill/restore instructions,
// minimizing icache cost.
- uint64_t now_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
+ uint64_t now_cycles =
+ static_cast<uint64_t>(GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW());
// Acquire pairs with the barrier in SeqRelease - if this load sees that
// store, the shared-data reads necessarily see that SeqRelease's updates
@@ -356,7 +359,8 @@ int64_t GetCurrentTimeNanos() {
uint64_t delta_cycles;
if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 &&
(delta_cycles = now_cycles - base_cycles) < min_cycles_per_sample) {
- return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale);
+ return static_cast<int64_t>(
+ base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale));
}
return GetCurrentTimeNanosSlowPath();
}
@@ -404,8 +408,8 @@ static int64_t GetCurrentTimeNanosSlowPath()
// Sample the kernel time base. This is the definition of
// "now" if we take the slow path.
uint64_t now_cycles;
- uint64_t now_ns =
- GetCurrentTimeNanosFromKernel(time_state.last_now_cycles, &now_cycles);
+ uint64_t now_ns = static_cast<uint64_t>(
+ GetCurrentTimeNanosFromKernel(time_state.last_now_cycles, &now_cycles));
time_state.last_now_cycles = now_cycles;
uint64_t estimated_base_ns;
@@ -432,7 +436,7 @@ static int64_t GetCurrentTimeNanosSlowPath()
time_state.lock.Unlock();
- return estimated_base_ns;
+ return static_cast<int64_t>(estimated_base_ns);
}
// Main part of the algorithm. Locks out readers, updates the approximation
@@ -489,7 +493,8 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
uint64_t assumed_next_sample_delta_cycles =
SafeDivideAndScale(kMinNSBetweenSamples, measured_nsscaled_per_cycle);
- int64_t diff_ns = now_ns - estimated_base_ns; // estimate low by this much
+ // Estimate low by this much.
+ int64_t diff_ns = static_cast<int64_t>(now_ns - estimated_base_ns);
// We want to set nsscaled_per_cycle so that our estimate of the ns time
// at the assumed cycle time is the assumed ns time.
@@ -500,7 +505,8 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
// of our current error, by solving:
// kMinNSBetweenSamples + diff_ns - (diff_ns / 16) ==
// (assumed_next_sample_delta_cycles * nsscaled_per_cycle) >> kScale
- ns = kMinNSBetweenSamples + diff_ns - (diff_ns / 16);
+ ns = static_cast<uint64_t>(static_cast<int64_t>(kMinNSBetweenSamples) +
+ diff_ns - (diff_ns / 16));
uint64_t new_nsscaled_per_cycle =
SafeDivideAndScale(ns, assumed_next_sample_delta_cycles);
if (new_nsscaled_per_cycle != 0 &&
@@ -558,7 +564,7 @@ constexpr absl::Duration MaxSleep() {
// REQUIRES: to_sleep <= MaxSleep().
void SleepOnce(absl::Duration to_sleep) {
#ifdef _WIN32
- Sleep(to_sleep / absl::Milliseconds(1));
+ Sleep(static_cast<DWORD>(to_sleep / absl::Milliseconds(1)));
#else
struct timespec sleep_time = absl::ToTimespec(to_sleep);
while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
diff --git a/contrib/restricted/abseil-cpp/absl/time/duration.cc b/contrib/restricted/abseil-cpp/absl/time/duration.cc
index 2bba62da0b..911e80f834 100644
--- a/contrib/restricted/abseil-cpp/absl/time/duration.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/duration.cc
@@ -617,7 +617,7 @@ timespec ToTimespec(Duration d) {
rep_lo -= kTicksPerSecond;
}
}
- ts.tv_sec = rep_hi;
+ ts.tv_sec = static_cast<decltype(ts.tv_sec)>(rep_hi);
if (ts.tv_sec == rep_hi) { // no time_t narrowing
ts.tv_nsec = rep_lo / kTicksPerNanosecond;
return ts;
@@ -645,7 +645,7 @@ timeval ToTimeval(Duration d) {
ts.tv_nsec -= 1000 * 1000 * 1000;
}
}
- tv.tv_sec = ts.tv_sec;
+ tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);
if (tv.tv_sec != ts.tv_sec) { // narrowing
if (ts.tv_sec < 0) {
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
@@ -691,7 +691,7 @@ namespace {
char* Format64(char* ep, int width, int64_t v) {
do {
--width;
- *--ep = '0' + (v % 10); // contiguous digits
+ *--ep = static_cast<char>('0' + (v % 10)); // contiguous digits
} while (v /= 10);
while (--width >= 0) *--ep = '0'; // zero pad
return ep;
@@ -728,7 +728,7 @@ void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
char* const ep = buf + sizeof(buf);
char* bp = Format64(ep, 0, n);
if (*bp != '0' || bp + 1 != ep) {
- out->append(bp, ep - bp);
+ out->append(bp, static_cast<size_t>(ep - bp));
out->append(unit.abbr.data(), unit.abbr.size());
}
}
@@ -745,12 +745,12 @@ void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
int64_t int_part = d;
if (int_part != 0 || frac_part != 0) {
char* bp = Format64(ep, 0, int_part); // always < 1000
- out->append(bp, ep - bp);
+ out->append(bp, static_cast<size_t>(ep - bp));
if (frac_part != 0) {
out->push_back('.');
bp = Format64(ep, prec, frac_part);
while (ep[-1] == '0') --ep;
- out->append(bp, ep - bp);
+ out->append(bp, static_cast<size_t>(ep - bp));
}
out->append(unit.abbr.data(), unit.abbr.size());
}
@@ -841,7 +841,7 @@ bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,
// in "*unit". The given string pointer is modified to point to the first
// unconsumed char.
bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {
- size_t size = end - *start;
+ size_t size = static_cast<size_t>(end - *start);
switch (size) {
case 0:
return false;
diff --git a/contrib/restricted/abseil-cpp/absl/time/format.cc b/contrib/restricted/abseil-cpp/absl/time/format.cc
index 4005fb704c..15a26b14f7 100644
--- a/contrib/restricted/abseil-cpp/absl/time/format.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/format.cc
@@ -64,7 +64,8 @@ cctz_parts Split(absl::Time t) {
// details about rep_hi and rep_lo.
absl::Time Join(const cctz_parts& parts) {
const int64_t rep_hi = (parts.sec - unix_epoch()).count();
- const uint32_t rep_lo = parts.fem.count() / (1000 * 1000 / 4);
+ const uint32_t rep_lo =
+ static_cast<uint32_t>(parts.fem.count() / (1000 * 1000 / 4));
const auto d = time_internal::MakeDuration(rep_hi, rep_lo);
return time_internal::FromUnixDuration(d);
}
diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
index d8cb047425..2e5f532911 100644
--- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
@@ -19,7 +19,7 @@
#endif
#if defined(HAS_STRPTIME) && HAS_STRPTIME
-#if !defined(_XOPEN_SOURCE)
+#if !defined(_XOPEN_SOURCE) && !defined(__OpenBSD__)
#define _XOPEN_SOURCE // Definedness suffices for strptime.
#endif
#endif
diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
index 4f175d95fc..787426f755 100644
--- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
@@ -134,6 +134,21 @@ std::int_fast64_t Decode64(const char* cp) {
return static_cast<std::int_fast64_t>(v - s64maxU - 1) - s64max - 1;
}
+// Does the rule for future transitions call for year-round daylight time?
+// See tz/zic.c:stringzone() for the details on how such rules are encoded.
+bool AllYearDST(const PosixTimeZone& posix) {
+ if (posix.dst_start.date.fmt != PosixTransition::N) return false;
+ if (posix.dst_start.date.n.day != 0) return false;
+ if (posix.dst_start.time.offset != 0) return false;
+
+ if (posix.dst_end.date.fmt != PosixTransition::J) return false;
+ if (posix.dst_end.date.j.day != kDaysPerYear[0]) return false;
+ const auto offset = posix.std_offset - posix.dst_offset;
+ if (posix.dst_end.time.offset + offset != kSecsPerDay) return false;
+
+ return true;
+}
+
// Generate a year-relative offset for a PosixTransition.
std::int_fast64_t TransOffset(bool leap_year, int jan1_weekday,
const PosixTransition& pt) {
@@ -351,6 +366,12 @@ bool TimeZoneInfo::ExtendTransitions() {
if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))
return false;
+ if (AllYearDST(posix)) { // dst only
+ // The future specification should match the last transition, and
+ // that means that handling the future will fall out naturally.
+ return EquivTransitions(transitions_.back().type_index, dst_ti);
+ }
+
// Extend the transitions for an additional 400 years using the
// future specification. Years beyond those can be handled by
// mapping back to a cycle-equivalent year within that range.
@@ -481,9 +502,9 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
// encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when
// interpreting a POSIX spec that does not include start/end rules, and
// that isn't the case here (see "zic -p").
- bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC
- bp += 1 * hdr.ttisstdcnt; // UTC/local indicators
- bp += 1 * hdr.ttisutcnt; // standard/wall indicators
+ bp += (time_len + 4) * hdr.leapcnt; // leap-time + TAI-UTC
+ bp += 1 * hdr.ttisstdcnt; // UTC/local indicators
+ bp += 1 * hdr.ttisutcnt; // standard/wall indicators
assert(bp == tbuf.data() + tbuf.size());
future_spec_.clear();
@@ -512,8 +533,8 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
// Trim redundant transitions. zic may have added these to work around
// differences between the glibc and reference implementations (see
- // zic.c:dontmerge) and the Qt library (see zic.c:WORK_AROUND_QTBUG_53071).
- // For us, they just get in the way when we do future_spec_ extension.
+ // zic.c:dontmerge) or to avoid bugs in old readers. For us, they just
+ // get in the way when we do future_spec_ extension.
while (hdr.timecnt > 1) {
if (!EquivTransitions(transitions_[hdr.timecnt - 1].type_index,
transitions_[hdr.timecnt - 2].type_index)) {
diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
index 55843c5e5b..849830b3db 100644
--- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -31,7 +31,7 @@
#if defined(__Fuchsia__)
#error #include <fuchsia/intl/cpp/fidl.h>
#error #include <lib/async-loop/cpp/loop.h>
-#error #include <lib/sys/cpp/component_context.h>
+#error #include <lib/fdio/directory.h>
#error #include <zircon/types.h>
#endif
@@ -140,8 +140,9 @@ time_zone local_time_zone() {
if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {
CFStringEncoding encoding = kCFStringEncodingUTF8;
CFIndex length = CFStringGetLength(tz_name);
- buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1);
- if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) {
+ CFIndex max_size = CFStringGetMaximumSizeForEncoding(length, encoding) + 1;
+ buffer.resize(static_cast<size_t>(max_size));
+ if (CFStringGetCString(tz_name, &buffer[0], max_size, encoding)) {
zone = &buffer[0];
}
}
@@ -160,11 +161,11 @@ time_zone local_time_zone() {
// would be set to null when the loop is destroyed, causing any other FIDL
// code running on the same thread to crash.
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
- std::unique_ptr<sys::ComponentContext> context =
- sys::ComponentContext::Create();
fuchsia::intl::PropertyProviderHandle handle;
- zx_status_t status = context->svc()->Connect(handle.NewRequest());
+ zx_status_t status = fdio_service_connect_by_name(
+ fuchsia::intl::PropertyProvider::Name_,
+ handle.NewRequest().TakeChannel().release());
if (status != ZX_OK) {
return;
}
diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
index 5ab5a59ecf..1b162337fd 100644
--- a/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
@@ -58,7 +58,8 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the
// Windows linker cannot handle that. Nor does the MinGW compiler know how to
// pass "#pragma comment(linker, ...)" to the Windows linker.
-#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__)
+#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__) && \
+ !defined(__CYGWIN__)
ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =
DefaultFactory;
#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION)
@@ -66,41 +67,41 @@ extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory;
ZoneInfoSourceFactory default_factory = DefaultFactory;
#if defined(_M_IX86) || defined(_M_ARM)
-#pragma comment( \
- linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@@ZA")
+#pragma comment( \
+ linker, \
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZA")
#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM64)
-#pragma comment( \
- linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
- "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
- "@@ZEA")
+#pragma comment( \
+ linker, \
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZEA")
#else
#error Unsupported MSVC platform
#endif // _M_<PLATFORM>
diff --git a/contrib/restricted/abseil-cpp/absl/time/time.cc b/contrib/restricted/abseil-cpp/absl/time/time.cc
index 1ec2026e25..7256a699d2 100644
--- a/contrib/restricted/abseil-cpp/absl/time/time.cc
+++ b/contrib/restricted/abseil-cpp/absl/time/time.cc
@@ -297,7 +297,7 @@ timespec ToTimespec(Time t) {
timespec ts;
absl::Duration d = time_internal::ToUnixDuration(t);
if (!time_internal::IsInfiniteDuration(d)) {
- ts.tv_sec = time_internal::GetRepHi(d);
+ ts.tv_sec = static_cast<decltype(ts.tv_sec)>(time_internal::GetRepHi(d));
if (ts.tv_sec == time_internal::GetRepHi(d)) { // no time_t narrowing
ts.tv_nsec = time_internal::GetRepLo(d) / 4; // floor
return ts;
@@ -316,7 +316,7 @@ timespec ToTimespec(Time t) {
timeval ToTimeval(Time t) {
timeval tv;
timespec ts = absl::ToTimespec(t);
- tv.tv_sec = ts.tv_sec;
+ tv.tv_sec = static_cast<decltype(tv.tv_sec)>(ts.tv_sec);
if (tv.tv_sec != ts.tv_sec) { // narrowing
if (ts.tv_sec < 0) {
tv.tv_sec = std::numeric_limits<decltype(tv.tv_sec)>::min();
diff --git a/contrib/restricted/abseil-cpp/absl/time/time.h b/contrib/restricted/abseil-cpp/absl/time/time.h
index bd01867e0c..cc3900826c 100644
--- a/contrib/restricted/abseil-cpp/absl/time/time.h
+++ b/contrib/restricted/abseil-cpp/absl/time/time.h
@@ -78,6 +78,7 @@ struct timeval;
#include <cmath>
#include <cstdint>
#include <ctime>
+#include <limits>
#include <ostream>
#include <string>
#include <type_traits>
@@ -97,19 +98,24 @@ class TimeZone; // Defined below
namespace time_internal {
int64_t IDivDuration(bool satq, Duration num, Duration den, Duration* rem);
-constexpr Time FromUnixDuration(Duration d);
-constexpr Duration ToUnixDuration(Time t);
-constexpr int64_t GetRepHi(Duration d);
-constexpr uint32_t GetRepLo(Duration d);
-constexpr Duration MakeDuration(int64_t hi, uint32_t lo);
-constexpr Duration MakeDuration(int64_t hi, int64_t lo);
-inline Duration MakePosDoubleDuration(double n);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
+ uint32_t lo);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
+ int64_t lo);
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n);
constexpr int64_t kTicksPerNanosecond = 4;
constexpr int64_t kTicksPerSecond = 1000 * 1000 * 1000 * kTicksPerNanosecond;
template <std::intmax_t N>
-constexpr Duration FromInt64(int64_t v, std::ratio<1, N>);
-constexpr Duration FromInt64(int64_t v, std::ratio<60>);
-constexpr Duration FromInt64(int64_t v, std::ratio<3600>);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<1, N>);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<60>);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<3600>);
template <typename T>
using EnableIfIntegral = typename std::enable_if<
std::is_integral<T>::value || std::is_enum<T>::value, int>::type;
@@ -222,37 +228,61 @@ class Duration {
};
// Relational Operators
-constexpr bool operator<(Duration lhs, Duration rhs);
-constexpr bool operator>(Duration lhs, Duration rhs) { return rhs < lhs; }
-constexpr bool operator>=(Duration lhs, Duration rhs) { return !(lhs < rhs); }
-constexpr bool operator<=(Duration lhs, Duration rhs) { return !(rhs < lhs); }
-constexpr bool operator==(Duration lhs, Duration rhs);
-constexpr bool operator!=(Duration lhs, Duration rhs) { return !(lhs == rhs); }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
+ Duration rhs);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Duration lhs,
+ Duration rhs) {
+ return rhs < lhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Duration lhs,
+ Duration rhs) {
+ return !(lhs < rhs);
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Duration lhs,
+ Duration rhs) {
+ return !(rhs < lhs);
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
+ Duration rhs);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Duration lhs,
+ Duration rhs) {
+ return !(lhs == rhs);
+}
// Additive Operators
-constexpr Duration operator-(Duration d);
-inline Duration operator+(Duration lhs, Duration rhs) { return lhs += rhs; }
-inline Duration operator-(Duration lhs, Duration rhs) { return lhs -= rhs; }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator+(Duration lhs,
+ Duration rhs) {
+ return lhs += rhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Duration lhs,
+ Duration rhs) {
+ return lhs -= rhs;
+}
// Multiplicative Operators
// Integer operands must be representable as int64_t.
template <typename T>
-Duration operator*(Duration lhs, T rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(Duration lhs, T rhs) {
return lhs *= rhs;
}
template <typename T>
-Duration operator*(T lhs, Duration rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator*(T lhs, Duration rhs) {
return rhs *= lhs;
}
template <typename T>
-Duration operator/(Duration lhs, T rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration operator/(Duration lhs, T rhs) {
return lhs /= rhs;
}
-inline int64_t operator/(Duration lhs, Duration rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t operator/(Duration lhs,
+ Duration rhs) {
return time_internal::IDivDuration(true, lhs, rhs,
&lhs); // trunc towards zero
}
-inline Duration operator%(Duration lhs, Duration rhs) { return lhs %= rhs; }
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator%(Duration lhs,
+ Duration rhs) {
+ return lhs %= rhs;
+}
// IDivDuration()
//
@@ -299,18 +329,20 @@ inline int64_t IDivDuration(Duration num, Duration den, Duration* rem) {
//
// double d = absl::FDivDuration(absl::Milliseconds(1500), absl::Seconds(1));
// // d == 1.5
-double FDivDuration(Duration num, Duration den);
+ABSL_ATTRIBUTE_CONST_FUNCTION double FDivDuration(Duration num, Duration den);
// ZeroDuration()
//
// Returns a zero-length duration. This function behaves just like the default
// constructor, but the name helps make the semantics clear at call sites.
-constexpr Duration ZeroDuration() { return Duration(); }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ZeroDuration() {
+ return Duration();
+}
// AbsDuration()
//
// Returns the absolute value of a duration.
-inline Duration AbsDuration(Duration d) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration AbsDuration(Duration d) {
return (d < ZeroDuration()) ? -d : d;
}
@@ -322,7 +354,7 @@ inline Duration AbsDuration(Duration d) {
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration a = absl::Trunc(d, absl::Microseconds(1)); // 123456us
-Duration Trunc(Duration d, Duration unit);
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Trunc(Duration d, Duration unit);
// Floor()
//
@@ -333,7 +365,7 @@ Duration Trunc(Duration d, Duration unit);
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration b = absl::Floor(d, absl::Microseconds(1)); // 123456us
-Duration Floor(Duration d, Duration unit);
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Floor(Duration d, Duration unit);
// Ceil()
//
@@ -344,7 +376,7 @@ Duration Floor(Duration d, Duration unit);
//
// absl::Duration d = absl::Nanoseconds(123456789);
// absl::Duration c = absl::Ceil(d, absl::Microseconds(1)); // 123457us
-Duration Ceil(Duration d, Duration unit);
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Ceil(Duration d, Duration unit);
// InfiniteDuration()
//
@@ -380,7 +412,7 @@ Duration Ceil(Duration d, Duration unit);
//
// The examples involving the `/` operator above also apply to `IDivDuration()`
// and `FDivDuration()`.
-constexpr Duration InfiniteDuration();
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration();
// Nanoseconds()
// Microseconds()
@@ -404,27 +436,27 @@ constexpr Duration InfiniteDuration();
// absl::Duration a = absl::Seconds(60);
// absl::Duration b = absl::Minutes(1); // b == a
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Nanoseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Nanoseconds(T n) {
return time_internal::FromInt64(n, std::nano{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Microseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Microseconds(T n) {
return time_internal::FromInt64(n, std::micro{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Milliseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Milliseconds(T n) {
return time_internal::FromInt64(n, std::milli{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Seconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Seconds(T n) {
return time_internal::FromInt64(n, std::ratio<1>{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Minutes(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Minutes(T n) {
return time_internal::FromInt64(n, std::ratio<60>{});
}
template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Hours(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration Hours(T n) {
return time_internal::FromInt64(n, std::ratio<3600>{});
}
@@ -438,19 +470,19 @@ constexpr Duration Hours(T n) {
// auto a = absl::Seconds(1.5); // OK
// auto b = absl::Milliseconds(1500); // BETTER
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Nanoseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Nanoseconds(T n) {
return n * Nanoseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Microseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Microseconds(T n) {
return n * Microseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Milliseconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Milliseconds(T n) {
return n * Milliseconds(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Seconds(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Seconds(T n) {
if (n >= 0) { // Note: `NaN >= 0` is false.
if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) {
return InfiniteDuration();
@@ -464,11 +496,11 @@ Duration Seconds(T n) {
}
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Minutes(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Minutes(T n) {
return n * Minutes(1);
}
template <typename T, time_internal::EnableIfFloat<T> = 0>
-Duration Hours(T n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration Hours(T n) {
return n * Hours(1);
}
@@ -488,14 +520,14 @@ Duration Hours(T n) {
//
// absl::Duration d = absl::Milliseconds(1500);
// int64_t isec = absl::ToInt64Seconds(d); // isec == 1
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Nanoseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Microseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Seconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Minutes(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d);
-
-// ToDoubleNanoSeconds()
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Nanoseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Microseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Seconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Minutes(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Hours(Duration d);
+
+// ToDoubleNanoseconds()
// ToDoubleMicroseconds()
// ToDoubleMilliseconds()
// ToDoubleSeconds()
@@ -510,12 +542,12 @@ ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d);
//
// absl::Duration d = absl::Milliseconds(1500);
// double dsec = absl::ToDoubleSeconds(d); // dsec == 1.5
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleNanoseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMicroseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMilliseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleSeconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMinutes(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleHours(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleNanoseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMicroseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMilliseconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleSeconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleMinutes(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToDoubleHours(Duration d);
// FromChrono()
//
@@ -525,12 +557,18 @@ ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleHours(Duration d);
//
// std::chrono::milliseconds ms(123);
// absl::Duration d = absl::FromChrono(ms);
-constexpr Duration FromChrono(const std::chrono::nanoseconds& d);
-constexpr Duration FromChrono(const std::chrono::microseconds& d);
-constexpr Duration FromChrono(const std::chrono::milliseconds& d);
-constexpr Duration FromChrono(const std::chrono::seconds& d);
-constexpr Duration FromChrono(const std::chrono::minutes& d);
-constexpr Duration FromChrono(const std::chrono::hours& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::nanoseconds& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::microseconds& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::milliseconds& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::seconds& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::minutes& d);
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::hours& d);
// ToChronoNanoseconds()
// ToChronoMicroseconds()
@@ -550,18 +588,21 @@ constexpr Duration FromChrono(const std::chrono::hours& d);
// auto y = absl::ToChronoNanoseconds(d); // x == y
// auto z = absl::ToChronoSeconds(absl::InfiniteDuration());
// // z == std::chrono::seconds::max()
-std::chrono::nanoseconds ToChronoNanoseconds(Duration d);
-std::chrono::microseconds ToChronoMicroseconds(Duration d);
-std::chrono::milliseconds ToChronoMilliseconds(Duration d);
-std::chrono::seconds ToChronoSeconds(Duration d);
-std::chrono::minutes ToChronoMinutes(Duration d);
-std::chrono::hours ToChronoHours(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::nanoseconds ToChronoNanoseconds(
+ Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::microseconds ToChronoMicroseconds(
+ Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::milliseconds ToChronoMilliseconds(
+ Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::seconds ToChronoSeconds(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::minutes ToChronoMinutes(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::hours ToChronoHours(Duration d);
// FormatDuration()
//
// Returns a string representing the duration in the form "72h3m0.5s".
// Returns "inf" or "-inf" for +/- `InfiniteDuration()`.
-std::string FormatDuration(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::string FormatDuration(Duration d);
// Output stream operator.
inline std::ostream& operator<<(std::ostream& os, Duration d) {
@@ -725,29 +766,49 @@ class Time {
};
// Relational Operators
-constexpr bool operator<(Time lhs, Time rhs) { return lhs.rep_ < rhs.rep_; }
-constexpr bool operator>(Time lhs, Time rhs) { return rhs < lhs; }
-constexpr bool operator>=(Time lhs, Time rhs) { return !(lhs < rhs); }
-constexpr bool operator<=(Time lhs, Time rhs) { return !(rhs < lhs); }
-constexpr bool operator==(Time lhs, Time rhs) { return lhs.rep_ == rhs.rep_; }
-constexpr bool operator!=(Time lhs, Time rhs) { return !(lhs == rhs); }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
+ return lhs.rep_ < rhs.rep_;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>(Time lhs, Time rhs) {
+ return rhs < lhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator>=(Time lhs, Time rhs) {
+ return !(lhs < rhs);
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<=(Time lhs, Time rhs) {
+ return !(rhs < lhs);
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Time lhs, Time rhs) {
+ return lhs.rep_ == rhs.rep_;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator!=(Time lhs, Time rhs) {
+ return !(lhs == rhs);
+}
// Additive Operators
-inline Time operator+(Time lhs, Duration rhs) { return lhs += rhs; }
-inline Time operator+(Duration lhs, Time rhs) { return rhs += lhs; }
-inline Time operator-(Time lhs, Duration rhs) { return lhs -= rhs; }
-inline Duration operator-(Time lhs, Time rhs) { return lhs.rep_ - rhs.rep_; }
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Time lhs, Duration rhs) {
+ return lhs += rhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator+(Duration lhs, Time rhs) {
+ return rhs += lhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Time operator-(Time lhs, Duration rhs) {
+ return lhs -= rhs;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration operator-(Time lhs, Time rhs) {
+ return lhs.rep_ - rhs.rep_;
+}
// UnixEpoch()
//
// Returns the `absl::Time` representing "1970-01-01 00:00:00.0 +0000".
-constexpr Time UnixEpoch() { return Time(); }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UnixEpoch() { return Time(); }
// UniversalEpoch()
//
// Returns the `absl::Time` representing "0001-01-01 00:00:00.0 +0000", the
// epoch of the ICU Universal Time Scale.
-constexpr Time UniversalEpoch() {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time UniversalEpoch() {
// 719162 is the number of days from 0001-01-01 to 1970-01-01,
// assuming the Gregorian calendar.
return Time(
@@ -757,7 +818,7 @@ constexpr Time UniversalEpoch() {
// InfiniteFuture()
//
// Returns an `absl::Time` that is infinitely far in the future.
-constexpr Time InfiniteFuture() {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfiniteFuture() {
return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
~uint32_t{0}));
}
@@ -765,7 +826,7 @@ constexpr Time InfiniteFuture() {
// InfinitePast()
//
// Returns an `absl::Time` that is infinitely far in the past.
-constexpr Time InfinitePast() {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time InfinitePast() {
return Time(time_internal::MakeDuration((std::numeric_limits<int64_t>::min)(),
~uint32_t{0}));
}
@@ -779,13 +840,13 @@ constexpr Time InfinitePast() {
// FromUniversal()
//
// Creates an `absl::Time` from a variety of other representations.
-constexpr Time FromUnixNanos(int64_t ns);
-constexpr Time FromUnixMicros(int64_t us);
-constexpr Time FromUnixMillis(int64_t ms);
-constexpr Time FromUnixSeconds(int64_t s);
-constexpr Time FromTimeT(time_t t);
-Time FromUDate(double udate);
-Time FromUniversal(int64_t universal);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s);
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t);
+ABSL_ATTRIBUTE_CONST_FUNCTION Time FromUDate(double udate);
+ABSL_ATTRIBUTE_CONST_FUNCTION Time FromUniversal(int64_t universal);
// ToUnixNanos()
// ToUnixMicros()
@@ -799,13 +860,13 @@ Time FromUniversal(int64_t universal);
// these operations round down toward negative infinity where necessary to
// adjust to the resolution of the result type. Beware of possible time_t
// over/underflow in ToTime{T,val,spec}() on 32-bit platforms.
-int64_t ToUnixNanos(Time t);
-int64_t ToUnixMicros(Time t);
-int64_t ToUnixMillis(Time t);
-int64_t ToUnixSeconds(Time t);
-time_t ToTimeT(Time t);
-double ToUDate(Time t);
-int64_t ToUniversal(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixNanos(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMicros(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixMillis(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUnixSeconds(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION time_t ToTimeT(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION double ToUDate(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToUniversal(Time t);
// DurationFromTimespec()
// DurationFromTimeval()
@@ -821,14 +882,14 @@ int64_t ToUniversal(Time t);
// and gettimeofday(2)), so conversion functions are provided for both cases.
// The "to timespec/val" direction is easily handled via overloading, but
// for "from timespec/val" the desired type is part of the function name.
-Duration DurationFromTimespec(timespec ts);
-Duration DurationFromTimeval(timeval tv);
-timespec ToTimespec(Duration d);
-timeval ToTimeval(Duration d);
-Time TimeFromTimespec(timespec ts);
-Time TimeFromTimeval(timeval tv);
-timespec ToTimespec(Time t);
-timeval ToTimeval(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimespec(timespec ts);
+ABSL_ATTRIBUTE_CONST_FUNCTION Duration DurationFromTimeval(timeval tv);
+ABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Duration d);
+ABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimespec(timespec ts);
+ABSL_ATTRIBUTE_CONST_FUNCTION Time TimeFromTimeval(timeval tv);
+ABSL_ATTRIBUTE_CONST_FUNCTION timespec ToTimespec(Time t);
+ABSL_ATTRIBUTE_CONST_FUNCTION timeval ToTimeval(Time t);
// FromChrono()
//
@@ -839,7 +900,8 @@ timeval ToTimeval(Time t);
// auto tp = std::chrono::system_clock::from_time_t(123);
// absl::Time t = absl::FromChrono(tp);
// // t == absl::FromTimeT(123)
-Time FromChrono(const std::chrono::system_clock::time_point& tp);
+ABSL_ATTRIBUTE_PURE_FUNCTION Time
+FromChrono(const std::chrono::system_clock::time_point& tp);
// ToChronoTime()
//
@@ -852,7 +914,8 @@ Time FromChrono(const std::chrono::system_clock::time_point& tp);
// absl::Time t = absl::FromTimeT(123);
// auto tp = absl::ToChronoTime(t);
// // tp == std::chrono::system_clock::from_time_t(123);
-std::chrono::system_clock::time_point ToChronoTime(Time);
+ABSL_ATTRIBUTE_CONST_FUNCTION std::chrono::system_clock::time_point
+ ToChronoTime(Time);
// AbslParseFlag()
//
@@ -1124,22 +1187,25 @@ inline TimeZone LocalTimeZone() {
// absl::Time t = ...;
// absl::TimeZone tz = ...;
// const auto cd = absl::ToCivilDay(t, tz);
-inline CivilSecond ToCivilSecond(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilSecond ToCivilSecond(Time t,
+ TimeZone tz) {
return tz.At(t).cs; // already a CivilSecond
}
-inline CivilMinute ToCivilMinute(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMinute ToCivilMinute(Time t,
+ TimeZone tz) {
return CivilMinute(tz.At(t).cs);
}
-inline CivilHour ToCivilHour(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilHour ToCivilHour(Time t, TimeZone tz) {
return CivilHour(tz.At(t).cs);
}
-inline CivilDay ToCivilDay(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilDay ToCivilDay(Time t, TimeZone tz) {
return CivilDay(tz.At(t).cs);
}
-inline CivilMonth ToCivilMonth(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilMonth ToCivilMonth(Time t,
+ TimeZone tz) {
return CivilMonth(tz.At(t).cs);
}
-inline CivilYear ToCivilYear(Time t, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline CivilYear ToCivilYear(Time t, TimeZone tz) {
return CivilYear(tz.At(t).cs);
}
@@ -1155,7 +1221,8 @@ inline CivilYear ToCivilYear(Time t, TimeZone tz) {
// being when two non-existent civil times map to the same transition time.
//
// Note: Accepts civil times of any alignment.
-inline Time FromCivil(CivilSecond ct, TimeZone tz) {
+ABSL_ATTRIBUTE_PURE_FUNCTION inline Time FromCivil(CivilSecond ct,
+ TimeZone tz) {
const auto ti = tz.At(ct);
if (ti.kind == TimeZone::TimeInfo::SKIPPED) return ti.trans;
return ti.pre;
@@ -1240,13 +1307,13 @@ inline Time FromDateTime(int64_t year, int mon, int day, int hour,
// instant, so `tm_isdst != 0` returns the DST instant, and `tm_isdst == 0`
// returns the non-DST instant, that would have matched if the transition never
// happened.
-Time FromTM(const struct tm& tm, TimeZone tz);
+ABSL_ATTRIBUTE_PURE_FUNCTION Time FromTM(const struct tm& tm, TimeZone tz);
// ToTM()
//
// Converts the given `absl::Time` to a struct tm using the given time zone.
// See ctime(3) for a description of the values of the tm fields.
-struct tm ToTM(Time t, TimeZone tz);
+ABSL_ATTRIBUTE_PURE_FUNCTION struct tm ToTM(Time t, TimeZone tz);
// RFC3339_full
// RFC3339_sec
@@ -1305,13 +1372,14 @@ ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
// In both cases the given format string and `absl::TimeZone` are ignored.
//
-std::string FormatTime(absl::string_view format, Time t, TimeZone tz);
+ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(absl::string_view format,
+ Time t, TimeZone tz);
// Convenience functions that format the given time using the RFC3339_full
// format. The first overload uses the provided TimeZone, while the second
// uses LocalTimeZone().
-std::string FormatTime(Time t, TimeZone tz);
-std::string FormatTime(Time t);
+ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t, TimeZone tz);
+ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t);
// Output stream operator.
inline std::ostream& operator<<(std::ostream& os, Time t) {
@@ -1389,18 +1457,20 @@ namespace time_internal {
// Creates a Duration with a given representation.
// REQUIRES: hi,lo is a valid representation of a Duration as specified
// in time/duration.cc.
-constexpr Duration MakeDuration(int64_t hi, uint32_t lo = 0) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
+ uint32_t lo = 0) {
return Duration(hi, lo);
}
-constexpr Duration MakeDuration(int64_t hi, int64_t lo) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeDuration(int64_t hi,
+ int64_t lo) {
return MakeDuration(hi, static_cast<uint32_t>(lo));
}
// Make a Duration value from a floating-point number, as long as that number
// is in the range [ 0 .. numeric_limits<int64_t>::max ), that is, as long as
// it's positive and can be converted to int64_t without risk of UB.
-inline Duration MakePosDoubleDuration(double n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline Duration MakePosDoubleDuration(double n) {
const int64_t int_secs = static_cast<int64_t>(n);
const uint32_t ticks = static_cast<uint32_t>(
std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond));
@@ -1413,23 +1483,28 @@ inline Duration MakePosDoubleDuration(double n) {
// pair. sec may be positive or negative. ticks must be in the range
// -kTicksPerSecond < *ticks < kTicksPerSecond. If ticks is negative it
// will be normalized to a positive value in the resulting Duration.
-constexpr Duration MakeNormalizedDuration(int64_t sec, int64_t ticks) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration MakeNormalizedDuration(
+ int64_t sec, int64_t ticks) {
return (ticks < 0) ? MakeDuration(sec - 1, ticks + kTicksPerSecond)
: MakeDuration(sec, ticks);
}
// Provide access to the Duration representation.
-constexpr int64_t GetRepHi(Duration d) { return d.rep_hi_; }
-constexpr uint32_t GetRepLo(Duration d) { return d.rep_lo_; }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t GetRepHi(Duration d) {
+ return d.rep_hi_;
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr uint32_t GetRepLo(Duration d) {
+ return d.rep_lo_;
+}
// Returns true iff d is positive or negative infinity.
-constexpr bool IsInfiniteDuration(Duration d) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool IsInfiniteDuration(Duration d) {
return GetRepLo(d) == ~uint32_t{0};
}
// Returns an infinite Duration with the opposite sign.
// REQUIRES: IsInfiniteDuration(d)
-constexpr Duration OppositeInfinity(Duration d) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration OppositeInfinity(Duration d) {
return GetRepHi(d) < 0
? MakeDuration((std::numeric_limits<int64_t>::max)(), ~uint32_t{0})
: MakeDuration((std::numeric_limits<int64_t>::min)(),
@@ -1437,7 +1512,8 @@ constexpr Duration OppositeInfinity(Duration d) {
}
// Returns (-n)-1 (equivalently -(n+1)) without avoidable overflow.
-constexpr int64_t NegateAndSubtractOne(int64_t n) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr int64_t NegateAndSubtractOne(
+ int64_t n) {
// Note: Good compilers will optimize this expression to ~n when using
// a two's-complement representation (which is required for int64_t).
return (n < 0) ? -(n + 1) : (-n) - 1;
@@ -1447,23 +1523,30 @@ constexpr int64_t NegateAndSubtractOne(int64_t n) {
// functions depend on the above mentioned choice of the Unix epoch for the
// Time representation (and both need to be Time friends). Without this
// knowledge, we would need to add-in/subtract-out UnixEpoch() respectively.
-constexpr Time FromUnixDuration(Duration d) { return Time(d); }
-constexpr Duration ToUnixDuration(Time t) { return t.rep_; }
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixDuration(Duration d) {
+ return Time(d);
+}
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration ToUnixDuration(Time t) {
+ return t.rep_;
+}
template <std::intmax_t N>
-constexpr Duration FromInt64(int64_t v, std::ratio<1, N>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<1, N>) {
static_assert(0 < N && N <= 1000 * 1000 * 1000, "Unsupported ratio");
// Subsecond ratios cannot overflow.
return MakeNormalizedDuration(
v / N, v % N * kTicksPerNanosecond * 1000 * 1000 * 1000 / N);
}
-constexpr Duration FromInt64(int64_t v, std::ratio<60>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<60>) {
return (v <= (std::numeric_limits<int64_t>::max)() / 60 &&
v >= (std::numeric_limits<int64_t>::min)() / 60)
? MakeDuration(v * 60)
: v > 0 ? InfiniteDuration() : -InfiniteDuration();
}
-constexpr Duration FromInt64(int64_t v, std::ratio<3600>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration FromInt64(int64_t v,
+ std::ratio<3600>) {
return (v <= (std::numeric_limits<int64_t>::max)() / 3600 &&
v >= (std::numeric_limits<int64_t>::min)() / 3600)
? MakeDuration(v * 3600)
@@ -1483,40 +1566,44 @@ constexpr auto IsValidRep64(char) -> bool {
// Converts a std::chrono::duration to an absl::Duration.
template <typename Rep, typename Period>
-constexpr Duration FromChrono(const std::chrono::duration<Rep, Period>& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::duration<Rep, Period>& d) {
static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
return FromInt64(int64_t{d.count()}, Period{});
}
template <typename Ratio>
-int64_t ToInt64(Duration d, Ratio) {
+ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64(Duration d, Ratio) {
// Note: This may be used on MSVC, which may have a system_clock period of
// std::ratio<1, 10 * 1000 * 1000>
return ToInt64Seconds(d * Ratio::den / Ratio::num);
}
// Fastpath implementations for the 6 common duration units.
-inline int64_t ToInt64(Duration d, std::nano) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::nano) {
return ToInt64Nanoseconds(d);
}
-inline int64_t ToInt64(Duration d, std::micro) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::micro) {
return ToInt64Microseconds(d);
}
-inline int64_t ToInt64(Duration d, std::milli) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d, std::milli) {
return ToInt64Milliseconds(d);
}
-inline int64_t ToInt64(Duration d, std::ratio<1>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
+ std::ratio<1>) {
return ToInt64Seconds(d);
}
-inline int64_t ToInt64(Duration d, std::ratio<60>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
+ std::ratio<60>) {
return ToInt64Minutes(d);
}
-inline int64_t ToInt64(Duration d, std::ratio<3600>) {
+ABSL_ATTRIBUTE_CONST_FUNCTION inline int64_t ToInt64(Duration d,
+ std::ratio<3600>) {
return ToInt64Hours(d);
}
// Converts an absl::Duration to a chrono duration of type T.
template <typename T>
-T ToChronoDuration(Duration d) {
+ABSL_ATTRIBUTE_CONST_FUNCTION T ToChronoDuration(Duration d) {
using Rep = typename T::rep;
using Period = typename T::period;
static_assert(IsValidRep64<Rep>(0), "duration::rep is invalid");
@@ -1530,7 +1617,8 @@ T ToChronoDuration(Duration d) {
} // namespace time_internal
-constexpr bool operator<(Duration lhs, Duration rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
+ Duration rhs) {
return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
: time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()
@@ -1539,12 +1627,13 @@ constexpr bool operator<(Duration lhs, Duration rhs) {
: time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
}
-constexpr bool operator==(Duration lhs, Duration rhs) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
+ Duration rhs) {
return time_internal::GetRepHi(lhs) == time_internal::GetRepHi(rhs) &&
time_internal::GetRepLo(lhs) == time_internal::GetRepLo(rhs);
}
-constexpr Duration operator-(Duration d) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration operator-(Duration d) {
// This is a little interesting because of the special cases.
//
// If rep_lo_ is zero, we have it easy; it's safe to negate rep_hi_, we're
@@ -1570,47 +1659,53 @@ constexpr Duration operator-(Duration d) {
time_internal::GetRepLo(d));
}
-constexpr Duration InfiniteDuration() {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Duration InfiniteDuration() {
return time_internal::MakeDuration((std::numeric_limits<int64_t>::max)(),
~uint32_t{0});
}
-constexpr Duration FromChrono(const std::chrono::nanoseconds& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::nanoseconds& d) {
return time_internal::FromChrono(d);
}
-constexpr Duration FromChrono(const std::chrono::microseconds& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::microseconds& d) {
return time_internal::FromChrono(d);
}
-constexpr Duration FromChrono(const std::chrono::milliseconds& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::milliseconds& d) {
return time_internal::FromChrono(d);
}
-constexpr Duration FromChrono(const std::chrono::seconds& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::seconds& d) {
return time_internal::FromChrono(d);
}
-constexpr Duration FromChrono(const std::chrono::minutes& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::minutes& d) {
return time_internal::FromChrono(d);
}
-constexpr Duration FromChrono(const std::chrono::hours& d) {
+ABSL_ATTRIBUTE_PURE_FUNCTION constexpr Duration FromChrono(
+ const std::chrono::hours& d) {
return time_internal::FromChrono(d);
}
-constexpr Time FromUnixNanos(int64_t ns) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixNanos(int64_t ns) {
return time_internal::FromUnixDuration(Nanoseconds(ns));
}
-constexpr Time FromUnixMicros(int64_t us) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMicros(int64_t us) {
return time_internal::FromUnixDuration(Microseconds(us));
}
-constexpr Time FromUnixMillis(int64_t ms) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixMillis(int64_t ms) {
return time_internal::FromUnixDuration(Milliseconds(ms));
}
-constexpr Time FromUnixSeconds(int64_t s) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromUnixSeconds(int64_t s) {
return time_internal::FromUnixDuration(Seconds(s));
}
-constexpr Time FromTimeT(time_t t) {
+ABSL_ATTRIBUTE_CONST_FUNCTION constexpr Time FromTimeT(time_t t) {
return time_internal::FromUnixDuration(Seconds(t));
}
diff --git a/contrib/restricted/abseil-cpp/absl/types/internal/span.h b/contrib/restricted/abseil-cpp/absl/types/internal/span.h
index 112612f4bd..344ad4dbad 100644
--- a/contrib/restricted/abseil-cpp/absl/types/internal/span.h
+++ b/contrib/restricted/abseil-cpp/absl/types/internal/span.h
@@ -28,10 +28,10 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace span_internal {
-// A constexpr min function
-constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
+template <typename T>
+class Span;
+namespace span_internal {
// Wrappers for access to container data pointers.
template <typename C>
constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
@@ -99,28 +99,39 @@ bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
}
-// The `IsConvertible` classes here are needed because of the
-// `std::is_convertible` bug in libcxx when compiled with GCC. This build
-// configuration is used by Android NDK toolchain. Reference link:
-// https://bugs.llvm.org/show_bug.cgi?id=27538.
template <typename From, typename To>
-struct IsConvertibleHelper {
- private:
- static std::true_type testval(To);
- static std::false_type testval(...);
+using EnableIfConvertibleTo =
+ typename std::enable_if<std::is_convertible<From, To>::value>::type;
+
+// IsView is true for types where the return type of .data() is the same for
+// mutable and const instances. This isn't foolproof, but it's only used to
+// enable a compiler warning.
+template <typename T, typename = void, typename = void>
+struct IsView {
+ static constexpr bool value = false;
+};
+template <typename T>
+struct IsView<
+ T, absl::void_t<decltype(span_internal::GetData(std::declval<const T&>()))>,
+ absl::void_t<decltype(span_internal::GetData(std::declval<T&>()))>> {
+ private:
+ using Container = std::remove_const_t<T>;
+ using ConstData =
+ decltype(span_internal::GetData(std::declval<const Container&>()));
+ using MutData = decltype(span_internal::GetData(std::declval<Container&>()));
public:
- using type = decltype(testval(std::declval<From>()));
+ static constexpr bool value = std::is_same<ConstData, MutData>::value;
};
-template <typename From, typename To>
-struct IsConvertible : IsConvertibleHelper<From, To>::type {};
+// These enablers result in 'int' so they can be used as typenames or defaults
+// in template paramters lists.
+template <typename T>
+using EnableIfIsView = std::enable_if_t<IsView<T>::value, int>;
+
+template <typename T>
+using EnableIfNotIsView = std::enable_if_t<!IsView<T>::value, int>;
-// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
-// older version of libcxx is not supported.
-template <typename From, typename To>
-using EnableIfConvertibleTo =
- typename std::enable_if<IsConvertible<From, To>::value>::type;
} // namespace span_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/contrib/restricted/abseil-cpp/absl/types/internal/variant.h b/contrib/restricted/abseil-cpp/absl/types/internal/variant.h
index 7c402ecef3..c82ded44f8 100644
--- a/contrib/restricted/abseil-cpp/absl/types/internal/variant.h
+++ b/contrib/restricted/abseil-cpp/absl/types/internal/variant.h
@@ -16,8 +16,8 @@
// separate file to avoid cluttering the top of the API header with
// implementation details.
-#ifndef ABSL_TYPES_VARIANT_INTERNAL_H_
-#define ABSL_TYPES_VARIANT_INTERNAL_H_
+#ifndef ABSL_TYPES_INTERNAL_VARIANT_H_
+#define ABSL_TYPES_INTERNAL_VARIANT_H_
#include <cassert>
#include <cstddef>
@@ -449,7 +449,7 @@ struct FlattenIndices;
template <std::size_t HeadSize, std::size_t... TailSize>
struct FlattenIndices<HeadSize, TailSize...> {
- template<class... SizeType>
+ template <class... SizeType>
static constexpr std::size_t Run(std::size_t head, SizeType... tail) {
return head + HeadSize * FlattenIndices<TailSize...>::Run(tail...);
}
@@ -498,8 +498,8 @@ struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
};
template <class Op, class... SizeType>
- static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(
- Op&& op, SizeType... i) {
+ static VisitIndicesResultT<Op, decltype(EndIndices)...> Run(Op&& op,
+ SizeType... i) {
return VisitIndicesSwitch<NumCasesOfSwitch<EndIndices...>::value>::Run(
FlattenedOp<Op>{absl::forward<Op>(op)},
FlattenIndices<(EndIndices + std::size_t{1})...>::Run(
@@ -683,13 +683,13 @@ struct VariantCoreAccess {
variant_internal::IndexOfConstructedType<Left, QualifiedNew>;
void operator()(SizeT<NewIndex::value> /*old_i*/
- ) const {
+ ) const {
Access<NewIndex::value>(*left) = absl::forward<QualifiedNew>(other);
}
template <std::size_t OldIndex>
void operator()(SizeT<OldIndex> /*old_i*/
- ) const {
+ ) const {
using New =
typename absl::variant_alternative<NewIndex::value, Left>::type;
if (std::is_nothrow_constructible<New, QualifiedNew>::value ||
@@ -868,18 +868,6 @@ struct IsNeitherSelfNorInPlace<Self, in_place_type_t<T>> : std::false_type {};
template <class Self, std::size_t I>
struct IsNeitherSelfNorInPlace<Self, in_place_index_t<I>> : std::false_type {};
-template <class Variant, class T, class = void>
-struct ConversionIsPossibleImpl : std::false_type {};
-
-template <class Variant, class T>
-struct ConversionIsPossibleImpl<
- Variant, T,
- void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
- : std::true_type {};
-
-template <class Variant, class T>
-struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
-
template <class Variant, class T>
struct IndexOfConstructedType<
Variant, T,
@@ -1151,16 +1139,16 @@ struct VariantHelper<variant<Ts...>> {
// Type metafunction which returns the element type selected if
// OverloadSet::Overload() is well-formed when called with argument type U.
template <typename U>
- using BestMatch = decltype(
- variant_internal::OverloadSet<Ts...>::Overload(std::declval<U>()));
+ using BestMatch = decltype(variant_internal::OverloadSet<Ts...>::Overload(
+ std::declval<U>()));
// Type metafunction which returns true if OverloadSet::Overload() is
// well-formed when called with argument type U.
// CanAccept can't be just an alias because there is a MSVC bug on parameter
// pack expansion involving decltype.
template <typename U>
- struct CanAccept :
- std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
+ struct CanAccept
+ : std::integral_constant<bool, !std::is_void<BestMatch<U>>::value> {};
// Type metafunction which returns true if Other is an instantiation of
// variant, and variants's converting constructor from Other will be
@@ -1183,8 +1171,8 @@ struct TrivialMoveOnly {
// A union's defaulted copy/move constructor is deleted if any variant member's
// copy/move constructor is nontrivial.
template <typename T>
-struct IsTriviallyMoveConstructible:
- std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
+struct IsTriviallyMoveConstructible
+ : std::is_move_constructible<Union<T, TrivialMoveOnly>> {};
// To guarantee triviality of all special-member functions that can be trivial,
// we use a chain of conditional bases for each one.
@@ -1419,14 +1407,14 @@ class VariantMoveAssignBaseNontrivial : protected VariantCopyBase<T...> {
VariantMoveAssignBaseNontrivial& operator=(
VariantMoveAssignBaseNontrivial const&) = default;
- VariantMoveAssignBaseNontrivial&
- operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
- absl::conjunction<std::is_nothrow_move_constructible<T>...,
- std::is_nothrow_move_assignable<T>...>::value) {
- VisitIndices<sizeof...(T)>::Run(
- VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
- return *this;
- }
+ VariantMoveAssignBaseNontrivial&
+ operator=(VariantMoveAssignBaseNontrivial&& other) noexcept(
+ absl::conjunction<std::is_nothrow_move_constructible<T>...,
+ std::is_nothrow_move_assignable<T>...>::value) {
+ VisitIndices<sizeof...(T)>::Run(
+ VariantCoreAccess::MakeMoveAssignVisitor(this, &other), other.index_);
+ return *this;
+ }
protected:
using Base::index_;
@@ -1450,12 +1438,12 @@ class VariantCopyAssignBaseNontrivial : protected VariantMoveAssignBase<T...> {
VariantCopyAssignBaseNontrivial& operator=(
VariantCopyAssignBaseNontrivial&&) = default;
- VariantCopyAssignBaseNontrivial& operator=(
- const VariantCopyAssignBaseNontrivial& other) {
- VisitIndices<sizeof...(T)>::Run(
- VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
- return *this;
- }
+ VariantCopyAssignBaseNontrivial& operator=(
+ const VariantCopyAssignBaseNontrivial& other) {
+ VisitIndices<sizeof...(T)>::Run(
+ VariantCoreAccess::MakeCopyAssignVisitor(this, other), other.index_);
+ return *this;
+ }
protected:
using Base::index_;
@@ -1643,4 +1631,4 @@ ABSL_NAMESPACE_END
} // namespace absl
#endif // !defined(ABSL_USES_STD_VARIANT)
-#endif // ABSL_TYPES_VARIANT_INTERNAL_H_
+#endif // ABSL_TYPES_INTERNAL_VARIANT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/types/span.h b/contrib/restricted/abseil-cpp/absl/types/span.h
index fdfbd77c07..d7bdbb1fb5 100644
--- a/contrib/restricted/abseil-cpp/absl/types/span.h
+++ b/contrib/restricted/abseil-cpp/absl/types/span.h
@@ -60,6 +60,7 @@
#include <type_traits>
#include <utility>
+#include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
@@ -160,12 +161,12 @@ class Span {
// Used to SFINAE-enable a function when the slice elements are const.
template <typename U>
- using EnableIfConstView =
+ using EnableIfValueIsConst =
typename std::enable_if<std::is_const<T>::value, U>::type;
// Used to SFINAE-enable a function when the slice elements are mutable.
template <typename U>
- using EnableIfMutableView =
+ using EnableIfValueIsMutable =
typename std::enable_if<!std::is_const<T>::value, U>::type;
public:
@@ -196,13 +197,34 @@ class Span {
// Explicit reference constructor for a mutable `Span<T>` type. Can be
// replaced with MakeSpan() to infer the type parameter.
template <typename V, typename = EnableIfConvertibleFrom<V>,
- typename = EnableIfMutableView<V>>
- explicit Span(V& v) noexcept // NOLINT(runtime/references)
+ typename = EnableIfValueIsMutable<V>,
+ typename = span_internal::EnableIfNotIsView<V>>
+ explicit Span(
+ V& v
+ ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/references)
: Span(span_internal::GetData(v), v.size()) {}
// Implicit reference constructor for a read-only `Span<const T>` type
template <typename V, typename = EnableIfConvertibleFrom<V>,
- typename = EnableIfConstView<V>>
+ typename = EnableIfValueIsConst<V>,
+ typename = span_internal::EnableIfNotIsView<V>>
+ constexpr Span(
+ const V& v
+ ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit)
+ : Span(span_internal::GetData(v), v.size()) {}
+
+ // Overloads of the above two functions that are only enabled for view types.
+ // This is so we can drop the ABSL_ATTRIBUTE_LIFETIME_BOUND annotation. These
+ // overloads must be made unique by using a different template parameter list
+ // (hence the = 0 for the IsView enabler).
+ template <typename V, typename = EnableIfConvertibleFrom<V>,
+ typename = EnableIfValueIsMutable<V>,
+ span_internal::EnableIfIsView<V> = 0>
+ explicit Span(V& v) noexcept // NOLINT(runtime/references)
+ : Span(span_internal::GetData(v), v.size()) {}
+ template <typename V, typename = EnableIfConvertibleFrom<V>,
+ typename = EnableIfValueIsConst<V>,
+ span_internal::EnableIfIsView<V> = 0>
constexpr Span(const V& v) noexcept // NOLINT(runtime/explicit)
: Span(span_internal::GetData(v), v.size()) {}
@@ -242,7 +264,7 @@ class Span {
// Process(ints);
//
template <typename LazyT = T,
- typename = EnableIfConstView<LazyT>>
+ typename = EnableIfValueIsConst<LazyT>>
Span(std::initializer_list<value_type> v
ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit)
: Span(v.begin(), v.size()) {}
@@ -398,7 +420,7 @@ class Span {
// absl::MakeSpan(vec).subspan(5); // throws std::out_of_range
constexpr Span subspan(size_type pos = 0, size_type len = npos) const {
return (pos <= size())
- ? Span(data() + pos, span_internal::Min(size() - pos, len))
+ ? Span(data() + pos, (std::min)(size() - pos, len))
: (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
}