aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp
diff options
context:
space:
mode:
authormaxim-yurchuk <maxim-yurchuk@yandex-team.com>2024-10-09 12:29:46 +0300
committermaxim-yurchuk <maxim-yurchuk@yandex-team.com>2024-10-09 13:14:22 +0300
commit9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch)
treea8fb3181d5947c0d78cf402aa56e686130179049 /contrib/restricted/abseil-cpp
parenta44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff)
downloadydb-9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80.tar.gz
publishFullContrib: true for ydb
<HIDDEN_URL> commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/restricted/abseil-cpp')
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/__init__.py257
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report686
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report720
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/licenses.list.txt245
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/override.nix12
-rw-r--r--contrib/restricted/abseil-cpp/.yandex_meta/provides.pbtxt78
-rw-r--r--contrib/restricted/abseil-cpp/absl/algorithm/.yandex_meta/licenses.list.txt16
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/.yandex_meta/licenses.list.txt50
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h34
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/exception_safety_testing.h1109
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/exception_testing.h42
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/inline_variable_testing.h46
-rw-r--r--contrib/restricted/abseil-cpp/absl/base/internal/pretty_function.h33
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/.yandex_meta/licenses.list.txt28
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/btree_map.h889
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/btree_set.h824
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/btree_test.h166
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/btree.h3046
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/btree_container.h763
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hash_generator_testing.h182
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_testing.h183
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/hashtable_debug.h102
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/layout.h844
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/node_slot_policy.h95
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/test_allocator.h387
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/test_instance_tracker.h274
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/tracked.h83
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h494
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h117
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_members_test.h87
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h352
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h496
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h91
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_members_test.h86
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h221
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/node_hash_map.h663
-rw-r--r--contrib/restricted/abseil-cpp/absl/container/node_hash_set.h554
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/.yandex_meta/licenses.list.txt62
-rw-r--r--contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h50
-rw-r--r--contrib/restricted/abseil-cpp/absl/flags/.yandex_meta/licenses.list.txt24
-rw-r--r--contrib/restricted/abseil-cpp/absl/functional/.yandex_meta/licenses.list.txt24
-rw-r--r--contrib/restricted/abseil-cpp/absl/functional/bind_front.h194
-rw-r--r--contrib/restricted/abseil-cpp/absl/functional/internal/front_binder.h95
-rw-r--r--contrib/restricted/abseil-cpp/absl/functional/overload.h92
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/.yandex_meta/licenses.list.txt38
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/hash_testing.h378
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/internal/hash_test.h87
-rw-r--r--contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h266
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/.yandex_meta/licenses.list.txt38
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/check.h209
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/flags.h43
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/structured.h58
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/test_actions.h90
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/test_helpers.h71
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/internal/test_matchers.h94
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/log_streamer.h181
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h197
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/structured.h70
-rw-r--r--contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h72
-rw-r--r--contrib/restricted/abseil-cpp/absl/memory/.yandex_meta/licenses.list.txt16
-rw-r--r--contrib/restricted/abseil-cpp/absl/meta/.yandex_meta/licenses.list.txt16
-rw-r--r--contrib/restricted/abseil-cpp/absl/numeric/.yandex_meta/licenses.list.txt38
-rw-r--r--contrib/restricted/abseil-cpp/absl/profiling/.yandex_meta/licenses.list.txt34
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/.yandex_meta/licenses.list.txt42
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/beta_distribution.h427
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h187
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/distributions.h452
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h165
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h95
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/explicit_seed_seq.h92
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/mock_helpers.h161
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h126
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/mock_validators.h98
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/nanobenchmark.h172
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/nonsecure_base.h161
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/pcg_engine.h287
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h264
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/sequence_urbg.h60
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h244
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h256
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/mock_distributions.h269
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h254
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h261
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/random.h189
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h202
-rw-r--r--contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h272
-rw-r--r--contrib/restricted/abseil-cpp/absl/status/.yandex_meta/licenses.list.txt20
-rw-r--r--contrib/restricted/abseil-cpp/absl/status/internal/status_matchers.h246
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/.yandex_meta/licenses.list.txt54
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h122
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/cordz_test_helpers.h153
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_test_util.h205
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h133
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h184
-rw-r--r--contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h40
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/.yandex_meta/licenses.list.txt52
-rw-r--r--contrib/restricted/abseil-cpp/absl/synchronization/internal/thread_pool.h96
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/.yandex_meta/licenses.list.txt42
-rw-r--r--contrib/restricted/abseil-cpp/absl/time/internal/test_util.h33
-rw-r--r--contrib/restricted/abseil-cpp/absl/types/.yandex_meta/licenses.list.txt24
-rw-r--r--contrib/restricted/abseil-cpp/absl/types/any.h519
-rw-r--r--contrib/restricted/abseil-cpp/absl/utility/.yandex_meta/licenses.list.txt34
-rw-r--r--contrib/restricted/abseil-cpp/absl/utility/internal/if_constexpr.h70
-rw-r--r--contrib/restricted/abseil-cpp/patches/fix-cuda-10.patch11
-rw-r--r--contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch87
105 files changed, 23753 insertions, 0 deletions
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py b/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py
new file mode 100644
index 0000000000..e7c7f6d255
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/__init__.py
@@ -0,0 +1,257 @@
+from devtools.yamaker.modules import Library, Linkable, Switch, Words
+from devtools.yamaker.project import CMakeNinjaNixProject
+
+
+# These libraries are used to
+# * Fix building with ya make --checkout (see DTCC-615 for details)
+# * Implement unbunding of
+HEADER_ONLY_LIBS = {
+ "absl/algorithm",
+ "absl/functional",
+ "absl/memory",
+ "absl/meta",
+ "absl/utility",
+}
+
+
+def post_install(self):
+ for lib in HEADER_ONLY_LIBS:
+ assert lib not in self.yamakes
+ self.yamakes[lib] = self.module(
+ Library,
+ NO_RUNTIME=True,
+ )
+
+ with self.yamakes["absl/time"] as m:
+ m.after(
+ "ADDINCL",
+ Switch(
+ {
+ "OS_DARWIN OR OS_IOS": Linkable(EXTRALIBS=[Words("-framework CoreFoundation")]),
+ }
+ ),
+ )
+
+ with self.yamakes["absl/log"] as log:
+ log.after(
+ "ADDINCL",
+ Switch(
+ OS_ANDROID=Linkable(LDFLAGS=["-llog"]),
+ ),
+ )
+
+ # fix (not yet automatically discoverable) dependencies on header-only parts of abseil
+ self.yamakes["absl/container"].PEERDIR |= {
+ f"{self.arcdir}/absl/types",
+ f"{self.arcdir}/absl/hash",
+ f"{self.arcdir}/absl/memory",
+ }
+
+ self.yamakes["absl/meta"].PEERDIR |= {
+ f"{self.arcdir}/absl/base",
+ }
+
+ self.yamakes["absl/memory"].PEERDIR |= {
+ f"{self.arcdir}/absl/meta",
+ }
+
+ self.yamakes["absl/debugging"].PEERDIR -= {
+ f"{self.arcdir}/absl/strings",
+ f"{self.arcdir}/absl/numeric",
+ f"{self.arcdir}/absl/demangle",
+ }
+ self.yamakes["absl/strings"].PEERDIR -= {
+ f"{self.arcdir}/absl/debugging",
+ f"{self.arcdir}/absl/demangle",
+ f"{self.arcdir}/absl/profiling",
+ f"{self.arcdir}/absl/status",
+ f"{self.arcdir}/absl/synchronization",
+ f"{self.arcdir}/absl/time",
+ f"{self.arcdir}/absl/types",
+ }
+ self.yamakes["absl/hash"].PEERDIR |= {
+ f"{self.arcdir}/absl/types",
+ }
+ self.yamakes["absl/flags"].PEERDIR |= {
+ f"{self.arcdir}/absl/memory",
+ }
+ self.yamakes["absl/types"].PEERDIR |= {
+ f"{self.arcdir}/absl/memory",
+ }
+
+ self.yamakes["absl/base"].PEERDIR.add("library/cpp/sanitizer/include")
+ self.yamakes["absl/debugging"].PEERDIR.add("library/cpp/sanitizer/include")
+ self.yamakes["absl/container"].PEERDIR.add("library/cpp/sanitizer/include")
+
+ with self.yamakes["."] as m:
+ lib = self.module(
+ Library,
+ PEERDIR={f"{self.arcdir}/{inc}" for inc in m.RECURSE},
+ RECURSE=m.RECURSE,
+ NO_RUNTIME=True,
+ )
+ for extra_lib in HEADER_ONLY_LIBS:
+ lib.PEERDIR.add(f"{self.arcdir}/{extra_lib}")
+ lib.RECURSE.add(extra_lib)
+
+ self.yamakes["."] = lib
+
+
+abseil_cpp = CMakeNinjaNixProject(
+ owners=["g:cpp-contrib"],
+ arcdir="contrib/restricted/abseil-cpp",
+ nixattr="abseil-cpp",
+ disable_includes=[
+ "emscripten.h",
+ "emscripten/*.h",
+ # if defined(__myriad2__)
+ "rtems.h",
+ # if defined(__Fuchsia__)
+ "fuchsia/intl/cpp/fidl.h",
+ "lib/async-loop/cpp/loop.h",
+ "lib/fdio/directory.h",
+ "lib/sys/cpp/component_context.h",
+ "zircon/types.h",
+ ],
+ copy_sources=[
+ "absl/base/internal/*.inc",
+ "absl/flags/internal/*.inc",
+ "absl/synchronization/internal/*.inc",
+ "absl/numeric/int128_no_intrinsic.inc",
+ "absl/debugging/internal/*.inc",
+ "absl/debugging/*.inc",
+ "absl/strings/internal/stl_type_traits.h",
+ "absl/time/internal/*.inc",
+ "absl/**/*.h",
+ ],
+ ignore_targets=[
+ # these depend on gtest, ignore it.
+ "absl_scoped_mock_log",
+ "absl_status_matchers",
+ ],
+ copy_sources_except=[
+ "absl/status/status_matchers.h",
+ ],
+ put={
+ "absl_bad_any_cast_impl": "absl/types",
+ "absl_base": "absl/base",
+ "absl_debugging_internal": "absl/debugging",
+ "absl_flags_internal": "absl/flags",
+ "absl_hash": "absl/hash",
+ "absl_int128": "absl/numeric",
+ "absl_log_entry": "absl/log",
+ "absl_periodic_sampler": "absl/profiling",
+ "absl_random_distributions": "absl/random",
+ "absl_raw_hash_set": "absl/container",
+ "absl_status": "absl/status",
+ "absl_strings": "absl/strings",
+ "absl_synchronization": "absl/synchronization",
+ "absl_time": "absl/time",
+ },
+ put_with={
+ "absl_bad_any_cast_impl": [
+ "absl_bad_optional_access",
+ "absl_bad_variant_access",
+ ],
+ "absl_base": [
+ "absl_log_severity",
+ "absl_malloc_internal",
+ "absl_poison",
+ "absl_raw_logging_internal",
+ "absl_scoped_set_env",
+ "absl_spinlock_wait",
+ "absl_strerror",
+ "absl_throw_delegate",
+ ],
+ "absl_debugging_internal": [
+ "absl_decode_rust_punycode",
+ "absl_demangle_internal",
+ "absl_demangle_rust",
+ "absl_examine_stack",
+ "absl_failure_signal_handler",
+ "absl_leak_check",
+ "absl_stacktrace",
+ "absl_symbolize",
+ "absl_utf8_for_code_point",
+ ],
+ "absl_flags_internal": [
+ "absl_flags_commandlineflag",
+ "absl_flags_commandlineflag_internal",
+ "absl_flags_config",
+ "absl_flags_marshalling",
+ "absl_flags_parse",
+ "absl_flags_private_handle_accessor",
+ "absl_flags_program_name",
+ "absl_flags_reflection",
+ "absl_flags_usage",
+ "absl_flags_usage_internal",
+ ],
+ "absl_hash": [
+ "absl_low_level_hash",
+ "absl_city",
+ ],
+ "absl_log_entry": [
+ "absl_die_if_null",
+ "absl_log_flags",
+ "absl_log_globals",
+ "absl_log_initialize",
+ "absl_log_internal_check_op",
+ "absl_log_internal_conditions",
+ "absl_log_internal_fnmatch",
+ "absl_log_internal_format",
+ "absl_log_internal_globals",
+ "absl_log_internal_log_sink_set",
+ "absl_log_internal_message",
+ "absl_log_internal_nullguard",
+ "absl_log_internal_proto",
+ "absl_log_sink",
+ "absl_vlog_config_internal",
+ ],
+ "absl_periodic_sampler": [
+ "absl_exponential_biased",
+ ],
+ "absl_random_distributions": [
+ "absl_random_internal_distribution_test_util",
+ "absl_random_internal_platform",
+ "absl_random_internal_pool_urbg",
+ "absl_random_internal_randen",
+ "absl_random_internal_randen_hwaes",
+ "absl_random_internal_randen_hwaes_impl",
+ "absl_random_internal_randen_slow",
+ "absl_random_internal_seed_material",
+ "absl_random_seed_gen_exception",
+ "absl_random_seed_sequences",
+ ],
+ "absl_raw_hash_set": [
+ "absl_hashtablez_sampler",
+ ],
+ "absl_strings": [
+ # FIXME thegeorg@:
+ # put crc libraries together with strings libraries
+ # to resolve dependency loop around absl_crc_cor
+ "absl_crc32c",
+ "absl_crc_cpu_detect",
+ "absl_crc_internal",
+ "absl_crc_cord_state",
+ "absl_cord",
+ "absl_cord_internal",
+ "absl_cordz_functions",
+ "absl_cordz_handle",
+ "absl_cordz_info",
+ "absl_cordz_sample_token",
+ "absl_statusor",
+ "absl_string_view",
+ "absl_strings_internal",
+ "absl_str_format_internal",
+ ],
+ "absl_synchronization": [
+ "absl_graphcycles_internal",
+ "absl_kernel_timeout_internal",
+ ],
+ "absl_time": [
+ "absl_civil_time",
+ "absl_time_zone",
+ ],
+ },
+ post_install=post_install,
+)
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report
new file mode 100644
index 0000000000..1d1da6829f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.copyrights.report
@@ -0,0 +1,686 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP COPYRIGHT_SERVICE_LABEL 02e3ff10f74acdb217118846c5465fc1
+BELONGS absl/algorithm/ya.make absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/memory/ya.make absl/meta/ya.make absl/numeric/ya.make absl/random/ya.make absl/strings/ya.make absl/synchronization/ya.make absl/time/ya.make absl/types/ya.make absl/utility/ya.make
+ License text:
+ // Copyright 2017 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/algorithm/algorithm.h [1:1]
+ absl/algorithm/container.h [1:1]
+ absl/base/attributes.h [1:1]
+ absl/base/call_once.h [1:1]
+ absl/base/casts.h [2:2]
+ absl/base/config.h [2:2]
+ absl/base/const_init.h [1:1]
+ absl/base/dynamic_annotations.h [1:1]
+ absl/base/internal/atomic_hook.h [1:1]
+ absl/base/internal/atomic_hook_test_helper.h [1:1]
+ absl/base/internal/cycleclock.cc [1:1]
+ absl/base/internal/cycleclock.h [2:2]
+ absl/base/internal/direct_mmap.h [1:1]
+ absl/base/internal/dynamic_annotations.h [1:1]
+ absl/base/internal/endian.h [1:1]
+ absl/base/internal/errno_saver.h [1:1]
+ absl/base/internal/exception_safety_testing.h [1:1]
+ absl/base/internal/exception_testing.h [1:1]
+ absl/base/internal/identity.h [1:1]
+ absl/base/internal/inline_variable.h [1:1]
+ absl/base/internal/inline_variable_testing.h [1:1]
+ absl/base/internal/invoke.h [1:1]
+ absl/base/internal/low_level_alloc.cc [1:1]
+ absl/base/internal/low_level_alloc.h [1:1]
+ absl/base/internal/low_level_scheduling.h [1:1]
+ absl/base/internal/per_thread_tls.h [1:1]
+ absl/base/internal/pretty_function.h [1:1]
+ absl/base/internal/raw_logging.cc [1:1]
+ absl/base/internal/raw_logging.h [1:1]
+ absl/base/internal/scheduling_mode.h [1:1]
+ absl/base/internal/spinlock.cc [1:1]
+ absl/base/internal/spinlock.h [2:2]
+ absl/base/internal/spinlock_akaros.inc [1:1]
+ absl/base/internal/spinlock_posix.inc [1:1]
+ absl/base/internal/spinlock_wait.cc [1:1]
+ absl/base/internal/spinlock_wait.h [1:1]
+ absl/base/internal/spinlock_win32.inc [1:1]
+ absl/base/internal/sysinfo.cc [1:1]
+ absl/base/internal/sysinfo.h [1:1]
+ absl/base/internal/thread_identity.cc [1:1]
+ absl/base/internal/thread_identity.h [1:1]
+ absl/base/internal/throw_delegate.cc [1:1]
+ absl/base/internal/throw_delegate.h [2:2]
+ absl/base/internal/tsan_mutex_interface.h [1:1]
+ absl/base/internal/unaligned_access.h [2:2]
+ absl/base/internal/unscaledcycleclock.cc [1:1]
+ absl/base/internal/unscaledcycleclock.h [1:1]
+ absl/base/log_severity.cc [1:1]
+ absl/base/log_severity.h [1:1]
+ absl/base/macros.h [2:2]
+ absl/base/optimization.h [2:2]
+ absl/base/policy_checks.h [1:1]
+ absl/base/port.h [1:1]
+ absl/base/thread_annotations.h [1:1]
+ absl/container/internal/test_instance_tracker.h [1:1]
+ absl/debugging/internal/address_is_readable.cc [1:1]
+ absl/debugging/internal/address_is_readable.h [1:1]
+ absl/debugging/internal/elf_mem_image.cc [1:1]
+ absl/debugging/internal/elf_mem_image.h [2:2]
+ absl/debugging/internal/stacktrace_arm-inl.inc [1:1]
+ absl/debugging/internal/stacktrace_config.h [2:2]
+ absl/debugging/internal/stacktrace_emscripten-inl.inc [1:1]
+ absl/debugging/internal/stacktrace_generic-inl.inc [1:1]
+ absl/debugging/internal/stacktrace_powerpc-inl.inc [1:1]
+ absl/debugging/internal/stacktrace_win32-inl.inc [1:1]
+ absl/debugging/internal/stacktrace_x86-inl.inc [1:1]
+ absl/debugging/internal/vdso_support.cc [1:1]
+ absl/debugging/internal/vdso_support.h [2:2]
+ absl/debugging/leak_check.cc [1:1]
+ absl/debugging/stacktrace.cc [1:1]
+ absl/memory/memory.h [1:1]
+ absl/meta/type_traits.h [2:2]
+ absl/numeric/int128.cc [1:1]
+ absl/numeric/int128.h [2:2]
+ absl/numeric/int128_have_intrinsic.inc [2:2]
+ absl/numeric/int128_no_intrinsic.inc [2:2]
+ absl/random/bernoulli_distribution.h [1:1]
+ absl/random/beta_distribution.h [1:1]
+ absl/random/discrete_distribution.cc [1:1]
+ absl/random/discrete_distribution.h [1:1]
+ absl/random/distributions.h [1:1]
+ absl/random/exponential_distribution.h [1:1]
+ absl/random/gaussian_distribution.h [1:1]
+ absl/random/internal/chi_square.cc [1:1]
+ absl/random/internal/chi_square.h [1:1]
+ absl/random/internal/distribution_test_util.cc [1:1]
+ absl/random/internal/distribution_test_util.h [1:1]
+ absl/random/internal/explicit_seed_seq.h [1:1]
+ absl/random/internal/fast_uniform_bits.h [1:1]
+ absl/random/internal/fastmath.h [1:1]
+ absl/random/internal/generate_real.h [1:1]
+ absl/random/internal/iostream_state_saver.h [1:1]
+ absl/random/internal/nonsecure_base.h [1:1]
+ absl/random/internal/platform.h [1:1]
+ absl/random/internal/pool_urbg.cc [1:1]
+ absl/random/internal/pool_urbg.h [1:1]
+ absl/random/internal/randen.cc [1:1]
+ absl/random/internal/randen.h [1:1]
+ absl/random/internal/randen_detect.cc [1:1]
+ absl/random/internal/randen_detect.h [1:1]
+ absl/random/internal/randen_engine.h [1:1]
+ absl/random/internal/randen_hwaes.cc [1:1]
+ absl/random/internal/randen_hwaes.h [1:1]
+ absl/random/internal/randen_round_keys.cc [1:1]
+ absl/random/internal/randen_slow.cc [1:1]
+ absl/random/internal/randen_slow.h [1:1]
+ absl/random/internal/randen_traits.h [1:1]
+ absl/random/internal/salted_seed_seq.h [1:1]
+ absl/random/internal/seed_material.cc [1:1]
+ absl/random/internal/seed_material.h [1:1]
+ absl/random/internal/sequence_urbg.h [1:1]
+ absl/random/internal/traits.h [1:1]
+ absl/random/internal/wide_multiply.h [1:1]
+ absl/random/log_uniform_int_distribution.h [1:1]
+ absl/random/poisson_distribution.h [1:1]
+ absl/random/random.h [1:1]
+ absl/random/seed_gen_exception.cc [1:1]
+ absl/random/seed_gen_exception.h [1:1]
+ absl/random/seed_sequences.cc [1:1]
+ absl/random/seed_sequences.h [1:1]
+ absl/random/uniform_int_distribution.h [1:1]
+ absl/random/uniform_real_distribution.h [1:1]
+ absl/random/zipf_distribution.h [1:1]
+ absl/strings/ascii.cc [1:1]
+ absl/strings/ascii.h [2:2]
+ absl/strings/escaping.cc [1:1]
+ absl/strings/escaping.h [2:2]
+ absl/strings/internal/escaping_test_common.h [1:1]
+ absl/strings/internal/memutil.cc [1:1]
+ absl/strings/internal/memutil.h [2:2]
+ absl/strings/internal/numbers_test_common.h [1:1]
+ absl/strings/internal/ostringstream.cc [1:1]
+ absl/strings/internal/ostringstream.h [1:1]
+ absl/strings/internal/resize_uninitialized.h [2:2]
+ absl/strings/internal/stl_type_traits.h [1:1]
+ absl/strings/internal/str_format/extension.cc [2:2]
+ absl/strings/internal/str_format/extension.h [2:2]
+ absl/strings/internal/str_format/output.cc [1:1]
+ absl/strings/internal/str_format/output.h [1:1]
+ absl/strings/internal/str_join_internal.h [2:2]
+ absl/strings/internal/str_split_internal.h [1:1]
+ absl/strings/internal/utf8.cc [1:1]
+ absl/strings/internal/utf8.h [1:1]
+ absl/strings/match.cc [1:1]
+ absl/strings/match.h [2:2]
+ absl/strings/numbers.cc [1:1]
+ absl/strings/numbers.h [1:1]
+ absl/strings/str_cat.cc [1:1]
+ absl/strings/str_cat.h [2:2]
+ absl/strings/str_join.h [2:2]
+ absl/strings/str_replace.cc [1:1]
+ absl/strings/str_replace.h [2:2]
+ absl/strings/str_split.cc [1:1]
+ absl/strings/str_split.h [2:2]
+ absl/strings/string_view.cc [1:1]
+ absl/strings/string_view.h [2:2]
+ absl/strings/strip.h [2:2]
+ absl/strings/substitute.cc [1:1]
+ absl/strings/substitute.h [2:2]
+ absl/synchronization/barrier.cc [1:1]
+ absl/synchronization/barrier.h [1:1]
+ absl/synchronization/blocking_counter.cc [1:1]
+ absl/synchronization/blocking_counter.h [2:2]
+ absl/synchronization/internal/create_thread_identity.cc [1:1]
+ absl/synchronization/internal/create_thread_identity.h [2:2]
+ absl/synchronization/internal/graphcycles.cc [1:1]
+ absl/synchronization/internal/graphcycles.h [1:1]
+ absl/synchronization/internal/kernel_timeout.h [1:1]
+ absl/synchronization/internal/per_thread_sem.cc [1:1]
+ absl/synchronization/internal/per_thread_sem.h [1:1]
+ absl/synchronization/internal/thread_pool.h [1:1]
+ absl/synchronization/internal/waiter.h [1:1]
+ absl/synchronization/mutex.cc [1:1]
+ absl/synchronization/mutex.h [1:1]
+ absl/synchronization/notification.cc [1:1]
+ absl/synchronization/notification.h [1:1]
+ absl/time/clock.cc [1:1]
+ absl/time/clock.h [1:1]
+ absl/time/duration.cc [1:1]
+ absl/time/format.cc [1:1]
+ absl/time/internal/test_util.h [1:1]
+ absl/time/time.cc [1:1]
+ absl/time/time.h [1:1]
+ absl/types/any.h [2:2]
+ absl/types/bad_any_cast.cc [1:1]
+ absl/types/bad_optional_access.cc [1:1]
+ absl/types/bad_variant_access.cc [1:1]
+ absl/types/internal/optional.h [1:1]
+ absl/types/optional.h [1:1]
+ absl/types/span.h [2:2]
+ absl/utility/utility.h [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL 05bdd09fb9fdb384a61f2eb54df462d6
+BELONGS absl/time/ya.make
+ License text:
+ // Copyright 2016 Google Inc. All Rights Reserved.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/time/internal/cctz/include/cctz/civil_time.h [1:1]
+ absl/time/internal/cctz/include/cctz/civil_time_detail.h [1:1]
+ absl/time/internal/cctz/include/cctz/time_zone.h [1:1]
+ absl/time/internal/cctz/include/cctz/zone_info_source.h [1:1]
+ absl/time/internal/cctz/src/civil_time_detail.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_fixed.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_fixed.h [1:1]
+ absl/time/internal/cctz/src/time_zone_format.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_if.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_if.h [1:1]
+ absl/time/internal/cctz/src/time_zone_impl.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_impl.h [1:1]
+ absl/time/internal/cctz/src/time_zone_info.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_info.h [1:1]
+ absl/time/internal/cctz/src/time_zone_libc.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_libc.h [1:1]
+ absl/time/internal/cctz/src/time_zone_lookup.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_posix.cc [1:1]
+ absl/time/internal/cctz/src/time_zone_posix.h [1:1]
+ absl/time/internal/cctz/src/zone_info_source.cc [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL 0ab55d6d498e0bb4faaf59c66546fbc5
+BELONGS absl/base/ya.make absl/hash/ya.make absl/log/ya.make absl/synchronization/ya.make absl/utility/ya.make
+ License text:
+ // Copyright 2023 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/nullability_impl.h [1:1]
+ absl/base/no_destructor.h [1:1]
+ absl/base/nullability.h [1:1]
+ absl/base/prefetch.h [1:1]
+ absl/functional/overload.h [1:1]
+ absl/hash/internal/hash_test.h [1:1]
+ absl/log/internal/fnmatch.cc [1:1]
+ absl/log/internal/fnmatch.h [1:1]
+ absl/log/internal/nullguard.cc [1:1]
+ absl/status/internal/status_internal.cc [1:1]
+ absl/strings/has_ostream_operator.h [1:1]
+ absl/synchronization/internal/futex_waiter.cc [1:1]
+ absl/synchronization/internal/futex_waiter.h [1:1]
+ absl/synchronization/internal/kernel_timeout.cc [1:1]
+ absl/synchronization/internal/pthread_waiter.cc [1:1]
+ absl/synchronization/internal/pthread_waiter.h [1:1]
+ absl/synchronization/internal/sem_waiter.cc [1:1]
+ absl/synchronization/internal/sem_waiter.h [1:1]
+ absl/synchronization/internal/stdcpp_waiter.cc [1:1]
+ absl/synchronization/internal/stdcpp_waiter.h [1:1]
+ absl/synchronization/internal/waiter_base.cc [1:1]
+ absl/synchronization/internal/waiter_base.h [1:1]
+ absl/synchronization/internal/win32_waiter.cc [1:1]
+ absl/synchronization/internal/win32_waiter.h [1:1]
+ absl/utility/internal/if_constexpr.h [1:1]
+ Belongs difference:
+ - absl/functional/ya.make absl/status/ya.make absl/strings/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL 2277624a2da390a98ec17138cb6dc2a5
+BELONGS absl/base/ya.make absl/container/ya.make absl/flags/ya.make absl/functional/ya.make absl/profiling/ya.make absl/random/ya.make absl/status/ya.make absl/strings/ya.make absl/types/ya.make
+ License text:
+ // Copyright 2019 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/scoped_set_env.cc [1:1]
+ absl/base/internal/scoped_set_env.h [2:2]
+ absl/base/options.h [1:1]
+ absl/container/inlined_vector.h [1:1]
+ absl/container/internal/inlined_vector.h [1:1]
+ absl/container/internal/unordered_map_members_test.h [1:1]
+ absl/container/internal/unordered_set_members_test.h [1:1]
+ absl/flags/config.h [2:2]
+ absl/flags/declare.h [2:2]
+ absl/flags/flag.h [2:2]
+ absl/flags/internal/commandlineflag.h [2:2]
+ absl/flags/internal/flag.cc [2:2]
+ absl/flags/internal/flag.h [2:2]
+ absl/flags/internal/parse.h [2:2]
+ absl/flags/internal/path_util.h [2:2]
+ absl/flags/internal/program_name.cc [2:2]
+ absl/flags/internal/program_name.h [2:2]
+ absl/flags/internal/registry.h [2:2]
+ absl/flags/internal/usage.cc [2:2]
+ absl/flags/internal/usage.h [2:2]
+ absl/flags/marshalling.cc [2:2]
+ absl/flags/marshalling.h [2:2]
+ absl/flags/parse.cc [2:2]
+ absl/flags/parse.h [2:2]
+ absl/flags/usage.cc [2:2]
+ absl/flags/usage.h [2:2]
+ absl/flags/usage_config.cc [2:2]
+ absl/flags/usage_config.h [2:2]
+ absl/functional/function_ref.h [1:1]
+ absl/functional/internal/function_ref.h [1:1]
+ absl/profiling/internal/exponential_biased.cc [1:1]
+ absl/profiling/internal/exponential_biased.h [1:1]
+ absl/profiling/internal/periodic_sampler.cc [1:1]
+ absl/profiling/internal/periodic_sampler.h [1:1]
+ absl/random/internal/mock_helpers.h [2:2]
+ absl/random/internal/mock_overload_set.h [2:2]
+ absl/random/internal/uniform_helper.h [1:1]
+ absl/status/internal/status_internal.h [1:1]
+ absl/status/status.cc [1:1]
+ absl/status/status.h [1:1]
+ absl/status/status_payload_printer.cc [1:1]
+ absl/status/status_payload_printer.h [1:1]
+ absl/strings/internal/cordz_functions.cc [1:1]
+ absl/strings/internal/cordz_functions.h [1:1]
+ absl/strings/internal/cordz_handle.cc [1:1]
+ absl/strings/internal/cordz_handle.h [1:1]
+ absl/strings/internal/cordz_info.cc [1:1]
+ absl/strings/internal/cordz_info.h [1:1]
+ absl/strings/internal/cordz_sample_token.cc [1:1]
+ absl/strings/internal/cordz_sample_token.h [1:1]
+ absl/strings/internal/cordz_statistics.h [1:1]
+ absl/types/internal/span.h [2:2]
+
+KEEP COPYRIGHT_SERVICE_LABEL 3fb410b721d46624abdaeb2473ffa5d6
+BELONGS absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/functional/ya.make absl/hash/ya.make absl/profiling/ya.make absl/random/ya.make absl/strings/ya.make absl/time/ya.make absl/types/ya.make
+ License text:
+ // Copyright 2018 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/hide_ptr.h [1:1]
+ absl/base/internal/spinlock_linux.inc [1:1]
+ absl/container/btree_map.h [1:1]
+ absl/container/btree_set.h [1:1]
+ absl/container/btree_test.h [1:1]
+ absl/container/fixed_array.h [1:1]
+ absl/container/flat_hash_map.h [1:1]
+ absl/container/flat_hash_set.h [1:1]
+ absl/container/internal/btree.h [1:1]
+ absl/container/internal/btree_container.h [1:1]
+ absl/container/internal/common.h [1:1]
+ absl/container/internal/compressed_tuple.h [1:1]
+ absl/container/internal/container_memory.h [1:1]
+ absl/container/internal/hash_function_defaults.h [1:1]
+ absl/container/internal/hash_generator_testing.h [1:1]
+ absl/container/internal/hash_policy_testing.h [1:1]
+ absl/container/internal/hash_policy_traits.h [1:1]
+ absl/container/internal/hashtable_debug.h [1:1]
+ absl/container/internal/hashtable_debug_hooks.h [1:1]
+ absl/container/internal/hashtablez_sampler.cc [1:1]
+ absl/container/internal/hashtablez_sampler.h [1:1]
+ absl/container/internal/hashtablez_sampler_force_weak_definition.cc [1:1]
+ absl/container/internal/layout.h [1:1]
+ absl/container/internal/node_slot_policy.h [1:1]
+ absl/container/internal/raw_hash_map.h [1:1]
+ absl/container/internal/raw_hash_set.cc [1:1]
+ absl/container/internal/raw_hash_set.h [1:1]
+ absl/container/internal/test_allocator.h [1:1]
+ absl/container/internal/tracked.h [1:1]
+ absl/container/internal/unordered_map_constructor_test.h [1:1]
+ absl/container/internal/unordered_map_lookup_test.h [1:1]
+ absl/container/internal/unordered_map_modifiers_test.h [1:1]
+ absl/container/internal/unordered_set_constructor_test.h [1:1]
+ absl/container/internal/unordered_set_lookup_test.h [1:1]
+ absl/container/internal/unordered_set_modifiers_test.h [1:1]
+ absl/container/node_hash_map.h [1:1]
+ absl/container/node_hash_set.h [1:1]
+ absl/debugging/failure_signal_handler.cc [2:2]
+ absl/debugging/failure_signal_handler.h [1:1]
+ absl/debugging/internal/demangle.cc [1:1]
+ absl/debugging/internal/demangle.h [1:1]
+ absl/debugging/internal/examine_stack.cc [2:2]
+ absl/debugging/internal/examine_stack.h [2:2]
+ absl/debugging/internal/stack_consumption.h [2:2]
+ absl/debugging/internal/symbolize.h [1:1]
+ absl/debugging/leak_check.h [1:1]
+ absl/debugging/stacktrace.h [1:1]
+ absl/debugging/symbolize.cc [1:1]
+ absl/debugging/symbolize.h [1:1]
+ absl/debugging/symbolize_elf.inc [1:1]
+ absl/debugging/symbolize_unimplemented.inc [1:1]
+ absl/debugging/symbolize_win32.inc [1:1]
+ absl/functional/bind_front.h [1:1]
+ absl/functional/internal/front_binder.h [1:1]
+ absl/hash/hash.h [1:1]
+ absl/hash/hash_testing.h [1:1]
+ absl/hash/internal/city.cc [1:1]
+ absl/hash/internal/city.h [1:1]
+ absl/hash/internal/hash.cc [1:1]
+ absl/hash/internal/hash.h [1:1]
+ absl/hash/internal/spy_hash_state.h [1:1]
+ absl/profiling/internal/sample_recorder.h [1:1]
+ absl/random/bit_gen_ref.h [2:2]
+ absl/random/internal/distribution_caller.h [2:2]
+ absl/random/internal/pcg_engine.h [1:1]
+ absl/random/mock_distributions.h [1:1]
+ absl/random/mocking_bit_gen.h [1:1]
+ absl/strings/charconv.cc [1:1]
+ absl/strings/charconv.h [1:1]
+ absl/strings/cord_test_helpers.h [2:2]
+ absl/strings/internal/charconv_bigint.cc [1:1]
+ absl/strings/internal/charconv_bigint.h [1:1]
+ absl/strings/internal/charconv_parse.cc [1:1]
+ absl/strings/internal/charconv_parse.h [1:1]
+ absl/strings/internal/pow10_helper.h [2:2]
+ absl/strings/str_format.h [2:2]
+ absl/time/civil_time.cc [1:1]
+ absl/time/civil_time.h [1:1]
+ absl/time/internal/get_current_time_chrono.inc [1:1]
+ absl/types/bad_any_cast.h [1:1]
+ absl/types/bad_optional_access.h [1:1]
+ absl/types/bad_variant_access.h [1:1]
+ absl/types/compare.h [1:1]
+ absl/types/internal/variant.h [1:1]
+ absl/types/variant.h [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL 58e60221a225d38384f3c66b2400cc91
+BELONGS absl/debugging/ya.make absl/flags/ya.make absl/numeric/ya.make absl/strings/ya.make ya.make
+ License text:
+ // Copyright 2021 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/cleanup/cleanup.h [1:1]
+ absl/cleanup/internal/cleanup.h [1:1]
+ absl/debugging/internal/stacktrace_riscv-inl.inc [1:1]
+ absl/numeric/internal/representation.h [1:1]
+ absl/strings/cord_analysis.cc [1:1]
+ absl/strings/cord_analysis.h [1:1]
+ absl/strings/cord_buffer.h [1:1]
+ absl/strings/cordz_test_helpers.h [1:1]
+ absl/strings/internal/cord_internal.h [1:1]
+ absl/strings/internal/cord_rep_btree.cc [1:1]
+ absl/strings/internal/cord_rep_btree.h [1:1]
+ absl/strings/internal/cord_rep_btree_navigator.cc [1:1]
+ absl/strings/internal/cord_rep_btree_navigator.h [1:1]
+ absl/strings/internal/cord_rep_btree_reader.cc [1:1]
+ absl/strings/internal/cord_rep_btree_reader.h [1:1]
+ absl/strings/internal/cord_rep_consume.cc [1:1]
+ absl/strings/internal/cord_rep_consume.h [1:1]
+ absl/strings/internal/cord_rep_crc.cc [1:1]
+ absl/strings/internal/cord_rep_crc.h [1:1]
+ absl/strings/internal/cord_rep_test_util.h [1:1]
+ absl/strings/internal/cordz_update_scope.h [1:1]
+ absl/strings/internal/cordz_update_tracker.h [1:1]
+ Belongs difference:
+ + absl/flags/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL 6499e2ad737f62db5558c81fbd2749a7
+BELONGS absl/random/ya.make
+ License text:
+ // Copyright 2017 Google Inc. All Rights Reserved.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/random/internal/nanobenchmark.h [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL 79f032533180bf3f602e8ed67e6258aa
+BELONGS absl/base/ya.make absl/container/ya.make absl/functional/ya.make absl/log/ya.make absl/strings/ya.make ya.make
+ License text:
+ // Copyright 2022 The Abseil Authors
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/cycleclock_config.h [1:1]
+ absl/base/internal/unscaledcycleclock_config.h [1:1]
+ absl/container/internal/common_policy_traits.h [1:1]
+ absl/crc/crc32c.cc [1:1]
+ absl/crc/crc32c.h [1:1]
+ absl/crc/internal/cpu_detect.cc [1:1]
+ absl/crc/internal/cpu_detect.h [1:1]
+ absl/crc/internal/crc.cc [1:1]
+ absl/crc/internal/crc.h [1:1]
+ absl/crc/internal/crc32_x86_arm_combined_simd.h [1:1]
+ absl/crc/internal/crc32c.h [1:1]
+ absl/crc/internal/crc32c_inline.h [1:1]
+ absl/crc/internal/crc_cord_state.cc [1:1]
+ absl/crc/internal/crc_cord_state.h [1:1]
+ absl/crc/internal/crc_internal.h [1:1]
+ absl/crc/internal/crc_memcpy.h [1:1]
+ absl/crc/internal/crc_memcpy_fallback.cc [1:1]
+ absl/crc/internal/crc_memcpy_x86_arm_combined.cc [1:1]
+ absl/crc/internal/crc_non_temporal_memcpy.cc [1:1]
+ absl/crc/internal/crc_x86_arm_combined.cc [1:1]
+ absl/crc/internal/non_temporal_arm_intrinsics.h [1:1]
+ absl/crc/internal/non_temporal_memcpy.h [1:1]
+ absl/functional/any_invocable.h [1:1]
+ absl/functional/internal/any_invocable.h [1:1]
+ absl/log/absl_check.h [1:1]
+ absl/log/absl_log.h [1:1]
+ absl/log/absl_vlog_is_on.h [1:1]
+ absl/log/check.h [1:1]
+ absl/log/die_if_null.cc [1:1]
+ absl/log/die_if_null.h [1:1]
+ absl/log/flags.cc [2:2]
+ absl/log/flags.h [1:1]
+ absl/log/globals.cc [1:1]
+ absl/log/globals.h [1:1]
+ absl/log/initialize.cc [1:1]
+ absl/log/initialize.h [1:1]
+ absl/log/internal/append_truncated.h [1:1]
+ absl/log/internal/check_impl.h [1:1]
+ absl/log/internal/check_op.cc [1:1]
+ absl/log/internal/check_op.h [1:1]
+ absl/log/internal/conditions.cc [1:1]
+ absl/log/internal/conditions.h [1:1]
+ absl/log/internal/config.h [1:1]
+ absl/log/internal/flags.h [1:1]
+ absl/log/internal/globals.cc [1:1]
+ absl/log/internal/globals.h [1:1]
+ absl/log/internal/log_format.cc [2:2]
+ absl/log/internal/log_format.h [1:1]
+ absl/log/internal/log_impl.h [1:1]
+ absl/log/internal/log_message.cc [2:2]
+ absl/log/internal/log_message.h [1:1]
+ absl/log/internal/log_sink_set.cc [2:2]
+ absl/log/internal/log_sink_set.h [1:1]
+ absl/log/internal/nullguard.h [1:1]
+ absl/log/internal/nullstream.h [1:1]
+ absl/log/internal/strip.h [1:1]
+ absl/log/internal/structured.h [1:1]
+ absl/log/internal/test_actions.h [1:1]
+ absl/log/internal/test_helpers.h [1:1]
+ absl/log/internal/test_matchers.h [1:1]
+ absl/log/internal/vlog_config.cc [1:1]
+ absl/log/internal/vlog_config.h [1:1]
+ absl/log/internal/voidify.h [1:1]
+ absl/log/log.h [1:1]
+ absl/log/log_entry.cc [2:2]
+ absl/log/log_entry.h [1:1]
+ absl/log/log_sink.cc [1:1]
+ absl/log/log_sink.h [1:1]
+ absl/log/log_sink_registry.h [1:1]
+ absl/log/log_streamer.h [1:1]
+ absl/log/scoped_mock_log.h [1:1]
+ absl/log/structured.h [1:1]
+ absl/log/vlog_is_on.h [1:1]
+ absl/strings/charset.h [1:1]
+ absl/strings/cord_buffer.cc [1:1]
+ absl/strings/has_absl_stringify.h [1:1]
+ absl/strings/internal/cord_data_edge.h [1:1]
+ absl/strings/internal/damerau_levenshtein_distance.cc [1:1]
+ absl/strings/internal/damerau_levenshtein_distance.h [1:1]
+ absl/strings/internal/str_format/constexpr_parser.h [1:1]
+ absl/strings/internal/stringify_sink.cc [1:1]
+ absl/strings/internal/stringify_sink.h [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL 9a67576708ae91ef266f0cfc231037fe
+BELONGS absl/strings/ya.make
+ License text:
+ // Copyright 2024 The Abseil Authors
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/poison.cc [1:1]
+ absl/base/internal/poison.h [1:1]
+ absl/container/hash_container_defaults.h [1:1]
+ absl/debugging/internal/bounded_utf8_length_sequence.h [1:1]
+ absl/debugging/internal/decode_rust_punycode.cc [1:1]
+ absl/debugging/internal/decode_rust_punycode.h [1:1]
+ absl/debugging/internal/demangle_rust.cc [1:1]
+ absl/debugging/internal/demangle_rust.h [1:1]
+ absl/debugging/internal/utf8_for_code_point.cc [1:1]
+ absl/debugging/internal/utf8_for_code_point.h [1:1]
+ absl/random/internal/mock_validators.h [1:1]
+ absl/status/internal/status_matchers.h [1:1]
+ Belongs difference:
+ + absl/strings/ya.make
+ - absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/random/ya.make absl/status/ya.make
+
+KEEP COPYRIGHT_SERVICE_LABEL 9fd4860fdb6776c0e8deab1d14ff7b1b
+BELONGS absl/debugging/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/debugging/internal/demangle_rust.cc [38:40]
+
+KEEP COPYRIGHT_SERVICE_LABEL d34864d3c7c7a5ffae3d414344aa54a8
+BELONGS absl/base/ya.make absl/debugging/ya.make absl/flags/ya.make absl/hash/ya.make absl/log/ya.make absl/numeric/ya.make absl/status/ya.make absl/strings/ya.make absl/synchronization/ya.make
+ License text:
+ // Copyright 2020 The Abseil Authors.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/base/internal/fast_type_id.h [2:2]
+ absl/base/internal/strerror.cc [1:1]
+ absl/base/internal/strerror.h [1:1]
+ absl/debugging/symbolize_darwin.inc [1:1]
+ absl/debugging/symbolize_emscripten.inc [1:1]
+ absl/flags/commandlineflag.cc [2:2]
+ absl/flags/commandlineflag.h [2:2]
+ absl/flags/internal/commandlineflag.cc [2:2]
+ absl/flags/internal/private_handle_accessor.cc [2:2]
+ absl/flags/internal/private_handle_accessor.h [2:2]
+ absl/flags/internal/sequence_lock.h [2:2]
+ absl/flags/reflection.cc [2:2]
+ absl/flags/reflection.h [2:2]
+ absl/hash/internal/low_level_hash.cc [1:1]
+ absl/hash/internal/low_level_hash.h [1:1]
+ absl/log/internal/proto.cc [1:1]
+ absl/log/internal/proto.h [1:1]
+ absl/numeric/bits.h [1:1]
+ absl/numeric/internal/bits.h [1:1]
+ absl/status/internal/statusor_internal.h [1:1]
+ absl/status/statusor.cc [1:1]
+ absl/status/statusor.h [1:1]
+ absl/strings/cord.cc [1:1]
+ absl/strings/cord.h [1:1]
+ absl/strings/internal/cord_internal.cc [1:1]
+ absl/strings/internal/cord_rep_flat.h [1:1]
+ absl/strings/internal/escaping.cc [1:1]
+ absl/strings/internal/escaping.h [1:1]
+ absl/strings/internal/str_format/arg.cc [1:1]
+ absl/strings/internal/str_format/arg.h [1:1]
+ absl/strings/internal/str_format/bind.cc [1:1]
+ absl/strings/internal/str_format/bind.h [1:1]
+ absl/strings/internal/str_format/checker.h [1:1]
+ absl/strings/internal/str_format/float_conversion.cc [1:1]
+ absl/strings/internal/str_format/float_conversion.h [1:1]
+ absl/strings/internal/str_format/parser.cc [1:1]
+ absl/strings/internal/str_format/parser.h [1:1]
+ absl/strings/internal/string_constant.h [1:1]
+ absl/synchronization/internal/futex.h [1:1]
+
+KEEP COPYRIGHT_SERVICE_LABEL d37bfeee971e2401eea92f7c8cb3ec44
+BELONGS absl/debugging/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: COPYRIGHT_SERVICE_LABEL
+ Score : 100.00
+ Match type : COPYRIGHT
+ Files with this license:
+ absl/debugging/internal/demangle_rust.cc [38:40]
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report
new file mode 100644
index 0000000000..7797dd2f87
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/devtools.licenses.report
@@ -0,0 +1,720 @@
+# File format ($ symbol means the beginning of a line):
+#
+# $ # this message
+# $ # =======================
+# $ # comments (all commentaries should starts with some number of spaces and # symbol)
+# ${action} {license id} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make
+# ${all_file_action} filename
+# $ # user commentaries (many lines)
+# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify)
+# ${action} {license spdx} {license text hash}
+# $BELONGS ./ya/make/file/relative/path/3/ya.make
+# ${all_file_action} filename
+# $ # user commentaries
+# $ generated description
+# $ ...
+#
+# You can modify action, all_file_action and add commentaries
+# Available actions:
+# keep - keep license in contrib and use in credits
+# skip - skip license
+# remove - remove all files with this license
+# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file
+#
+# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory)
+# We suppose that that files can contain some license info
+# Available all file actions:
+# FILE_IGNORE - ignore file (do nothing)
+# FILE_INCLUDE - include all file data into licenses text file
+# =======================
+
+KEEP Apache-2.0 0e8699c5f5ea602534a6558430df2b8d
+BELONGS absl/base/ya.make absl/debugging/ya.make absl/hash/ya.make absl/log/ya.make absl/numeric/ya.make absl/profiling/ya.make absl/random/ya.make absl/strings/ya.make absl/synchronization/ya.make absl/utility/ya.make ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ absl/base/internal/cycleclock_config.h [3:13]
+ absl/base/internal/poison.cc [3:13]
+ absl/base/internal/poison.h [3:13]
+ absl/base/internal/unscaledcycleclock_config.h [3:13]
+ absl/base/prefetch.h [3:13]
+ absl/container/hash_container_defaults.h [3:13]
+ absl/crc/crc32c.cc [3:13]
+ absl/crc/crc32c.h [3:13]
+ absl/crc/internal/cpu_detect.cc [3:13]
+ absl/crc/internal/cpu_detect.h [3:13]
+ absl/crc/internal/crc32c.h [3:13]
+ absl/crc/internal/crc_cord_state.cc [3:13]
+ absl/crc/internal/crc_cord_state.h [3:13]
+ absl/crc/internal/crc_memcpy.h [3:13]
+ absl/crc/internal/crc_memcpy_fallback.cc [3:13]
+ absl/crc/internal/crc_memcpy_x86_arm_combined.cc [3:13]
+ absl/crc/internal/crc_non_temporal_memcpy.cc [3:13]
+ absl/crc/internal/non_temporal_arm_intrinsics.h [3:13]
+ absl/crc/internal/non_temporal_memcpy.h [3:13]
+ absl/debugging/internal/bounded_utf8_length_sequence.h [3:13]
+ absl/debugging/internal/decode_rust_punycode.cc [3:13]
+ absl/debugging/internal/decode_rust_punycode.h [3:13]
+ absl/debugging/internal/demangle_rust.cc [3:13]
+ absl/debugging/internal/demangle_rust.h [3:13]
+ absl/debugging/internal/stacktrace_riscv-inl.inc [3:13]
+ absl/debugging/internal/utf8_for_code_point.cc [3:13]
+ absl/debugging/internal/utf8_for_code_point.h [3:13]
+ absl/hash/internal/low_level_hash.cc [3:13]
+ absl/hash/internal/low_level_hash.h [3:13]
+ absl/log/internal/append_truncated.h [3:13]
+ absl/log/internal/fnmatch.cc [3:13]
+ absl/log/internal/fnmatch.h [3:13]
+ absl/log/internal/log_impl.h [3:13]
+ absl/log/internal/nullguard.cc [3:13]
+ absl/log/internal/vlog_config.cc [3:13]
+ absl/log/internal/vlog_config.h [3:13]
+ absl/log/log_sink.cc [3:13]
+ absl/numeric/bits.h [3:13]
+ absl/numeric/internal/bits.h [3:13]
+ absl/numeric/internal/representation.h [3:13]
+ absl/profiling/internal/exponential_biased.cc [3:13]
+ absl/profiling/internal/exponential_biased.h [3:13]
+ absl/random/internal/mock_validators.h [3:13]
+ absl/random/internal/nanobenchmark.h [3:13]
+ absl/status/internal/status_internal.cc [3:13]
+ absl/status/internal/status_matchers.h [3:13]
+ absl/strings/cord_analysis.cc [3:13]
+ absl/strings/cord_analysis.h [3:13]
+ absl/strings/cord_buffer.cc [3:13]
+ absl/strings/cord_buffer.h [3:13]
+ absl/strings/cordz_test_helpers.h [3:13]
+ absl/strings/has_absl_stringify.h [3:13]
+ absl/strings/has_ostream_operator.h [3:13]
+ absl/strings/internal/cord_data_edge.h [3:13]
+ absl/strings/internal/cord_rep_btree.cc [3:13]
+ absl/strings/internal/cord_rep_btree.h [3:13]
+ absl/strings/internal/cord_rep_btree_navigator.cc [3:13]
+ absl/strings/internal/cord_rep_btree_navigator.h [3:13]
+ absl/strings/internal/cord_rep_btree_reader.cc [3:13]
+ absl/strings/internal/cord_rep_btree_reader.h [3:13]
+ absl/strings/internal/cord_rep_consume.cc [3:13]
+ absl/strings/internal/cord_rep_consume.h [3:13]
+ absl/strings/internal/cord_rep_crc.cc [3:13]
+ absl/strings/internal/cord_rep_crc.h [3:13]
+ absl/strings/internal/cord_rep_flat.h [3:13]
+ absl/strings/internal/cord_rep_test_util.h [3:13]
+ absl/strings/internal/cordz_update_scope.h [3:13]
+ absl/strings/internal/cordz_update_tracker.h [3:13]
+ absl/strings/internal/damerau_levenshtein_distance.cc [3:13]
+ absl/strings/internal/damerau_levenshtein_distance.h [3:13]
+ absl/strings/internal/str_format/constexpr_parser.h [3:13]
+ absl/strings/internal/stringify_sink.cc [3:13]
+ absl/strings/internal/stringify_sink.h [3:13]
+ absl/synchronization/internal/kernel_timeout.cc [3:13]
+ absl/utility/internal/if_constexpr.h [3:13]
+ Belongs difference:
+ - absl/container/ya.make absl/status/ya.make
+
+KEEP Apache-2.0 0f66a26c8211d9f8c21369fcb6702370
+BELONGS absl/time/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ absl/time/internal/cctz/include/cctz/civil_time.h [3:13]
+ absl/time/internal/cctz/include/cctz/civil_time_detail.h [3:13]
+ absl/time/internal/cctz/include/cctz/time_zone.h [3:13]
+ absl/time/internal/cctz/include/cctz/zone_info_source.h [3:13]
+ absl/time/internal/cctz/src/civil_time_detail.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_fixed.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_fixed.h [3:13]
+ absl/time/internal/cctz/src/time_zone_format.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_if.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_if.h [3:13]
+ absl/time/internal/cctz/src/time_zone_impl.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_impl.h [3:13]
+ absl/time/internal/cctz/src/time_zone_info.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_info.h [3:13]
+ absl/time/internal/cctz/src/time_zone_libc.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_libc.h [3:13]
+ absl/time/internal/cctz/src/time_zone_lookup.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_posix.cc [3:13]
+ absl/time/internal/cctz/src/time_zone_posix.h [3:13]
+ absl/time/internal/cctz/src/zone_info_source.cc [3:13]
+
+KEEP Apache-2.0 3493ceb30c6c8a1d5127bc1f0b030380
+BELONGS ya.make
+ License text:
+ \## License
+ The Abseil C++ library is licensed under the terms of the Apache
+ license. See [LICENSE](LICENSE) for more information.
+ Scancode info:
+ Original SPDX id: MIT
+ Score : 52.63
+ Match type : NOTICE
+ Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT
+ Files with this license:
+ README.md [145:148]
+
+KEEP Public-Domain 3a682fe6def1cddc889298ee2a043f6f
+BELONGS absl/time/ya.make
+ License text:
+ ** This file is in the public domain, so clarified as of
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-public-domain
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.linfo.org/publicdomain.html, https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/public-domain.LICENSE
+ Files with this license:
+ absl/time/internal/cctz/src/tzfile.h [8:8]
+
+KEEP Apache-2.0 3ea5060c4f08f5769674fbf0c0fb3992
+BELONGS absl/algorithm/ya.make absl/base/ya.make absl/container/ya.make absl/debugging/ya.make absl/flags/ya.make absl/functional/ya.make absl/hash/ya.make absl/log/ya.make absl/memory/ya.make absl/meta/ya.make absl/numeric/ya.make absl/profiling/ya.make absl/random/ya.make absl/status/ya.make absl/strings/ya.make absl/synchronization/ya.make absl/time/ya.make absl/types/ya.make absl/utility/ya.make ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ absl/algorithm/algorithm.h [3:13]
+ absl/algorithm/container.h [3:13]
+ absl/base/attributes.h [3:13]
+ absl/base/call_once.h [3:13]
+ absl/base/casts.h [4:14]
+ absl/base/config.h [4:14]
+ absl/base/const_init.h [3:13]
+ absl/base/dynamic_annotations.h [3:13]
+ absl/base/internal/atomic_hook.h [3:13]
+ absl/base/internal/atomic_hook_test_helper.h [3:13]
+ absl/base/internal/cycleclock.cc [3:13]
+ absl/base/internal/cycleclock.h [4:14]
+ absl/base/internal/direct_mmap.h [3:13]
+ absl/base/internal/dynamic_annotations.h [3:13]
+ absl/base/internal/endian.h [3:13]
+ absl/base/internal/errno_saver.h [3:13]
+ absl/base/internal/exception_safety_testing.h [3:13]
+ absl/base/internal/exception_testing.h [3:13]
+ absl/base/internal/fast_type_id.h [4:14]
+ absl/base/internal/hide_ptr.h [3:13]
+ absl/base/internal/identity.h [3:13]
+ absl/base/internal/inline_variable.h [3:13]
+ absl/base/internal/inline_variable_testing.h [3:13]
+ absl/base/internal/invoke.h [3:13]
+ absl/base/internal/low_level_alloc.cc [3:13]
+ absl/base/internal/low_level_alloc.h [3:13]
+ absl/base/internal/low_level_scheduling.h [3:13]
+ absl/base/internal/nullability_impl.h [3:13]
+ absl/base/internal/per_thread_tls.h [3:13]
+ absl/base/internal/pretty_function.h [3:13]
+ absl/base/internal/raw_logging.cc [3:13]
+ absl/base/internal/raw_logging.h [3:13]
+ absl/base/internal/scheduling_mode.h [3:13]
+ absl/base/internal/scoped_set_env.cc [3:13]
+ absl/base/internal/scoped_set_env.h [4:14]
+ absl/base/internal/spinlock.cc [3:13]
+ absl/base/internal/spinlock.h [4:14]
+ absl/base/internal/spinlock_akaros.inc [3:13]
+ absl/base/internal/spinlock_linux.inc [3:13]
+ absl/base/internal/spinlock_posix.inc [3:13]
+ absl/base/internal/spinlock_wait.cc [3:13]
+ absl/base/internal/spinlock_wait.h [3:13]
+ absl/base/internal/spinlock_win32.inc [3:13]
+ absl/base/internal/strerror.cc [3:13]
+ absl/base/internal/strerror.h [3:13]
+ absl/base/internal/sysinfo.cc [3:13]
+ absl/base/internal/sysinfo.h [3:13]
+ absl/base/internal/thread_identity.cc [3:13]
+ absl/base/internal/thread_identity.h [3:13]
+ absl/base/internal/throw_delegate.cc [3:13]
+ absl/base/internal/throw_delegate.h [4:14]
+ absl/base/internal/tsan_mutex_interface.h [3:13]
+ absl/base/internal/unaligned_access.h [4:14]
+ absl/base/internal/unscaledcycleclock.cc [3:13]
+ absl/base/internal/unscaledcycleclock.h [3:13]
+ absl/base/log_severity.cc [3:13]
+ absl/base/log_severity.h [3:13]
+ absl/base/macros.h [4:14]
+ absl/base/no_destructor.h [3:13]
+ absl/base/nullability.h [3:13]
+ absl/base/optimization.h [4:14]
+ absl/base/options.h [3:13]
+ absl/base/policy_checks.h [3:13]
+ absl/base/port.h [3:13]
+ absl/base/thread_annotations.h [3:13]
+ absl/cleanup/cleanup.h [3:13]
+ absl/cleanup/internal/cleanup.h [3:13]
+ absl/container/btree_map.h [3:13]
+ absl/container/btree_set.h [3:13]
+ absl/container/btree_test.h [3:13]
+ absl/container/fixed_array.h [3:13]
+ absl/container/flat_hash_map.h [3:13]
+ absl/container/flat_hash_set.h [3:13]
+ absl/container/inlined_vector.h [3:13]
+ absl/container/internal/btree.h [3:13]
+ absl/container/internal/btree_container.h [3:13]
+ absl/container/internal/common.h [3:13]
+ absl/container/internal/common_policy_traits.h [3:13]
+ absl/container/internal/compressed_tuple.h [3:13]
+ absl/container/internal/container_memory.h [3:13]
+ absl/container/internal/hash_function_defaults.h [3:13]
+ absl/container/internal/hash_generator_testing.h [3:13]
+ absl/container/internal/hash_policy_testing.h [3:13]
+ absl/container/internal/hash_policy_traits.h [3:13]
+ absl/container/internal/hashtable_debug.h [3:13]
+ absl/container/internal/hashtable_debug_hooks.h [3:13]
+ absl/container/internal/hashtablez_sampler.cc [3:13]
+ absl/container/internal/hashtablez_sampler.h [3:13]
+ absl/container/internal/hashtablez_sampler_force_weak_definition.cc [3:13]
+ absl/container/internal/inlined_vector.h [3:13]
+ absl/container/internal/layout.h [3:13]
+ absl/container/internal/node_slot_policy.h [3:13]
+ absl/container/internal/raw_hash_map.h [3:13]
+ absl/container/internal/raw_hash_set.cc [3:13]
+ absl/container/internal/raw_hash_set.h [3:13]
+ absl/container/internal/test_allocator.h [3:13]
+ absl/container/internal/test_instance_tracker.h [3:13]
+ absl/container/internal/tracked.h [3:13]
+ absl/container/internal/unordered_map_constructor_test.h [3:13]
+ absl/container/internal/unordered_map_lookup_test.h [3:13]
+ absl/container/internal/unordered_map_members_test.h [3:13]
+ absl/container/internal/unordered_map_modifiers_test.h [3:13]
+ absl/container/internal/unordered_set_constructor_test.h [3:13]
+ absl/container/internal/unordered_set_lookup_test.h [3:13]
+ absl/container/internal/unordered_set_members_test.h [3:13]
+ absl/container/internal/unordered_set_modifiers_test.h [3:13]
+ absl/container/node_hash_map.h [3:13]
+ absl/container/node_hash_set.h [3:13]
+ absl/crc/internal/crc.cc [3:13]
+ absl/crc/internal/crc.h [3:13]
+ absl/crc/internal/crc32_x86_arm_combined_simd.h [3:13]
+ absl/crc/internal/crc32c_inline.h [3:13]
+ absl/crc/internal/crc_internal.h [3:13]
+ absl/crc/internal/crc_x86_arm_combined.cc [3:13]
+ absl/debugging/failure_signal_handler.cc [4:14]
+ absl/debugging/failure_signal_handler.h [3:13]
+ absl/debugging/internal/address_is_readable.cc [3:13]
+ absl/debugging/internal/address_is_readable.h [3:13]
+ absl/debugging/internal/demangle.cc [3:13]
+ absl/debugging/internal/demangle.h [3:13]
+ absl/debugging/internal/elf_mem_image.cc [3:13]
+ absl/debugging/internal/examine_stack.cc [4:14]
+ absl/debugging/internal/examine_stack.h [4:14]
+ absl/debugging/internal/stack_consumption.h [4:14]
+ absl/debugging/internal/stacktrace_arm-inl.inc [3:13]
+ absl/debugging/internal/stacktrace_emscripten-inl.inc [3:13]
+ absl/debugging/internal/stacktrace_generic-inl.inc [3:13]
+ absl/debugging/internal/stacktrace_powerpc-inl.inc [3:13]
+ absl/debugging/internal/stacktrace_win32-inl.inc [3:13]
+ absl/debugging/internal/stacktrace_x86-inl.inc [3:13]
+ absl/debugging/internal/symbolize.h [3:13]
+ absl/debugging/internal/vdso_support.cc [3:13]
+ absl/debugging/internal/vdso_support.h [4:14]
+ absl/debugging/leak_check.cc [3:13]
+ absl/debugging/leak_check.h [3:13]
+ absl/debugging/stacktrace.cc [3:13]
+ absl/debugging/stacktrace.h [3:13]
+ absl/debugging/symbolize.cc [3:13]
+ absl/debugging/symbolize.h [3:13]
+ absl/debugging/symbolize_darwin.inc [3:13]
+ absl/debugging/symbolize_elf.inc [3:13]
+ absl/debugging/symbolize_emscripten.inc [3:13]
+ absl/debugging/symbolize_unimplemented.inc [3:13]
+ absl/debugging/symbolize_win32.inc [3:13]
+ absl/flags/commandlineflag.cc [4:14]
+ absl/flags/commandlineflag.h [4:14]
+ absl/flags/config.h [4:14]
+ absl/flags/declare.h [4:14]
+ absl/flags/flag.h [4:14]
+ absl/flags/internal/commandlineflag.cc [4:14]
+ absl/flags/internal/commandlineflag.h [4:14]
+ absl/flags/internal/flag.cc [4:14]
+ absl/flags/internal/flag.h [4:14]
+ absl/flags/internal/parse.h [4:14]
+ absl/flags/internal/path_util.h [4:14]
+ absl/flags/internal/private_handle_accessor.cc [4:14]
+ absl/flags/internal/private_handle_accessor.h [4:14]
+ absl/flags/internal/program_name.cc [4:14]
+ absl/flags/internal/program_name.h [4:14]
+ absl/flags/internal/registry.h [4:14]
+ absl/flags/internal/sequence_lock.h [4:14]
+ absl/flags/internal/usage.cc [4:14]
+ absl/flags/internal/usage.h [4:14]
+ absl/flags/marshalling.cc [4:14]
+ absl/flags/marshalling.h [4:14]
+ absl/flags/parse.cc [4:14]
+ absl/flags/parse.h [4:14]
+ absl/flags/reflection.cc [4:14]
+ absl/flags/reflection.h [4:14]
+ absl/flags/usage.cc [4:14]
+ absl/flags/usage.h [4:14]
+ absl/flags/usage_config.cc [4:14]
+ absl/flags/usage_config.h [4:14]
+ absl/functional/any_invocable.h [3:13]
+ absl/functional/bind_front.h [3:13]
+ absl/functional/function_ref.h [3:13]
+ absl/functional/internal/any_invocable.h [3:13]
+ absl/functional/internal/front_binder.h [3:13]
+ absl/functional/internal/function_ref.h [3:13]
+ absl/functional/overload.h [3:13]
+ absl/hash/hash.h [3:13]
+ absl/hash/hash_testing.h [3:13]
+ absl/hash/internal/city.cc [3:13]
+ absl/hash/internal/city.h [3:13]
+ absl/hash/internal/hash.cc [3:13]
+ absl/hash/internal/hash.h [3:13]
+ absl/hash/internal/hash_test.h [3:13]
+ absl/hash/internal/spy_hash_state.h [3:13]
+ absl/log/absl_check.h [3:13]
+ absl/log/absl_log.h [3:13]
+ absl/log/absl_vlog_is_on.h [3:13]
+ absl/log/check.h [3:13]
+ absl/log/die_if_null.cc [3:13]
+ absl/log/die_if_null.h [3:13]
+ absl/log/flags.cc [4:14]
+ absl/log/flags.h [3:13]
+ absl/log/globals.cc [3:13]
+ absl/log/globals.h [3:13]
+ absl/log/initialize.cc [3:13]
+ absl/log/initialize.h [3:13]
+ absl/log/internal/check_impl.h [3:13]
+ absl/log/internal/check_op.cc [3:13]
+ absl/log/internal/check_op.h [3:13]
+ absl/log/internal/conditions.cc [3:13]
+ absl/log/internal/conditions.h [3:13]
+ absl/log/internal/config.h [3:13]
+ absl/log/internal/flags.h [3:13]
+ absl/log/internal/globals.cc [3:13]
+ absl/log/internal/globals.h [3:13]
+ absl/log/internal/log_format.cc [4:14]
+ absl/log/internal/log_format.h [3:13]
+ absl/log/internal/log_message.cc [4:14]
+ absl/log/internal/log_message.h [3:13]
+ absl/log/internal/log_sink_set.cc [4:14]
+ absl/log/internal/log_sink_set.h [3:13]
+ absl/log/internal/nullguard.h [3:13]
+ absl/log/internal/nullstream.h [3:13]
+ absl/log/internal/proto.cc [3:13]
+ absl/log/internal/proto.h [3:13]
+ absl/log/internal/strip.h [3:13]
+ absl/log/internal/structured.h [3:13]
+ absl/log/internal/test_actions.h [3:13]
+ absl/log/internal/test_helpers.h [3:13]
+ absl/log/internal/test_matchers.h [3:13]
+ absl/log/internal/voidify.h [3:13]
+ absl/log/log.h [3:13]
+ absl/log/log_entry.cc [4:14]
+ absl/log/log_entry.h [3:13]
+ absl/log/log_sink.h [3:13]
+ absl/log/log_sink_registry.h [3:13]
+ absl/log/log_streamer.h [3:13]
+ absl/log/scoped_mock_log.h [3:13]
+ absl/log/structured.h [3:13]
+ absl/log/vlog_is_on.h [3:13]
+ absl/memory/memory.h [3:13]
+ absl/meta/type_traits.h [4:14]
+ absl/numeric/int128.cc [3:13]
+ absl/numeric/int128.h [4:14]
+ absl/numeric/int128_have_intrinsic.inc [4:14]
+ absl/numeric/int128_no_intrinsic.inc [4:14]
+ absl/profiling/internal/periodic_sampler.cc [3:13]
+ absl/profiling/internal/periodic_sampler.h [3:13]
+ absl/profiling/internal/sample_recorder.h [3:13]
+ absl/random/bernoulli_distribution.h [3:13]
+ absl/random/beta_distribution.h [3:13]
+ absl/random/bit_gen_ref.h [4:14]
+ absl/random/discrete_distribution.cc [3:13]
+ absl/random/discrete_distribution.h [3:13]
+ absl/random/distributions.h [3:13]
+ absl/random/exponential_distribution.h [3:13]
+ absl/random/gaussian_distribution.h [3:13]
+ absl/random/internal/chi_square.cc [3:13]
+ absl/random/internal/chi_square.h [3:13]
+ absl/random/internal/distribution_caller.h [4:14]
+ absl/random/internal/distribution_test_util.cc [3:13]
+ absl/random/internal/distribution_test_util.h [3:13]
+ absl/random/internal/explicit_seed_seq.h [3:13]
+ absl/random/internal/fast_uniform_bits.h [3:13]
+ absl/random/internal/fastmath.h [3:13]
+ absl/random/internal/generate_real.h [3:13]
+ absl/random/internal/iostream_state_saver.h [3:13]
+ absl/random/internal/mock_helpers.h [4:14]
+ absl/random/internal/mock_overload_set.h [4:14]
+ absl/random/internal/nonsecure_base.h [3:13]
+ absl/random/internal/pcg_engine.h [3:13]
+ absl/random/internal/platform.h [3:13]
+ absl/random/internal/pool_urbg.cc [3:13]
+ absl/random/internal/pool_urbg.h [3:13]
+ absl/random/internal/randen.cc [3:13]
+ absl/random/internal/randen.h [3:13]
+ absl/random/internal/randen_detect.cc [3:13]
+ absl/random/internal/randen_detect.h [3:13]
+ absl/random/internal/randen_engine.h [3:13]
+ absl/random/internal/randen_hwaes.cc [3:13]
+ absl/random/internal/randen_hwaes.h [3:13]
+ absl/random/internal/randen_round_keys.cc [3:13]
+ absl/random/internal/randen_slow.cc [3:13]
+ absl/random/internal/randen_slow.h [3:13]
+ absl/random/internal/randen_traits.h [3:13]
+ absl/random/internal/salted_seed_seq.h [3:13]
+ absl/random/internal/seed_material.cc [3:13]
+ absl/random/internal/seed_material.h [3:13]
+ absl/random/internal/sequence_urbg.h [3:13]
+ absl/random/internal/traits.h [3:13]
+ absl/random/internal/uniform_helper.h [3:13]
+ absl/random/internal/wide_multiply.h [3:13]
+ absl/random/log_uniform_int_distribution.h [3:13]
+ absl/random/mock_distributions.h [3:13]
+ absl/random/mocking_bit_gen.h [3:13]
+ absl/random/poisson_distribution.h [3:13]
+ absl/random/random.h [3:13]
+ absl/random/seed_gen_exception.cc [3:13]
+ absl/random/seed_gen_exception.h [3:13]
+ absl/random/seed_sequences.cc [3:13]
+ absl/random/seed_sequences.h [3:13]
+ absl/random/uniform_int_distribution.h [3:13]
+ absl/random/uniform_real_distribution.h [3:13]
+ absl/random/zipf_distribution.h [3:13]
+ absl/status/internal/status_internal.h [3:13]
+ absl/status/internal/statusor_internal.h [3:13]
+ absl/status/status.cc [3:13]
+ absl/status/status.h [3:13]
+ absl/status/status_payload_printer.cc [3:13]
+ absl/status/status_payload_printer.h [3:13]
+ absl/status/statusor.cc [3:13]
+ absl/status/statusor.h [3:13]
+ absl/strings/ascii.cc [3:13]
+ absl/strings/ascii.h [4:14]
+ absl/strings/charconv.cc [3:13]
+ absl/strings/charconv.h [3:13]
+ absl/strings/charset.h [3:13]
+ absl/strings/cord.cc [3:13]
+ absl/strings/cord.h [3:13]
+ absl/strings/cord_test_helpers.h [4:14]
+ absl/strings/escaping.cc [3:13]
+ absl/strings/escaping.h [4:14]
+ absl/strings/internal/charconv_bigint.cc [3:13]
+ absl/strings/internal/charconv_bigint.h [3:13]
+ absl/strings/internal/charconv_parse.cc [3:13]
+ absl/strings/internal/charconv_parse.h [3:13]
+ absl/strings/internal/cord_internal.cc [3:13]
+ absl/strings/internal/cord_internal.h [3:13]
+ absl/strings/internal/cordz_functions.cc [3:13]
+ absl/strings/internal/cordz_functions.h [3:13]
+ absl/strings/internal/cordz_handle.cc [3:13]
+ absl/strings/internal/cordz_handle.h [3:13]
+ absl/strings/internal/cordz_info.cc [3:13]
+ absl/strings/internal/cordz_info.h [3:13]
+ absl/strings/internal/cordz_sample_token.cc [3:13]
+ absl/strings/internal/cordz_sample_token.h [3:13]
+ absl/strings/internal/cordz_statistics.h [3:13]
+ absl/strings/internal/escaping.cc [3:13]
+ absl/strings/internal/escaping.h [3:13]
+ absl/strings/internal/escaping_test_common.h [3:13]
+ absl/strings/internal/memutil.cc [3:13]
+ absl/strings/internal/memutil.h [4:14]
+ absl/strings/internal/numbers_test_common.h [3:13]
+ absl/strings/internal/ostringstream.cc [3:13]
+ absl/strings/internal/ostringstream.h [3:13]
+ absl/strings/internal/pow10_helper.h [4:14]
+ absl/strings/internal/resize_uninitialized.h [4:14]
+ absl/strings/internal/stl_type_traits.h [3:13]
+ absl/strings/internal/str_format/arg.cc [3:13]
+ absl/strings/internal/str_format/arg.h [3:13]
+ absl/strings/internal/str_format/bind.cc [3:13]
+ absl/strings/internal/str_format/bind.h [3:13]
+ absl/strings/internal/str_format/checker.h [3:13]
+ absl/strings/internal/str_format/extension.cc [4:14]
+ absl/strings/internal/str_format/extension.h [4:14]
+ absl/strings/internal/str_format/float_conversion.cc [3:13]
+ absl/strings/internal/str_format/float_conversion.h [3:13]
+ absl/strings/internal/str_format/output.cc [3:13]
+ absl/strings/internal/str_format/output.h [3:13]
+ absl/strings/internal/str_format/parser.cc [3:13]
+ absl/strings/internal/str_format/parser.h [3:13]
+ absl/strings/internal/str_join_internal.h [4:14]
+ absl/strings/internal/str_split_internal.h [3:13]
+ absl/strings/internal/string_constant.h [3:13]
+ absl/strings/internal/utf8.cc [3:13]
+ absl/strings/internal/utf8.h [3:13]
+ absl/strings/match.cc [3:13]
+ absl/strings/match.h [4:14]
+ absl/strings/numbers.cc [3:13]
+ absl/strings/numbers.h [3:13]
+ absl/strings/str_cat.cc [3:13]
+ absl/strings/str_cat.h [4:14]
+ absl/strings/str_format.h [4:14]
+ absl/strings/str_join.h [4:14]
+ absl/strings/str_replace.cc [3:13]
+ absl/strings/str_replace.h [4:14]
+ absl/strings/str_split.cc [3:13]
+ absl/strings/str_split.h [4:14]
+ absl/strings/string_view.cc [3:13]
+ absl/strings/string_view.h [4:14]
+ absl/strings/strip.h [4:14]
+ absl/strings/substitute.cc [3:13]
+ absl/strings/substitute.h [4:14]
+ absl/synchronization/barrier.cc [3:13]
+ absl/synchronization/barrier.h [3:13]
+ absl/synchronization/blocking_counter.cc [3:13]
+ absl/synchronization/blocking_counter.h [4:14]
+ absl/synchronization/internal/create_thread_identity.cc [3:13]
+ absl/synchronization/internal/futex.h [3:13]
+ absl/synchronization/internal/futex_waiter.cc [3:13]
+ absl/synchronization/internal/futex_waiter.h [3:13]
+ absl/synchronization/internal/graphcycles.cc [3:13]
+ absl/synchronization/internal/graphcycles.h [3:13]
+ absl/synchronization/internal/kernel_timeout.h [3:13]
+ absl/synchronization/internal/per_thread_sem.cc [3:13]
+ absl/synchronization/internal/per_thread_sem.h [3:13]
+ absl/synchronization/internal/pthread_waiter.cc [3:13]
+ absl/synchronization/internal/pthread_waiter.h [3:13]
+ absl/synchronization/internal/sem_waiter.cc [3:13]
+ absl/synchronization/internal/sem_waiter.h [3:13]
+ absl/synchronization/internal/stdcpp_waiter.cc [3:13]
+ absl/synchronization/internal/stdcpp_waiter.h [3:13]
+ absl/synchronization/internal/thread_pool.h [3:13]
+ absl/synchronization/internal/waiter.h [3:13]
+ absl/synchronization/internal/waiter_base.cc [3:13]
+ absl/synchronization/internal/waiter_base.h [3:13]
+ absl/synchronization/internal/win32_waiter.cc [3:13]
+ absl/synchronization/internal/win32_waiter.h [3:13]
+ absl/synchronization/mutex.cc [3:13]
+ absl/synchronization/mutex.h [3:13]
+ absl/synchronization/notification.cc [3:13]
+ absl/synchronization/notification.h [3:13]
+ absl/time/civil_time.cc [3:13]
+ absl/time/civil_time.h [3:13]
+ absl/time/clock.cc [3:13]
+ absl/time/clock.h [3:13]
+ absl/time/duration.cc [3:13]
+ absl/time/format.cc [3:13]
+ absl/time/internal/get_current_time_chrono.inc [3:13]
+ absl/time/internal/test_util.h [3:13]
+ absl/time/time.cc [3:13]
+ absl/time/time.h [3:13]
+ absl/types/any.h [4:14]
+ absl/types/bad_any_cast.cc [3:13]
+ absl/types/bad_any_cast.h [3:13]
+ absl/types/bad_optional_access.cc [3:13]
+ absl/types/bad_optional_access.h [3:13]
+ absl/types/bad_variant_access.cc [3:13]
+ absl/types/bad_variant_access.h [3:13]
+ absl/types/compare.h [3:13]
+ absl/types/internal/optional.h [3:13]
+ absl/types/internal/span.h [4:14]
+ absl/types/internal/variant.h [3:13]
+ absl/types/optional.h [3:13]
+ absl/types/span.h [4:14]
+ absl/types/variant.h [3:13]
+ absl/utility/utility.h [3:13]
+
+SKIP LicenseRef-scancode-warranty-disclaimer 5ba761db85e57267704f71a6bcf20c2a
+BELONGS absl/container/ya.make absl/profiling/ya.make
+ License text:
+ // This utility is internal-only. Use at your own risk.
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-warranty-disclaimer
+ Score : 100.00
+ Match type : TEXT
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/warranty-disclaimer.LICENSE
+ Files with this license:
+ absl/container/internal/hashtablez_sampler.h [37:37]
+ absl/profiling/internal/sample_recorder.h [22:22]
+
+SKIP LicenseRef-scancode-generic-cla 5d780ffa423067f23c6a123ae33e7c18
+BELONGS ya.make
+ License text:
+ \## Contributor License Agreement
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-generic-cla
+ Score : 16.00
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/generic-cla.LICENSE
+ Files with this license:
+ CONTRIBUTING.md [9:9]
+
+SKIP LicenseRef-scancode-unknown-license-reference 8e1ade755f3bfad0a6736f291073f1ac
+BELONGS ya.make
+ License text:
+ license. See [LICENSE](LICENSE) for more information.
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-unknown-license-reference
+ Score : 100.00
+ Match type : REFERENCE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/unknown-license-reference.LICENSE
+ Files with this license:
+ README.md [148:148]
+
+SKIP LicenseRef-scancode-generic-exception 99cf00730bf3973359b67cfa5b7ac051
+BELONGS absl/synchronization/ya.make
+ License text:
+ // logging; as a special exception, the function may acquire other mutexes
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-generic-exception
+ Score : 16.00
+ Match type : INTRO
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/generic-exception.LICENSE
+ Files with this license:
+ absl/synchronization/mutex.h [317:317]
+
+KEEP Apache-2.0 cac6cbe8ed5a3da569f7c01e4e486688
+BELONGS ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : TEXT
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ LICENSE [2:202]
+
+KEEP Apache-2.0 d4afbfe97ca1f27103271d24e8af5b32
+BELONGS absl/debugging/ya.make absl/synchronization/ya.make
+ Note: matched license text is too long. Read it in the source files.
+ Scancode info:
+ Original SPDX id: Apache-2.0
+ Score : 100.00
+ Match type : NOTICE
+ Links : http://www.apache.org/licenses/, http://www.apache.org/licenses/LICENSE-2.0, https://spdx.org/licenses/Apache-2.0
+ Files with this license:
+ absl/debugging/internal/elf_mem_image.h [4:14]
+ absl/debugging/internal/stacktrace_config.h [4:14]
+ absl/synchronization/internal/create_thread_identity.h [4:14]
+
+SKIP LicenseRef-scancode-generic-cla d72fcd21b18e44b666a94e6225ed43eb
+BELONGS ya.make
+ License text:
+ Contributions to this project must be accompanied by a Contributor License
+ Agreement. You (or your employer) retain the copyright to your contribution,
+ Scancode info:
+ Original SPDX id: LicenseRef-scancode-generic-cla
+ Score : 16.00
+ Match type : NOTICE
+ Links : https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/generic-cla.LICENSE
+ Files with this license:
+ CONTRIBUTING.md [11:12]
+
+SKIP BSD-2-Clause AND GPL-2.0-only e12cf8844c9d92dd647ddf4320b73d06
+BELONGS absl/strings/ya.make
+# not a license
+ License text:
+ // input unless explicitly stated otherwise. All functions returning a CordRep*
+ Scancode info:
+ Original SPDX id: BSD-2-Clause
+ Score : 8.16
+ Match type : NOTICE
+ Links : http://opensource.org/licenses/bsd-license.php, http://www.opensource.org/licenses/BSD-2-Clause, https://spdx.org/licenses/BSD-2-Clause
+ Files with this license:
+ absl/strings/internal/cord_rep_btree.h [58:58]
+ Scancode info:
+ Original SPDX id: GPL-2.0-only
+ Score : 8.16
+ Match type : NOTICE
+ Links : http://www.gnu.org/licenses/gpl-2.0.html, http://www.gnu.org/licenses/gpl-2.0.txt, https://spdx.org/licenses/GPL-2.0-only
+ Files with this license:
+ absl/strings/internal/cord_rep_btree.h [58:58]
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..b95cfa928f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/licenses.list.txt
@@ -0,0 +1,245 @@
+====================Apache-2.0====================
+ Apache License
+ Version 2.0, January 2004
+ https://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
+
+
+====================Apache-2.0====================
+## License
+
+The Abseil C++ library is licensed under the terms of the Apache
+license. See [LICENSE](LICENSE) for more information.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/override.nix b/contrib/restricted/abseil-cpp/.yandex_meta/override.nix
new file mode 100644
index 0000000000..48e4443dd6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/override.nix
@@ -0,0 +1,12 @@
+self: super: with self; rec {
+ version = "20240722.0";
+
+ src = fetchFromGitHub {
+ owner = "abseil";
+ repo = "abseil-cpp";
+ rev = version;
+ hash = "sha256-51jpDhdZ0n+KLmxh8KVaTz53pZAB0dHjmILFX+OLud4=";
+ };
+
+ patches = [];
+}
diff --git a/contrib/restricted/abseil-cpp/.yandex_meta/provides.pbtxt b/contrib/restricted/abseil-cpp/.yandex_meta/provides.pbtxt
new file mode 100644
index 0000000000..c5178bd5ff
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/.yandex_meta/provides.pbtxt
@@ -0,0 +1,78 @@
+p { i: "abseil-cpp" x: "absl_bad_any_cast_impl" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/types" }
+p { i: "abseil-cpp" x: "absl_bad_optional_access" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/types" }
+p { i: "abseil-cpp" x: "absl_bad_variant_access" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/types" }
+p { i: "abseil-cpp" x: "absl_base" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_city" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/hash" }
+p { i: "abseil-cpp" x: "absl_civil_time" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/time" }
+p { i: "abseil-cpp" x: "absl_cord" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_cord_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_cordz_functions" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_cordz_handle" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_cordz_info" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_cordz_sample_token" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_debugging_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_demangle_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_examine_stack" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_exponential_biased" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/profiling" }
+p { i: "abseil-cpp" x: "absl_failure_signal_handler" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_flags" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_commandlineflag" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_commandlineflag_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_config" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_marshalling" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_parse" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_private_handle_accessor" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_program_name" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_reflection" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_usage" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_flags_usage_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/flags" }
+p { i: "abseil-cpp" x: "absl_graphcycles_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/synchronization" }
+p { i: "abseil-cpp" x: "absl_hash" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/hash" }
+p { i: "abseil-cpp" x: "absl_hashtablez_sampler" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/container" }
+p { i: "abseil-cpp" x: "absl_int128" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/numeric" }
+p { i: "abseil-cpp" x: "absl_leak_check" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_leak_check_disable" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_log_internal_check_op" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/log" }
+p { i: "abseil-cpp" x: "absl_log_internal_message" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/log" }
+p { i: "abseil-cpp" x: "absl_log_internal_nullguard" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/log" }
+p { i: "abseil-cpp" x: "absl_log_severity" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_low_level_hash" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/hash" }
+p { i: "abseil-cpp" x: "absl_malloc_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_periodic_sampler" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/profiling" }
+p { i: "abseil-cpp" x: "absl_random_distributions" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_distribution_test_util" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_platform" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_pool_urbg" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_randen" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_randen_hwaes" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_randen_hwaes_impl" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_randen_slow" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_internal_seed_material" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_seed_gen_exception" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_random_seed_sequences" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/random" }
+p { i: "abseil-cpp" x: "absl_raw_hash_set" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/container" }
+p { i: "abseil-cpp" x: "absl_raw_logging_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_scoped_set_env" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_spinlock_wait" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_stacktrace" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_status" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/status" }
+p { i: "abseil-cpp" x: "absl_statusor" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/status" }
+p { i: "abseil-cpp" x: "absl_str_format_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_strerror" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_strings" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_strings_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/strings" }
+p { i: "abseil-cpp" x: "absl_symbolize" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/debugging" }
+p { i: "abseil-cpp" x: "absl_synchronization" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/synchronization" }
+p { i: "abseil-cpp" x: "absl_throw_delegate" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/base" }
+p { i: "abseil-cpp" x: "absl_time" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/time" }
+p { i: "abseil-cpp" x: "absl_time_zone" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/time" }
+p { i: "abseil-cpp" x: "absl_vlog_config_internal" ix: true peerdir: "contrib/restricted/abseil-cpp/absl/log" }
+
+# These are header-only parts of abseil project.
+# As we can not properly work with header-only libraries, they can only be used for unbundle_from
+p { x: "absl_algorithm" peerdir: "contrib/restrcited/abseil-cpp/absl/algorithm" }
+p { x: "absl_functional" peerdir: "contrib/restrcited/abseil-cpp/absl/functional" }
+p { x: "absl_memory" peerdir: "contrib/restrcited/abseil-cpp/absl/memory" }
+p { x: "absl_meta" peerdir: "contrib/restricted/abseil-cpp/absl/meta" }
+p { x: "absl_utility" peerdir: "contrib/restricted/abseil-cpp/absl/utility" }
diff --git a/contrib/restricted/abseil-cpp/absl/algorithm/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/algorithm/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..7be6b42848
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/algorithm/.yandex_meta/licenses.list.txt
@@ -0,0 +1,16 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/base/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/base/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..e1ae6d662d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/.yandex_meta/licenses.list.txt
@@ -0,0 +1,50 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
+
+
+====================COPYRIGHT====================
+// Copyright 2023 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h b/contrib/restricted/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
new file mode 100644
index 0000000000..c72015ef96
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
@@ -0,0 +1,34 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
+#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
+
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace atomic_hook_internal {
+
+using VoidF = void (*)();
+extern absl::base_internal::AtomicHook<VoidF> func;
+extern int default_func_calls;
+void DefaultFunc();
+void RegisterFunc(VoidF func);
+
+} // namespace atomic_hook_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_TEST_HELPER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/exception_safety_testing.h b/contrib/restricted/abseil-cpp/absl/base/internal/exception_safety_testing.h
new file mode 100644
index 0000000000..c106154407
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/exception_safety_testing.h
@@ -0,0 +1,1109 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Utilities for testing exception-safety
+
+#ifndef ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
+#define ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
+
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <initializer_list>
+#include <iosfwd>
+#include <string>
+#include <tuple>
+#include <unordered_map>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/pretty_function.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "absl/utility/utility.h"
+
+namespace testing {
+
+enum class TypeSpec;
+enum class AllocSpec;
+
+constexpr TypeSpec operator|(TypeSpec a, TypeSpec b) {
+ using T = absl::underlying_type_t<TypeSpec>;
+ return static_cast<TypeSpec>(static_cast<T>(a) | static_cast<T>(b));
+}
+
+constexpr TypeSpec operator&(TypeSpec a, TypeSpec b) {
+ using T = absl::underlying_type_t<TypeSpec>;
+ return static_cast<TypeSpec>(static_cast<T>(a) & static_cast<T>(b));
+}
+
+constexpr AllocSpec operator|(AllocSpec a, AllocSpec b) {
+ using T = absl::underlying_type_t<AllocSpec>;
+ return static_cast<AllocSpec>(static_cast<T>(a) | static_cast<T>(b));
+}
+
+constexpr AllocSpec operator&(AllocSpec a, AllocSpec b) {
+ using T = absl::underlying_type_t<AllocSpec>;
+ return static_cast<AllocSpec>(static_cast<T>(a) & static_cast<T>(b));
+}
+
+namespace exceptions_internal {
+
+std::string GetSpecString(TypeSpec);
+std::string GetSpecString(AllocSpec);
+
+struct NoThrowTag {};
+struct StrongGuaranteeTagType {};
+
+// A simple exception class. We throw this so that test code can catch
+// exceptions specifically thrown by ThrowingValue.
+class TestException {
+ public:
+ explicit TestException(absl::string_view msg) : msg_(msg) {}
+ virtual ~TestException() {}
+ virtual const char* what() const noexcept { return msg_.c_str(); }
+
+ private:
+ std::string msg_;
+};
+
+// TestBadAllocException exists because allocation functions must throw an
+// exception which can be caught by a handler of std::bad_alloc. We use a child
+// class of std::bad_alloc so we can customise the error message, and also
+// derive from TestException so we don't accidentally end up catching an actual
+// bad_alloc exception in TestExceptionSafety.
+class TestBadAllocException : public std::bad_alloc, public TestException {
+ public:
+ explicit TestBadAllocException(absl::string_view msg) : TestException(msg) {}
+ using TestException::what;
+};
+
+extern int countdown;
+
+// Allows the countdown variable to be set manually (defaulting to the initial
+// value of 0)
+inline void SetCountdown(int i = 0) { countdown = i; }
+// Sets the countdown to the terminal value -1
+inline void UnsetCountdown() { SetCountdown(-1); }
+
+void MaybeThrow(absl::string_view msg, bool throw_bad_alloc = false);
+
+testing::AssertionResult FailureMessage(const TestException& e,
+ int countdown) noexcept;
+
+struct TrackedAddress {
+ bool is_alive;
+ std::string description;
+};
+
+// Inspects the constructions and destructions of anything inheriting from
+// TrackedObject. This allows us to safely "leak" TrackedObjects, as
+// ConstructorTracker will destroy everything left over in its destructor.
+class ConstructorTracker {
+ public:
+ explicit ConstructorTracker(int count) : countdown_(count) {
+ assert(current_tracker_instance_ == nullptr);
+ current_tracker_instance_ = this;
+ }
+
+ ~ConstructorTracker() {
+ assert(current_tracker_instance_ == this);
+ current_tracker_instance_ = nullptr;
+
+ for (auto& it : address_map_) {
+ void* address = it.first;
+ TrackedAddress& tracked_address = it.second;
+ if (tracked_address.is_alive) {
+ ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+ countdown_, "Object was not destroyed.");
+ }
+ }
+ }
+
+ static void ObjectConstructed(void* address, std::string description) {
+ if (!CurrentlyTracking()) return;
+
+ TrackedAddress& tracked_address =
+ current_tracker_instance_->address_map_[address];
+ if (tracked_address.is_alive) {
+ ADD_FAILURE() << ErrorMessage(
+ address, tracked_address.description,
+ current_tracker_instance_->countdown_,
+ "Object was re-constructed. Current object was constructed by " +
+ description);
+ }
+ tracked_address = {true, std::move(description)};
+ }
+
+ static void ObjectDestructed(void* address) {
+ if (!CurrentlyTracking()) return;
+
+ auto it = current_tracker_instance_->address_map_.find(address);
+ // Not tracked. Ignore.
+ if (it == current_tracker_instance_->address_map_.end()) return;
+
+ TrackedAddress& tracked_address = it->second;
+ if (!tracked_address.is_alive) {
+ ADD_FAILURE() << ErrorMessage(address, tracked_address.description,
+ current_tracker_instance_->countdown_,
+ "Object was re-destroyed.");
+ }
+ tracked_address.is_alive = false;
+ }
+
+ private:
+ static bool CurrentlyTracking() {
+ return current_tracker_instance_ != nullptr;
+ }
+
+ static std::string ErrorMessage(void* address,
+ const std::string& address_description,
+ int countdown,
+ const std::string& error_description) {
+ return absl::Substitute(
+ "With coundtown at $0:\n"
+ " $1\n"
+ " Object originally constructed by $2\n"
+ " Object address: $3\n",
+ countdown, error_description, address_description, address);
+ }
+
+ std::unordered_map<void*, TrackedAddress> address_map_;
+ int countdown_;
+
+ static ConstructorTracker* current_tracker_instance_;
+};
+
+class TrackedObject {
+ public:
+ TrackedObject(const TrackedObject&) = delete;
+ TrackedObject(TrackedObject&&) = delete;
+
+ protected:
+ explicit TrackedObject(std::string description) {
+ ConstructorTracker::ObjectConstructed(this, std::move(description));
+ }
+
+ ~TrackedObject() noexcept { ConstructorTracker::ObjectDestructed(this); }
+};
+} // namespace exceptions_internal
+
+extern exceptions_internal::NoThrowTag nothrow_ctor;
+
+extern exceptions_internal::StrongGuaranteeTagType strong_guarantee;
+
+// A test class which is convertible to bool. The conversion can be
+// instrumented to throw at a controlled time.
+class ThrowingBool {
+ public:
+ ThrowingBool(bool b) noexcept : b_(b) {} // NOLINT(runtime/explicit)
+ operator bool() const { // NOLINT
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return b_;
+ }
+
+ private:
+ bool b_;
+};
+
+/*
+ * Configuration enum for the ThrowingValue type that defines behavior for the
+ * lifetime of the instance. Use testing::nothrow_ctor to prevent the integer
+ * constructor from throwing.
+ *
+ * kEverythingThrows: Every operation can throw an exception
+ * kNoThrowCopy: Copy construction and copy assignment will not throw
+ * kNoThrowMove: Move construction and move assignment will not throw
+ * kNoThrowNew: Overloaded operators new and new[] will not throw
+ */
+enum class TypeSpec {
+ kEverythingThrows = 0,
+ kNoThrowCopy = 1,
+ kNoThrowMove = 1 << 1,
+ kNoThrowNew = 1 << 2,
+};
+
+/*
+ * A testing class instrumented to throw an exception at a controlled time.
+ *
+ * ThrowingValue implements a slightly relaxed version of the Regular concept --
+ * that is it's a value type with the expected semantics. It also implements
+ * arithmetic operations. It doesn't implement member and pointer operators
+ * like operator-> or operator[].
+ *
+ * ThrowingValue can be instrumented to have certain operations be noexcept by
+ * using compile-time bitfield template arguments. That is, to make an
+ * ThrowingValue which has noexcept move construction/assignment and noexcept
+ * copy construction/assignment, use the following:
+ * ThrowingValue<testing::kNoThrowMove | testing::kNoThrowCopy> my_thrwr{val};
+ */
+template <TypeSpec Spec = TypeSpec::kEverythingThrows>
+class ThrowingValue : private exceptions_internal::TrackedObject {
+ static constexpr bool IsSpecified(TypeSpec spec) {
+ return static_cast<bool>(Spec & spec);
+ }
+
+ static constexpr int kDefaultValue = 0;
+ static constexpr int kBadValue = 938550620;
+
+ public:
+ ThrowingValue() : TrackedObject(GetInstanceString(kDefaultValue)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ = kDefaultValue;
+ }
+
+ ThrowingValue(const ThrowingValue& other) noexcept(
+ IsSpecified(TypeSpec::kNoThrowCopy))
+ : TrackedObject(GetInstanceString(other.dummy_)) {
+ if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ }
+ dummy_ = other.dummy_;
+ }
+
+ ThrowingValue(ThrowingValue&& other) noexcept(
+ IsSpecified(TypeSpec::kNoThrowMove))
+ : TrackedObject(GetInstanceString(other.dummy_)) {
+ if (!IsSpecified(TypeSpec::kNoThrowMove)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ }
+ dummy_ = other.dummy_;
+ }
+
+ explicit ThrowingValue(int i) : TrackedObject(GetInstanceString(i)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ = i;
+ }
+
+ ThrowingValue(int i, exceptions_internal::NoThrowTag) noexcept
+ : TrackedObject(GetInstanceString(i)), dummy_(i) {}
+
+ // absl expects nothrow destructors
+ ~ThrowingValue() noexcept = default;
+
+ ThrowingValue& operator=(const ThrowingValue& other) noexcept(
+ IsSpecified(TypeSpec::kNoThrowCopy)) {
+ dummy_ = kBadValue;
+ if (!IsSpecified(TypeSpec::kNoThrowCopy)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ }
+ dummy_ = other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator=(ThrowingValue&& other) noexcept(
+ IsSpecified(TypeSpec::kNoThrowMove)) {
+ dummy_ = kBadValue;
+ if (!IsSpecified(TypeSpec::kNoThrowMove)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ }
+ dummy_ = other.dummy_;
+ return *this;
+ }
+
+ // Arithmetic Operators
+ ThrowingValue operator+(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ + other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator+() const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator-(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ - other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator-() const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(-dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue& operator++() {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ ++dummy_;
+ return *this;
+ }
+
+ ThrowingValue operator++(int) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ auto out = ThrowingValue(dummy_, nothrow_ctor);
+ ++dummy_;
+ return out;
+ }
+
+ ThrowingValue& operator--() {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ --dummy_;
+ return *this;
+ }
+
+ ThrowingValue operator--(int) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ auto out = ThrowingValue(dummy_, nothrow_ctor);
+ --dummy_;
+ return out;
+ }
+
+ ThrowingValue operator*(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ * other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator/(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ / other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator%(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ % other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator<<(int shift) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ << shift, nothrow_ctor);
+ }
+
+ ThrowingValue operator>>(int shift) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ >> shift, nothrow_ctor);
+ }
+
+ // Comparison Operators
+ // NOTE: We use `ThrowingBool` instead of `bool` because most STL
+ // types/containers requires T to be convertible to bool.
+ friend ThrowingBool operator==(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ == b.dummy_;
+ }
+ friend ThrowingBool operator!=(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ != b.dummy_;
+ }
+ friend ThrowingBool operator<(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ < b.dummy_;
+ }
+ friend ThrowingBool operator<=(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ <= b.dummy_;
+ }
+ friend ThrowingBool operator>(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ > b.dummy_;
+ }
+ friend ThrowingBool operator>=(const ThrowingValue& a,
+ const ThrowingValue& b) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return a.dummy_ >= b.dummy_;
+ }
+
+ // Logical Operators
+ ThrowingBool operator!() const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return !dummy_;
+ }
+
+ ThrowingBool operator&&(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return dummy_ && other.dummy_;
+ }
+
+ ThrowingBool operator||(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return dummy_ || other.dummy_;
+ }
+
+ // Bitwise Logical Operators
+ ThrowingValue operator~() const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(~dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator&(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ & other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator|(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ | other.dummy_, nothrow_ctor);
+ }
+
+ ThrowingValue operator^(const ThrowingValue& other) const {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return ThrowingValue(dummy_ ^ other.dummy_, nothrow_ctor);
+ }
+
+ // Compound Assignment operators
+ ThrowingValue& operator+=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ += other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator-=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ -= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator*=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ *= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator/=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ /= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator%=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ %= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator&=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ &= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator|=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ |= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator^=(const ThrowingValue& other) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ ^= other.dummy_;
+ return *this;
+ }
+
+ ThrowingValue& operator<<=(int shift) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ <<= shift;
+ return *this;
+ }
+
+ ThrowingValue& operator>>=(int shift) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ >>= shift;
+ return *this;
+ }
+
+ // Pointer operators
+ void operator&() const = delete; // NOLINT(runtime/operator)
+
+ // Stream operators
+ friend std::ostream& operator<<(std::ostream& os, const ThrowingValue& tv) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return os << GetInstanceString(tv.dummy_);
+ }
+
+ friend std::istream& operator>>(std::istream& is, const ThrowingValue&) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ return is;
+ }
+
+ // Memory management operators
+ static void* operator new(size_t s) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new(s);
+ }
+
+ static void* operator new[](size_t s) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new[](s);
+ }
+
+ template <typename... Args>
+ static void* operator new(size_t s, Args&&... args) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new(s, std::forward<Args>(args)...);
+ }
+
+ template <typename... Args>
+ static void* operator new[](size_t s, Args&&... args) noexcept(
+ IsSpecified(TypeSpec::kNoThrowNew)) {
+ if (!IsSpecified(TypeSpec::kNoThrowNew)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
+ }
+ return ::operator new[](s, std::forward<Args>(args)...);
+ }
+
+ // Abseil doesn't support throwing overloaded operator delete. These are
+ // provided so a throwing operator-new can clean up after itself.
+ void operator delete(void* p) noexcept { ::operator delete(p); }
+
+ template <typename... Args>
+ void operator delete(void* p, Args&&... args) noexcept {
+ ::operator delete(p, std::forward<Args>(args)...);
+ }
+
+ void operator delete[](void* p) noexcept { return ::operator delete[](p); }
+
+ template <typename... Args>
+ void operator delete[](void* p, Args&&... args) noexcept {
+ return ::operator delete[](p, std::forward<Args>(args)...);
+ }
+
+ // Non-standard access to the actual contained value. No need for this to
+ // throw.
+ int& Get() noexcept { return dummy_; }
+ const int& Get() const noexcept { return dummy_; }
+
+ private:
+ static std::string GetInstanceString(int dummy) {
+ return absl::StrCat("ThrowingValue<",
+ exceptions_internal::GetSpecString(Spec), ">(", dummy,
+ ")");
+ }
+
+ int dummy_;
+};
+// While not having to do with exceptions, explicitly delete comma operator, to
+// make sure we don't use it on user-supplied types.
+template <TypeSpec Spec, typename T>
+void operator,(const ThrowingValue<Spec>&, T&&) = delete;
+template <TypeSpec Spec, typename T>
+void operator,(T&&, const ThrowingValue<Spec>&) = delete;
+
+/*
+ * Configuration enum for the ThrowingAllocator type that defines behavior for
+ * the lifetime of the instance.
+ *
+ * kEverythingThrows: Calls to the member functions may throw
+ * kNoThrowAllocate: Calls to the member functions will not throw
+ */
+enum class AllocSpec {
+ kEverythingThrows = 0,
+ kNoThrowAllocate = 1,
+};
+
+/*
+ * An allocator type which is instrumented to throw at a controlled time, or not
+ * to throw, using AllocSpec. The supported settings are the default of every
+ * function which is allowed to throw in a conforming allocator possibly
+ * throwing, or nothing throws, in line with the ABSL_ALLOCATOR_THROWS
+ * configuration macro.
+ */
+template <typename T, AllocSpec Spec = AllocSpec::kEverythingThrows>
+class ThrowingAllocator : private exceptions_internal::TrackedObject {
+ static constexpr bool IsSpecified(AllocSpec spec) {
+ return static_cast<bool>(Spec & spec);
+ }
+
+ public:
+ using pointer = T*;
+ using const_pointer = const T*;
+ using reference = T&;
+ using const_reference = const T&;
+ using void_pointer = void*;
+ using const_void_pointer = const void*;
+ using value_type = T;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ using is_nothrow =
+ std::integral_constant<bool, Spec == AllocSpec::kNoThrowAllocate>;
+ using propagate_on_container_copy_assignment = std::true_type;
+ using propagate_on_container_move_assignment = std::true_type;
+ using propagate_on_container_swap = std::true_type;
+ using is_always_equal = std::false_type;
+
+ ThrowingAllocator() : TrackedObject(GetInstanceString(next_id_)) {
+ exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION);
+ dummy_ = std::make_shared<const int>(next_id_++);
+ }
+
+ template <typename U>
+ ThrowingAllocator(const ThrowingAllocator<U, Spec>& other) noexcept // NOLINT
+ : TrackedObject(GetInstanceString(*other.State())),
+ dummy_(other.State()) {}
+
+ // According to C++11 standard [17.6.3.5], Table 28, the move/copy ctors of
+ // allocator shall not exit via an exception, thus they are marked noexcept.
+ ThrowingAllocator(const ThrowingAllocator& other) noexcept
+ : TrackedObject(GetInstanceString(*other.State())),
+ dummy_(other.State()) {}
+
+ template <typename U>
+ ThrowingAllocator(ThrowingAllocator<U, Spec>&& other) noexcept // NOLINT
+ : TrackedObject(GetInstanceString(*other.State())),
+ dummy_(std::move(other.State())) {}
+
+ ThrowingAllocator(ThrowingAllocator&& other) noexcept
+ : TrackedObject(GetInstanceString(*other.State())),
+ dummy_(std::move(other.State())) {}
+
+ ~ThrowingAllocator() noexcept = default;
+
+ ThrowingAllocator& operator=(const ThrowingAllocator& other) noexcept {
+ dummy_ = other.State();
+ return *this;
+ }
+
+ template <typename U>
+ ThrowingAllocator& operator=(
+ const ThrowingAllocator<U, Spec>& other) noexcept {
+ dummy_ = other.State();
+ return *this;
+ }
+
+ template <typename U>
+ ThrowingAllocator& operator=(ThrowingAllocator<U, Spec>&& other) noexcept {
+ dummy_ = std::move(other.State());
+ return *this;
+ }
+
+ template <typename U>
+ struct rebind {
+ using other = ThrowingAllocator<U, Spec>;
+ };
+
+ pointer allocate(size_type n) noexcept(
+ IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
+ return static_cast<pointer>(::operator new(n * sizeof(T)));
+ }
+
+ pointer allocate(size_type n, const_void_pointer) noexcept(
+ IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ return allocate(n);
+ }
+
+ void deallocate(pointer ptr, size_type) noexcept {
+ ReadState();
+ ::operator delete(static_cast<void*>(ptr));
+ }
+
+ template <typename U, typename... Args>
+ void construct(U* ptr, Args&&... args) noexcept(
+ IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
+ ::new (static_cast<void*>(ptr)) U(std::forward<Args>(args)...);
+ }
+
+ template <typename U>
+ void destroy(U* p) noexcept {
+ ReadState();
+ p->~U();
+ }
+
+ size_type max_size() const noexcept {
+ return (std::numeric_limits<difference_type>::max)() / sizeof(value_type);
+ }
+
+ ThrowingAllocator select_on_container_copy_construction() noexcept(
+ IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
+ return *this;
+ }
+
+ template <typename U>
+ bool operator==(const ThrowingAllocator<U, Spec>& other) const noexcept {
+ return dummy_ == other.dummy_;
+ }
+
+ template <typename U>
+ bool operator!=(const ThrowingAllocator<U, Spec>& other) const noexcept {
+ return dummy_ != other.dummy_;
+ }
+
+ template <typename, AllocSpec>
+ friend class ThrowingAllocator;
+
+ private:
+ static std::string GetInstanceString(int dummy) {
+ return absl::StrCat("ThrowingAllocator<",
+ exceptions_internal::GetSpecString(Spec), ">(", dummy,
+ ")");
+ }
+
+ const std::shared_ptr<const int>& State() const { return dummy_; }
+ std::shared_ptr<const int>& State() { return dummy_; }
+
+ void ReadState() {
+ // we know that this will never be true, but the compiler doesn't, so this
+ // should safely force a read of the value.
+ if (*dummy_ < 0) std::abort();
+ }
+
+ void ReadStateAndMaybeThrow(absl::string_view msg) const {
+ if (!IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ exceptions_internal::MaybeThrow(
+ absl::Substitute("Allocator id $0 threw from $1", *dummy_, msg));
+ }
+ }
+
+ static int next_id_;
+ std::shared_ptr<const int> dummy_;
+};
+
+template <typename T, AllocSpec Spec>
+int ThrowingAllocator<T, Spec>::next_id_ = 0;
+
+// Tests for resource leaks by attempting to construct a T using args repeatedly
+// until successful, using the countdown method. Side effects can then be
+// tested for resource leaks.
+template <typename T, typename... Args>
+void TestThrowingCtor(Args&&... args) {
+ struct Cleanup {
+ ~Cleanup() { exceptions_internal::UnsetCountdown(); }
+ } c;
+ for (int count = 0;; ++count) {
+ exceptions_internal::ConstructorTracker ct(count);
+ exceptions_internal::SetCountdown(count);
+ try {
+ T temp(std::forward<Args>(args)...);
+ static_cast<void>(temp);
+ break;
+ } catch (const exceptions_internal::TestException&) {
+ }
+ }
+}
+
+// Tests the nothrow guarantee of the provided nullary operation. If the an
+// exception is thrown, the result will be AssertionFailure(). Otherwise, it
+// will be AssertionSuccess().
+template <typename Operation>
+testing::AssertionResult TestNothrowOp(const Operation& operation) {
+ struct Cleanup {
+ Cleanup() { exceptions_internal::SetCountdown(); }
+ ~Cleanup() { exceptions_internal::UnsetCountdown(); }
+ } c;
+ try {
+ operation();
+ return testing::AssertionSuccess();
+ } catch (const exceptions_internal::TestException&) {
+ return testing::AssertionFailure()
+ << "TestException thrown during call to operation() when nothrow "
+ "guarantee was expected.";
+ } catch (...) {
+ return testing::AssertionFailure()
+ << "Unknown exception thrown during call to operation() when "
+ "nothrow guarantee was expected.";
+ }
+}
+
+namespace exceptions_internal {
+
+// Dummy struct for ExceptionSafetyTestBuilder<> partial state.
+struct UninitializedT {};
+
+template <typename T>
+class DefaultFactory {
+ public:
+ explicit DefaultFactory(const T& t) : t_(t) {}
+ std::unique_ptr<T> operator()() const { return absl::make_unique<T>(t_); }
+
+ private:
+ T t_;
+};
+
+template <size_t LazyContractsCount, typename LazyFactory,
+ typename LazyOperation>
+using EnableIfTestable = typename absl::enable_if_t<
+ LazyContractsCount != 0 &&
+ !std::is_same<LazyFactory, UninitializedT>::value &&
+ !std::is_same<LazyOperation, UninitializedT>::value>;
+
+template <typename Factory = UninitializedT,
+ typename Operation = UninitializedT, typename... Contracts>
+class ExceptionSafetyTestBuilder;
+
+} // namespace exceptions_internal
+
+/*
+ * Constructs an empty ExceptionSafetyTestBuilder. All
+ * ExceptionSafetyTestBuilder objects are immutable and all With[thing] mutation
+ * methods return new instances of ExceptionSafetyTestBuilder.
+ *
+ * In order to test a T for exception safety, a factory for that T, a testable
+ * operation, and at least one contract callback returning an assertion
+ * result must be applied using the respective methods.
+ */
+exceptions_internal::ExceptionSafetyTestBuilder<> MakeExceptionSafetyTester();
+
+namespace exceptions_internal {
+template <typename T>
+struct IsUniquePtr : std::false_type {};
+
+template <typename T, typename D>
+struct IsUniquePtr<std::unique_ptr<T, D>> : std::true_type {};
+
+template <typename Factory>
+struct FactoryPtrTypeHelper {
+ using type = decltype(std::declval<const Factory&>()());
+
+ static_assert(IsUniquePtr<type>::value, "Factories must return a unique_ptr");
+};
+
+template <typename Factory>
+using FactoryPtrType = typename FactoryPtrTypeHelper<Factory>::type;
+
+template <typename Factory>
+using FactoryElementType = typename FactoryPtrType<Factory>::element_type;
+
+template <typename T>
+class ExceptionSafetyTest {
+ using Factory = std::function<std::unique_ptr<T>()>;
+ using Operation = std::function<void(T*)>;
+ using Contract = std::function<AssertionResult(T*)>;
+
+ public:
+ template <typename... Contracts>
+ explicit ExceptionSafetyTest(const Factory& f, const Operation& op,
+ const Contracts&... contracts)
+ : factory_(f), operation_(op), contracts_{WrapContract(contracts)...} {}
+
+ AssertionResult Test() const {
+ for (int count = 0;; ++count) {
+ exceptions_internal::ConstructorTracker ct(count);
+
+ for (const auto& contract : contracts_) {
+ auto t_ptr = factory_();
+ try {
+ SetCountdown(count);
+ operation_(t_ptr.get());
+ // Unset for the case that the operation throws no exceptions, which
+ // would leave the countdown set and break the *next* exception safety
+ // test after this one.
+ UnsetCountdown();
+ return AssertionSuccess();
+ } catch (const exceptions_internal::TestException& e) {
+ if (!contract(t_ptr.get())) {
+ return AssertionFailure() << e.what() << " failed contract check";
+ }
+ }
+ }
+ }
+ }
+
+ private:
+ template <typename ContractFn>
+ Contract WrapContract(const ContractFn& contract) {
+ return [contract](T* t_ptr) { return AssertionResult(contract(t_ptr)); };
+ }
+
+ Contract WrapContract(StrongGuaranteeTagType) {
+ return [this](T* t_ptr) { return AssertionResult(*factory_() == *t_ptr); };
+ }
+
+ Factory factory_;
+ Operation operation_;
+ std::vector<Contract> contracts_;
+};
+
+/*
+ * Builds a tester object that tests if performing a operation on a T follows
+ * exception safety guarantees. Verification is done via contract assertion
+ * callbacks applied to T instances post-throw.
+ *
+ * Template parameters for ExceptionSafetyTestBuilder:
+ *
+ * - Factory: The factory object (passed in via tester.WithFactory(...) or
+ * tester.WithInitialValue(...)) must be invocable with the signature
+ * `std::unique_ptr<T> operator()() const` where T is the type being tested.
+ * It is used for reliably creating identical T instances to test on.
+ *
+ * - Operation: The operation object (passed in via tester.WithOperation(...)
+ * or tester.Test(...)) must be invocable with the signature
+ * `void operator()(T*) const` where T is the type being tested. It is used
+ * for performing steps on a T instance that may throw and that need to be
+ * checked for exception safety. Each call to the operation will receive a
+ * fresh T instance so it's free to modify and destroy the T instances as it
+ * pleases.
+ *
+ * - Contracts...: The contract assertion callback objects (passed in via
+ * tester.WithContracts(...)) must be invocable with the signature
+ * `testing::AssertionResult operator()(T*) const` where T is the type being
+ * tested. Contract assertion callbacks are provided T instances post-throw.
+ * They must return testing::AssertionSuccess when the type contracts of the
+ * provided T instance hold. If the type contracts of the T instance do not
+ * hold, they must return testing::AssertionFailure. Execution order of
+ * Contracts... is unspecified. They will each individually get a fresh T
+ * instance so they are free to modify and destroy the T instances as they
+ * please.
+ */
+template <typename Factory, typename Operation, typename... Contracts>
+class ExceptionSafetyTestBuilder {
+ public:
+ /*
+ * Returns a new ExceptionSafetyTestBuilder with an included T factory based
+ * on the provided T instance. The existing factory will not be included in
+ * the newly created tester instance. The created factory returns a new T
+ * instance by copy-constructing the provided const T& t.
+ *
+ * Preconditions for tester.WithInitialValue(const T& t):
+ *
+ * - The const T& t object must be copy-constructible where T is the type
+ * being tested. For non-copy-constructible objects, use the method
+ * tester.WithFactory(...).
+ */
+ template <typename T>
+ ExceptionSafetyTestBuilder<DefaultFactory<T>, Operation, Contracts...>
+ WithInitialValue(const T& t) const {
+ return WithFactory(DefaultFactory<T>(t));
+ }
+
+ /*
+ * Returns a new ExceptionSafetyTestBuilder with the provided T factory
+ * included. The existing factory will not be included in the newly-created
+ * tester instance. This method is intended for use with types lacking a copy
+ * constructor. Types that can be copy-constructed should instead use the
+ * method tester.WithInitialValue(...).
+ */
+ template <typename NewFactory>
+ ExceptionSafetyTestBuilder<absl::decay_t<NewFactory>, Operation, Contracts...>
+ WithFactory(const NewFactory& new_factory) const {
+ return {new_factory, operation_, contracts_};
+ }
+
+ /*
+ * Returns a new ExceptionSafetyTestBuilder with the provided testable
+ * operation included. The existing operation will not be included in the
+ * newly created tester.
+ */
+ template <typename NewOperation>
+ ExceptionSafetyTestBuilder<Factory, absl::decay_t<NewOperation>, Contracts...>
+ WithOperation(const NewOperation& new_operation) const {
+ return {factory_, new_operation, contracts_};
+ }
+
+ /*
+ * Returns a new ExceptionSafetyTestBuilder with the provided MoreContracts...
+ * combined with the Contracts... that were already included in the instance
+ * on which the method was called. Contracts... cannot be removed or replaced
+ * once added to an ExceptionSafetyTestBuilder instance. A fresh object must
+ * be created in order to get an empty Contracts... list.
+ *
+ * In addition to passing in custom contract assertion callbacks, this method
+ * accepts `testing::strong_guarantee` as an argument which checks T instances
+ * post-throw against freshly created T instances via operator== to verify
+ * that any state changes made during the execution of the operation were
+ * properly rolled back.
+ */
+ template <typename... MoreContracts>
+ ExceptionSafetyTestBuilder<Factory, Operation, Contracts...,
+ absl::decay_t<MoreContracts>...>
+ WithContracts(const MoreContracts&... more_contracts) const {
+ return {
+ factory_, operation_,
+ std::tuple_cat(contracts_, std::tuple<absl::decay_t<MoreContracts>...>(
+ more_contracts...))};
+ }
+
+ /*
+ * Returns a testing::AssertionResult that is the reduced result of the
+ * exception safety algorithm. The algorithm short circuits and returns
+ * AssertionFailure after the first contract callback returns an
+ * AssertionFailure. Otherwise, if all contract callbacks return an
+ * AssertionSuccess, the reduced result is AssertionSuccess.
+ *
+ * The passed-in testable operation will not be saved in a new tester instance
+ * nor will it modify/replace the existing tester instance. This is useful
+ * when each operation being tested is unique and does not need to be reused.
+ *
+ * Preconditions for tester.Test(const NewOperation& new_operation):
+ *
+ * - May only be called after at least one contract assertion callback and a
+ * factory or initial value have been provided.
+ */
+ template <
+ typename NewOperation,
+ typename = EnableIfTestable<sizeof...(Contracts), Factory, NewOperation>>
+ testing::AssertionResult Test(const NewOperation& new_operation) const {
+ return TestImpl(new_operation, absl::index_sequence_for<Contracts...>());
+ }
+
+ /*
+ * Returns a testing::AssertionResult that is the reduced result of the
+ * exception safety algorithm. The algorithm short circuits and returns
+ * AssertionFailure after the first contract callback returns an
+ * AssertionFailure. Otherwise, if all contract callbacks return an
+ * AssertionSuccess, the reduced result is AssertionSuccess.
+ *
+ * Preconditions for tester.Test():
+ *
+ * - May only be called after at least one contract assertion callback, a
+ * factory or initial value and a testable operation have been provided.
+ */
+ template <
+ typename LazyOperation = Operation,
+ typename = EnableIfTestable<sizeof...(Contracts), Factory, LazyOperation>>
+ testing::AssertionResult Test() const {
+ return Test(operation_);
+ }
+
+ private:
+ template <typename, typename, typename...>
+ friend class ExceptionSafetyTestBuilder;
+
+ friend ExceptionSafetyTestBuilder<> testing::MakeExceptionSafetyTester();
+
+ ExceptionSafetyTestBuilder() {}
+
+ ExceptionSafetyTestBuilder(const Factory& f, const Operation& o,
+ const std::tuple<Contracts...>& i)
+ : factory_(f), operation_(o), contracts_(i) {}
+
+ template <typename SelectedOperation, size_t... Indices>
+ testing::AssertionResult TestImpl(SelectedOperation selected_operation,
+ absl::index_sequence<Indices...>) const {
+ return ExceptionSafetyTest<FactoryElementType<Factory>>(
+ factory_, selected_operation, std::get<Indices>(contracts_)...)
+ .Test();
+ }
+
+ Factory factory_;
+ Operation operation_;
+ std::tuple<Contracts...> contracts_;
+};
+
+} // namespace exceptions_internal
+
+} // namespace testing
+
+#endif // ABSL_HAVE_EXCEPTIONS
+
+#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/exception_testing.h b/contrib/restricted/abseil-cpp/absl/base/internal/exception_testing.h
new file mode 100644
index 0000000000..01b5465571
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/exception_testing.h
@@ -0,0 +1,42 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Testing utilities for ABSL types which throw exceptions.
+
+#ifndef ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
+#define ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+// ABSL_BASE_INTERNAL_EXPECT_FAIL tests either for a specified thrown exception
+// if exceptions are enabled, or for death with a specified text in the error
+// message
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
+ EXPECT_THROW(expr, exception_t)
+
+#elif defined(__ANDROID__)
+// Android asserts do not log anywhere that gtest can currently inspect.
+// So we expect exit, but cannot match the message.
+#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
+ EXPECT_DEATH(expr, ".*")
+#else
+#define ABSL_BASE_INTERNAL_EXPECT_FAIL(expr, exception_t, text) \
+ EXPECT_DEATH_IF_SUPPORTED(expr, text)
+
+#endif
+
+#endif // ABSL_BASE_INTERNAL_EXCEPTION_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable_testing.h b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable_testing.h
new file mode 100644
index 0000000000..f3c81459fa
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/inline_variable_testing.h
@@ -0,0 +1,46 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
+#define ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
+
+#include "absl/base/internal/inline_variable.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace inline_variable_testing_internal {
+
+struct Foo {
+ int value = 5;
+};
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, inline_variable_foo, {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(Foo, other_inline_variable_foo, {});
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(int, inline_variable_int, 5);
+ABSL_INTERNAL_INLINE_CONSTEXPR(int, other_inline_variable_int, 5);
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(void(*)(), inline_variable_fun_ptr, nullptr);
+
+const Foo& get_foo_a();
+const Foo& get_foo_b();
+
+const int& get_int_a();
+const int& get_int_b();
+
+} // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_INLINE_VARIABLE_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/base/internal/pretty_function.h b/contrib/restricted/abseil-cpp/absl/base/internal/pretty_function.h
new file mode 100644
index 0000000000..35d51676dc
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/base/internal/pretty_function.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_
+#define ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_
+
+// ABSL_PRETTY_FUNCTION
+//
+// In C++11, __func__ gives the undecorated name of the current function. That
+// is, "main", not "int main()". Various compilers give extra macros to get the
+// decorated function name, including return type and arguments, to
+// differentiate between overload sets. ABSL_PRETTY_FUNCTION is a portable
+// version of these macros which forwards to the correct macro on each compiler.
+#if defined(_MSC_VER)
+#define ABSL_PRETTY_FUNCTION __FUNCSIG__
+#elif defined(__GNUC__)
+#define ABSL_PRETTY_FUNCTION __PRETTY_FUNCTION__
+#else
+#error "Unsupported compiler"
+#endif
+
+#endif // ABSL_BASE_INTERNAL_PRETTY_FUNCTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/container/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..b482ebce8a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/.yandex_meta/licenses.list.txt
@@ -0,0 +1,28 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
diff --git a/contrib/restricted/abseil-cpp/absl/container/btree_map.h b/contrib/restricted/abseil-cpp/absl/container/btree_map.h
new file mode 100644
index 0000000000..b959b674ee
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/btree_map.h
@@ -0,0 +1,889 @@
+// Copyright 2018 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: btree_map.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines B-tree maps: sorted associative containers mapping
+// keys to values.
+//
+// * `absl::btree_map<>`
+// * `absl::btree_multimap<>`
+//
+// These B-tree types are similar to the corresponding types in the STL
+// (`std::map` and `std::multimap`) and generally conform to the STL interfaces
+// of those types. However, because they are implemented using B-trees, they
+// are more efficient in most situations.
+//
+// Unlike `std::map` and `std::multimap`, which are commonly implemented using
+// red-black tree nodes, B-tree maps use more generic B-tree nodes able to hold
+// multiple values per node. Holding multiple values per node often makes
+// B-tree maps perform better than their `std::map` counterparts, because
+// multiple entries can be checked within the same cache hit.
+//
+// However, these types should not be considered drop-in replacements for
+// `std::map` and `std::multimap` as there are some API differences, which are
+// noted in this header file. The most consequential differences with respect to
+// migrating to b-tree from the STL types are listed in the next paragraph.
+// Other API differences are minor.
+//
+// Importantly, insertions and deletions may invalidate outstanding iterators,
+// pointers, and references to elements. Such invalidations are typically only
+// an issue if insertion and deletion operations are interleaved with the use of
+// more than one iterator, pointer, or reference simultaneously. For this
+// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
+// iterator at the current position. Another important difference is that
+// key-types must be copy-constructible.
+//
+// Another API difference is that btree iterators can be subtracted, and this
+// is faster than using std::distance.
+//
+// B-tree maps are not exception-safe.
+
+#ifndef ABSL_CONTAINER_BTREE_MAP_H_
+#define ABSL_CONTAINER_BTREE_MAP_H_
+
+#include "absl/base/attributes.h"
+#include "absl/container/internal/btree.h" // IWYU pragma: export
+#include "absl/container/internal/btree_container.h" // IWYU pragma: export
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace container_internal {
+
+template <typename Key, typename Data, typename Compare, typename Alloc,
+ int TargetNodeSize, bool IsMulti>
+struct map_params;
+
+} // namespace container_internal
+
+// absl::btree_map<>
+//
+// An `absl::btree_map<K, V>` is an ordered associative container of
+// unique keys and associated values designed to be a more efficient replacement
+// for `std::map` (in most cases).
+//
+// Keys are sorted using an (optional) comparison function, which defaults to
+// `std::less<K>`.
+//
+// An `absl::btree_map<K, V>` uses a default allocator of
+// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)
+// nodes, and construct and destruct values within those nodes. You may
+// instead specify a custom allocator `A` (which in turn requires specifying a
+// custom comparator `C`) as in `absl::btree_map<K, V, C, A>`.
+//
+template <typename Key, typename Value, typename Compare = std::less<Key>,
+ typename Alloc = std::allocator<std::pair<const Key, Value>>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_map
+ : public container_internal::btree_map_container<
+ container_internal::btree<container_internal::map_params<
+ Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*IsMulti=*/false>>> {
+ using Base = typename btree_map::btree_map_container;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A `btree_map` supports the same overload set as `std::map`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // absl::btree_map<int, std::string> map1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::btree_map<int, std::string> map2 =
+ // {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+ //
+ // * Copy constructor
+ //
+ // absl::btree_map<int, std::string> map3(map2);
+ //
+ // * Copy assignment operator
+ //
+ // absl::btree_map<int, std::string> map4;
+ // map4 = map3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::btree_map<int, std::string> map5(std::move(map4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::btree_map<int, std::string> map6;
+ // map6 = std::move(map5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+ // absl::btree_map<int, std::string> map7(v.begin(), v.end());
+ btree_map() {}
+ using Base::Base;
+
+ // btree_map::begin()
+ //
+ // Returns an iterator to the beginning of the `btree_map`.
+ using Base::begin;
+
+ // btree_map::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `btree_map`.
+ using Base::cbegin;
+
+ // btree_map::end()
+ //
+ // Returns an iterator to the end of the `btree_map`.
+ using Base::end;
+
+ // btree_map::cend()
+ //
+ // Returns a const iterator to the end of the `btree_map`.
+ using Base::cend;
+
+ // btree_map::empty()
+ //
+ // Returns whether or not the `btree_map` is empty.
+ using Base::empty;
+
+ // btree_map::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `btree_map` under current memory constraints. This value can be thought
+ // of as the largest value of `std::distance(begin(), end())` for a
+ // `btree_map<Key, T>`.
+ using Base::max_size;
+
+ // btree_map::size()
+ //
+ // Returns the number of elements currently within the `btree_map`.
+ using Base::size;
+
+ // btree_map::clear()
+ //
+ // Removes all elements from the `btree_map`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ using Base::clear;
+
+ // btree_map::erase()
+ //
+ // Erases elements within the `btree_map`. If an erase occurs, any references,
+ // pointers, or iterators are invalidated.
+ // Overloads are listed below.
+ //
+ // iterator erase(iterator position):
+ // iterator erase(const_iterator position):
+ //
+ // Erases the element at `position` of the `btree_map`, returning
+ // the iterator pointing to the element after the one that was erased
+ // (or end() if none exists).
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning
+ // the iterator pointing to the element after the interval that was erased
+ // (or end() if none exists).
+ //
+ // template <typename K> size_type erase(const K& key):
+ //
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
+ using Base::erase;
+
+ // btree_map::insert()
+ //
+ // Inserts an element of the specified value into the `btree_map`,
+ // returning an iterator pointing to the newly inserted element, provided that
+ // an element with the given key does not already exist. If an insertion
+ // occurs, any references, pointers, or iterators are invalidated.
+ // Overloads are listed below.
+ //
+ // std::pair<iterator,bool> insert(const value_type& value):
+ //
+ // Inserts a value into the `btree_map`. Returns a pair consisting of an
+ // iterator to the inserted element (or to the element that prevented the
+ // insertion) and a bool denoting whether the insertion took place.
+ //
+ // std::pair<iterator,bool> insert(value_type&& value):
+ //
+ // Inserts a moveable value into the `btree_map`. Returns a pair
+ // consisting of an iterator to the inserted element (or to the element that
+ // prevented the insertion) and a bool denoting whether the insertion took
+ // place.
+ //
+ // iterator insert(const_iterator hint, const value_type& value):
+ // iterator insert(const_iterator hint, value_type&& value):
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element, or to the existing element that prevented the
+ // insertion.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // void insert(std::initializer_list<init_type> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ using Base::insert;
+
+ // btree_map::insert_or_assign()
+ //
+ // Inserts an element of the specified value into the `btree_map` provided
+ // that a value with the given key does not already exist, or replaces the
+ // corresponding mapped type with the forwarded `obj` argument if a key for
+ // that value already exists, returning an iterator pointing to the newly
+ // inserted element. Overloads are listed below.
+ //
+ // pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj):
+ // pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `btree_map`. If the returned bool is true, insertion took place, and if
+ // it's false, assignment took place.
+ //
+ // iterator insert_or_assign(const_iterator hint,
+ // const key_type& k, M&& obj):
+ // iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `btree_map` using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search.
+ using Base::insert_or_assign;
+
+ // btree_map::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_map`, provided that no element with the given key
+ // already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately. Prefer `try_emplace()` unless your key is not
+ // copyable or moveable.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace;
+
+ // btree_map::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_map`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search, and only inserts
+ // provided that no element with the given key already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately. Prefer `try_emplace()` unless your key is not
+ // copyable or moveable.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace_hint;
+
+ // btree_map::try_emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_map`, provided that no element with the given key
+ // already exists. Unlike `emplace()`, if an element with the given key
+ // already exists, we guarantee that no element is constructed.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated.
+ //
+ // Overloads are listed below.
+ //
+ // std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):
+ // std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):
+ //
+ // Inserts (via copy or move) the element of the specified key into the
+ // `btree_map`.
+ //
+ // iterator try_emplace(const_iterator hint,
+ // const key_type& k, Args&&... args):
+ // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):
+ //
+ // Inserts (via copy or move) the element of the specified key into the
+ // `btree_map` using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search.
+ using Base::try_emplace;
+
+ // btree_map::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Any references, pointers, or iterators
+ // are invalidated. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the element at the indicated position and returns a node handle
+ // owning that extracted data.
+ //
+ // template <typename K> node_type extract(const K& k):
+ //
+ // Extracts the element with the key matching the passed key value and
+ // returns a node handle owning that extracted data. If the `btree_map`
+ // does not contain an element with a matching key, this function returns an
+ // empty node handle.
+ //
+ // NOTE: when compiled in an earlier version of C++ than C++17,
+ // `node_type::key()` returns a const reference to the key instead of a
+ // mutable reference. We cannot safely return a mutable reference without
+ // std::launder (which is not available before C++17).
+ //
+ // NOTE: In this context, `node_type` refers to the C++17 concept of a
+ // move-only type that owns and provides access to the elements in associative
+ // containers (https://en.cppreference.com/w/cpp/container/node_handle).
+ // It does NOT refer to the data layout of the underlying btree.
+ using Base::extract;
+
+ // btree_map::extract_and_get_next()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle along with an iterator to the next
+ // element.
+ //
+ // extract_and_get_next_return_type extract_and_get_next(
+ // const_iterator position):
+ //
+ // Extracts the element at the indicated position, returns a struct
+ // containing a member named `node`: a node handle owning that extracted
+ // data and a member named `next`: an iterator pointing to the next element
+ // in the btree.
+ using Base::extract_and_get_next;
+
+ // btree_map::merge()
+ //
+ // Extracts elements from a given `source` btree_map into this
+ // `btree_map`. If the destination `btree_map` already contains an
+ // element with an equivalent key, that element is not extracted.
+ using Base::merge;
+
+ // btree_map::swap(btree_map& other)
+ //
+ // Exchanges the contents of this `btree_map` with those of the `other`
+ // btree_map, avoiding invocation of any move, copy, or swap operations on
+ // individual elements.
+ //
+ // All iterators and references on the `btree_map` remain valid, excepting
+ // for the past-the-end iterator, which is invalidated.
+ using Base::swap;
+
+ // btree_map::at()
+ //
+ // Returns a reference to the mapped value of the element with key equivalent
+ // to the passed key.
+ using Base::at;
+
+ // btree_map::contains()
+ //
+ // template <typename K> bool contains(const K& key) const:
+ //
+ // Determines whether an element comparing equal to the given `key` exists
+ // within the `btree_map`, returning `true` if so or `false` otherwise.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::contains;
+
+ // btree_map::count()
+ //
+ // template <typename K> size_type count(const K& key) const:
+ //
+ // Returns the number of elements comparing equal to the given `key` within
+ // the `btree_map`. Note that this function will return either `1` or `0`
+ // since duplicate elements are not allowed within a `btree_map`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::count;
+
+ // btree_map::equal_range()
+ //
+ // Returns a half-open range [first, last), defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the `btree_map`.
+ using Base::equal_range;
+
+ // btree_map::find()
+ //
+ // template <typename K> iterator find(const K& key):
+ // template <typename K> const_iterator find(const K& key) const:
+ //
+ // Finds an element with the passed `key` within the `btree_map`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::find;
+
+ // btree_map::lower_bound()
+ //
+ // template <typename K> iterator lower_bound(const K& key):
+ // template <typename K> const_iterator lower_bound(const K& key) const:
+ //
+ // Finds the first element with a key that is not less than `key` within the
+ // `btree_map`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::lower_bound;
+
+ // btree_map::upper_bound()
+ //
+ // template <typename K> iterator upper_bound(const K& key):
+ // template <typename K> const_iterator upper_bound(const K& key) const:
+ //
+ // Finds the first element with a key that is greater than `key` within the
+ // `btree_map`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::upper_bound;
+
+ // btree_map::operator[]()
+ //
+ // Returns a reference to the value mapped to the passed key within the
+ // `btree_map`, performing an `insert()` if the key does not already
+ // exist.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated. Otherwise iterators are not affected and references are not
+ // invalidated. Overloads are listed below.
+ //
+ // T& operator[](key_type&& key):
+ // T& operator[](const key_type& key):
+ //
+ // Inserts a value_type object constructed in-place if the element with the
+ // given key does not exist.
+ using Base::operator[];
+
+ // btree_map::get_allocator()
+ //
+ // Returns the allocator function associated with this `btree_map`.
+ using Base::get_allocator;
+
+ // btree_map::key_comp();
+ //
+ // Returns the key comparator associated with this `btree_map`.
+ using Base::key_comp;
+
+ // btree_map::value_comp();
+ //
+ // Returns the value comparator associated with this `btree_map`.
+ using Base::value_comp;
+};
+
+// absl::swap(absl::btree_map<>, absl::btree_map<>)
+//
+// Swaps the contents of two `absl::btree_map` containers.
+template <typename K, typename V, typename C, typename A>
+void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) {
+ return x.swap(y);
+}
+
+// absl::erase_if(absl::btree_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+// Returns the number of erased elements.
+template <typename K, typename V, typename C, typename A, typename Pred>
+typename btree_map<K, V, C, A>::size_type erase_if(
+ btree_map<K, V, C, A> &map, Pred pred) {
+ return container_internal::btree_access::erase_if(map, std::move(pred));
+}
+
+// absl::btree_multimap
+//
+// An `absl::btree_multimap<K, V>` is an ordered associative container of
+// keys and associated values designed to be a more efficient replacement for
+// `std::multimap` (in most cases). Unlike `absl::btree_map`, a B-tree multimap
+// allows multiple elements with equivalent keys.
+//
+// Keys are sorted using an (optional) comparison function, which defaults to
+// `std::less<K>`.
+//
+// An `absl::btree_multimap<K, V>` uses a default allocator of
+// `std::allocator<std::pair<const K, V>>` to allocate (and deallocate)
+// nodes, and construct and destruct values within those nodes. You may
+// instead specify a custom allocator `A` (which in turn requires specifying a
+// custom comparator `C`) as in `absl::btree_multimap<K, V, C, A>`.
+//
+template <typename Key, typename Value, typename Compare = std::less<Key>,
+ typename Alloc = std::allocator<std::pair<const Key, Value>>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multimap
+ : public container_internal::btree_multimap_container<
+ container_internal::btree<container_internal::map_params<
+ Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*IsMulti=*/true>>> {
+ using Base = typename btree_multimap::btree_multimap_container;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A `btree_multimap` supports the same overload set as `std::multimap`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // absl::btree_multimap<int, std::string> map1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::btree_multimap<int, std::string> map2 =
+ // {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+ //
+ // * Copy constructor
+ //
+ // absl::btree_multimap<int, std::string> map3(map2);
+ //
+ // * Copy assignment operator
+ //
+ // absl::btree_multimap<int, std::string> map4;
+ // map4 = map3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::btree_multimap<int, std::string> map5(std::move(map4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::btree_multimap<int, std::string> map6;
+ // map6 = std::move(map5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+ // absl::btree_multimap<int, std::string> map7(v.begin(), v.end());
+ btree_multimap() {}
+ using Base::Base;
+
+ // btree_multimap::begin()
+ //
+ // Returns an iterator to the beginning of the `btree_multimap`.
+ using Base::begin;
+
+ // btree_multimap::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `btree_multimap`.
+ using Base::cbegin;
+
+ // btree_multimap::end()
+ //
+ // Returns an iterator to the end of the `btree_multimap`.
+ using Base::end;
+
+ // btree_multimap::cend()
+ //
+ // Returns a const iterator to the end of the `btree_multimap`.
+ using Base::cend;
+
+ // btree_multimap::empty()
+ //
+ // Returns whether or not the `btree_multimap` is empty.
+ using Base::empty;
+
+ // btree_multimap::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `btree_multimap` under current memory constraints. This value can be
+ // thought of as the largest value of `std::distance(begin(), end())` for a
+ // `btree_multimap<Key, T>`.
+ using Base::max_size;
+
+ // btree_multimap::size()
+ //
+ // Returns the number of elements currently within the `btree_multimap`.
+ using Base::size;
+
+ // btree_multimap::clear()
+ //
+ // Removes all elements from the `btree_multimap`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ using Base::clear;
+
+ // btree_multimap::erase()
+ //
+ // Erases elements within the `btree_multimap`. If an erase occurs, any
+ // references, pointers, or iterators are invalidated.
+ // Overloads are listed below.
+ //
+ // iterator erase(iterator position):
+ // iterator erase(const_iterator position):
+ //
+ // Erases the element at `position` of the `btree_multimap`, returning
+ // the iterator pointing to the element after the one that was erased
+ // (or end() if none exists).
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning
+ // the iterator pointing to the element after the interval that was erased
+ // (or end() if none exists).
+ //
+ // template <typename K> size_type erase(const K& key):
+ //
+ // Erases the elements matching the key, if any exist, returning the
+ // number of elements erased.
+ using Base::erase;
+
+ // btree_multimap::insert()
+ //
+ // Inserts an element of the specified value into the `btree_multimap`,
+ // returning an iterator pointing to the newly inserted element.
+ // Any references, pointers, or iterators are invalidated. Overloads are
+ // listed below.
+ //
+ // iterator insert(const value_type& value):
+ //
+ // Inserts a value into the `btree_multimap`, returning an iterator to the
+ // inserted element.
+ //
+ // iterator insert(value_type&& value):
+ //
+ // Inserts a moveable value into the `btree_multimap`, returning an iterator
+ // to the inserted element.
+ //
+ // iterator insert(const_iterator hint, const value_type& value):
+ // iterator insert(const_iterator hint, value_type&& value):
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // void insert(std::initializer_list<init_type> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ using Base::insert;
+
+ // btree_multimap::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_multimap`. Any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace;
+
+ // btree_multimap::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_multimap`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search.
+ //
+ // Any references, pointers, or iterators are invalidated.
+ using Base::emplace_hint;
+
+ // btree_multimap::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the element at the indicated position and returns a node handle
+ // owning that extracted data.
+ //
+ // template <typename K> node_type extract(const K& k):
+ //
+ // Extracts the element with the key matching the passed key value and
+ // returns a node handle owning that extracted data. If the `btree_multimap`
+ // does not contain an element with a matching key, this function returns an
+ // empty node handle.
+ //
+ // NOTE: when compiled in an earlier version of C++ than C++17,
+ // `node_type::key()` returns a const reference to the key instead of a
+ // mutable reference. We cannot safely return a mutable reference without
+ // std::launder (which is not available before C++17).
+ //
+ // NOTE: In this context, `node_type` refers to the C++17 concept of a
+ // move-only type that owns and provides access to the elements in associative
+ // containers (https://en.cppreference.com/w/cpp/container/node_handle).
+ // It does NOT refer to the data layout of the underlying btree.
+ using Base::extract;
+
+ // btree_multimap::extract_and_get_next()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle along with an iterator to the next
+ // element.
+ //
+ // extract_and_get_next_return_type extract_and_get_next(
+ // const_iterator position):
+ //
+ // Extracts the element at the indicated position, returns a struct
+ // containing a member named `node`: a node handle owning that extracted
+ // data and a member named `next`: an iterator pointing to the next element
+ // in the btree.
+ using Base::extract_and_get_next;
+
+ // btree_multimap::merge()
+ //
+ // Extracts all elements from a given `source` btree_multimap into this
+ // `btree_multimap`.
+ using Base::merge;
+
+ // btree_multimap::swap(btree_multimap& other)
+ //
+ // Exchanges the contents of this `btree_multimap` with those of the `other`
+ // btree_multimap, avoiding invocation of any move, copy, or swap operations
+ // on individual elements.
+ //
+ // All iterators and references on the `btree_multimap` remain valid,
+ // excepting for the past-the-end iterator, which is invalidated.
+ using Base::swap;
+
+ // btree_multimap::contains()
+ //
+ // template <typename K> bool contains(const K& key) const:
+ //
+ // Determines whether an element comparing equal to the given `key` exists
+ // within the `btree_multimap`, returning `true` if so or `false` otherwise.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::contains;
+
+ // btree_multimap::count()
+ //
+ // template <typename K> size_type count(const K& key) const:
+ //
+ // Returns the number of elements comparing equal to the given `key` within
+ // the `btree_multimap`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::count;
+
+ // btree_multimap::equal_range()
+ //
+ // Returns a half-open range [first, last), defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the
+ // `btree_multimap`.
+ using Base::equal_range;
+
+ // btree_multimap::find()
+ //
+ // template <typename K> iterator find(const K& key):
+ // template <typename K> const_iterator find(const K& key) const:
+ //
+ // Finds an element with the passed `key` within the `btree_multimap`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::find;
+
+ // btree_multimap::lower_bound()
+ //
+ // template <typename K> iterator lower_bound(const K& key):
+ // template <typename K> const_iterator lower_bound(const K& key) const:
+ //
+ // Finds the first element with a key that is not less than `key` within the
+ // `btree_multimap`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::lower_bound;
+
+ // btree_multimap::upper_bound()
+ //
+ // template <typename K> iterator upper_bound(const K& key):
+ // template <typename K> const_iterator upper_bound(const K& key) const:
+ //
+ // Finds the first element with a key that is greater than `key` within the
+ // `btree_multimap`.
+ //
+ // Supports heterogeneous lookup, provided that the map has a compatible
+ // heterogeneous comparator.
+ using Base::upper_bound;
+
+ // btree_multimap::get_allocator()
+ //
+ // Returns the allocator function associated with this `btree_multimap`.
+ using Base::get_allocator;
+
+ // btree_multimap::key_comp();
+ //
+ // Returns the key comparator associated with this `btree_multimap`.
+ using Base::key_comp;
+
+ // btree_multimap::value_comp();
+ //
+ // Returns the value comparator associated with this `btree_multimap`.
+ using Base::value_comp;
+};
+
+// absl::swap(absl::btree_multimap<>, absl::btree_multimap<>)
+//
+// Swaps the contents of two `absl::btree_multimap` containers.
+template <typename K, typename V, typename C, typename A>
+void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) {
+ return x.swap(y);
+}
+
+// absl::erase_if(absl::btree_multimap<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+// Returns the number of erased elements.
+template <typename K, typename V, typename C, typename A, typename Pred>
+typename btree_multimap<K, V, C, A>::size_type erase_if(
+ btree_multimap<K, V, C, A> &map, Pred pred) {
+ return container_internal::btree_access::erase_if(map, std::move(pred));
+}
+
+namespace container_internal {
+
+// A parameters structure for holding the type parameters for a btree_map.
+// Compare and Alloc should be nothrow copy-constructible.
+template <typename Key, typename Data, typename Compare, typename Alloc,
+ int TargetNodeSize, bool IsMulti>
+struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, IsMulti,
+ /*IsMap=*/true, map_slot_policy<Key, Data>> {
+ using super_type = typename map_params::common_params;
+ using mapped_type = Data;
+ // This type allows us to move keys when it is safe to do so. It is safe
+ // for maps in which value_type and mutable_value_type are layout compatible.
+ using slot_policy = typename super_type::slot_policy;
+ using slot_type = typename super_type::slot_type;
+ using value_type = typename super_type::value_type;
+ using init_type = typename super_type::init_type;
+
+ template <typename V>
+ static auto key(const V &value ABSL_ATTRIBUTE_LIFETIME_BOUND)
+ -> decltype((value.first)) {
+ return value.first;
+ }
+ static const Key &key(const slot_type *s) { return slot_policy::key(s); }
+ static const Key &key(slot_type *s) { return slot_policy::key(s); }
+ // For use in node handle.
+ static auto mutable_key(slot_type *s)
+ -> decltype(slot_policy::mutable_key(s)) {
+ return slot_policy::mutable_key(s);
+ }
+ static mapped_type &value(value_type *value) { return value->second; }
+};
+
+} // namespace container_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_BTREE_MAP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/btree_set.h b/contrib/restricted/abseil-cpp/absl/container/btree_set.h
new file mode 100644
index 0000000000..986d27da6f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/btree_set.h
@@ -0,0 +1,824 @@
+// Copyright 2018 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: btree_set.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines B-tree sets: sorted associative containers of
+// values.
+//
+// * `absl::btree_set<>`
+// * `absl::btree_multiset<>`
+//
+// These B-tree types are similar to the corresponding types in the STL
+// (`std::set` and `std::multiset`) and generally conform to the STL interfaces
+// of those types. However, because they are implemented using B-trees, they
+// are more efficient in most situations.
+//
+// Unlike `std::set` and `std::multiset`, which are commonly implemented using
+// red-black tree nodes, B-tree sets use more generic B-tree nodes able to hold
+// multiple values per node. Holding multiple values per node often makes
+// B-tree sets perform better than their `std::set` counterparts, because
+// multiple entries can be checked within the same cache hit.
+//
+// However, these types should not be considered drop-in replacements for
+// `std::set` and `std::multiset` as there are some API differences, which are
+// noted in this header file. The most consequential differences with respect to
+// migrating to b-tree from the STL types are listed in the next paragraph.
+// Other API differences are minor.
+//
+// Importantly, insertions and deletions may invalidate outstanding iterators,
+// pointers, and references to elements. Such invalidations are typically only
+// an issue if insertion and deletion operations are interleaved with the use of
+// more than one iterator, pointer, or reference simultaneously. For this
+// reason, `insert()`, `erase()`, and `extract_and_get_next()` return a valid
+// iterator at the current position.
+//
+// Another API difference is that btree iterators can be subtracted, and this
+// is faster than using std::distance.
+//
+// B-tree sets are not exception-safe.
+
+#ifndef ABSL_CONTAINER_BTREE_SET_H_
+#define ABSL_CONTAINER_BTREE_SET_H_
+
+#include "absl/base/attributes.h"
+#include "absl/container/internal/btree.h" // IWYU pragma: export
+#include "absl/container/internal/btree_container.h" // IWYU pragma: export
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace container_internal {
+
+template <typename Key>
+struct set_slot_policy;
+
+template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
+ bool IsMulti>
+struct set_params;
+
+} // namespace container_internal
+
+// absl::btree_set<>
+//
+// An `absl::btree_set<K>` is an ordered associative container of unique key
+// values designed to be a more efficient replacement for `std::set` (in most
+// cases).
+//
+// Keys are sorted using an (optional) comparison function, which defaults to
+// `std::less<K>`.
+//
+// An `absl::btree_set<K>` uses a default allocator of `std::allocator<K>` to
+// allocate (and deallocate) nodes, and construct and destruct values within
+// those nodes. You may instead specify a custom allocator `A` (which in turn
+// requires specifying a custom comparator `C`) as in
+// `absl::btree_set<K, C, A>`.
+//
+template <typename Key, typename Compare = std::less<Key>,
+ typename Alloc = std::allocator<Key>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_set
+ : public container_internal::btree_set_container<
+ container_internal::btree<container_internal::set_params<
+ Key, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*IsMulti=*/false>>> {
+ using Base = typename btree_set::btree_set_container;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A `btree_set` supports the same overload set as `std::set`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // absl::btree_set<std::string> set1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::btree_set<std::string> set2 =
+ // {{"huey"}, {"dewey"}, {"louie"},};
+ //
+ // * Copy constructor
+ //
+ // absl::btree_set<std::string> set3(set2);
+ //
+ // * Copy assignment operator
+ //
+ // absl::btree_set<std::string> set4;
+ // set4 = set3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::btree_set<std::string> set5(std::move(set4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::btree_set<std::string> set6;
+ // set6 = std::move(set5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::string> v = {"a", "b"};
+ // absl::btree_set<std::string> set7(v.begin(), v.end());
+ btree_set() {}
+ using Base::Base;
+
+ // btree_set::begin()
+ //
+ // Returns an iterator to the beginning of the `btree_set`.
+ using Base::begin;
+
+ // btree_set::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `btree_set`.
+ using Base::cbegin;
+
+ // btree_set::end()
+ //
+ // Returns an iterator to the end of the `btree_set`.
+ using Base::end;
+
+ // btree_set::cend()
+ //
+ // Returns a const iterator to the end of the `btree_set`.
+ using Base::cend;
+
+ // btree_set::empty()
+ //
+ // Returns whether or not the `btree_set` is empty.
+ using Base::empty;
+
+ // btree_set::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `btree_set` under current memory constraints. This value can be thought
+ // of as the largest value of `std::distance(begin(), end())` for a
+ // `btree_set<Key>`.
+ using Base::max_size;
+
+ // btree_set::size()
+ //
+ // Returns the number of elements currently within the `btree_set`.
+ using Base::size;
+
+ // btree_set::clear()
+ //
+ // Removes all elements from the `btree_set`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ using Base::clear;
+
+ // btree_set::erase()
+ //
+ // Erases elements within the `btree_set`. Overloads are listed below.
+ //
+ // iterator erase(iterator position):
+ // iterator erase(const_iterator position):
+ //
+ // Erases the element at `position` of the `btree_set`, returning
+ // the iterator pointing to the element after the one that was erased
+ // (or end() if none exists).
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning
+ // the iterator pointing to the element after the interval that was erased
+ // (or end() if none exists).
+ //
+ // template <typename K> size_type erase(const K& key):
+ //
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
+ using Base::erase;
+
+ // btree_set::insert()
+ //
+ // Inserts an element of the specified value into the `btree_set`,
+ // returning an iterator pointing to the newly inserted element, provided that
+ // an element with the given key does not already exist. If an insertion
+ // occurs, any references, pointers, or iterators are invalidated.
+ // Overloads are listed below.
+ //
+ // std::pair<iterator,bool> insert(const value_type& value):
+ //
+ // Inserts a value into the `btree_set`. Returns a pair consisting of an
+ // iterator to the inserted element (or to the element that prevented the
+ // insertion) and a bool denoting whether the insertion took place.
+ //
+ // std::pair<iterator,bool> insert(value_type&& value):
+ //
+ // Inserts a moveable value into the `btree_set`. Returns a pair
+ // consisting of an iterator to the inserted element (or to the element that
+ // prevented the insertion) and a bool denoting whether the insertion took
+ // place.
+ //
+ // iterator insert(const_iterator hint, const value_type& value):
+ // iterator insert(const_iterator hint, value_type&& value):
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element, or to the existing element that prevented the
+ // insertion.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // void insert(std::initializer_list<init_type> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ using Base::insert;
+
+ // btree_set::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_set`, provided that no element with the given key
+ // already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace;
+
+ // btree_set::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_set`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search, and only inserts
+ // provided that no element with the given key already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately.
+ //
+ // If an insertion occurs, any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace_hint;
+
+ // btree_set::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Any references, pointers, or iterators
+ // are invalidated. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the element at the indicated position and returns a node handle
+ // owning that extracted data.
+ //
+ // template <typename K> node_type extract(const K& k):
+ //
+ // Extracts the element with the key matching the passed key value and
+ // returns a node handle owning that extracted data. If the `btree_set`
+ // does not contain an element with a matching key, this function returns an
+ // empty node handle.
+ //
+ // NOTE: In this context, `node_type` refers to the C++17 concept of a
+ // move-only type that owns and provides access to the elements in associative
+ // containers (https://en.cppreference.com/w/cpp/container/node_handle).
+ // It does NOT refer to the data layout of the underlying btree.
+ using Base::extract;
+
+ // btree_set::extract_and_get_next()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle along with an iterator to the next
+ // element.
+ //
+ // extract_and_get_next_return_type extract_and_get_next(
+ // const_iterator position):
+ //
+ // Extracts the element at the indicated position, returns a struct
+ // containing a member named `node`: a node handle owning that extracted
+ // data and a member named `next`: an iterator pointing to the next element
+ // in the btree.
+ using Base::extract_and_get_next;
+
+ // btree_set::merge()
+ //
+ // Extracts elements from a given `source` btree_set into this
+ // `btree_set`. If the destination `btree_set` already contains an
+ // element with an equivalent key, that element is not extracted.
+ using Base::merge;
+
+ // btree_set::swap(btree_set& other)
+ //
+ // Exchanges the contents of this `btree_set` with those of the `other`
+ // btree_set, avoiding invocation of any move, copy, or swap operations on
+ // individual elements.
+ //
+ // All iterators and references on the `btree_set` remain valid, excepting
+ // for the past-the-end iterator, which is invalidated.
+ using Base::swap;
+
+ // btree_set::contains()
+ //
+ // template <typename K> bool contains(const K& key) const:
+ //
+ // Determines whether an element comparing equal to the given `key` exists
+ // within the `btree_set`, returning `true` if so or `false` otherwise.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::contains;
+
+ // btree_set::count()
+ //
+ // template <typename K> size_type count(const K& key) const:
+ //
+ // Returns the number of elements comparing equal to the given `key` within
+ // the `btree_set`. Note that this function will return either `1` or `0`
+ // since duplicate elements are not allowed within a `btree_set`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::count;
+
+ // btree_set::equal_range()
+ //
+ // Returns a closed range [first, last], defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the
+ // `btree_set`.
+ using Base::equal_range;
+
+ // btree_set::find()
+ //
+ // template <typename K> iterator find(const K& key):
+ // template <typename K> const_iterator find(const K& key) const:
+ //
+ // Finds an element with the passed `key` within the `btree_set`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::find;
+
+ // btree_set::lower_bound()
+ //
+ // template <typename K> iterator lower_bound(const K& key):
+ // template <typename K> const_iterator lower_bound(const K& key) const:
+ //
+ // Finds the first element that is not less than `key` within the `btree_set`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::lower_bound;
+
+ // btree_set::upper_bound()
+ //
+ // template <typename K> iterator upper_bound(const K& key):
+ // template <typename K> const_iterator upper_bound(const K& key) const:
+ //
+ // Finds the first element that is greater than `key` within the `btree_set`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::upper_bound;
+
+ // btree_set::get_allocator()
+ //
+ // Returns the allocator function associated with this `btree_set`.
+ using Base::get_allocator;
+
+ // btree_set::key_comp();
+ //
+ // Returns the key comparator associated with this `btree_set`.
+ using Base::key_comp;
+
+ // btree_set::value_comp();
+ //
+ // Returns the value comparator associated with this `btree_set`. The keys to
+ // sort the elements are the values themselves, therefore `value_comp` and its
+ // sibling member function `key_comp` are equivalent.
+ using Base::value_comp;
+};
+
+// absl::swap(absl::btree_set<>, absl::btree_set<>)
+//
+// Swaps the contents of two `absl::btree_set` containers.
+template <typename K, typename C, typename A>
+void swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) {
+ return x.swap(y);
+}
+
+// absl::erase_if(absl::btree_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+// Returns the number of erased elements.
+template <typename K, typename C, typename A, typename Pred>
+typename btree_set<K, C, A>::size_type erase_if(btree_set<K, C, A> &set,
+ Pred pred) {
+ return container_internal::btree_access::erase_if(set, std::move(pred));
+}
+
+// absl::btree_multiset<>
+//
+// An `absl::btree_multiset<K>` is an ordered associative container of
+// keys and associated values designed to be a more efficient replacement
+// for `std::multiset` (in most cases). Unlike `absl::btree_set`, a B-tree
+// multiset allows equivalent elements.
+//
+// Keys are sorted using an (optional) comparison function, which defaults to
+// `std::less<K>`.
+//
+// An `absl::btree_multiset<K>` uses a default allocator of `std::allocator<K>`
+// to allocate (and deallocate) nodes, and construct and destruct values within
+// those nodes. You may instead specify a custom allocator `A` (which in turn
+// requires specifying a custom comparator `C`) as in
+// `absl::btree_multiset<K, C, A>`.
+//
+template <typename Key, typename Compare = std::less<Key>,
+ typename Alloc = std::allocator<Key>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER btree_multiset
+ : public container_internal::btree_multiset_container<
+ container_internal::btree<container_internal::set_params<
+ Key, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*IsMulti=*/true>>> {
+ using Base = typename btree_multiset::btree_multiset_container;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A `btree_multiset` supports the same overload set as `std::set`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // absl::btree_multiset<std::string> set1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::btree_multiset<std::string> set2 =
+ // {{"huey"}, {"dewey"}, {"louie"},};
+ //
+ // * Copy constructor
+ //
+ // absl::btree_multiset<std::string> set3(set2);
+ //
+ // * Copy assignment operator
+ //
+ // absl::btree_multiset<std::string> set4;
+ // set4 = set3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::btree_multiset<std::string> set5(std::move(set4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::btree_multiset<std::string> set6;
+ // set6 = std::move(set5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::string> v = {"a", "b"};
+ // absl::btree_multiset<std::string> set7(v.begin(), v.end());
+ btree_multiset() {}
+ using Base::Base;
+
+ // btree_multiset::begin()
+ //
+ // Returns an iterator to the beginning of the `btree_multiset`.
+ using Base::begin;
+
+ // btree_multiset::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `btree_multiset`.
+ using Base::cbegin;
+
+ // btree_multiset::end()
+ //
+ // Returns an iterator to the end of the `btree_multiset`.
+ using Base::end;
+
+ // btree_multiset::cend()
+ //
+ // Returns a const iterator to the end of the `btree_multiset`.
+ using Base::cend;
+
+ // btree_multiset::empty()
+ //
+ // Returns whether or not the `btree_multiset` is empty.
+ using Base::empty;
+
+ // btree_multiset::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `btree_multiset` under current memory constraints. This value can be
+ // thought of as the largest value of `std::distance(begin(), end())` for a
+ // `btree_multiset<Key>`.
+ using Base::max_size;
+
+ // btree_multiset::size()
+ //
+ // Returns the number of elements currently within the `btree_multiset`.
+ using Base::size;
+
+ // btree_multiset::clear()
+ //
+ // Removes all elements from the `btree_multiset`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ using Base::clear;
+
+ // btree_multiset::erase()
+ //
+ // Erases elements within the `btree_multiset`. Overloads are listed below.
+ //
+ // iterator erase(iterator position):
+ // iterator erase(const_iterator position):
+ //
+ // Erases the element at `position` of the `btree_multiset`, returning
+ // the iterator pointing to the element after the one that was erased
+ // (or end() if none exists).
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning
+ // the iterator pointing to the element after the interval that was erased
+ // (or end() if none exists).
+ //
+ // template <typename K> size_type erase(const K& key):
+ //
+ // Erases the elements matching the key, if any exist, returning the
+ // number of elements erased.
+ using Base::erase;
+
+ // btree_multiset::insert()
+ //
+ // Inserts an element of the specified value into the `btree_multiset`,
+ // returning an iterator pointing to the newly inserted element.
+ // Any references, pointers, or iterators are invalidated. Overloads are
+ // listed below.
+ //
+ // iterator insert(const value_type& value):
+ //
+ // Inserts a value into the `btree_multiset`, returning an iterator to the
+ // inserted element.
+ //
+ // iterator insert(value_type&& value):
+ //
+ // Inserts a moveable value into the `btree_multiset`, returning an iterator
+ // to the inserted element.
+ //
+ // iterator insert(const_iterator hint, const value_type& value):
+ // iterator insert(const_iterator hint, value_type&& value):
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // void insert(std::initializer_list<init_type> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ using Base::insert;
+
+ // btree_multiset::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_multiset`. Any references, pointers, or iterators are
+ // invalidated.
+ using Base::emplace;
+
+ // btree_multiset::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `btree_multiset`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search.
+ //
+ // Any references, pointers, or iterators are invalidated.
+ using Base::emplace_hint;
+
+ // btree_multiset::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the element at the indicated position and returns a node handle
+ // owning that extracted data.
+ //
+ // template <typename K> node_type extract(const K& k):
+ //
+ // Extracts the element with the key matching the passed key value and
+ // returns a node handle owning that extracted data. If the `btree_multiset`
+ // does not contain an element with a matching key, this function returns an
+ // empty node handle.
+ //
+ // NOTE: In this context, `node_type` refers to the C++17 concept of a
+ // move-only type that owns and provides access to the elements in associative
+ // containers (https://en.cppreference.com/w/cpp/container/node_handle).
+ // It does NOT refer to the data layout of the underlying btree.
+ using Base::extract;
+
+ // btree_multiset::extract_and_get_next()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle along with an iterator to the next
+ // element.
+ //
+ // extract_and_get_next_return_type extract_and_get_next(
+ // const_iterator position):
+ //
+ // Extracts the element at the indicated position, returns a struct
+ // containing a member named `node`: a node handle owning that extracted
+ // data and a member named `next`: an iterator pointing to the next element
+ // in the btree.
+ using Base::extract_and_get_next;
+
+ // btree_multiset::merge()
+ //
+ // Extracts all elements from a given `source` btree_multiset into this
+ // `btree_multiset`.
+ using Base::merge;
+
+ // btree_multiset::swap(btree_multiset& other)
+ //
+ // Exchanges the contents of this `btree_multiset` with those of the `other`
+ // btree_multiset, avoiding invocation of any move, copy, or swap operations
+ // on individual elements.
+ //
+ // All iterators and references on the `btree_multiset` remain valid,
+ // excepting for the past-the-end iterator, which is invalidated.
+ using Base::swap;
+
+ // btree_multiset::contains()
+ //
+ // template <typename K> bool contains(const K& key) const:
+ //
+ // Determines whether an element comparing equal to the given `key` exists
+ // within the `btree_multiset`, returning `true` if so or `false` otherwise.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::contains;
+
+ // btree_multiset::count()
+ //
+ // template <typename K> size_type count(const K& key) const:
+ //
+ // Returns the number of elements comparing equal to the given `key` within
+ // the `btree_multiset`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::count;
+
+ // btree_multiset::equal_range()
+ //
+ // Returns a closed range [first, last], defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the
+ // `btree_multiset`.
+ using Base::equal_range;
+
+ // btree_multiset::find()
+ //
+ // template <typename K> iterator find(const K& key):
+ // template <typename K> const_iterator find(const K& key) const:
+ //
+ // Finds an element with the passed `key` within the `btree_multiset`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::find;
+
+ // btree_multiset::lower_bound()
+ //
+ // template <typename K> iterator lower_bound(const K& key):
+ // template <typename K> const_iterator lower_bound(const K& key) const:
+ //
+ // Finds the first element that is not less than `key` within the
+ // `btree_multiset`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::lower_bound;
+
+ // btree_multiset::upper_bound()
+ //
+ // template <typename K> iterator upper_bound(const K& key):
+ // template <typename K> const_iterator upper_bound(const K& key) const:
+ //
+ // Finds the first element that is greater than `key` within the
+ // `btree_multiset`.
+ //
+ // Supports heterogeneous lookup, provided that the set has a compatible
+ // heterogeneous comparator.
+ using Base::upper_bound;
+
+ // btree_multiset::get_allocator()
+ //
+ // Returns the allocator function associated with this `btree_multiset`.
+ using Base::get_allocator;
+
+ // btree_multiset::key_comp();
+ //
+ // Returns the key comparator associated with this `btree_multiset`.
+ using Base::key_comp;
+
+ // btree_multiset::value_comp();
+ //
+ // Returns the value comparator associated with this `btree_multiset`. The
+ // keys to sort the elements are the values themselves, therefore `value_comp`
+ // and its sibling member function `key_comp` are equivalent.
+ using Base::value_comp;
+};
+
+// absl::swap(absl::btree_multiset<>, absl::btree_multiset<>)
+//
+// Swaps the contents of two `absl::btree_multiset` containers.
+template <typename K, typename C, typename A>
+void swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) {
+ return x.swap(y);
+}
+
+// absl::erase_if(absl::btree_multiset<>, Pred)
+//
+// Erases all elements that satisfy the predicate pred from the container.
+// Returns the number of erased elements.
+template <typename K, typename C, typename A, typename Pred>
+typename btree_multiset<K, C, A>::size_type erase_if(
+ btree_multiset<K, C, A> & set, Pred pred) {
+ return container_internal::btree_access::erase_if(set, std::move(pred));
+}
+
+namespace container_internal {
+
+// This type implements the necessary functions from the
+// absl::container_internal::slot_type interface for btree_(multi)set.
+template <typename Key>
+struct set_slot_policy {
+ using slot_type = Key;
+ using value_type = Key;
+ using mutable_value_type = Key;
+
+ static value_type &element(slot_type *slot) { return *slot; }
+ static const value_type &element(const slot_type *slot) { return *slot; }
+
+ template <typename Alloc, class... Args>
+ static void construct(Alloc *alloc, slot_type *slot, Args &&...args) {
+ absl::allocator_traits<Alloc>::construct(*alloc, slot,
+ std::forward<Args>(args)...);
+ }
+
+ template <typename Alloc>
+ static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {
+ absl::allocator_traits<Alloc>::construct(*alloc, slot, std::move(*other));
+ }
+
+ template <typename Alloc>
+ static void construct(Alloc *alloc, slot_type *slot, const slot_type *other) {
+ absl::allocator_traits<Alloc>::construct(*alloc, slot, *other);
+ }
+
+ template <typename Alloc>
+ static void destroy(Alloc *alloc, slot_type *slot) {
+ absl::allocator_traits<Alloc>::destroy(*alloc, slot);
+ }
+};
+
+// A parameters structure for holding the type parameters for a btree_set.
+// Compare and Alloc should be nothrow copy-constructible.
+template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
+ bool IsMulti>
+struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, IsMulti,
+ /*IsMap=*/false, set_slot_policy<Key>> {
+ using value_type = Key;
+ using slot_type = typename set_params::common_params::slot_type;
+
+ template <typename V>
+ static const V &key(const V &value) {
+ return value;
+ }
+ static const Key &key(const slot_type *slot) { return *slot; }
+ static const Key &key(slot_type *slot) { return *slot; }
+};
+
+} // namespace container_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_BTREE_SET_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/btree_test.h b/contrib/restricted/abseil-cpp/absl/container/btree_test.h
new file mode 100644
index 0000000000..624908072d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/btree_test.h
@@ -0,0 +1,166 @@
+// Copyright 2018 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_BTREE_TEST_H_
+#define ABSL_CONTAINER_BTREE_TEST_H_
+
+#include <algorithm>
+#include <cassert>
+#include <random>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/cord.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// Like remove_const but propagates the removal through std::pair.
+template <typename T>
+struct remove_pair_const {
+ using type = typename std::remove_const<T>::type;
+};
+template <typename T, typename U>
+struct remove_pair_const<std::pair<T, U> > {
+ using type = std::pair<typename remove_pair_const<T>::type,
+ typename remove_pair_const<U>::type>;
+};
+
+// Utility class to provide an accessor for a key given a value. The default
+// behavior is to treat the value as a pair and return the first element.
+template <typename K, typename V>
+struct KeyOfValue {
+ struct type {
+ const K& operator()(const V& p) const { return p.first; }
+ };
+};
+
+// Partial specialization of KeyOfValue class for when the key and value are
+// the same type such as in set<> and btree_set<>.
+template <typename K>
+struct KeyOfValue<K, K> {
+ struct type {
+ const K& operator()(const K& k) const { return k; }
+ };
+};
+
+inline char* GenerateDigits(char buf[16], unsigned val, unsigned maxval) {
+ assert(val <= maxval);
+ constexpr unsigned kBase = 64; // avoid integer division.
+ unsigned p = 15;
+ buf[p--] = 0;
+ while (maxval > 0) {
+ buf[p--] = ' ' + (val % kBase);
+ val /= kBase;
+ maxval /= kBase;
+ }
+ return buf + p + 1;
+}
+
+template <typename K>
+struct Generator {
+ int maxval;
+ explicit Generator(int m) : maxval(m) {}
+ K operator()(int i) const {
+ assert(i <= maxval);
+ return K(i);
+ }
+};
+
+template <>
+struct Generator<absl::Time> {
+ int maxval;
+ explicit Generator(int m) : maxval(m) {}
+ absl::Time operator()(int i) const { return absl::FromUnixMillis(i); }
+};
+
+template <>
+struct Generator<std::string> {
+ int maxval;
+ explicit Generator(int m) : maxval(m) {}
+ std::string operator()(int i) const {
+ char buf[16];
+ return GenerateDigits(buf, i, maxval);
+ }
+};
+
+template <>
+struct Generator<Cord> {
+ int maxval;
+ explicit Generator(int m) : maxval(m) {}
+ Cord operator()(int i) const {
+ char buf[16];
+ return Cord(GenerateDigits(buf, i, maxval));
+ }
+};
+
+template <typename T, typename U>
+struct Generator<std::pair<T, U> > {
+ Generator<typename remove_pair_const<T>::type> tgen;
+ Generator<typename remove_pair_const<U>::type> ugen;
+
+ explicit Generator(int m) : tgen(m), ugen(m) {}
+ std::pair<T, U> operator()(int i) const {
+ return std::make_pair(tgen(i), ugen(i));
+ }
+};
+
+// Generate n values for our tests and benchmarks. Value range is [0, maxval].
+inline std::vector<int> GenerateNumbersWithSeed(int n, int maxval, int seed) {
+ // NOTE: Some tests rely on generated numbers not changing between test runs.
+ // We use std::minstd_rand0 because it is well-defined, but don't use
+ // std::uniform_int_distribution because platforms use different algorithms.
+ std::minstd_rand0 rng(seed);
+
+ std::vector<int> values;
+ absl::flat_hash_set<int> unique_values;
+ if (values.size() < n) {
+ for (int i = values.size(); i < n; i++) {
+ int value;
+ do {
+ value = static_cast<int>(rng()) % (maxval + 1);
+ } while (!unique_values.insert(value).second);
+
+ values.push_back(value);
+ }
+ }
+ return values;
+}
+
+// Generates n values in the range [0, maxval].
+template <typename V>
+std::vector<V> GenerateValuesWithSeed(int n, int maxval, int seed) {
+ const std::vector<int> nums = GenerateNumbersWithSeed(n, maxval, seed);
+ Generator<V> gen(maxval);
+ std::vector<V> vec;
+
+ vec.reserve(n);
+ for (int i = 0; i < n; i++) {
+ vec.push_back(gen(nums[i]));
+ }
+
+ return vec;
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_BTREE_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/btree.h b/contrib/restricted/abseil-cpp/absl/container/internal/btree.h
new file mode 100644
index 0000000000..689e71a5ce
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/btree.h
@@ -0,0 +1,3046 @@
+// Copyright 2018 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.
+
+// A btree implementation of the STL set and map interfaces. A btree is smaller
+// and generally also faster than STL set/map (refer to the benchmarks below).
+// The red-black tree implementation of STL set/map has an overhead of 3
+// pointers (left, right and parent) plus the node color information for each
+// stored value. So a set<int32_t> consumes 40 bytes for each value stored in
+// 64-bit mode. This btree implementation stores multiple values on fixed
+// size nodes (usually 256 bytes) and doesn't store child pointers for leaf
+// nodes. The result is that a btree_set<int32_t> may use much less memory per
+// stored value. For the random insertion benchmark in btree_bench.cc, a
+// btree_set<int32_t> with node-size of 256 uses 5.1 bytes per stored value.
+//
+// The packing of multiple values on to each node of a btree has another effect
+// besides better space utilization: better cache locality due to fewer cache
+// lines being accessed. Better cache locality translates into faster
+// operations.
+//
+// CAVEATS
+//
+// Insertions and deletions on a btree can cause splitting, merging or
+// rebalancing of btree nodes. And even without these operations, insertions
+// and deletions on a btree will move values around within a node. In both
+// cases, the result is that insertions and deletions can invalidate iterators
+// pointing to values other than the one being inserted/deleted. Therefore, this
+// container does not provide pointer stability. This is notably different from
+// STL set/map which takes care to not invalidate iterators on insert/erase
+// except, of course, for iterators pointing to the value being erased. A
+// partial workaround when erasing is available: erase() returns an iterator
+// pointing to the item just after the one that was erased (or end() if none
+// exists).
+
+#ifndef ABSL_CONTAINER_INTERNAL_BTREE_H_
+#define ABSL_CONTAINER_INTERNAL_BTREE_H_
+
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <functional>
+#include <iterator>
+#include <limits>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/internal/common.h"
+#include "absl/container/internal/common_policy_traits.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/container/internal/container_memory.h"
+#include "absl/container/internal/layout.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/compare.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+#error ABSL_BTREE_ENABLE_GENERATIONS cannot be directly set
+#elif (defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_HWADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_MEMORY_SANITIZER)) && \
+ !defined(NDEBUG_SANITIZER) // If defined, performance is important.
+// When compiled in sanitizer mode, we add generation integers to the nodes and
+// iterators. When iterators are used, we validate that the container has not
+// been mutated since the iterator was constructed.
+#define ABSL_BTREE_ENABLE_GENERATIONS
+#endif
+
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+constexpr bool BtreeGenerationsEnabled() { return true; }
+#else
+constexpr bool BtreeGenerationsEnabled() { return false; }
+#endif
+
+template <typename Compare, typename T, typename U>
+using compare_result_t = absl::result_of_t<const Compare(const T &, const U &)>;
+
+// A helper class that indicates if the Compare parameter is a key-compare-to
+// comparator.
+template <typename Compare, typename T>
+using btree_is_key_compare_to =
+ std::is_convertible<compare_result_t<Compare, T, T>, absl::weak_ordering>;
+
+struct StringBtreeDefaultLess {
+ using is_transparent = void;
+
+ StringBtreeDefaultLess() = default;
+
+ // Compatibility constructor.
+ StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT
+ StringBtreeDefaultLess(std::less<absl::string_view>) {} // NOLINT
+
+ // Allow converting to std::less for use in key_comp()/value_comp().
+ explicit operator std::less<std::string>() const { return {}; }
+ explicit operator std::less<absl::string_view>() const { return {}; }
+ explicit operator std::less<absl::Cord>() const { return {}; }
+
+ absl::weak_ordering operator()(absl::string_view lhs,
+ absl::string_view rhs) const {
+ return compare_internal::compare_result_as_ordering(lhs.compare(rhs));
+ }
+ StringBtreeDefaultLess(std::less<absl::Cord>) {} // NOLINT
+ absl::weak_ordering operator()(const absl::Cord &lhs,
+ const absl::Cord &rhs) const {
+ return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
+ }
+ absl::weak_ordering operator()(const absl::Cord &lhs,
+ absl::string_view rhs) const {
+ return compare_internal::compare_result_as_ordering(lhs.Compare(rhs));
+ }
+ absl::weak_ordering operator()(absl::string_view lhs,
+ const absl::Cord &rhs) const {
+ return compare_internal::compare_result_as_ordering(-rhs.Compare(lhs));
+ }
+};
+
+struct StringBtreeDefaultGreater {
+ using is_transparent = void;
+
+ StringBtreeDefaultGreater() = default;
+
+ StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT
+ StringBtreeDefaultGreater(std::greater<absl::string_view>) {} // NOLINT
+
+ // Allow converting to std::greater for use in key_comp()/value_comp().
+ explicit operator std::greater<std::string>() const { return {}; }
+ explicit operator std::greater<absl::string_view>() const { return {}; }
+ explicit operator std::greater<absl::Cord>() const { return {}; }
+
+ absl::weak_ordering operator()(absl::string_view lhs,
+ absl::string_view rhs) const {
+ return compare_internal::compare_result_as_ordering(rhs.compare(lhs));
+ }
+ StringBtreeDefaultGreater(std::greater<absl::Cord>) {} // NOLINT
+ absl::weak_ordering operator()(const absl::Cord &lhs,
+ const absl::Cord &rhs) const {
+ return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
+ }
+ absl::weak_ordering operator()(const absl::Cord &lhs,
+ absl::string_view rhs) const {
+ return compare_internal::compare_result_as_ordering(-lhs.Compare(rhs));
+ }
+ absl::weak_ordering operator()(absl::string_view lhs,
+ const absl::Cord &rhs) const {
+ return compare_internal::compare_result_as_ordering(rhs.Compare(lhs));
+ }
+};
+
+// See below comments for checked_compare.
+template <typename Compare, bool is_class = std::is_class<Compare>::value>
+struct checked_compare_base : Compare {
+ using Compare::Compare;
+ explicit checked_compare_base(Compare c) : Compare(std::move(c)) {}
+ const Compare &comp() const { return *this; }
+};
+template <typename Compare>
+struct checked_compare_base<Compare, false> {
+ explicit checked_compare_base(Compare c) : compare(std::move(c)) {}
+ const Compare &comp() const { return compare; }
+ Compare compare;
+};
+
+// A mechanism for opting out of checked_compare for use only in btree_test.cc.
+struct BtreeTestOnlyCheckedCompareOptOutBase {};
+
+// A helper class to adapt the specified comparator for two use cases:
+// (1) When using common Abseil string types with common comparison functors,
+// convert a boolean comparison into a three-way comparison that returns an
+// `absl::weak_ordering`. This helper class is specialized for
+// less<std::string>, greater<std::string>, less<string_view>,
+// greater<string_view>, less<absl::Cord>, and greater<absl::Cord>.
+// (2) Adapt the comparator to diagnose cases of non-strict-weak-ordering (see
+// https://en.cppreference.com/w/cpp/named_req/Compare) in debug mode. Whenever
+// a comparison is made, we will make assertions to verify that the comparator
+// is valid.
+template <typename Compare, typename Key>
+struct key_compare_adapter {
+ // Inherit from checked_compare_base to support function pointers and also
+ // keep empty-base-optimization (EBO) support for classes.
+ // Note: we can't use CompressedTuple here because that would interfere
+ // with the EBO for `btree::rightmost_`. `btree::rightmost_` is itself a
+ // CompressedTuple and nested `CompressedTuple`s don't support EBO.
+ // TODO(b/214288561): use CompressedTuple instead once it supports EBO for
+ // nested `CompressedTuple`s.
+ struct checked_compare : checked_compare_base<Compare> {
+ private:
+ using Base = typename checked_compare::checked_compare_base;
+ using Base::comp;
+
+ // If possible, returns whether `t` is equivalent to itself. We can only do
+ // this for `Key`s because we can't be sure that it's safe to call
+ // `comp()(k, k)` otherwise. Even if SFINAE allows it, there could be a
+ // compilation failure inside the implementation of the comparison operator.
+ bool is_self_equivalent(const Key &k) const {
+ // Note: this works for both boolean and three-way comparators.
+ return comp()(k, k) == 0;
+ }
+ // If we can't compare `t` with itself, returns true unconditionally.
+ template <typename T>
+ bool is_self_equivalent(const T &) const {
+ return true;
+ }
+
+ public:
+ using Base::Base;
+ checked_compare(Compare comp) : Base(std::move(comp)) {} // NOLINT
+
+ // Allow converting to Compare for use in key_comp()/value_comp().
+ explicit operator Compare() const { return comp(); }
+
+ template <typename T, typename U,
+ absl::enable_if_t<
+ std::is_same<bool, compare_result_t<Compare, T, U>>::value,
+ int> = 0>
+ bool operator()(const T &lhs, const U &rhs) const {
+ // NOTE: if any of these assertions fail, then the comparator does not
+ // establish a strict-weak-ordering (see
+ // https://en.cppreference.com/w/cpp/named_req/Compare).
+ assert(is_self_equivalent(lhs));
+ assert(is_self_equivalent(rhs));
+ const bool lhs_comp_rhs = comp()(lhs, rhs);
+ assert(!lhs_comp_rhs || !comp()(rhs, lhs));
+ return lhs_comp_rhs;
+ }
+
+ template <
+ typename T, typename U,
+ absl::enable_if_t<std::is_convertible<compare_result_t<Compare, T, U>,
+ absl::weak_ordering>::value,
+ int> = 0>
+ absl::weak_ordering operator()(const T &lhs, const U &rhs) const {
+ // NOTE: if any of these assertions fail, then the comparator does not
+ // establish a strict-weak-ordering (see
+ // https://en.cppreference.com/w/cpp/named_req/Compare).
+ assert(is_self_equivalent(lhs));
+ assert(is_self_equivalent(rhs));
+ const absl::weak_ordering lhs_comp_rhs = comp()(lhs, rhs);
+#ifndef NDEBUG
+ const absl::weak_ordering rhs_comp_lhs = comp()(rhs, lhs);
+ if (lhs_comp_rhs > 0) {
+ assert(rhs_comp_lhs < 0 && "lhs_comp_rhs > 0 -> rhs_comp_lhs < 0");
+ } else if (lhs_comp_rhs == 0) {
+ assert(rhs_comp_lhs == 0 && "lhs_comp_rhs == 0 -> rhs_comp_lhs == 0");
+ } else {
+ assert(rhs_comp_lhs > 0 && "lhs_comp_rhs < 0 -> rhs_comp_lhs > 0");
+ }
+#endif
+ return lhs_comp_rhs;
+ }
+ };
+ using type = absl::conditional_t<
+ std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase, Compare>::value,
+ Compare, checked_compare>;
+};
+
+template <>
+struct key_compare_adapter<std::less<std::string>, std::string> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_adapter<std::greater<std::string>, std::string> {
+ using type = StringBtreeDefaultGreater;
+};
+
+template <>
+struct key_compare_adapter<std::less<absl::string_view>, absl::string_view> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_adapter<std::greater<absl::string_view>, absl::string_view> {
+ using type = StringBtreeDefaultGreater;
+};
+
+template <>
+struct key_compare_adapter<std::less<absl::Cord>, absl::Cord> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_adapter<std::greater<absl::Cord>, absl::Cord> {
+ using type = StringBtreeDefaultGreater;
+};
+
+// Detects an 'absl_btree_prefer_linear_node_search' member. This is
+// a protocol used as an opt-in or opt-out of linear search.
+//
+// For example, this would be useful for key types that wrap an integer
+// and define their own cheap operator<(). For example:
+//
+// class K {
+// public:
+// using absl_btree_prefer_linear_node_search = std::true_type;
+// ...
+// private:
+// friend bool operator<(K a, K b) { return a.k_ < b.k_; }
+// int k_;
+// };
+//
+// btree_map<K, V> m; // Uses linear search
+//
+// If T has the preference tag, then it has a preference.
+// Btree will use the tag's truth value.
+template <typename T, typename = void>
+struct has_linear_node_search_preference : std::false_type {};
+template <typename T, typename = void>
+struct prefers_linear_node_search : std::false_type {};
+template <typename T>
+struct has_linear_node_search_preference<
+ T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+ : std::true_type {};
+template <typename T>
+struct prefers_linear_node_search<
+ T, absl::void_t<typename T::absl_btree_prefer_linear_node_search>>
+ : T::absl_btree_prefer_linear_node_search {};
+
+template <typename Compare, typename Key>
+constexpr bool compare_has_valid_result_type() {
+ using compare_result_type = compare_result_t<Compare, Key, Key>;
+ return std::is_same<compare_result_type, bool>::value ||
+ std::is_convertible<compare_result_type, absl::weak_ordering>::value;
+}
+
+template <typename original_key_compare, typename value_type>
+class map_value_compare {
+ template <typename Params>
+ friend class btree;
+
+ // Note: this `protected` is part of the API of std::map::value_compare. See
+ // https://en.cppreference.com/w/cpp/container/map/value_compare.
+ protected:
+ explicit map_value_compare(original_key_compare c) : comp(std::move(c)) {}
+
+ original_key_compare comp; // NOLINT
+
+ public:
+ auto operator()(const value_type &lhs, const value_type &rhs) const
+ -> decltype(comp(lhs.first, rhs.first)) {
+ return comp(lhs.first, rhs.first);
+ }
+};
+
+template <typename Key, typename Compare, typename Alloc, int TargetNodeSize,
+ bool IsMulti, bool IsMap, typename SlotPolicy>
+struct common_params : common_policy_traits<SlotPolicy> {
+ using original_key_compare = Compare;
+
+ // If Compare is a common comparator for a string-like type, then we adapt it
+ // to use heterogeneous lookup and to be a key-compare-to comparator.
+ // We also adapt the comparator to diagnose invalid comparators in debug mode.
+ // We disable this when `Compare` is invalid in a way that will cause
+ // adaptation to fail (having invalid return type) so that we can give a
+ // better compilation failure in static_assert_validation. If we don't do
+ // this, then there will be cascading compilation failures that are confusing
+ // for users.
+ using key_compare =
+ absl::conditional_t<!compare_has_valid_result_type<Compare, Key>(),
+ Compare,
+ typename key_compare_adapter<Compare, Key>::type>;
+
+ static constexpr bool kIsKeyCompareStringAdapted =
+ std::is_same<key_compare, StringBtreeDefaultLess>::value ||
+ std::is_same<key_compare, StringBtreeDefaultGreater>::value;
+ static constexpr bool kIsKeyCompareTransparent =
+ IsTransparent<original_key_compare>::value || kIsKeyCompareStringAdapted;
+
+ // A type which indicates if we have a key-compare-to functor or a plain old
+ // key-compare functor.
+ using is_key_compare_to = btree_is_key_compare_to<key_compare, Key>;
+
+ using allocator_type = Alloc;
+ using key_type = Key;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+
+ using slot_policy = SlotPolicy;
+ using slot_type = typename slot_policy::slot_type;
+ using value_type = typename slot_policy::value_type;
+ using init_type = typename slot_policy::mutable_value_type;
+ using pointer = value_type *;
+ using const_pointer = const value_type *;
+ using reference = value_type &;
+ using const_reference = const value_type &;
+
+ using value_compare =
+ absl::conditional_t<IsMap,
+ map_value_compare<original_key_compare, value_type>,
+ original_key_compare>;
+ using is_map_container = std::integral_constant<bool, IsMap>;
+
+ // For the given lookup key type, returns whether we can have multiple
+ // equivalent keys in the btree. If this is a multi-container, then we can.
+ // Otherwise, we can have multiple equivalent keys only if all of the
+ // following conditions are met:
+ // - The comparator is transparent.
+ // - The lookup key type is not the same as key_type.
+ // - The comparator is not a StringBtreeDefault{Less,Greater} comparator
+ // that we know has the same equivalence classes for all lookup types.
+ template <typename LookupKey>
+ constexpr static bool can_have_multiple_equivalent_keys() {
+ return IsMulti || (IsTransparent<key_compare>::value &&
+ !std::is_same<LookupKey, Key>::value &&
+ !kIsKeyCompareStringAdapted);
+ }
+
+ enum {
+ kTargetNodeSize = TargetNodeSize,
+
+ // Upper bound for the available space for slots. This is largest for leaf
+ // nodes, which have overhead of at least a pointer + 4 bytes (for storing
+ // 3 field_types and an enum).
+ kNodeSlotSpace = TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4),
+ };
+
+ // This is an integral type large enough to hold as many slots as will fit a
+ // node of TargetNodeSize bytes.
+ using node_count_type =
+ absl::conditional_t<(kNodeSlotSpace / sizeof(slot_type) >
+ (std::numeric_limits<uint8_t>::max)()),
+ uint16_t, uint8_t>; // NOLINT
+};
+
+// An adapter class that converts a lower-bound compare into an upper-bound
+// compare. Note: there is no need to make a version of this adapter specialized
+// for key-compare-to functors because the upper-bound (the first value greater
+// than the input) is never an exact match.
+template <typename Compare>
+struct upper_bound_adapter {
+ explicit upper_bound_adapter(const Compare &c) : comp(c) {}
+ template <typename K1, typename K2>
+ bool operator()(const K1 &a, const K2 &b) const {
+ // Returns true when a is not greater than b.
+ return !compare_internal::compare_result_as_less_than(comp(b, a));
+ }
+
+ private:
+ Compare comp;
+};
+
+enum class MatchKind : uint8_t { kEq, kNe };
+
+template <typename V, bool IsCompareTo>
+struct SearchResult {
+ V value;
+ MatchKind match;
+
+ static constexpr bool HasMatch() { return true; }
+ bool IsEq() const { return match == MatchKind::kEq; }
+};
+
+// When we don't use CompareTo, `match` is not present.
+// This ensures that callers can't use it accidentally when it provides no
+// useful information.
+template <typename V>
+struct SearchResult<V, false> {
+ SearchResult() = default;
+ explicit SearchResult(V v) : value(v) {}
+ SearchResult(V v, MatchKind /*match*/) : value(v) {}
+
+ V value;
+
+ static constexpr bool HasMatch() { return false; }
+ static constexpr bool IsEq() { return false; }
+};
+
+// A node in the btree holding. The same node type is used for both internal
+// and leaf nodes in the btree, though the nodes are allocated in such a way
+// that the children array is only valid in internal nodes.
+template <typename Params>
+class btree_node {
+ using is_key_compare_to = typename Params::is_key_compare_to;
+ using field_type = typename Params::node_count_type;
+ using allocator_type = typename Params::allocator_type;
+ using slot_type = typename Params::slot_type;
+ using original_key_compare = typename Params::original_key_compare;
+
+ public:
+ using params_type = Params;
+ using key_type = typename Params::key_type;
+ using value_type = typename Params::value_type;
+ using pointer = typename Params::pointer;
+ using const_pointer = typename Params::const_pointer;
+ using reference = typename Params::reference;
+ using const_reference = typename Params::const_reference;
+ using key_compare = typename Params::key_compare;
+ using size_type = typename Params::size_type;
+ using difference_type = typename Params::difference_type;
+
+ // Btree decides whether to use linear node search as follows:
+ // - If the comparator expresses a preference, use that.
+ // - If the key expresses a preference, use that.
+ // - If the key is arithmetic and the comparator is std::less or
+ // std::greater, choose linear.
+ // - Otherwise, choose binary.
+ // TODO(ezb): Might make sense to add condition(s) based on node-size.
+ using use_linear_search = std::integral_constant<
+ bool, has_linear_node_search_preference<original_key_compare>::value
+ ? prefers_linear_node_search<original_key_compare>::value
+ : has_linear_node_search_preference<key_type>::value
+ ? prefers_linear_node_search<key_type>::value
+ : std::is_arithmetic<key_type>::value &&
+ (std::is_same<std::less<key_type>,
+ original_key_compare>::value ||
+ std::is_same<std::greater<key_type>,
+ original_key_compare>::value)>;
+
+ // This class is organized by absl::container_internal::Layout as if it had
+ // the following structure:
+ // // A pointer to the node's parent.
+ // btree_node *parent;
+ //
+ // // When ABSL_BTREE_ENABLE_GENERATIONS is defined, we also have a
+ // // generation integer in order to check that when iterators are
+ // // used, they haven't been invalidated already. Only the generation on
+ // // the root is used, but we have one on each node because whether a node
+ // // is root or not can change.
+ // uint32_t generation;
+ //
+ // // The position of the node in the node's parent.
+ // field_type position;
+ // // The index of the first populated value in `values`.
+ // // TODO(ezb): right now, `start` is always 0. Update insertion/merge
+ // // logic to allow for floating storage within nodes.
+ // field_type start;
+ // // The index after the last populated value in `values`. Currently, this
+ // // is the same as the count of values.
+ // field_type finish;
+ // // The maximum number of values the node can hold. This is an integer in
+ // // [1, kNodeSlots] for root leaf nodes, kNodeSlots for non-root leaf
+ // // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal
+ // // nodes (even though there are still kNodeSlots values in the node).
+ // // TODO(ezb): make max_count use only 4 bits and record log2(capacity)
+ // // to free extra bits for is_root, etc.
+ // field_type max_count;
+ //
+ // // The array of values. The capacity is `max_count` for leaf nodes and
+ // // kNodeSlots for internal nodes. Only the values in
+ // // [start, finish) have been initialized and are valid.
+ // slot_type values[max_count];
+ //
+ // // The array of child pointers. The keys in children[i] are all less
+ // // than key(i). The keys in children[i + 1] are all greater than key(i).
+ // // There are 0 children for leaf nodes and kNodeSlots + 1 children for
+ // // internal nodes.
+ // btree_node *children[kNodeSlots + 1];
+ //
+ // This class is only constructed by EmptyNodeType. Normally, pointers to the
+ // layout above are allocated, cast to btree_node*, and de-allocated within
+ // the btree implementation.
+ ~btree_node() = default;
+ btree_node(btree_node const &) = delete;
+ btree_node &operator=(btree_node const &) = delete;
+
+ protected:
+ btree_node() = default;
+
+ private:
+ using layout_type =
+ absl::container_internal::Layout<btree_node *, uint32_t, field_type,
+ slot_type, btree_node *>;
+ using leaf_layout_type = typename layout_type::template WithStaticSizes<
+ /*parent*/ 1,
+ /*generation*/ BtreeGenerationsEnabled() ? 1 : 0,
+ /*position, start, finish, max_count*/ 4>;
+ constexpr static size_type SizeWithNSlots(size_type n) {
+ return leaf_layout_type(/*slots*/ n, /*children*/ 0).AllocSize();
+ }
+ // A lower bound for the overhead of fields other than slots in a leaf node.
+ constexpr static size_type MinimumOverhead() {
+ return SizeWithNSlots(1) - sizeof(slot_type);
+ }
+
+ // Compute how many values we can fit onto a leaf node taking into account
+ // padding.
+ constexpr static size_type NodeTargetSlots(const size_type begin,
+ const size_type end) {
+ return begin == end ? begin
+ : SizeWithNSlots((begin + end) / 2 + 1) >
+ params_type::kTargetNodeSize
+ ? NodeTargetSlots(begin, (begin + end) / 2)
+ : NodeTargetSlots((begin + end) / 2 + 1, end);
+ }
+
+ constexpr static size_type kTargetNodeSize = params_type::kTargetNodeSize;
+ constexpr static size_type kNodeTargetSlots =
+ NodeTargetSlots(0, kTargetNodeSize);
+
+ // We need a minimum of 3 slots per internal node in order to perform
+ // splitting (1 value for the two nodes involved in the split and 1 value
+ // propagated to the parent as the delimiter for the split). For performance
+ // reasons, we don't allow 3 slots-per-node due to bad worst case occupancy of
+ // 1/3 (for a node, not a b-tree).
+ constexpr static size_type kMinNodeSlots = 4;
+
+ constexpr static size_type kNodeSlots =
+ kNodeTargetSlots >= kMinNodeSlots ? kNodeTargetSlots : kMinNodeSlots;
+
+ using internal_layout_type = typename layout_type::template WithStaticSizes<
+ /*parent*/ 1,
+ /*generation*/ BtreeGenerationsEnabled() ? 1 : 0,
+ /*position, start, finish, max_count*/ 4, /*slots*/ kNodeSlots,
+ /*children*/ kNodeSlots + 1>;
+
+ // The node is internal (i.e. is not a leaf node) if and only if `max_count`
+ // has this value.
+ constexpr static field_type kInternalNodeMaxCount = 0;
+
+ // Leaves can have less than kNodeSlots values.
+ constexpr static leaf_layout_type LeafLayout(
+ const size_type slot_count = kNodeSlots) {
+ return leaf_layout_type(slot_count, 0);
+ }
+ constexpr static auto InternalLayout() { return internal_layout_type(); }
+ constexpr static size_type LeafSize(const size_type slot_count = kNodeSlots) {
+ return LeafLayout(slot_count).AllocSize();
+ }
+ constexpr static size_type InternalSize() {
+ return InternalLayout().AllocSize();
+ }
+
+ constexpr static size_type Alignment() {
+ static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
+ "Alignment of all nodes must be equal.");
+ return InternalLayout().Alignment();
+ }
+
+ // N is the index of the type in the Layout definition.
+ // ElementType<N> is the Nth type in the Layout definition.
+ template <size_type N>
+ inline typename layout_type::template ElementType<N> *GetField() {
+ // We assert that we don't read from values that aren't there.
+ assert(N < 4 || is_internal());
+ return InternalLayout().template Pointer<N>(reinterpret_cast<char *>(this));
+ }
+ template <size_type N>
+ inline const typename layout_type::template ElementType<N> *GetField() const {
+ assert(N < 4 || is_internal());
+ return InternalLayout().template Pointer<N>(
+ reinterpret_cast<const char *>(this));
+ }
+ void set_parent(btree_node *p) { *GetField<0>() = p; }
+ field_type &mutable_finish() { return GetField<2>()[2]; }
+ slot_type *slot(size_type i) { return &GetField<3>()[i]; }
+ slot_type *start_slot() { return slot(start()); }
+ slot_type *finish_slot() { return slot(finish()); }
+ const slot_type *slot(size_type i) const { return &GetField<3>()[i]; }
+ void set_position(field_type v) { GetField<2>()[0] = v; }
+ void set_start(field_type v) { GetField<2>()[1] = v; }
+ void set_finish(field_type v) { GetField<2>()[2] = v; }
+ // This method is only called by the node init methods.
+ void set_max_count(field_type v) { GetField<2>()[3] = v; }
+
+ public:
+ // Whether this is a leaf node or not. This value doesn't change after the
+ // node is created.
+ bool is_leaf() const { return GetField<2>()[3] != kInternalNodeMaxCount; }
+ // Whether this is an internal node or not. This value doesn't change after
+ // the node is created.
+ bool is_internal() const { return !is_leaf(); }
+
+ // Getter for the position of this node in its parent.
+ field_type position() const { return GetField<2>()[0]; }
+
+ // Getter for the offset of the first value in the `values` array.
+ field_type start() const {
+ // TODO(ezb): when floating storage is implemented, return GetField<2>()[1];
+ assert(GetField<2>()[1] == 0);
+ return 0;
+ }
+
+ // Getter for the offset after the last value in the `values` array.
+ field_type finish() const { return GetField<2>()[2]; }
+
+ // Getters for the number of values stored in this node.
+ field_type count() const {
+ assert(finish() >= start());
+ return finish() - start();
+ }
+ field_type max_count() const {
+ // Internal nodes have max_count==kInternalNodeMaxCount.
+ // Leaf nodes have max_count in [1, kNodeSlots].
+ const field_type max_count = GetField<2>()[3];
+ return max_count == field_type{kInternalNodeMaxCount}
+ ? field_type{kNodeSlots}
+ : max_count;
+ }
+
+ // Getter for the parent of this node.
+ btree_node *parent() const { return *GetField<0>(); }
+ // Getter for whether the node is the root of the tree. The parent of the
+ // root of the tree is the leftmost node in the tree which is guaranteed to
+ // be a leaf.
+ bool is_root() const { return parent()->is_leaf(); }
+ void make_root() {
+ assert(parent()->is_root());
+ set_generation(parent()->generation());
+ set_parent(parent()->parent());
+ }
+
+ // Gets the root node's generation integer, which is the one used by the tree.
+ uint32_t *get_root_generation() const {
+ assert(BtreeGenerationsEnabled());
+ const btree_node *curr = this;
+ for (; !curr->is_root(); curr = curr->parent()) continue;
+ return const_cast<uint32_t *>(&curr->GetField<1>()[0]);
+ }
+
+ // Returns the generation for iterator validation.
+ uint32_t generation() const {
+ return BtreeGenerationsEnabled() ? *get_root_generation() : 0;
+ }
+ // Updates generation. Should only be called on a root node or during node
+ // initialization.
+ void set_generation(uint32_t generation) {
+ if (BtreeGenerationsEnabled()) GetField<1>()[0] = generation;
+ }
+ // Updates the generation. We do this whenever the node is mutated.
+ void next_generation() {
+ if (BtreeGenerationsEnabled()) ++*get_root_generation();
+ }
+
+ // Getters for the key/value at position i in the node.
+ const key_type &key(size_type i) const { return params_type::key(slot(i)); }
+ reference value(size_type i) { return params_type::element(slot(i)); }
+ const_reference value(size_type i) const {
+ return params_type::element(slot(i));
+ }
+
+ // Getters/setter for the child at position i in the node.
+ btree_node *child(field_type i) const { return GetField<4>()[i]; }
+ btree_node *start_child() const { return child(start()); }
+ btree_node *&mutable_child(field_type i) { return GetField<4>()[i]; }
+ void clear_child(field_type i) {
+ absl::container_internal::SanitizerPoisonObject(&mutable_child(i));
+ }
+ void set_child_noupdate_position(field_type i, btree_node *c) {
+ absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i));
+ mutable_child(i) = c;
+ }
+ void set_child(field_type i, btree_node *c) {
+ set_child_noupdate_position(i, c);
+ c->set_position(i);
+ }
+ void init_child(field_type i, btree_node *c) {
+ set_child(i, c);
+ c->set_parent(this);
+ }
+
+ // Returns the position of the first value whose key is not less than k.
+ template <typename K>
+ SearchResult<size_type, is_key_compare_to::value> lower_bound(
+ const K &k, const key_compare &comp) const {
+ return use_linear_search::value ? linear_search(k, comp)
+ : binary_search(k, comp);
+ }
+ // Returns the position of the first value whose key is greater than k.
+ template <typename K>
+ size_type upper_bound(const K &k, const key_compare &comp) const {
+ auto upper_compare = upper_bound_adapter<key_compare>(comp);
+ return use_linear_search::value ? linear_search(k, upper_compare).value
+ : binary_search(k, upper_compare).value;
+ }
+
+ template <typename K, typename Compare>
+ SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
+ linear_search(const K &k, const Compare &comp) const {
+ return linear_search_impl(k, start(), finish(), comp,
+ btree_is_key_compare_to<Compare, key_type>());
+ }
+
+ template <typename K, typename Compare>
+ SearchResult<size_type, btree_is_key_compare_to<Compare, key_type>::value>
+ binary_search(const K &k, const Compare &comp) const {
+ return binary_search_impl(k, start(), finish(), comp,
+ btree_is_key_compare_to<Compare, key_type>());
+ }
+
+ // Returns the position of the first value whose key is not less than k using
+ // linear search performed using plain compare.
+ template <typename K, typename Compare>
+ SearchResult<size_type, false> linear_search_impl(
+ const K &k, size_type s, const size_type e, const Compare &comp,
+ std::false_type /* IsCompareTo */) const {
+ while (s < e) {
+ if (!comp(key(s), k)) {
+ break;
+ }
+ ++s;
+ }
+ return SearchResult<size_type, false>{s};
+ }
+
+ // Returns the position of the first value whose key is not less than k using
+ // linear search performed using compare-to.
+ template <typename K, typename Compare>
+ SearchResult<size_type, true> linear_search_impl(
+ const K &k, size_type s, const size_type e, const Compare &comp,
+ std::true_type /* IsCompareTo */) const {
+ while (s < e) {
+ const absl::weak_ordering c = comp(key(s), k);
+ if (c == 0) {
+ return {s, MatchKind::kEq};
+ } else if (c > 0) {
+ break;
+ }
+ ++s;
+ }
+ return {s, MatchKind::kNe};
+ }
+
+ // Returns the position of the first value whose key is not less than k using
+ // binary search performed using plain compare.
+ template <typename K, typename Compare>
+ SearchResult<size_type, false> binary_search_impl(
+ const K &k, size_type s, size_type e, const Compare &comp,
+ std::false_type /* IsCompareTo */) const {
+ while (s != e) {
+ const size_type mid = (s + e) >> 1;
+ if (comp(key(mid), k)) {
+ s = mid + 1;
+ } else {
+ e = mid;
+ }
+ }
+ return SearchResult<size_type, false>{s};
+ }
+
+ // Returns the position of the first value whose key is not less than k using
+ // binary search performed using compare-to.
+ template <typename K, typename CompareTo>
+ SearchResult<size_type, true> binary_search_impl(
+ const K &k, size_type s, size_type e, const CompareTo &comp,
+ std::true_type /* IsCompareTo */) const {
+ if (params_type::template can_have_multiple_equivalent_keys<K>()) {
+ MatchKind exact_match = MatchKind::kNe;
+ while (s != e) {
+ const size_type mid = (s + e) >> 1;
+ const absl::weak_ordering c = comp(key(mid), k);
+ if (c < 0) {
+ s = mid + 1;
+ } else {
+ e = mid;
+ if (c == 0) {
+ // Need to return the first value whose key is not less than k,
+ // which requires continuing the binary search if there could be
+ // multiple equivalent keys.
+ exact_match = MatchKind::kEq;
+ }
+ }
+ }
+ return {s, exact_match};
+ } else { // Can't have multiple equivalent keys.
+ while (s != e) {
+ const size_type mid = (s + e) >> 1;
+ const absl::weak_ordering c = comp(key(mid), k);
+ if (c < 0) {
+ s = mid + 1;
+ } else if (c > 0) {
+ e = mid;
+ } else {
+ return {mid, MatchKind::kEq};
+ }
+ }
+ return {s, MatchKind::kNe};
+ }
+ }
+
+ // Returns whether key i is ordered correctly with respect to the other keys
+ // in the node. The motivation here is to detect comparators that violate
+ // transitivity. Note: we only do comparisons of keys on this node rather than
+ // the whole tree so that this is constant time.
+ template <typename Compare>
+ bool is_ordered_correctly(field_type i, const Compare &comp) const {
+ if (std::is_base_of<BtreeTestOnlyCheckedCompareOptOutBase,
+ Compare>::value ||
+ params_type::kIsKeyCompareStringAdapted) {
+ return true;
+ }
+
+ const auto compare = [&](field_type a, field_type b) {
+ const absl::weak_ordering cmp =
+ compare_internal::do_three_way_comparison(comp, key(a), key(b));
+ return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+ };
+ int cmp = -1;
+ constexpr bool kCanHaveEquivKeys =
+ params_type::template can_have_multiple_equivalent_keys<key_type>();
+ for (field_type j = start(); j < finish(); ++j) {
+ if (j == i) {
+ if (cmp > 0) return false;
+ continue;
+ }
+ int new_cmp = compare(j, i);
+ if (new_cmp < cmp || (!kCanHaveEquivKeys && new_cmp == 0)) return false;
+ cmp = new_cmp;
+ }
+ return true;
+ }
+
+ // Emplaces a value at position i, shifting all existing values and
+ // children at positions >= i to the right by 1.
+ template <typename... Args>
+ void emplace_value(field_type i, allocator_type *alloc, Args &&...args);
+
+ // Removes the values at positions [i, i + to_erase), shifting all existing
+ // values and children after that range to the left by to_erase. Clears all
+ // children between [i, i + to_erase).
+ void remove_values(field_type i, field_type to_erase, allocator_type *alloc);
+
+ // Rebalances a node with its right sibling.
+ void rebalance_right_to_left(field_type to_move, btree_node *right,
+ allocator_type *alloc);
+ void rebalance_left_to_right(field_type to_move, btree_node *right,
+ allocator_type *alloc);
+
+ // Splits a node, moving a portion of the node's values to its right sibling.
+ void split(int insert_position, btree_node *dest, allocator_type *alloc);
+
+ // Merges a node with its right sibling, moving all of the values and the
+ // delimiting key in the parent node onto itself, and deleting the src node.
+ void merge(btree_node *src, allocator_type *alloc);
+
+ // Node allocation/deletion routines.
+ void init_leaf(field_type position, field_type max_count,
+ btree_node *parent) {
+ set_generation(0);
+ set_parent(parent);
+ set_position(position);
+ set_start(0);
+ set_finish(0);
+ set_max_count(max_count);
+ absl::container_internal::SanitizerPoisonMemoryRegion(
+ start_slot(), max_count * sizeof(slot_type));
+ }
+ void init_internal(field_type position, btree_node *parent) {
+ init_leaf(position, kNodeSlots, parent);
+ // Set `max_count` to a sentinel value to indicate that this node is
+ // internal.
+ set_max_count(kInternalNodeMaxCount);
+ absl::container_internal::SanitizerPoisonMemoryRegion(
+ &mutable_child(start()), (kNodeSlots + 1) * sizeof(btree_node *));
+ }
+
+ static void deallocate(const size_type size, btree_node *node,
+ allocator_type *alloc) {
+ absl::container_internal::SanitizerUnpoisonMemoryRegion(node, size);
+ absl::container_internal::Deallocate<Alignment()>(alloc, node, size);
+ }
+
+ // Deletes a node and all of its children.
+ static void clear_and_delete(btree_node *node, allocator_type *alloc);
+
+ private:
+ template <typename... Args>
+ void value_init(const field_type i, allocator_type *alloc, Args &&...args) {
+ next_generation();
+ absl::container_internal::SanitizerUnpoisonObject(slot(i));
+ params_type::construct(alloc, slot(i), std::forward<Args>(args)...);
+ }
+ void value_destroy(const field_type i, allocator_type *alloc) {
+ next_generation();
+ params_type::destroy(alloc, slot(i));
+ absl::container_internal::SanitizerPoisonObject(slot(i));
+ }
+ void value_destroy_n(const field_type i, const field_type n,
+ allocator_type *alloc) {
+ next_generation();
+ for (slot_type *s = slot(i), *end = slot(i + n); s != end; ++s) {
+ params_type::destroy(alloc, s);
+ absl::container_internal::SanitizerPoisonObject(s);
+ }
+ }
+
+ static void transfer(slot_type *dest, slot_type *src, allocator_type *alloc) {
+ absl::container_internal::SanitizerUnpoisonObject(dest);
+ params_type::transfer(alloc, dest, src);
+ absl::container_internal::SanitizerPoisonObject(src);
+ }
+
+ // Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`.
+ void transfer(const size_type dest_i, const size_type src_i,
+ btree_node *src_node, allocator_type *alloc) {
+ next_generation();
+ transfer(slot(dest_i), src_node->slot(src_i), alloc);
+ }
+
+ // Transfers `n` values starting at value `src_i` in `src_node` into the
+ // values starting at value `dest_i` in `this`.
+ void transfer_n(const size_type n, const size_type dest_i,
+ const size_type src_i, btree_node *src_node,
+ allocator_type *alloc) {
+ next_generation();
+ for (slot_type *src = src_node->slot(src_i), *end = src + n,
+ *dest = slot(dest_i);
+ src != end; ++src, ++dest) {
+ transfer(dest, src, alloc);
+ }
+ }
+
+ // Same as above, except that we start at the end and work our way to the
+ // beginning.
+ void transfer_n_backward(const size_type n, const size_type dest_i,
+ const size_type src_i, btree_node *src_node,
+ allocator_type *alloc) {
+ next_generation();
+ for (slot_type *src = src_node->slot(src_i + n), *end = src - n,
+ *dest = slot(dest_i + n);
+ src != end; --src, --dest) {
+ // If we modified the loop index calculations above to avoid the -1s here,
+ // it would result in UB in the computation of `end` (and possibly `src`
+ // as well, if n == 0), since slot() is effectively an array index and it
+ // is UB to compute the address of any out-of-bounds array element except
+ // for one-past-the-end.
+ transfer(dest - 1, src - 1, alloc);
+ }
+ }
+
+ template <typename P>
+ friend class btree;
+ template <typename N, typename R, typename P>
+ friend class btree_iterator;
+ friend class BtreeNodePeer;
+ friend struct btree_access;
+};
+
+template <typename Node>
+bool AreNodesFromSameContainer(const Node *node_a, const Node *node_b) {
+ // If either node is null, then give up on checking whether they're from the
+ // same container. (If exactly one is null, then we'll trigger the
+ // default-constructed assert in Equals.)
+ if (node_a == nullptr || node_b == nullptr) return true;
+ while (!node_a->is_root()) node_a = node_a->parent();
+ while (!node_b->is_root()) node_b = node_b->parent();
+ return node_a == node_b;
+}
+
+class btree_iterator_generation_info_enabled {
+ public:
+ explicit btree_iterator_generation_info_enabled(uint32_t g)
+ : generation_(g) {}
+
+ // Updates the generation. For use internally right before we return an
+ // iterator to the user.
+ template <typename Node>
+ void update_generation(const Node *node) {
+ if (node != nullptr) generation_ = node->generation();
+ }
+ uint32_t generation() const { return generation_; }
+
+ template <typename Node>
+ void assert_valid_generation(const Node *node) const {
+ if (node != nullptr && node->generation() != generation_) {
+ ABSL_INTERNAL_LOG(
+ FATAL,
+ "Attempting to use an invalidated iterator. The corresponding b-tree "
+ "container has been mutated since this iterator was constructed.");
+ }
+ }
+
+ private:
+ // Used to check that the iterator hasn't been invalidated.
+ uint32_t generation_;
+};
+
+class btree_iterator_generation_info_disabled {
+ public:
+ explicit btree_iterator_generation_info_disabled(uint32_t) {}
+ static void update_generation(const void *) {}
+ static uint32_t generation() { return 0; }
+ static void assert_valid_generation(const void *) {}
+};
+
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+using btree_iterator_generation_info = btree_iterator_generation_info_enabled;
+#else
+using btree_iterator_generation_info = btree_iterator_generation_info_disabled;
+#endif
+
+template <typename Node, typename Reference, typename Pointer>
+class btree_iterator : private btree_iterator_generation_info {
+ using field_type = typename Node::field_type;
+ using key_type = typename Node::key_type;
+ using size_type = typename Node::size_type;
+ using params_type = typename Node::params_type;
+ using is_map_container = typename params_type::is_map_container;
+
+ using node_type = Node;
+ using normal_node = typename std::remove_const<Node>::type;
+ using const_node = const Node;
+ using normal_pointer = typename params_type::pointer;
+ using normal_reference = typename params_type::reference;
+ using const_pointer = typename params_type::const_pointer;
+ using const_reference = typename params_type::const_reference;
+ using slot_type = typename params_type::slot_type;
+
+ // In sets, all iterators are const.
+ using iterator = absl::conditional_t<
+ is_map_container::value,
+ btree_iterator<normal_node, normal_reference, normal_pointer>,
+ btree_iterator<normal_node, const_reference, const_pointer>>;
+ using const_iterator =
+ btree_iterator<const_node, const_reference, const_pointer>;
+
+ public:
+ // These aliases are public for std::iterator_traits.
+ using difference_type = typename Node::difference_type;
+ using value_type = typename params_type::value_type;
+ using pointer = Pointer;
+ using reference = Reference;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ btree_iterator() : btree_iterator(nullptr, -1) {}
+ explicit btree_iterator(Node *n) : btree_iterator(n, n->start()) {}
+ btree_iterator(Node *n, int p)
+ : btree_iterator_generation_info(n != nullptr ? n->generation()
+ : ~uint32_t{}),
+ node_(n),
+ position_(p) {}
+
+ // NOTE: this SFINAE allows for implicit conversions from iterator to
+ // const_iterator, but it specifically avoids hiding the copy constructor so
+ // that the trivial one will be used when possible.
+ template <typename N, typename R, typename P,
+ absl::enable_if_t<
+ std::is_same<btree_iterator<N, R, P>, iterator>::value &&
+ std::is_same<btree_iterator, const_iterator>::value,
+ int> = 0>
+ btree_iterator(const btree_iterator<N, R, P> other) // NOLINT
+ : btree_iterator_generation_info(other),
+ node_(other.node_),
+ position_(other.position_) {}
+
+ bool operator==(const iterator &other) const {
+ return Equals(other);
+ }
+ bool operator==(const const_iterator &other) const {
+ return Equals(other);
+ }
+ bool operator!=(const iterator &other) const {
+ return !Equals(other);
+ }
+ bool operator!=(const const_iterator &other) const {
+ return !Equals(other);
+ }
+
+ // Returns n such that n calls to ++other yields *this.
+ // Precondition: n exists.
+ difference_type operator-(const_iterator other) const {
+ if (node_ == other.node_) {
+ if (node_->is_leaf()) return position_ - other.position_;
+ if (position_ == other.position_) return 0;
+ }
+ return distance_slow(other);
+ }
+
+ // Accessors for the key/value the iterator is pointing at.
+ reference operator*() const {
+ ABSL_HARDENING_ASSERT(node_ != nullptr);
+ assert_valid_generation(node_);
+ ABSL_HARDENING_ASSERT(position_ >= node_->start());
+ if (position_ >= node_->finish()) {
+ ABSL_HARDENING_ASSERT(!IsEndIterator() && "Dereferencing end() iterator");
+ ABSL_HARDENING_ASSERT(position_ < node_->finish());
+ }
+ return node_->value(static_cast<field_type>(position_));
+ }
+ pointer operator->() const { return &operator*(); }
+
+ btree_iterator &operator++() {
+ increment();
+ return *this;
+ }
+ btree_iterator &operator--() {
+ decrement();
+ return *this;
+ }
+ btree_iterator operator++(int) {
+ btree_iterator tmp = *this;
+ ++*this;
+ return tmp;
+ }
+ btree_iterator operator--(int) {
+ btree_iterator tmp = *this;
+ --*this;
+ return tmp;
+ }
+
+ private:
+ friend iterator;
+ friend const_iterator;
+ template <typename Params>
+ friend class btree;
+ template <typename Tree>
+ friend class btree_container;
+ template <typename Tree>
+ friend class btree_set_container;
+ template <typename Tree>
+ friend class btree_map_container;
+ template <typename Tree>
+ friend class btree_multiset_container;
+ template <typename TreeType, typename CheckerType>
+ friend class base_checker;
+ friend struct btree_access;
+
+ // This SFINAE allows explicit conversions from const_iterator to
+ // iterator, but also avoids hiding the copy constructor.
+ // NOTE: the const_cast is safe because this constructor is only called by
+ // non-const methods and the container owns the nodes.
+ template <typename N, typename R, typename P,
+ absl::enable_if_t<
+ std::is_same<btree_iterator<N, R, P>, const_iterator>::value &&
+ std::is_same<btree_iterator, iterator>::value,
+ int> = 0>
+ explicit btree_iterator(const btree_iterator<N, R, P> other)
+ : btree_iterator_generation_info(other.generation()),
+ node_(const_cast<node_type *>(other.node_)),
+ position_(other.position_) {}
+
+ bool Equals(const const_iterator other) const {
+ ABSL_HARDENING_ASSERT(((node_ == nullptr && other.node_ == nullptr) ||
+ (node_ != nullptr && other.node_ != nullptr)) &&
+ "Comparing default-constructed iterator with "
+ "non-default-constructed iterator.");
+ // Note: we use assert instead of ABSL_HARDENING_ASSERT here because this
+ // changes the complexity of Equals from O(1) to O(log(N) + log(M)) where
+ // N/M are sizes of the containers containing node_/other.node_.
+ assert(AreNodesFromSameContainer(node_, other.node_) &&
+ "Comparing iterators from different containers.");
+ assert_valid_generation(node_);
+ other.assert_valid_generation(other.node_);
+ return node_ == other.node_ && position_ == other.position_;
+ }
+
+ bool IsEndIterator() const {
+ if (position_ != node_->finish()) return false;
+ node_type *node = node_;
+ while (!node->is_root()) {
+ if (node->position() != node->parent()->finish()) return false;
+ node = node->parent();
+ }
+ return true;
+ }
+
+ // Returns n such that n calls to ++other yields *this.
+ // Precondition: n exists && (this->node_ != other.node_ ||
+ // !this->node_->is_leaf() || this->position_ != other.position_).
+ difference_type distance_slow(const_iterator other) const;
+
+ // Increment/decrement the iterator.
+ void increment() {
+ assert_valid_generation(node_);
+ if (node_->is_leaf() && ++position_ < node_->finish()) {
+ return;
+ }
+ increment_slow();
+ }
+ void increment_slow();
+
+ void decrement() {
+ assert_valid_generation(node_);
+ if (node_->is_leaf() && --position_ >= node_->start()) {
+ return;
+ }
+ decrement_slow();
+ }
+ void decrement_slow();
+
+ const key_type &key() const {
+ return node_->key(static_cast<size_type>(position_));
+ }
+ decltype(std::declval<Node *>()->slot(0)) slot() {
+ return node_->slot(static_cast<size_type>(position_));
+ }
+
+ void update_generation() {
+ btree_iterator_generation_info::update_generation(node_);
+ }
+
+ // The node in the tree the iterator is pointing at.
+ Node *node_;
+ // The position within the node of the tree the iterator is pointing at.
+ // NOTE: this is an int rather than a field_type because iterators can point
+ // to invalid positions (such as -1) in certain circumstances.
+ int position_;
+};
+
+template <typename Params>
+class btree {
+ using node_type = btree_node<Params>;
+ using is_key_compare_to = typename Params::is_key_compare_to;
+ using field_type = typename node_type::field_type;
+
+ // We use a static empty node for the root/leftmost/rightmost of empty btrees
+ // in order to avoid branching in begin()/end().
+ struct EmptyNodeType : node_type {
+ using field_type = typename node_type::field_type;
+ node_type *parent;
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+ uint32_t generation = 0;
+#endif
+ field_type position = 0;
+ field_type start = 0;
+ field_type finish = 0;
+ // max_count must be != kInternalNodeMaxCount (so that this node is regarded
+ // as a leaf node). max_count() is never called when the tree is empty.
+ field_type max_count = node_type::kInternalNodeMaxCount + 1;
+
+ constexpr EmptyNodeType() : parent(this) {}
+ };
+
+ static node_type *EmptyNode() {
+ alignas(node_type::Alignment()) static constexpr EmptyNodeType empty_node;
+ return const_cast<EmptyNodeType *>(&empty_node);
+ }
+
+ enum : uint32_t {
+ kNodeSlots = node_type::kNodeSlots,
+ kMinNodeValues = kNodeSlots / 2,
+ };
+
+ struct node_stats {
+ using size_type = typename Params::size_type;
+
+ node_stats(size_type l, size_type i) : leaf_nodes(l), internal_nodes(i) {}
+
+ node_stats &operator+=(const node_stats &other) {
+ leaf_nodes += other.leaf_nodes;
+ internal_nodes += other.internal_nodes;
+ return *this;
+ }
+
+ size_type leaf_nodes;
+ size_type internal_nodes;
+ };
+
+ public:
+ using key_type = typename Params::key_type;
+ using value_type = typename Params::value_type;
+ using size_type = typename Params::size_type;
+ using difference_type = typename Params::difference_type;
+ using key_compare = typename Params::key_compare;
+ using original_key_compare = typename Params::original_key_compare;
+ using value_compare = typename Params::value_compare;
+ using allocator_type = typename Params::allocator_type;
+ using reference = typename Params::reference;
+ using const_reference = typename Params::const_reference;
+ using pointer = typename Params::pointer;
+ using const_pointer = typename Params::const_pointer;
+ using iterator =
+ typename btree_iterator<node_type, reference, pointer>::iterator;
+ using const_iterator = typename iterator::const_iterator;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using node_handle_type = node_handle<Params, Params, allocator_type>;
+
+ // Internal types made public for use by btree_container types.
+ using params_type = Params;
+ using slot_type = typename Params::slot_type;
+
+ private:
+ // Copies or moves (depending on the template parameter) the values in
+ // other into this btree in their order in other. This btree must be empty
+ // before this method is called. This method is used in copy construction,
+ // copy assignment, and move assignment.
+ template <typename Btree>
+ void copy_or_move_values_in_order(Btree &other);
+
+ // Validates that various assumptions/requirements are true at compile time.
+ constexpr static bool static_assert_validation();
+
+ public:
+ btree(const key_compare &comp, const allocator_type &alloc)
+ : root_(EmptyNode()), rightmost_(comp, alloc, EmptyNode()), size_(0) {}
+
+ btree(const btree &other) : btree(other, other.allocator()) {}
+ btree(const btree &other, const allocator_type &alloc)
+ : btree(other.key_comp(), alloc) {
+ copy_or_move_values_in_order(other);
+ }
+ btree(btree &&other) noexcept
+ : root_(std::exchange(other.root_, EmptyNode())),
+ rightmost_(std::move(other.rightmost_)),
+ size_(std::exchange(other.size_, 0u)) {
+ other.mutable_rightmost() = EmptyNode();
+ }
+ btree(btree &&other, const allocator_type &alloc)
+ : btree(other.key_comp(), alloc) {
+ if (alloc == other.allocator()) {
+ swap(other);
+ } else {
+ // Move values from `other` one at a time when allocators are different.
+ copy_or_move_values_in_order(other);
+ }
+ }
+
+ ~btree() {
+ // Put static_asserts in destructor to avoid triggering them before the type
+ // is complete.
+ static_assert(static_assert_validation(), "This call must be elided.");
+ clear();
+ }
+
+ // Assign the contents of other to *this.
+ btree &operator=(const btree &other);
+ btree &operator=(btree &&other) noexcept;
+
+ iterator begin() { return iterator(leftmost()); }
+ const_iterator begin() const { return const_iterator(leftmost()); }
+ iterator end() { return iterator(rightmost(), rightmost()->finish()); }
+ const_iterator end() const {
+ return const_iterator(rightmost(), rightmost()->finish());
+ }
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator(end());
+ }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const {
+ return const_reverse_iterator(begin());
+ }
+
+ // Finds the first element whose key is not less than `key`.
+ template <typename K>
+ iterator lower_bound(const K &key) {
+ return internal_end(internal_lower_bound(key).value);
+ }
+ template <typename K>
+ const_iterator lower_bound(const K &key) const {
+ return internal_end(internal_lower_bound(key).value);
+ }
+
+ // Finds the first element whose key is not less than `key` and also returns
+ // whether that element is equal to `key`.
+ template <typename K>
+ std::pair<iterator, bool> lower_bound_equal(const K &key) const;
+
+ // Finds the first element whose key is greater than `key`.
+ template <typename K>
+ iterator upper_bound(const K &key) {
+ return internal_end(internal_upper_bound(key));
+ }
+ template <typename K>
+ const_iterator upper_bound(const K &key) const {
+ return internal_end(internal_upper_bound(key));
+ }
+
+ // Finds the range of values which compare equal to key. The first member of
+ // the returned pair is equal to lower_bound(key). The second member of the
+ // pair is equal to upper_bound(key).
+ template <typename K>
+ std::pair<iterator, iterator> equal_range(const K &key);
+ template <typename K>
+ std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
+ return const_cast<btree *>(this)->equal_range(key);
+ }
+
+ // Inserts a value into the btree only if it does not already exist. The
+ // boolean return value indicates whether insertion succeeded or failed.
+ // Requirement: if `key` already exists in the btree, does not consume `args`.
+ // Requirement: `key` is never referenced after consuming `args`.
+ template <typename K, typename... Args>
+ std::pair<iterator, bool> insert_unique(const K &key, Args &&...args);
+
+ // Inserts with hint. Checks to see if the value should be placed immediately
+ // before `position` in the tree. If so, then the insertion will take
+ // amortized constant time. If not, the insertion will take amortized
+ // logarithmic time as if a call to insert_unique() were made.
+ // Requirement: if `key` already exists in the btree, does not consume `args`.
+ // Requirement: `key` is never referenced after consuming `args`.
+ template <typename K, typename... Args>
+ std::pair<iterator, bool> insert_hint_unique(iterator position, const K &key,
+ Args &&...args);
+
+ // Insert a range of values into the btree.
+ // Note: the first overload avoids constructing a value_type if the key
+ // already exists in the btree.
+ template <typename InputIterator,
+ typename = decltype(std::declval<const key_compare &>()(
+ params_type::key(*std::declval<InputIterator>()),
+ std::declval<const key_type &>()))>
+ void insert_iterator_unique(InputIterator b, InputIterator e, int);
+ // We need the second overload for cases in which we need to construct a
+ // value_type in order to compare it with the keys already in the btree.
+ template <typename InputIterator>
+ void insert_iterator_unique(InputIterator b, InputIterator e, char);
+
+ // Inserts a value into the btree.
+ template <typename ValueType>
+ iterator insert_multi(const key_type &key, ValueType &&v);
+
+ // Inserts a value into the btree.
+ template <typename ValueType>
+ iterator insert_multi(ValueType &&v) {
+ return insert_multi(params_type::key(v), std::forward<ValueType>(v));
+ }
+
+ // Insert with hint. Check to see if the value should be placed immediately
+ // before position in the tree. If it does, then the insertion will take
+ // amortized constant time. If not, the insertion will take amortized
+ // logarithmic time as if a call to insert_multi(v) were made.
+ template <typename ValueType>
+ iterator insert_hint_multi(iterator position, ValueType &&v);
+
+ // Insert a range of values into the btree.
+ template <typename InputIterator>
+ void insert_iterator_multi(InputIterator b,
+ InputIterator e);
+
+ // Erase the specified iterator from the btree. The iterator must be valid
+ // (i.e. not equal to end()). Return an iterator pointing to the node after
+ // the one that was erased (or end() if none exists).
+ // Requirement: does not read the value at `*iter`.
+ iterator erase(iterator iter);
+
+ // Erases range. Returns the number of keys erased and an iterator pointing
+ // to the element after the last erased element.
+ std::pair<size_type, iterator> erase_range(iterator begin, iterator end);
+
+ // Finds an element with key equivalent to `key` or returns `end()` if `key`
+ // is not present.
+ template <typename K>
+ iterator find(const K &key) {
+ return internal_end(internal_find(key));
+ }
+ template <typename K>
+ const_iterator find(const K &key) const {
+ return internal_end(internal_find(key));
+ }
+
+ // Clear the btree, deleting all of the values it contains.
+ void clear();
+
+ // Swaps the contents of `this` and `other`.
+ void swap(btree &other);
+
+ const key_compare &key_comp() const noexcept {
+ return rightmost_.template get<0>();
+ }
+ template <typename K1, typename K2>
+ bool compare_keys(const K1 &a, const K2 &b) const {
+ return compare_internal::compare_result_as_less_than(key_comp()(a, b));
+ }
+
+ value_compare value_comp() const {
+ return value_compare(original_key_compare(key_comp()));
+ }
+
+ // Verifies the structure of the btree.
+ void verify() const;
+
+ // Size routines.
+ size_type size() const { return size_; }
+ size_type max_size() const { return (std::numeric_limits<size_type>::max)(); }
+ bool empty() const { return size_ == 0; }
+
+ // The height of the btree. An empty tree will have height 0.
+ size_type height() const {
+ size_type h = 0;
+ if (!empty()) {
+ // Count the length of the chain from the leftmost node up to the
+ // root. We actually count from the root back around to the level below
+ // the root, but the calculation is the same because of the circularity
+ // of that traversal.
+ const node_type *n = root();
+ do {
+ ++h;
+ n = n->parent();
+ } while (n != root());
+ }
+ return h;
+ }
+
+ // The number of internal, leaf and total nodes used by the btree.
+ size_type leaf_nodes() const { return internal_stats(root()).leaf_nodes; }
+ size_type internal_nodes() const {
+ return internal_stats(root()).internal_nodes;
+ }
+ size_type nodes() const {
+ node_stats stats = internal_stats(root());
+ return stats.leaf_nodes + stats.internal_nodes;
+ }
+
+ // The total number of bytes used by the btree.
+ // TODO(b/169338300): update to support node_btree_*.
+ size_type bytes_used() const {
+ node_stats stats = internal_stats(root());
+ if (stats.leaf_nodes == 1 && stats.internal_nodes == 0) {
+ return sizeof(*this) + node_type::LeafSize(root()->max_count());
+ } else {
+ return sizeof(*this) + stats.leaf_nodes * node_type::LeafSize() +
+ stats.internal_nodes * node_type::InternalSize();
+ }
+ }
+
+ // The average number of bytes used per value stored in the btree assuming
+ // random insertion order.
+ static double average_bytes_per_value() {
+ // The expected number of values per node with random insertion order is the
+ // average of the maximum and minimum numbers of values per node.
+ const double expected_values_per_node = (kNodeSlots + kMinNodeValues) / 2.0;
+ return node_type::LeafSize() / expected_values_per_node;
+ }
+
+ // The fullness of the btree. Computed as the number of elements in the btree
+ // divided by the maximum number of elements a tree with the current number
+ // of nodes could hold. A value of 1 indicates perfect space
+ // utilization. Smaller values indicate space wastage.
+ // Returns 0 for empty trees.
+ double fullness() const {
+ if (empty()) return 0.0;
+ return static_cast<double>(size()) / (nodes() * kNodeSlots);
+ }
+ // The overhead of the btree structure in bytes per node. Computed as the
+ // total number of bytes used by the btree minus the number of bytes used for
+ // storing elements divided by the number of elements.
+ // Returns 0 for empty trees.
+ double overhead() const {
+ if (empty()) return 0.0;
+ return (bytes_used() - size() * sizeof(value_type)) /
+ static_cast<double>(size());
+ }
+
+ // The allocator used by the btree.
+ allocator_type get_allocator() const { return allocator(); }
+
+ private:
+ friend struct btree_access;
+
+ // Internal accessor routines.
+ node_type *root() { return root_; }
+ const node_type *root() const { return root_; }
+ node_type *&mutable_root() noexcept { return root_; }
+ node_type *rightmost() { return rightmost_.template get<2>(); }
+ const node_type *rightmost() const { return rightmost_.template get<2>(); }
+ node_type *&mutable_rightmost() noexcept {
+ return rightmost_.template get<2>();
+ }
+ key_compare *mutable_key_comp() noexcept {
+ return &rightmost_.template get<0>();
+ }
+
+ // The leftmost node is stored as the parent of the root node.
+ node_type *leftmost() { return root()->parent(); }
+ const node_type *leftmost() const { return root()->parent(); }
+
+ // Allocator routines.
+ allocator_type *mutable_allocator() noexcept {
+ return &rightmost_.template get<1>();
+ }
+ const allocator_type &allocator() const noexcept {
+ return rightmost_.template get<1>();
+ }
+
+ // Allocates a correctly aligned node of at least size bytes using the
+ // allocator.
+ node_type *allocate(size_type size) {
+ return reinterpret_cast<node_type *>(
+ absl::container_internal::Allocate<node_type::Alignment()>(
+ mutable_allocator(), size));
+ }
+
+ // Node creation/deletion routines.
+ node_type *new_internal_node(field_type position, node_type *parent) {
+ node_type *n = allocate(node_type::InternalSize());
+ n->init_internal(position, parent);
+ return n;
+ }
+ node_type *new_leaf_node(field_type position, node_type *parent) {
+ node_type *n = allocate(node_type::LeafSize());
+ n->init_leaf(position, kNodeSlots, parent);
+ return n;
+ }
+ node_type *new_leaf_root_node(field_type max_count) {
+ node_type *n = allocate(node_type::LeafSize(max_count));
+ n->init_leaf(/*position=*/0, max_count, /*parent=*/n);
+ return n;
+ }
+
+ // Deletion helper routines.
+ iterator rebalance_after_delete(iterator iter);
+
+ // Rebalances or splits the node iter points to.
+ void rebalance_or_split(iterator *iter);
+
+ // Merges the values of left, right and the delimiting key on their parent
+ // onto left, removing the delimiting key and deleting right.
+ void merge_nodes(node_type *left, node_type *right);
+
+ // Tries to merge node with its left or right sibling, and failing that,
+ // rebalance with its left or right sibling. Returns true if a merge
+ // occurred, at which point it is no longer valid to access node. Returns
+ // false if no merging took place.
+ bool try_merge_or_rebalance(iterator *iter);
+
+ // Tries to shrink the height of the tree by 1.
+ void try_shrink();
+
+ iterator internal_end(iterator iter) {
+ return iter.node_ != nullptr ? iter : end();
+ }
+ const_iterator internal_end(const_iterator iter) const {
+ return iter.node_ != nullptr ? iter : end();
+ }
+
+ // Emplaces a value into the btree immediately before iter. Requires that
+ // key(v) <= iter.key() and (--iter).key() <= key(v).
+ template <typename... Args>
+ iterator internal_emplace(iterator iter, Args &&...args);
+
+ // Returns an iterator pointing to the first value >= the value "iter" is
+ // pointing at. Note that "iter" might be pointing to an invalid location such
+ // as iter.position_ == iter.node_->finish(). This routine simply moves iter
+ // up in the tree to a valid location. Requires: iter.node_ is non-null.
+ template <typename IterType>
+ static IterType internal_last(IterType iter);
+
+ // Returns an iterator pointing to the leaf position at which key would
+ // reside in the tree, unless there is an exact match - in which case, the
+ // result may not be on a leaf. When there's a three-way comparator, we can
+ // return whether there was an exact match. This allows the caller to avoid a
+ // subsequent comparison to determine if an exact match was made, which is
+ // important for keys with expensive comparison, such as strings.
+ template <typename K>
+ SearchResult<iterator, is_key_compare_to::value> internal_locate(
+ const K &key) const;
+
+ // Internal routine which implements lower_bound().
+ template <typename K>
+ SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
+ const K &key) const;
+
+ // Internal routine which implements upper_bound().
+ template <typename K>
+ iterator internal_upper_bound(const K &key) const;
+
+ // Internal routine which implements find().
+ template <typename K>
+ iterator internal_find(const K &key) const;
+
+ // Verifies the tree structure of node.
+ size_type internal_verify(const node_type *node, const key_type *lo,
+ const key_type *hi) const;
+
+ node_stats internal_stats(const node_type *node) const {
+ // The root can be a static empty node.
+ if (node == nullptr || (node == root() && empty())) {
+ return node_stats(0, 0);
+ }
+ if (node->is_leaf()) {
+ return node_stats(1, 0);
+ }
+ node_stats res(0, 1);
+ for (int i = node->start(); i <= node->finish(); ++i) {
+ res += internal_stats(node->child(i));
+ }
+ return res;
+ }
+
+ node_type *root_;
+
+ // A pointer to the rightmost node. Note that the leftmost node is stored as
+ // the root's parent. We use compressed tuple in order to save space because
+ // key_compare and allocator_type are usually empty.
+ absl::container_internal::CompressedTuple<key_compare, allocator_type,
+ node_type *>
+ rightmost_;
+
+ // Number of values.
+ size_type size_;
+};
+
+////
+// btree_node methods
+template <typename P>
+template <typename... Args>
+inline void btree_node<P>::emplace_value(const field_type i,
+ allocator_type *alloc,
+ Args &&...args) {
+ assert(i >= start());
+ assert(i <= finish());
+ // Shift old values to create space for new value and then construct it in
+ // place.
+ if (i < finish()) {
+ transfer_n_backward(finish() - i, /*dest_i=*/i + 1, /*src_i=*/i, this,
+ alloc);
+ }
+ value_init(static_cast<field_type>(i), alloc, std::forward<Args>(args)...);
+ set_finish(finish() + 1);
+
+ if (is_internal() && finish() > i + 1) {
+ for (field_type j = finish(); j > i + 1; --j) {
+ set_child(j, child(j - 1));
+ }
+ clear_child(i + 1);
+ }
+}
+
+template <typename P>
+inline void btree_node<P>::remove_values(const field_type i,
+ const field_type to_erase,
+ allocator_type *alloc) {
+ // Transfer values after the removed range into their new places.
+ value_destroy_n(i, to_erase, alloc);
+ const field_type orig_finish = finish();
+ const field_type src_i = i + to_erase;
+ transfer_n(orig_finish - src_i, i, src_i, this, alloc);
+
+ if (is_internal()) {
+ // Delete all children between begin and end.
+ for (field_type j = 0; j < to_erase; ++j) {
+ clear_and_delete(child(i + j + 1), alloc);
+ }
+ // Rotate children after end into new positions.
+ for (field_type j = i + to_erase + 1; j <= orig_finish; ++j) {
+ set_child(j - to_erase, child(j));
+ clear_child(j);
+ }
+ }
+ set_finish(orig_finish - to_erase);
+}
+
+template <typename P>
+void btree_node<P>::rebalance_right_to_left(field_type to_move,
+ btree_node *right,
+ allocator_type *alloc) {
+ assert(parent() == right->parent());
+ assert(position() + 1 == right->position());
+ assert(right->count() >= count());
+ assert(to_move >= 1);
+ assert(to_move <= right->count());
+
+ // 1) Move the delimiting value in the parent to the left node.
+ transfer(finish(), position(), parent(), alloc);
+
+ // 2) Move the (to_move - 1) values from the right node to the left node.
+ transfer_n(to_move - 1, finish() + 1, right->start(), right, alloc);
+
+ // 3) Move the new delimiting value to the parent from the right node.
+ parent()->transfer(position(), right->start() + to_move - 1, right, alloc);
+
+ // 4) Shift the values in the right node to their correct positions.
+ right->transfer_n(right->count() - to_move, right->start(),
+ right->start() + to_move, right, alloc);
+
+ if (is_internal()) {
+ // Move the child pointers from the right to the left node.
+ for (field_type i = 0; i < to_move; ++i) {
+ init_child(finish() + i + 1, right->child(i));
+ }
+ for (field_type i = right->start(); i <= right->finish() - to_move; ++i) {
+ assert(i + to_move <= right->max_count());
+ right->init_child(i, right->child(i + to_move));
+ right->clear_child(i + to_move);
+ }
+ }
+
+ // Fixup `finish` on the left and right nodes.
+ set_finish(finish() + to_move);
+ right->set_finish(right->finish() - to_move);
+}
+
+template <typename P>
+void btree_node<P>::rebalance_left_to_right(field_type to_move,
+ btree_node *right,
+ allocator_type *alloc) {
+ assert(parent() == right->parent());
+ assert(position() + 1 == right->position());
+ assert(count() >= right->count());
+ assert(to_move >= 1);
+ assert(to_move <= count());
+
+ // Values in the right node are shifted to the right to make room for the
+ // new to_move values. Then, the delimiting value in the parent and the
+ // other (to_move - 1) values in the left node are moved into the right node.
+ // Lastly, a new delimiting value is moved from the left node into the
+ // parent, and the remaining empty left node entries are destroyed.
+
+ // 1) Shift existing values in the right node to their correct positions.
+ right->transfer_n_backward(right->count(), right->start() + to_move,
+ right->start(), right, alloc);
+
+ // 2) Move the delimiting value in the parent to the right node.
+ right->transfer(right->start() + to_move - 1, position(), parent(), alloc);
+
+ // 3) Move the (to_move - 1) values from the left node to the right node.
+ right->transfer_n(to_move - 1, right->start(), finish() - (to_move - 1), this,
+ alloc);
+
+ // 4) Move the new delimiting value to the parent from the left node.
+ parent()->transfer(position(), finish() - to_move, this, alloc);
+
+ if (is_internal()) {
+ // Move the child pointers from the left to the right node.
+ for (field_type i = right->finish() + 1; i > right->start(); --i) {
+ right->init_child(i - 1 + to_move, right->child(i - 1));
+ right->clear_child(i - 1);
+ }
+ for (field_type i = 1; i <= to_move; ++i) {
+ right->init_child(i - 1, child(finish() - to_move + i));
+ clear_child(finish() - to_move + i);
+ }
+ }
+
+ // Fixup the counts on the left and right nodes.
+ set_finish(finish() - to_move);
+ right->set_finish(right->finish() + to_move);
+}
+
+template <typename P>
+void btree_node<P>::split(const int insert_position, btree_node *dest,
+ allocator_type *alloc) {
+ assert(dest->count() == 0);
+ assert(max_count() == kNodeSlots);
+ assert(position() + 1 == dest->position());
+ assert(parent() == dest->parent());
+
+ // We bias the split based on the position being inserted. If we're
+ // inserting at the beginning of the left node then bias the split to put
+ // more values on the right node. If we're inserting at the end of the
+ // right node then bias the split to put more values on the left node.
+ if (insert_position == start()) {
+ dest->set_finish(dest->start() + finish() - 1);
+ } else if (insert_position == kNodeSlots) {
+ dest->set_finish(dest->start());
+ } else {
+ dest->set_finish(dest->start() + count() / 2);
+ }
+ set_finish(finish() - dest->count());
+ assert(count() >= 1);
+
+ // Move values from the left sibling to the right sibling.
+ dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);
+
+ // The split key is the largest value in the left sibling.
+ --mutable_finish();
+ parent()->emplace_value(position(), alloc, finish_slot());
+ value_destroy(finish(), alloc);
+ parent()->set_child_noupdate_position(position() + 1, dest);
+
+ if (is_internal()) {
+ for (field_type i = dest->start(), j = finish() + 1; i <= dest->finish();
+ ++i, ++j) {
+ assert(child(j) != nullptr);
+ dest->init_child(i, child(j));
+ clear_child(j);
+ }
+ }
+}
+
+template <typename P>
+void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
+ assert(parent() == src->parent());
+ assert(position() + 1 == src->position());
+
+ // Move the delimiting value to the left node.
+ value_init(finish(), alloc, parent()->slot(position()));
+
+ // Move the values from the right to the left node.
+ transfer_n(src->count(), finish() + 1, src->start(), src, alloc);
+
+ if (is_internal()) {
+ // Move the child pointers from the right to the left node.
+ for (field_type i = src->start(), j = finish() + 1; i <= src->finish();
+ ++i, ++j) {
+ init_child(j, src->child(i));
+ src->clear_child(i);
+ }
+ }
+
+ // Fixup `finish` on the src and dest nodes.
+ set_finish(start() + 1 + count() + src->count());
+ src->set_finish(src->start());
+
+ // Remove the value on the parent node and delete the src node.
+ parent()->remove_values(position(), /*to_erase=*/1, alloc);
+}
+
+template <typename P>
+void btree_node<P>::clear_and_delete(btree_node *node, allocator_type *alloc) {
+ if (node->is_leaf()) {
+ node->value_destroy_n(node->start(), node->count(), alloc);
+ deallocate(LeafSize(node->max_count()), node, alloc);
+ return;
+ }
+ if (node->count() == 0) {
+ deallocate(InternalSize(), node, alloc);
+ return;
+ }
+
+ // The parent of the root of the subtree we are deleting.
+ btree_node *delete_root_parent = node->parent();
+
+ // Navigate to the leftmost leaf under node, and then delete upwards.
+ while (node->is_internal()) node = node->start_child();
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+ // When generations are enabled, we delete the leftmost leaf last in case it's
+ // the parent of the root and we need to check whether it's a leaf before we
+ // can update the root's generation.
+ // TODO(ezb): if we change btree_node::is_root to check a bool inside the node
+ // instead of checking whether the parent is a leaf, we can remove this logic.
+ btree_node *leftmost_leaf = node;
+#endif
+ // Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,
+ // which isn't guaranteed to be a valid `field_type`.
+ size_type pos = node->position();
+ btree_node *parent = node->parent();
+ for (;;) {
+ // In each iteration of the next loop, we delete one leaf node and go right.
+ assert(pos <= parent->finish());
+ do {
+ node = parent->child(static_cast<field_type>(pos));
+ if (node->is_internal()) {
+ // Navigate to the leftmost leaf under node.
+ while (node->is_internal()) node = node->start_child();
+ pos = node->position();
+ parent = node->parent();
+ }
+ node->value_destroy_n(node->start(), node->count(), alloc);
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+ if (leftmost_leaf != node)
+#endif
+ deallocate(LeafSize(node->max_count()), node, alloc);
+ ++pos;
+ } while (pos <= parent->finish());
+
+ // Once we've deleted all children of parent, delete parent and go up/right.
+ assert(pos > parent->finish());
+ do {
+ node = parent;
+ pos = node->position();
+ parent = node->parent();
+ node->value_destroy_n(node->start(), node->count(), alloc);
+ deallocate(InternalSize(), node, alloc);
+ if (parent == delete_root_parent) {
+#ifdef ABSL_BTREE_ENABLE_GENERATIONS
+ deallocate(LeafSize(leftmost_leaf->max_count()), leftmost_leaf, alloc);
+#endif
+ return;
+ }
+ ++pos;
+ } while (pos > parent->finish());
+ }
+}
+
+////
+// btree_iterator methods
+
+// Note: the implementation here is based on btree_node::clear_and_delete.
+template <typename N, typename R, typename P>
+auto btree_iterator<N, R, P>::distance_slow(const_iterator other) const
+ -> difference_type {
+ const_iterator begin = other;
+ const_iterator end = *this;
+ assert(begin.node_ != end.node_ || !begin.node_->is_leaf() ||
+ begin.position_ != end.position_);
+
+ const node_type *node = begin.node_;
+ // We need to compensate for double counting if begin.node_ is a leaf node.
+ difference_type count = node->is_leaf() ? -begin.position_ : 0;
+
+ // First navigate to the leftmost leaf node past begin.
+ if (node->is_internal()) {
+ ++count;
+ node = node->child(begin.position_ + 1);
+ }
+ while (node->is_internal()) node = node->start_child();
+
+ // Use `size_type` because `pos` needs to be able to hold `kNodeSlots+1`,
+ // which isn't guaranteed to be a valid `field_type`.
+ size_type pos = node->position();
+ const node_type *parent = node->parent();
+ for (;;) {
+ // In each iteration of the next loop, we count one leaf node and go right.
+ assert(pos <= parent->finish());
+ do {
+ node = parent->child(static_cast<field_type>(pos));
+ if (node->is_internal()) {
+ // Navigate to the leftmost leaf under node.
+ while (node->is_internal()) node = node->start_child();
+ pos = node->position();
+ parent = node->parent();
+ }
+ if (node == end.node_) return count + end.position_;
+ if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
+ return count + node->count();
+ // +1 is for the next internal node value.
+ count += node->count() + 1;
+ ++pos;
+ } while (pos <= parent->finish());
+
+ // Once we've counted all children of parent, go up/right.
+ assert(pos > parent->finish());
+ do {
+ node = parent;
+ pos = node->position();
+ parent = node->parent();
+ // -1 because we counted the value at end and shouldn't.
+ if (parent == end.node_ && pos == static_cast<size_type>(end.position_))
+ return count - 1;
+ ++pos;
+ } while (pos > parent->finish());
+ }
+}
+
+template <typename N, typename R, typename P>
+void btree_iterator<N, R, P>::increment_slow() {
+ if (node_->is_leaf()) {
+ assert(position_ >= node_->finish());
+ btree_iterator save(*this);
+ while (position_ == node_->finish() && !node_->is_root()) {
+ assert(node_->parent()->child(node_->position()) == node_);
+ position_ = node_->position();
+ node_ = node_->parent();
+ }
+ // TODO(ezb): assert we aren't incrementing end() instead of handling.
+ if (position_ == node_->finish()) {
+ *this = save;
+ }
+ } else {
+ assert(position_ < node_->finish());
+ node_ = node_->child(static_cast<field_type>(position_ + 1));
+ while (node_->is_internal()) {
+ node_ = node_->start_child();
+ }
+ position_ = node_->start();
+ }
+}
+
+template <typename N, typename R, typename P>
+void btree_iterator<N, R, P>::decrement_slow() {
+ if (node_->is_leaf()) {
+ assert(position_ <= -1);
+ btree_iterator save(*this);
+ while (position_ < node_->start() && !node_->is_root()) {
+ assert(node_->parent()->child(node_->position()) == node_);
+ position_ = node_->position() - 1;
+ node_ = node_->parent();
+ }
+ // TODO(ezb): assert we aren't decrementing begin() instead of handling.
+ if (position_ < node_->start()) {
+ *this = save;
+ }
+ } else {
+ assert(position_ >= node_->start());
+ node_ = node_->child(static_cast<field_type>(position_));
+ while (node_->is_internal()) {
+ node_ = node_->child(node_->finish());
+ }
+ position_ = node_->finish() - 1;
+ }
+}
+
+////
+// btree methods
+template <typename P>
+template <typename Btree>
+void btree<P>::copy_or_move_values_in_order(Btree &other) {
+ static_assert(std::is_same<btree, Btree>::value ||
+ std::is_same<const btree, Btree>::value,
+ "Btree type must be same or const.");
+ assert(empty());
+
+ // We can avoid key comparisons because we know the order of the
+ // values is the same order we'll store them in.
+ auto iter = other.begin();
+ if (iter == other.end()) return;
+ insert_multi(iter.slot());
+ ++iter;
+ for (; iter != other.end(); ++iter) {
+ // If the btree is not empty, we can just insert the new value at the end
+ // of the tree.
+ internal_emplace(end(), iter.slot());
+ }
+}
+
+template <typename P>
+constexpr bool btree<P>::static_assert_validation() {
+ static_assert(std::is_nothrow_copy_constructible<key_compare>::value,
+ "Key comparison must be nothrow copy constructible");
+ static_assert(std::is_nothrow_copy_constructible<allocator_type>::value,
+ "Allocator must be nothrow copy constructible");
+ static_assert(std::is_trivially_copyable<iterator>::value,
+ "iterator not trivially copyable.");
+
+ // Note: We assert that kTargetValues, which is computed from
+ // Params::kTargetNodeSize, must fit the node_type::field_type.
+ static_assert(
+ kNodeSlots < (1 << (8 * sizeof(typename node_type::field_type))),
+ "target node size too large");
+
+ // Verify that key_compare returns an absl::{weak,strong}_ordering or bool.
+ static_assert(
+ compare_has_valid_result_type<key_compare, key_type>(),
+ "key comparison function must return absl::{weak,strong}_ordering or "
+ "bool.");
+
+ // Test the assumption made in setting kNodeSlotSpace.
+ static_assert(node_type::MinimumOverhead() >= sizeof(void *) + 4,
+ "node space assumption incorrect");
+
+ return true;
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::lower_bound_equal(const K &key) const
+ -> std::pair<iterator, bool> {
+ const SearchResult<iterator, is_key_compare_to::value> res =
+ internal_lower_bound(key);
+ const iterator lower = iterator(internal_end(res.value));
+ const bool equal = res.HasMatch()
+ ? res.IsEq()
+ : lower != end() && !compare_keys(key, lower.key());
+ return {lower, equal};
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::equal_range(const K &key) -> std::pair<iterator, iterator> {
+ const std::pair<iterator, bool> lower_and_equal = lower_bound_equal(key);
+ const iterator lower = lower_and_equal.first;
+ if (!lower_and_equal.second) {
+ return {lower, lower};
+ }
+
+ const iterator next = std::next(lower);
+ if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
+ // The next iterator after lower must point to a key greater than `key`.
+ // Note: if this assert fails, then it may indicate that the comparator does
+ // not meet the equivalence requirements for Compare
+ // (see https://en.cppreference.com/w/cpp/named_req/Compare).
+ assert(next == end() || compare_keys(key, next.key()));
+ return {lower, next};
+ }
+ // Try once more to avoid the call to upper_bound() if there's only one
+ // equivalent key. This should prevent all calls to upper_bound() in cases of
+ // unique-containers with heterogeneous comparators in which all comparison
+ // operators have the same equivalence classes.
+ if (next == end() || compare_keys(key, next.key())) return {lower, next};
+
+ // In this case, we need to call upper_bound() to avoid worst case O(N)
+ // behavior if we were to iterate over equal keys.
+ return {lower, upper_bound(key)};
+}
+
+template <typename P>
+template <typename K, typename... Args>
+auto btree<P>::insert_unique(const K &key, Args &&...args)
+ -> std::pair<iterator, bool> {
+ if (empty()) {
+ mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
+ }
+
+ SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
+ iterator iter = res.value;
+
+ if (res.HasMatch()) {
+ if (res.IsEq()) {
+ // The key already exists in the tree, do nothing.
+ return {iter, false};
+ }
+ } else {
+ iterator last = internal_last(iter);
+ if (last.node_ && !compare_keys(key, last.key())) {
+ // The key already exists in the tree, do nothing.
+ return {last, false};
+ }
+ }
+ return {internal_emplace(iter, std::forward<Args>(args)...), true};
+}
+
+template <typename P>
+template <typename K, typename... Args>
+inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
+ Args &&...args)
+ -> std::pair<iterator, bool> {
+ if (!empty()) {
+ if (position == end() || compare_keys(key, position.key())) {
+ if (position == begin() || compare_keys(std::prev(position).key(), key)) {
+ // prev.key() < key < position.key()
+ return {internal_emplace(position, std::forward<Args>(args)...), true};
+ }
+ } else if (compare_keys(position.key(), key)) {
+ ++position;
+ if (position == end() || compare_keys(key, position.key())) {
+ // {original `position`}.key() < key < {current `position`}.key()
+ return {internal_emplace(position, std::forward<Args>(args)...), true};
+ }
+ } else {
+ // position.key() == key
+ return {position, false};
+ }
+ }
+ return insert_unique(key, std::forward<Args>(args)...);
+}
+
+template <typename P>
+template <typename InputIterator, typename>
+void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, int) {
+ for (; b != e; ++b) {
+ insert_hint_unique(end(), params_type::key(*b), *b);
+ }
+}
+
+template <typename P>
+template <typename InputIterator>
+void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e, char) {
+ for (; b != e; ++b) {
+ // Use a node handle to manage a temp slot.
+ auto node_handle =
+ CommonAccess::Construct<node_handle_type>(get_allocator(), *b);
+ slot_type *slot = CommonAccess::GetSlot(node_handle);
+ insert_hint_unique(end(), params_type::key(slot), slot);
+ }
+}
+
+template <typename P>
+template <typename ValueType>
+auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
+ if (empty()) {
+ mutable_root() = mutable_rightmost() = new_leaf_root_node(1);
+ }
+
+ iterator iter = internal_upper_bound(key);
+ if (iter.node_ == nullptr) {
+ iter = end();
+ }
+ return internal_emplace(iter, std::forward<ValueType>(v));
+}
+
+template <typename P>
+template <typename ValueType>
+auto btree<P>::insert_hint_multi(iterator position, ValueType &&v) -> iterator {
+ if (!empty()) {
+ const key_type &key = params_type::key(v);
+ if (position == end() || !compare_keys(position.key(), key)) {
+ if (position == begin() ||
+ !compare_keys(key, std::prev(position).key())) {
+ // prev.key() <= key <= position.key()
+ return internal_emplace(position, std::forward<ValueType>(v));
+ }
+ } else {
+ ++position;
+ if (position == end() || !compare_keys(position.key(), key)) {
+ // {original `position`}.key() < key < {current `position`}.key()
+ return internal_emplace(position, std::forward<ValueType>(v));
+ }
+ }
+ }
+ return insert_multi(std::forward<ValueType>(v));
+}
+
+template <typename P>
+template <typename InputIterator>
+void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
+ for (; b != e; ++b) {
+ insert_hint_multi(end(), *b);
+ }
+}
+
+template <typename P>
+auto btree<P>::operator=(const btree &other) -> btree & {
+ if (this != &other) {
+ clear();
+
+ *mutable_key_comp() = other.key_comp();
+ if (absl::allocator_traits<
+ allocator_type>::propagate_on_container_copy_assignment::value) {
+ *mutable_allocator() = other.allocator();
+ }
+
+ copy_or_move_values_in_order(other);
+ }
+ return *this;
+}
+
+template <typename P>
+auto btree<P>::operator=(btree &&other) noexcept -> btree & {
+ if (this != &other) {
+ clear();
+
+ using std::swap;
+ if (absl::allocator_traits<
+ allocator_type>::propagate_on_container_move_assignment::value) {
+ swap(root_, other.root_);
+ // Note: `rightmost_` also contains the allocator and the key comparator.
+ swap(rightmost_, other.rightmost_);
+ swap(size_, other.size_);
+ } else {
+ if (allocator() == other.allocator()) {
+ swap(mutable_root(), other.mutable_root());
+ swap(*mutable_key_comp(), *other.mutable_key_comp());
+ swap(mutable_rightmost(), other.mutable_rightmost());
+ swap(size_, other.size_);
+ } else {
+ // We aren't allowed to propagate the allocator and the allocator is
+ // different so we can't take over its memory. We must move each element
+ // individually. We need both `other` and `this` to have `other`s key
+ // comparator while moving the values so we can't swap the key
+ // comparators.
+ *mutable_key_comp() = other.key_comp();
+ copy_or_move_values_in_order(other);
+ }
+ }
+ }
+ return *this;
+}
+
+template <typename P>
+auto btree<P>::erase(iterator iter) -> iterator {
+ iter.node_->value_destroy(static_cast<field_type>(iter.position_),
+ mutable_allocator());
+ iter.update_generation();
+
+ const bool internal_delete = iter.node_->is_internal();
+ if (internal_delete) {
+ // Deletion of a value on an internal node. First, transfer the largest
+ // value from our left child here, then erase/rebalance from that position.
+ // We can get to the largest value from our left child by decrementing iter.
+ iterator internal_iter(iter);
+ --iter;
+ assert(iter.node_->is_leaf());
+ internal_iter.node_->transfer(
+ static_cast<size_type>(internal_iter.position_),
+ static_cast<size_type>(iter.position_), iter.node_,
+ mutable_allocator());
+ } else {
+ // Shift values after erased position in leaf. In the internal case, we
+ // don't need to do this because the leaf position is the end of the node.
+ const field_type transfer_from =
+ static_cast<field_type>(iter.position_ + 1);
+ const field_type num_to_transfer = iter.node_->finish() - transfer_from;
+ iter.node_->transfer_n(num_to_transfer,
+ static_cast<size_type>(iter.position_),
+ transfer_from, iter.node_, mutable_allocator());
+ }
+ // Update node finish and container size.
+ iter.node_->set_finish(iter.node_->finish() - 1);
+ --size_;
+
+ // We want to return the next value after the one we just erased. If we
+ // erased from an internal node (internal_delete == true), then the next
+ // value is ++(++iter). If we erased from a leaf node (internal_delete ==
+ // false) then the next value is ++iter. Note that ++iter may point to an
+ // internal node and the value in the internal node may move to a leaf node
+ // (iter.node_) when rebalancing is performed at the leaf level.
+
+ iterator res = rebalance_after_delete(iter);
+
+ // If we erased from an internal node, advance the iterator.
+ if (internal_delete) {
+ ++res;
+ }
+ return res;
+}
+
+template <typename P>
+auto btree<P>::rebalance_after_delete(iterator iter) -> iterator {
+ // Merge/rebalance as we walk back up the tree.
+ iterator res(iter);
+ bool first_iteration = true;
+ for (;;) {
+ if (iter.node_ == root()) {
+ try_shrink();
+ if (empty()) {
+ return end();
+ }
+ break;
+ }
+ if (iter.node_->count() >= kMinNodeValues) {
+ break;
+ }
+ bool merged = try_merge_or_rebalance(&iter);
+ // On the first iteration, we should update `res` with `iter` because `res`
+ // may have been invalidated.
+ if (first_iteration) {
+ res = iter;
+ first_iteration = false;
+ }
+ if (!merged) {
+ break;
+ }
+ iter.position_ = iter.node_->position();
+ iter.node_ = iter.node_->parent();
+ }
+ res.update_generation();
+
+ // Adjust our return value. If we're pointing at the end of a node, advance
+ // the iterator.
+ if (res.position_ == res.node_->finish()) {
+ res.position_ = res.node_->finish() - 1;
+ ++res;
+ }
+
+ return res;
+}
+
+// Note: we tried implementing this more efficiently by erasing all of the
+// elements in [begin, end) at once and then doing rebalancing once at the end
+// (rather than interleaving deletion and rebalancing), but that adds a lot of
+// complexity, which seems to outweigh the performance win.
+template <typename P>
+auto btree<P>::erase_range(iterator begin, iterator end)
+ -> std::pair<size_type, iterator> {
+ size_type count = static_cast<size_type>(end - begin);
+ assert(count >= 0);
+
+ if (count == 0) {
+ return {0, begin};
+ }
+
+ if (static_cast<size_type>(count) == size_) {
+ clear();
+ return {count, this->end()};
+ }
+
+ if (begin.node_ == end.node_) {
+ assert(end.position_ > begin.position_);
+ begin.node_->remove_values(
+ static_cast<field_type>(begin.position_),
+ static_cast<field_type>(end.position_ - begin.position_),
+ mutable_allocator());
+ size_ -= count;
+ return {count, rebalance_after_delete(begin)};
+ }
+
+ const size_type target_size = size_ - count;
+ while (size_ > target_size) {
+ if (begin.node_->is_leaf()) {
+ const size_type remaining_to_erase = size_ - target_size;
+ const size_type remaining_in_node =
+ static_cast<size_type>(begin.node_->finish() - begin.position_);
+ const field_type to_erase = static_cast<field_type>(
+ (std::min)(remaining_to_erase, remaining_in_node));
+ begin.node_->remove_values(static_cast<field_type>(begin.position_),
+ to_erase, mutable_allocator());
+ size_ -= to_erase;
+ begin = rebalance_after_delete(begin);
+ } else {
+ begin = erase(begin);
+ }
+ }
+ begin.update_generation();
+ return {count, begin};
+}
+
+template <typename P>
+void btree<P>::clear() {
+ if (!empty()) {
+ node_type::clear_and_delete(root(), mutable_allocator());
+ }
+ mutable_root() = mutable_rightmost() = EmptyNode();
+ size_ = 0;
+}
+
+template <typename P>
+void btree<P>::swap(btree &other) {
+ using std::swap;
+ if (absl::allocator_traits<
+ allocator_type>::propagate_on_container_swap::value) {
+ // Note: `rightmost_` also contains the allocator and the key comparator.
+ swap(rightmost_, other.rightmost_);
+ } else {
+ // It's undefined behavior if the allocators are unequal here.
+ assert(allocator() == other.allocator());
+ swap(mutable_rightmost(), other.mutable_rightmost());
+ swap(*mutable_key_comp(), *other.mutable_key_comp());
+ }
+ swap(mutable_root(), other.mutable_root());
+ swap(size_, other.size_);
+}
+
+template <typename P>
+void btree<P>::verify() const {
+ assert(root() != nullptr);
+ assert(leftmost() != nullptr);
+ assert(rightmost() != nullptr);
+ assert(empty() || size() == internal_verify(root(), nullptr, nullptr));
+ assert(leftmost() == (++const_iterator(root(), -1)).node_);
+ assert(rightmost() == (--const_iterator(root(), root()->finish())).node_);
+ assert(leftmost()->is_leaf());
+ assert(rightmost()->is_leaf());
+}
+
+template <typename P>
+void btree<P>::rebalance_or_split(iterator *iter) {
+ node_type *&node = iter->node_;
+ int &insert_position = iter->position_;
+ assert(node->count() == node->max_count());
+ assert(kNodeSlots == node->max_count());
+
+ // First try to make room on the node by rebalancing.
+ node_type *parent = node->parent();
+ if (node != root()) {
+ if (node->position() > parent->start()) {
+ // Try rebalancing with our left sibling.
+ node_type *left = parent->child(node->position() - 1);
+ assert(left->max_count() == kNodeSlots);
+ if (left->count() < kNodeSlots) {
+ // We bias rebalancing based on the position being inserted. If we're
+ // inserting at the end of the right node then we bias rebalancing to
+ // fill up the left node.
+ field_type to_move =
+ (kNodeSlots - left->count()) /
+ (1 + (static_cast<field_type>(insert_position) < kNodeSlots));
+ to_move = (std::max)(field_type{1}, to_move);
+
+ if (static_cast<field_type>(insert_position) - to_move >=
+ node->start() ||
+ left->count() + to_move < kNodeSlots) {
+ left->rebalance_right_to_left(to_move, node, mutable_allocator());
+
+ assert(node->max_count() - node->count() == to_move);
+ insert_position = static_cast<int>(
+ static_cast<field_type>(insert_position) - to_move);
+ if (insert_position < node->start()) {
+ insert_position = insert_position + left->count() + 1;
+ node = left;
+ }
+
+ assert(node->count() < node->max_count());
+ return;
+ }
+ }
+ }
+
+ if (node->position() < parent->finish()) {
+ // Try rebalancing with our right sibling.
+ node_type *right = parent->child(node->position() + 1);
+ assert(right->max_count() == kNodeSlots);
+ if (right->count() < kNodeSlots) {
+ // We bias rebalancing based on the position being inserted. If we're
+ // inserting at the beginning of the left node then we bias rebalancing
+ // to fill up the right node.
+ field_type to_move = (kNodeSlots - right->count()) /
+ (1 + (insert_position > node->start()));
+ to_move = (std::max)(field_type{1}, to_move);
+
+ if (static_cast<field_type>(insert_position) <=
+ node->finish() - to_move ||
+ right->count() + to_move < kNodeSlots) {
+ node->rebalance_left_to_right(to_move, right, mutable_allocator());
+
+ if (insert_position > node->finish()) {
+ insert_position = insert_position - node->count() - 1;
+ node = right;
+ }
+
+ assert(node->count() < node->max_count());
+ return;
+ }
+ }
+ }
+
+ // Rebalancing failed, make sure there is room on the parent node for a new
+ // value.
+ assert(parent->max_count() == kNodeSlots);
+ if (parent->count() == kNodeSlots) {
+ iterator parent_iter(parent, node->position());
+ rebalance_or_split(&parent_iter);
+ parent = node->parent();
+ }
+ } else {
+ // Rebalancing not possible because this is the root node.
+ // Create a new root node and set the current root node as the child of the
+ // new root.
+ parent = new_internal_node(/*position=*/0, parent);
+ parent->set_generation(root()->generation());
+ parent->init_child(parent->start(), node);
+ mutable_root() = parent;
+ // If the former root was a leaf node, then it's now the rightmost node.
+ assert(parent->start_child()->is_internal() ||
+ parent->start_child() == rightmost());
+ }
+
+ // Split the node.
+ node_type *split_node;
+ if (node->is_leaf()) {
+ split_node = new_leaf_node(node->position() + 1, parent);
+ node->split(insert_position, split_node, mutable_allocator());
+ if (rightmost() == node) mutable_rightmost() = split_node;
+ } else {
+ split_node = new_internal_node(node->position() + 1, parent);
+ node->split(insert_position, split_node, mutable_allocator());
+ }
+
+ if (insert_position > node->finish()) {
+ insert_position = insert_position - node->count() - 1;
+ node = split_node;
+ }
+}
+
+template <typename P>
+void btree<P>::merge_nodes(node_type *left, node_type *right) {
+ left->merge(right, mutable_allocator());
+ if (rightmost() == right) mutable_rightmost() = left;
+}
+
+template <typename P>
+bool btree<P>::try_merge_or_rebalance(iterator *iter) {
+ node_type *parent = iter->node_->parent();
+ if (iter->node_->position() > parent->start()) {
+ // Try merging with our left sibling.
+ node_type *left = parent->child(iter->node_->position() - 1);
+ assert(left->max_count() == kNodeSlots);
+ if (1U + left->count() + iter->node_->count() <= kNodeSlots) {
+ iter->position_ += 1 + left->count();
+ merge_nodes(left, iter->node_);
+ iter->node_ = left;
+ return true;
+ }
+ }
+ if (iter->node_->position() < parent->finish()) {
+ // Try merging with our right sibling.
+ node_type *right = parent->child(iter->node_->position() + 1);
+ assert(right->max_count() == kNodeSlots);
+ if (1U + iter->node_->count() + right->count() <= kNodeSlots) {
+ merge_nodes(iter->node_, right);
+ return true;
+ }
+ // Try rebalancing with our right sibling. We don't perform rebalancing if
+ // we deleted the first element from iter->node_ and the node is not
+ // empty. This is a small optimization for the common pattern of deleting
+ // from the front of the tree.
+ if (right->count() > kMinNodeValues &&
+ (iter->node_->count() == 0 || iter->position_ > iter->node_->start())) {
+ field_type to_move = (right->count() - iter->node_->count()) / 2;
+ to_move =
+ (std::min)(to_move, static_cast<field_type>(right->count() - 1));
+ iter->node_->rebalance_right_to_left(to_move, right, mutable_allocator());
+ return false;
+ }
+ }
+ if (iter->node_->position() > parent->start()) {
+ // Try rebalancing with our left sibling. We don't perform rebalancing if
+ // we deleted the last element from iter->node_ and the node is not
+ // empty. This is a small optimization for the common pattern of deleting
+ // from the back of the tree.
+ node_type *left = parent->child(iter->node_->position() - 1);
+ if (left->count() > kMinNodeValues &&
+ (iter->node_->count() == 0 ||
+ iter->position_ < iter->node_->finish())) {
+ field_type to_move = (left->count() - iter->node_->count()) / 2;
+ to_move = (std::min)(to_move, static_cast<field_type>(left->count() - 1));
+ left->rebalance_left_to_right(to_move, iter->node_, mutable_allocator());
+ iter->position_ += to_move;
+ return false;
+ }
+ }
+ return false;
+}
+
+template <typename P>
+void btree<P>::try_shrink() {
+ node_type *orig_root = root();
+ if (orig_root->count() > 0) {
+ return;
+ }
+ // Deleted the last item on the root node, shrink the height of the tree.
+ if (orig_root->is_leaf()) {
+ assert(size() == 0);
+ mutable_root() = mutable_rightmost() = EmptyNode();
+ } else {
+ node_type *child = orig_root->start_child();
+ child->make_root();
+ mutable_root() = child;
+ }
+ node_type::clear_and_delete(orig_root, mutable_allocator());
+}
+
+template <typename P>
+template <typename IterType>
+inline IterType btree<P>::internal_last(IterType iter) {
+ assert(iter.node_ != nullptr);
+ while (iter.position_ == iter.node_->finish()) {
+ iter.position_ = iter.node_->position();
+ iter.node_ = iter.node_->parent();
+ if (iter.node_->is_leaf()) {
+ iter.node_ = nullptr;
+ break;
+ }
+ }
+ iter.update_generation();
+ return iter;
+}
+
+template <typename P>
+template <typename... Args>
+inline auto btree<P>::internal_emplace(iterator iter, Args &&...args)
+ -> iterator {
+ if (iter.node_->is_internal()) {
+ // We can't insert on an internal node. Instead, we'll insert after the
+ // previous value which is guaranteed to be on a leaf node.
+ --iter;
+ ++iter.position_;
+ }
+ const field_type max_count = iter.node_->max_count();
+ allocator_type *alloc = mutable_allocator();
+
+ const auto transfer_and_delete = [&](node_type *old_node,
+ node_type *new_node) {
+ new_node->transfer_n(old_node->count(), new_node->start(),
+ old_node->start(), old_node, alloc);
+ new_node->set_finish(old_node->finish());
+ old_node->set_finish(old_node->start());
+ new_node->set_generation(old_node->generation());
+ node_type::clear_and_delete(old_node, alloc);
+ };
+ const auto replace_leaf_root_node = [&](field_type new_node_size) {
+ assert(iter.node_ == root());
+ node_type *old_root = iter.node_;
+ node_type *new_root = iter.node_ = new_leaf_root_node(new_node_size);
+ transfer_and_delete(old_root, new_root);
+ mutable_root() = mutable_rightmost() = new_root;
+ };
+
+ bool replaced_node = false;
+ if (iter.node_->count() == max_count) {
+ // Make room in the leaf for the new item.
+ if (max_count < kNodeSlots) {
+ // Insertion into the root where the root is smaller than the full node
+ // size. Simply grow the size of the root node.
+ replace_leaf_root_node(static_cast<field_type>(
+ (std::min)(static_cast<int>(kNodeSlots), 2 * max_count)));
+ replaced_node = true;
+ } else {
+ rebalance_or_split(&iter);
+ }
+ }
+ (void)replaced_node;
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_HWADDRESS_SANITIZER)
+ if (!replaced_node) {
+ assert(iter.node_->is_leaf());
+ if (iter.node_->is_root()) {
+ replace_leaf_root_node(max_count);
+ } else {
+ node_type *old_node = iter.node_;
+ const bool was_rightmost = rightmost() == old_node;
+ const bool was_leftmost = leftmost() == old_node;
+ node_type *parent = old_node->parent();
+ const field_type position = old_node->position();
+ node_type *new_node = iter.node_ = new_leaf_node(position, parent);
+ parent->set_child_noupdate_position(position, new_node);
+ transfer_and_delete(old_node, new_node);
+ if (was_rightmost) mutable_rightmost() = new_node;
+ // The leftmost node is stored as the parent of the root node.
+ if (was_leftmost) root()->set_parent(new_node);
+ }
+ }
+#endif
+ iter.node_->emplace_value(static_cast<field_type>(iter.position_), alloc,
+ std::forward<Args>(args)...);
+ assert(
+ iter.node_->is_ordered_correctly(static_cast<field_type>(iter.position_),
+ original_key_compare(key_comp())) &&
+ "If this assert fails, then either (1) the comparator may violate "
+ "transitivity, i.e. comp(a,b) && comp(b,c) -> comp(a,c) (see "
+ "https://en.cppreference.com/w/cpp/named_req/Compare), or (2) a "
+ "key may have been mutated after it was inserted into the tree.");
+ ++size_;
+ iter.update_generation();
+ return iter;
+}
+
+template <typename P>
+template <typename K>
+inline auto btree<P>::internal_locate(const K &key) const
+ -> SearchResult<iterator, is_key_compare_to::value> {
+ iterator iter(const_cast<node_type *>(root()));
+ for (;;) {
+ SearchResult<size_type, is_key_compare_to::value> res =
+ iter.node_->lower_bound(key, key_comp());
+ iter.position_ = static_cast<int>(res.value);
+ if (res.IsEq()) {
+ return {iter, MatchKind::kEq};
+ }
+ // Note: in the non-key-compare-to case, we don't need to walk all the way
+ // down the tree if the keys are equal, but determining equality would
+ // require doing an extra comparison on each node on the way down, and we
+ // will need to go all the way to the leaf node in the expected case.
+ if (iter.node_->is_leaf()) {
+ break;
+ }
+ iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
+ }
+ // Note: in the non-key-compare-to case, the key may actually be equivalent
+ // here (and the MatchKind::kNe is ignored).
+ return {iter, MatchKind::kNe};
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::internal_lower_bound(const K &key) const
+ -> SearchResult<iterator, is_key_compare_to::value> {
+ if (!params_type::template can_have_multiple_equivalent_keys<K>()) {
+ SearchResult<iterator, is_key_compare_to::value> ret = internal_locate(key);
+ ret.value = internal_last(ret.value);
+ return ret;
+ }
+ iterator iter(const_cast<node_type *>(root()));
+ SearchResult<size_type, is_key_compare_to::value> res;
+ bool seen_eq = false;
+ for (;;) {
+ res = iter.node_->lower_bound(key, key_comp());
+ iter.position_ = static_cast<int>(res.value);
+ if (iter.node_->is_leaf()) {
+ break;
+ }
+ seen_eq = seen_eq || res.IsEq();
+ iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
+ }
+ if (res.IsEq()) return {iter, MatchKind::kEq};
+ return {internal_last(iter), seen_eq ? MatchKind::kEq : MatchKind::kNe};
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
+ iterator iter(const_cast<node_type *>(root()));
+ for (;;) {
+ iter.position_ = static_cast<int>(iter.node_->upper_bound(key, key_comp()));
+ if (iter.node_->is_leaf()) {
+ break;
+ }
+ iter.node_ = iter.node_->child(static_cast<field_type>(iter.position_));
+ }
+ return internal_last(iter);
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::internal_find(const K &key) const -> iterator {
+ SearchResult<iterator, is_key_compare_to::value> res = internal_locate(key);
+ if (res.HasMatch()) {
+ if (res.IsEq()) {
+ return res.value;
+ }
+ } else {
+ const iterator iter = internal_last(res.value);
+ if (iter.node_ != nullptr && !compare_keys(key, iter.key())) {
+ return iter;
+ }
+ }
+ return {nullptr, 0};
+}
+
+template <typename P>
+typename btree<P>::size_type btree<P>::internal_verify(
+ const node_type *node, const key_type *lo, const key_type *hi) const {
+ assert(node->count() > 0);
+ assert(node->count() <= node->max_count());
+ if (lo) {
+ assert(!compare_keys(node->key(node->start()), *lo));
+ }
+ if (hi) {
+ assert(!compare_keys(*hi, node->key(node->finish() - 1)));
+ }
+ for (int i = node->start() + 1; i < node->finish(); ++i) {
+ assert(!compare_keys(node->key(i), node->key(i - 1)));
+ }
+ size_type count = node->count();
+ if (node->is_internal()) {
+ for (field_type i = node->start(); i <= node->finish(); ++i) {
+ assert(node->child(i) != nullptr);
+ assert(node->child(i)->parent() == node);
+ assert(node->child(i)->position() == i);
+ count += internal_verify(node->child(i),
+ i == node->start() ? lo : &node->key(i - 1),
+ i == node->finish() ? hi : &node->key(i));
+ }
+ }
+ return count;
+}
+
+struct btree_access {
+ template <typename BtreeContainer, typename Pred>
+ static auto erase_if(BtreeContainer &container, Pred pred) ->
+ typename BtreeContainer::size_type {
+ const auto initial_size = container.size();
+ auto &tree = container.tree_;
+ auto *alloc = tree.mutable_allocator();
+ for (auto it = container.begin(); it != container.end();) {
+ if (!pred(*it)) {
+ ++it;
+ continue;
+ }
+ auto *node = it.node_;
+ if (node->is_internal()) {
+ // Handle internal nodes normally.
+ it = container.erase(it);
+ continue;
+ }
+ // If this is a leaf node, then we do all the erases from this node
+ // at once before doing rebalancing.
+
+ // The current position to transfer slots to.
+ int to_pos = it.position_;
+ node->value_destroy(it.position_, alloc);
+ while (++it.position_ < node->finish()) {
+ it.update_generation();
+ if (pred(*it)) {
+ node->value_destroy(it.position_, alloc);
+ } else {
+ node->transfer(node->slot(to_pos++), node->slot(it.position_), alloc);
+ }
+ }
+ const int num_deleted = node->finish() - to_pos;
+ tree.size_ -= num_deleted;
+ node->set_finish(to_pos);
+ it.position_ = to_pos;
+ it = tree.rebalance_after_delete(it);
+ }
+ return initial_size - container.size();
+ }
+};
+
+#undef ABSL_BTREE_ENABLE_GENERATIONS
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_BTREE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/btree_container.h b/contrib/restricted/abseil-cpp/absl/container/internal/btree_container.h
new file mode 100644
index 0000000000..a68ce44554
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/btree_container.h
@@ -0,0 +1,763 @@
+// Copyright 2018 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_BTREE_CONTAINER_H_
+#define ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
+
+#include <algorithm>
+#include <initializer_list>
+#include <iterator>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/container/internal/btree.h" // IWYU pragma: export
+#include "absl/container/internal/common.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// A common base class for btree_set, btree_map, btree_multiset, and
+// btree_multimap.
+template <typename Tree>
+class btree_container {
+ using params_type = typename Tree::params_type;
+
+ protected:
+ // Alias used for heterogeneous lookup functions.
+ // `key_arg<K>` evaluates to `K` when the functors are transparent and to
+ // `key_type` otherwise. It permits template argument deduction on `K` for the
+ // transparent case.
+ template <class K>
+ using key_arg =
+ typename KeyArg<params_type::kIsKeyCompareTransparent>::template type<
+ K, typename Tree::key_type>;
+
+ public:
+ using key_type = typename Tree::key_type;
+ using value_type = typename Tree::value_type;
+ using size_type = typename Tree::size_type;
+ using difference_type = typename Tree::difference_type;
+ using key_compare = typename Tree::original_key_compare;
+ using value_compare = typename Tree::value_compare;
+ using allocator_type = typename Tree::allocator_type;
+ using reference = typename Tree::reference;
+ using const_reference = typename Tree::const_reference;
+ using pointer = typename Tree::pointer;
+ using const_pointer = typename Tree::const_pointer;
+ using iterator = typename Tree::iterator;
+ using const_iterator = typename Tree::const_iterator;
+ using reverse_iterator = typename Tree::reverse_iterator;
+ using const_reverse_iterator = typename Tree::const_reverse_iterator;
+ using node_type = typename Tree::node_handle_type;
+
+ struct extract_and_get_next_return_type {
+ node_type node;
+ iterator next;
+ };
+
+ // Constructors/assignments.
+ btree_container() : tree_(key_compare(), allocator_type()) {}
+ explicit btree_container(const key_compare &comp,
+ const allocator_type &alloc = allocator_type())
+ : tree_(comp, alloc) {}
+ explicit btree_container(const allocator_type &alloc)
+ : tree_(key_compare(), alloc) {}
+
+ btree_container(const btree_container &other)
+ : btree_container(other, absl::allocator_traits<allocator_type>::
+ select_on_container_copy_construction(
+ other.get_allocator())) {}
+ btree_container(const btree_container &other, const allocator_type &alloc)
+ : tree_(other.tree_, alloc) {}
+
+ btree_container(btree_container &&other) noexcept(
+ std::is_nothrow_move_constructible<Tree>::value) = default;
+ btree_container(btree_container &&other, const allocator_type &alloc)
+ : tree_(std::move(other.tree_), alloc) {}
+
+ btree_container &operator=(const btree_container &other) = default;
+ btree_container &operator=(btree_container &&other) noexcept(
+ std::is_nothrow_move_assignable<Tree>::value) = default;
+
+ // Iterator routines.
+ iterator begin() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.begin(); }
+ const_iterator begin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.begin();
+ }
+ const_iterator cbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.begin();
+ }
+ iterator end() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.end(); }
+ const_iterator end() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.end();
+ }
+ const_iterator cend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.end();
+ }
+ reverse_iterator rbegin() ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.rbegin();
+ }
+ const_reverse_iterator rbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.rbegin();
+ }
+ const_reverse_iterator crbegin() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.rbegin();
+ }
+ reverse_iterator rend() ABSL_ATTRIBUTE_LIFETIME_BOUND { return tree_.rend(); }
+ const_reverse_iterator rend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.rend();
+ }
+ const_reverse_iterator crend() const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.rend();
+ }
+
+ // Lookup routines.
+ template <typename K = key_type>
+ size_type count(const key_arg<K> &key) const {
+ auto equal_range = this->equal_range(key);
+ return equal_range.second - equal_range.first;
+ }
+ template <typename K = key_type>
+ iterator find(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.find(key);
+ }
+ template <typename K = key_type>
+ const_iterator find(const key_arg<K> &key) const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.find(key);
+ }
+ template <typename K = key_type>
+ bool contains(const key_arg<K> &key) const {
+ return find(key) != end();
+ }
+ template <typename K = key_type>
+ iterator lower_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.lower_bound(key);
+ }
+ template <typename K = key_type>
+ const_iterator lower_bound(const key_arg<K> &key) const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.lower_bound(key);
+ }
+ template <typename K = key_type>
+ iterator upper_bound(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.upper_bound(key);
+ }
+ template <typename K = key_type>
+ const_iterator upper_bound(const key_arg<K> &key) const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.upper_bound(key);
+ }
+ template <typename K = key_type>
+ std::pair<iterator, iterator> equal_range(const key_arg<K> &key)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.equal_range(key);
+ }
+ template <typename K = key_type>
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_arg<K> &key) const ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.equal_range(key);
+ }
+
+ // Deletion routines. Note that there is also a deletion routine that is
+ // specific to btree_set_container/btree_multiset_container.
+
+ // Erase the specified iterator from the btree. The iterator must be valid
+ // (i.e. not equal to end()). Return an iterator pointing to the node after
+ // the one that was erased (or end() if none exists).
+ iterator erase(const_iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.erase(iterator(iter));
+ }
+ iterator erase(iterator iter) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.erase(iter);
+ }
+ iterator erase(const_iterator first,
+ const_iterator last) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return tree_.erase_range(iterator(first), iterator(last)).second;
+ }
+ template <typename K = key_type>
+ size_type erase(const key_arg<K> &key) {
+ auto equal_range = this->equal_range(key);
+ return tree_.erase_range(equal_range.first, equal_range.second).first;
+ }
+
+ // Extract routines.
+ extract_and_get_next_return_type extract_and_get_next(const_iterator position)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ // Use Construct instead of Transfer because the rebalancing code will
+ // destroy the slot later.
+ // Note: we rely on erase() taking place after Construct().
+ return {CommonAccess::Construct<node_type>(get_allocator(),
+ iterator(position).slot()),
+ erase(position)};
+ }
+ node_type extract(iterator position) {
+ // Use Construct instead of Transfer because the rebalancing code will
+ // destroy the slot later.
+ auto node =
+ CommonAccess::Construct<node_type>(get_allocator(), position.slot());
+ erase(position);
+ return node;
+ }
+ node_type extract(const_iterator position) {
+ return extract(iterator(position));
+ }
+
+ // Utility routines.
+ ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }
+ void swap(btree_container &other) { tree_.swap(other.tree_); }
+ void verify() const { tree_.verify(); }
+
+ // Size routines.
+ size_type size() const { return tree_.size(); }
+ size_type max_size() const { return tree_.max_size(); }
+ bool empty() const { return tree_.empty(); }
+
+ friend bool operator==(const btree_container &x, const btree_container &y) {
+ if (x.size() != y.size()) return false;
+ return std::equal(x.begin(), x.end(), y.begin());
+ }
+
+ friend bool operator!=(const btree_container &x, const btree_container &y) {
+ return !(x == y);
+ }
+
+ friend bool operator<(const btree_container &x, const btree_container &y) {
+ return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end());
+ }
+
+ friend bool operator>(const btree_container &x, const btree_container &y) {
+ return y < x;
+ }
+
+ friend bool operator<=(const btree_container &x, const btree_container &y) {
+ return !(y < x);
+ }
+
+ friend bool operator>=(const btree_container &x, const btree_container &y) {
+ return !(x < y);
+ }
+
+ // The allocator used by the btree.
+ allocator_type get_allocator() const { return tree_.get_allocator(); }
+
+ // The key comparator used by the btree.
+ key_compare key_comp() const { return key_compare(tree_.key_comp()); }
+ value_compare value_comp() const { return tree_.value_comp(); }
+
+ // Support absl::Hash.
+ template <typename State>
+ friend State AbslHashValue(State h, const btree_container &b) {
+ for (const auto &v : b) {
+ h = State::combine(std::move(h), v);
+ }
+ return State::combine(std::move(h), b.size());
+ }
+
+ protected:
+ friend struct btree_access;
+ Tree tree_;
+};
+
+// A common base class for btree_set and btree_map.
+template <typename Tree>
+class btree_set_container : public btree_container<Tree> {
+ using super_type = btree_container<Tree>;
+ using params_type = typename Tree::params_type;
+ using init_type = typename params_type::init_type;
+ using is_key_compare_to = typename params_type::is_key_compare_to;
+ friend class BtreeNodePeer;
+
+ protected:
+ template <class K>
+ using key_arg = typename super_type::template key_arg<K>;
+
+ public:
+ using key_type = typename Tree::key_type;
+ using value_type = typename Tree::value_type;
+ using size_type = typename Tree::size_type;
+ using key_compare = typename Tree::original_key_compare;
+ using allocator_type = typename Tree::allocator_type;
+ using iterator = typename Tree::iterator;
+ using const_iterator = typename Tree::const_iterator;
+ using node_type = typename super_type::node_type;
+ using insert_return_type = InsertReturnType<iterator, node_type>;
+
+ // Inherit constructors.
+ using super_type::super_type;
+ btree_set_container() {}
+
+ // Range constructors.
+ template <class InputIterator>
+ btree_set_container(InputIterator b, InputIterator e,
+ const key_compare &comp = key_compare(),
+ const allocator_type &alloc = allocator_type())
+ : super_type(comp, alloc) {
+ insert(b, e);
+ }
+ template <class InputIterator>
+ btree_set_container(InputIterator b, InputIterator e,
+ const allocator_type &alloc)
+ : btree_set_container(b, e, key_compare(), alloc) {}
+
+ // Initializer list constructors.
+ btree_set_container(std::initializer_list<init_type> init,
+ const key_compare &comp = key_compare(),
+ const allocator_type &alloc = allocator_type())
+ : btree_set_container(init.begin(), init.end(), comp, alloc) {}
+ btree_set_container(std::initializer_list<init_type> init,
+ const allocator_type &alloc)
+ : btree_set_container(init.begin(), init.end(), alloc) {}
+
+ // Insertion routines.
+ std::pair<iterator, bool> insert(const value_type &v)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_unique(params_type::key(v), v);
+ }
+ std::pair<iterator, bool> insert(value_type &&v)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_unique(params_type::key(v), std::move(v));
+ }
+ template <typename... Args>
+ std::pair<iterator, bool> emplace(Args &&...args)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ // Use a node handle to manage a temp slot.
+ auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
+ std::forward<Args>(args)...);
+ auto *slot = CommonAccess::GetSlot(node);
+ return this->tree_.insert_unique(params_type::key(slot), slot);
+ }
+ iterator insert(const_iterator hint,
+ const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_
+ .insert_hint_unique(iterator(hint), params_type::key(v), v)
+ .first;
+ }
+ iterator insert(const_iterator hint,
+ value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_
+ .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
+ .first;
+ }
+ template <typename... Args>
+ iterator emplace_hint(const_iterator hint,
+ Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ // Use a node handle to manage a temp slot.
+ auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
+ std::forward<Args>(args)...);
+ auto *slot = CommonAccess::GetSlot(node);
+ return this->tree_
+ .insert_hint_unique(iterator(hint), params_type::key(slot), slot)
+ .first;
+ }
+ template <typename InputIterator>
+ void insert(InputIterator b, InputIterator e) {
+ this->tree_.insert_iterator_unique(b, e, 0);
+ }
+ void insert(std::initializer_list<init_type> init) {
+ this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
+ }
+ insert_return_type insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ if (!node) return {this->end(), false, node_type()};
+ std::pair<iterator, bool> res =
+ this->tree_.insert_unique(params_type::key(CommonAccess::GetSlot(node)),
+ CommonAccess::GetSlot(node));
+ if (res.second) {
+ CommonAccess::Destroy(&node);
+ return {res.first, true, node_type()};
+ } else {
+ return {res.first, false, std::move(node)};
+ }
+ }
+ iterator insert(const_iterator hint,
+ node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ if (!node) return this->end();
+ std::pair<iterator, bool> res = this->tree_.insert_hint_unique(
+ iterator(hint), params_type::key(CommonAccess::GetSlot(node)),
+ CommonAccess::GetSlot(node));
+ if (res.second) CommonAccess::Destroy(&node);
+ return res.first;
+ }
+
+ // Node extraction routines.
+ template <typename K = key_type>
+ node_type extract(const key_arg<K> &key) {
+ const std::pair<iterator, bool> lower_and_equal =
+ this->tree_.lower_bound_equal(key);
+ return lower_and_equal.second ? extract(lower_and_equal.first)
+ : node_type();
+ }
+ using super_type::extract;
+
+ // Merge routines.
+ // Moves elements from `src` into `this`. If the element already exists in
+ // `this`, it is left unmodified in `src`.
+ template <
+ typename T,
+ typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_same<value_type, typename T::value_type>,
+ std::is_same<allocator_type, typename T::allocator_type>,
+ std::is_same<typename params_type::is_map_container,
+ typename T::params_type::is_map_container>>::value,
+ int> = 0>
+ void merge(btree_container<T> &src) { // NOLINT
+ for (auto src_it = src.begin(); src_it != src.end();) {
+ if (insert(std::move(params_type::element(src_it.slot()))).second) {
+ src_it = src.erase(src_it);
+ } else {
+ ++src_it;
+ }
+ }
+ }
+
+ template <
+ typename T,
+ typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_same<value_type, typename T::value_type>,
+ std::is_same<allocator_type, typename T::allocator_type>,
+ std::is_same<typename params_type::is_map_container,
+ typename T::params_type::is_map_container>>::value,
+ int> = 0>
+ void merge(btree_container<T> &&src) {
+ merge(src);
+ }
+};
+
+// Base class for btree_map.
+template <typename Tree>
+class btree_map_container : public btree_set_container<Tree> {
+ using super_type = btree_set_container<Tree>;
+ using params_type = typename Tree::params_type;
+ friend class BtreeNodePeer;
+
+ private:
+ template <class K>
+ using key_arg = typename super_type::template key_arg<K>;
+
+ public:
+ using key_type = typename Tree::key_type;
+ using mapped_type = typename params_type::mapped_type;
+ using value_type = typename Tree::value_type;
+ using key_compare = typename Tree::original_key_compare;
+ using allocator_type = typename Tree::allocator_type;
+ using iterator = typename Tree::iterator;
+ using const_iterator = typename Tree::const_iterator;
+
+ // Inherit constructors.
+ using super_type::super_type;
+ btree_map_container() {}
+
+ // Insertion routines.
+ // Note: the nullptr template arguments and extra `const M&` overloads allow
+ // for supporting bitfield arguments.
+ template <typename K = key_type, class M>
+ std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, const M &obj)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_impl(k, obj);
+ }
+ template <typename K = key_type, class M, K * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, const M &obj)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_impl(std::forward<K>(k), obj);
+ }
+ template <typename K = key_type, class M, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(const key_arg<K> &k, M &&obj)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_impl(k, std::forward<M>(obj));
+ }
+ template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_arg<K> &&k, M &&obj)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_impl(std::forward<K>(k), std::forward<M>(obj));
+ }
+ template <typename K = key_type, class M>
+ iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
+ const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_hint_impl(hint, k, obj);
+ }
+ template <typename K = key_type, class M, K * = nullptr>
+ iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
+ const M &obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_hint_impl(hint, std::forward<K>(k), obj);
+ }
+ template <typename K = key_type, class M, M * = nullptr>
+ iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
+ M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_hint_impl(hint, k, std::forward<M>(obj));
+ }
+ template <typename K = key_type, class M, K * = nullptr, M * = nullptr>
+ iterator insert_or_assign(const_iterator hint, key_arg<K> &&k,
+ M &&obj) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return insert_or_assign_hint_impl(hint, std::forward<K>(k),
+ std::forward<M>(obj));
+ }
+
+ template <typename K = key_type, typename... Args,
+ typename absl::enable_if_t<
+ !std::is_convertible<K, const_iterator>::value, int> = 0>
+ std::pair<iterator, bool> try_emplace(const key_arg<K> &k, Args &&...args)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace_impl(k, std::forward<Args>(args)...);
+ }
+ template <typename K = key_type, typename... Args,
+ typename absl::enable_if_t<
+ !std::is_convertible<K, const_iterator>::value, int> = 0>
+ std::pair<iterator, bool> try_emplace(key_arg<K> &&k, Args &&...args)
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace_impl(std::forward<K>(k), std::forward<Args>(args)...);
+ }
+ template <typename K = key_type, typename... Args>
+ iterator try_emplace(const_iterator hint, const key_arg<K> &k,
+ Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
+ }
+ template <typename K = key_type, typename... Args>
+ iterator try_emplace(const_iterator hint, key_arg<K> &&k,
+ Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace_hint_impl(hint, std::forward<K>(k),
+ std::forward<Args>(args)...);
+ }
+
+ template <typename K = key_type>
+ mapped_type &operator[](const key_arg<K> &k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace(k).first->second;
+ }
+ template <typename K = key_type>
+ mapped_type &operator[](key_arg<K> &&k) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return try_emplace(std::forward<K>(k)).first->second;
+ }
+
+ template <typename K = key_type>
+ mapped_type &at(const key_arg<K> &key) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ auto it = this->find(key);
+ if (it == this->end())
+ base_internal::ThrowStdOutOfRange("absl::btree_map::at");
+ return it->second;
+ }
+ template <typename K = key_type>
+ const mapped_type &at(const key_arg<K> &key) const
+ ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ auto it = this->find(key);
+ if (it == this->end())
+ base_internal::ThrowStdOutOfRange("absl::btree_map::at");
+ return it->second;
+ }
+
+ private:
+ // Note: when we call `std::forward<M>(obj)` twice, it's safe because
+ // insert_unique/insert_hint_unique are guaranteed to not consume `obj` when
+ // `ret.second` is false.
+ template <class K, class M>
+ std::pair<iterator, bool> insert_or_assign_impl(K &&k, M &&obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, std::forward<K>(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret;
+ }
+ template <class K, class M>
+ iterator insert_or_assign_hint_impl(const_iterator hint, K &&k, M &&obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(hint), k, std::forward<K>(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret.first;
+ }
+
+ template <class K, class... Args>
+ std::pair<iterator, bool> try_emplace_impl(K &&k, Args &&... args) {
+ return this->tree_.insert_unique(
+ k, std::piecewise_construct, std::forward_as_tuple(std::forward<K>(k)),
+ std::forward_as_tuple(std::forward<Args>(args)...));
+ }
+ template <class K, class... Args>
+ iterator try_emplace_hint_impl(const_iterator hint, K &&k, Args &&... args) {
+ return this->tree_
+ .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
+ std::forward_as_tuple(std::forward<K>(k)),
+ std::forward_as_tuple(std::forward<Args>(args)...))
+ .first;
+ }
+};
+
+// A common base class for btree_multiset and btree_multimap.
+template <typename Tree>
+class btree_multiset_container : public btree_container<Tree> {
+ using super_type = btree_container<Tree>;
+ using params_type = typename Tree::params_type;
+ using init_type = typename params_type::init_type;
+ using is_key_compare_to = typename params_type::is_key_compare_to;
+ friend class BtreeNodePeer;
+
+ template <class K>
+ using key_arg = typename super_type::template key_arg<K>;
+
+ public:
+ using key_type = typename Tree::key_type;
+ using value_type = typename Tree::value_type;
+ using size_type = typename Tree::size_type;
+ using key_compare = typename Tree::original_key_compare;
+ using allocator_type = typename Tree::allocator_type;
+ using iterator = typename Tree::iterator;
+ using const_iterator = typename Tree::const_iterator;
+ using node_type = typename super_type::node_type;
+
+ // Inherit constructors.
+ using super_type::super_type;
+ btree_multiset_container() {}
+
+ // Range constructors.
+ template <class InputIterator>
+ btree_multiset_container(InputIterator b, InputIterator e,
+ const key_compare &comp = key_compare(),
+ const allocator_type &alloc = allocator_type())
+ : super_type(comp, alloc) {
+ insert(b, e);
+ }
+ template <class InputIterator>
+ btree_multiset_container(InputIterator b, InputIterator e,
+ const allocator_type &alloc)
+ : btree_multiset_container(b, e, key_compare(), alloc) {}
+
+ // Initializer list constructors.
+ btree_multiset_container(std::initializer_list<init_type> init,
+ const key_compare &comp = key_compare(),
+ const allocator_type &alloc = allocator_type())
+ : btree_multiset_container(init.begin(), init.end(), comp, alloc) {}
+ btree_multiset_container(std::initializer_list<init_type> init,
+ const allocator_type &alloc)
+ : btree_multiset_container(init.begin(), init.end(), alloc) {}
+
+ // Insertion routines.
+ iterator insert(const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_multi(v);
+ }
+ iterator insert(value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_multi(std::move(v));
+ }
+ iterator insert(const_iterator hint,
+ const value_type &v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_hint_multi(iterator(hint), v);
+ }
+ iterator insert(const_iterator hint,
+ value_type &&v) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
+ }
+ template <typename InputIterator>
+ void insert(InputIterator b, InputIterator e) {
+ this->tree_.insert_iterator_multi(b, e);
+ }
+ void insert(std::initializer_list<init_type> init) {
+ this->tree_.insert_iterator_multi(init.begin(), init.end());
+ }
+ template <typename... Args>
+ iterator emplace(Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ // Use a node handle to manage a temp slot.
+ auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
+ std::forward<Args>(args)...);
+ return this->tree_.insert_multi(CommonAccess::GetSlot(node));
+ }
+ template <typename... Args>
+ iterator emplace_hint(const_iterator hint,
+ Args &&...args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ // Use a node handle to manage a temp slot.
+ auto node = CommonAccess::Construct<node_type>(this->get_allocator(),
+ std::forward<Args>(args)...);
+ return this->tree_.insert_hint_multi(iterator(hint),
+ CommonAccess::GetSlot(node));
+ }
+ iterator insert(node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ if (!node) return this->end();
+ iterator res =
+ this->tree_.insert_multi(params_type::key(CommonAccess::GetSlot(node)),
+ CommonAccess::GetSlot(node));
+ CommonAccess::Destroy(&node);
+ return res;
+ }
+ iterator insert(const_iterator hint,
+ node_type &&node) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ if (!node) return this->end();
+ iterator res = this->tree_.insert_hint_multi(
+ iterator(hint),
+ std::move(params_type::element(CommonAccess::GetSlot(node))));
+ CommonAccess::Destroy(&node);
+ return res;
+ }
+
+ // Node extraction routines.
+ template <typename K = key_type>
+ node_type extract(const key_arg<K> &key) {
+ const std::pair<iterator, bool> lower_and_equal =
+ this->tree_.lower_bound_equal(key);
+ return lower_and_equal.second ? extract(lower_and_equal.first)
+ : node_type();
+ }
+ using super_type::extract;
+
+ // Merge routines.
+ // Moves all elements from `src` into `this`.
+ template <
+ typename T,
+ typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_same<value_type, typename T::value_type>,
+ std::is_same<allocator_type, typename T::allocator_type>,
+ std::is_same<typename params_type::is_map_container,
+ typename T::params_type::is_map_container>>::value,
+ int> = 0>
+ void merge(btree_container<T> &src) { // NOLINT
+ for (auto src_it = src.begin(), end = src.end(); src_it != end; ++src_it) {
+ insert(std::move(params_type::element(src_it.slot())));
+ }
+ src.clear();
+ }
+
+ template <
+ typename T,
+ typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_same<value_type, typename T::value_type>,
+ std::is_same<allocator_type, typename T::allocator_type>,
+ std::is_same<typename params_type::is_map_container,
+ typename T::params_type::is_map_container>>::value,
+ int> = 0>
+ void merge(btree_container<T> &&src) {
+ merge(src);
+ }
+};
+
+// A base class for btree_multimap.
+template <typename Tree>
+class btree_multimap_container : public btree_multiset_container<Tree> {
+ using super_type = btree_multiset_container<Tree>;
+ using params_type = typename Tree::params_type;
+ friend class BtreeNodePeer;
+
+ public:
+ using mapped_type = typename params_type::mapped_type;
+
+ // Inherit constructors.
+ using super_type::super_type;
+ btree_multimap_container() {}
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_BTREE_CONTAINER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hash_generator_testing.h b/contrib/restricted/abseil-cpp/absl/container/internal/hash_generator_testing.h
new file mode 100644
index 0000000000..f1f555a5c1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hash_generator_testing.h
@@ -0,0 +1,182 @@
+// Copyright 2018 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.
+//
+// Generates random values for testing. Specialized only for the few types we
+// care about.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
+#define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <cassert>
+#include <iosfwd>
+#include <random>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/container/internal/hash_policy_testing.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace hash_internal {
+namespace generator_internal {
+
+template <class Container, class = void>
+struct IsMap : std::false_type {};
+
+template <class Map>
+struct IsMap<Map, absl::void_t<typename Map::mapped_type>> : std::true_type {};
+
+} // namespace generator_internal
+
+std::mt19937_64* GetSharedRng();
+
+enum Enum {
+ kEnumEmpty,
+ kEnumDeleted,
+};
+
+enum class EnumClass : uint64_t {
+ kEmpty,
+ kDeleted,
+};
+
+inline std::ostream& operator<<(std::ostream& o, const EnumClass& ec) {
+ return o << static_cast<uint64_t>(ec);
+}
+
+template <class T, class E = void>
+struct Generator;
+
+template <class T>
+struct Generator<T, typename std::enable_if<std::is_integral<T>::value>::type> {
+ T operator()() const {
+ std::uniform_int_distribution<T> dist;
+ return dist(*GetSharedRng());
+ }
+};
+
+template <>
+struct Generator<Enum> {
+ Enum operator()() const {
+ std::uniform_int_distribution<typename std::underlying_type<Enum>::type>
+ dist;
+ while (true) {
+ auto variate = dist(*GetSharedRng());
+ if (variate != kEnumEmpty && variate != kEnumDeleted)
+ return static_cast<Enum>(variate);
+ }
+ }
+};
+
+template <>
+struct Generator<EnumClass> {
+ EnumClass operator()() const {
+ std::uniform_int_distribution<
+ typename std::underlying_type<EnumClass>::type>
+ dist;
+ while (true) {
+ EnumClass variate = static_cast<EnumClass>(dist(*GetSharedRng()));
+ if (variate != EnumClass::kEmpty && variate != EnumClass::kDeleted)
+ return static_cast<EnumClass>(variate);
+ }
+ }
+};
+
+template <>
+struct Generator<std::string> {
+ std::string operator()() const;
+};
+
+template <>
+struct Generator<absl::string_view> {
+ absl::string_view operator()() const;
+};
+
+template <>
+struct Generator<NonStandardLayout> {
+ NonStandardLayout operator()() const {
+ return NonStandardLayout(Generator<std::string>()());
+ }
+};
+
+template <class K, class V>
+struct Generator<std::pair<K, V>> {
+ std::pair<K, V> operator()() const {
+ return std::pair<K, V>(Generator<typename std::decay<K>::type>()(),
+ Generator<typename std::decay<V>::type>()());
+ }
+};
+
+template <class... Ts>
+struct Generator<std::tuple<Ts...>> {
+ std::tuple<Ts...> operator()() const {
+ return std::tuple<Ts...>(Generator<typename std::decay<Ts>::type>()()...);
+ }
+};
+
+template <class T>
+struct Generator<std::unique_ptr<T>> {
+ std::unique_ptr<T> operator()() const {
+ return absl::make_unique<T>(Generator<T>()());
+ }
+};
+
+template <class U>
+struct Generator<U, absl::void_t<decltype(std::declval<U&>().key()),
+ decltype(std::declval<U&>().value())>>
+ : Generator<std::pair<
+ typename std::decay<decltype(std::declval<U&>().key())>::type,
+ typename std::decay<decltype(std::declval<U&>().value())>::type>> {};
+
+template <class Container>
+using GeneratedType = decltype(
+ std::declval<const Generator<
+ typename std::conditional<generator_internal::IsMap<Container>::value,
+ typename Container::value_type,
+ typename Container::key_type>::type>&>()());
+
+// Naive wrapper that performs a linear search of previous values.
+// Beware this is O(SQR), which is reasonable for smaller kMaxValues.
+template <class T, size_t kMaxValues = 64, class E = void>
+struct UniqueGenerator {
+ Generator<T, E> gen;
+ std::vector<T> values;
+
+ T operator()() {
+ assert(values.size() < kMaxValues);
+ for (;;) {
+ T value = gen();
+ if (std::find(values.begin(), values.end(), value) == values.end()) {
+ values.push_back(value);
+ return value;
+ }
+ }
+ }
+};
+
+} // namespace hash_internal
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_testing.h b/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_testing.h
new file mode 100644
index 0000000000..66bb12ec45
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hash_policy_testing.h
@@ -0,0 +1,183 @@
+// Copyright 2018 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.
+//
+// Utilities to help tests verify that hash tables properly handle stateful
+// allocators and hash functions.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
+#define ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
+
+#include <cstdlib>
+#include <limits>
+#include <memory>
+#include <ostream>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/hash/hash.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace hash_testing_internal {
+
+template <class Derived>
+struct WithId {
+ WithId() : id_(next_id<Derived>()) {}
+ WithId(const WithId& that) : id_(that.id_) {}
+ WithId(WithId&& that) : id_(that.id_) { that.id_ = 0; }
+ WithId& operator=(const WithId& that) {
+ id_ = that.id_;
+ return *this;
+ }
+ WithId& operator=(WithId&& that) {
+ id_ = that.id_;
+ that.id_ = 0;
+ return *this;
+ }
+
+ size_t id() const { return id_; }
+
+ friend bool operator==(const WithId& a, const WithId& b) {
+ return a.id_ == b.id_;
+ }
+ friend bool operator!=(const WithId& a, const WithId& b) { return !(a == b); }
+
+ protected:
+ explicit WithId(size_t id) : id_(id) {}
+
+ private:
+ size_t id_;
+
+ template <class T>
+ static size_t next_id() {
+ // 0 is reserved for moved from state.
+ static size_t gId = 1;
+ return gId++;
+ }
+};
+
+} // namespace hash_testing_internal
+
+struct NonStandardLayout {
+ NonStandardLayout() {}
+ explicit NonStandardLayout(std::string s) : value(std::move(s)) {}
+ virtual ~NonStandardLayout() {}
+
+ friend bool operator==(const NonStandardLayout& a,
+ const NonStandardLayout& b) {
+ return a.value == b.value;
+ }
+ friend bool operator!=(const NonStandardLayout& a,
+ const NonStandardLayout& b) {
+ return a.value != b.value;
+ }
+
+ template <typename H>
+ friend H AbslHashValue(H h, const NonStandardLayout& v) {
+ return H::combine(std::move(h), v.value);
+ }
+
+ std::string value;
+};
+
+struct StatefulTestingHash
+ : absl::container_internal::hash_testing_internal::WithId<
+ StatefulTestingHash> {
+ template <class T>
+ size_t operator()(const T& t) const {
+ return absl::Hash<T>{}(t);
+ }
+};
+
+struct StatefulTestingEqual
+ : absl::container_internal::hash_testing_internal::WithId<
+ StatefulTestingEqual> {
+ template <class T, class U>
+ bool operator()(const T& t, const U& u) const {
+ return t == u;
+ }
+};
+
+// It is expected that Alloc() == Alloc() for all allocators so we cannot use
+// WithId base. We need to explicitly assign ids.
+template <class T = int>
+struct Alloc : std::allocator<T> {
+ using propagate_on_container_swap = std::true_type;
+
+ // Using old paradigm for this to ensure compatibility.
+ explicit Alloc(size_t id = 0) : id_(id) {}
+
+ Alloc(const Alloc&) = default;
+ Alloc& operator=(const Alloc&) = default;
+
+ template <class U>
+ Alloc(const Alloc<U>& that) : std::allocator<T>(that), id_(that.id()) {}
+
+ template <class U>
+ struct rebind {
+ using other = Alloc<U>;
+ };
+
+ size_t id() const { return id_; }
+
+ friend bool operator==(const Alloc& a, const Alloc& b) {
+ return a.id_ == b.id_;
+ }
+ friend bool operator!=(const Alloc& a, const Alloc& b) { return !(a == b); }
+
+ private:
+ size_t id_ = (std::numeric_limits<size_t>::max)();
+};
+
+template <class Map>
+auto items(const Map& m) -> std::vector<
+ std::pair<typename Map::key_type, typename Map::mapped_type>> {
+ using std::get;
+ std::vector<std::pair<typename Map::key_type, typename Map::mapped_type>> res;
+ res.reserve(m.size());
+ for (const auto& v : m) res.emplace_back(get<0>(v), get<1>(v));
+ return res;
+}
+
+template <class Set>
+auto keys(const Set& s)
+ -> std::vector<typename std::decay<typename Set::key_type>::type> {
+ std::vector<typename std::decay<typename Set::key_type>::type> res;
+ res.reserve(s.size());
+ for (const auto& v : s) res.emplace_back(v);
+ return res;
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions
+// where the unordered containers are missing certain constructors that
+// take allocator arguments. This test is defined ad-hoc for the platforms
+// we care about (notably Crosstool 17) because libstdcxx's useless
+// versioning scheme precludes a more principled solution.
+// From GCC-4.9 Changelog: (src: https://gcc.gnu.org/gcc-4.9/changes.html)
+// "the unordered associative containers in <unordered_map> and <unordered_set>
+// meet the allocator-aware container requirements;"
+#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20140425
+#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 0
+#else
+#define ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS 1
+#endif
+
+#endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/hashtable_debug.h b/contrib/restricted/abseil-cpp/absl/container/internal/hashtable_debug.h
new file mode 100644
index 0000000000..c79c1a9891
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/hashtable_debug.h
@@ -0,0 +1,102 @@
+// Copyright 2018 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.
+//
+// This library provides APIs to debug the probing behavior of hash tables.
+//
+// In general, the probing behavior is a black box for users and only the
+// side effects can be measured in the form of performance differences.
+// These APIs give a glimpse on the actual behavior of the probing algorithms in
+// these hashtables given a specified hash function and a set of elements.
+//
+// The probe count distribution can be used to assess the quality of the hash
+// function for that particular hash table. Note that a hash function that
+// performs well in one hash table implementation does not necessarily performs
+// well in a different one.
+//
+// This library supports std::unordered_{set,map}, dense_hash_{set,map} and
+// absl::{flat,node,string}_hash_{set,map}.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
+#define ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
+
+#include <cstddef>
+#include <algorithm>
+#include <type_traits>
+#include <vector>
+
+#include "absl/container/internal/hashtable_debug_hooks.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// Returns the number of probes required to lookup `key`. Returns 0 for a
+// search with no collisions. Higher values mean more hash collisions occurred;
+// however, the exact meaning of this number varies according to the container
+// type.
+template <typename C>
+size_t GetHashtableDebugNumProbes(
+ const C& c, const typename C::key_type& key) {
+ return absl::container_internal::hashtable_debug_internal::
+ HashtableDebugAccess<C>::GetNumProbes(c, key);
+}
+
+// Gets a histogram of the number of probes for each elements in the container.
+// The sum of all the values in the vector is equal to container.size().
+template <typename C>
+std::vector<size_t> GetHashtableDebugNumProbesHistogram(const C& container) {
+ std::vector<size_t> v;
+ for (auto it = container.begin(); it != container.end(); ++it) {
+ size_t num_probes = GetHashtableDebugNumProbes(
+ container,
+ absl::container_internal::hashtable_debug_internal::GetKey<C>(*it, 0));
+ v.resize((std::max)(v.size(), num_probes + 1));
+ v[num_probes]++;
+ }
+ return v;
+}
+
+struct HashtableDebugProbeSummary {
+ size_t total_elements;
+ size_t total_num_probes;
+ double mean;
+};
+
+// Gets a summary of the probe count distribution for the elements in the
+// container.
+template <typename C>
+HashtableDebugProbeSummary GetHashtableDebugProbeSummary(const C& container) {
+ auto probes = GetHashtableDebugNumProbesHistogram(container);
+ HashtableDebugProbeSummary summary = {};
+ for (size_t i = 0; i < probes.size(); ++i) {
+ summary.total_elements += probes[i];
+ summary.total_num_probes += probes[i] * i;
+ }
+ summary.mean = 1.0 * summary.total_num_probes / summary.total_elements;
+ return summary;
+}
+
+// Returns the number of bytes requested from the allocator by the container
+// and not freed.
+template <typename C>
+size_t AllocatedByteSize(const C& c) {
+ return absl::container_internal::hashtable_debug_internal::
+ HashtableDebugAccess<C>::AllocatedByteSize(c);
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/layout.h b/contrib/restricted/abseil-cpp/absl/container/internal/layout.h
new file mode 100644
index 0000000000..384929af49
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/layout.h
@@ -0,0 +1,844 @@
+// Copyright 2018 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.
+//
+// MOTIVATION AND TUTORIAL
+//
+// If you want to put in a single heap allocation N doubles followed by M ints,
+// it's easy if N and M are known at compile time.
+//
+// struct S {
+// double a[N];
+// int b[M];
+// };
+//
+// S* p = new S;
+//
+// But what if N and M are known only in run time? Class template Layout to the
+// rescue! It's a portable generalization of the technique known as struct hack.
+//
+// // This object will tell us everything we need to know about the memory
+// // layout of double[N] followed by int[M]. It's structurally identical to
+// // size_t[2] that stores N and M. It's very cheap to create.
+// const Layout<double, int> layout(N, M);
+//
+// // Allocate enough memory for both arrays. `AllocSize()` tells us how much
+// // memory is needed. We are free to use any allocation function we want as
+// // long as it returns aligned memory.
+// std::unique_ptr<unsigned char[]> p(new unsigned char[layout.AllocSize()]);
+//
+// // Obtain the pointer to the array of doubles.
+// // Equivalent to `reinterpret_cast<double*>(p.get())`.
+// //
+// // We could have written layout.Pointer<0>(p) instead. If all the types are
+// // unique you can use either form, but if some types are repeated you must
+// // use the index form.
+// double* a = layout.Pointer<double>(p.get());
+//
+// // Obtain the pointer to the array of ints.
+// // Equivalent to `reinterpret_cast<int*>(p.get() + N * 8)`.
+// int* b = layout.Pointer<int>(p);
+//
+// If we are unable to specify sizes of all fields, we can pass as many sizes as
+// we can to `Partial()`. In return, it'll allow us to access the fields whose
+// locations and sizes can be computed from the provided information.
+// `Partial()` comes in handy when the array sizes are embedded into the
+// allocation.
+//
+// // size_t[0] containing N, size_t[1] containing M, double[N], int[M].
+// using L = Layout<size_t, size_t, double, int>;
+//
+// unsigned char* Allocate(size_t n, size_t m) {
+// const L layout(1, 1, n, m);
+// unsigned char* p = new unsigned char[layout.AllocSize()];
+// *layout.Pointer<0>(p) = n;
+// *layout.Pointer<1>(p) = m;
+// return p;
+// }
+//
+// void Use(unsigned char* p) {
+// // First, extract N and M.
+// // Specify that the first array has only one element. Using `prefix` we
+// // can access the first two arrays but not more.
+// constexpr auto prefix = L::Partial(1);
+// size_t n = *prefix.Pointer<0>(p);
+// size_t m = *prefix.Pointer<1>(p);
+//
+// // Now we can get pointers to the payload.
+// const L layout(1, 1, n, m);
+// double* a = layout.Pointer<double>(p);
+// int* b = layout.Pointer<int>(p);
+// }
+//
+// The layout we used above combines fixed-size with dynamically-sized fields.
+// This is quite common. Layout is optimized for this use case and attempts to
+// generate optimal code. To help the compiler do that in more cases, you can
+// specify the fixed sizes using `WithStaticSizes`. This ensures that all
+// computations that can be performed at compile time are indeed performed at
+// compile time. Note that sometimes the `template` keyword is needed. E.g.:
+//
+// using SL = L::template WithStaticSizes<1, 1>;
+//
+// void Use(unsigned char* p) {
+// // First, extract N and M.
+// // Using `prefix` we can access the first three arrays but not more.
+// //
+// // More details: The first element always has offset 0. `SL`
+// // has offsets for the second and third array based on sizes of
+// // the first and second array, specified via `WithStaticSizes`.
+// constexpr auto prefix = SL::Partial();
+// size_t n = *prefix.Pointer<0>(p);
+// size_t m = *prefix.Pointer<1>(p);
+//
+// // Now we can get a pointer to the final payload.
+// const SL layout(n, m);
+// double* a = layout.Pointer<double>(p);
+// int* b = layout.Pointer<int>(p);
+// }
+//
+// Efficiency tip: The order of fields matters. In `Layout<T1, ..., TN>` try to
+// ensure that `alignof(T1) >= ... >= alignof(TN)`. This way you'll have no
+// padding in between arrays.
+//
+// You can manually override the alignment of an array by wrapping the type in
+// `Aligned<T, N>`. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
+// and behavior as `Layout<..., T, ...>` except that the first element of the
+// array of `T` is aligned to `N` (the rest of the elements follow without
+// padding). `N` cannot be less than `alignof(T)`.
+//
+// `AllocSize()` and `Pointer()` are the most basic methods for dealing with
+// memory layouts. Check out the reference or code below to discover more.
+//
+// EXAMPLE
+//
+// // Immutable move-only string with sizeof equal to sizeof(void*). The
+// // string size and the characters are kept in the same heap allocation.
+// class CompactString {
+// public:
+// CompactString(const char* s = "") {
+// const size_t size = strlen(s);
+// // size_t[1] followed by char[size + 1].
+// const L layout(size + 1);
+// p_.reset(new unsigned char[layout.AllocSize()]);
+// // If running under ASAN, mark the padding bytes, if any, to catch
+// // memory errors.
+// layout.PoisonPadding(p_.get());
+// // Store the size in the allocation.
+// *layout.Pointer<size_t>(p_.get()) = size;
+// // Store the characters in the allocation.
+// memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
+// }
+//
+// size_t size() const {
+// // Equivalent to reinterpret_cast<size_t&>(*p).
+// return *L::Partial().Pointer<size_t>(p_.get());
+// }
+//
+// const char* c_str() const {
+// // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
+// return L::Partial().Pointer<char>(p_.get());
+// }
+//
+// private:
+// // Our heap allocation contains a single size_t followed by an array of
+// // chars.
+// using L = Layout<size_t, char>::WithStaticSizes<1>;
+// std::unique_ptr<unsigned char[]> p_;
+// };
+//
+// int main() {
+// CompactString s = "hello";
+// assert(s.size() == 5);
+// assert(strcmp(s.c_str(), "hello") == 0);
+// }
+//
+// DOCUMENTATION
+//
+// The interface exported by this file consists of:
+// - class `Layout<>` and its public members.
+// - The public members of classes `internal_layout::LayoutWithStaticSizes<>`
+// and `internal_layout::LayoutImpl<>`. Those classes aren't intended to be
+// used directly, and their name and template parameter list are internal
+// implementation details, but the classes themselves provide most of the
+// functionality in this file. See comments on their members for detailed
+// documentation.
+//
+// `Layout<T1,... Tn>::Partial(count1,..., countm)` (where `m` <= `n`) returns a
+// `LayoutImpl<>` object. `Layout<T1,..., Tn> layout(count1,..., countn)`
+// creates a `Layout` object, which exposes the same functionality by inheriting
+// from `LayoutImpl<>`.
+
+#ifndef ABSL_CONTAINER_INTERNAL_LAYOUT_H_
+#define ABSL_CONTAINER_INTERNAL_LAYOUT_H_
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <array>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/debugging/internal/demangle.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/str_cat.h"
+#include "absl/types/span.h"
+#include "absl/utility/utility.h"
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// A type wrapper that instructs `Layout` to use the specific alignment for the
+// array. `Layout<..., Aligned<T, N>, ...>` has exactly the same API
+// and behavior as `Layout<..., T, ...>` except that the first element of the
+// array of `T` is aligned to `N` (the rest of the elements follow without
+// padding).
+//
+// Requires: `N >= alignof(T)` and `N` is a power of 2.
+template <class T, size_t N>
+struct Aligned;
+
+namespace internal_layout {
+
+template <class T>
+struct NotAligned {};
+
+template <class T, size_t N>
+struct NotAligned<const Aligned<T, N>> {
+ static_assert(sizeof(T) == 0, "Aligned<T, N> cannot be const-qualified");
+};
+
+template <size_t>
+using IntToSize = size_t;
+
+template <class T>
+struct Type : NotAligned<T> {
+ using type = T;
+};
+
+template <class T, size_t N>
+struct Type<Aligned<T, N>> {
+ using type = T;
+};
+
+template <class T>
+struct SizeOf : NotAligned<T>, std::integral_constant<size_t, sizeof(T)> {};
+
+template <class T, size_t N>
+struct SizeOf<Aligned<T, N>> : std::integral_constant<size_t, sizeof(T)> {};
+
+// Note: workaround for https://gcc.gnu.org/PR88115
+template <class T>
+struct AlignOf : NotAligned<T> {
+ static constexpr size_t value = alignof(T);
+};
+
+template <class T, size_t N>
+struct AlignOf<Aligned<T, N>> {
+ static_assert(N % alignof(T) == 0,
+ "Custom alignment can't be lower than the type's alignment");
+ static constexpr size_t value = N;
+};
+
+// Does `Ts...` contain `T`?
+template <class T, class... Ts>
+using Contains = absl::disjunction<std::is_same<T, Ts>...>;
+
+template <class From, class To>
+using CopyConst =
+ typename std::conditional<std::is_const<From>::value, const To, To>::type;
+
+// Note: We're not qualifying this with absl:: because it doesn't compile under
+// MSVC.
+template <class T>
+using SliceType = Span<T>;
+
+// This namespace contains no types. It prevents functions defined in it from
+// being found by ADL.
+namespace adl_barrier {
+
+template <class Needle, class... Ts>
+constexpr size_t Find(Needle, Needle, Ts...) {
+ static_assert(!Contains<Needle, Ts...>(), "Duplicate element type");
+ return 0;
+}
+
+template <class Needle, class T, class... Ts>
+constexpr size_t Find(Needle, T, Ts...) {
+ return adl_barrier::Find(Needle(), Ts()...) + 1;
+}
+
+constexpr bool IsPow2(size_t n) { return !(n & (n - 1)); }
+
+// Returns `q * m` for the smallest `q` such that `q * m >= n`.
+// Requires: `m` is a power of two. It's enforced by IsLegalElementType below.
+constexpr size_t Align(size_t n, size_t m) { return (n + m - 1) & ~(m - 1); }
+
+constexpr size_t Min(size_t a, size_t b) { return b < a ? b : a; }
+
+constexpr size_t Max(size_t a) { return a; }
+
+template <class... Ts>
+constexpr size_t Max(size_t a, size_t b, Ts... rest) {
+ return adl_barrier::Max(b < a ? a : b, rest...);
+}
+
+template <class T>
+std::string TypeName() {
+ std::string out;
+#if ABSL_INTERNAL_HAS_RTTI
+ absl::StrAppend(&out, "<",
+ absl::debugging_internal::DemangleString(typeid(T).name()),
+ ">");
+#endif
+ return out;
+}
+
+} // namespace adl_barrier
+
+template <bool C>
+using EnableIf = typename std::enable_if<C, int>::type;
+
+// Can `T` be a template argument of `Layout`?
+template <class T>
+using IsLegalElementType = std::integral_constant<
+ bool, !std::is_reference<T>::value && !std::is_volatile<T>::value &&
+ !std::is_reference<typename Type<T>::type>::value &&
+ !std::is_volatile<typename Type<T>::type>::value &&
+ adl_barrier::IsPow2(AlignOf<T>::value)>;
+
+template <class Elements, class StaticSizeSeq, class RuntimeSizeSeq,
+ class SizeSeq, class OffsetSeq>
+class LayoutImpl;
+
+// Public base class of `Layout` and the result type of `Layout::Partial()`.
+//
+// `Elements...` contains all template arguments of `Layout` that created this
+// instance.
+//
+// `StaticSizeSeq...` is an index_sequence containing the sizes specified at
+// compile-time.
+//
+// `RuntimeSizeSeq...` is `[0, NumRuntimeSizes)`, where `NumRuntimeSizes` is the
+// number of arguments passed to `Layout::Partial()` or `Layout::Layout()`.
+//
+// `SizeSeq...` is `[0, NumSizes)` where `NumSizes` is `NumRuntimeSizes` plus
+// the number of sizes in `StaticSizeSeq`.
+//
+// `OffsetSeq...` is `[0, NumOffsets)` where `NumOffsets` is
+// `Min(sizeof...(Elements), NumSizes + 1)` (the number of arrays for which we
+// can compute offsets).
+template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
+ size_t... SizeSeq, size_t... OffsetSeq>
+class LayoutImpl<
+ std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
+ absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
+ absl::index_sequence<OffsetSeq...>> {
+ private:
+ static_assert(sizeof...(Elements) > 0, "At least one field is required");
+ static_assert(absl::conjunction<IsLegalElementType<Elements>...>::value,
+ "Invalid element type (see IsLegalElementType)");
+ static_assert(sizeof...(StaticSizeSeq) <= sizeof...(Elements),
+ "Too many static sizes specified");
+
+ enum {
+ NumTypes = sizeof...(Elements),
+ NumStaticSizes = sizeof...(StaticSizeSeq),
+ NumRuntimeSizes = sizeof...(RuntimeSizeSeq),
+ NumSizes = sizeof...(SizeSeq),
+ NumOffsets = sizeof...(OffsetSeq),
+ };
+
+ // These are guaranteed by `Layout`.
+ static_assert(NumStaticSizes + NumRuntimeSizes == NumSizes, "Internal error");
+ static_assert(NumSizes <= NumTypes, "Internal error");
+ static_assert(NumOffsets == adl_barrier::Min(NumTypes, NumSizes + 1),
+ "Internal error");
+ static_assert(NumTypes > 0, "Internal error");
+
+ static constexpr std::array<size_t, sizeof...(StaticSizeSeq)> kStaticSizes = {
+ StaticSizeSeq...};
+
+ // Returns the index of `T` in `Elements...`. Results in a compilation error
+ // if `Elements...` doesn't contain exactly one instance of `T`.
+ template <class T>
+ static constexpr size_t ElementIndex() {
+ static_assert(Contains<Type<T>, Type<typename Type<Elements>::type>...>(),
+ "Type not found");
+ return adl_barrier::Find(Type<T>(),
+ Type<typename Type<Elements>::type>()...);
+ }
+
+ template <size_t N>
+ using ElementAlignment =
+ AlignOf<typename std::tuple_element<N, std::tuple<Elements...>>::type>;
+
+ public:
+ // Element types of all arrays packed in a tuple.
+ using ElementTypes = std::tuple<typename Type<Elements>::type...>;
+
+ // Element type of the Nth array.
+ template <size_t N>
+ using ElementType = typename std::tuple_element<N, ElementTypes>::type;
+
+ constexpr explicit LayoutImpl(IntToSize<RuntimeSizeSeq>... sizes)
+ : size_{sizes...} {}
+
+ // Alignment of the layout, equal to the strictest alignment of all elements.
+ // All pointers passed to the methods of layout must be aligned to this value.
+ static constexpr size_t Alignment() {
+ return adl_barrier::Max(AlignOf<Elements>::value...);
+ }
+
+ // Offset in bytes of the Nth array.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // assert(x.Offset<0>() == 0); // The ints starts from 0.
+ // assert(x.Offset<1>() == 16); // The doubles starts from 16.
+ //
+ // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
+ template <size_t N, EnableIf<N == 0> = 0>
+ constexpr size_t Offset() const {
+ return 0;
+ }
+
+ template <size_t N, EnableIf<N != 0> = 0>
+ constexpr size_t Offset() const {
+ static_assert(N < NumOffsets, "Index out of bounds");
+ return adl_barrier::Align(
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>(),
+ ElementAlignment<N>::value);
+ }
+
+ // Offset in bytes of the array with the specified element type. There must
+ // be exactly one such array and its zero-based index must be at most
+ // `NumSizes`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // assert(x.Offset<int>() == 0); // The ints starts from 0.
+ // assert(x.Offset<double>() == 16); // The doubles starts from 16.
+ template <class T>
+ constexpr size_t Offset() const {
+ return Offset<ElementIndex<T>()>();
+ }
+
+ // Offsets in bytes of all arrays for which the offsets are known.
+ constexpr std::array<size_t, NumOffsets> Offsets() const {
+ return {{Offset<OffsetSeq>()...}};
+ }
+
+ // The number of elements in the Nth array (zero-based).
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // assert(x.Size<0>() == 3);
+ // assert(x.Size<1>() == 4);
+ //
+ // Requires: `N < NumSizes`.
+ template <size_t N, EnableIf<(N < NumStaticSizes)> = 0>
+ constexpr size_t Size() const {
+ return kStaticSizes[N];
+ }
+
+ template <size_t N, EnableIf<(N >= NumStaticSizes)> = 0>
+ constexpr size_t Size() const {
+ static_assert(N < NumSizes, "Index out of bounds");
+ return size_[N - NumStaticSizes];
+ }
+
+ // The number of elements in the array with the specified element type.
+ // There must be exactly one such array and its zero-based index must be
+ // at most `NumSizes`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // assert(x.Size<int>() == 3);
+ // assert(x.Size<double>() == 4);
+ template <class T>
+ constexpr size_t Size() const {
+ return Size<ElementIndex<T>()>();
+ }
+
+ // The number of elements of all arrays for which they are known.
+ constexpr std::array<size_t, NumSizes> Sizes() const {
+ return {{Size<SizeSeq>()...}};
+ }
+
+ // Pointer to the beginning of the Nth array.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ // int* ints = x.Pointer<0>(p);
+ // double* doubles = x.Pointer<1>(p);
+ //
+ // Requires: `N <= NumSizes && N < sizeof...(Ts)`.
+ // Requires: `p` is aligned to `Alignment()`.
+ template <size_t N, class Char>
+ CopyConst<Char, ElementType<N>>* Pointer(Char* p) const {
+ using C = typename std::remove_const<Char>::type;
+ static_assert(
+ std::is_same<C, char>() || std::is_same<C, unsigned char>() ||
+ std::is_same<C, signed char>(),
+ "The argument must be a pointer to [const] [signed|unsigned] char");
+ constexpr size_t alignment = Alignment();
+ (void)alignment;
+ assert(reinterpret_cast<uintptr_t>(p) % alignment == 0);
+ return reinterpret_cast<CopyConst<Char, ElementType<N>>*>(p + Offset<N>());
+ }
+
+ // Pointer to the beginning of the array with the specified element type.
+ // There must be exactly one such array and its zero-based index must be at
+ // most `NumSizes`.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ // int* ints = x.Pointer<int>(p);
+ // double* doubles = x.Pointer<double>(p);
+ //
+ // Requires: `p` is aligned to `Alignment()`.
+ template <class T, class Char>
+ CopyConst<Char, T>* Pointer(Char* p) const {
+ return Pointer<ElementIndex<T>()>(p);
+ }
+
+ // Pointers to all arrays for which pointers are known.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ //
+ // int* ints;
+ // double* doubles;
+ // std::tie(ints, doubles) = x.Pointers(p);
+ //
+ // Requires: `p` is aligned to `Alignment()`.
+ template <class Char>
+ auto Pointers(Char* p) const {
+ return std::tuple<CopyConst<Char, ElementType<OffsetSeq>>*...>(
+ Pointer<OffsetSeq>(p)...);
+ }
+
+ // The Nth array.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ // Span<int> ints = x.Slice<0>(p);
+ // Span<double> doubles = x.Slice<1>(p);
+ //
+ // Requires: `N < NumSizes`.
+ // Requires: `p` is aligned to `Alignment()`.
+ template <size_t N, class Char>
+ SliceType<CopyConst<Char, ElementType<N>>> Slice(Char* p) const {
+ return SliceType<CopyConst<Char, ElementType<N>>>(Pointer<N>(p), Size<N>());
+ }
+
+ // The array with the specified element type. There must be exactly one
+ // such array and its zero-based index must be less than `NumSizes`.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ // Span<int> ints = x.Slice<int>(p);
+ // Span<double> doubles = x.Slice<double>(p);
+ //
+ // Requires: `p` is aligned to `Alignment()`.
+ template <class T, class Char>
+ SliceType<CopyConst<Char, T>> Slice(Char* p) const {
+ return Slice<ElementIndex<T>()>(p);
+ }
+
+ // All arrays with known sizes.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()];
+ //
+ // Span<int> ints;
+ // Span<double> doubles;
+ // std::tie(ints, doubles) = x.Slices(p);
+ //
+ // Requires: `p` is aligned to `Alignment()`.
+ //
+ // Note: We mark the parameter as unused because GCC detects it is not used
+ // when `SizeSeq` is empty [-Werror=unused-but-set-parameter].
+ template <class Char>
+ auto Slices(ABSL_ATTRIBUTE_UNUSED Char* p) const {
+ return std::tuple<SliceType<CopyConst<Char, ElementType<SizeSeq>>>...>(
+ Slice<SizeSeq>(p)...);
+ }
+
+ // The size of the allocation that fits all arrays.
+ //
+ // // int[3], 4 bytes of padding, double[4].
+ // Layout<int, double> x(3, 4);
+ // unsigned char* p = new unsigned char[x.AllocSize()]; // 48 bytes
+ //
+ // Requires: `NumSizes == sizeof...(Ts)`.
+ constexpr size_t AllocSize() const {
+ static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
+ return Offset<NumTypes - 1>() +
+ SizeOf<ElementType<NumTypes - 1>>::value * Size<NumTypes - 1>();
+ }
+
+ // If built with --config=asan, poisons padding bytes (if any) in the
+ // allocation. The pointer must point to a memory block at least
+ // `AllocSize()` bytes in length.
+ //
+ // `Char` must be `[const] [signed|unsigned] char`.
+ //
+ // Requires: `p` is aligned to `Alignment()`.
+ template <class Char, size_t N = NumOffsets - 1, EnableIf<N == 0> = 0>
+ void PoisonPadding(const Char* p) const {
+ Pointer<0>(p); // verify the requirements on `Char` and `p`
+ }
+
+ template <class Char, size_t N = NumOffsets - 1, EnableIf<N != 0> = 0>
+ void PoisonPadding(const Char* p) const {
+ static_assert(N < NumOffsets, "Index out of bounds");
+ (void)p;
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+ PoisonPadding<Char, N - 1>(p);
+ // The `if` is an optimization. It doesn't affect the observable behaviour.
+ if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
+ size_t start =
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * Size<N - 1>();
+ ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
+ }
+#endif
+ }
+
+ // Human-readable description of the memory layout. Useful for debugging.
+ // Slow.
+ //
+ // // char[5], 3 bytes of padding, int[3], 4 bytes of padding, followed
+ // // by an unknown number of doubles.
+ // auto x = Layout<char, int, double>::Partial(5, 3);
+ // assert(x.DebugString() ==
+ // "@0<char>(1)[5]; @8<int>(4)[3]; @24<double>(8)");
+ //
+ // Each field is in the following format: @offset<type>(sizeof)[size] (<type>
+ // may be missing depending on the target platform). For example,
+ // @8<int>(4)[3] means that at offset 8 we have an array of ints, where each
+ // int is 4 bytes, and we have 3 of those ints. The size of the last field may
+ // be missing (as in the example above). Only fields with known offsets are
+ // described. Type names may differ across platforms: one compiler might
+ // produce "unsigned*" where another produces "unsigned int *".
+ std::string DebugString() const {
+ const auto offsets = Offsets();
+ const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>::value...};
+ const std::string types[] = {
+ adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
+ std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
+ for (size_t i = 0; i != NumOffsets - 1; ++i) {
+ absl::StrAppend(&res, "[", DebugSize(i), "]; @", offsets[i + 1],
+ types[i + 1], "(", sizes[i + 1], ")");
+ }
+ // NumSizes is a constant that may be zero. Some compilers cannot see that
+ // inside the if statement "size_[NumSizes - 1]" must be valid.
+ int last = static_cast<int>(NumSizes) - 1;
+ if (NumTypes == NumSizes && last >= 0) {
+ absl::StrAppend(&res, "[", DebugSize(static_cast<size_t>(last)), "]");
+ }
+ return res;
+ }
+
+ private:
+ size_t DebugSize(size_t n) const {
+ if (n < NumStaticSizes) {
+ return kStaticSizes[n];
+ } else {
+ return size_[n - NumStaticSizes];
+ }
+ }
+
+ // Arguments of `Layout::Partial()` or `Layout::Layout()`.
+ size_t size_[NumRuntimeSizes > 0 ? NumRuntimeSizes : 1];
+};
+
+// Defining a constexpr static class member variable is redundant and deprecated
+// in C++17, but required in C++14.
+template <class... Elements, size_t... StaticSizeSeq, size_t... RuntimeSizeSeq,
+ size_t... SizeSeq, size_t... OffsetSeq>
+constexpr std::array<size_t, sizeof...(StaticSizeSeq)> LayoutImpl<
+ std::tuple<Elements...>, absl::index_sequence<StaticSizeSeq...>,
+ absl::index_sequence<RuntimeSizeSeq...>, absl::index_sequence<SizeSeq...>,
+ absl::index_sequence<OffsetSeq...>>::kStaticSizes;
+
+template <class StaticSizeSeq, size_t NumRuntimeSizes, class... Ts>
+using LayoutType = LayoutImpl<
+ std::tuple<Ts...>, StaticSizeSeq,
+ absl::make_index_sequence<NumRuntimeSizes>,
+ absl::make_index_sequence<NumRuntimeSizes + StaticSizeSeq::size()>,
+ absl::make_index_sequence<adl_barrier::Min(
+ sizeof...(Ts), NumRuntimeSizes + StaticSizeSeq::size() + 1)>>;
+
+template <class StaticSizeSeq, class... Ts>
+class LayoutWithStaticSizes
+ : public LayoutType<StaticSizeSeq,
+ sizeof...(Ts) - adl_barrier::Min(sizeof...(Ts),
+ StaticSizeSeq::size()),
+ Ts...> {
+ private:
+ using Super =
+ LayoutType<StaticSizeSeq,
+ sizeof...(Ts) -
+ adl_barrier::Min(sizeof...(Ts), StaticSizeSeq::size()),
+ Ts...>;
+
+ public:
+ // The result type of `Partial()` with `NumSizes` arguments.
+ template <size_t NumSizes>
+ using PartialType =
+ internal_layout::LayoutType<StaticSizeSeq, NumSizes, Ts...>;
+
+ // `Layout` knows the element types of the arrays we want to lay out in
+ // memory but not the number of elements in each array.
+ // `Partial(size1, ..., sizeN)` allows us to specify the latter. The
+ // resulting immutable object can be used to obtain pointers to the
+ // individual arrays.
+ //
+ // It's allowed to pass fewer array sizes than the number of arrays. E.g.,
+ // if all you need is to the offset of the second array, you only need to
+ // pass one argument -- the number of elements in the first array.
+ //
+ // // int[3] followed by 4 bytes of padding and an unknown number of
+ // // doubles.
+ // auto x = Layout<int, double>::Partial(3);
+ // // doubles start at byte 16.
+ // assert(x.Offset<1>() == 16);
+ //
+ // If you know the number of elements in all arrays, you can still call
+ // `Partial()` but it's more convenient to use the constructor of `Layout`.
+ //
+ // Layout<int, double> x(3, 5);
+ //
+ // Note: The sizes of the arrays must be specified in number of elements,
+ // not in bytes.
+ //
+ // Requires: `sizeof...(Sizes) + NumStaticSizes <= sizeof...(Ts)`.
+ // Requires: all arguments are convertible to `size_t`.
+ template <class... Sizes>
+ static constexpr PartialType<sizeof...(Sizes)> Partial(Sizes&&... sizes) {
+ static_assert(sizeof...(Sizes) + StaticSizeSeq::size() <= sizeof...(Ts),
+ "");
+ return PartialType<sizeof...(Sizes)>(
+ static_cast<size_t>(std::forward<Sizes>(sizes))...);
+ }
+
+ // Inherit LayoutType's constructor.
+ //
+ // Creates a layout with the sizes of all arrays specified. If you know
+ // only the sizes of the first N arrays (where N can be zero), you can use
+ // `Partial()` defined above. The constructor is essentially equivalent to
+ // calling `Partial()` and passing in all array sizes; the constructor is
+ // provided as a convenient abbreviation.
+ //
+ // Note: The sizes of the arrays must be specified in number of elements,
+ // not in bytes.
+ //
+ // Implementation note: we do this via a `using` declaration instead of
+ // defining our own explicit constructor because the signature of LayoutType's
+ // constructor depends on RuntimeSizeSeq, which we don't have access to here.
+ // If we defined our own constructor here, it would have to use a parameter
+ // pack and then cast the arguments to size_t when calling the superclass
+ // constructor, similar to what Partial() does. But that would suffer from the
+ // same problem that Partial() has, which is that the parameter types are
+ // inferred from the arguments, which may be signed types, which must then be
+ // cast to size_t. This can lead to negative values being silently (i.e. with
+ // no compiler warnings) cast to an unsigned type. Having a constructor with
+ // size_t parameters helps the compiler generate better warnings about
+ // potential bad casts, while avoiding false warnings when positive literal
+ // arguments are used. If an argument is a positive literal integer (e.g.
+ // `1`), the compiler will understand that it can be safely converted to
+ // size_t, and hence not generate a warning. But if a negative literal (e.g.
+ // `-1`) or a variable with signed type is used, then it can generate a
+ // warning about a potentially unsafe implicit cast. It would be great if we
+ // could do this for Partial() too, but unfortunately as of C++23 there seems
+ // to be no way to define a function with a variable number of parameters of a
+ // certain type, a.k.a. homogeneous function parameter packs. So we're forced
+ // to choose between explicitly casting the arguments to size_t, which
+ // suppresses all warnings, even potentially valid ones, or implicitly casting
+ // them to size_t, which generates bogus warnings whenever literal arguments
+ // are used, even if they're positive.
+ using Super::Super;
+};
+
+} // namespace internal_layout
+
+// Descriptor of arrays of various types and sizes laid out in memory one after
+// another. See the top of the file for documentation.
+//
+// Check out the public API of internal_layout::LayoutWithStaticSizes and
+// internal_layout::LayoutImpl above. Those types are internal to the library
+// but their methods are public, and they are inherited by `Layout`.
+template <class... Ts>
+class Layout : public internal_layout::LayoutWithStaticSizes<
+ absl::make_index_sequence<0>, Ts...> {
+ private:
+ using Super =
+ internal_layout::LayoutWithStaticSizes<absl::make_index_sequence<0>,
+ Ts...>;
+
+ public:
+ // If you know the sizes of some or all of the arrays at compile time, you can
+ // use `WithStaticSizes` or `WithStaticSizeSequence` to create a `Layout` type
+ // with those sizes baked in. This can help the compiler generate optimal code
+ // for calculating array offsets and AllocSize().
+ //
+ // Like `Partial()`, the N sizes you specify are for the first N arrays, and
+ // they specify the number of elements in each array, not the number of bytes.
+ template <class StaticSizeSeq>
+ using WithStaticSizeSequence =
+ internal_layout::LayoutWithStaticSizes<StaticSizeSeq, Ts...>;
+
+ template <size_t... StaticSizes>
+ using WithStaticSizes =
+ WithStaticSizeSequence<std::index_sequence<StaticSizes...>>;
+
+ // Inherit LayoutWithStaticSizes's constructor, which requires you to specify
+ // all the array sizes.
+ using Super::Super;
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/node_slot_policy.h b/contrib/restricted/abseil-cpp/absl/container/internal/node_slot_policy.h
new file mode 100644
index 0000000000..3f1874d4ec
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/node_slot_policy.h
@@ -0,0 +1,95 @@
+// Copyright 2018 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.
+//
+// Adapts a policy for nodes.
+//
+// The node policy should model:
+//
+// struct Policy {
+// // Returns a new node allocated and constructed using the allocator, using
+// // the specified arguments.
+// template <class Alloc, class... Args>
+// value_type* new_element(Alloc* alloc, Args&&... args) const;
+//
+// // Destroys and deallocates node using the allocator.
+// template <class Alloc>
+// void delete_element(Alloc* alloc, value_type* node) const;
+// };
+//
+// It may also optionally define `value()` and `apply()`. For documentation on
+// these, see hash_policy_traits.h.
+
+#ifndef ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_
+#define ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_
+
+#include <cassert>
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class Reference, class Policy>
+struct node_slot_policy {
+ static_assert(std::is_lvalue_reference<Reference>::value, "");
+
+ using slot_type = typename std::remove_cv<
+ typename std::remove_reference<Reference>::type>::type*;
+
+ template <class Alloc, class... Args>
+ static void construct(Alloc* alloc, slot_type* slot, Args&&... args) {
+ *slot = Policy::new_element(alloc, std::forward<Args>(args)...);
+ }
+
+ template <class Alloc>
+ static void destroy(Alloc* alloc, slot_type* slot) {
+ Policy::delete_element(alloc, *slot);
+ }
+
+ // Returns true_type to indicate that transfer can use memcpy.
+ template <class Alloc>
+ static std::true_type transfer(Alloc*, slot_type* new_slot,
+ slot_type* old_slot) {
+ *new_slot = *old_slot;
+ return {};
+ }
+
+ static size_t space_used(const slot_type* slot) {
+ if (slot == nullptr) return Policy::element_space_used(nullptr);
+ return Policy::element_space_used(*slot);
+ }
+
+ static Reference element(slot_type* slot) { return **slot; }
+
+ template <class T, class P = Policy>
+ static auto value(T* elem) -> decltype(P::value(elem)) {
+ return P::value(elem);
+ }
+
+ template <class... Ts, class P = Policy>
+ static auto apply(Ts&&... ts) -> decltype(P::apply(std::forward<Ts>(ts)...)) {
+ return P::apply(std::forward<Ts>(ts)...);
+ }
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_NODE_SLOT_POLICY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/test_allocator.h b/contrib/restricted/abseil-cpp/absl/container/internal/test_allocator.h
new file mode 100644
index 0000000000..8e365a3c5d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/test_allocator.h
@@ -0,0 +1,387 @@
+// Copyright 2018 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_TEST_ALLOCATOR_H_
+#define ABSL_CONTAINER_INTERNAL_TEST_ALLOCATOR_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// This is a stateful allocator, but the state lives outside of the
+// allocator (in whatever test is using the allocator). This is odd
+// but helps in tests where the allocator is propagated into nested
+// containers - that chain of allocators uses the same state and is
+// thus easier to query for aggregate allocation information.
+template <typename T>
+class CountingAllocator {
+ public:
+ using Allocator = std::allocator<T>;
+ using AllocatorTraits = std::allocator_traits<Allocator>;
+ using value_type = typename AllocatorTraits::value_type;
+ using pointer = typename AllocatorTraits::pointer;
+ using const_pointer = typename AllocatorTraits::const_pointer;
+ using size_type = typename AllocatorTraits::size_type;
+ using difference_type = typename AllocatorTraits::difference_type;
+
+ CountingAllocator() = default;
+ explicit CountingAllocator(int64_t* bytes_used) : bytes_used_(bytes_used) {}
+ CountingAllocator(int64_t* bytes_used, int64_t* instance_count)
+ : bytes_used_(bytes_used), instance_count_(instance_count) {}
+
+ template <typename U>
+ CountingAllocator(const CountingAllocator<U>& x)
+ : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}
+
+ pointer allocate(
+ size_type n,
+ typename AllocatorTraits::const_void_pointer hint = nullptr) {
+ Allocator allocator;
+ pointer ptr = AllocatorTraits::allocate(allocator, n, hint);
+ if (bytes_used_ != nullptr) {
+ *bytes_used_ += n * sizeof(T);
+ }
+ return ptr;
+ }
+
+ void deallocate(pointer p, size_type n) {
+ Allocator allocator;
+ AllocatorTraits::deallocate(allocator, p, n);
+ if (bytes_used_ != nullptr) {
+ *bytes_used_ -= n * sizeof(T);
+ }
+ }
+
+ template <typename U, typename... Args>
+ void construct(U* p, Args&&... args) {
+ Allocator allocator;
+ AllocatorTraits::construct(allocator, p, std::forward<Args>(args)...);
+ if (instance_count_ != nullptr) {
+ *instance_count_ += 1;
+ }
+ }
+
+ template <typename U>
+ void destroy(U* p) {
+ Allocator allocator;
+ // Ignore GCC warning bug.
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuse-after-free"
+#endif
+ AllocatorTraits::destroy(allocator, p);
+#if ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(12, 0)
+#pragma GCC diagnostic pop
+#endif
+ if (instance_count_ != nullptr) {
+ *instance_count_ -= 1;
+ }
+ }
+
+ template <typename U>
+ class rebind {
+ public:
+ using other = CountingAllocator<U>;
+ };
+
+ friend bool operator==(const CountingAllocator& a,
+ const CountingAllocator& b) {
+ return a.bytes_used_ == b.bytes_used_ &&
+ a.instance_count_ == b.instance_count_;
+ }
+
+ friend bool operator!=(const CountingAllocator& a,
+ const CountingAllocator& b) {
+ return !(a == b);
+ }
+
+ int64_t* bytes_used_ = nullptr;
+ int64_t* instance_count_ = nullptr;
+};
+
+template <typename T>
+struct CopyAssignPropagatingCountingAlloc : public CountingAllocator<T> {
+ using propagate_on_container_copy_assignment = std::true_type;
+
+ using Base = CountingAllocator<T>;
+ using Base::Base;
+
+ template <typename U>
+ explicit CopyAssignPropagatingCountingAlloc(
+ const CopyAssignPropagatingCountingAlloc<U>& other)
+ : Base(other.bytes_used_, other.instance_count_) {}
+
+ template <typename U>
+ struct rebind {
+ using other = CopyAssignPropagatingCountingAlloc<U>;
+ };
+};
+
+template <typename T>
+struct MoveAssignPropagatingCountingAlloc : public CountingAllocator<T> {
+ using propagate_on_container_move_assignment = std::true_type;
+
+ using Base = CountingAllocator<T>;
+ using Base::Base;
+
+ template <typename U>
+ explicit MoveAssignPropagatingCountingAlloc(
+ const MoveAssignPropagatingCountingAlloc<U>& other)
+ : Base(other.bytes_used_, other.instance_count_) {}
+
+ template <typename U>
+ struct rebind {
+ using other = MoveAssignPropagatingCountingAlloc<U>;
+ };
+};
+
+template <typename T>
+struct SwapPropagatingCountingAlloc : public CountingAllocator<T> {
+ using propagate_on_container_swap = std::true_type;
+
+ using Base = CountingAllocator<T>;
+ using Base::Base;
+
+ template <typename U>
+ explicit SwapPropagatingCountingAlloc(
+ const SwapPropagatingCountingAlloc<U>& other)
+ : Base(other.bytes_used_, other.instance_count_) {}
+
+ template <typename U>
+ struct rebind {
+ using other = SwapPropagatingCountingAlloc<U>;
+ };
+};
+
+// Tries to allocate memory at the minimum alignment even when the default
+// allocator uses a higher alignment.
+template <typename T>
+struct MinimumAlignmentAlloc : std::allocator<T> {
+ MinimumAlignmentAlloc() = default;
+
+ template <typename U>
+ explicit MinimumAlignmentAlloc(const MinimumAlignmentAlloc<U>& /*other*/) {}
+
+ template <class U>
+ struct rebind {
+ using other = MinimumAlignmentAlloc<U>;
+ };
+
+ T* allocate(size_t n) {
+ T* ptr = std::allocator<T>::allocate(n + 1);
+ char* cptr = reinterpret_cast<char*>(ptr);
+ cptr += alignof(T);
+ return reinterpret_cast<T*>(cptr);
+ }
+
+ void deallocate(T* ptr, size_t n) {
+ char* cptr = reinterpret_cast<char*>(ptr);
+ cptr -= alignof(T);
+ std::allocator<T>::deallocate(reinterpret_cast<T*>(cptr), n + 1);
+ }
+};
+
+inline bool IsAssertEnabled() {
+ // Use an assert with side-effects to figure out if they are actually enabled.
+ bool assert_enabled = false;
+ assert([&]() { // NOLINT
+ assert_enabled = true;
+ return true;
+ }());
+ return assert_enabled;
+}
+
+template <template <class Alloc> class Container>
+void TestCopyAssignAllocPropagation() {
+ int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;
+ CopyAssignPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);
+ CopyAssignPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);
+
+ // Test propagating allocator_type.
+ {
+ Container<CopyAssignPropagatingCountingAlloc<int>> c1(allocator1);
+ Container<CopyAssignPropagatingCountingAlloc<int>> c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_NE(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2 = c1;
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 200);
+ EXPECT_EQ(instances2, 0);
+ }
+ // Test non-propagating allocator_type with different allocators.
+ {
+ Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_EQ(c2.get_allocator(), allocator2);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2 = c1;
+
+ EXPECT_EQ(c2.get_allocator(), allocator2);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 100);
+ }
+ EXPECT_EQ(bytes1, 0);
+ EXPECT_EQ(instances1, 0);
+ EXPECT_EQ(bytes2, 0);
+ EXPECT_EQ(instances2, 0);
+}
+
+template <template <class Alloc> class Container>
+void TestMoveAssignAllocPropagation() {
+ int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;
+ MoveAssignPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);
+ MoveAssignPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);
+
+ // Test propagating allocator_type.
+ {
+ Container<MoveAssignPropagatingCountingAlloc<int>> c1(allocator1);
+ Container<MoveAssignPropagatingCountingAlloc<int>> c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_NE(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2 = std::move(c1);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+ }
+ // Test non-propagating allocator_type with equal allocators.
+ {
+ Container<CountingAllocator<int>> c1(allocator1), c2(allocator1);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2 = std::move(c1);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+ }
+ // Test non-propagating allocator_type with different allocators.
+ {
+ Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_NE(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2 = std::move(c1);
+
+ EXPECT_EQ(c2.get_allocator(), allocator2);
+ EXPECT_LE(instances1, 100); // The values in c1 may or may not have been
+ // destroyed at this point.
+ EXPECT_EQ(instances2, 100);
+ }
+ EXPECT_EQ(bytes1, 0);
+ EXPECT_EQ(instances1, 0);
+ EXPECT_EQ(bytes2, 0);
+ EXPECT_EQ(instances2, 0);
+}
+
+template <template <class Alloc> class Container>
+void TestSwapAllocPropagation() {
+ int64_t bytes1 = 0, instances1 = 0, bytes2 = 0, instances2 = 0;
+ SwapPropagatingCountingAlloc<int> allocator1(&bytes1, &instances1);
+ SwapPropagatingCountingAlloc<int> allocator2(&bytes2, &instances2);
+
+ // Test propagating allocator_type.
+ {
+ Container<SwapPropagatingCountingAlloc<int>> c1(allocator1), c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_NE(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2.swap(c1);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+ }
+ // Test non-propagating allocator_type with equal allocators.
+ {
+ Container<CountingAllocator<int>> c1(allocator1), c2(allocator1);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+
+ c2.swap(c1);
+
+ EXPECT_EQ(c2.get_allocator(), allocator1);
+ EXPECT_EQ(instances1, 100);
+ EXPECT_EQ(instances2, 0);
+ }
+ // Test non-propagating allocator_type with different allocators.
+ {
+ Container<CountingAllocator<int>> c1(allocator1), c2(allocator2);
+
+ for (int i = 0; i < 100; ++i) c1.insert(i);
+
+ EXPECT_NE(c1.get_allocator(), c2.get_allocator());
+ if (IsAssertEnabled()) {
+ EXPECT_DEATH_IF_SUPPORTED(c2.swap(c1), "");
+ }
+ }
+ EXPECT_EQ(bytes1, 0);
+ EXPECT_EQ(instances1, 0);
+ EXPECT_EQ(bytes2, 0);
+ EXPECT_EQ(instances2, 0);
+}
+
+template <template <class Alloc> class Container>
+void TestAllocPropagation() {
+ TestCopyAssignAllocPropagation<Container>();
+ TestMoveAssignAllocPropagation<Container>();
+ TestSwapAllocPropagation<Container>();
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_TEST_ALLOCATOR_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/test_instance_tracker.h b/contrib/restricted/abseil-cpp/absl/container/internal/test_instance_tracker.h
new file mode 100644
index 0000000000..5ff6fd714e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/test_instance_tracker.h
@@ -0,0 +1,274 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
+#define ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
+
+#include <cstdlib>
+#include <ostream>
+
+#include "absl/types/compare.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace test_internal {
+
+// A type that counts number of occurrences of the type, the live occurrences of
+// the type, as well as the number of copies, moves, swaps, and comparisons that
+// have occurred on the type. This is used as a base class for the copyable,
+// copyable+movable, and movable types below that are used in actual tests. Use
+// InstanceTracker in tests to track the number of instances.
+class BaseCountedInstance {
+ public:
+ explicit BaseCountedInstance(int x) : value_(x) {
+ ++num_instances_;
+ ++num_live_instances_;
+ }
+ BaseCountedInstance(const BaseCountedInstance& x)
+ : value_(x.value_), is_live_(x.is_live_) {
+ ++num_instances_;
+ if (is_live_) ++num_live_instances_;
+ ++num_copies_;
+ }
+ BaseCountedInstance(BaseCountedInstance&& x)
+ : value_(x.value_), is_live_(x.is_live_) {
+ x.is_live_ = false;
+ ++num_instances_;
+ ++num_moves_;
+ }
+ ~BaseCountedInstance() {
+ --num_instances_;
+ if (is_live_) --num_live_instances_;
+ }
+
+ BaseCountedInstance& operator=(const BaseCountedInstance& x) {
+ value_ = x.value_;
+ if (is_live_) --num_live_instances_;
+ is_live_ = x.is_live_;
+ if (is_live_) ++num_live_instances_;
+ ++num_copies_;
+ return *this;
+ }
+ BaseCountedInstance& operator=(BaseCountedInstance&& x) {
+ value_ = x.value_;
+ if (is_live_) --num_live_instances_;
+ is_live_ = x.is_live_;
+ x.is_live_ = false;
+ ++num_moves_;
+ return *this;
+ }
+
+ bool operator==(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ == x.value_;
+ }
+
+ bool operator!=(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ != x.value_;
+ }
+
+ bool operator<(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ < x.value_;
+ }
+
+ bool operator>(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ > x.value_;
+ }
+
+ bool operator<=(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ <= x.value_;
+ }
+
+ bool operator>=(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ >= x.value_;
+ }
+
+ absl::weak_ordering compare(const BaseCountedInstance& x) const {
+ ++num_comparisons_;
+ return value_ < x.value_
+ ? absl::weak_ordering::less
+ : value_ == x.value_ ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+
+ int value() const {
+ if (!is_live_) std::abort();
+ return value_;
+ }
+
+ friend std::ostream& operator<<(std::ostream& o,
+ const BaseCountedInstance& v) {
+ return o << "[value:" << v.value() << "]";
+ }
+
+ // Implementation of efficient swap() that counts swaps.
+ static void SwapImpl(
+ BaseCountedInstance& lhs, // NOLINT(runtime/references)
+ BaseCountedInstance& rhs) { // NOLINT(runtime/references)
+ using std::swap;
+ swap(lhs.value_, rhs.value_);
+ swap(lhs.is_live_, rhs.is_live_);
+ ++BaseCountedInstance::num_swaps_;
+ }
+
+ private:
+ friend class InstanceTracker;
+
+ int value_;
+
+ // Indicates if the value is live, ie it hasn't been moved away from.
+ bool is_live_ = true;
+
+ // Number of instances.
+ static int num_instances_;
+
+ // Number of live instances (those that have not been moved away from.)
+ static int num_live_instances_;
+
+ // Number of times that BaseCountedInstance objects were moved.
+ static int num_moves_;
+
+ // Number of times that BaseCountedInstance objects were copied.
+ static int num_copies_;
+
+ // Number of times that BaseCountedInstance objects were swapped.
+ static int num_swaps_;
+
+ // Number of times that BaseCountedInstance objects were compared.
+ static int num_comparisons_;
+};
+
+// Helper to track the BaseCountedInstance instance counters. Expects that the
+// number of instances and live_instances are the same when it is constructed
+// and when it is destructed.
+class InstanceTracker {
+ public:
+ InstanceTracker()
+ : start_instances_(BaseCountedInstance::num_instances_),
+ start_live_instances_(BaseCountedInstance::num_live_instances_) {
+ ResetCopiesMovesSwaps();
+ }
+ ~InstanceTracker() {
+ if (instances() != 0) std::abort();
+ if (live_instances() != 0) std::abort();
+ }
+
+ // Returns the number of BaseCountedInstance instances both containing valid
+ // values and those moved away from compared to when the InstanceTracker was
+ // constructed
+ int instances() const {
+ return BaseCountedInstance::num_instances_ - start_instances_;
+ }
+
+ // Returns the number of live BaseCountedInstance instances compared to when
+ // the InstanceTracker was constructed
+ int live_instances() const {
+ return BaseCountedInstance::num_live_instances_ - start_live_instances_;
+ }
+
+ // Returns the number of moves on BaseCountedInstance objects since
+ // construction or since the last call to ResetCopiesMovesSwaps().
+ int moves() const { return BaseCountedInstance::num_moves_ - start_moves_; }
+
+ // Returns the number of copies on BaseCountedInstance objects since
+ // construction or the last call to ResetCopiesMovesSwaps().
+ int copies() const {
+ return BaseCountedInstance::num_copies_ - start_copies_;
+ }
+
+ // Returns the number of swaps on BaseCountedInstance objects since
+ // construction or the last call to ResetCopiesMovesSwaps().
+ int swaps() const { return BaseCountedInstance::num_swaps_ - start_swaps_; }
+
+ // Returns the number of comparisons on BaseCountedInstance objects since
+ // construction or the last call to ResetCopiesMovesSwaps().
+ int comparisons() const {
+ return BaseCountedInstance::num_comparisons_ - start_comparisons_;
+ }
+
+ // Resets the base values for moves, copies, comparisons, and swaps to the
+ // current values, so that subsequent Get*() calls for moves, copies,
+ // comparisons, and swaps will compare to the situation at the point of this
+ // call.
+ void ResetCopiesMovesSwaps() {
+ start_moves_ = BaseCountedInstance::num_moves_;
+ start_copies_ = BaseCountedInstance::num_copies_;
+ start_swaps_ = BaseCountedInstance::num_swaps_;
+ start_comparisons_ = BaseCountedInstance::num_comparisons_;
+ }
+
+ private:
+ int start_instances_;
+ int start_live_instances_;
+ int start_moves_;
+ int start_copies_;
+ int start_swaps_;
+ int start_comparisons_;
+};
+
+// Copyable, not movable.
+class CopyableOnlyInstance : public BaseCountedInstance {
+ public:
+ explicit CopyableOnlyInstance(int x) : BaseCountedInstance(x) {}
+ CopyableOnlyInstance(const CopyableOnlyInstance& rhs) = default;
+ CopyableOnlyInstance& operator=(const CopyableOnlyInstance& rhs) = default;
+
+ friend void swap(CopyableOnlyInstance& lhs, CopyableOnlyInstance& rhs) {
+ BaseCountedInstance::SwapImpl(lhs, rhs);
+ }
+
+ static bool supports_move() { return false; }
+};
+
+// Copyable and movable.
+class CopyableMovableInstance : public BaseCountedInstance {
+ public:
+ explicit CopyableMovableInstance(int x) : BaseCountedInstance(x) {}
+ CopyableMovableInstance(const CopyableMovableInstance& rhs) = default;
+ CopyableMovableInstance(CopyableMovableInstance&& rhs) = default;
+ CopyableMovableInstance& operator=(const CopyableMovableInstance& rhs) =
+ default;
+ CopyableMovableInstance& operator=(CopyableMovableInstance&& rhs) = default;
+
+ friend void swap(CopyableMovableInstance& lhs, CopyableMovableInstance& rhs) {
+ BaseCountedInstance::SwapImpl(lhs, rhs);
+ }
+
+ static bool supports_move() { return true; }
+};
+
+// Only movable, not default-constructible.
+class MovableOnlyInstance : public BaseCountedInstance {
+ public:
+ explicit MovableOnlyInstance(int x) : BaseCountedInstance(x) {}
+ MovableOnlyInstance(MovableOnlyInstance&& other) = default;
+ MovableOnlyInstance& operator=(MovableOnlyInstance&& other) = default;
+
+ friend void swap(MovableOnlyInstance& lhs, MovableOnlyInstance& rhs) {
+ BaseCountedInstance::SwapImpl(lhs, rhs);
+ }
+
+ static bool supports_move() { return true; }
+};
+
+} // namespace test_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/tracked.h b/contrib/restricted/abseil-cpp/absl/container/internal/tracked.h
new file mode 100644
index 0000000000..29f5829f71
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/tracked.h
@@ -0,0 +1,83 @@
+// Copyright 2018 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_TRACKED_H_
+#define ABSL_CONTAINER_INTERNAL_TRACKED_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// A class that tracks its copies and moves so that it can be queried in tests.
+template <class T>
+class Tracked {
+ public:
+ Tracked() {}
+ // NOLINTNEXTLINE(runtime/explicit)
+ Tracked(const T& val) : val_(val) {}
+ Tracked(const Tracked& that)
+ : val_(that.val_),
+ num_moves_(that.num_moves_),
+ num_copies_(that.num_copies_) {
+ ++(*num_copies_);
+ }
+ Tracked(Tracked&& that)
+ : val_(std::move(that.val_)),
+ num_moves_(std::move(that.num_moves_)),
+ num_copies_(std::move(that.num_copies_)) {
+ ++(*num_moves_);
+ }
+ Tracked& operator=(const Tracked& that) {
+ val_ = that.val_;
+ num_moves_ = that.num_moves_;
+ num_copies_ = that.num_copies_;
+ ++(*num_copies_);
+ }
+ Tracked& operator=(Tracked&& that) {
+ val_ = std::move(that.val_);
+ num_moves_ = std::move(that.num_moves_);
+ num_copies_ = std::move(that.num_copies_);
+ ++(*num_moves_);
+ }
+
+ const T& val() const { return val_; }
+
+ friend bool operator==(const Tracked& a, const Tracked& b) {
+ return a.val_ == b.val_;
+ }
+ friend bool operator!=(const Tracked& a, const Tracked& b) {
+ return !(a == b);
+ }
+
+ size_t num_copies() { return *num_copies_; }
+ size_t num_moves() { return *num_moves_; }
+
+ private:
+ T val_;
+ std::shared_ptr<size_t> num_moves_ = std::make_shared<size_t>(0);
+ std::shared_ptr<size_t> num_copies_ = std::make_shared<size_t>(0);
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_TRACKED_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
new file mode 100644
index 0000000000..7e84dc2554
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
@@ -0,0 +1,494 @@
+// Copyright 2018 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_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
+
+#include <algorithm>
+#include <unordered_map>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordMap>
+class ConstructorTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ConstructorTest);
+
+TYPED_TEST_P(ConstructorTest, NoArgs) {
+ TypeParam m;
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCount) {
+ TypeParam m(123);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHash) {
+ using H = typename TypeParam::hasher;
+ H hasher;
+ TypeParam m(123, hasher);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashEqual) {
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ H hasher;
+ E equal;
+ TypeParam m(123, hasher, equal);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+template <typename T>
+struct is_std_unordered_map : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_map<std::unordered_map<T...>> : std::true_type {};
+
+#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+ absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+ has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ TypeParam m(123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+ BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ TypeParam m(123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+ BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+ absl::disjunction<absl::negation<is_std_unordered_map<T>>,
+ has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ TypeParam m(alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(m, ::testing::UnorderedElementsAre());
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+ AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::UniqueGenerator<T>());
+ TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::UniqueGenerator<T>());
+ TypeParam m(values.begin(), values.end(), 123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+ InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::UniqueGenerator<T>());
+ TypeParam m(values.begin(), values.end(), 123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+ InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructor) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ TypeParam n(m);
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ TypeParam n(m, A(11));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_NE(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+ CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+// TODO(alkis): Test non-propagating allocators on copy constructors.
+
+TYPED_TEST_P(ConstructorTest, MoveConstructor) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ TypeParam t(m);
+ TypeParam n(std::move(t));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ TypeParam t(m);
+ TypeParam n(std::move(t), A(1));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_NE(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+ MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+// TODO(alkis): Test non-propagating allocators on move constructors.
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(values, 123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using A = typename TypeParam::allocator_type;
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ A alloc(0);
+ TypeParam m(values, 123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+ InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m(values, 123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+ InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, Assignment) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
+ TypeParam n;
+ n = m;
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m, n);
+}
+
+// TODO(alkis): Test [non-]propagating allocators on move/copy assignments
+// (it depends on traits).
+
+TYPED_TEST_P(ConstructorTest, MoveAssignment) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
+ TypeParam t(m);
+ TypeParam n;
+ n = std::move(t);
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m;
+ m = values;
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m({gen(), gen(), gen()});
+ TypeParam n({gen()});
+ n = m;
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ TypeParam m({gen(), gen(), gen()});
+ TypeParam t(m);
+ TypeParam n({gen()});
+ n = std::move(t);
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m;
+ m = values;
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::UniqueGenerator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m(values);
+ m = *&m; // Avoid -Wself-assign
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+// We cannot test self move as standard states that it leaves standard
+// containers in unspecified state (and in practice in causes memory-leak
+// according to heap-checker!).
+
+REGISTER_TYPED_TEST_SUITE_P(
+ ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
+ BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+ InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+ InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
+ MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
+ InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
+ MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+ MoveAssignmentOverwritesExisting,
+ AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h
new file mode 100644
index 0000000000..3713cd9a2b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h
@@ -0,0 +1,117 @@
+// Copyright 2018 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_UNORDERED_MAP_LOOKUP_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordMap>
+class LookupTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(LookupTest);
+
+TYPED_TEST_P(LookupTest, At) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ for (const auto& p : values) {
+ const auto& val = m.at(p.first);
+ EXPECT_EQ(p.second, val) << ::testing::PrintToString(p.first);
+ }
+}
+
+TYPED_TEST_P(LookupTest, OperatorBracket) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& p : values) {
+ auto& val = m[p.first];
+ EXPECT_EQ(V(), val) << ::testing::PrintToString(p.first);
+ val = p.second;
+ }
+ for (const auto& p : values)
+ EXPECT_EQ(p.second, m[p.first]) << ::testing::PrintToString(p.first);
+}
+
+TYPED_TEST_P(LookupTest, Count) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& p : values)
+ EXPECT_EQ(0, m.count(p.first)) << ::testing::PrintToString(p.first);
+ m.insert(values.begin(), values.end());
+ for (const auto& p : values)
+ EXPECT_EQ(1, m.count(p.first)) << ::testing::PrintToString(p.first);
+}
+
+TYPED_TEST_P(LookupTest, Find) {
+ using std::get;
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& p : values)
+ EXPECT_TRUE(m.end() == m.find(p.first))
+ << ::testing::PrintToString(p.first);
+ m.insert(values.begin(), values.end());
+ for (const auto& p : values) {
+ auto it = m.find(p.first);
+ EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(p.first);
+ EXPECT_EQ(p.second, get<1>(*it)) << ::testing::PrintToString(p.first);
+ }
+}
+
+TYPED_TEST_P(LookupTest, EqualRange) {
+ using std::get;
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& p : values) {
+ auto r = m.equal_range(p.first);
+ ASSERT_EQ(0, std::distance(r.first, r.second));
+ }
+ m.insert(values.begin(), values.end());
+ for (const auto& p : values) {
+ auto r = m.equal_range(p.first);
+ ASSERT_EQ(1, std::distance(r.first, r.second));
+ EXPECT_EQ(p.second, get<1>(*r.first)) << ::testing::PrintToString(p.first);
+ }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(LookupTest, At, OperatorBracket, Count, Find,
+ EqualRange);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_LOOKUP_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_members_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_members_test.h
new file mode 100644
index 0000000000..7d48cdb890
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_members_test.h
@@ -0,0 +1,87 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordMap>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+ EXPECT_TRUE((std::is_same<std::pair<const typename TypeParam::key_type,
+ typename TypeParam::mapped_type>,
+ typename TypeParam::value_type>()));
+ EXPECT_TRUE((absl::conjunction<
+ absl::negation<std::is_signed<typename TypeParam::size_type>>,
+ std::is_integral<typename TypeParam::size_type>>()));
+ EXPECT_TRUE((absl::conjunction<
+ std::is_signed<typename TypeParam::difference_type>,
+ std::is_integral<typename TypeParam::difference_type>>()));
+ EXPECT_TRUE((std::is_convertible<
+ decltype(std::declval<const typename TypeParam::hasher&>()(
+ std::declval<const typename TypeParam::key_type&>())),
+ size_t>()));
+ EXPECT_TRUE((std::is_convertible<
+ decltype(std::declval<const typename TypeParam::key_equal&>()(
+ std::declval<const typename TypeParam::key_type&>(),
+ std::declval<const typename TypeParam::key_type&>())),
+ bool>()));
+ EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+ typename TypeParam::value_type>()));
+ EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+ typename TypeParam::reference>()));
+ EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+ typename TypeParam::const_reference>()));
+ EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+ typename TypeParam::allocator_type>::pointer,
+ typename TypeParam::pointer>()));
+ EXPECT_TRUE(
+ (std::is_same<typename std::allocator_traits<
+ typename TypeParam::allocator_type>::const_pointer,
+ typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+ EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+ TypeParam t = {typename TypeParam::value_type{}};
+ EXPECT_EQ(t.begin(), t.cbegin());
+ EXPECT_EQ(t.end(), t.cend());
+ EXPECT_NE(t.begin(), t.end());
+ EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MEMBERS_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
new file mode 100644
index 0000000000..4d9ab30fd4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
@@ -0,0 +1,352 @@
+// Copyright 2018 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_UNORDERED_MAP_MODIFIERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
+
+#include <memory>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordMap>
+class ModifiersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ModifiersTest);
+
+TYPED_TEST_P(ModifiersTest, Clear) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ m.clear();
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());
+ EXPECT_TRUE(m.empty());
+}
+
+TYPED_TEST_P(ModifiersTest, Insert) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ auto p = m.insert(val);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(val, *p.first);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ p = m.insert(val2);
+ EXPECT_FALSE(p.second);
+ EXPECT_EQ(val, *p.first);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertHint) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ auto it = m.insert(m.end(), val);
+ EXPECT_TRUE(it != m.end());
+ EXPECT_EQ(val, *it);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ it = m.insert(it, val2);
+ EXPECT_TRUE(it != m.end());
+ EXPECT_EQ(val, *it);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertRange) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ m.insert(values.begin(), values.end());
+ ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ m.reserve(10);
+ const size_t original_capacity = m.bucket_count();
+ m.insert(val);
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ m.insert(val2);
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {
+#if !defined(__GLIBCXX__)
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> base_values;
+ std::generate_n(std::back_inserter(base_values), 10,
+ hash_internal::Generator<T>());
+ std::vector<T> values;
+ while (values.size() != 100) {
+ std::copy_n(base_values.begin(), 10, std::back_inserter(values));
+ }
+ TypeParam m;
+ m.reserve(10);
+ const size_t original_capacity = m.bucket_count();
+ m.insert(values.begin(), values.end());
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+#endif
+}
+
+TYPED_TEST_P(ModifiersTest, InsertOrAssign) {
+#ifdef UNORDERED_MAP_CXX17
+ using std::get;
+ using K = typename TypeParam::key_type;
+ using V = typename TypeParam::mapped_type;
+ K k = hash_internal::Generator<K>()();
+ V val = hash_internal::Generator<V>()();
+ TypeParam m;
+ auto p = m.insert_or_assign(k, val);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(k, get<0>(*p.first));
+ EXPECT_EQ(val, get<1>(*p.first));
+ V val2 = hash_internal::Generator<V>()();
+ p = m.insert_or_assign(k, val2);
+ EXPECT_FALSE(p.second);
+ EXPECT_EQ(k, get<0>(*p.first));
+ EXPECT_EQ(val2, get<1>(*p.first));
+#endif
+}
+
+TYPED_TEST_P(ModifiersTest, InsertOrAssignHint) {
+#ifdef UNORDERED_MAP_CXX17
+ using std::get;
+ using K = typename TypeParam::key_type;
+ using V = typename TypeParam::mapped_type;
+ K k = hash_internal::Generator<K>()();
+ V val = hash_internal::Generator<V>()();
+ TypeParam m;
+ auto it = m.insert_or_assign(m.end(), k, val);
+ EXPECT_TRUE(it != m.end());
+ EXPECT_EQ(k, get<0>(*it));
+ EXPECT_EQ(val, get<1>(*it));
+ V val2 = hash_internal::Generator<V>()();
+ it = m.insert_or_assign(it, k, val2);
+ EXPECT_EQ(k, get<0>(*it));
+ EXPECT_EQ(val2, get<1>(*it));
+#endif
+}
+
+TYPED_TEST_P(ModifiersTest, Emplace) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto p = m.emplace(val);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(val, *p.first);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ p = m.emplace(val2);
+ EXPECT_FALSE(p.second);
+ EXPECT_EQ(val, *p.first);
+}
+
+TYPED_TEST_P(ModifiersTest, EmplaceHint) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto it = m.emplace_hint(m.end(), val);
+ EXPECT_EQ(val, *it);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ it = m.emplace_hint(it, val2);
+ EXPECT_EQ(val, *it);
+}
+
+TYPED_TEST_P(ModifiersTest, TryEmplace) {
+#ifdef UNORDERED_MAP_CXX17
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto p = m.try_emplace(val.first, val.second);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(val, *p.first);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ p = m.try_emplace(val2.first, val2.second);
+ EXPECT_FALSE(p.second);
+ EXPECT_EQ(val, *p.first);
+#endif
+}
+
+TYPED_TEST_P(ModifiersTest, TryEmplaceHint) {
+#ifdef UNORDERED_MAP_CXX17
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto it = m.try_emplace(m.end(), val.first, val.second);
+ EXPECT_EQ(val, *it);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ it = m.try_emplace(it, val2.first, val2.second);
+ EXPECT_EQ(val, *it);
+#endif
+}
+
+template <class V>
+using IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type;
+
+// In openmap we chose not to return the iterator from erase because that's
+// more expensive. As such we adapt erase to return an iterator here.
+struct EraseFirst {
+ template <class Map>
+ auto operator()(Map* m, int) const
+ -> IfNotVoid<decltype(m->erase(m->begin()))> {
+ return m->erase(m->begin());
+ }
+ template <class Map>
+ typename Map::iterator operator()(Map* m, ...) const {
+ auto it = m->begin();
+ m->erase(it++);
+ return it;
+ }
+};
+
+TYPED_TEST_P(ModifiersTest, Erase) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using std::get;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ auto& first = *m.begin();
+ std::vector<T> values2;
+ for (const auto& val : values)
+ if (get<0>(val) != get<0>(first)) values2.push_back(val);
+ auto it = EraseFirst()(&m, 0);
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it));
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values2.begin(),
+ values2.end()));
+}
+
+TYPED_TEST_P(ModifiersTest, EraseRange) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ auto it = m.erase(m.begin(), m.end());
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAre());
+ EXPECT_TRUE(it == m.end());
+}
+
+TYPED_TEST_P(ModifiersTest, EraseKey) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_EQ(1, m.erase(values[0].first));
+ EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0]));
+ EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values.begin() + 1,
+ values.end()));
+}
+
+TYPED_TEST_P(ModifiersTest, Swap) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> v1;
+ std::vector<T> v2;
+ std::generate_n(std::back_inserter(v1), 5, hash_internal::Generator<T>());
+ std::generate_n(std::back_inserter(v2), 5, hash_internal::Generator<T>());
+ TypeParam m1(v1.begin(), v1.end());
+ TypeParam m2(v2.begin(), v2.end());
+ EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v1));
+ EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v2));
+ m1.swap(m2);
+ EXPECT_THAT(items(m1), ::testing::UnorderedElementsAreArray(v2));
+ EXPECT_THAT(items(m2), ::testing::UnorderedElementsAreArray(v1));
+}
+
+// TODO(alkis): Write tests for extract.
+// TODO(alkis): Write tests for merge.
+
+REGISTER_TYPED_TEST_SUITE_P(ModifiersTest, Clear, Insert, InsertHint,
+ InsertRange, InsertWithinCapacity,
+ InsertRangeWithinCapacity, InsertOrAssign,
+ InsertOrAssignHint, Emplace, EmplaceHint,
+ TryEmplace, TryEmplaceHint, Erase, EraseRange,
+ EraseKey, Swap);
+
+template <typename Type>
+struct is_unique_ptr : std::false_type {};
+
+template <typename Type>
+struct is_unique_ptr<std::unique_ptr<Type>> : std::true_type {};
+
+template <class UnordMap>
+class UniquePtrModifiersTest : public ::testing::Test {
+ protected:
+ UniquePtrModifiersTest() {
+ static_assert(is_unique_ptr<typename UnordMap::mapped_type>::value,
+ "UniquePtrModifiersTyest may only be called with a "
+ "std::unique_ptr value type.");
+ }
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UniquePtrModifiersTest);
+
+TYPED_TEST_SUITE_P(UniquePtrModifiersTest);
+
+// Test that we do not move from rvalue arguments if an insertion does not
+// happen.
+TYPED_TEST_P(UniquePtrModifiersTest, TryEmplace) {
+#ifdef UNORDERED_MAP_CXX17
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using V = typename TypeParam::mapped_type;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ auto p = m.try_emplace(val.first, std::move(val.second));
+ EXPECT_TRUE(p.second);
+ // A moved from std::unique_ptr is guaranteed to be nullptr.
+ EXPECT_EQ(val.second, nullptr);
+ T val2 = {val.first, hash_internal::Generator<V>()()};
+ p = m.try_emplace(val2.first, std::move(val2.second));
+ EXPECT_FALSE(p.second);
+ EXPECT_NE(val2.second, nullptr);
+#endif
+}
+
+REGISTER_TYPED_TEST_SUITE_P(UniquePtrModifiersTest, TryEmplace);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_MODIFIERS_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h
new file mode 100644
index 0000000000..af1116e6c3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h
@@ -0,0 +1,496 @@
+// Copyright 2018 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_UNORDERED_SET_CONSTRUCTOR_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
+
+#include <algorithm>
+#include <unordered_set>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordMap>
+class ConstructorTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ConstructorTest);
+
+TYPED_TEST_P(ConstructorTest, NoArgs) {
+ TypeParam m;
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCount) {
+ TypeParam m(123);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHash) {
+ using H = typename TypeParam::hasher;
+ H hasher;
+ TypeParam m(123, hasher);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashEqual) {
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ H hasher;
+ E equal;
+ TypeParam m(123, hasher, equal);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+
+ const auto& cm = m;
+ EXPECT_EQ(cm.hash_function(), hasher);
+ EXPECT_EQ(cm.key_eq(), equal);
+ EXPECT_EQ(cm.get_allocator(), alloc);
+ EXPECT_TRUE(cm.empty());
+ EXPECT_THAT(keys(cm), ::testing::UnorderedElementsAre());
+ EXPECT_GE(cm.bucket_count(), 123);
+}
+
+template <typename T>
+struct is_std_unordered_set : std::false_type {};
+
+template <typename... T>
+struct is_std_unordered_set<std::unordered_set<T...>> : std::true_type {};
+
+#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+using has_cxx14_std_apis = std::true_type;
+#else
+using has_cxx14_std_apis = std::false_type;
+#endif
+
+template <typename T>
+using expect_cxx14_apis =
+ absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+ has_cxx14_std_apis>;
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountAllocTest(std::true_type) {
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ TypeParam m(123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+ BucketCountAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void BucketCountHashAllocTest(std::true_type) {
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ TypeParam m(123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
+ BucketCountHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+using has_alloc_std_constructors = std::true_type;
+#else
+using has_alloc_std_constructors = std::false_type;
+#endif
+
+template <typename T>
+using expect_alloc_constructors =
+ absl::disjunction<absl::negation<is_std_unordered_set<T>>,
+ has_alloc_std_constructors>;
+
+template <typename TypeParam>
+void AllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void AllocTest(std::true_type) {
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ TypeParam m(alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_TRUE(m.empty());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+ AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ std::vector<T> values;
+ for (size_t i = 0; i != 10; ++i)
+ values.push_back(hash_internal::Generator<T>()());
+ TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using A = typename TypeParam::allocator_type;
+ A alloc(0);
+ std::vector<T> values;
+ for (size_t i = 0; i != 10; ++i)
+ values.push_back(hash_internal::Generator<T>()());
+ TypeParam m(values.begin(), values.end(), 123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
+ InputIteratorBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InputIteratorBucketHashAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ std::vector<T> values;
+ for (size_t i = 0; i != 10; ++i)
+ values.push_back(hash_internal::Generator<T>()());
+ TypeParam m(values.begin(), values.end(), 123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+ InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructor) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
+ TypeParam n(m);
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+ EXPECT_NE(TypeParam(0, hasher, equal, alloc), n);
+}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void CopyConstructorAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
+ TypeParam n(m, A(11));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_NE(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+ CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+// TODO(alkis): Test non-propagating allocators on copy constructors.
+
+TYPED_TEST_P(ConstructorTest, MoveConstructor) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
+ TypeParam t(m);
+ TypeParam n(std::move(t));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void MoveConstructorAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(123, hasher, equal, alloc);
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
+ TypeParam t(m);
+ TypeParam n(std::move(t), A(1));
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_NE(m.get_allocator(), n.get_allocator());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+ MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
+}
+
+// TODO(alkis): Test non-propagating allocators on move constructors.
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ TypeParam m(values, 123, hasher, equal, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.key_eq(), equal);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using A = typename TypeParam::allocator_type;
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ A alloc(0);
+ TypeParam m(values, 123, alloc);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
+ InitializerListBucketAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::false_type) {}
+
+template <typename TypeParam>
+void InitializerListBucketHashAllocTest(std::true_type) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ A alloc(0);
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m(values, 123, hasher, alloc);
+ EXPECT_EQ(m.hash_function(), hasher);
+ EXPECT_EQ(m.get_allocator(), alloc);
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_GE(m.bucket_count(), 123);
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+ InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
+}
+
+TYPED_TEST_P(ConstructorTest, CopyAssignment) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::Generator<T> gen;
+ TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
+ TypeParam n;
+ n = m;
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m, n);
+}
+
+// TODO(alkis): Test [non-]propagating allocators on move/copy assignments
+// (it depends on traits).
+
+TYPED_TEST_P(ConstructorTest, MoveAssignment) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ using H = typename TypeParam::hasher;
+ using E = typename TypeParam::key_equal;
+ using A = typename TypeParam::allocator_type;
+ H hasher;
+ E equal;
+ A alloc(0);
+ hash_internal::Generator<T> gen;
+ TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
+ TypeParam t(m);
+ TypeParam n;
+ n = std::move(t);
+ EXPECT_EQ(m.hash_function(), n.hash_function());
+ EXPECT_EQ(m.key_eq(), n.key_eq());
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m;
+ m = values;
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ TypeParam m({gen(), gen(), gen()});
+ TypeParam n({gen()});
+ n = m;
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ TypeParam m({gen(), gen(), gen()});
+ TypeParam t(m);
+ TypeParam n({gen()});
+ n = std::move(t);
+ EXPECT_EQ(m, n);
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m;
+ m = values;
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ hash_internal::Generator<T> gen;
+ std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
+ TypeParam m(values);
+ m = *&m; // Avoid -Wself-assign.
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+REGISTER_TYPED_TEST_SUITE_P(
+ ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
+ BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+ InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+ InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
+ MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
+ InitializerListBucketAlloc, InitializerListBucketHashAlloc, CopyAssignment,
+ MoveAssignment, AssignmentFromInitializerList, AssignmentOverwritesExisting,
+ MoveAssignmentOverwritesExisting,
+ AssignmentFromInitializerListOverwritesExisting, AssignmentOnSelf);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_CONSTRUCTOR_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h
new file mode 100644
index 0000000000..b35f766e79
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h
@@ -0,0 +1,91 @@
+// Copyright 2018 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_UNORDERED_SET_LOOKUP_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordSet>
+class LookupTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(LookupTest);
+
+TYPED_TEST_P(LookupTest, Count) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& v : values)
+ EXPECT_EQ(0, m.count(v)) << ::testing::PrintToString(v);
+ m.insert(values.begin(), values.end());
+ for (const auto& v : values)
+ EXPECT_EQ(1, m.count(v)) << ::testing::PrintToString(v);
+}
+
+TYPED_TEST_P(LookupTest, Find) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& v : values)
+ EXPECT_TRUE(m.end() == m.find(v)) << ::testing::PrintToString(v);
+ m.insert(values.begin(), values.end());
+ for (const auto& v : values) {
+ typename TypeParam::iterator it = m.find(v);
+ static_assert(std::is_same<const typename TypeParam::value_type&,
+ decltype(*it)>::value,
+ "");
+ static_assert(std::is_same<const typename TypeParam::value_type*,
+ decltype(it.operator->())>::value,
+ "");
+ EXPECT_TRUE(m.end() != it) << ::testing::PrintToString(v);
+ EXPECT_EQ(v, *it) << ::testing::PrintToString(v);
+ }
+}
+
+TYPED_TEST_P(LookupTest, EqualRange) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ for (const auto& v : values) {
+ auto r = m.equal_range(v);
+ ASSERT_EQ(0, std::distance(r.first, r.second));
+ }
+ m.insert(values.begin(), values.end());
+ for (const auto& v : values) {
+ auto r = m.equal_range(v);
+ ASSERT_EQ(1, std::distance(r.first, r.second));
+ EXPECT_EQ(v, *r.first);
+ }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(LookupTest, Count, Find, EqualRange);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_LOOKUP_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_members_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_members_test.h
new file mode 100644
index 0000000000..4c5e104af2
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_members_test.h
@@ -0,0 +1,86 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
+
+#include <type_traits>
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordSet>
+class MembersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(MembersTest);
+
+template <typename T>
+void UseType() {}
+
+TYPED_TEST_P(MembersTest, Typedefs) {
+ EXPECT_TRUE((std::is_same<typename TypeParam::key_type,
+ typename TypeParam::value_type>()));
+ EXPECT_TRUE((absl::conjunction<
+ absl::negation<std::is_signed<typename TypeParam::size_type>>,
+ std::is_integral<typename TypeParam::size_type>>()));
+ EXPECT_TRUE((absl::conjunction<
+ std::is_signed<typename TypeParam::difference_type>,
+ std::is_integral<typename TypeParam::difference_type>>()));
+ EXPECT_TRUE((std::is_convertible<
+ decltype(std::declval<const typename TypeParam::hasher&>()(
+ std::declval<const typename TypeParam::key_type&>())),
+ size_t>()));
+ EXPECT_TRUE((std::is_convertible<
+ decltype(std::declval<const typename TypeParam::key_equal&>()(
+ std::declval<const typename TypeParam::key_type&>(),
+ std::declval<const typename TypeParam::key_type&>())),
+ bool>()));
+ EXPECT_TRUE((std::is_same<typename TypeParam::allocator_type::value_type,
+ typename TypeParam::value_type>()));
+ EXPECT_TRUE((std::is_same<typename TypeParam::value_type&,
+ typename TypeParam::reference>()));
+ EXPECT_TRUE((std::is_same<const typename TypeParam::value_type&,
+ typename TypeParam::const_reference>()));
+ EXPECT_TRUE((std::is_same<typename std::allocator_traits<
+ typename TypeParam::allocator_type>::pointer,
+ typename TypeParam::pointer>()));
+ EXPECT_TRUE(
+ (std::is_same<typename std::allocator_traits<
+ typename TypeParam::allocator_type>::const_pointer,
+ typename TypeParam::const_pointer>()));
+}
+
+TYPED_TEST_P(MembersTest, SimpleFunctions) {
+ EXPECT_GT(TypeParam().max_size(), 0);
+}
+
+TYPED_TEST_P(MembersTest, BeginEnd) {
+ TypeParam t = {typename TypeParam::value_type{}};
+ EXPECT_EQ(t.begin(), t.cbegin());
+ EXPECT_EQ(t.end(), t.cend());
+ EXPECT_NE(t.begin(), t.end());
+ EXPECT_NE(t.cbegin(), t.cend());
+}
+
+REGISTER_TYPED_TEST_SUITE_P(MembersTest, Typedefs, SimpleFunctions, BeginEnd);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MEMBERS_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
new file mode 100644
index 0000000000..d8864bb28e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
@@ -0,0 +1,221 @@
+// Copyright 2018 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_UNORDERED_SET_MODIFIERS_TEST_H_
+#define ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/hash_generator_testing.h"
+#include "absl/container/internal/hash_policy_testing.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class UnordSet>
+class ModifiersTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ModifiersTest);
+
+TYPED_TEST_P(ModifiersTest, Clear) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ m.clear();
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_TRUE(m.empty());
+}
+
+TYPED_TEST_P(ModifiersTest, Insert) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ auto p = m.insert(val);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(val, *p.first);
+ p = m.insert(val);
+ EXPECT_FALSE(p.second);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertHint) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ auto it = m.insert(m.end(), val);
+ EXPECT_TRUE(it != m.end());
+ EXPECT_EQ(val, *it);
+ it = m.insert(it, val);
+ EXPECT_TRUE(it != m.end());
+ EXPECT_EQ(val, *it);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertRange) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m;
+ m.insert(values.begin(), values.end());
+ ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+}
+
+TYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ m.reserve(10);
+ const size_t original_capacity = m.bucket_count();
+ m.insert(val);
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+ m.insert(val);
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+}
+
+TYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {
+#if !defined(__GLIBCXX__)
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> base_values;
+ std::generate_n(std::back_inserter(base_values), 10,
+ hash_internal::Generator<T>());
+ std::vector<T> values;
+ while (values.size() != 100) {
+ values.insert(values.end(), base_values.begin(), base_values.end());
+ }
+ TypeParam m;
+ m.reserve(10);
+ const size_t original_capacity = m.bucket_count();
+ m.insert(values.begin(), values.end());
+ EXPECT_EQ(m.bucket_count(), original_capacity);
+#endif
+}
+
+TYPED_TEST_P(ModifiersTest, Emplace) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto p = m.emplace(val);
+ EXPECT_TRUE(p.second);
+ EXPECT_EQ(val, *p.first);
+ p = m.emplace(val);
+ EXPECT_FALSE(p.second);
+ EXPECT_EQ(val, *p.first);
+}
+
+TYPED_TEST_P(ModifiersTest, EmplaceHint) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ T val = hash_internal::Generator<T>()();
+ TypeParam m;
+ // TODO(alkis): We need a way to run emplace in a more meaningful way. Perhaps
+ // with test traits/policy.
+ auto it = m.emplace_hint(m.end(), val);
+ EXPECT_EQ(val, *it);
+ it = m.emplace_hint(it, val);
+ EXPECT_EQ(val, *it);
+}
+
+template <class V>
+using IfNotVoid = typename std::enable_if<!std::is_void<V>::value, V>::type;
+
+// In openmap we chose not to return the iterator from erase because that's
+// more expensive. As such we adapt erase to return an iterator here.
+struct EraseFirst {
+ template <class Map>
+ auto operator()(Map* m, int) const
+ -> IfNotVoid<decltype(m->erase(m->begin()))> {
+ return m->erase(m->begin());
+ }
+ template <class Map>
+ typename Map::iterator operator()(Map* m, ...) const {
+ auto it = m->begin();
+ m->erase(it++);
+ return it;
+ }
+};
+
+TYPED_TEST_P(ModifiersTest, Erase) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ std::vector<T> values2;
+ for (const auto& val : values)
+ if (val != *m.begin()) values2.push_back(val);
+ auto it = EraseFirst()(&m, 0);
+ ASSERT_TRUE(it != m.end());
+ EXPECT_EQ(1, std::count(values2.begin(), values2.end(), *it));
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values2.begin(),
+ values2.end()));
+}
+
+TYPED_TEST_P(ModifiersTest, EraseRange) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ auto it = m.erase(m.begin(), m.end());
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
+ EXPECT_TRUE(it == m.end());
+}
+
+TYPED_TEST_P(ModifiersTest, EraseKey) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> values;
+ std::generate_n(std::back_inserter(values), 10,
+ hash_internal::Generator<T>());
+ TypeParam m(values.begin(), values.end());
+ ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
+ EXPECT_EQ(1, m.erase(values[0]));
+ EXPECT_EQ(0, std::count(m.begin(), m.end(), values[0]));
+ EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values.begin() + 1,
+ values.end()));
+}
+
+TYPED_TEST_P(ModifiersTest, Swap) {
+ using T = hash_internal::GeneratedType<TypeParam>;
+ std::vector<T> v1;
+ std::vector<T> v2;
+ std::generate_n(std::back_inserter(v1), 5, hash_internal::Generator<T>());
+ std::generate_n(std::back_inserter(v2), 5, hash_internal::Generator<T>());
+ TypeParam m1(v1.begin(), v1.end());
+ TypeParam m2(v2.begin(), v2.end());
+ EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v1));
+ EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v2));
+ m1.swap(m2);
+ EXPECT_THAT(keys(m1), ::testing::UnorderedElementsAreArray(v2));
+ EXPECT_THAT(keys(m2), ::testing::UnorderedElementsAreArray(v1));
+}
+
+// TODO(alkis): Write tests for extract.
+// TODO(alkis): Write tests for merge.
+
+REGISTER_TYPED_TEST_SUITE_P(ModifiersTest, Clear, Insert, InsertHint,
+ InsertRange, InsertWithinCapacity,
+ InsertRangeWithinCapacity, Emplace, EmplaceHint,
+ Erase, EraseRange, EraseKey, Swap);
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h b/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h
new file mode 100644
index 0000000000..5615e4966b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/node_hash_map.h
@@ -0,0 +1,663 @@
+// Copyright 2018 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: node_hash_map.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::node_hash_map<K, V>` is an unordered associative container of
+// unique keys and associated values designed to be a more efficient replacement
+// for `std::unordered_map`. Like `unordered_map`, search, insertion, and
+// deletion of map elements can be done as an `O(1)` operation. However,
+// `node_hash_map` (and other unordered associative containers known as the
+// collection of Abseil "Swiss tables") contain other optimizations that result
+// in both memory and computation advantages.
+//
+// In most cases, your default choice for a hash map should be a map of type
+// `flat_hash_map`. However, if you need pointer stability and cannot store
+// a `flat_hash_map` with `unique_ptr` elements, a `node_hash_map` may be a
+// valid alternative. As well, if you are migrating your code from using
+// `std::unordered_map`, a `node_hash_map` provides a more straightforward
+// migration, because it guarantees pointer stability. Consider migrating to
+// `node_hash_map` and perhaps converting to a more efficient `flat_hash_map`
+// upon further review.
+//
+// `node_hash_map` is not exception-safe.
+
+#ifndef ABSL_CONTAINER_NODE_HASH_MAP_H_
+#define ABSL_CONTAINER_NODE_HASH_MAP_H_
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "absl/algorithm/container.h"
+#include "absl/base/attributes.h"
+#include "absl/container/hash_container_defaults.h"
+#include "absl/container/internal/container_memory.h"
+#include "absl/container/internal/node_slot_policy.h"
+#include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+template <class Key, class Value>
+class NodeHashMapPolicy;
+} // namespace container_internal
+
+// -----------------------------------------------------------------------------
+// absl::node_hash_map
+// -----------------------------------------------------------------------------
+//
+// An `absl::node_hash_map<K, V>` is an unordered associative container which
+// has been optimized for both speed and memory footprint in most common use
+// cases. Its interface is similar to that of `std::unordered_map<K, V>` with
+// the following notable differences:
+//
+// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
+// `insert()`, provided that the map is provided a compatible heterogeneous
+// hashing function and equality operator. See below for details.
+// * Contains a `capacity()` member function indicating the number of element
+// slots (open, deleted, and empty) within the hash map.
+// * Returns `void` from the `erase(iterator)` overload.
+//
+// By default, `node_hash_map` uses the `absl::Hash` hashing framework.
+// All fundamental and Abseil types that support the `absl::Hash` framework have
+// a compatible equality operator for comparing insertions into `node_hash_map`.
+// If your type is not yet supported by the `absl::Hash` framework, see
+// absl/hash/hash.h for information on extending Abseil hashing to user-defined
+// types.
+//
+// Using `absl::node_hash_map` at interface boundaries in dynamically loaded
+// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
+// be randomized across dynamically loaded libraries.
+//
+// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type
+// parameters can be used or `T` should have public inner types
+// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,
+// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be
+// well-formed. Both types are basically functors:
+// * `Hash` should support `size_t operator()(U val) const` that returns a hash
+// for the given `val`.
+// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true
+// if `lhs` is equal to `rhs`.
+//
+// In most cases `T` needs only to provide the `absl_container_hash`. In this
+// case `std::equal_to<void>` will be used instead of `eq` part.
+//
+// Example:
+//
+// // Create a node hash map of three strings (that map to strings)
+// absl::node_hash_map<std::string, std::string> ducks =
+// {{"a", "huey"}, {"b", "dewey"}, {"c", "louie"}};
+//
+// // Insert a new element into the node hash map
+// ducks.insert({"d", "donald"}};
+//
+// // Force a rehash of the node hash map
+// ducks.rehash(0);
+//
+// // Find the element with the key "b"
+// std::string search_key = "b";
+// auto result = ducks.find(search_key);
+// if (result != ducks.end()) {
+// std::cout << "Result: " << result->second << std::endl;
+// }
+template <class Key, class Value, class Hash = DefaultHashContainerHash<Key>,
+ class Eq = DefaultHashContainerEq<Key>,
+ class Alloc = std::allocator<std::pair<const Key, Value>>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_map
+ : public absl::container_internal::raw_hash_map<
+ absl::container_internal::NodeHashMapPolicy<Key, Value>, Hash, Eq,
+ Alloc> {
+ using Base = typename node_hash_map::raw_hash_map;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A node_hash_map supports the same overload set as `std::unordered_map`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // // No allocation for the table's elements is made.
+ // absl::node_hash_map<int, std::string> map1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::node_hash_map<int, std::string> map2 =
+ // {{1, "huey"}, {2, "dewey"}, {3, "louie"},};
+ //
+ // * Copy constructor
+ //
+ // absl::node_hash_map<int, std::string> map3(map2);
+ //
+ // * Copy assignment operator
+ //
+ // // Hash functor and Comparator are copied as well
+ // absl::node_hash_map<int, std::string> map4;
+ // map4 = map3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::node_hash_map<int, std::string> map5(std::move(map4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::node_hash_map<int, std::string> map6;
+ // map6 = std::move(map5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+ // absl::node_hash_map<int, std::string> map7(v.begin(), v.end());
+ node_hash_map() {}
+ using Base::Base;
+
+ // node_hash_map::begin()
+ //
+ // Returns an iterator to the beginning of the `node_hash_map`.
+ using Base::begin;
+
+ // node_hash_map::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `node_hash_map`.
+ using Base::cbegin;
+
+ // node_hash_map::cend()
+ //
+ // Returns a const iterator to the end of the `node_hash_map`.
+ using Base::cend;
+
+ // node_hash_map::end()
+ //
+ // Returns an iterator to the end of the `node_hash_map`.
+ using Base::end;
+
+ // node_hash_map::capacity()
+ //
+ // Returns the number of element slots (assigned, deleted, and empty)
+ // available within the `node_hash_map`.
+ //
+ // NOTE: this member function is particular to `absl::node_hash_map` and is
+ // not provided in the `std::unordered_map` API.
+ using Base::capacity;
+
+ // node_hash_map::empty()
+ //
+ // Returns whether or not the `node_hash_map` is empty.
+ using Base::empty;
+
+ // node_hash_map::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `node_hash_map` under current memory constraints. This value can be thought
+ // of as the largest value of `std::distance(begin(), end())` for a
+ // `node_hash_map<K, V>`.
+ using Base::max_size;
+
+ // node_hash_map::size()
+ //
+ // Returns the number of elements currently within the `node_hash_map`.
+ using Base::size;
+
+ // node_hash_map::clear()
+ //
+ // Removes all elements from the `node_hash_map`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ //
+ // NOTE: this operation may shrink the underlying buffer. To avoid shrinking
+ // the underlying buffer call `erase(begin(), end())`.
+ using Base::clear;
+
+ // node_hash_map::erase()
+ //
+ // Erases elements within the `node_hash_map`. Erasing does not trigger a
+ // rehash. Overloads are listed below.
+ //
+ // void erase(const_iterator pos):
+ //
+ // Erases the element at `position` of the `node_hash_map`, returning
+ // `void`.
+ //
+ // NOTE: this return behavior is different than that of STL containers in
+ // general and `std::unordered_map` in particular.
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning an
+ // iterator pointing to `last`. The special case of calling
+ // `erase(begin(), end())` resets the reserved growth such that if
+ // `reserve(N)` has previously been called and there has been no intervening
+ // call to `clear()`, then after calling `erase(begin(), end())`, it is safe
+ // to assume that inserting N elements will not cause a rehash.
+ //
+ // size_type erase(const key_type& key):
+ //
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
+ using Base::erase;
+
+ // node_hash_map::insert()
+ //
+ // Inserts an element of the specified value into the `node_hash_map`,
+ // returning an iterator pointing to the newly inserted element, provided that
+ // an element with the given key does not already exist. If rehashing occurs
+ // due to the insertion, all iterators are invalidated. Overloads are listed
+ // below.
+ //
+ // std::pair<iterator,bool> insert(const init_type& value):
+ //
+ // Inserts a value into the `node_hash_map`. Returns a pair consisting of an
+ // iterator to the inserted element (or to the element that prevented the
+ // insertion) and a `bool` denoting whether the insertion took place.
+ //
+ // std::pair<iterator,bool> insert(T&& value):
+ // std::pair<iterator,bool> insert(init_type&& value):
+ //
+ // Inserts a moveable value into the `node_hash_map`. Returns a `std::pair`
+ // consisting of an iterator to the inserted element (or to the element that
+ // prevented the insertion) and a `bool` denoting whether the insertion took
+ // place.
+ //
+ // iterator insert(const_iterator hint, const init_type& value):
+ // iterator insert(const_iterator hint, T&& value):
+ // iterator insert(const_iterator hint, init_type&& value);
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element, or to the existing element that prevented the
+ // insertion.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // NOTE: Although the STL does not specify which element may be inserted if
+ // multiple keys compare equivalently, for `node_hash_map` we guarantee the
+ // first match is inserted.
+ //
+ // void insert(std::initializer_list<init_type> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ //
+ // NOTE: Although the STL does not specify which element may be inserted if
+ // multiple keys compare equivalently within the initializer list, for
+ // `node_hash_map` we guarantee the first match is inserted.
+ using Base::insert;
+
+ // node_hash_map::insert_or_assign()
+ //
+ // Inserts an element of the specified value into the `node_hash_map` provided
+ // that a value with the given key does not already exist, or replaces it with
+ // the element value if a key for that value already exists, returning an
+ // iterator pointing to the newly inserted element. If rehashing occurs due to
+ // the insertion, all iterators are invalidated. Overloads are listed
+ // below.
+ //
+ // std::pair<iterator, bool> insert_or_assign(const init_type& k, T&& obj):
+ // std::pair<iterator, bool> insert_or_assign(init_type&& k, T&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `node_hash_map`.
+ //
+ // iterator insert_or_assign(const_iterator hint,
+ // const init_type& k, T&& obj):
+ // iterator insert_or_assign(const_iterator hint, init_type&& k, T&& obj):
+ //
+ // Inserts/Assigns (or moves) the element of the specified key into the
+ // `node_hash_map` using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search.
+ using Base::insert_or_assign;
+
+ // node_hash_map::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `node_hash_map`, provided that no element with the given key
+ // already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately. Prefer `try_emplace()` unless your key is not
+ // copyable or moveable.
+ //
+ // If rehashing occurs due to the insertion, all iterators are invalidated.
+ using Base::emplace;
+
+ // node_hash_map::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `node_hash_map`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search, and only inserts
+ // provided that no element with the given key already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately. Prefer `try_emplace()` unless your key is not
+ // copyable or moveable.
+ //
+ // If rehashing occurs due to the insertion, all iterators are invalidated.
+ using Base::emplace_hint;
+
+ // node_hash_map::try_emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `node_hash_map`, provided that no element with the given key
+ // already exists. Unlike `emplace()`, if an element with the given key
+ // already exists, we guarantee that no element is constructed.
+ //
+ // If rehashing occurs due to the insertion, all iterators are invalidated.
+ // Overloads are listed below.
+ //
+ // std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args):
+ // std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args):
+ //
+ // Inserts (via copy or move) the element of the specified key into the
+ // `node_hash_map`.
+ //
+ // iterator try_emplace(const_iterator hint,
+ // const key_type& k, Args&&... args):
+ // iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args):
+ //
+ // Inserts (via copy or move) the element of the specified key into the
+ // `node_hash_map` using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search.
+ //
+ // All `try_emplace()` overloads make the same guarantees regarding rvalue
+ // arguments as `std::unordered_map::try_emplace()`, namely that these
+ // functions will not move from rvalue arguments if insertions do not happen.
+ using Base::try_emplace;
+
+ // node_hash_map::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the key,value pair of the element at the indicated position and
+ // returns a node handle owning that extracted data.
+ //
+ // node_type extract(const key_type& x):
+ //
+ // Extracts the key,value pair of the element with a key matching the passed
+ // key value and returns a node handle owning that extracted data. If the
+ // `node_hash_map` does not contain an element with a matching key, this
+ // function returns an empty node handle.
+ //
+ // NOTE: when compiled in an earlier version of C++ than C++17,
+ // `node_type::key()` returns a const reference to the key instead of a
+ // mutable reference. We cannot safely return a mutable reference without
+ // std::launder (which is not available before C++17).
+ using Base::extract;
+
+ // node_hash_map::merge()
+ //
+ // Extracts elements from a given `source` node hash map into this
+ // `node_hash_map`. If the destination `node_hash_map` already contains an
+ // element with an equivalent key, that element is not extracted.
+ using Base::merge;
+
+ // node_hash_map::swap(node_hash_map& other)
+ //
+ // Exchanges the contents of this `node_hash_map` with those of the `other`
+ // node hash map, avoiding invocation of any move, copy, or swap operations on
+ // individual elements.
+ //
+ // All iterators and references on the `node_hash_map` remain valid, excepting
+ // for the past-the-end iterator, which is invalidated.
+ //
+ // `swap()` requires that the node hash map's hashing and key equivalence
+ // functions be Swappable, and are exchanged using unqualified calls to
+ // non-member `swap()`. If the map's allocator has
+ // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
+ // set to `true`, the allocators are also exchanged using an unqualified call
+ // to non-member `swap()`; otherwise, the allocators are not swapped.
+ using Base::swap;
+
+ // node_hash_map::rehash(count)
+ //
+ // Rehashes the `node_hash_map`, setting the number of slots to be at least
+ // the passed value. If the new number of slots increases the load factor more
+ // than the current maximum load factor
+ // (`count` < `size()` / `max_load_factor()`), then the new number of slots
+ // will be at least `size()` / `max_load_factor()`.
+ //
+ // To force a rehash, pass rehash(0).
+ using Base::rehash;
+
+ // node_hash_map::reserve(count)
+ //
+ // Sets the number of slots in the `node_hash_map` to the number needed to
+ // accommodate at least `count` total elements without exceeding the current
+ // maximum load factor, and may rehash the container if needed.
+ using Base::reserve;
+
+ // node_hash_map::at()
+ //
+ // Returns a reference to the mapped value of the element with key equivalent
+ // to the passed key.
+ using Base::at;
+
+ // node_hash_map::contains()
+ //
+ // Determines whether an element with a key comparing equal to the given `key`
+ // exists within the `node_hash_map`, returning `true` if so or `false`
+ // otherwise.
+ using Base::contains;
+
+ // node_hash_map::count(const Key& key) const
+ //
+ // Returns the number of elements with a key comparing equal to the given
+ // `key` within the `node_hash_map`. note that this function will return
+ // either `1` or `0` since duplicate keys are not allowed within a
+ // `node_hash_map`.
+ using Base::count;
+
+ // node_hash_map::equal_range()
+ //
+ // Returns a closed range [first, last], defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the
+ // `node_hash_map`.
+ using Base::equal_range;
+
+ // node_hash_map::find()
+ //
+ // Finds an element with the passed `key` within the `node_hash_map`.
+ using Base::find;
+
+ // node_hash_map::operator[]()
+ //
+ // Returns a reference to the value mapped to the passed key within the
+ // `node_hash_map`, performing an `insert()` if the key does not already
+ // exist. If an insertion occurs and results in a rehashing of the container,
+ // all iterators are invalidated. Otherwise iterators are not affected and
+ // references are not invalidated. Overloads are listed below.
+ //
+ // T& operator[](const Key& key):
+ //
+ // Inserts an init_type object constructed in-place if the element with the
+ // given key does not exist.
+ //
+ // T& operator[](Key&& key):
+ //
+ // Inserts an init_type object constructed in-place provided that an element
+ // with the given key does not exist.
+ using Base::operator[];
+
+ // node_hash_map::bucket_count()
+ //
+ // Returns the number of "buckets" within the `node_hash_map`.
+ using Base::bucket_count;
+
+ // node_hash_map::load_factor()
+ //
+ // Returns the current load factor of the `node_hash_map` (the average number
+ // of slots occupied with a value within the hash map).
+ using Base::load_factor;
+
+ // node_hash_map::max_load_factor()
+ //
+ // Manages the maximum load factor of the `node_hash_map`. Overloads are
+ // listed below.
+ //
+ // float node_hash_map::max_load_factor()
+ //
+ // Returns the current maximum load factor of the `node_hash_map`.
+ //
+ // void node_hash_map::max_load_factor(float ml)
+ //
+ // Sets the maximum load factor of the `node_hash_map` to the passed value.
+ //
+ // NOTE: This overload is provided only for API compatibility with the STL;
+ // `node_hash_map` will ignore any set load factor and manage its rehashing
+ // internally as an implementation detail.
+ using Base::max_load_factor;
+
+ // node_hash_map::get_allocator()
+ //
+ // Returns the allocator function associated with this `node_hash_map`.
+ using Base::get_allocator;
+
+ // node_hash_map::hash_function()
+ //
+ // Returns the hashing function used to hash the keys within this
+ // `node_hash_map`.
+ using Base::hash_function;
+
+ // node_hash_map::key_eq()
+ //
+ // Returns the function used for comparing keys equality.
+ using Base::key_eq;
+};
+
+// erase_if(node_hash_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+// Returns the number of erased elements.
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Predicate>
+typename node_hash_map<K, V, H, E, A>::size_type erase_if(
+ node_hash_map<K, V, H, E, A>& c, Predicate pred) {
+ return container_internal::EraseIf(pred, &c);
+}
+
+namespace container_internal {
+
+// c_for_each_fast(node_hash_map<>, Function)
+//
+// Container-based version of the <algorithm> `std::for_each()` function to
+// apply a function to a container's elements.
+// There is no guarantees on the order of the function calls.
+// Erasure and/or insertion of elements in the function is not allowed.
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Function>
+decay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c,
+ Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Function>
+decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c,
+ Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Function>
+decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c,
+ Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+
+} // namespace container_internal
+
+namespace container_internal {
+
+template <class Key, class Value>
+class NodeHashMapPolicy
+ : public absl::container_internal::node_slot_policy<
+ std::pair<const Key, Value>&, NodeHashMapPolicy<Key, Value>> {
+ using value_type = std::pair<const Key, Value>;
+
+ public:
+ using key_type = Key;
+ using mapped_type = Value;
+ using init_type = std::pair</*non const*/ key_type, mapped_type>;
+
+ template <class Allocator, class... Args>
+ static value_type* new_element(Allocator* alloc, Args&&... args) {
+ using PairAlloc = typename absl::allocator_traits<
+ Allocator>::template rebind_alloc<value_type>;
+ PairAlloc pair_alloc(*alloc);
+ value_type* res =
+ absl::allocator_traits<PairAlloc>::allocate(pair_alloc, 1);
+ absl::allocator_traits<PairAlloc>::construct(pair_alloc, res,
+ std::forward<Args>(args)...);
+ return res;
+ }
+
+ template <class Allocator>
+ static void delete_element(Allocator* alloc, value_type* pair) {
+ using PairAlloc = typename absl::allocator_traits<
+ Allocator>::template rebind_alloc<value_type>;
+ PairAlloc pair_alloc(*alloc);
+ absl::allocator_traits<PairAlloc>::destroy(pair_alloc, pair);
+ absl::allocator_traits<PairAlloc>::deallocate(pair_alloc, pair, 1);
+ }
+
+ template <class F, class... Args>
+ static decltype(absl::container_internal::DecomposePair(
+ std::declval<F>(), std::declval<Args>()...))
+ apply(F&& f, Args&&... args) {
+ return absl::container_internal::DecomposePair(std::forward<F>(f),
+ std::forward<Args>(args)...);
+ }
+
+ static size_t element_space_used(const value_type*) {
+ return sizeof(value_type);
+ }
+
+ static Value& value(value_type* elem) { return elem->second; }
+ static const Value& value(const value_type* elem) { return elem->second; }
+
+ template <class Hash>
+ static constexpr HashSlotFn get_hash_slot_fn() {
+ return memory_internal::IsLayoutCompatible<Key, Value>::value
+ ? &TypeErasedDerefAndApplyToSlotFn<Hash, Key>
+ : nullptr;
+ }
+};
+} // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class T, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<
+ absl::node_hash_map<Key, T, Hash, KeyEqual, Allocator>> : std::true_type {};
+
+} // namespace container_algorithm_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_NODE_HASH_MAP_H_
diff --git a/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h b/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h
new file mode 100644
index 0000000000..53435ae630
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/container/node_hash_set.h
@@ -0,0 +1,554 @@
+// Copyright 2018 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: node_hash_set.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::node_hash_set<T>` is an unordered associative container designed to
+// be a more efficient replacement for `std::unordered_set`. Like
+// `unordered_set`, search, insertion, and deletion of set elements can be done
+// as an `O(1)` operation. However, `node_hash_set` (and other unordered
+// associative containers known as the collection of Abseil "Swiss tables")
+// contain other optimizations that result in both memory and computation
+// advantages.
+//
+// In most cases, your default choice for a hash table should be a map of type
+// `flat_hash_map` or a set of type `flat_hash_set`. However, if you need
+// pointer stability, a `node_hash_set` should be your preferred choice. As
+// well, if you are migrating your code from using `std::unordered_set`, a
+// `node_hash_set` should be an easy migration. Consider migrating to
+// `node_hash_set` and perhaps converting to a more efficient `flat_hash_set`
+// upon further review.
+//
+// `node_hash_set` is not exception-safe.
+
+#ifndef ABSL_CONTAINER_NODE_HASH_SET_H_
+#define ABSL_CONTAINER_NODE_HASH_SET_H_
+
+#include <cstddef>
+#include <memory>
+#include <type_traits>
+
+#include "absl/algorithm/container.h"
+#include "absl/base/attributes.h"
+#include "absl/container/hash_container_defaults.h"
+#include "absl/container/internal/container_memory.h"
+#include "absl/container/internal/node_slot_policy.h"
+#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+template <typename T>
+struct NodeHashSetPolicy;
+} // namespace container_internal
+
+// -----------------------------------------------------------------------------
+// absl::node_hash_set
+// -----------------------------------------------------------------------------
+//
+// An `absl::node_hash_set<T>` is an unordered associative container which
+// has been optimized for both speed and memory footprint in most common use
+// cases. Its interface is similar to that of `std::unordered_set<T>` with the
+// following notable differences:
+//
+// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
+// `insert()`, provided that the set is provided a compatible heterogeneous
+// hashing function and equality operator. See below for details.
+// * Contains a `capacity()` member function indicating the number of element
+// slots (open, deleted, and empty) within the hash set.
+// * Returns `void` from the `erase(iterator)` overload.
+//
+// By default, `node_hash_set` uses the `absl::Hash` hashing framework.
+// All fundamental and Abseil types that support the `absl::Hash` framework have
+// a compatible equality operator for comparing insertions into `node_hash_set`.
+// If your type is not yet supported by the `absl::Hash` framework, see
+// absl/hash/hash.h for information on extending Abseil hashing to user-defined
+// types.
+//
+// Using `absl::node_hash_set` at interface boundaries in dynamically loaded
+// libraries (e.g. .dll, .so) is unsupported due to way `absl::Hash` values may
+// be randomized across dynamically loaded libraries.
+//
+// To achieve heterogeneous lookup for custom types either `Hash` and `Eq` type
+// parameters can be used or `T` should have public inner types
+// `absl_container_hash` and (optionally) `absl_container_eq`. In either case,
+// `typename Hash::is_transparent` and `typename Eq::is_transparent` should be
+// well-formed. Both types are basically functors:
+// * `Hash` should support `size_t operator()(U val) const` that returns a hash
+// for the given `val`.
+// * `Eq` should support `bool operator()(U lhs, V rhs) const` that returns true
+// if `lhs` is equal to `rhs`.
+//
+// In most cases `T` needs only to provide the `absl_container_hash`. In this
+// case `std::equal_to<void>` will be used instead of `eq` part.
+//
+// Example:
+//
+// // Create a node hash set of three strings
+// absl::node_hash_set<std::string> ducks =
+// {"huey", "dewey", "louie"};
+//
+// // Insert a new element into the node hash set
+// ducks.insert("donald");
+//
+// // Force a rehash of the node hash set
+// ducks.rehash(0);
+//
+// // See if "dewey" is present
+// if (ducks.contains("dewey")) {
+// std::cout << "We found dewey!" << std::endl;
+// }
+template <class T, class Hash = DefaultHashContainerHash<T>,
+ class Eq = DefaultHashContainerEq<T>, class Alloc = std::allocator<T>>
+class ABSL_INTERNAL_ATTRIBUTE_OWNER node_hash_set
+ : public absl::container_internal::raw_hash_set<
+ absl::container_internal::NodeHashSetPolicy<T>, Hash, Eq, Alloc> {
+ using Base = typename node_hash_set::raw_hash_set;
+
+ public:
+ // Constructors and Assignment Operators
+ //
+ // A node_hash_set supports the same overload set as `std::unordered_set`
+ // for construction and assignment:
+ //
+ // * Default constructor
+ //
+ // // No allocation for the table's elements is made.
+ // absl::node_hash_set<std::string> set1;
+ //
+ // * Initializer List constructor
+ //
+ // absl::node_hash_set<std::string> set2 =
+ // {{"huey"}, {"dewey"}, {"louie"}};
+ //
+ // * Copy constructor
+ //
+ // absl::node_hash_set<std::string> set3(set2);
+ //
+ // * Copy assignment operator
+ //
+ // // Hash functor and Comparator are copied as well
+ // absl::node_hash_set<std::string> set4;
+ // set4 = set3;
+ //
+ // * Move constructor
+ //
+ // // Move is guaranteed efficient
+ // absl::node_hash_set<std::string> set5(std::move(set4));
+ //
+ // * Move assignment operator
+ //
+ // // May be efficient if allocators are compatible
+ // absl::node_hash_set<std::string> set6;
+ // set6 = std::move(set5);
+ //
+ // * Range constructor
+ //
+ // std::vector<std::string> v = {"a", "b"};
+ // absl::node_hash_set<std::string> set7(v.begin(), v.end());
+ node_hash_set() {}
+ using Base::Base;
+
+ // node_hash_set::begin()
+ //
+ // Returns an iterator to the beginning of the `node_hash_set`.
+ using Base::begin;
+
+ // node_hash_set::cbegin()
+ //
+ // Returns a const iterator to the beginning of the `node_hash_set`.
+ using Base::cbegin;
+
+ // node_hash_set::cend()
+ //
+ // Returns a const iterator to the end of the `node_hash_set`.
+ using Base::cend;
+
+ // node_hash_set::end()
+ //
+ // Returns an iterator to the end of the `node_hash_set`.
+ using Base::end;
+
+ // node_hash_set::capacity()
+ //
+ // Returns the number of element slots (assigned, deleted, and empty)
+ // available within the `node_hash_set`.
+ //
+ // NOTE: this member function is particular to `absl::node_hash_set` and is
+ // not provided in the `std::unordered_set` API.
+ using Base::capacity;
+
+ // node_hash_set::empty()
+ //
+ // Returns whether or not the `node_hash_set` is empty.
+ using Base::empty;
+
+ // node_hash_set::max_size()
+ //
+ // Returns the largest theoretical possible number of elements within a
+ // `node_hash_set` under current memory constraints. This value can be thought
+ // of the largest value of `std::distance(begin(), end())` for a
+ // `node_hash_set<T>`.
+ using Base::max_size;
+
+ // node_hash_set::size()
+ //
+ // Returns the number of elements currently within the `node_hash_set`.
+ using Base::size;
+
+ // node_hash_set::clear()
+ //
+ // Removes all elements from the `node_hash_set`. Invalidates any references,
+ // pointers, or iterators referring to contained elements.
+ //
+ // NOTE: this operation may shrink the underlying buffer. To avoid shrinking
+ // the underlying buffer call `erase(begin(), end())`.
+ using Base::clear;
+
+ // node_hash_set::erase()
+ //
+ // Erases elements within the `node_hash_set`. Erasing does not trigger a
+ // rehash. Overloads are listed below.
+ //
+ // void erase(const_iterator pos):
+ //
+ // Erases the element at `position` of the `node_hash_set`, returning
+ // `void`.
+ //
+ // NOTE: this return behavior is different than that of STL containers in
+ // general and `std::unordered_set` in particular.
+ //
+ // iterator erase(const_iterator first, const_iterator last):
+ //
+ // Erases the elements in the open interval [`first`, `last`), returning an
+ // iterator pointing to `last`. The special case of calling
+ // `erase(begin(), end())` resets the reserved growth such that if
+ // `reserve(N)` has previously been called and there has been no intervening
+ // call to `clear()`, then after calling `erase(begin(), end())`, it is safe
+ // to assume that inserting N elements will not cause a rehash.
+ //
+ // size_type erase(const key_type& key):
+ //
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
+ using Base::erase;
+
+ // node_hash_set::insert()
+ //
+ // Inserts an element of the specified value into the `node_hash_set`,
+ // returning an iterator pointing to the newly inserted element, provided that
+ // an element with the given key does not already exist. If rehashing occurs
+ // due to the insertion, all iterators are invalidated. Overloads are listed
+ // below.
+ //
+ // std::pair<iterator,bool> insert(const T& value):
+ //
+ // Inserts a value into the `node_hash_set`. Returns a pair consisting of an
+ // iterator to the inserted element (or to the element that prevented the
+ // insertion) and a bool denoting whether the insertion took place.
+ //
+ // std::pair<iterator,bool> insert(T&& value):
+ //
+ // Inserts a moveable value into the `node_hash_set`. Returns a pair
+ // consisting of an iterator to the inserted element (or to the element that
+ // prevented the insertion) and a bool denoting whether the insertion took
+ // place.
+ //
+ // iterator insert(const_iterator hint, const T& value):
+ // iterator insert(const_iterator hint, T&& value):
+ //
+ // Inserts a value, using the position of `hint` as a non-binding suggestion
+ // for where to begin the insertion search. Returns an iterator to the
+ // inserted element, or to the existing element that prevented the
+ // insertion.
+ //
+ // void insert(InputIterator first, InputIterator last):
+ //
+ // Inserts a range of values [`first`, `last`).
+ //
+ // NOTE: Although the STL does not specify which element may be inserted if
+ // multiple keys compare equivalently, for `node_hash_set` we guarantee the
+ // first match is inserted.
+ //
+ // void insert(std::initializer_list<T> ilist):
+ //
+ // Inserts the elements within the initializer list `ilist`.
+ //
+ // NOTE: Although the STL does not specify which element may be inserted if
+ // multiple keys compare equivalently within the initializer list, for
+ // `node_hash_set` we guarantee the first match is inserted.
+ using Base::insert;
+
+ // node_hash_set::emplace()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `node_hash_set`, provided that no element with the given key
+ // already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately.
+ //
+ // If rehashing occurs due to the insertion, all iterators are invalidated.
+ using Base::emplace;
+
+ // node_hash_set::emplace_hint()
+ //
+ // Inserts an element of the specified value by constructing it in-place
+ // within the `node_hash_set`, using the position of `hint` as a non-binding
+ // suggestion for where to begin the insertion search, and only inserts
+ // provided that no element with the given key already exists.
+ //
+ // The element may be constructed even if there already is an element with the
+ // key in the container, in which case the newly constructed element will be
+ // destroyed immediately.
+ //
+ // If rehashing occurs due to the insertion, all iterators are invalidated.
+ using Base::emplace_hint;
+
+ // node_hash_set::extract()
+ //
+ // Extracts the indicated element, erasing it in the process, and returns it
+ // as a C++17-compatible node handle. Overloads are listed below.
+ //
+ // node_type extract(const_iterator position):
+ //
+ // Extracts the element at the indicated position and returns a node handle
+ // owning that extracted data.
+ //
+ // node_type extract(const key_type& x):
+ //
+ // Extracts the element with the key matching the passed key value and
+ // returns a node handle owning that extracted data. If the `node_hash_set`
+ // does not contain an element with a matching key, this function returns an
+ // empty node handle.
+ using Base::extract;
+
+ // node_hash_set::merge()
+ //
+ // Extracts elements from a given `source` node hash set into this
+ // `node_hash_set`. If the destination `node_hash_set` already contains an
+ // element with an equivalent key, that element is not extracted.
+ using Base::merge;
+
+ // node_hash_set::swap(node_hash_set& other)
+ //
+ // Exchanges the contents of this `node_hash_set` with those of the `other`
+ // node hash set, avoiding invocation of any move, copy, or swap operations on
+ // individual elements.
+ //
+ // All iterators and references on the `node_hash_set` remain valid, excepting
+ // for the past-the-end iterator, which is invalidated.
+ //
+ // `swap()` requires that the node hash set's hashing and key equivalence
+ // functions be Swappable, and are exchanged using unqualified calls to
+ // non-member `swap()`. If the set's allocator has
+ // `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
+ // set to `true`, the allocators are also exchanged using an unqualified call
+ // to non-member `swap()`; otherwise, the allocators are not swapped.
+ using Base::swap;
+
+ // node_hash_set::rehash(count)
+ //
+ // Rehashes the `node_hash_set`, setting the number of slots to be at least
+ // the passed value. If the new number of slots increases the load factor more
+ // than the current maximum load factor
+ // (`count` < `size()` / `max_load_factor()`), then the new number of slots
+ // will be at least `size()` / `max_load_factor()`.
+ //
+ // To force a rehash, pass rehash(0).
+ //
+ // NOTE: unlike behavior in `std::unordered_set`, references are also
+ // invalidated upon a `rehash()`.
+ using Base::rehash;
+
+ // node_hash_set::reserve(count)
+ //
+ // Sets the number of slots in the `node_hash_set` to the number needed to
+ // accommodate at least `count` total elements without exceeding the current
+ // maximum load factor, and may rehash the container if needed.
+ using Base::reserve;
+
+ // node_hash_set::contains()
+ //
+ // Determines whether an element comparing equal to the given `key` exists
+ // within the `node_hash_set`, returning `true` if so or `false` otherwise.
+ using Base::contains;
+
+ // node_hash_set::count(const Key& key) const
+ //
+ // Returns the number of elements comparing equal to the given `key` within
+ // the `node_hash_set`. note that this function will return either `1` or `0`
+ // since duplicate elements are not allowed within a `node_hash_set`.
+ using Base::count;
+
+ // node_hash_set::equal_range()
+ //
+ // Returns a closed range [first, last], defined by a `std::pair` of two
+ // iterators, containing all elements with the passed key in the
+ // `node_hash_set`.
+ using Base::equal_range;
+
+ // node_hash_set::find()
+ //
+ // Finds an element with the passed `key` within the `node_hash_set`.
+ using Base::find;
+
+ // node_hash_set::bucket_count()
+ //
+ // Returns the number of "buckets" within the `node_hash_set`. Note that
+ // because a node hash set contains all elements within its internal storage,
+ // this value simply equals the current capacity of the `node_hash_set`.
+ using Base::bucket_count;
+
+ // node_hash_set::load_factor()
+ //
+ // Returns the current load factor of the `node_hash_set` (the average number
+ // of slots occupied with a value within the hash set).
+ using Base::load_factor;
+
+ // node_hash_set::max_load_factor()
+ //
+ // Manages the maximum load factor of the `node_hash_set`. Overloads are
+ // listed below.
+ //
+ // float node_hash_set::max_load_factor()
+ //
+ // Returns the current maximum load factor of the `node_hash_set`.
+ //
+ // void node_hash_set::max_load_factor(float ml)
+ //
+ // Sets the maximum load factor of the `node_hash_set` to the passed value.
+ //
+ // NOTE: This overload is provided only for API compatibility with the STL;
+ // `node_hash_set` will ignore any set load factor and manage its rehashing
+ // internally as an implementation detail.
+ using Base::max_load_factor;
+
+ // node_hash_set::get_allocator()
+ //
+ // Returns the allocator function associated with this `node_hash_set`.
+ using Base::get_allocator;
+
+ // node_hash_set::hash_function()
+ //
+ // Returns the hashing function used to hash the keys within this
+ // `node_hash_set`.
+ using Base::hash_function;
+
+ // node_hash_set::key_eq()
+ //
+ // Returns the function used for comparing keys equality.
+ using Base::key_eq;
+};
+
+// erase_if(node_hash_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+// Returns the number of erased elements.
+template <typename T, typename H, typename E, typename A, typename Predicate>
+typename node_hash_set<T, H, E, A>::size_type erase_if(
+ node_hash_set<T, H, E, A>& c, Predicate pred) {
+ return container_internal::EraseIf(pred, &c);
+}
+
+namespace container_internal {
+
+// c_for_each_fast(node_hash_set<>, Function)
+//
+// Container-based version of the <algorithm> `std::for_each()` function to
+// apply a function to a container's elements.
+// There is no guarantees on the order of the function calls.
+// Erasure and/or insertion of elements in the function is not allowed.
+template <typename T, typename H, typename E, typename A, typename Function>
+decay_t<Function> c_for_each_fast(const node_hash_set<T, H, E, A>& c,
+ Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+template <typename T, typename H, typename E, typename A, typename Function>
+decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>& c, Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+template <typename T, typename H, typename E, typename A, typename Function>
+decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>&& c, Function&& f) {
+ container_internal::ForEach(f, &c);
+ return f;
+}
+
+} // namespace container_internal
+
+namespace container_internal {
+
+template <class T>
+struct NodeHashSetPolicy
+ : absl::container_internal::node_slot_policy<T&, NodeHashSetPolicy<T>> {
+ using key_type = T;
+ using init_type = T;
+ using constant_iterators = std::true_type;
+
+ template <class Allocator, class... Args>
+ static T* new_element(Allocator* alloc, Args&&... args) {
+ using ValueAlloc =
+ typename absl::allocator_traits<Allocator>::template rebind_alloc<T>;
+ ValueAlloc value_alloc(*alloc);
+ T* res = absl::allocator_traits<ValueAlloc>::allocate(value_alloc, 1);
+ absl::allocator_traits<ValueAlloc>::construct(value_alloc, res,
+ std::forward<Args>(args)...);
+ return res;
+ }
+
+ template <class Allocator>
+ static void delete_element(Allocator* alloc, T* elem) {
+ using ValueAlloc =
+ typename absl::allocator_traits<Allocator>::template rebind_alloc<T>;
+ ValueAlloc value_alloc(*alloc);
+ absl::allocator_traits<ValueAlloc>::destroy(value_alloc, elem);
+ absl::allocator_traits<ValueAlloc>::deallocate(value_alloc, elem, 1);
+ }
+
+ template <class F, class... Args>
+ static decltype(absl::container_internal::DecomposeValue(
+ std::declval<F>(), std::declval<Args>()...))
+ apply(F&& f, Args&&... args) {
+ return absl::container_internal::DecomposeValue(
+ std::forward<F>(f), std::forward<Args>(args)...);
+ }
+
+ static size_t element_space_used(const T*) { return sizeof(T); }
+
+ template <class Hash>
+ static constexpr HashSlotFn get_hash_slot_fn() {
+ return &TypeErasedDerefAndApplyToSlotFn<Hash, T>;
+ }
+};
+} // namespace container_internal
+
+namespace container_algorithm_internal {
+
+// Specialization of trait in absl/algorithm/container.h
+template <class Key, class Hash, class KeyEqual, class Allocator>
+struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>>
+ : std::true_type {};
+
+} // namespace container_algorithm_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_NODE_HASH_SET_H_
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/debugging/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..e4449c2e97
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/debugging/.yandex_meta/licenses.list.txt
@@ -0,0 +1,62 @@
+====================Apache-2.0====================
+ * 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+bool IsAlpha(char c) { return IsLower(c) || IsUpper(c); }
+bool IsIdentifierChar(char c) { return IsAlpha(c) || IsDigit(c) || c == '_'; }
+bool IsLowerHexDigit(char c) { return IsDigit(c) || ('a' <= c && c <= 'f'); }
diff --git a/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h b/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h
new file mode 100644
index 0000000000..f41b64c39d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/debugging/internal/stack_consumption.h
@@ -0,0 +1,50 @@
+//
+// Copyright 2018 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.
+
+// Helper function for measuring stack consumption of signal handlers.
+
+#ifndef ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_
+#define ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_
+
+#include "absl/base/config.h"
+
+// The code in this module is not portable.
+// Use this feature test macro to detect its availability.
+#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
+#error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly
+#elif !defined(__APPLE__) && !defined(_WIN32) && \
+ (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
+ defined(__aarch64__) || defined(__riscv))
+#define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace debugging_internal {
+
+// Returns the stack consumption in bytes for the code exercised by
+// signal_handler. To measure stack consumption, signal_handler is registered
+// as a signal handler, so the code that it exercises must be async-signal
+// safe. The argument of signal_handler is an implementation detail of signal
+// handlers and should ignored by the code for signal_handler. Use global
+// variables to pass information between your test code and signal_handler.
+int GetSignalHandlerStackConsumption(void (*signal_handler)(int));
+
+} // namespace debugging_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
+
+#endif // ABSL_DEBUGGING_INTERNAL_STACK_CONSUMPTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/flags/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/flags/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..690ae5993e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/flags/.yandex_meta/licenses.list.txt
@@ -0,0 +1,24 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/functional/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/functional/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..5e9e839caa
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/functional/.yandex_meta/licenses.list.txt
@@ -0,0 +1,24 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
diff --git a/contrib/restricted/abseil-cpp/absl/functional/bind_front.h b/contrib/restricted/abseil-cpp/absl/functional/bind_front.h
new file mode 100644
index 0000000000..885f24b8f3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/functional/bind_front.h
@@ -0,0 +1,194 @@
+// Copyright 2018 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: bind_front.h
+// -----------------------------------------------------------------------------
+//
+// `absl::bind_front()` returns a functor by binding a number of arguments to
+// the front of a provided (usually more generic) functor. Unlike `std::bind`,
+// it does not require the use of argument placeholders. The simpler syntax of
+// `absl::bind_front()` allows you to avoid known misuses with `std::bind()`.
+//
+// `absl::bind_front()` is meant as a drop-in replacement for C++20's upcoming
+// `std::bind_front()`, which similarly resolves these issues with
+// `std::bind()`. Both `bind_front()` alternatives, unlike `std::bind()`, allow
+// partial function application. (See
+// https://en.wikipedia.org/wiki/Partial_application).
+
+#ifndef ABSL_FUNCTIONAL_BIND_FRONT_H_
+#define ABSL_FUNCTIONAL_BIND_FRONT_H_
+
+#if defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L
+#include <functional> // For std::bind_front.
+#endif // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L
+
+#include <utility>
+
+#include "absl/functional/internal/front_binder.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// bind_front()
+//
+// Binds the first N arguments of an invocable object and stores them by value.
+//
+// Like `std::bind()`, `absl::bind_front()` is implicitly convertible to
+// `std::function`. In particular, it may be used as a simpler replacement for
+// `std::bind()` in most cases, as it does not require placeholders to be
+// specified. More importantly, it provides more reliable correctness guarantees
+// than `std::bind()`; while `std::bind()` will silently ignore passing more
+// parameters than expected, for example, `absl::bind_front()` will report such
+// mis-uses as errors. In C++20, `absl::bind_front` is replaced by
+// `std::bind_front`.
+//
+// absl::bind_front(a...) can be seen as storing the results of
+// std::make_tuple(a...).
+//
+// Example: Binding a free function.
+//
+// int Minus(int a, int b) { return a - b; }
+//
+// assert(absl::bind_front(Minus)(3, 2) == 3 - 2);
+// assert(absl::bind_front(Minus, 3)(2) == 3 - 2);
+// assert(absl::bind_front(Minus, 3, 2)() == 3 - 2);
+//
+// Example: Binding a member function.
+//
+// struct Math {
+// int Double(int a) const { return 2 * a; }
+// };
+//
+// Math math;
+//
+// assert(absl::bind_front(&Math::Double)(&math, 3) == 2 * 3);
+// // Stores a pointer to math inside the functor.
+// assert(absl::bind_front(&Math::Double, &math)(3) == 2 * 3);
+// // Stores a copy of math inside the functor.
+// assert(absl::bind_front(&Math::Double, math)(3) == 2 * 3);
+// // Stores std::unique_ptr<Math> inside the functor.
+// assert(absl::bind_front(&Math::Double,
+// std::unique_ptr<Math>(new Math))(3) == 2 * 3);
+//
+// Example: Using `absl::bind_front()`, instead of `std::bind()`, with
+// `std::function`.
+//
+// class FileReader {
+// public:
+// void ReadFileAsync(const std::string& filename, std::string* content,
+// const std::function<void()>& done) {
+// // Calls Executor::Schedule(std::function<void()>).
+// Executor::DefaultExecutor()->Schedule(
+// absl::bind_front(&FileReader::BlockingRead, this,
+// filename, content, done));
+// }
+//
+// private:
+// void BlockingRead(const std::string& filename, std::string* content,
+// const std::function<void()>& done) {
+// CHECK_OK(file::GetContents(filename, content, {}));
+// done();
+// }
+// };
+//
+// `absl::bind_front()` stores bound arguments explicitly using the type passed
+// rather than implicitly based on the type accepted by its functor.
+//
+// Example: Binding arguments explicitly.
+//
+// void LogStringView(absl::string_view sv) {
+// LOG(INFO) << sv;
+// }
+//
+// Executor* e = Executor::DefaultExecutor();
+// std::string s = "hello";
+// absl::string_view sv = s;
+//
+// // absl::bind_front(LogStringView, arg) makes a copy of arg and stores it.
+// e->Schedule(absl::bind_front(LogStringView, sv)); // ERROR: dangling
+// // string_view.
+//
+// e->Schedule(absl::bind_front(LogStringView, s)); // OK: stores a copy of
+// // s.
+//
+// To store some of the arguments passed to `absl::bind_front()` by reference,
+// use std::ref()` and `std::cref()`.
+//
+// Example: Storing some of the bound arguments by reference.
+//
+// class Service {
+// public:
+// void Serve(const Request& req, std::function<void()>* done) {
+// // The request protocol buffer won't be deleted until done is called.
+// // It's safe to store a reference to it inside the functor.
+// Executor::DefaultExecutor()->Schedule(
+// absl::bind_front(&Service::BlockingServe, this, std::cref(req),
+// done));
+// }
+//
+// private:
+// void BlockingServe(const Request& req, std::function<void()>* done);
+// };
+//
+// Example: Storing bound arguments by reference.
+//
+// void Print(const std::string& a, const std::string& b) {
+// std::cerr << a << b;
+// }
+//
+// std::string hi = "Hello, ";
+// std::vector<std::string> names = {"Chuk", "Gek"};
+// // Doesn't copy hi.
+// for_each(names.begin(), names.end(),
+// absl::bind_front(Print, std::ref(hi)));
+//
+// // DO NOT DO THIS: the functor may outlive "hi", resulting in
+// // dangling references.
+// foo->DoInFuture(absl::bind_front(Print, std::ref(hi), "Guest")); // BAD!
+// auto f = absl::bind_front(Print, std::ref(hi), "Guest"); // BAD!
+//
+// Example: Storing reference-like types.
+//
+// void Print(absl::string_view a, const std::string& b) {
+// std::cerr << a << b;
+// }
+//
+// std::string hi = "Hello, ";
+// // Copies "hi".
+// absl::bind_front(Print, hi)("Chuk");
+//
+// // Compile error: std::reference_wrapper<const string> is not implicitly
+// // convertible to string_view.
+// // absl::bind_front(Print, std::cref(hi))("Chuk");
+//
+// // Doesn't copy "hi".
+// absl::bind_front(Print, absl::string_view(hi))("Chuk");
+//
+#if defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L
+using std::bind_front;
+#else // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L
+template <class F, class... BoundArgs>
+constexpr functional_internal::bind_front_t<F, BoundArgs...> bind_front(
+ F&& func, BoundArgs&&... args) {
+ return functional_internal::bind_front_t<F, BoundArgs...>(
+ absl::in_place, std::forward<F>(func), std::forward<BoundArgs>(args)...);
+}
+#endif // defined(__cpp_lib_bind_front) && __cpp_lib_bind_front >= 201907L
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_BIND_FRONT_H_
diff --git a/contrib/restricted/abseil-cpp/absl/functional/internal/front_binder.h b/contrib/restricted/abseil-cpp/absl/functional/internal/front_binder.h
new file mode 100644
index 0000000000..44a5492897
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/functional/internal/front_binder.h
@@ -0,0 +1,95 @@
+// Copyright 2018 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 details for `absl::bind_front()`.
+
+#ifndef ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
+#define ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
+
+#include <cstddef>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/meta/type_traits.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace functional_internal {
+
+// Invoke the method, expanding the tuple of bound arguments.
+template <class R, class Tuple, size_t... Idx, class... Args>
+R Apply(Tuple&& bound, absl::index_sequence<Idx...>, Args&&... free) {
+ return base_internal::invoke(
+ std::forward<Tuple>(bound).template get<Idx>()...,
+ std::forward<Args>(free)...);
+}
+
+template <class F, class... BoundArgs>
+class FrontBinder {
+ using BoundArgsT = absl::container_internal::CompressedTuple<F, BoundArgs...>;
+ using Idx = absl::make_index_sequence<sizeof...(BoundArgs) + 1>;
+
+ BoundArgsT bound_args_;
+
+ public:
+ template <class... Ts>
+ constexpr explicit FrontBinder(absl::in_place_t, Ts&&... ts)
+ : bound_args_(std::forward<Ts>(ts)...) {}
+
+ template <class... FreeArgs, class R = base_internal::invoke_result_t<
+ F&, BoundArgs&..., FreeArgs&&...>>
+ R operator()(FreeArgs&&... free_args) & {
+ return functional_internal::Apply<R>(bound_args_, Idx(),
+ std::forward<FreeArgs>(free_args)...);
+ }
+
+ template <class... FreeArgs,
+ class R = base_internal::invoke_result_t<
+ const F&, const BoundArgs&..., FreeArgs&&...>>
+ R operator()(FreeArgs&&... free_args) const& {
+ return functional_internal::Apply<R>(bound_args_, Idx(),
+ std::forward<FreeArgs>(free_args)...);
+ }
+
+ template <class... FreeArgs, class R = base_internal::invoke_result_t<
+ F&&, BoundArgs&&..., FreeArgs&&...>>
+ R operator()(FreeArgs&&... free_args) && {
+ // This overload is called when *this is an rvalue. If some of the bound
+ // arguments are stored by value or rvalue reference, we move them.
+ return functional_internal::Apply<R>(std::move(bound_args_), Idx(),
+ std::forward<FreeArgs>(free_args)...);
+ }
+
+ template <class... FreeArgs,
+ class R = base_internal::invoke_result_t<
+ const F&&, const BoundArgs&&..., FreeArgs&&...>>
+ R operator()(FreeArgs&&... free_args) const&& {
+ // This overload is called when *this is an rvalue. If some of the bound
+ // arguments are stored by value or rvalue reference, we move them.
+ return functional_internal::Apply<R>(std::move(bound_args_), Idx(),
+ std::forward<FreeArgs>(free_args)...);
+ }
+};
+
+template <class F, class... BoundArgs>
+using bind_front_t = FrontBinder<decay_t<F>, absl::decay_t<BoundArgs>...>;
+
+} // namespace functional_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_INTERNAL_FRONT_BINDER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/functional/overload.h b/contrib/restricted/abseil-cpp/absl/functional/overload.h
new file mode 100644
index 0000000000..7e19e70503
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/functional/overload.h
@@ -0,0 +1,92 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: overload.h
+// -----------------------------------------------------------------------------
+//
+// `absl::Overload` is a functor that provides overloads based on the functors
+// with which it is created. This can, for example, be used to locally define an
+// anonymous visitor type for `std::visit` inside a function using lambdas.
+//
+// Before using this function, consider whether named function overloads would
+// be a better design.
+//
+// Note: absl::Overload requires C++17.
+//
+// Example:
+//
+// std::variant<std::string, int32_t, int64_t> v(int32_t{1});
+// const size_t result =
+// std::visit(absl::Overload{
+// [](const std::string& s) { return s.size(); },
+// [](const auto& s) { return sizeof(s); },
+// },
+// v);
+// assert(result == 4);
+//
+
+#ifndef ABSL_FUNCTIONAL_OVERLOAD_H_
+#define ABSL_FUNCTIONAL_OVERLOAD_H_
+
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
+ ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
+
+template <typename... T>
+struct Overload final : T... {
+ using T::operator()...;
+
+ // For historical reasons we want to support use that looks like a function
+ // call:
+ //
+ // absl::Overload(lambda_1, lambda_2)
+ //
+ // This works automatically in C++20 because we have support for parenthesized
+ // aggregate initialization. Before then we must provide a constructor that
+ // makes this work.
+ //
+ constexpr explicit Overload(T... ts) : T(std::move(ts))... {}
+};
+
+// Before C++20, which added support for CTAD for aggregate types, we must also
+// teach the compiler how to deduce the template arguments for Overload.
+//
+template <typename... T>
+Overload(T...) -> Overload<T...>;
+
+#else
+
+namespace functional_internal {
+template <typename T>
+constexpr bool kDependentFalse = false;
+}
+
+template <typename Dependent = int, typename... T>
+auto Overload(T&&...) {
+ static_assert(functional_internal::kDependentFalse<Dependent>,
+ "Overload is only usable with C++17 or above.");
+}
+
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_OVERLOAD_H_
diff --git a/contrib/restricted/abseil-cpp/absl/hash/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/hash/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..65ad9be886
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/hash/.yandex_meta/licenses.list.txt
@@ -0,0 +1,38 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2023 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h b/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h
new file mode 100644
index 0000000000..1e1c574149
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/hash/hash_testing.h
@@ -0,0 +1,378 @@
+// Copyright 2018 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_HASH_HASH_TESTING_H_
+#define ABSL_HASH_HASH_TESTING_H_
+
+#include <initializer_list>
+#include <tuple>
+#include <type_traits>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/hash/internal/spy_hash_state.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/str_cat.h"
+#include "absl/types/variant.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Run the absl::Hash algorithm over all the elements passed in and verify that
+// their hash expansion is congruent with their `==` operator.
+//
+// It is used in conjunction with EXPECT_TRUE. Failures will output information
+// on what requirement failed and on which objects.
+//
+// Users should pass a collection of types as either an initializer list or a
+// container of cases.
+//
+// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+// {v1, v2, ..., vN}));
+//
+// std::vector<MyType> cases;
+// // Fill cases...
+// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+//
+// Users can pass a variety of types for testing heterogeneous lookup with
+// `std::make_tuple`:
+//
+// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+// std::make_tuple(v1, v2, ..., vN)));
+//
+//
+// Ideally, the values passed should provide enough coverage of the `==`
+// operator and the AbslHashValue implementations.
+// For dynamically sized types, the empty state should usually be included in
+// the values.
+//
+// The function accepts an optional comparator function, in case that `==` is
+// not enough for the values provided.
+//
+// Usage:
+//
+// EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+// std::make_tuple(v1, v2, ..., vN), MyCustomEq{}));
+//
+// It checks the following requirements:
+// 1. The expansion for a value is deterministic.
+// 2. For any two objects `a` and `b` in the sequence, if `a == b` evaluates
+// to true, then their hash expansion must be equal.
+// 3. If `a == b` evaluates to false their hash expansion must be unequal.
+// 4. If `a == b` evaluates to false neither hash expansion can be a
+// suffix of the other.
+// 5. AbslHashValue overloads should not be called by the user. They are only
+// meant to be called by the framework. Users should call H::combine() and
+// H::combine_contiguous().
+// 6. No moved-from instance of the hash state is used in the implementation
+// of AbslHashValue.
+//
+// The values do not have to have the same type. This can be useful for
+// equivalent types that support heterogeneous lookup.
+//
+// A possible reason for breaking (2) is combining state in the hash expansion
+// that was not used in `==`.
+// For example:
+//
+// struct Bad2 {
+// int a, b;
+// template <typename H>
+// friend H AbslHashValue(H state, Bad2 x) {
+// // Uses a and b.
+// return H::combine(std::move(state), x.a, x.b);
+// }
+// friend bool operator==(Bad2 x, Bad2 y) {
+// // Only uses a.
+// return x.a == y.a;
+// }
+// };
+//
+// As for (3), breaking this usually means that there is state being passed to
+// the `==` operator that is not used in the hash expansion.
+// For example:
+//
+// struct Bad3 {
+// int a, b;
+// template <typename H>
+// friend H AbslHashValue(H state, Bad3 x) {
+// // Only uses a.
+// return H::combine(std::move(state), x.a);
+// }
+// friend bool operator==(Bad3 x, Bad3 y) {
+// // Uses a and b.
+// return x.a == y.a && x.b == y.b;
+// }
+// };
+//
+// Finally, a common way to break 4 is by combining dynamic ranges without
+// combining the size of the range.
+// For example:
+//
+// struct Bad4 {
+// int *p, size;
+// template <typename H>
+// friend H AbslHashValue(H state, Bad4 x) {
+// return H::combine_contiguous(std::move(state), x.p, x.p + x.size);
+// }
+// friend bool operator==(Bad4 x, Bad4 y) {
+// // Compare two ranges for equality. C++14 code can instead use std::equal.
+// return absl::equal(x.p, x.p + x.size, y.p, y.p + y.size);
+// }
+// };
+//
+// An easy solution to this is to combine the size after combining the range,
+// like so:
+// template <typename H>
+// friend H AbslHashValue(H state, Bad4 x) {
+// return H::combine(
+// H::combine_contiguous(std::move(state), x.p, x.p + x.size), x.size);
+// }
+//
+template <int&... ExplicitBarrier, typename Container>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(const Container& values);
+
+template <int&... ExplicitBarrier, typename Container, typename Eq>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals);
+
+template <int&..., typename T>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values);
+
+template <int&..., typename T, typename Eq>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
+ Eq equals);
+
+namespace hash_internal {
+
+struct PrintVisitor {
+ size_t index;
+ template <typename T>
+ std::string operator()(const T* value) const {
+ return absl::StrCat("#", index, "(", testing::PrintToString(*value), ")");
+ }
+};
+
+template <typename Eq>
+struct EqVisitor {
+ Eq eq;
+ template <typename T, typename U>
+ bool operator()(const T* t, const U* u) const {
+ return eq(*t, *u);
+ }
+};
+
+struct ExpandVisitor {
+ template <typename T>
+ SpyHashState operator()(const T* value) const {
+ return SpyHashState::combine(SpyHashState(), *value);
+ }
+};
+
+template <typename Container, typename Eq>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
+ using V = typename Container::value_type;
+
+ struct Info {
+ const V& value;
+ size_t index;
+ std::string ToString() const {
+ return absl::visit(PrintVisitor{index}, value);
+ }
+ SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); }
+ };
+
+ using EqClass = std::vector<Info>;
+ std::vector<EqClass> classes;
+
+ // Gather the values in equivalence classes.
+ size_t i = 0;
+ for (const auto& value : values) {
+ EqClass* c = nullptr;
+ for (auto& eqclass : classes) {
+ if (absl::visit(EqVisitor<Eq>{equals}, value, eqclass[0].value)) {
+ c = &eqclass;
+ break;
+ }
+ }
+ if (c == nullptr) {
+ classes.emplace_back();
+ c = &classes.back();
+ }
+ c->push_back({value, i});
+ ++i;
+
+ // Verify potential errors captured by SpyHashState.
+ if (auto error = c->back().expand().error()) {
+ return testing::AssertionFailure() << *error;
+ }
+ }
+
+ if (classes.size() < 2) {
+ return testing::AssertionFailure()
+ << "At least two equivalence classes are expected.";
+ }
+
+ // We assume that equality is correctly implemented.
+ // Now we verify that AbslHashValue is also correctly implemented.
+
+ for (const auto& c : classes) {
+ // All elements of the equivalence class must have the same hash
+ // expansion.
+ const SpyHashState expected = c[0].expand();
+ for (const Info& v : c) {
+ if (v.expand() != v.expand()) {
+ return testing::AssertionFailure()
+ << "Hash expansion for " << v.ToString()
+ << " is non-deterministic.";
+ }
+ if (v.expand() != expected) {
+ return testing::AssertionFailure()
+ << "Values " << c[0].ToString() << " and " << v.ToString()
+ << " evaluate as equal but have an unequal hash expansion.";
+ }
+ }
+
+ // Elements from other classes must have different hash expansion.
+ for (const auto& c2 : classes) {
+ if (&c == &c2) continue;
+ const SpyHashState c2_hash = c2[0].expand();
+ switch (SpyHashState::Compare(expected, c2_hash)) {
+ case SpyHashState::CompareResult::kEqual:
+ return testing::AssertionFailure()
+ << "Values " << c[0].ToString() << " and " << c2[0].ToString()
+ << " evaluate as unequal but have an equal hash expansion.";
+ case SpyHashState::CompareResult::kBSuffixA:
+ return testing::AssertionFailure()
+ << "Hash expansion of " << c2[0].ToString()
+ << " is a suffix of the hash expansion of " << c[0].ToString()
+ << ".";
+ case SpyHashState::CompareResult::kASuffixB:
+ return testing::AssertionFailure()
+ << "Hash expansion of " << c[0].ToString()
+ << " is a suffix of the hash expansion of " << c2[0].ToString()
+ << ".";
+ case SpyHashState::CompareResult::kUnequal:
+ break;
+ }
+ }
+ }
+ return testing::AssertionSuccess();
+}
+
+template <typename... T>
+struct TypeSet {
+ template <typename U, bool = disjunction<std::is_same<T, U>...>::value>
+ struct Insert {
+ using type = TypeSet<U, T...>;
+ };
+ template <typename U>
+ struct Insert<U, true> {
+ using type = TypeSet;
+ };
+
+ template <template <typename...> class C>
+ using apply = C<T...>;
+};
+
+template <typename... T>
+struct MakeTypeSet : TypeSet<> {};
+template <typename T, typename... Ts>
+struct MakeTypeSet<T, Ts...> : MakeTypeSet<Ts...>::template Insert<T>::type {};
+
+template <typename... T>
+using VariantForTypes = typename MakeTypeSet<
+ const typename std::decay<T>::type*...>::template apply<absl::variant>;
+
+template <typename Container>
+struct ContainerAsVector {
+ using V = absl::variant<const typename Container::value_type*>;
+ using Out = std::vector<V>;
+
+ static Out Do(const Container& values) {
+ Out out;
+ for (const auto& v : values) out.push_back(&v);
+ return out;
+ }
+};
+
+template <typename... T>
+struct ContainerAsVector<std::tuple<T...>> {
+ using V = VariantForTypes<T...>;
+ using Out = std::vector<V>;
+
+ template <size_t... I>
+ static Out DoImpl(const std::tuple<T...>& tuple, absl::index_sequence<I...>) {
+ return Out{&std::get<I>(tuple)...};
+ }
+
+ static Out Do(const std::tuple<T...>& values) {
+ return DoImpl(values, absl::index_sequence_for<T...>());
+ }
+};
+
+template <>
+struct ContainerAsVector<std::tuple<>> {
+ static std::vector<VariantForTypes<int>> Do(std::tuple<>) { return {}; }
+};
+
+struct DefaultEquals {
+ template <typename T, typename U>
+ bool operator()(const T& t, const U& u) const {
+ return t == u;
+ }
+};
+
+} // namespace hash_internal
+
+template <int&..., typename Container>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(const Container& values) {
+ return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
+ hash_internal::ContainerAsVector<Container>::Do(values),
+ hash_internal::DefaultEquals{});
+}
+
+template <int&..., typename Container, typename Eq>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
+ return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
+ hash_internal::ContainerAsVector<Container>::Do(values), equals);
+}
+
+template <int&..., typename T>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values) {
+ return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
+ hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
+ hash_internal::DefaultEquals{});
+}
+
+template <int&..., typename T, typename Eq>
+ABSL_MUST_USE_RESULT testing::AssertionResult
+VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
+ Eq equals) {
+ return hash_internal::VerifyTypeImplementsAbslHashCorrectly(
+ hash_internal::ContainerAsVector<std::initializer_list<T>>::Do(values),
+ equals);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_HASH_HASH_TESTING_H_
diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/hash_test.h b/contrib/restricted/abseil-cpp/absl/hash/internal/hash_test.h
new file mode 100644
index 0000000000..9963dc0b8d
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/hash/internal/hash_test.h
@@ -0,0 +1,87 @@
+// 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.
+
+// Common code shared between absl/hash/hash_test.cc and
+// absl/hash/hash_instantiated_test.cc.
+
+#ifndef ABSL_HASH_INTERNAL_HASH_TEST_H_
+#define ABSL_HASH_INTERNAL_HASH_TEST_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/hash/hash.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_test_internal {
+
+// Utility wrapper of T for the purposes of testing the `AbslHash` type erasure
+// mechanism. `TypeErasedValue<T>` can be constructed with a `T`, and can
+// be compared and hashed. However, all hashing goes through the hashing
+// type-erasure framework.
+template <typename T>
+class TypeErasedValue {
+ public:
+ TypeErasedValue() = default;
+ TypeErasedValue(const TypeErasedValue&) = default;
+ TypeErasedValue(TypeErasedValue&&) = default;
+ explicit TypeErasedValue(const T& n) : n_(n) {}
+
+ template <typename H>
+ friend H AbslHashValue(H hash_state, const TypeErasedValue& v) {
+ v.HashValue(absl::HashState::Create(&hash_state));
+ return hash_state;
+ }
+
+ void HashValue(absl::HashState state) const {
+ absl::HashState::combine(std::move(state), n_);
+ }
+
+ bool operator==(const TypeErasedValue& rhs) const { return n_ == rhs.n_; }
+ bool operator!=(const TypeErasedValue& rhs) const { return !(*this == rhs); }
+
+ private:
+ T n_;
+};
+
+// A TypeErasedValue refinement, for containers. It exposes the wrapped
+// `value_type` and is constructible from an initializer list.
+template <typename T>
+class TypeErasedContainer : public TypeErasedValue<T> {
+ public:
+ using value_type = typename T::value_type;
+ TypeErasedContainer() = default;
+ TypeErasedContainer(const TypeErasedContainer&) = default;
+ TypeErasedContainer(TypeErasedContainer&&) = default;
+ explicit TypeErasedContainer(const T& n) : TypeErasedValue<T>(n) {}
+ TypeErasedContainer(std::initializer_list<value_type> init_list)
+ : TypeErasedContainer(T(init_list.begin(), init_list.end())) {}
+ // one-argument constructor of value type T, to appease older toolchains that
+ // get confused by one-element initializer lists in some contexts
+ explicit TypeErasedContainer(const value_type& v)
+ : TypeErasedContainer(T(&v, &v + 1)) {}
+};
+
+// Helper trait to verify if T is hashable. We use absl::Hash's poison status to
+// detect it.
+template <typename T>
+using is_hashable = std::is_default_constructible<absl::Hash<T>>;
+
+} // namespace hash_test_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_HASH_INTERNAL_HASH_TEST_H_
diff --git a/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h b/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h
new file mode 100644
index 0000000000..357c301c4a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/hash/internal/spy_hash_state.h
@@ -0,0 +1,266 @@
+// Copyright 2018 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_HASH_INTERNAL_SPY_HASH_STATE_H_
+#define ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_
+
+#include <algorithm>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "absl/hash/hash.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+// SpyHashState is an implementation of the HashState API that simply
+// accumulates all input bytes in an internal buffer. This makes it useful
+// for testing AbslHashValue overloads (so long as they are templated on the
+// HashState parameter), since it can report the exact hash representation
+// that the AbslHashValue overload produces.
+//
+// Sample usage:
+// EXPECT_EQ(SpyHashState::combine(SpyHashState(), foo),
+// SpyHashState::combine(SpyHashState(), bar));
+template <typename T>
+class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
+ public:
+ SpyHashStateImpl() : error_(std::make_shared<absl::optional<std::string>>()) {
+ static_assert(std::is_void<T>::value, "");
+ }
+
+ // Move-only
+ SpyHashStateImpl(const SpyHashStateImpl&) = delete;
+ SpyHashStateImpl& operator=(const SpyHashStateImpl&) = delete;
+
+ SpyHashStateImpl(SpyHashStateImpl&& other) noexcept {
+ *this = std::move(other);
+ }
+
+ SpyHashStateImpl& operator=(SpyHashStateImpl&& other) noexcept {
+ hash_representation_ = std::move(other.hash_representation_);
+ error_ = other.error_;
+ moved_from_ = other.moved_from_;
+ other.moved_from_ = true;
+ return *this;
+ }
+
+ template <typename U>
+ SpyHashStateImpl(SpyHashStateImpl<U>&& other) { // NOLINT
+ hash_representation_ = std::move(other.hash_representation_);
+ error_ = other.error_;
+ moved_from_ = other.moved_from_;
+ other.moved_from_ = true;
+ }
+
+ template <typename A, typename... Args>
+ static SpyHashStateImpl combine(SpyHashStateImpl s, const A& a,
+ const Args&... args) {
+ // Pass an instance of SpyHashStateImpl<A> when trying to combine `A`. This
+ // allows us to test that the user only uses this instance for combine calls
+ // and does not call AbslHashValue directly.
+ // See AbslHashValue implementation at the bottom.
+ s = SpyHashStateImpl<A>::HashStateBase::combine(std::move(s), a);
+ return SpyHashStateImpl::combine(std::move(s), args...);
+ }
+ static SpyHashStateImpl combine(SpyHashStateImpl s) {
+ if (direct_absl_hash_value_error_) {
+ *s.error_ = "AbslHashValue should not be invoked directly.";
+ } else if (s.moved_from_) {
+ *s.error_ = "Used moved-from instance of the hash state object.";
+ }
+ return s;
+ }
+
+ static void SetDirectAbslHashValueError() {
+ direct_absl_hash_value_error_ = true;
+ }
+
+ // Two SpyHashStateImpl objects are equal if they hold equal hash
+ // representations.
+ friend bool operator==(const SpyHashStateImpl& lhs,
+ const SpyHashStateImpl& rhs) {
+ return lhs.hash_representation_ == rhs.hash_representation_;
+ }
+
+ friend bool operator!=(const SpyHashStateImpl& lhs,
+ const SpyHashStateImpl& rhs) {
+ return !(lhs == rhs);
+ }
+
+ enum class CompareResult {
+ kEqual,
+ kASuffixB,
+ kBSuffixA,
+ kUnequal,
+ };
+
+ static CompareResult Compare(const SpyHashStateImpl& a,
+ const SpyHashStateImpl& b) {
+ const std::string a_flat = absl::StrJoin(a.hash_representation_, "");
+ const std::string b_flat = absl::StrJoin(b.hash_representation_, "");
+ if (a_flat == b_flat) return CompareResult::kEqual;
+ if (absl::EndsWith(a_flat, b_flat)) return CompareResult::kBSuffixA;
+ if (absl::EndsWith(b_flat, a_flat)) return CompareResult::kASuffixB;
+ return CompareResult::kUnequal;
+ }
+
+ // operator<< prints the hash representation as a hex and ASCII dump, to
+ // facilitate debugging.
+ friend std::ostream& operator<<(std::ostream& out,
+ const SpyHashStateImpl& hash_state) {
+ out << "[\n";
+ for (auto& s : hash_state.hash_representation_) {
+ size_t offset = 0;
+ for (char c : s) {
+ if (offset % 16 == 0) {
+ out << absl::StreamFormat("\n0x%04x: ", offset);
+ }
+ if (offset % 2 == 0) {
+ out << " ";
+ }
+ out << absl::StreamFormat("%02x", c);
+ ++offset;
+ }
+ out << "\n";
+ }
+ return out << "]";
+ }
+
+ // The base case of the combine recursion, which writes raw bytes into the
+ // internal buffer.
+ static SpyHashStateImpl combine_contiguous(SpyHashStateImpl hash_state,
+ const unsigned char* begin,
+ size_t size) {
+ const size_t large_chunk_stride = PiecewiseChunkSize();
+ // Combining a large contiguous buffer must have the same effect as
+ // doing it piecewise by the stride length, followed by the (possibly
+ // empty) remainder.
+ while (size > large_chunk_stride) {
+ hash_state = SpyHashStateImpl::combine_contiguous(
+ std::move(hash_state), begin, large_chunk_stride);
+ begin += large_chunk_stride;
+ size -= large_chunk_stride;
+ }
+
+ if (size > 0) {
+ hash_state.hash_representation_.emplace_back(
+ reinterpret_cast<const char*>(begin), size);
+ }
+ return hash_state;
+ }
+
+ using SpyHashStateImpl::HashStateBase::combine_contiguous;
+
+ template <typename CombinerT>
+ static SpyHashStateImpl RunCombineUnordered(SpyHashStateImpl state,
+ CombinerT combiner) {
+ UnorderedCombinerCallback cb;
+
+ combiner(SpyHashStateImpl<void>{}, std::ref(cb));
+
+ std::sort(cb.element_hash_representations.begin(),
+ cb.element_hash_representations.end());
+ state.hash_representation_.insert(state.hash_representation_.end(),
+ cb.element_hash_representations.begin(),
+ cb.element_hash_representations.end());
+ if (cb.error && cb.error->has_value()) {
+ state.error_ = std::move(cb.error);
+ }
+ return state;
+ }
+
+ absl::optional<std::string> error() const {
+ if (moved_from_) {
+ return "Returned a moved-from instance of the hash state object.";
+ }
+ return *error_;
+ }
+
+ private:
+ template <typename U>
+ friend class SpyHashStateImpl;
+
+ struct UnorderedCombinerCallback {
+ std::vector<std::string> element_hash_representations;
+ std::shared_ptr<absl::optional<std::string>> error;
+
+ // The inner spy can have a different type.
+ template <typename U>
+ void operator()(SpyHashStateImpl<U>& inner) {
+ element_hash_representations.push_back(
+ absl::StrJoin(inner.hash_representation_, ""));
+ if (inner.error_->has_value()) {
+ error = std::move(inner.error_);
+ }
+ inner = SpyHashStateImpl<void>{};
+ }
+ };
+
+ // This is true if SpyHashStateImpl<T> has been passed to a call of
+ // AbslHashValue with the wrong type. This detects that the user called
+ // AbslHashValue directly (because the hash state type does not match).
+ static bool direct_absl_hash_value_error_;
+
+ std::vector<std::string> hash_representation_;
+ // This is a shared_ptr because we want all instances of the particular
+ // SpyHashState run to share the field. This way we can set the error for
+ // use-after-move and all the copies will see it.
+ std::shared_ptr<absl::optional<std::string>> error_;
+ bool moved_from_ = false;
+};
+
+template <typename T>
+bool SpyHashStateImpl<T>::direct_absl_hash_value_error_;
+
+template <bool& B>
+struct OdrUse {
+ constexpr OdrUse() {}
+ bool& b = B;
+};
+
+template <void (*)()>
+struct RunOnStartup {
+ static bool run;
+ static constexpr OdrUse<run> kOdrUse{};
+};
+
+template <void (*f)()>
+bool RunOnStartup<f>::run = (f(), true);
+
+template <
+ typename T, typename U,
+ // Only trigger for when (T != U),
+ typename = absl::enable_if_t<!std::is_same<T, U>::value>,
+ // This statement works in two ways:
+ // - First, it instantiates RunOnStartup and forces the initialization of
+ // `run`, which set the global variable.
+ // - Second, it triggers a SFINAE error disabling the overload to prevent
+ // compile time errors. If we didn't disable the overload we would get
+ // ambiguous overload errors, which we don't want.
+ int = RunOnStartup<SpyHashStateImpl<T>::SetDirectAbslHashValueError>::run>
+void AbslHashValue(SpyHashStateImpl<T>, const U&);
+
+using SpyHashState = SpyHashStateImpl<void>;
+
+} // namespace hash_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_HASH_INTERNAL_SPY_HASH_STATE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/log/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..c9ebdec01c
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/.yandex_meta/licenses.list.txt
@@ -0,0 +1,38 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
+
+
+====================COPYRIGHT====================
+// Copyright 2023 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/log/check.h b/contrib/restricted/abseil-cpp/absl/log/check.h
new file mode 100644
index 0000000000..50f633ddf6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/check.h
@@ -0,0 +1,209 @@
+// 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/check.h
+// -----------------------------------------------------------------------------
+//
+// This header declares a family of `CHECK` macros.
+//
+// `CHECK` macros terminate the program with a fatal error if the specified
+// condition is not true.
+//
+// Except for those whose names begin with `DCHECK`, these macros are not
+// controlled by `NDEBUG` (cf. `assert`), so the check will be executed
+// regardless of compilation mode. `CHECK` and friends are thus useful for
+// confirming invariants in situations where continuing to run would be worse
+// than terminating, e.g., due to risk of data corruption or security
+// compromise. It is also more robust and portable to deliberately terminate
+// at a particular place with a useful message and backtrace than to assume some
+// ultimately unspecified and unreliable crashing behavior (such as a
+// "segmentation fault").
+
+#ifndef ABSL_LOG_CHECK_H_
+#define ABSL_LOG_CHECK_H_
+
+#include "absl/log/internal/check_impl.h"
+#include "absl/log/internal/check_op.h" // IWYU pragma: export
+#include "absl/log/internal/conditions.h" // IWYU pragma: export
+#include "absl/log/internal/log_message.h" // IWYU pragma: export
+#include "absl/log/internal/strip.h" // IWYU pragma: export
+
+// CHECK()
+//
+// `CHECK` terminates the program with a fatal error if `condition` is not true.
+//
+// The message may include additional information such as stack traces, when
+// available.
+//
+// Example:
+//
+// CHECK(!cheese.empty()) << "Out of Cheese";
+//
+// Might produce a message like:
+//
+// Check failed: !cheese.empty() Out of Cheese
+#define CHECK(condition) ABSL_LOG_INTERNAL_CHECK_IMPL((condition), #condition)
+
+// QCHECK()
+//
+// `QCHECK` behaves like `CHECK` but does not print a full stack trace and does
+// not run registered error handlers (as `QFATAL`). It is useful when the
+// problem is definitely unrelated to program flow, e.g. when validating user
+// input.
+#define QCHECK(condition) ABSL_LOG_INTERNAL_QCHECK_IMPL((condition), #condition)
+
+// PCHECK()
+//
+// `PCHECK` behaves like `CHECK` but appends a description of the current state
+// of `errno` to the failure message.
+//
+// Example:
+//
+// int fd = open("/var/empty/missing", O_RDONLY);
+// PCHECK(fd != -1) << "posix is difficult";
+//
+// Might produce a message like:
+//
+// Check failed: fd != -1 posix is difficult: No such file or directory [2]
+#define PCHECK(condition) ABSL_LOG_INTERNAL_PCHECK_IMPL((condition), #condition)
+
+// DCHECK()
+//
+// `DCHECK` behaves like `CHECK` in debug mode and does nothing otherwise (as
+// `DLOG`). Unlike with `CHECK` (but as with `assert`), it is not safe to rely
+// on evaluation of `condition`: when `NDEBUG` is enabled, DCHECK does not
+// evaluate the condition.
+#define DCHECK(condition) ABSL_LOG_INTERNAL_DCHECK_IMPL((condition), #condition)
+
+// `CHECK_EQ` and friends are syntactic sugar for `CHECK(x == y)` that
+// automatically output the expression being tested and the evaluated values on
+// either side.
+//
+// Example:
+//
+// int x = 3, y = 5;
+// CHECK_EQ(2 * x, y) << "oops!";
+//
+// Might produce a message like:
+//
+// Check failed: 2 * x == y (6 vs. 5) oops!
+//
+// The values must implement the appropriate comparison operator as well as
+// `operator<<(std::ostream&, ...)`. Care is taken to ensure that each
+// argument is evaluated exactly once, and that anything which is legal to pass
+// as a function argument is legal here. In particular, the arguments may be
+// temporary expressions which will end up being destroyed at the end of the
+// statement,
+//
+// Example:
+//
+// CHECK_EQ(std::string("abc")[1], 'b');
+//
+// WARNING: Passing `NULL` as an argument to `CHECK_EQ` and similar macros does
+// not compile. Use `nullptr` instead.
+#define CHECK_EQ(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_EQ_IMPL((val1), #val1, (val2), #val2)
+#define CHECK_NE(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_NE_IMPL((val1), #val1, (val2), #val2)
+#define CHECK_LE(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_LE_IMPL((val1), #val1, (val2), #val2)
+#define CHECK_LT(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_LT_IMPL((val1), #val1, (val2), #val2)
+#define CHECK_GE(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_GE_IMPL((val1), #val1, (val2), #val2)
+#define CHECK_GT(val1, val2) \
+ ABSL_LOG_INTERNAL_CHECK_GT_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_EQ(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_EQ_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_NE(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_NE_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_LE(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_LE_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_LT(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_LT_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_GE(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_GE_IMPL((val1), #val1, (val2), #val2)
+#define QCHECK_GT(val1, val2) \
+ ABSL_LOG_INTERNAL_QCHECK_GT_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_EQ(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_EQ_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_NE(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_NE_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_LE(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_LE_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_LT(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_LT_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_GE(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_GE_IMPL((val1), #val1, (val2), #val2)
+#define DCHECK_GT(val1, val2) \
+ ABSL_LOG_INTERNAL_DCHECK_GT_IMPL((val1), #val1, (val2), #val2)
+
+// `CHECK_OK` and friends validate that the provided `absl::Status` or
+// `absl::StatusOr<T>` is OK. If it isn't, they print a failure message that
+// includes the actual status and terminate the program.
+//
+// As with all `DCHECK` variants, `DCHECK_OK` has no effect (not even
+// evaluating its argument) if `NDEBUG` is enabled.
+//
+// Example:
+//
+// CHECK_OK(FunctionReturnsStatus(x, y, z)) << "oops!";
+//
+// Might produce a message like:
+//
+// Check failed: FunctionReturnsStatus(x, y, z) is OK (ABORTED: timeout) oops!
+#define CHECK_OK(status) ABSL_LOG_INTERNAL_CHECK_OK_IMPL((status), #status)
+#define QCHECK_OK(status) ABSL_LOG_INTERNAL_QCHECK_OK_IMPL((status), #status)
+#define DCHECK_OK(status) ABSL_LOG_INTERNAL_DCHECK_OK_IMPL((status), #status)
+
+// `CHECK_STREQ` and friends provide `CHECK_EQ` functionality for C strings,
+// i.e., null-terminated char arrays. The `CASE` versions are case-insensitive.
+//
+// Example:
+//
+// CHECK_STREQ(argv[0], "./skynet");
+//
+// Note that both arguments may be temporary strings which are destroyed by the
+// compiler at the end of the current full expression.
+//
+// Example:
+//
+// CHECK_STREQ(Foo().c_str(), Bar().c_str());
+#define CHECK_STREQ(s1, s2) \
+ ABSL_LOG_INTERNAL_CHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
+#define CHECK_STRNE(s1, s2) \
+ ABSL_LOG_INTERNAL_CHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
+#define CHECK_STRCASEEQ(s1, s2) \
+ ABSL_LOG_INTERNAL_CHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
+#define CHECK_STRCASENE(s1, s2) \
+ ABSL_LOG_INTERNAL_CHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
+#define QCHECK_STREQ(s1, s2) \
+ ABSL_LOG_INTERNAL_QCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
+#define QCHECK_STRNE(s1, s2) \
+ ABSL_LOG_INTERNAL_QCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
+#define QCHECK_STRCASEEQ(s1, s2) \
+ ABSL_LOG_INTERNAL_QCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
+#define QCHECK_STRCASENE(s1, s2) \
+ ABSL_LOG_INTERNAL_QCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
+#define DCHECK_STREQ(s1, s2) \
+ ABSL_LOG_INTERNAL_DCHECK_STREQ_IMPL((s1), #s1, (s2), #s2)
+#define DCHECK_STRNE(s1, s2) \
+ ABSL_LOG_INTERNAL_DCHECK_STRNE_IMPL((s1), #s1, (s2), #s2)
+#define DCHECK_STRCASEEQ(s1, s2) \
+ ABSL_LOG_INTERNAL_DCHECK_STRCASEEQ_IMPL((s1), #s1, (s2), #s2)
+#define DCHECK_STRCASENE(s1, s2) \
+ ABSL_LOG_INTERNAL_DCHECK_STRCASENE_IMPL((s1), #s1, (s2), #s2)
+
+#endif // ABSL_LOG_CHECK_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/flags.h b/contrib/restricted/abseil-cpp/absl/log/flags.h
new file mode 100644
index 0000000000..146cfdd6ca
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/flags.h
@@ -0,0 +1,43 @@
+// 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/flags.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_LOG_FLAGS_H_
+#define ABSL_LOG_FLAGS_H_
+
+// The Abseil Logging library supports the following command line flags to
+// configure logging behavior at runtime:
+//
+// --stderrthreshold=<value>
+// Log messages at or above this threshold level are copied to stderr.
+//
+// --minloglevel=<value>
+// Messages logged at a lower level than this are discarded and don't actually
+// get logged anywhere.
+//
+// --log_backtrace_at=<file:linenum>
+// Emit a backtrace (stack trace) when logging at file:linenum.
+//
+// To use these commandline flags, the //absl/log:flags library must be
+// explicitly linked, and absl::ParseCommandLine() must be called before the
+// call to absl::InitializeLog().
+//
+// To configure the Log library programmatically, use the interfaces defined in
+// absl/log/globals.h.
+
+#endif // ABSL_LOG_FLAGS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/structured.h b/contrib/restricted/abseil-cpp/absl/log/internal/structured.h
new file mode 100644
index 0000000000..5223dbc310
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/structured.h
@@ -0,0 +1,58 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/structured.h
+// -----------------------------------------------------------------------------
+
+#ifndef ABSL_LOG_INTERNAL_STRUCTURED_H_
+#define ABSL_LOG_INTERNAL_STRUCTURED_H_
+
+#include <ostream>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/log_message.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+class ABSL_MUST_USE_RESULT AsLiteralImpl final {
+ public:
+ explicit AsLiteralImpl(absl::string_view str) : str_(str) {}
+ AsLiteralImpl(const AsLiteralImpl&) = default;
+ AsLiteralImpl& operator=(const AsLiteralImpl&) = default;
+
+ private:
+ absl::string_view str_;
+
+ friend std::ostream& operator<<(std::ostream& os, AsLiteralImpl as_literal) {
+ return os << as_literal.str_;
+ }
+ void AddToMessage(log_internal::LogMessage& m) {
+ m.CopyToEncodedBuffer<log_internal::LogMessage::StringType::kLiteral>(str_);
+ }
+ friend log_internal::LogMessage& operator<<(log_internal::LogMessage& m,
+ AsLiteralImpl as_literal) {
+ as_literal.AddToMessage(m);
+ return m;
+ }
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_STRUCTURED_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/test_actions.h b/contrib/restricted/abseil-cpp/absl/log/internal/test_actions.h
new file mode 100644
index 0000000000..649a050521
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/test_actions.h
@@ -0,0 +1,90 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_actions.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's actions used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+#define ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
+
+#include <iostream>
+#include <ostream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// These actions are used by the child process in a death test.
+//
+// Expectations set in the child cannot cause test failure in the parent
+// directly. Instead, the child can use these actions with
+// `EXPECT_CALL`/`WillOnce` and `ON_CALL`/`WillByDefault` (for unexpected calls)
+// to write messages to stderr that the parent can match against.
+struct WriteToStderr final {
+ explicit WriteToStderr(absl::string_view m) : message(m) {}
+ std::string message;
+
+ template <typename... Args>
+ void operator()(const Args&...) const {
+ std::cerr << message << std::endl;
+ }
+};
+
+struct WriteToStderrWithFilename final {
+ explicit WriteToStderrWithFilename(absl::string_view m) : message(m) {}
+
+ std::string message;
+
+ void operator()(const absl::LogEntry& entry) const;
+};
+
+struct WriteEntryToStderr final {
+ explicit WriteEntryToStderr(absl::string_view m) : message(m) {}
+
+ std::string message = "";
+
+ void operator()(const absl::LogEntry& entry) const;
+ void operator()(absl::LogSeverity, absl::string_view,
+ absl::string_view) const;
+};
+
+// See the documentation for `DeathTestValidateExpectations` above.
+// `DeathTestExpectedLogging` should be used once in a given death test, and the
+// applicable severity level is the one that should be passed to
+// `DeathTestValidateExpectations`.
+inline WriteEntryToStderr DeathTestExpectedLogging() {
+ return WriteEntryToStderr{"Mock received expected entry:"};
+}
+
+// `DeathTestUnexpectedLogging` should be used zero or more times to mark
+// messages that should not hit the logs as the process dies.
+inline WriteEntryToStderr DeathTestUnexpectedLogging() {
+ return WriteEntryToStderr{"Mock received unexpected entry:"};
+}
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_ACTIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/test_helpers.h b/contrib/restricted/abseil-cpp/absl/log/internal/test_helpers.h
new file mode 100644
index 0000000000..714bc7bddc
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/test_helpers.h
@@ -0,0 +1,71 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_helpers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares testing helpers for the logging library.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+#define ABSL_LOG_INTERNAL_TEST_HELPERS_H_
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/globals.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+
+// `ABSL_MIN_LOG_LEVEL` can't be used directly since it is not always defined.
+constexpr auto kAbslMinLogLevel =
+#ifdef ABSL_MIN_LOG_LEVEL
+ static_cast<absl::LogSeverityAtLeast>(ABSL_MIN_LOG_LEVEL);
+#else
+ absl::LogSeverityAtLeast::kInfo;
+#endif
+
+// Returns false if the specified severity level is disabled by
+// `ABSL_MIN_LOG_LEVEL` or `absl::MinLogLevel()`.
+bool LoggingEnabledAt(absl::LogSeverity severity);
+
+// -----------------------------------------------------------------------------
+// Googletest Death Test Predicates
+// -----------------------------------------------------------------------------
+
+#if GTEST_HAS_DEATH_TEST
+
+bool DiedOfFatal(int exit_status);
+bool DiedOfQFatal(int exit_status);
+
+#endif
+
+// -----------------------------------------------------------------------------
+// Helper for Log initialization in test
+// -----------------------------------------------------------------------------
+
+class LogTestEnvironment : public ::testing::Environment {
+ public:
+ ~LogTestEnvironment() override = default;
+
+ void SetUp() override;
+};
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_HELPERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/internal/test_matchers.h b/contrib/restricted/abseil-cpp/absl/log/internal/test_matchers.h
new file mode 100644
index 0000000000..906eda2408
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/internal/test_matchers.h
@@ -0,0 +1,94 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/internal/test_matchers.h
+// -----------------------------------------------------------------------------
+//
+// This file declares Googletest's matchers used in the Abseil Logging library
+// unit tests.
+
+#ifndef ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+#define ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
+
+#include <iosfwd>
+#include <sstream>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/internal/test_helpers.h"
+#include "absl/log/log_entry.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace log_internal {
+// In some configurations, Googletest's string matchers (e.g.
+// `::testing::EndsWith`) need help to match `absl::string_view`.
+::testing::Matcher<absl::string_view> AsString(
+ const ::testing::Matcher<const std::string&>& str_matcher);
+
+// These matchers correspond to the components of `absl::LogEntry`.
+::testing::Matcher<const absl::LogEntry&> SourceFilename(
+ const ::testing::Matcher<absl::string_view>& source_filename);
+::testing::Matcher<const absl::LogEntry&> SourceBasename(
+ const ::testing::Matcher<absl::string_view>& source_basename);
+// Be careful with this one; multi-line statements using `__LINE__` evaluate
+// differently on different platforms. In particular, the MSVC implementation
+// of `EXPECT_DEATH` returns the line number of the macro expansion to all lines
+// within the code block that's expected to die.
+::testing::Matcher<const absl::LogEntry&> SourceLine(
+ const ::testing::Matcher<int>& source_line);
+::testing::Matcher<const absl::LogEntry&> Prefix(
+ const ::testing::Matcher<bool>& prefix);
+::testing::Matcher<const absl::LogEntry&> LogSeverity(
+ const ::testing::Matcher<absl::LogSeverity>& log_severity);
+::testing::Matcher<const absl::LogEntry&> Timestamp(
+ const ::testing::Matcher<absl::Time>& timestamp);
+// Matches if the `LogEntry`'s timestamp falls after the instantiation of this
+// matcher and before its execution, as is normal when used with EXPECT_CALL.
+::testing::Matcher<absl::Time> InMatchWindow();
+::testing::Matcher<const absl::LogEntry&> ThreadID(
+ const ::testing::Matcher<absl::LogEntry::tid_t>&);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefixAndNewline(
+ const ::testing::Matcher<absl::string_view>&
+ text_message_with_prefix_and_newline);
+::testing::Matcher<const absl::LogEntry&> TextMessageWithPrefix(
+ const ::testing::Matcher<absl::string_view>& text_message_with_prefix);
+::testing::Matcher<const absl::LogEntry&> TextMessage(
+ const ::testing::Matcher<absl::string_view>& text_message);
+::testing::Matcher<const absl::LogEntry&> TextPrefix(
+ const ::testing::Matcher<absl::string_view>& text_prefix);
+::testing::Matcher<const absl::LogEntry&> Verbosity(
+ const ::testing::Matcher<int>& verbosity);
+::testing::Matcher<const absl::LogEntry&> Stacktrace(
+ const ::testing::Matcher<absl::string_view>& stacktrace);
+// Behaves as `Eq(stream.str())`, but produces better failure messages.
+::testing::Matcher<absl::string_view> MatchesOstream(
+ const std::ostringstream& stream);
+::testing::Matcher<const std::string&> DeathTestValidateExpectations();
+
+::testing::Matcher<const absl::LogEntry&> RawEncodedMessage(
+ const ::testing::Matcher<absl::string_view>& raw_encoded_message);
+#define ENCODED_MESSAGE(message_matcher) ::testing::_
+
+} // namespace log_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_INTERNAL_TEST_MATCHERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/log_streamer.h b/contrib/restricted/abseil-cpp/absl/log/log_streamer.h
new file mode 100644
index 0000000000..4ed2435d61
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/log_streamer.h
@@ -0,0 +1,181 @@
+// 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_streamer.h
+// -----------------------------------------------------------------------------
+//
+// This header declares the class `LogStreamer` and convenience functions to
+// construct LogStreamer objects with different associated log severity levels.
+
+#ifndef ABSL_LOG_LOG_STREAMER_H_
+#define ABSL_LOG_LOG_STREAMER_H_
+
+#include <ios>
+#include <memory>
+#include <ostream>
+#include <string>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/absl_log.h"
+#include "absl/strings/internal/ostringstream.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// LogStreamer
+//
+// Although you can stream into `LOG(INFO)`, you can't pass it into a function
+// that takes a `std::ostream` parameter. `LogStreamer::stream()` provides a
+// `std::ostream` that buffers everything that's streamed in. The buffer's
+// contents are logged as if by `LOG` when the `LogStreamer` is destroyed.
+// If nothing is streamed in, an empty message is logged. If the specified
+// severity is `absl::LogSeverity::kFatal`, the program will be terminated when
+// the `LogStreamer` is destroyed regardless of whether any data were streamed
+// in.
+//
+// Factory functions corresponding to the `absl::LogSeverity` enumerators
+// are provided for convenience; if the desired severity is variable, invoke the
+// constructor directly.
+//
+// LogStreamer is movable, but not copyable.
+//
+// Examples:
+//
+// ShaveYakAndWriteToStream(
+// yak, absl::LogInfoStreamer(__FILE__, __LINE__).stream());
+//
+// {
+// // This logs a single line containing data streamed by all three function
+// // calls.
+// absl::LogStreamer streamer(absl::LogSeverity::kInfo, __FILE__, __LINE__);
+// ShaveYakAndWriteToStream(yak1, streamer.stream());
+// streamer.stream() << " ";
+// ShaveYakAndWriteToStream(yak2, streamer.stream());
+// streamer.stream() << " ";
+// ShaveYakAndWriteToStreamPointer(yak3, &streamer.stream());
+// }
+class LogStreamer final {
+ public:
+ // LogStreamer::LogStreamer()
+ //
+ // Creates a LogStreamer with a given `severity` that will log a message
+ // attributed to the given `file` and `line`.
+ explicit LogStreamer(absl::LogSeverity severity, absl::string_view file,
+ int line)
+ : severity_(severity),
+ line_(line),
+ file_(file),
+ stream_(absl::in_place, &buf_) {
+ // To match `LOG`'s defaults:
+ stream_->setf(std::ios_base::showbase | std::ios_base::boolalpha);
+ }
+
+ // A moved-from `absl::LogStreamer` does not `LOG` when destroyed,
+ // and a program that streams into one has undefined behavior.
+ LogStreamer(LogStreamer&& that) noexcept
+ : severity_(that.severity_),
+ line_(that.line_),
+ file_(std::move(that.file_)),
+ buf_(std::move(that.buf_)),
+ stream_(std::move(that.stream_)) {
+ if (stream_.has_value()) stream_->str(&buf_);
+ that.stream_.reset();
+ }
+ LogStreamer& operator=(LogStreamer&& that) {
+ ABSL_LOG_IF(LEVEL(severity_), stream_).AtLocation(file_, line_) << buf_;
+ severity_ = that.severity_;
+ file_ = std::move(that.file_);
+ line_ = that.line_;
+ buf_ = std::move(that.buf_);
+ stream_ = std::move(that.stream_);
+ if (stream_.has_value()) stream_->str(&buf_);
+ that.stream_.reset();
+ return *this;
+ }
+
+ // LogStreamer::~LogStreamer()
+ //
+ // Logs this LogStreamer's buffered content as if by LOG.
+ ~LogStreamer() {
+ ABSL_LOG_IF(LEVEL(severity_), stream_.has_value()).AtLocation(file_, line_)
+ << buf_;
+ }
+
+ // LogStreamer::stream()
+ //
+ // Returns the `std::ostream` to use to write into this LogStreamer' internal
+ // buffer.
+ std::ostream& stream() { return *stream_; }
+
+ private:
+ absl::LogSeverity severity_;
+ int line_;
+ std::string file_;
+ std::string buf_;
+ // A disengaged `stream_` indicates a moved-from `LogStreamer` that should not
+ // `LOG` upon destruction.
+ absl::optional<absl::strings_internal::OStringStream> stream_;
+};
+
+// LogInfoStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kInfo.
+inline LogStreamer LogInfoStreamer(absl::string_view file, int line) {
+ return absl::LogStreamer(absl::LogSeverity::kInfo, file, line);
+}
+
+// LogWarningStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kWarning.
+inline LogStreamer LogWarningStreamer(absl::string_view file, int line) {
+ return absl::LogStreamer(absl::LogSeverity::kWarning, file, line);
+}
+
+// LogErrorStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kError.
+inline LogStreamer LogErrorStreamer(absl::string_view file, int line) {
+ return absl::LogStreamer(absl::LogSeverity::kError, file, line);
+}
+
+// LogFatalStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kFatal.
+//
+// The program will be terminated when this `LogStreamer` is destroyed,
+// regardless of whether any data were streamed in.
+inline LogStreamer LogFatalStreamer(absl::string_view file, int line) {
+ return absl::LogStreamer(absl::LogSeverity::kFatal, file, line);
+}
+
+// LogDebugFatalStreamer()
+//
+// Returns a LogStreamer that writes at level LogSeverity::kLogDebugFatal.
+//
+// In debug mode, the program will be terminated when this `LogStreamer` is
+// destroyed, regardless of whether any data were streamed in.
+inline LogStreamer LogDebugFatalStreamer(absl::string_view file, int line) {
+ return absl::LogStreamer(absl::kLogDebugFatal, file, line);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_LOG_STREAMER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h b/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h
new file mode 100644
index 0000000000..399e604deb
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/scoped_mock_log.h
@@ -0,0 +1,197 @@
+// 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/scoped_mock_log.h
+// -----------------------------------------------------------------------------
+//
+// This header declares `class absl::ScopedMockLog`, for use in testing.
+
+#ifndef ABSL_LOG_SCOPED_MOCK_LOG_H_
+#define ABSL_LOG_SCOPED_MOCK_LOG_H_
+
+#include <atomic>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/log/log_entry.h"
+#include "absl/log/log_sink.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// MockLogDefault
+//
+// Controls how ScopedMockLog responds to unexpected calls by default.
+enum class MockLogDefault { kIgnoreUnexpected, kDisallowUnexpected };
+
+// ScopedMockLog
+//
+// ScopedMockLog is a LogSink that intercepts LOG() messages issued during its
+// lifespan.
+//
+// Using this together with GoogleTest, it's easy to test how a piece of code
+// calls LOG(). The typical usage, noting the distinction between
+// "uninteresting" and "unexpected", looks like this:
+//
+// using ::testing::_;
+// using ::testing::AnyNumber;
+// using ::testing::EndsWith;
+// using ::testing::kDoNotCaptureLogsYet;
+// using ::testing::Lt;
+//
+// TEST(FooTest, LogsCorrectly) {
+// // Simple robust setup, ignores unexpected logs.
+// absl::ScopedMockLog log;
+//
+// // We expect the WARNING "Something bad!" exactly twice.
+// EXPECT_CALL(log, Log(absl::LogSeverity::kWarning, _, "Something bad!"))
+// .Times(2);
+//
+// // But we want no messages from foo.cc.
+// EXPECT_CALL(log, Log(_, EndsWith("/foo.cc"), _)).Times(0);
+//
+// log.StartCapturingLogs(); // Call this after done setting expectations.
+// Foo(); // Exercises the code under test.
+// }
+//
+// TEST(BarTest, LogsExactlyCorrectly) {
+// // Strict checking, fails for unexpected logs.
+// absl::ScopedMockLog log(absl::MockLogDefault::kDisallowUnexpected);
+//
+// // ... but ignore low severity messages
+// EXPECT_CALL(log, Log(Lt(absl::LogSeverity::kWarning), _, _))
+// .Times(AnyNumber());
+//
+// // We expect the ERROR "Something bad!" exactly once.
+// EXPECT_CALL(log, Log(absl::LogSeverity::kError, EndsWith("/foo.cc"),
+// "Something bad!"))
+// .Times(1);
+//
+// log.StartCapturingLogs(); // Call this after done setting expectations.
+// Bar(); // Exercises the code under test.
+// }
+//
+// Note that in a multi-threaded environment, all LOG() messages from a single
+// thread will be handled in sequence, but that cannot be guaranteed for
+// messages from different threads. In fact, if the same or multiple
+// expectations are matched on two threads concurrently, their actions will be
+// executed concurrently as well and may interleave.
+class ScopedMockLog final {
+ public:
+ // ScopedMockLog::ScopedMockLog()
+ //
+ // Sets up the log and adds default expectations.
+ explicit ScopedMockLog(
+ MockLogDefault default_exp = MockLogDefault::kIgnoreUnexpected);
+ ScopedMockLog(const ScopedMockLog&) = delete;
+ ScopedMockLog& operator=(const ScopedMockLog&) = delete;
+
+ // ScopedMockLog::~ScopedMockLog()
+ //
+ // Stops intercepting logs and destroys this ScopedMockLog.
+ ~ScopedMockLog();
+
+ // ScopedMockLog::StartCapturingLogs()
+ //
+ // Starts log capturing if the object isn't already doing so. Otherwise
+ // crashes.
+ //
+ // Usually this method is called in the same thread that created this
+ // ScopedMockLog. It is the user's responsibility to not call this method if
+ // another thread may be calling it or StopCapturingLogs() at the same time.
+ // It is undefined behavior to add expectations while capturing logs is
+ // enabled.
+ void StartCapturingLogs();
+
+ // ScopedMockLog::StopCapturingLogs()
+ //
+ // Stops log capturing if the object is capturing logs. Otherwise crashes.
+ //
+ // Usually this method is called in the same thread that created this object.
+ // It is the user's responsibility to not call this method if another thread
+ // may be calling it or StartCapturingLogs() at the same time.
+ //
+ // It is UB to add expectations, while capturing logs is enabled.
+ void StopCapturingLogs();
+
+ // ScopedMockLog::UseAsLocalSink()
+ //
+ // Each `ScopedMockLog` is implemented with an `absl::LogSink`; this method
+ // returns a reference to that sink (e.g. for use with
+ // `LOG(...).ToSinkOnly()`) and marks the `ScopedMockLog` as having been used
+ // even if `StartCapturingLogs` is never called.
+ absl::LogSink& UseAsLocalSink();
+
+ // Implements the mock method:
+ //
+ // void Log(LogSeverity severity, absl::string_view file_path,
+ // absl::string_view message);
+ //
+ // The second argument to Log() is the full path of the source file in
+ // which the LOG() was issued.
+ //
+ // This is a shorthand form, which should be used by most users. Use the
+ // `Send` mock only if you want to add expectations for other log message
+ // attributes.
+ MOCK_METHOD(void, Log,
+ (absl::LogSeverity severity, const std::string& file_path,
+ const std::string& message));
+
+ // Implements the mock method:
+ //
+ // void Send(const absl::LogEntry& entry);
+ //
+ // This is the most generic form of mock that can be specified. Use this mock
+ // only if you want to add expectations for log message attributes different
+ // from the log message text, log message path and log message severity.
+ //
+ // If no expectations are specified for this mock, the default action is to
+ // forward the call to the `Log` mock.
+ MOCK_METHOD(void, Send, (const absl::LogEntry&));
+
+ // Implements the mock method:
+ //
+ // void Flush();
+ //
+ // Use this mock only if you want to add expectations for log flush calls.
+ MOCK_METHOD(void, Flush, ());
+
+ private:
+ class ForwardingSink final : public absl::LogSink {
+ public:
+ explicit ForwardingSink(ScopedMockLog* sml) : sml_(sml) {}
+ ForwardingSink(const ForwardingSink&) = delete;
+ ForwardingSink& operator=(const ForwardingSink&) = delete;
+ void Send(const absl::LogEntry& entry) override { sml_->Send(entry); }
+ void Flush() override { sml_->Flush(); }
+
+ private:
+ ScopedMockLog* sml_;
+ };
+
+ ForwardingSink sink_;
+ bool is_capturing_logs_;
+ // Until C++20, the default constructor leaves the underlying value wrapped in
+ // std::atomic uninitialized, so all constructors should be sure to initialize
+ // is_triggered_.
+ std::atomic<bool> is_triggered_;
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_SCOPED_MOCK_LOG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/structured.h b/contrib/restricted/abseil-cpp/absl/log/structured.h
new file mode 100644
index 0000000000..9ad69fbdcd
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/structured.h
@@ -0,0 +1,70 @@
+// 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/structured.h
+// -----------------------------------------------------------------------------
+//
+// This header declares APIs supporting structured logging, allowing log
+// statements to be more easily parsed, especially by automated processes.
+//
+// When structured logging is in use, data streamed into a `LOG` statement are
+// encoded as `Value` fields in a `logging.proto.Event` protocol buffer message.
+// The individual data are exposed programmatically to `LogSink`s and to the
+// user via some log reading tools which are able to query the structured data
+// more usefully than would be possible if each message was a single opaque
+// string. These helpers allow user code to add additional structure to the
+// data they stream.
+
+#ifndef ABSL_LOG_STRUCTURED_H_
+#define ABSL_LOG_STRUCTURED_H_
+
+#include <ostream>
+
+#include "absl/base/config.h"
+#include "absl/log/internal/structured.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// LogAsLiteral()
+//
+// Annotates its argument as a string literal so that structured logging
+// captures it as a `literal` field instead of a `str` field (the default).
+// This does not affect the text representation, only the structure.
+//
+// Streaming `LogAsLiteral(s)` into a `std::ostream` behaves just like streaming
+// `s` directly.
+//
+// Using `LogAsLiteral()` is occasionally appropriate and useful when proxying
+// data logged from another system or another language. For example:
+//
+// void Logger::LogString(absl::string_view str, absl::LogSeverity severity,
+// const char *file, int line) {
+// LOG(LEVEL(severity)).AtLocation(file, line) << str;
+// }
+// void Logger::LogStringLiteral(absl::string_view str,
+// absl::LogSeverity severity, const char *file,
+// int line) {
+// LOG(LEVEL(severity)).AtLocation(file, line) << absl::LogAsLiteral(str);
+// }
+inline log_internal::AsLiteralImpl LogAsLiteral(absl::string_view s) {
+ return log_internal::AsLiteralImpl(s);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_LOG_STRUCTURED_H_
diff --git a/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h
new file mode 100644
index 0000000000..f7539df4ea
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/log/vlog_is_on.h
@@ -0,0 +1,72 @@
+// Copyright 2022 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: log/vlog_is_on.h
+// -----------------------------------------------------------------------------
+//
+// This header defines the `VLOG_IS_ON()` macro that controls the
+// variable-verbosity conditional logging.
+//
+// It's used by `VLOG` in log.h, or it can also be used directly like this:
+//
+// if (VLOG_IS_ON(2)) {
+// foo_server.RecomputeStatisticsExpensive();
+// LOG(INFO) << foo_server.LastStatisticsAsString();
+// }
+//
+// Each source file has an effective verbosity level that's a non-negative
+// integer computed from the `--vmodule` and `--v` flags.
+// `VLOG_IS_ON(n)` is true, and `VLOG(n)` logs, if that effective verbosity
+// level is greater than or equal to `n`.
+//
+// `--vmodule` takes a comma-delimited list of key=value pairs. Each key is a
+// pattern matched against filenames, and the values give the effective severity
+// level applied to matching files. '?' and '*' characters in patterns are
+// interpreted as single-character and zero-or-more-character wildcards.
+// Patterns including a slash character are matched against full pathnames,
+// while those without are matched against basenames only. One suffix (i.e. the
+// last . and everything after it) is stripped from each filename prior to
+// matching, as is the special suffix "-inl".
+//
+// Files are matched against globs in `--vmodule` in order, and the first match
+// determines the verbosity level.
+//
+// Files which do not match any pattern in `--vmodule` use the value of `--v` as
+// their effective verbosity level. The default is 0.
+//
+// SetVLogLevel helper function is provided to do limited dynamic control over
+// V-logging by appending to `--vmodule`. Because these go at the beginning of
+// the list, they take priority over any globs previously added.
+//
+// Resetting --vmodule will override all previous modifications to `--vmodule`,
+// including via SetVLogLevel.
+
+#ifndef ABSL_LOG_VLOG_IS_ON_H_
+#define ABSL_LOG_VLOG_IS_ON_H_
+
+#include "absl/log/absl_vlog_is_on.h" // IWYU pragma: export
+
+// IWYU pragma: private, include "absl/log/log.h"
+
+// Each VLOG_IS_ON call site gets its own VLogSite that registers with the
+// global linked list of sites to asynchronously update its verbosity level on
+// changes to --v or --vmodule. The verbosity can also be set by manually
+// calling SetVLogLevel.
+//
+// VLOG_IS_ON is not async signal safe, but it is guaranteed not to allocate
+// new memory.
+#define VLOG_IS_ON(verbose_level) ABSL_VLOG_IS_ON(verbose_level)
+
+#endif // ABSL_LOG_VLOG_IS_ON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/memory/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/memory/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..7be6b42848
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/memory/.yandex_meta/licenses.list.txt
@@ -0,0 +1,16 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/meta/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/meta/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..7be6b42848
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/meta/.yandex_meta/licenses.list.txt
@@ -0,0 +1,16 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/numeric/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/numeric/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..3d70f7ab0e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/numeric/.yandex_meta/licenses.list.txt
@@ -0,0 +1,38 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/profiling/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/profiling/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..0f16ad2dc9
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/profiling/.yandex_meta/licenses.list.txt
@@ -0,0 +1,34 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/random/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/random/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..ff1e5ecf7f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/.yandex_meta/licenses.list.txt
@@ -0,0 +1,42 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 Google Inc. All Rights Reserved.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h b/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h
new file mode 100644
index 0000000000..432c51612a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/beta_distribution.h
@@ -0,0 +1,427 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_BETA_DISTRIBUTION_H_
+#define ABSL_RANDOM_BETA_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <ostream>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
+#include "absl/random/internal/iostream_state_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::beta_distribution:
+// Generate a floating-point variate conforming to a Beta distribution:
+// pdf(x) \propto x^(alpha-1) * (1-x)^(beta-1),
+// where the params alpha and beta are both strictly positive real values.
+//
+// The support is the open interval (0, 1), but the return value might be equal
+// to 0 or 1, due to numerical errors when alpha and beta are very different.
+//
+// Usage note: One usage is that alpha and beta are counts of number of
+// successes and failures. When the total number of trials are large, consider
+// approximating a beta distribution with a Gaussian distribution with the same
+// mean and variance. One could use the skewness, which depends only on the
+// smaller of alpha and beta when the number of trials are sufficiently large,
+// to quantify how far a beta distribution is from the normal distribution.
+template <typename RealType = double>
+class beta_distribution {
+ public:
+ using result_type = RealType;
+
+ class param_type {
+ public:
+ using distribution_type = beta_distribution;
+
+ explicit param_type(result_type alpha, result_type beta)
+ : alpha_(alpha), beta_(beta) {
+ assert(alpha >= 0);
+ assert(beta >= 0);
+ assert(alpha <= (std::numeric_limits<result_type>::max)());
+ assert(beta <= (std::numeric_limits<result_type>::max)());
+ if (alpha == 0 || beta == 0) {
+ method_ = DEGENERATE_SMALL;
+ x_ = (alpha >= beta) ? 1 : 0;
+ return;
+ }
+ // a_ = min(beta, alpha), b_ = max(beta, alpha).
+ if (beta < alpha) {
+ inverted_ = true;
+ a_ = beta;
+ b_ = alpha;
+ } else {
+ inverted_ = false;
+ a_ = alpha;
+ b_ = beta;
+ }
+ if (a_ <= 1 && b_ >= ThresholdForLargeA()) {
+ method_ = DEGENERATE_SMALL;
+ x_ = inverted_ ? result_type(1) : result_type(0);
+ return;
+ }
+ // For threshold values, see also:
+ // Evaluation of Beta Generation Algorithms, Ying-Chao Hung, et. al.
+ // February, 2009.
+ if ((b_ < 1.0 && a_ + b_ <= 1.2) || a_ <= ThresholdForSmallA()) {
+ // Choose Joehnk over Cheng when it's faster or when Cheng encounters
+ // numerical issues.
+ method_ = JOEHNK;
+ a_ = result_type(1) / alpha_;
+ b_ = result_type(1) / beta_;
+ if (std::isinf(a_) || std::isinf(b_)) {
+ method_ = DEGENERATE_SMALL;
+ x_ = inverted_ ? result_type(1) : result_type(0);
+ }
+ return;
+ }
+ if (a_ >= ThresholdForLargeA()) {
+ method_ = DEGENERATE_LARGE;
+ // Note: on PPC for long double, evaluating
+ // `std::numeric_limits::max() / ThresholdForLargeA` results in NaN.
+ result_type r = a_ / b_;
+ x_ = (inverted_ ? result_type(1) : r) / (1 + r);
+ return;
+ }
+ x_ = a_ + b_;
+ log_x_ = std::log(x_);
+ if (a_ <= 1) {
+ method_ = CHENG_BA;
+ y_ = result_type(1) / a_;
+ gamma_ = a_ + a_;
+ return;
+ }
+ method_ = CHENG_BB;
+ result_type r = (a_ - 1) / (b_ - 1);
+ y_ = std::sqrt((1 + r) / (b_ * r * 2 - r + 1));
+ gamma_ = a_ + result_type(1) / y_;
+ }
+
+ result_type alpha() const { return alpha_; }
+ result_type beta() const { return beta_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.alpha_ == b.alpha_ && a.beta_ == b.beta_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class beta_distribution;
+
+#ifdef _MSC_VER
+ // MSVC does not have constexpr implementations for std::log and std::exp
+ // so they are computed at runtime.
+#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR
+#else
+#define ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR constexpr
+#endif
+
+ // The threshold for whether std::exp(1/a) is finite.
+ // Note that this value is quite large, and a smaller a_ is NOT abnormal.
+ static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type
+ ThresholdForSmallA() {
+ return result_type(1) /
+ std::log((std::numeric_limits<result_type>::max)());
+ }
+
+ // The threshold for whether a * std::log(a) is finite.
+ static ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR result_type
+ ThresholdForLargeA() {
+ return std::exp(
+ std::log((std::numeric_limits<result_type>::max)()) -
+ std::log(std::log((std::numeric_limits<result_type>::max)())) -
+ ThresholdPadding());
+ }
+
+#undef ABSL_RANDOM_INTERNAL_LOG_EXP_CONSTEXPR
+
+ // Pad the threshold for large A for long double on PPC. This is done via a
+ // template specialization below.
+ static constexpr result_type ThresholdPadding() { return 0; }
+
+ enum Method {
+ JOEHNK, // Uses algorithm Joehnk
+ CHENG_BA, // Uses algorithm BA in Cheng
+ CHENG_BB, // Uses algorithm BB in Cheng
+
+ // Note: See also:
+ // Hung et al. Evaluation of beta generation algorithms. Communications
+ // in Statistics-Simulation and Computation 38.4 (2009): 750-770.
+ // especially:
+ // Zechner, Heinz, and Ernst Stadlober. Generating beta variates via
+ // patchwork rejection. Computing 50.1 (1993): 1-18.
+
+ DEGENERATE_SMALL, // a_ is abnormally small.
+ DEGENERATE_LARGE, // a_ is abnormally large.
+ };
+
+ result_type alpha_;
+ result_type beta_;
+
+ result_type a_{}; // the smaller of {alpha, beta}, or 1.0/alpha_ in JOEHNK
+ result_type b_{}; // the larger of {alpha, beta}, or 1.0/beta_ in JOEHNK
+ result_type x_{}; // alpha + beta, or the result in degenerate cases
+ result_type log_x_{}; // log(x_)
+ result_type y_{}; // "beta" in Cheng
+ result_type gamma_{}; // "gamma" in Cheng
+
+ Method method_{};
+
+ // Placing this last for optimal alignment.
+ // Whether alpha_ != a_, i.e. true iff alpha_ > beta_.
+ bool inverted_{};
+
+ static_assert(std::is_floating_point<RealType>::value,
+ "Class-template absl::beta_distribution<> must be "
+ "parameterized using a floating-point type.");
+ };
+
+ beta_distribution() : beta_distribution(1) {}
+
+ explicit beta_distribution(result_type alpha, result_type beta = 1)
+ : param_(alpha, beta) {}
+
+ explicit beta_distribution(const param_type& p) : param_(p) {}
+
+ void reset() {}
+
+ // Generating functions
+ template <typename URBG>
+ result_type operator()(URBG& g) { // NOLINT(runtime/references)
+ return (*this)(g, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ param_type param() const { return param_; }
+ void param(const param_type& p) { param_ = p; }
+
+ result_type(min)() const { return 0; }
+ result_type(max)() const { return 1; }
+
+ result_type alpha() const { return param_.alpha(); }
+ result_type beta() const { return param_.beta(); }
+
+ friend bool operator==(const beta_distribution& a,
+ const beta_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const beta_distribution& a,
+ const beta_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ template <typename URBG>
+ result_type AlgorithmJoehnk(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ template <typename URBG>
+ result_type AlgorithmCheng(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ template <typename URBG>
+ result_type DegenerateCase(URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ if (p.method_ == param_type::DEGENERATE_SMALL && p.alpha_ == p.beta_) {
+ // Returns 0 or 1 with equal probability.
+ random_internal::FastUniformBits<uint8_t> fast_u8;
+ return static_cast<result_type>((fast_u8(g) & 0x10) !=
+ 0); // pick any single bit.
+ }
+ return p.x_;
+ }
+
+ param_type param_;
+ random_internal::FastUniformBits<uint64_t> fast_u64_;
+};
+
+#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__PPC__)
+// PPC needs a more stringent boundary for long double.
+template <>
+constexpr long double
+beta_distribution<long double>::param_type::ThresholdPadding() {
+ return 10;
+}
+#endif
+
+template <typename RealType>
+template <typename URBG>
+typename beta_distribution<RealType>::result_type
+beta_distribution<RealType>::AlgorithmJoehnk(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+ using real_type =
+ absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
+ // Based on Joehnk, M. D. Erzeugung von betaverteilten und gammaverteilten
+ // Zufallszahlen. Metrika 8.1 (1964): 5-15.
+ // This method is described in Knuth, Vol 2 (Third Edition), pp 134.
+
+ result_type u, v, x, y, z;
+ for (;;) {
+ u = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+ fast_u64_(g));
+ v = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+ fast_u64_(g));
+
+ // Direct method. std::pow is slow for float, so rely on the optimizer to
+ // remove the std::pow() path for that case.
+ if (!std::is_same<float, result_type>::value) {
+ x = std::pow(u, p.a_);
+ y = std::pow(v, p.b_);
+ z = x + y;
+ if (z > 1) {
+ // Reject if and only if `x + y > 1.0`
+ continue;
+ }
+ if (z > 0) {
+ // When both alpha and beta are small, x and y are both close to 0, so
+ // divide by (x+y) directly may result in nan.
+ return x / z;
+ }
+ }
+
+ // Log transform.
+ // x = log( pow(u, p.a_) ), y = log( pow(v, p.b_) )
+ // since u, v <= 1.0, x, y < 0.
+ x = std::log(u) * p.a_;
+ y = std::log(v) * p.b_;
+ if (!std::isfinite(x) || !std::isfinite(y)) {
+ continue;
+ }
+ // z = log( pow(u, a) + pow(v, b) )
+ z = x > y ? (x + std::log(1 + std::exp(y - x)))
+ : (y + std::log(1 + std::exp(x - y)));
+ // Reject iff log(x+y) > 0.
+ if (z > 0) {
+ continue;
+ }
+ return std::exp(x - z);
+ }
+}
+
+template <typename RealType>
+template <typename URBG>
+typename beta_distribution<RealType>::result_type
+beta_distribution<RealType>::AlgorithmCheng(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+ using real_type =
+ absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
+ // Based on Cheng, Russell CH. Generating beta variates with nonintegral
+ // shape parameters. Communications of the ACM 21.4 (1978): 317-322.
+ // (https://dl.acm.org/citation.cfm?id=359482).
+ static constexpr result_type kLogFour =
+ result_type(1.3862943611198906188344642429163531361); // log(4)
+ static constexpr result_type kS =
+ result_type(2.6094379124341003746007593332261876); // 1+log(5)
+
+ const bool use_algorithm_ba = (p.method_ == param_type::CHENG_BA);
+ result_type u1, u2, v, w, z, r, s, t, bw_inv, lhs;
+ for (;;) {
+ u1 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+ fast_u64_(g));
+ u2 = GenerateRealFromBits<real_type, GeneratePositiveTag, false>(
+ fast_u64_(g));
+ v = p.y_ * std::log(u1 / (1 - u1));
+ w = p.a_ * std::exp(v);
+ bw_inv = result_type(1) / (p.b_ + w);
+ r = p.gamma_ * v - kLogFour;
+ s = p.a_ + r - w;
+ z = u1 * u1 * u2;
+ if (!use_algorithm_ba && s + kS >= 5 * z) {
+ break;
+ }
+ t = std::log(z);
+ if (!use_algorithm_ba && s >= t) {
+ break;
+ }
+ lhs = p.x_ * (p.log_x_ + std::log(bw_inv)) + r;
+ if (lhs >= t) {
+ break;
+ }
+ }
+ return p.inverted_ ? (1 - w * bw_inv) : w * bw_inv;
+}
+
+template <typename RealType>
+template <typename URBG>
+typename beta_distribution<RealType>::result_type
+beta_distribution<RealType>::operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ switch (p.method_) {
+ case param_type::JOEHNK:
+ return AlgorithmJoehnk(g, p);
+ case param_type::CHENG_BA:
+ ABSL_FALLTHROUGH_INTENDED;
+ case param_type::CHENG_BB:
+ return AlgorithmCheng(g, p);
+ default:
+ return DegenerateCase(g, p);
+ }
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const beta_distribution<RealType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
+ os << x.alpha() << os.fill() << x.beta();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ beta_distribution<RealType>& x) { // NOLINT(runtime/references)
+ using result_type = typename beta_distribution<RealType>::result_type;
+ using param_type = typename beta_distribution<RealType>::param_type;
+ result_type alpha, beta;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ alpha = random_internal::read_floating_point<result_type>(is);
+ if (is.fail()) return is;
+ beta = random_internal::read_floating_point<result_type>(is);
+ if (!is.fail()) {
+ x.param(param_type(alpha, beta));
+ }
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_BETA_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h b/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h
new file mode 100644
index 0000000000..ac26d9d4ab
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/bit_gen_ref.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2018 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: bit_gen_ref.h
+// -----------------------------------------------------------------------------
+//
+// This header defines a bit generator "reference" class, for use in interfaces
+// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.
+// `std::mt19937`) bit generators.
+
+#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
+#define ABSL_RANDOM_BIT_GEN_REF_H_
+
+#include <limits>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/macros.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/distribution_caller.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+template <typename URBG, typename = void, typename = void, typename = void>
+struct is_urbg : std::false_type {};
+
+template <typename URBG>
+struct is_urbg<
+ URBG,
+ absl::enable_if_t<std::is_same<
+ typename URBG::result_type,
+ typename std::decay<decltype((URBG::min)())>::type>::value>,
+ absl::enable_if_t<std::is_same<
+ typename URBG::result_type,
+ typename std::decay<decltype((URBG::max)())>::type>::value>,
+ absl::enable_if_t<std::is_same<
+ typename URBG::result_type,
+ typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
+ : std::true_type {};
+
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
+} // namespace random_internal
+
+// -----------------------------------------------------------------------------
+// absl::BitGenRef
+// -----------------------------------------------------------------------------
+//
+// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic
+// non-owning "reference" interface for use in place of any specific uniform
+// random bit generator (URBG). This class may be used for both Abseil
+// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g
+// `std::mt19937`, `std::minstd_rand`) bit generators.
+//
+// Like other reference classes, `absl::BitGenRef` does not own the
+// underlying bit generator, and the underlying instance must outlive the
+// `absl::BitGenRef`.
+//
+// `absl::BitGenRef` is particularly useful when used with an
+// `absl::MockingBitGen` to test specific paths in functions which use random
+// values.
+//
+// Example:
+// void TakesBitGenRef(absl::BitGenRef gen) {
+// int x = absl::Uniform<int>(gen, 0, 1000);
+// }
+//
+class BitGenRef {
+ // SFINAE to detect whether the URBG type includes a member matching
+ // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+ //
+ // These live inside BitGenRef so that they have friend access
+ // to MockingBitGen. (see similar methods in DistributionCaller).
+ template <template <class...> class Trait, class AlwaysVoid, class... Args>
+ struct detector : std::false_type {};
+ template <template <class...> class Trait, class... Args>
+ struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+ : std::true_type {};
+
+ template <class T>
+ using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+ std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
+ std::declval<void*>()));
+
+ template <typename T>
+ using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+
+ public:
+ BitGenRef(const BitGenRef&) = default;
+ BitGenRef(BitGenRef&&) = default;
+ BitGenRef& operator=(const BitGenRef&) = default;
+ BitGenRef& operator=(BitGenRef&&) = default;
+
+ template <
+ typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
+ typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
+ random_internal::is_urbg<URBG>::value &&
+ !HasInvokeMock<URBG>::value)>* = nullptr>
+ BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT
+ : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+ mock_call_(NotAMock),
+ generate_impl_fn_(ImplFn<URBG>) {}
+
+ template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
+ typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
+ random_internal::is_urbg<URBG>::value &&
+ HasInvokeMock<URBG>::value)>* = nullptr>
+ BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND) // NOLINT
+ : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+ mock_call_(&MockCall<URBG>),
+ generate_impl_fn_(ImplFn<URBG>) {}
+
+ using result_type = uint64_t;
+
+ static constexpr result_type(min)() {
+ return (std::numeric_limits<result_type>::min)();
+ }
+
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
+
+ private:
+ using impl_fn = result_type (*)(uintptr_t);
+ using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
+ void*);
+
+ template <typename URBG>
+ static result_type ImplFn(uintptr_t ptr) {
+ // Ensure that the return values from operator() fill the entire
+ // range promised by result_type, min() and max().
+ absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
+ return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
+ }
+
+ // Get a type-erased InvokeMock pointer.
+ template <typename URBG>
+ static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
+ void* result, void* arg_tuple) {
+ return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
+ arg_tuple);
+ }
+ static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
+ return false;
+ }
+
+ inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+ void* result) {
+ if (mock_call_ == NotAMock) return false; // avoids an indirect call.
+ return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
+ }
+
+ uintptr_t t_erased_gen_ptr_;
+ mock_call_fn mock_call_;
+ impl_fn generate_impl_fn_;
+
+ template <typename>
+ friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
+ friend class ::absl::random_internal::MockHelpers; // for InvokeMock
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_BIT_GEN_REF_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/distributions.h b/contrib/restricted/abseil-cpp/absl/random/distributions.h
new file mode 100644
index 0000000000..b6ade685d4
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/distributions.h
@@ -0,0 +1,452 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: distributions.h
+// -----------------------------------------------------------------------------
+//
+// This header defines functions representing distributions, which you use in
+// combination with an Abseil random bit generator to produce random values
+// according to the rules of that distribution.
+//
+// The Abseil random library defines the following distributions within this
+// file:
+//
+// * `absl::Uniform` for uniform (constant) distributions having constant
+// probability
+// * `absl::Bernoulli` for discrete distributions having exactly two outcomes
+// * `absl::Beta` for continuous distributions parameterized through two
+// free parameters
+// * `absl::Exponential` for discrete distributions of events occurring
+// continuously and independently at a constant average rate
+// * `absl::Gaussian` (also known as "normal distributions") for continuous
+// distributions using an associated quadratic function
+// * `absl::LogUniform` for discrete distributions where the log to the given
+// base of all values is uniform
+// * `absl::Poisson` for discrete probability distributions that express the
+// probability of a given number of events occurring within a fixed interval
+// * `absl::Zipf` for discrete probability distributions commonly used for
+// modelling of rare events
+//
+// Prefer use of these distribution function classes over manual construction of
+// your own distribution classes, as it allows library maintainers greater
+// flexibility to change the underlying implementation in the future.
+
+#ifndef ABSL_RANDOM_DISTRIBUTIONS_H_
+#define ABSL_RANDOM_DISTRIBUTIONS_H_
+
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/inline_variable.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/bernoulli_distribution.h"
+#include "absl/random/beta_distribution.h"
+#include "absl/random/exponential_distribution.h"
+#include "absl/random/gaussian_distribution.h"
+#include "absl/random/internal/distribution_caller.h" // IWYU pragma: export
+#include "absl/random/internal/traits.h"
+#include "absl/random/internal/uniform_helper.h" // IWYU pragma: export
+#include "absl/random/log_uniform_int_distribution.h"
+#include "absl/random/poisson_distribution.h"
+#include "absl/random/uniform_int_distribution.h" // IWYU pragma: export
+#include "absl/random/uniform_real_distribution.h" // IWYU pragma: export
+#include "absl/random/zipf_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosedClosed,
+ {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedClosedTag, IntervalClosed, {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalClosedOpenTag, IntervalClosedOpen, {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpenOpen, {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenOpenTag, IntervalOpen, {});
+ABSL_INTERNAL_INLINE_CONSTEXPR(IntervalOpenClosedTag, IntervalOpenClosed, {});
+
+// -----------------------------------------------------------------------------
+// absl::Uniform<T>(tag, bitgen, lo, hi)
+// -----------------------------------------------------------------------------
+//
+// `absl::Uniform()` produces random values of type `T` uniformly distributed in
+// a defined interval {lo, hi}. The interval `tag` defines the type of interval
+// which should be one of the following possible values:
+//
+// * `absl::IntervalOpenOpen`
+// * `absl::IntervalOpenClosed`
+// * `absl::IntervalClosedOpen`
+// * `absl::IntervalClosedClosed`
+//
+// where "open" refers to an exclusive value (excluded) from the output, while
+// "closed" refers to an inclusive value (included) from the output.
+//
+// In the absence of an explicit return type `T`, `absl::Uniform()` will deduce
+// the return type based on the provided endpoint arguments {A lo, B hi}.
+// Given these endpoints, one of {A, B} will be chosen as the return type, if
+// a type can be implicitly converted into the other in a lossless way. The
+// lack of any such implicit conversion between {A, B} will produce a
+// compile-time error
+//
+// See https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
+//
+// Example:
+//
+// absl::BitGen bitgen;
+//
+// // Produce a random float value between 0.0 and 1.0, inclusive
+// auto x = absl::Uniform(absl::IntervalClosedClosed, bitgen, 0.0f, 1.0f);
+//
+// // The most common interval of `absl::IntervalClosedOpen` is available by
+// // default:
+//
+// auto x = absl::Uniform(bitgen, 0.0f, 1.0f);
+//
+// // Return-types are typically inferred from the arguments, however callers
+// // can optionally provide an explicit return-type to the template.
+//
+// auto x = absl::Uniform<float>(bitgen, 0, 1);
+//
+template <typename R = void, typename TagType, typename URBG>
+typename absl::enable_if_t<!std::is_same<R, void>::value, R> //
+Uniform(TagType tag,
+ URBG&& urbg, // NOLINT(runtime/references)
+ R lo, R hi) {
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = random_internal::UniformDistributionWrapper<R>;
+
+ auto a = random_internal::uniform_lower_bound(tag, lo, hi);
+ auto b = random_internal::uniform_upper_bound(tag, lo, hi);
+ if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, tag, lo, hi);
+}
+
+// absl::Uniform<T>(bitgen, lo, hi)
+//
+// Overload of `Uniform()` using the default closed-open interval of [lo, hi),
+// and returning values of type `T`
+template <typename R = void, typename URBG>
+typename absl::enable_if_t<!std::is_same<R, void>::value, R> //
+Uniform(URBG&& urbg, // NOLINT(runtime/references)
+ R lo, R hi) {
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = random_internal::UniformDistributionWrapper<R>;
+ constexpr auto tag = absl::IntervalClosedOpen;
+
+ auto a = random_internal::uniform_lower_bound(tag, lo, hi);
+ auto b = random_internal::uniform_upper_bound(tag, lo, hi);
+ if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, lo, hi);
+}
+
+// absl::Uniform(tag, bitgen, lo, hi)
+//
+// Overload of `Uniform()` using different (but compatible) lo, hi types. Note
+// that a compile-error will result if the return type cannot be deduced
+// correctly from the passed types.
+template <typename R = void, typename TagType, typename URBG, typename A,
+ typename B>
+typename absl::enable_if_t<std::is_same<R, void>::value,
+ random_internal::uniform_inferred_return_t<A, B>>
+Uniform(TagType tag,
+ URBG&& urbg, // NOLINT(runtime/references)
+ A lo, B hi) {
+ using gen_t = absl::decay_t<URBG>;
+ using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
+ using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
+
+ auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
+ auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
+ if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, tag, static_cast<return_t>(lo),
+ static_cast<return_t>(hi));
+}
+
+// absl::Uniform(bitgen, lo, hi)
+//
+// Overload of `Uniform()` using different (but compatible) lo, hi types and the
+// default closed-open interval of [lo, hi). Note that a compile-error will
+// result if the return type cannot be deduced correctly from the passed types.
+template <typename R = void, typename URBG, typename A, typename B>
+typename absl::enable_if_t<std::is_same<R, void>::value,
+ random_internal::uniform_inferred_return_t<A, B>>
+Uniform(URBG&& urbg, // NOLINT(runtime/references)
+ A lo, B hi) {
+ using gen_t = absl::decay_t<URBG>;
+ using return_t = typename random_internal::uniform_inferred_return_t<A, B>;
+ using distribution_t = random_internal::UniformDistributionWrapper<return_t>;
+
+ constexpr auto tag = absl::IntervalClosedOpen;
+ auto a = random_internal::uniform_lower_bound<return_t>(tag, lo, hi);
+ auto b = random_internal::uniform_upper_bound<return_t>(tag, lo, hi);
+ if (!random_internal::is_uniform_range_valid(a, b)) return lo;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, static_cast<return_t>(lo),
+ static_cast<return_t>(hi));
+}
+
+// absl::Uniform<unsigned T>(bitgen)
+//
+// Overload of Uniform() using the minimum and maximum values of a given type
+// `T` (which must be unsigned), returning a value of type `unsigned T`
+template <typename R, typename URBG>
+typename absl::enable_if_t<!std::numeric_limits<R>::is_signed, R> //
+Uniform(URBG&& urbg) { // NOLINT(runtime/references)
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = random_internal::UniformDistributionWrapper<R>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Bernoulli(bitgen, p)
+// -----------------------------------------------------------------------------
+//
+// `absl::Bernoulli` produces a random boolean value, with probability `p`
+// (where 0.0 <= p <= 1.0) equaling `true`.
+//
+// Prefer `absl::Bernoulli` to produce boolean values over other alternatives
+// such as comparing an `absl::Uniform()` value to a specific output.
+//
+// See https://en.wikipedia.org/wiki/Bernoulli_distribution
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// if (absl::Bernoulli(bitgen, 1.0/3721.0)) {
+// std::cout << "Asteroid field navigation successful.";
+// }
+//
+template <typename URBG>
+bool Bernoulli(URBG&& urbg, // NOLINT(runtime/references)
+ double p) {
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = absl::bernoulli_distribution;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, p);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Beta<T>(bitgen, alpha, beta)
+// -----------------------------------------------------------------------------
+//
+// `absl::Beta` produces a floating point number distributed in the closed
+// interval [0,1] and parameterized by two values `alpha` and `beta` as per a
+// Beta distribution. `T` must be a floating point type, but may be inferred
+// from the types of `alpha` and `beta`.
+//
+// See https://en.wikipedia.org/wiki/Beta_distribution.
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// double sample = absl::Beta(bitgen, 3.0, 2.0);
+//
+template <typename RealType, typename URBG>
+RealType Beta(URBG&& urbg, // NOLINT(runtime/references)
+ RealType alpha, RealType beta) {
+ static_assert(
+ std::is_floating_point<RealType>::value,
+ "Template-argument 'RealType' must be a floating-point type, in "
+ "absl::Beta<RealType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::beta_distribution<RealType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, alpha, beta);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Exponential<T>(bitgen, lambda = 1)
+// -----------------------------------------------------------------------------
+//
+// `absl::Exponential` produces a floating point number representing the
+// distance (time) between two consecutive events in a point process of events
+// occurring continuously and independently at a constant average rate. `T` must
+// be a floating point type, but may be inferred from the type of `lambda`.
+//
+// See https://en.wikipedia.org/wiki/Exponential_distribution.
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// double call_length = absl::Exponential(bitgen, 7.0);
+//
+template <typename RealType, typename URBG>
+RealType Exponential(URBG&& urbg, // NOLINT(runtime/references)
+ RealType lambda = 1) {
+ static_assert(
+ std::is_floating_point<RealType>::value,
+ "Template-argument 'RealType' must be a floating-point type, in "
+ "absl::Exponential<RealType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::exponential_distribution<RealType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, lambda);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Gaussian<T>(bitgen, mean = 0, stddev = 1)
+// -----------------------------------------------------------------------------
+//
+// `absl::Gaussian` produces a floating point number selected from the Gaussian
+// (ie. "Normal") distribution. `T` must be a floating point type, but may be
+// inferred from the types of `mean` and `stddev`.
+//
+// See https://en.wikipedia.org/wiki/Normal_distribution
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// double giraffe_height = absl::Gaussian(bitgen, 16.3, 3.3);
+//
+template <typename RealType, typename URBG>
+RealType Gaussian(URBG&& urbg, // NOLINT(runtime/references)
+ RealType mean = 0, RealType stddev = 1) {
+ static_assert(
+ std::is_floating_point<RealType>::value,
+ "Template-argument 'RealType' must be a floating-point type, in "
+ "absl::Gaussian<RealType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::gaussian_distribution<RealType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, mean, stddev);
+}
+
+// -----------------------------------------------------------------------------
+// absl::LogUniform<T>(bitgen, lo, hi, base = 2)
+// -----------------------------------------------------------------------------
+//
+// `absl::LogUniform` produces random values distributed where the log to a
+// given base of all values is uniform in a closed interval [lo, hi]. `T` must
+// be an integral type, but may be inferred from the types of `lo` and `hi`.
+//
+// I.e., `LogUniform(0, n, b)` is uniformly distributed across buckets
+// [0], [1, b-1], [b, b^2-1] .. [b^(k-1), (b^k)-1] .. [b^floor(log(n, b)), n]
+// and is uniformly distributed within each bucket.
+//
+// The resulting probability density is inversely related to bucket size, though
+// values in the final bucket may be more likely than previous values. (In the
+// extreme case where n = b^i the final value will be tied with zero as the most
+// probable result.
+//
+// If `lo` is nonzero then this distribution is shifted to the desired interval,
+// so LogUniform(lo, hi, b) is equivalent to LogUniform(0, hi-lo, b)+lo.
+//
+// See https://en.wikipedia.org/wiki/Reciprocal_distribution
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// int v = absl::LogUniform(bitgen, 0, 1000);
+//
+template <typename IntType, typename URBG>
+IntType LogUniform(URBG&& urbg, // NOLINT(runtime/references)
+ IntType lo, IntType hi, IntType base = 2) {
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Template-argument 'IntType' must be an integral type, in "
+ "absl::LogUniform<IntType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, lo, hi, base);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Poisson<T>(bitgen, mean = 1)
+// -----------------------------------------------------------------------------
+//
+// `absl::Poisson` produces discrete probabilities for a given number of events
+// occurring within a fixed interval within the closed interval [0, max]. `T`
+// must be an integral type.
+//
+// See https://en.wikipedia.org/wiki/Poisson_distribution
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// int requests_per_minute = absl::Poisson<int>(bitgen, 3.2);
+//
+template <typename IntType, typename URBG>
+IntType Poisson(URBG&& urbg, // NOLINT(runtime/references)
+ double mean = 1.0) {
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Template-argument 'IntType' must be an integral type, in "
+ "absl::Poisson<IntType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::poisson_distribution<IntType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, mean);
+}
+
+// -----------------------------------------------------------------------------
+// absl::Zipf<T>(bitgen, hi = max, q = 2, v = 1)
+// -----------------------------------------------------------------------------
+//
+// `absl::Zipf` produces discrete probabilities commonly used for modelling of
+// rare events over the closed interval [0, hi]. The parameters `v` and `q`
+// determine the skew of the distribution. `T` must be an integral type, but
+// may be inferred from the type of `hi`.
+//
+// See http://mathworld.wolfram.com/ZipfDistribution.html
+//
+// Example:
+//
+// absl::BitGen bitgen;
+// ...
+// int term_rank = absl::Zipf<int>(bitgen);
+//
+template <typename IntType, typename URBG>
+IntType Zipf(URBG&& urbg, // NOLINT(runtime/references)
+ IntType hi = (std::numeric_limits<IntType>::max)(), double q = 2.0,
+ double v = 1.0) {
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Template-argument 'IntType' must be an integral type, in "
+ "absl::Zipf<IntType, URBG>(...)");
+
+ using gen_t = absl::decay_t<URBG>;
+ using distribution_t = typename absl::zipf_distribution<IntType>;
+
+ return random_internal::DistributionCaller<gen_t>::template Call<
+ distribution_t>(&urbg, hi, q, v);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_DISTRIBUTIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h b/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h
new file mode 100644
index 0000000000..b5caf8a1e1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/exponential_distribution.h
@@ -0,0 +1,165 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
+#define ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/generate_real.h"
+#include "absl/random/internal/iostream_state_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::exponential_distribution:
+// Generates a number conforming to an exponential distribution and is
+// equivalent to the standard [rand.dist.pois.exp] distribution.
+template <typename RealType = double>
+class exponential_distribution {
+ public:
+ using result_type = RealType;
+
+ class param_type {
+ public:
+ using distribution_type = exponential_distribution;
+
+ explicit param_type(result_type lambda = 1) : lambda_(lambda) {
+ assert(lambda > 0);
+ neg_inv_lambda_ = -result_type(1) / lambda_;
+ }
+
+ result_type lambda() const { return lambda_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.lambda_ == b.lambda_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class exponential_distribution;
+
+ result_type lambda_;
+ result_type neg_inv_lambda_;
+
+ static_assert(
+ std::is_floating_point<RealType>::value,
+ "Class-template absl::exponential_distribution<> must be parameterized "
+ "using a floating-point type.");
+ };
+
+ exponential_distribution() : exponential_distribution(1) {}
+
+ explicit exponential_distribution(result_type lambda) : param_(lambda) {}
+
+ explicit exponential_distribution(const param_type& p) : param_(p) {}
+
+ void reset() {}
+
+ // Generating functions
+ template <typename URBG>
+ result_type operator()(URBG& g) { // NOLINT(runtime/references)
+ return (*this)(g, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ param_type param() const { return param_; }
+ void param(const param_type& p) { param_ = p; }
+
+ result_type(min)() const { return 0; }
+ result_type(max)() const {
+ return std::numeric_limits<result_type>::infinity();
+ }
+
+ result_type lambda() const { return param_.lambda(); }
+
+ friend bool operator==(const exponential_distribution& a,
+ const exponential_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const exponential_distribution& a,
+ const exponential_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+ random_internal::FastUniformBits<uint64_t> fast_u64_;
+};
+
+// --------------------------------------------------------------------------
+// Implementation details follow
+// --------------------------------------------------------------------------
+
+template <typename RealType>
+template <typename URBG>
+typename exponential_distribution<RealType>::result_type
+exponential_distribution<RealType>::operator()(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ using random_internal::GenerateNegativeTag;
+ using random_internal::GenerateRealFromBits;
+ using real_type =
+ absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
+ const result_type u = GenerateRealFromBits<real_type, GenerateNegativeTag,
+ false>(fast_u64_(g)); // U(-1, 0)
+
+ // log1p(-x) is mathematically equivalent to log(1 - x) but has more
+ // accuracy for x near zero.
+ return p.neg_inv_lambda_ * std::log1p(u);
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const exponential_distribution<RealType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
+ os << x.lambda();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ exponential_distribution<RealType>& x) { // NOLINT(runtime/references)
+ using result_type = typename exponential_distribution<RealType>::result_type;
+ using param_type = typename exponential_distribution<RealType>::param_type;
+ result_type lambda;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ lambda = random_internal::read_floating_point<result_type>(is);
+ if (!is.fail()) {
+ x.param(param_type(lambda));
+ }
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_EXPONENTIAL_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h
new file mode 100644
index 0000000000..0f162a4e29
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/distribution_caller.h
@@ -0,0 +1,95 @@
+//
+// Copyright 2018 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_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
+#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
+
+#include <utility>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// DistributionCaller provides an opportunity to overload the general
+// mechanism for calling a distribution, allowing for mock-RNG classes
+// to intercept such calls.
+template <typename URBG>
+struct DistributionCaller {
+ static_assert(!std::is_pointer<URBG>::value,
+ "You must pass a reference, not a pointer.");
+ // SFINAE to detect whether the URBG type includes a member matching
+ // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
+ //
+ // These live inside BitGenRef so that they have friend access
+ // to MockingBitGen. (see similar methods in DistributionCaller).
+ template <template <class...> class Trait, class AlwaysVoid, class... Args>
+ struct detector : std::false_type {};
+ template <template <class...> class Trait, class... Args>
+ struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+ : std::true_type {};
+
+ template <class T>
+ using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+ std::declval<::absl::base_internal::FastTypeIdType>(),
+ std::declval<void*>(), std::declval<void*>()));
+
+ using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
+
+ // Default implementation of distribution caller.
+ template <typename DistrT, typename... Args>
+ static typename DistrT::result_type Impl(std::false_type, URBG* urbg,
+ Args&&... args) {
+ DistrT dist(std::forward<Args>(args)...);
+ return dist(*urbg);
+ }
+
+ // Mock implementation of distribution caller.
+ // The underlying KeyT must match the KeyT constructed by MockOverloadSet.
+ template <typename DistrT, typename... Args>
+ static typename DistrT::result_type Impl(std::true_type, URBG* urbg,
+ Args&&... args) {
+ using ResultT = typename DistrT::result_type;
+ using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
+ using KeyT = ResultT(DistrT, ArgTupleT);
+
+ ArgTupleT arg_tuple(std::forward<Args>(args)...);
+ ResultT result;
+ if (!urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+ &result)) {
+ auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
+ result = dist(*urbg);
+ }
+ return result;
+ }
+
+ // Default implementation of distribution caller.
+ template <typename DistrT, typename... Args>
+ static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
+ return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
+ std::forward<Args>(args)...);
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_CALLER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/explicit_seed_seq.h b/contrib/restricted/abseil-cpp/absl/random/internal/explicit_seed_seq.h
new file mode 100644
index 0000000000..25f791535f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/explicit_seed_seq.h
@@ -0,0 +1,92 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_
+#define ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <initializer_list>
+#include <iterator>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// This class conforms to the C++ Standard "Seed Sequence" concept
+// [rand.req.seedseq].
+//
+// An "ExplicitSeedSeq" is meant to provide a conformant interface for
+// forwarding pre-computed seed material to the constructor of a class
+// conforming to the "Uniform Random Bit Generator" concept. This class makes no
+// attempt to mutate the state provided by its constructor, and returns it
+// directly via ExplicitSeedSeq::generate().
+//
+// If this class is asked to generate more seed material than was provided to
+// the constructor, then the remaining bytes will be filled with deterministic,
+// nonrandom data.
+class ExplicitSeedSeq {
+ public:
+ using result_type = uint32_t;
+
+ ExplicitSeedSeq() : state_() {}
+
+ // Copy and move both allowed.
+ ExplicitSeedSeq(const ExplicitSeedSeq& other) = default;
+ ExplicitSeedSeq& operator=(const ExplicitSeedSeq& other) = default;
+ ExplicitSeedSeq(ExplicitSeedSeq&& other) = default;
+ ExplicitSeedSeq& operator=(ExplicitSeedSeq&& other) = default;
+
+ template <typename Iterator>
+ ExplicitSeedSeq(Iterator begin, Iterator end) {
+ for (auto it = begin; it != end; it++) {
+ state_.push_back(*it & 0xffffffff);
+ }
+ }
+
+ template <typename T>
+ ExplicitSeedSeq(std::initializer_list<T> il)
+ : ExplicitSeedSeq(il.begin(), il.end()) {}
+
+ size_t size() const { return state_.size(); }
+
+ template <typename OutIterator>
+ void param(OutIterator out) const {
+ std::copy(std::begin(state_), std::end(state_), out);
+ }
+
+ template <typename OutIterator>
+ void generate(OutIterator begin, OutIterator end) {
+ for (size_t index = 0; begin != end; begin++) {
+ *begin = state_.empty() ? 0 : state_[index++];
+ if (index >= state_.size()) {
+ index = 0;
+ }
+ }
+ }
+
+ protected:
+ std::vector<uint32_t> state_;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_EXPLICIT_SEED_SEQ_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/mock_helpers.h b/contrib/restricted/abseil-cpp/absl/random/internal/mock_helpers.h
new file mode 100644
index 0000000000..19d05612ee
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/mock_helpers.h
@@ -0,0 +1,161 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
+
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// A no-op validator meeting the ValidatorT requirements for MockHelpers.
+//
+// Custom validators should follow a similar structure, passing the type to
+// MockHelpers::MockFor<KeyT>(m, CustomValidatorT()).
+struct NoOpValidator {
+ // Default validation: do nothing.
+ template <typename ResultT, typename... Args>
+ static void Validate(ResultT, Args&&...) {}
+};
+
+// MockHelpers works in conjunction with MockOverloadSet, MockingBitGen, and
+// BitGenRef to enable the mocking capability for absl distribution functions.
+//
+// MockingBitGen registers mocks based on the typeid of a mock signature, KeyT,
+// which is used to generate a unique id.
+//
+// KeyT is a signature of the form:
+// result_type(discriminator_type, std::tuple<args...>)
+// The mocked function signature will be composed from KeyT as:
+// result_type(args...)
+//
+class MockHelpers {
+ using IdType = ::absl::base_internal::FastTypeIdType;
+
+ // Given a key signature type used to index the mock, extract the components.
+ // KeyT is expected to have the form:
+ // result_type(discriminator_type, arg_tuple_type)
+ template <typename KeyT>
+ struct KeySignature;
+
+ template <typename ResultT, typename DiscriminatorT, typename ArgTupleT>
+ struct KeySignature<ResultT(DiscriminatorT, ArgTupleT)> {
+ using result_type = ResultT;
+ using discriminator_type = DiscriminatorT;
+ using arg_tuple_type = ArgTupleT;
+ };
+
+ // Detector for InvokeMock.
+ template <class T>
+ using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+ std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
+
+ // Empty implementation of InvokeMock.
+ template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+ typename... Args>
+ static absl::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
+ return absl::nullopt;
+ }
+
+ // Non-empty implementation of InvokeMock.
+ template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
+ typename = invoke_mock_t<URBG>, typename... Args>
+ static absl::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
+ Args&&... args) {
+ ArgTupleT arg_tuple(std::forward<Args>(args)...);
+ ReturnT result;
+ if (urbg->InvokeMock(::absl::base_internal::FastTypeId<KeyT>(), &arg_tuple,
+ &result)) {
+ return result;
+ }
+ return absl::nullopt;
+ }
+
+ public:
+ // InvokeMock is private; this provides access for some specialized use cases.
+ template <typename URBG>
+ static inline bool PrivateInvokeMock(URBG* urbg, IdType type,
+ void* args_tuple, void* result) {
+ return urbg->InvokeMock(type, args_tuple, result);
+ }
+
+ // Invoke a mock for the KeyT (may or may not be a signature).
+ //
+ // KeyT is used to generate a typeid-based lookup key for the mock.
+ // KeyT is a signature of the form:
+ // result_type(discriminator_type, std::tuple<args...>)
+ // The mocked function signature will be composed from KeyT as:
+ // result_type(args...)
+ //
+ // An instance of arg_tuple_type must be constructable from Args..., since
+ // the underlying mechanism requires a pointer to an argument tuple.
+ template <typename KeyT, typename URBG, typename... Args>
+ static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
+ -> absl::optional<typename KeySignature<KeyT>::result_type> {
+ // Use function overloading to dispatch to the implementation since
+ // more modern patterns (e.g. require + constexpr) are not supported in all
+ // compiler configurations.
+ return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
+ typename KeySignature<KeyT>::arg_tuple_type, URBG>(
+ 0, urbg, std::forward<Args>(args)...);
+ }
+
+ // Acquire a mock for the KeyT (may or may not be a signature), set up to use
+ // the ValidatorT to verify that the result is in the range of the RNG
+ // function.
+ //
+ // KeyT is used to generate a typeid-based lookup for the mock.
+ // KeyT is a signature of the form:
+ // result_type(discriminator_type, std::tuple<args...>)
+ // The mocked function signature will be composed from KeyT as:
+ // result_type(args...)
+ // ValidatorT::Validate will be called after the result of the RNG. The
+ // signature is expected to be of the form:
+ // ValidatorT::Validate(result, args...)
+ template <typename KeyT, typename ValidatorT, typename MockURBG>
+ static auto MockFor(MockURBG& m, ValidatorT)
+ -> decltype(m.template RegisterMock<
+ typename KeySignature<KeyT>::result_type,
+ typename KeySignature<KeyT>::arg_tuple_type>(
+ m, std::declval<IdType>(), ValidatorT())) {
+ return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
+ typename KeySignature<KeyT>::arg_tuple_type>(
+ m, ::absl::base_internal::FastTypeId<KeyT>(), ValidatorT());
+ }
+
+ // Acquire a mock for the KeyT (may or may not be a signature).
+ //
+ // KeyT is used to generate a typeid-based lookup for the mock.
+ // KeyT is a signature of the form:
+ // result_type(discriminator_type, std::tuple<args...>)
+ // The mocked function signature will be composed from KeyT as:
+ // result_type(args...)
+ template <typename KeyT, typename MockURBG>
+ static decltype(auto) MockFor(MockURBG& m) {
+ return MockFor<KeyT>(m, NoOpValidator());
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h b/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h
new file mode 100644
index 0000000000..cfaeeeef1a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/mock_overload_set.h
@@ -0,0 +1,126 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
+
+#include <tuple>
+#include <type_traits>
+
+#include "gmock/gmock.h"
+#include "absl/base/config.h"
+#include "absl/random/internal/mock_helpers.h"
+#include "absl/random/mocking_bit_gen.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+template <typename DistrT, typename ValidatorT, typename Fn>
+struct MockSingleOverload;
+
+// MockSingleOverload
+//
+// MockSingleOverload hooks in to gMock's `ON_CALL` and `EXPECT_CALL` macros.
+// EXPECT_CALL(mock_single_overload, Call(...))` will expand to a call to
+// `mock_single_overload.gmock_Call(...)`. Because expectations are stored on
+// the MockingBitGen (an argument passed inside `Call(...)`), this forwards to
+// arguments to MockingBitGen::Register.
+//
+// The underlying KeyT must match the KeyT constructed by DistributionCaller.
+template <typename DistrT, typename ValidatorT, typename Ret, typename... Args>
+struct MockSingleOverload<DistrT, ValidatorT, Ret(MockingBitGen&, Args...)> {
+ static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
+ "Overload signature must have return type matching the "
+ "distribution result_type.");
+ using KeyT = Ret(DistrT, std::tuple<Args...>);
+
+ template <typename MockURBG>
+ auto gmock_Call(MockURBG& gen, const ::testing::Matcher<Args>&... matchers)
+ -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
+ .gmock_Call(matchers...)) {
+ static_assert(
+ std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
+ std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
+ "Mocking requires an absl::MockingBitGen");
+ return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
+ .gmock_Call(matchers...);
+ }
+};
+
+template <typename DistrT, typename ValidatorT, typename Ret, typename Arg,
+ typename... Args>
+struct MockSingleOverload<DistrT, ValidatorT,
+ Ret(Arg, MockingBitGen&, Args...)> {
+ static_assert(std::is_same<typename DistrT::result_type, Ret>::value,
+ "Overload signature must have return type matching the "
+ "distribution result_type.");
+ using KeyT = Ret(DistrT, std::tuple<Arg, Args...>);
+
+ template <typename MockURBG>
+ auto gmock_Call(const ::testing::Matcher<Arg>& matcher, MockURBG& gen,
+ const ::testing::Matcher<Args>&... matchers)
+ -> decltype(MockHelpers::MockFor<KeyT>(gen, ValidatorT())
+ .gmock_Call(matcher, matchers...)) {
+ static_assert(
+ std::is_base_of<MockingBitGenImpl<true>, MockURBG>::value ||
+ std::is_base_of<MockingBitGenImpl<false>, MockURBG>::value,
+ "Mocking requires an absl::MockingBitGen");
+ return MockHelpers::MockFor<KeyT>(gen, ValidatorT())
+ .gmock_Call(matcher, matchers...);
+ }
+};
+
+// MockOverloadSetWithValidator
+//
+// MockOverloadSetWithValidator is a wrapper around MockOverloadSet which takes
+// an additional Validator parameter, allowing for customization of the mock
+// behavior.
+//
+// `ValidatorT::Validate(result, args...)` will be called after the mock
+// distribution returns a value in `result`, allowing for validation against the
+// args.
+template <typename DistrT, typename ValidatorT, typename... Fns>
+struct MockOverloadSetWithValidator;
+
+template <typename DistrT, typename ValidatorT, typename Sig>
+struct MockOverloadSetWithValidator<DistrT, ValidatorT, Sig>
+ : public MockSingleOverload<DistrT, ValidatorT, Sig> {
+ using MockSingleOverload<DistrT, ValidatorT, Sig>::gmock_Call;
+};
+
+template <typename DistrT, typename ValidatorT, typename FirstSig,
+ typename... Rest>
+struct MockOverloadSetWithValidator<DistrT, ValidatorT, FirstSig, Rest...>
+ : public MockSingleOverload<DistrT, ValidatorT, FirstSig>,
+ public MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...> {
+ using MockSingleOverload<DistrT, ValidatorT, FirstSig>::gmock_Call;
+ using MockOverloadSetWithValidator<DistrT, ValidatorT, Rest...>::gmock_Call;
+};
+
+// MockOverloadSet
+//
+// MockOverloadSet takes a distribution and a collection of signatures and
+// performs overload resolution amongst all the overloads. This makes
+// `EXPECT_CALL(mock_overload_set, Call(...))` expand and do overload resolution
+// correctly.
+template <typename DistrT, typename... Signatures>
+using MockOverloadSet =
+ MockOverloadSetWithValidator<DistrT, NoOpValidator, Signatures...>;
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/mock_validators.h b/contrib/restricted/abseil-cpp/absl/random/internal/mock_validators.h
new file mode 100644
index 0000000000..d76d169c25
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/mock_validators.h
@@ -0,0 +1,98 @@
+// Copyright 2024 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_RANDOM_INTERNAL_MOCK_VALIDATORS_H_
+#define ABSL_RANDOM_INTERNAL_MOCK_VALIDATORS_H_
+
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/uniform_helper.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+template <typename NumType>
+class UniformDistributionValidator {
+ public:
+ // Handle absl::Uniform<NumType>(gen, absl::IntervalTag, lo, hi).
+ template <typename TagType>
+ static void Validate(NumType x, TagType tag, NumType lo, NumType hi) {
+ // For invalid ranges, absl::Uniform() simply returns one of the bounds.
+ if (x == lo && lo == hi) return;
+
+ ValidateImpl(std::is_floating_point<NumType>{}, x, tag, lo, hi);
+ }
+
+ // Handle absl::Uniform<NumType>(gen, lo, hi).
+ static void Validate(NumType x, NumType lo, NumType hi) {
+ Validate(x, IntervalClosedOpenTag(), lo, hi);
+ }
+
+ // Handle absl::Uniform<NumType>(gen).
+ static void Validate(NumType) {
+ // absl::Uniform<NumType>(gen) spans the entire range of `NumType`, so any
+ // value is okay. This overload exists because the validation logic attempts
+ // to call it anyway rather than adding extra SFINAE.
+ }
+
+ private:
+ static absl::string_view TagLbBound(IntervalClosedOpenTag) { return "["; }
+ static absl::string_view TagLbBound(IntervalOpenOpenTag) { return "("; }
+ static absl::string_view TagLbBound(IntervalClosedClosedTag) { return "["; }
+ static absl::string_view TagLbBound(IntervalOpenClosedTag) { return "("; }
+ static absl::string_view TagUbBound(IntervalClosedOpenTag) { return ")"; }
+ static absl::string_view TagUbBound(IntervalOpenOpenTag) { return ")"; }
+ static absl::string_view TagUbBound(IntervalClosedClosedTag) { return "]"; }
+ static absl::string_view TagUbBound(IntervalOpenClosedTag) { return "]"; }
+
+ template <typename TagType>
+ static void ValidateImpl(std::true_type /* is_floating_point */, NumType x,
+ TagType tag, NumType lo, NumType hi) {
+ UniformDistributionWrapper<NumType> dist(tag, lo, hi);
+ NumType lb = dist.a();
+ NumType ub = dist.b();
+ // uniform_real_distribution is always closed-open, so the upper bound is
+ // always non-inclusive.
+ ABSL_INTERNAL_CHECK(lb <= x && x < ub,
+ absl::StrCat(x, " is not in ", TagLbBound(tag), lo,
+ ", ", hi, TagUbBound(tag)));
+ }
+
+ template <typename TagType>
+ static void ValidateImpl(std::false_type /* is_floating_point */, NumType x,
+ TagType tag, NumType lo, NumType hi) {
+ using stream_type =
+ typename random_internal::stream_format_type<NumType>::type;
+
+ UniformDistributionWrapper<NumType> dist(tag, lo, hi);
+ NumType lb = dist.a();
+ NumType ub = dist.b();
+ ABSL_INTERNAL_CHECK(
+ lb <= x && x <= ub,
+ absl::StrCat(stream_type{x}, " is not in ", TagLbBound(tag),
+ stream_type{lo}, ", ", stream_type{hi}, TagUbBound(tag)));
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_MOCK_VALIDATORS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/nanobenchmark.h b/contrib/restricted/abseil-cpp/absl/random/internal/nanobenchmark.h
new file mode 100644
index 0000000000..a5097ba27b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/nanobenchmark.h
@@ -0,0 +1,172 @@
+// Copyright 2017 Google Inc. All Rights Reserved.
+//
+// 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_RANDOM_INTERNAL_NANOBENCHMARK_H_
+#define ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_
+
+// Benchmarks functions of a single integer argument with realistic branch
+// prediction hit rates. Uses a robust estimator to summarize the measurements.
+// The precision is about 0.2%.
+//
+// Examples: see nanobenchmark_test.cc.
+//
+// Background: Microbenchmarks such as http://github.com/google/benchmark
+// can measure elapsed times on the order of a microsecond. Shorter functions
+// are typically measured by repeating them thousands of times and dividing
+// the total elapsed time by this count. Unfortunately, repetition (especially
+// with the same input parameter!) influences the runtime. In time-critical
+// code, it is reasonable to expect warm instruction/data caches and TLBs,
+// but a perfect record of which branches will be taken is unrealistic.
+// Unless the application also repeatedly invokes the measured function with
+// the same parameter, the benchmark is measuring something very different -
+// a best-case result, almost as if the parameter were made a compile-time
+// constant. This may lead to erroneous conclusions about branch-heavy
+// algorithms outperforming branch-free alternatives.
+//
+// Our approach differs in three ways. Adding fences to the timer functions
+// reduces variability due to instruction reordering, improving the timer
+// resolution to about 40 CPU cycles. However, shorter functions must still
+// be invoked repeatedly. For more realistic branch prediction performance,
+// we vary the input parameter according to a user-specified distribution.
+// Thus, instead of VaryInputs(Measure(Repeat(func))), we change the
+// loop nesting to Measure(Repeat(VaryInputs(func))). We also estimate the
+// central tendency of the measurement samples with the "half sample mode",
+// which is more robust to outliers and skewed data than the mean or median.
+
+// NOTE: for compatibility with multiple translation units compiled with
+// distinct flags, avoid #including headers that define functions.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal_nanobenchmark {
+
+// Input influencing the function being measured (e.g. number of bytes to copy).
+using FuncInput = size_t;
+
+// "Proof of work" returned by Func to ensure the compiler does not elide it.
+using FuncOutput = uint64_t;
+
+// Function to measure: either 1) a captureless lambda or function with two
+// arguments or 2) a lambda with capture, in which case the first argument
+// is reserved for use by MeasureClosure.
+using Func = FuncOutput (*)(const void*, FuncInput);
+
+// Internal parameters that determine precision/resolution/measuring time.
+struct Params {
+ // For measuring timer overhead/resolution. Used in a nested loop =>
+ // quadratic time, acceptable because we know timer overhead is "low".
+ // constexpr because this is used to define array bounds.
+ static constexpr size_t kTimerSamples = 256;
+
+ // Best-case precision, expressed as a divisor of the timer resolution.
+ // Larger => more calls to Func and higher precision.
+ size_t precision_divisor = 1024;
+
+ // Ratio between full and subset input distribution sizes. Cannot be less
+ // than 2; larger values increase measurement time but more faithfully
+ // model the given input distribution.
+ size_t subset_ratio = 2;
+
+ // Together with the estimated Func duration, determines how many times to
+ // call Func before checking the sample variability. Larger values increase
+ // measurement time, memory/cache use and precision.
+ double seconds_per_eval = 4E-3;
+
+ // The minimum number of samples before estimating the central tendency.
+ size_t min_samples_per_eval = 7;
+
+ // The mode is better than median for estimating the central tendency of
+ // skewed/fat-tailed distributions, but it requires sufficient samples
+ // relative to the width of half-ranges.
+ size_t min_mode_samples = 64;
+
+ // Maximum permissible variability (= median absolute deviation / center).
+ double target_rel_mad = 0.002;
+
+ // Abort after this many evals without reaching target_rel_mad. This
+ // prevents infinite loops.
+ size_t max_evals = 9;
+
+ // Retry the measure loop up to this many times.
+ size_t max_measure_retries = 2;
+
+ // Whether to print additional statistics to stdout.
+ bool verbose = true;
+};
+
+// Measurement result for each unique input.
+struct Result {
+ FuncInput input;
+
+ // Robust estimate (mode or median) of duration.
+ float ticks;
+
+ // Measure of variability (median absolute deviation relative to "ticks").
+ float variability;
+};
+
+// Ensures the thread is running on the specified cpu, and no others.
+// Reduces noise due to desynchronized socket RDTSC and context switches.
+// If "cpu" is negative, pin to the currently running core.
+void PinThreadToCPU(const int cpu = -1);
+
+// Returns tick rate, useful for converting measurements to seconds. Invariant
+// means the tick counter frequency is independent of CPU throttling or sleep.
+// This call may be expensive, callers should cache the result.
+double InvariantTicksPerSecond();
+
+// Precisely measures the number of ticks elapsed when calling "func" with the
+// given inputs, shuffled to ensure realistic branch prediction hit rates.
+//
+// "func" returns a 'proof of work' to ensure its computations are not elided.
+// "arg" is passed to Func, or reserved for internal use by MeasureClosure.
+// "inputs" is an array of "num_inputs" (not necessarily unique) arguments to
+// "func". The values should be chosen to maximize coverage of "func". This
+// represents a distribution, so a value's frequency should reflect its
+// probability in the real application. Order does not matter; for example, a
+// uniform distribution over [0, 4) could be represented as {3,0,2,1}.
+// Returns how many Result were written to "results": one per unique input, or
+// zero if the measurement failed (an error message goes to stderr).
+size_t Measure(const Func func, const void* arg, const FuncInput* inputs,
+ const size_t num_inputs, Result* results,
+ const Params& p = Params());
+
+// Calls operator() of the given closure (lambda function).
+template <class Closure>
+static FuncOutput CallClosure(const void* f, const FuncInput input) {
+ return (*reinterpret_cast<const Closure*>(f))(input);
+}
+
+// Same as Measure, except "closure" is typically a lambda function of
+// FuncInput -> FuncOutput with a capture list.
+template <class Closure>
+static inline size_t MeasureClosure(const Closure& closure,
+ const FuncInput* inputs,
+ const size_t num_inputs, Result* results,
+ const Params& p = Params()) {
+ return Measure(reinterpret_cast<Func>(&CallClosure<Closure>),
+ reinterpret_cast<const void*>(&closure), inputs, num_inputs,
+ results, p);
+}
+
+} // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_NANOBENCHMARK_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/nonsecure_base.h b/contrib/restricted/abseil-cpp/absl/random/internal/nonsecure_base.h
new file mode 100644
index 0000000000..c3b80335ae
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/nonsecure_base.h
@@ -0,0 +1,161 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
+#define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
+
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/base/macros.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/pool_urbg.h"
+#include "absl/random/internal/salted_seed_seq.h"
+#include "absl/random/internal/seed_material.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// RandenPoolSeedSeq is a custom seed sequence type where generate() fills the
+// provided buffer via the RandenPool entropy source.
+class RandenPoolSeedSeq {
+ private:
+ struct ContiguousTag {};
+ struct BufferTag {};
+
+ // Generate random unsigned values directly into the buffer.
+ template <typename Contiguous>
+ void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) {
+ const size_t n = static_cast<size_t>(std::distance(begin, end));
+ auto* a = &(*begin);
+ RandenPool<uint8_t>::Fill(
+ absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n));
+ }
+
+ // Construct a buffer of size n and fill it with values, then copy
+ // those values into the seed iterators.
+ template <typename RandomAccessIterator>
+ void generate_impl(BufferTag, RandomAccessIterator begin,
+ RandomAccessIterator end) {
+ const size_t n = std::distance(begin, end);
+ absl::InlinedVector<uint32_t, 8> data(n, 0);
+ RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end()));
+ std::copy(std::begin(data), std::end(data), begin);
+ }
+
+ public:
+ using result_type = uint32_t;
+
+ size_t size() { return 0; }
+
+ template <typename OutIterator>
+ void param(OutIterator) const {}
+
+ template <typename RandomAccessIterator>
+ void generate(RandomAccessIterator begin, RandomAccessIterator end) {
+ // RandomAccessIterator must be assignable from uint32_t
+ if (begin != end) {
+ using U = typename std::iterator_traits<RandomAccessIterator>::value_type;
+ // ContiguousTag indicates the common case of a known contiguous buffer,
+ // which allows directly filling the buffer. In C++20,
+ // std::contiguous_iterator_tag provides a mechanism for testing this
+ // capability, however until Abseil's support requirements allow us to
+ // assume C++20, limit checks to a few common cases.
+ using TagType = absl::conditional_t<
+ (std::is_pointer<RandomAccessIterator>::value ||
+ std::is_same<RandomAccessIterator,
+ typename std::vector<U>::iterator>::value),
+ ContiguousTag, BufferTag>;
+
+ generate_impl(TagType{}, begin, end);
+ }
+ }
+};
+
+// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
+// by a thread-unique URBG-instance.
+template <typename URBG, typename Seeder = RandenPoolSeedSeq>
+class NonsecureURBGBase {
+ public:
+ using result_type = typename URBG::result_type;
+
+ // Default constructor
+ NonsecureURBGBase() : urbg_(ConstructURBG()) {}
+
+ // Copy disallowed, move allowed.
+ NonsecureURBGBase(const NonsecureURBGBase&) = delete;
+ NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete;
+ NonsecureURBGBase(NonsecureURBGBase&&) = default;
+ NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default;
+
+ // Constructor using a seed
+ template <class SSeq, typename = typename absl::enable_if_t<
+ !std::is_same<SSeq, NonsecureURBGBase>::value>>
+ explicit NonsecureURBGBase(SSeq&& seq)
+ : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {}
+
+ // Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we
+ // enclose min() or max() in parens as (min)() and (max)().
+ // Additionally, clang-format requires no space before this construction.
+
+ // NonsecureURBGBase::min()
+ static constexpr result_type(min)() { return (URBG::min)(); }
+
+ // NonsecureURBGBase::max()
+ static constexpr result_type(max)() { return (URBG::max)(); }
+
+ // NonsecureURBGBase::operator()()
+ result_type operator()() { return urbg_(); }
+
+ // NonsecureURBGBase::discard()
+ void discard(unsigned long long values) { // NOLINT(runtime/int)
+ urbg_.discard(values);
+ }
+
+ bool operator==(const NonsecureURBGBase& other) const {
+ return urbg_ == other.urbg_;
+ }
+
+ bool operator!=(const NonsecureURBGBase& other) const {
+ return !(urbg_ == other.urbg_);
+ }
+
+ private:
+ static URBG ConstructURBG() {
+ Seeder seeder;
+ return URBG(seeder);
+ }
+
+ template <typename SSeq>
+ static URBG ConstructURBG(SSeq&& seq) { // NOLINT(runtime/references)
+ auto salted_seq =
+ random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq));
+ return URBG(salted_seq);
+ }
+
+ URBG urbg_;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/pcg_engine.h b/contrib/restricted/abseil-cpp/absl/random/internal/pcg_engine.h
new file mode 100644
index 0000000000..e1f4ef3317
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/pcg_engine.h
@@ -0,0 +1,287 @@
+// Copyright 2018 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_RANDOM_INTERNAL_PCG_ENGINE_H_
+#define ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_
+
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/iostream_state_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// pcg_engine is a simplified implementation of Melissa O'Neil's PCG engine in
+// C++. PCG combines a linear congruential generator (LCG) with output state
+// mixing functions to generate each random variate. pcg_engine supports only a
+// single sequence (oneseq), and does not support streams.
+//
+// pcg_engine is parameterized by two types:
+// Params, which provides the multiplier and increment values;
+// Mix, which mixes the state into the result.
+//
+template <typename Params, typename Mix>
+class pcg_engine {
+ static_assert(std::is_same<typename Params::state_type,
+ typename Mix::state_type>::value,
+ "Class-template absl::pcg_engine must be parameterized by "
+ "Params and Mix with identical state_type");
+
+ static_assert(std::is_unsigned<typename Mix::result_type>::value,
+ "Class-template absl::pcg_engine must be parameterized by "
+ "an unsigned Mix::result_type");
+
+ using params_type = Params;
+ using mix_type = Mix;
+ using state_type = typename Mix::state_type;
+
+ public:
+ // C++11 URBG interface:
+ using result_type = typename Mix::result_type;
+
+ static constexpr result_type(min)() {
+ return (std::numeric_limits<result_type>::min)();
+ }
+
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ explicit pcg_engine(uint64_t seed_value = 0) { seed(seed_value); }
+
+ template <class SeedSequence,
+ typename = typename absl::enable_if_t<
+ !std::is_same<SeedSequence, pcg_engine>::value>>
+ explicit pcg_engine(SeedSequence&& seq) {
+ seed(seq);
+ }
+
+ pcg_engine(const pcg_engine&) = default;
+ pcg_engine& operator=(const pcg_engine&) = default;
+ pcg_engine(pcg_engine&&) = default;
+ pcg_engine& operator=(pcg_engine&&) = default;
+
+ result_type operator()() {
+ // Advance the LCG state, always using the new value to generate the output.
+ state_ = lcg(state_);
+ return Mix{}(state_);
+ }
+
+ void seed(uint64_t seed_value = 0) {
+ state_type tmp = seed_value;
+ state_ = lcg(tmp + Params::increment());
+ }
+
+ template <class SeedSequence>
+ typename absl::enable_if_t<
+ !std::is_convertible<SeedSequence, uint64_t>::value, void>
+ seed(SeedSequence&& seq) {
+ reseed(seq);
+ }
+
+ void discard(uint64_t count) { state_ = advance(state_, count); }
+
+ bool operator==(const pcg_engine& other) const {
+ return state_ == other.state_;
+ }
+
+ bool operator!=(const pcg_engine& other) const { return !(*this == other); }
+
+ template <class CharT, class Traits>
+ friend typename absl::enable_if_t<(sizeof(state_type) == 16),
+ std::basic_ostream<CharT, Traits>&>
+ operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const pcg_engine& engine) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ random_internal::stream_u128_helper<state_type> helper;
+ helper.write(pcg_engine::params_type::multiplier(), os);
+ os << os.fill();
+ helper.write(pcg_engine::params_type::increment(), os);
+ os << os.fill();
+ helper.write(engine.state_, os);
+ return os;
+ }
+
+ template <class CharT, class Traits>
+ friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
+ std::basic_ostream<CharT, Traits>&>
+ operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const pcg_engine& engine) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os << pcg_engine::params_type::multiplier() << os.fill();
+ os << pcg_engine::params_type::increment() << os.fill();
+ os << engine.state_;
+ return os;
+ }
+
+ template <class CharT, class Traits>
+ friend typename absl::enable_if_t<(sizeof(state_type) == 16),
+ std::basic_istream<CharT, Traits>&>
+ operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ pcg_engine& engine) { // NOLINT(runtime/references)
+ random_internal::stream_u128_helper<state_type> helper;
+ auto mult = helper.read(is);
+ auto inc = helper.read(is);
+ auto tmp = helper.read(is);
+ if (mult != pcg_engine::params_type::multiplier() ||
+ inc != pcg_engine::params_type::increment()) {
+ // signal failure by setting the failbit.
+ is.setstate(is.rdstate() | std::ios_base::failbit);
+ }
+ if (!is.fail()) {
+ engine.state_ = tmp;
+ }
+ return is;
+ }
+
+ template <class CharT, class Traits>
+ friend typename absl::enable_if_t<(sizeof(state_type) <= 8),
+ std::basic_istream<CharT, Traits>&>
+ operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ pcg_engine& engine) { // NOLINT(runtime/references)
+ state_type mult{}, inc{}, tmp{};
+ is >> mult >> inc >> tmp;
+ if (mult != pcg_engine::params_type::multiplier() ||
+ inc != pcg_engine::params_type::increment()) {
+ // signal failure by setting the failbit.
+ is.setstate(is.rdstate() | std::ios_base::failbit);
+ }
+ if (!is.fail()) {
+ engine.state_ = tmp;
+ }
+ return is;
+ }
+
+ private:
+ state_type state_;
+
+ // Returns the linear-congruential generator next state.
+ static inline constexpr state_type lcg(state_type s) {
+ return s * Params::multiplier() + Params::increment();
+ }
+
+ // Returns the linear-congruential arbitrary seek state.
+ inline state_type advance(state_type s, uint64_t n) const {
+ state_type mult = Params::multiplier();
+ state_type inc = Params::increment();
+ state_type m = 1;
+ state_type i = 0;
+ while (n > 0) {
+ if (n & 1) {
+ m *= mult;
+ i = i * mult + inc;
+ }
+ inc = (mult + 1) * inc;
+ mult *= mult;
+ n >>= 1;
+ }
+ return m * s + i;
+ }
+
+ template <class SeedSequence>
+ void reseed(SeedSequence& seq) {
+ using sequence_result_type = typename SeedSequence::result_type;
+ constexpr size_t kBufferSize =
+ sizeof(state_type) / sizeof(sequence_result_type);
+ sequence_result_type buffer[kBufferSize];
+ seq.generate(std::begin(buffer), std::end(buffer));
+ // Convert the seed output to a single state value.
+ state_type tmp = buffer[0];
+ for (size_t i = 1; i < kBufferSize; i++) {
+ tmp <<= (sizeof(sequence_result_type) * 8);
+ tmp |= buffer[i];
+ }
+ state_ = lcg(tmp + params_type::increment());
+ }
+};
+
+// Parameterized implementation of the PCG 128-bit oneseq state.
+// This provides state_type, multiplier, and increment for pcg_engine.
+template <uint64_t kMultA, uint64_t kMultB, uint64_t kIncA, uint64_t kIncB>
+class pcg128_params {
+ public:
+ using state_type = absl::uint128;
+ static inline constexpr state_type multiplier() {
+ return absl::MakeUint128(kMultA, kMultB);
+ }
+ static inline constexpr state_type increment() {
+ return absl::MakeUint128(kIncA, kIncB);
+ }
+};
+
+// Implementation of the PCG xsl_rr_128_64 128-bit mixing function, which
+// accepts an input of state_type and mixes it into an output of result_type.
+struct pcg_xsl_rr_128_64 {
+ using state_type = absl::uint128;
+ using result_type = uint64_t;
+
+ inline uint64_t operator()(state_type state) {
+ // This is equivalent to the xsl_rr_128_64 mixing function.
+ uint64_t rotate = static_cast<uint64_t>(state >> 122u);
+ state ^= state >> 64;
+ uint64_t s = static_cast<uint64_t>(state);
+ return rotr(s, static_cast<int>(rotate));
+ }
+};
+
+// Parameterized implementation of the PCG 64-bit oneseq state.
+// This provides state_type, multiplier, and increment for pcg_engine.
+template <uint64_t kMult, uint64_t kInc>
+class pcg64_params {
+ public:
+ using state_type = uint64_t;
+ static inline constexpr state_type multiplier() { return kMult; }
+ static inline constexpr state_type increment() { return kInc; }
+};
+
+// Implementation of the PCG xsh_rr_64_32 64-bit mixing function, which accepts
+// an input of state_type and mixes it into an output of result_type.
+struct pcg_xsh_rr_64_32 {
+ using state_type = uint64_t;
+ using result_type = uint32_t;
+ inline uint32_t operator()(uint64_t state) {
+ return rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27),
+ state >> 59);
+ }
+};
+
+// Stable pcg_engine implementations:
+// This is a 64-bit generator using 128-bits of state.
+// The output sequence is equivalent to Melissa O'Neil's pcg64_oneseq.
+using pcg64_2018_engine = pcg_engine<
+ random_internal::pcg128_params<0x2360ed051fc65da4ull, 0x4385df649fccf645ull,
+ 0x5851f42d4c957f2d, 0x14057b7ef767814f>,
+ random_internal::pcg_xsl_rr_128_64>;
+
+// This is a 32-bit generator using 64-bits of state.
+// This is equivalent to Melissa O'Neil's pcg32_oneseq.
+using pcg32_2018_engine = pcg_engine<
+ random_internal::pcg64_params<0x5851f42d4c957f2dull, 0x14057b7ef767814full>,
+ random_internal::pcg_xsh_rr_64_32>;
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_PCG_ENGINE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h b/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h
new file mode 100644
index 0000000000..fe2d9f6c15
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/randen_engine.h
@@ -0,0 +1,264 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
+
+#include <algorithm>
+#include <cinttypes>
+#include <cstdlib>
+#include <iostream>
+#include <iterator>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/internal/endian.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/randen.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Deterministic pseudorandom byte generator with backtracking resistance
+// (leaking the state does not compromise prior outputs). Based on Reverie
+// (see "A Robust and Sponge-Like PRNG with Improved Efficiency") instantiated
+// with an improved Simpira-like permutation.
+// Returns values of type "T" (must be a built-in unsigned integer type).
+//
+// RANDen = RANDom generator or beetroots in Swiss High German.
+// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
+// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
+template <typename T>
+class alignas(8) randen_engine {
+ public:
+ // C++11 URBG interface:
+ using result_type = T;
+ static_assert(std::is_unsigned<result_type>::value,
+ "randen_engine template argument must be a built-in unsigned "
+ "integer type");
+
+ static constexpr result_type(min)() {
+ return (std::numeric_limits<result_type>::min)();
+ }
+
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ randen_engine() : randen_engine(0) {}
+ explicit randen_engine(result_type seed_value) { seed(seed_value); }
+
+ template <class SeedSequence,
+ typename = typename absl::enable_if_t<
+ !std::is_same<SeedSequence, randen_engine>::value>>
+ explicit randen_engine(SeedSequence&& seq) {
+ seed(seq);
+ }
+
+ // alignment requirements dictate custom copy and move constructors.
+ randen_engine(const randen_engine& other)
+ : next_(other.next_), impl_(other.impl_) {
+ std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));
+ }
+ randen_engine& operator=(const randen_engine& other) {
+ next_ = other.next_;
+ impl_ = other.impl_;
+ std::memcpy(state(), other.state(), kStateSizeT * sizeof(result_type));
+ return *this;
+ }
+
+ // Returns random bits from the buffer in units of result_type.
+ result_type operator()() {
+ // Refill the buffer if needed (unlikely).
+ auto* begin = state();
+ if (next_ >= kStateSizeT) {
+ next_ = kCapacityT;
+ impl_.Generate(begin);
+ }
+ return little_endian::ToHost(begin[next_++]);
+ }
+
+ template <class SeedSequence>
+ typename absl::enable_if_t<
+ !std::is_convertible<SeedSequence, result_type>::value>
+ seed(SeedSequence&& seq) {
+ // Zeroes the state.
+ seed();
+ reseed(seq);
+ }
+
+ void seed(result_type seed_value = 0) {
+ next_ = kStateSizeT;
+ // Zeroes the inner state and fills the outer state with seed_value to
+ // mimic the behaviour of reseed
+ auto* begin = state();
+ std::fill(begin, begin + kCapacityT, 0);
+ std::fill(begin + kCapacityT, begin + kStateSizeT, seed_value);
+ }
+
+ // Inserts entropy into (part of) the state. Calling this periodically with
+ // sufficient entropy ensures prediction resistance (attackers cannot predict
+ // future outputs even if state is compromised).
+ template <class SeedSequence>
+ void reseed(SeedSequence& seq) {
+ using sequence_result_type = typename SeedSequence::result_type;
+ static_assert(sizeof(sequence_result_type) == 4,
+ "SeedSequence::result_type must be 32-bit");
+ constexpr size_t kBufferSize =
+ Randen::kSeedBytes / sizeof(sequence_result_type);
+ alignas(16) sequence_result_type buffer[kBufferSize];
+
+ // Randen::Absorb XORs the seed into state, which is then mixed by a call
+ // to Randen::Generate. Seeding with only the provided entropy is preferred
+ // to using an arbitrary generate() call, so use [rand.req.seed_seq]
+ // size as a proxy for the number of entropy units that can be generated
+ // without relying on seed sequence mixing...
+ const size_t entropy_size = seq.size();
+ if (entropy_size < kBufferSize) {
+ // ... and only request that many values, or 256-bits, when unspecified.
+ const size_t requested_entropy = (entropy_size == 0) ? 8u : entropy_size;
+ std::fill(buffer + requested_entropy, buffer + kBufferSize, 0);
+ seq.generate(buffer, buffer + requested_entropy);
+#ifdef ABSL_IS_BIG_ENDIAN
+ // Randen expects the seed buffer to be in Little Endian; reverse it on
+ // Big Endian platforms.
+ for (sequence_result_type& e : buffer) {
+ e = absl::little_endian::FromHost(e);
+ }
+#endif
+ // The Randen paper suggests preferentially initializing even-numbered
+ // 128-bit vectors of the randen state (there are 16 such vectors).
+ // The seed data is merged into the state offset by 128-bits, which
+ // implies preferring seed bytes [16..31, ..., 208..223]. Since the
+ // buffer is 32-bit values, we swap the corresponding buffer positions in
+ // 128-bit chunks.
+ size_t dst = kBufferSize;
+ while (dst > 7) {
+ // leave the odd bucket as-is.
+ dst -= 4;
+ size_t src = dst >> 1;
+ // swap 128-bits into the even bucket
+ std::swap(buffer[--dst], buffer[--src]);
+ std::swap(buffer[--dst], buffer[--src]);
+ std::swap(buffer[--dst], buffer[--src]);
+ std::swap(buffer[--dst], buffer[--src]);
+ }
+ } else {
+ seq.generate(buffer, buffer + kBufferSize);
+ }
+ impl_.Absorb(buffer, state());
+
+ // Generate will be called when operator() is called
+ next_ = kStateSizeT;
+ }
+
+ void discard(uint64_t count) {
+ uint64_t step = std::min<uint64_t>(kStateSizeT - next_, count);
+ count -= step;
+
+ constexpr uint64_t kRateT = kStateSizeT - kCapacityT;
+ auto* begin = state();
+ while (count > 0) {
+ next_ = kCapacityT;
+ impl_.Generate(*reinterpret_cast<result_type(*)[kStateSizeT]>(begin));
+ step = std::min<uint64_t>(kRateT, count);
+ count -= step;
+ }
+ next_ += step;
+ }
+
+ bool operator==(const randen_engine& other) const {
+ const auto* begin = state();
+ return next_ == other.next_ &&
+ std::equal(begin, begin + kStateSizeT, other.state());
+ }
+
+ bool operator!=(const randen_engine& other) const {
+ return !(*this == other);
+ }
+
+ template <class CharT, class Traits>
+ friend std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const randen_engine<T>& engine) { // NOLINT(runtime/references)
+ using numeric_type =
+ typename random_internal::stream_format_type<result_type>::type;
+ auto saver = random_internal::make_ostream_state_saver(os);
+ auto* it = engine.state();
+ for (auto* end = it + kStateSizeT; it < end; ++it) {
+ // In the case that `elem` is `uint8_t`, it must be cast to something
+ // larger so that it prints as an integer rather than a character. For
+ // simplicity, apply the cast all circumstances.
+ os << static_cast<numeric_type>(little_endian::FromHost(*it))
+ << os.fill();
+ }
+ os << engine.next_;
+ return os;
+ }
+
+ template <class CharT, class Traits>
+ friend std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ randen_engine<T>& engine) { // NOLINT(runtime/references)
+ using numeric_type =
+ typename random_internal::stream_format_type<result_type>::type;
+ result_type state[kStateSizeT];
+ size_t next;
+ for (auto& elem : state) {
+ // It is not possible to read uint8_t from wide streams, so it is
+ // necessary to read a wider type and then cast it to uint8_t.
+ numeric_type value;
+ is >> value;
+ elem = little_endian::ToHost(static_cast<result_type>(value));
+ }
+ is >> next;
+ if (is.fail()) {
+ return is;
+ }
+ std::memcpy(engine.state(), state, sizeof(state));
+ engine.next_ = next;
+ return is;
+ }
+
+ private:
+ static constexpr size_t kStateSizeT =
+ Randen::kStateBytes / sizeof(result_type);
+ static constexpr size_t kCapacityT =
+ Randen::kCapacityBytes / sizeof(result_type);
+
+ // Returns the state array pointer, which is aligned to 16 bytes.
+ // The first kCapacityT are the `inner' sponge; the remainder are available.
+ result_type* state() {
+ return reinterpret_cast<result_type*>(
+ (reinterpret_cast<uintptr_t>(&raw_state_) & 0xf) ? (raw_state_ + 8)
+ : raw_state_);
+ }
+ const result_type* state() const {
+ return const_cast<randen_engine*>(this)->state();
+ }
+
+ // raw state array, manually aligned in state(). This overallocates
+ // by 8 bytes since C++ does not guarantee extended heap alignment.
+ alignas(8) char raw_state_[Randen::kStateBytes + 8];
+ size_t next_; // index within state()
+ Randen impl_;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_ENGINE_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/sequence_urbg.h b/contrib/restricted/abseil-cpp/absl/random/internal/sequence_urbg.h
new file mode 100644
index 0000000000..bc96a12cd2
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/sequence_urbg.h
@@ -0,0 +1,60 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_
+#define ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_
+
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// `sequence_urbg` is a simple random number generator which meets the
+// requirements of [rand.req.urbg], and is solely for testing absl
+// distributions.
+class sequence_urbg {
+ public:
+ using result_type = uint64_t;
+
+ static constexpr result_type(min)() {
+ return (std::numeric_limits<result_type>::min)();
+ }
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ sequence_urbg(std::initializer_list<result_type> data) : i_(0), data_(data) {}
+ void reset() { i_ = 0; }
+
+ result_type operator()() { return data_[i_++ % data_.size()]; }
+
+ size_t invocations() const { return i_; }
+
+ private:
+ size_t i_;
+ std::vector<result_type> data_;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_SEQUENCE_URBG_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h b/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h
new file mode 100644
index 0000000000..db737e13f3
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/internal/uniform_helper.h
@@ -0,0 +1,244 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
+#define ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
+
+#include <cmath>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename IntType>
+class uniform_int_distribution;
+
+template <typename RealType>
+class uniform_real_distribution;
+
+// Interval tag types which specify whether the interval is open or closed
+// on either boundary.
+
+namespace random_internal {
+template <typename T>
+struct TagTypeCompare {};
+
+template <typename T>
+constexpr bool operator==(TagTypeCompare<T>, TagTypeCompare<T>) {
+ // Tags are mono-states. They always compare equal.
+ return true;
+}
+template <typename T>
+constexpr bool operator!=(TagTypeCompare<T>, TagTypeCompare<T>) {
+ return false;
+}
+
+} // namespace random_internal
+
+struct IntervalClosedClosedTag
+ : public random_internal::TagTypeCompare<IntervalClosedClosedTag> {};
+struct IntervalClosedOpenTag
+ : public random_internal::TagTypeCompare<IntervalClosedOpenTag> {};
+struct IntervalOpenClosedTag
+ : public random_internal::TagTypeCompare<IntervalOpenClosedTag> {};
+struct IntervalOpenOpenTag
+ : public random_internal::TagTypeCompare<IntervalOpenOpenTag> {};
+
+namespace random_internal {
+
+// In the absence of an explicitly provided return-type, the template
+// "uniform_inferred_return_t<A, B>" is used to derive a suitable type, based on
+// the data-types of the endpoint-arguments {A lo, B hi}.
+//
+// Given endpoints {A lo, B hi}, one of {A, B} will be chosen as the
+// return-type, if one type can be implicitly converted into the other, in a
+// lossless way. The template "is_widening_convertible" implements the
+// compile-time logic for deciding if such a conversion is possible.
+//
+// If no such conversion between {A, B} exists, then the overload for
+// absl::Uniform() will be discarded, and the call will be ill-formed.
+// Return-type for absl::Uniform() when the return-type is inferred.
+template <typename A, typename B>
+using uniform_inferred_return_t =
+ absl::enable_if_t<absl::disjunction<is_widening_convertible<A, B>,
+ is_widening_convertible<B, A>>::value,
+ typename std::conditional<
+ is_widening_convertible<A, B>::value, B, A>::type>;
+
+// The functions
+// uniform_lower_bound(tag, a, b)
+// and
+// uniform_upper_bound(tag, a, b)
+// are used as implementation-details for absl::Uniform().
+//
+// Conceptually,
+// [a, b] == [uniform_lower_bound(IntervalClosedClosed, a, b),
+// uniform_upper_bound(IntervalClosedClosed, a, b)]
+// (a, b) == [uniform_lower_bound(IntervalOpenOpen, a, b),
+// uniform_upper_bound(IntervalOpenOpen, a, b)]
+// [a, b) == [uniform_lower_bound(IntervalClosedOpen, a, b),
+// uniform_upper_bound(IntervalClosedOpen, a, b)]
+// (a, b] == [uniform_lower_bound(IntervalOpenClosed, a, b),
+// uniform_upper_bound(IntervalOpenClosed, a, b)]
+//
+template <typename IntType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ IsIntegral<IntType>,
+ absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
+ std::is_same<Tag, IntervalOpenOpenTag>>>::value,
+ IntType>
+uniform_lower_bound(Tag, IntType a, IntType) {
+ return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;
+}
+
+template <typename FloatType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_floating_point<FloatType>,
+ absl::disjunction<std::is_same<Tag, IntervalOpenClosedTag>,
+ std::is_same<Tag, IntervalOpenOpenTag>>>::value,
+ FloatType>
+uniform_lower_bound(Tag, FloatType a, FloatType b) {
+ return std::nextafter(a, b);
+}
+
+template <typename NumType, typename Tag>
+typename absl::enable_if_t<
+ absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+ std::is_same<Tag, IntervalClosedOpenTag>>::value,
+ NumType>
+uniform_lower_bound(Tag, NumType a, NumType) {
+ return a;
+}
+
+template <typename IntType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ IsIntegral<IntType>,
+ absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
+ std::is_same<Tag, IntervalOpenOpenTag>>>::value,
+ IntType>
+uniform_upper_bound(Tag, IntType, IntType b) {
+ return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;
+}
+
+template <typename FloatType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_floating_point<FloatType>,
+ absl::disjunction<std::is_same<Tag, IntervalClosedOpenTag>,
+ std::is_same<Tag, IntervalOpenOpenTag>>>::value,
+ FloatType>
+uniform_upper_bound(Tag, FloatType, FloatType b) {
+ return b;
+}
+
+template <typename IntType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ IsIntegral<IntType>,
+ absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+ std::is_same<Tag, IntervalOpenClosedTag>>>::value,
+ IntType>
+uniform_upper_bound(Tag, IntType, IntType b) {
+ return b;
+}
+
+template <typename FloatType, typename Tag>
+typename absl::enable_if_t<
+ absl::conjunction<
+ std::is_floating_point<FloatType>,
+ absl::disjunction<std::is_same<Tag, IntervalClosedClosedTag>,
+ std::is_same<Tag, IntervalOpenClosedTag>>>::value,
+ FloatType>
+uniform_upper_bound(Tag, FloatType, FloatType b) {
+ return std::nextafter(b, (std::numeric_limits<FloatType>::max)());
+}
+
+// Returns whether the bounds are valid for the underlying distribution.
+// Inputs must have already been resolved via uniform_*_bound calls.
+//
+// The c++ standard constraints in [rand.dist.uni.int] are listed as:
+// requires: lo <= hi.
+//
+// In the uniform_int_distrubtion, {lo, hi} are closed, closed. Thus:
+// [0, 0] is legal.
+// [0, 0) is not legal, but [0, 1) is, which translates to [0, 0].
+// (0, 1) is not legal, but (0, 2) is, which translates to [1, 1].
+// (0, 0] is not legal, but (0, 1] is, which translates to [1, 1].
+//
+// The c++ standard constraints in [rand.dist.uni.real] are listed as:
+// requires: lo <= hi.
+// requires: (hi - lo) <= numeric_limits<T>::max()
+//
+// In the uniform_real_distribution, {lo, hi} are closed, open, Thus:
+// [0, 0] is legal, which is [0, 0+epsilon).
+// [0, 0) is legal.
+// (0, 0) is not legal, but (0-epsilon, 0+epsilon) is.
+// (0, 0] is not legal, but (0, 0+epsilon] is.
+//
+template <typename FloatType>
+absl::enable_if_t<std::is_floating_point<FloatType>::value, bool>
+is_uniform_range_valid(FloatType a, FloatType b) {
+ return a <= b && std::isfinite(b - a);
+}
+
+template <typename IntType>
+absl::enable_if_t<IsIntegral<IntType>::value, bool>
+is_uniform_range_valid(IntType a, IntType b) {
+ return a <= b;
+}
+
+// UniformDistribution selects either absl::uniform_int_distribution
+// or absl::uniform_real_distribution depending on the NumType parameter.
+template <typename NumType>
+using UniformDistribution =
+ typename std::conditional<IsIntegral<NumType>::value,
+ absl::uniform_int_distribution<NumType>,
+ absl::uniform_real_distribution<NumType>>::type;
+
+// UniformDistributionWrapper is used as the underlying distribution type
+// by the absl::Uniform template function. It selects the proper Abseil
+// uniform distribution and provides constructor overloads that match the
+// expected parameter order as well as adjusting distribution bounds based
+// on the tag.
+template <typename NumType>
+struct UniformDistributionWrapper : public UniformDistribution<NumType> {
+ template <typename TagType>
+ explicit UniformDistributionWrapper(TagType, NumType lo, NumType hi)
+ : UniformDistribution<NumType>(
+ uniform_lower_bound<NumType>(TagType{}, lo, hi),
+ uniform_upper_bound<NumType>(TagType{}, lo, hi)) {}
+
+ explicit UniformDistributionWrapper(NumType lo, NumType hi)
+ : UniformDistribution<NumType>(
+ uniform_lower_bound<NumType>(IntervalClosedOpenTag(), lo, hi),
+ uniform_upper_bound<NumType>(IntervalClosedOpenTag(), lo, hi)) {}
+
+ explicit UniformDistributionWrapper()
+ : UniformDistribution<NumType>(std::numeric_limits<NumType>::lowest(),
+ (std::numeric_limits<NumType>::max)()) {}
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_UNIFORM_HELPER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h b/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h
new file mode 100644
index 0000000000..4afff8f604
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/log_uniform_int_distribution.h
@@ -0,0 +1,256 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
+#define ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
+
+#include <algorithm>
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <ostream>
+#include <type_traits>
+
+#include "absl/numeric/bits.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/uniform_int_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// log_uniform_int_distribution:
+//
+// Returns a random variate R in range [min, max] such that
+// floor(log(R-min, base)) is uniformly distributed.
+// We ensure uniformity by discretization using the
+// boundary sets [0, 1, base, base * base, ... min(base*n, max)]
+//
+template <typename IntType = int>
+class log_uniform_int_distribution {
+ private:
+ using unsigned_type =
+ typename random_internal::make_unsigned_bits<IntType>::type;
+
+ public:
+ using result_type = IntType;
+
+ class param_type {
+ public:
+ using distribution_type = log_uniform_int_distribution;
+
+ explicit param_type(
+ result_type min = 0,
+ result_type max = (std::numeric_limits<result_type>::max)(),
+ result_type base = 2)
+ : min_(min),
+ max_(max),
+ base_(base),
+ range_(static_cast<unsigned_type>(max_) -
+ static_cast<unsigned_type>(min_)),
+ log_range_(0) {
+ assert(max_ >= min_);
+ assert(base_ > 1);
+
+ if (base_ == 2) {
+ // Determine where the first set bit is on range(), giving a log2(range)
+ // value which can be used to construct bounds.
+ log_range_ = (std::min)(random_internal::BitWidth(range()),
+ std::numeric_limits<unsigned_type>::digits);
+ } else {
+ // NOTE: Computing the logN(x) introduces error from 2 sources:
+ // 1. Conversion of int to double loses precision for values >=
+ // 2^53, which may cause some log() computations to operate on
+ // different values.
+ // 2. The error introduced by the division will cause the result
+ // to differ from the expected value.
+ //
+ // Thus a result which should equal K may equal K +/- epsilon,
+ // which can eliminate some values depending on where the bounds fall.
+ const double inv_log_base = 1.0 / std::log(static_cast<double>(base_));
+ const double log_range = std::log(static_cast<double>(range()) + 0.5);
+ log_range_ = static_cast<int>(std::ceil(inv_log_base * log_range));
+ }
+ }
+
+ result_type(min)() const { return min_; }
+ result_type(max)() const { return max_; }
+ result_type base() const { return base_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.min_ == b.min_ && a.max_ == b.max_ && a.base_ == b.base_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class log_uniform_int_distribution;
+
+ int log_range() const { return log_range_; }
+ unsigned_type range() const { return range_; }
+
+ result_type min_;
+ result_type max_;
+ result_type base_;
+ unsigned_type range_; // max - min
+ int log_range_; // ceil(logN(range_))
+
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Class-template absl::log_uniform_int_distribution<> must be "
+ "parameterized using an integral type.");
+ };
+
+ log_uniform_int_distribution() : log_uniform_int_distribution(0) {}
+
+ explicit log_uniform_int_distribution(
+ result_type min,
+ result_type max = (std::numeric_limits<result_type>::max)(),
+ result_type base = 2)
+ : param_(min, max, base) {}
+
+ explicit log_uniform_int_distribution(const param_type& p) : param_(p) {}
+
+ void reset() {}
+
+ // generating functions
+ template <typename URBG>
+ result_type operator()(URBG& g) { // NOLINT(runtime/references)
+ return (*this)(g, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ return static_cast<result_type>((p.min)() + Generate(g, p));
+ }
+
+ result_type(min)() const { return (param_.min)(); }
+ result_type(max)() const { return (param_.max)(); }
+ result_type base() const { return param_.base(); }
+
+ param_type param() const { return param_; }
+ void param(const param_type& p) { param_ = p; }
+
+ friend bool operator==(const log_uniform_int_distribution& a,
+ const log_uniform_int_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const log_uniform_int_distribution& a,
+ const log_uniform_int_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ // Returns a log-uniform variate in the range [0, p.range()]. The caller
+ // should add min() to shift the result to the correct range.
+ template <typename URNG>
+ unsigned_type Generate(URNG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ param_type param_;
+};
+
+template <typename IntType>
+template <typename URBG>
+typename log_uniform_int_distribution<IntType>::unsigned_type
+log_uniform_int_distribution<IntType>::Generate(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ // sample e over [0, log_range]. Map the results of e to this:
+ // 0 => 0
+ // 1 => [1, b-1]
+ // 2 => [b, (b^2)-1]
+ // n => [b^(n-1)..(b^n)-1]
+ const int e = absl::uniform_int_distribution<int>(0, p.log_range())(g);
+ if (e == 0) {
+ return 0;
+ }
+ const int d = e - 1;
+
+ unsigned_type base_e, top_e;
+ if (p.base() == 2) {
+ base_e = static_cast<unsigned_type>(1) << d;
+
+ top_e = (e >= std::numeric_limits<unsigned_type>::digits)
+ ? (std::numeric_limits<unsigned_type>::max)()
+ : (static_cast<unsigned_type>(1) << e) - 1;
+ } else {
+ const double r = std::pow(static_cast<double>(p.base()), d);
+ const double s = (r * static_cast<double>(p.base())) - 1.0;
+
+ base_e =
+ (r > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
+ ? (std::numeric_limits<unsigned_type>::max)()
+ : static_cast<unsigned_type>(r);
+
+ top_e =
+ (s > static_cast<double>((std::numeric_limits<unsigned_type>::max)()))
+ ? (std::numeric_limits<unsigned_type>::max)()
+ : static_cast<unsigned_type>(s);
+ }
+
+ const unsigned_type lo = (base_e >= p.range()) ? p.range() : base_e;
+ const unsigned_type hi = (top_e >= p.range()) ? p.range() : top_e;
+
+ // choose uniformly over [lo, hi]
+ return absl::uniform_int_distribution<result_type>(
+ static_cast<result_type>(lo), static_cast<result_type>(hi))(g);
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const log_uniform_int_distribution<IntType>& x) {
+ using stream_type =
+ typename random_internal::stream_format_type<IntType>::type;
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os << static_cast<stream_type>((x.min)()) << os.fill()
+ << static_cast<stream_type>((x.max)()) << os.fill()
+ << static_cast<stream_type>(x.base());
+ return os;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ log_uniform_int_distribution<IntType>& x) { // NOLINT(runtime/references)
+ using param_type = typename log_uniform_int_distribution<IntType>::param_type;
+ using result_type =
+ typename log_uniform_int_distribution<IntType>::result_type;
+ using stream_type =
+ typename random_internal::stream_format_type<IntType>::type;
+
+ stream_type min;
+ stream_type max;
+ stream_type base;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ is >> min >> max >> base;
+ if (!is.fail()) {
+ x.param(param_type(static_cast<result_type>(min),
+ static_cast<result_type>(max),
+ static_cast<result_type>(base)));
+ }
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_LOG_UNIFORM_INT_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h b/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h
new file mode 100644
index 0000000000..b379262cb6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/mock_distributions.h
@@ -0,0 +1,269 @@
+// Copyright 2018 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: mock_distributions.h
+// -----------------------------------------------------------------------------
+//
+// This file contains mock distribution functions for use alongside an
+// `absl::MockingBitGen` object within the Googletest testing framework. Such
+// mocks are useful to provide deterministic values as return values within
+// (otherwise random) Abseil distribution functions.
+//
+// The return type of each function is a mock expectation object which
+// is used to set the match result.
+//
+// More information about the Googletest testing framework is available at
+// https://github.com/google/googletest
+//
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockUniform<int>(), Call(mock, 1, 1000))
+// .WillRepeatedly(testing::ReturnRoundRobin({20, 40}));
+//
+// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
+// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
+// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 20);
+// EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000), 40);
+
+#ifndef ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
+#define ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
+
+#include "absl/base/config.h"
+#include "absl/random/bernoulli_distribution.h"
+#include "absl/random/beta_distribution.h"
+#include "absl/random/distributions.h"
+#include "absl/random/exponential_distribution.h"
+#include "absl/random/gaussian_distribution.h"
+#include "absl/random/internal/mock_overload_set.h"
+#include "absl/random/internal/mock_validators.h"
+#include "absl/random/log_uniform_int_distribution.h"
+#include "absl/random/mocking_bit_gen.h"
+#include "absl/random/poisson_distribution.h"
+#include "absl/random/zipf_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// absl::MockUniform
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Uniform.
+//
+// `absl::MockUniform` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(mock))
+// .WillOnce(Return(123456));
+// auto x = absl::Uniform<uint32_t>(mock);
+// assert(x == 123456)
+//
+template <typename R>
+using MockUniform = random_internal::MockOverloadSetWithValidator<
+ random_internal::UniformDistributionWrapper<R>,
+ random_internal::UniformDistributionValidator<R>,
+ R(IntervalClosedOpenTag, MockingBitGen&, R, R),
+ R(IntervalClosedClosedTag, MockingBitGen&, R, R),
+ R(IntervalOpenOpenTag, MockingBitGen&, R, R),
+ R(IntervalOpenClosedTag, MockingBitGen&, R, R), R(MockingBitGen&, R, R),
+ R(MockingBitGen&)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockBernoulli
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Bernoulli.
+//
+// `absl::MockBernoulli` is a class used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockBernoulli(), Call(mock, testing::_))
+// .WillOnce(Return(false));
+// assert(absl::Bernoulli(mock, 0.5) == false);
+//
+using MockBernoulli =
+ random_internal::MockOverloadSet<absl::bernoulli_distribution,
+ bool(MockingBitGen&, double)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockBeta
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Beta.
+//
+// `absl::MockBeta` is a class used in conjunction with Googletest's `ON_CALL()`
+// and `EXPECT_CALL()` macros. To use it, default-construct an instance of it
+// inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the same way one
+// would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockBeta(), Call(mock, 3.0, 2.0))
+// .WillOnce(Return(0.567));
+// auto x = absl::Beta<double>(mock, 3.0, 2.0);
+// assert(x == 0.567);
+//
+template <typename RealType>
+using MockBeta =
+ random_internal::MockOverloadSet<absl::beta_distribution<RealType>,
+ RealType(MockingBitGen&, RealType,
+ RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockExponential
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Exponential.
+//
+// `absl::MockExponential` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockExponential<double>(), Call(mock, 0.5))
+// .WillOnce(Return(12.3456789));
+// auto x = absl::Exponential<double>(mock, 0.5);
+// assert(x == 12.3456789)
+//
+template <typename RealType>
+using MockExponential =
+ random_internal::MockOverloadSet<absl::exponential_distribution<RealType>,
+ RealType(MockingBitGen&, RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockGaussian
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Gaussian.
+//
+// `absl::MockGaussian` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockGaussian<double>(), Call(mock, 16.3, 3.3))
+// .WillOnce(Return(12.3456789));
+// auto x = absl::Gaussian<double>(mock, 16.3, 3.3);
+// assert(x == 12.3456789)
+//
+template <typename RealType>
+using MockGaussian =
+ random_internal::MockOverloadSet<absl::gaussian_distribution<RealType>,
+ RealType(MockingBitGen&, RealType,
+ RealType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockLogUniform
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::LogUniform.
+//
+// `absl::MockLogUniform` is a class template used in conjunction with
+// Googletest's `ON_CALL()` and `EXPECT_CALL()` macros. To use it,
+// default-construct an instance of it inside `ON_CALL()` or `EXPECT_CALL()`,
+// and use `Call(...)` the same way one would define mocks on a
+// Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockLogUniform<int>(), Call(mock, 10, 10000, 10))
+// .WillOnce(Return(1221));
+// auto x = absl::LogUniform<int>(mock, 10, 10000, 10);
+// assert(x == 1221)
+//
+template <typename IntType>
+using MockLogUniform = random_internal::MockOverloadSet<
+ absl::log_uniform_int_distribution<IntType>,
+ IntType(MockingBitGen&, IntType, IntType, IntType)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockPoisson
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Poisson.
+//
+// `absl::MockPoisson` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockPoisson<int>(), Call(mock, 2.0))
+// .WillOnce(Return(1221));
+// auto x = absl::Poisson<int>(mock, 2.0);
+// assert(x == 1221)
+//
+template <typename IntType>
+using MockPoisson =
+ random_internal::MockOverloadSet<absl::poisson_distribution<IntType>,
+ IntType(MockingBitGen&, double)>;
+
+// -----------------------------------------------------------------------------
+// absl::MockZipf
+// -----------------------------------------------------------------------------
+//
+// Matches calls to absl::Zipf.
+//
+// `absl::MockZipf` is a class template used in conjunction with Googletest's
+// `ON_CALL()` and `EXPECT_CALL()` macros. To use it, default-construct an
+// instance of it inside `ON_CALL()` or `EXPECT_CALL()`, and use `Call(...)` the
+// same way one would define mocks on a Googletest `MockFunction()`.
+//
+// Example:
+//
+// absl::MockingBitGen mock;
+// EXPECT_CALL(absl::MockZipf<int>(), Call(mock, 1000000, 2.0, 1.0))
+// .WillOnce(Return(1221));
+// auto x = absl::Zipf<int>(mock, 1000000, 2.0, 1.0);
+// assert(x == 1221)
+//
+template <typename IntType>
+using MockZipf =
+ random_internal::MockOverloadSet<absl::zipf_distribution<IntType>,
+ IntType(MockingBitGen&, IntType, double,
+ double)>;
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_MOCK_DISTRIBUTIONS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h b/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h
new file mode 100644
index 0000000000..041989de20
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/mocking_bit_gen.h
@@ -0,0 +1,254 @@
+// Copyright 2018 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.
+//
+// -----------------------------------------------------------------------------
+// mocking_bit_gen.h
+// -----------------------------------------------------------------------------
+//
+// This file includes an `absl::MockingBitGen` class to use as a mock within the
+// Googletest testing framework. Such a mock is useful to provide deterministic
+// values as return values within (otherwise random) Abseil distribution
+// functions. Such determinism within a mock is useful within testing frameworks
+// to test otherwise indeterminate APIs.
+//
+// More information about the Googletest testing framework is available at
+// https://github.com/google/googletest
+
+#ifndef ABSL_RANDOM_MOCKING_BIT_GEN_H_
+#define ABSL_RANDOM_MOCKING_BIT_GEN_H_
+
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/mock_helpers.h"
+#include "absl/random/random.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class BitGenRef;
+
+namespace random_internal {
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
+// Implements MockingBitGen with an option to turn on extra validation.
+template <bool EnableValidation>
+class MockingBitGenImpl {
+ public:
+ MockingBitGenImpl() = default;
+ ~MockingBitGenImpl() = default;
+
+ // URBG interface
+ using result_type = absl::BitGen::result_type;
+
+ static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+ static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+ result_type operator()() { return gen_(); }
+
+ private:
+ // GetMockFnType returns the testing::MockFunction for a result and tuple.
+ // This method only exists for type deduction and is otherwise unimplemented.
+ template <typename ResultT, typename... Args>
+ static auto GetMockFnType(ResultT, std::tuple<Args...>)
+ -> ::testing::MockFunction<ResultT(Args...)>;
+
+ // MockFnCaller is a helper method for use with absl::apply to
+ // apply an ArgTupleT to a compatible MockFunction.
+ // NOTE: MockFnCaller is essentially equivalent to the lambda:
+ // [fn](auto... args) { return fn->Call(std::move(args)...)}
+ // however that fails to build on some supported platforms.
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename Tuple>
+ struct MockFnCaller;
+
+ // specialization for std::tuple.
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename... Args>
+ struct MockFnCaller<MockFnType, ValidatorT, ResultT, std::tuple<Args...>> {
+ MockFnType* fn;
+ inline ResultT operator()(Args... args) {
+ ResultT result = fn->Call(args...);
+ ValidatorT::Validate(result, args...);
+ return result;
+ }
+ };
+
+ // FunctionHolder owns a particular ::testing::MockFunction associated with
+ // a mocked type signature, and implement the type-erased Apply call, which
+ // applies type-erased arguments to the mock.
+ class FunctionHolder {
+ public:
+ virtual ~FunctionHolder() = default;
+
+ // Call is a dispatch function which converts the
+ // generic type-erased parameters into a specific mock invocation call.
+ virtual void Apply(/*ArgTupleT*/ void* args_tuple,
+ /*ResultT*/ void* result) = 0;
+ };
+
+ template <typename MockFnType, typename ValidatorT, typename ResultT,
+ typename ArgTupleT>
+ class FunctionHolderImpl final : public FunctionHolder {
+ public:
+ void Apply(void* args_tuple, void* result) final {
+ // Requires tuple_args to point to a ArgTupleT, which is a
+ // std::tuple<Args...> used to invoke the mock function. Requires result
+ // to point to a ResultT, which is the result of the call.
+ *static_cast<ResultT*>(result) = absl::apply(
+ MockFnCaller<MockFnType, ValidatorT, ResultT, ArgTupleT>{&mock_fn_},
+ *static_cast<ArgTupleT*>(args_tuple));
+ }
+
+ MockFnType mock_fn_;
+ };
+
+ // MockingBitGen::RegisterMock
+ //
+ // RegisterMock<ResultT, ArgTupleT>(FastTypeIdType) is the main extension
+ // point for extending the MockingBitGen framework. It provides a mechanism to
+ // install a mock expectation for a function like ResultT(Args...) keyed by
+ // type_idex onto the MockingBitGen context. The key is that the type_index
+ // used to register must match the type index used to call the mock.
+ //
+ // The returned MockFunction<...> type can be used to setup additional
+ // distribution parameters of the expectation.
+ template <typename ResultT, typename ArgTupleT, typename SelfT,
+ typename ValidatorT>
+ auto RegisterMock(SelfT&, base_internal::FastTypeIdType type, ValidatorT)
+ -> decltype(GetMockFnType(std::declval<ResultT>(),
+ std::declval<ArgTupleT>()))& {
+ using ActualValidatorT =
+ std::conditional_t<EnableValidation, ValidatorT, NoOpValidator>;
+ using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
+ std::declval<ArgTupleT>()));
+
+ using WrappedFnType = absl::conditional_t<
+ std::is_same<SelfT, ::testing::NiceMock<MockingBitGenImpl>>::value,
+ ::testing::NiceMock<MockFnType>,
+ absl::conditional_t<
+ std::is_same<SelfT, ::testing::NaggyMock<MockingBitGenImpl>>::value,
+ ::testing::NaggyMock<MockFnType>,
+ absl::conditional_t<
+ std::is_same<SelfT,
+ ::testing::StrictMock<MockingBitGenImpl>>::value,
+ ::testing::StrictMock<MockFnType>, MockFnType>>>;
+
+ using ImplT =
+ FunctionHolderImpl<WrappedFnType, ActualValidatorT, ResultT, ArgTupleT>;
+ auto& mock = mocks_[type];
+ if (!mock) {
+ mock = absl::make_unique<ImplT>();
+ }
+ return static_cast<ImplT*>(mock.get())->mock_fn_;
+ }
+
+ // MockingBitGen::InvokeMock
+ //
+ // InvokeMock(FastTypeIdType, args, result) is the entrypoint for invoking
+ // mocks registered on MockingBitGen.
+ //
+ // When no mocks are registered on the provided FastTypeIdType, returns false.
+ // Otherwise attempts to invoke the mock function ResultT(Args...) that
+ // was previously registered via the type_index.
+ // Requires tuple_args to point to a ArgTupleT, which is a std::tuple<Args...>
+ // used to invoke the mock function.
+ // Requires result to point to a ResultT, which is the result of the call.
+ inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
+ void* result) {
+ // Trigger a mock, if there exists one that matches `param`.
+ auto it = mocks_.find(type);
+ if (it == mocks_.end()) return false;
+ it->second->Apply(args_tuple, result);
+ return true;
+ }
+
+ absl::flat_hash_map<base_internal::FastTypeIdType,
+ std::unique_ptr<FunctionHolder>>
+ mocks_;
+ absl::BitGen gen_;
+
+ template <typename>
+ friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
+ friend class ::absl::BitGenRef; // for InvokeMock
+ friend class ::absl::random_internal::MockHelpers; // for RegisterMock,
+ // InvokeMock
+};
+
+} // namespace random_internal
+
+// MockingBitGen
+//
+// `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
+// which can act in place of an `absl::BitGen` URBG within tests using the
+// Googletest testing framework.
+//
+// Usage:
+//
+// Use an `absl::MockingBitGen` along with a mock distribution object (within
+// mock_distributions.h) inside Googletest constructs such as ON_CALL(),
+// EXPECT_TRUE(), etc. to produce deterministic results conforming to the
+// distribution's API contract.
+//
+// Example:
+//
+// // Mock a call to an `absl::Bernoulli` distribution using Googletest
+// absl::MockingBitGen bitgen;
+//
+// ON_CALL(absl::MockBernoulli(), Call(bitgen, 0.5))
+// .WillByDefault(testing::Return(true));
+// EXPECT_TRUE(absl::Bernoulli(bitgen, 0.5));
+//
+// // Mock a call to an `absl::Uniform` distribution within Googletest
+// absl::MockingBitGen bitgen;
+//
+// ON_CALL(absl::MockUniform<int>(), Call(bitgen, testing::_, testing::_))
+// .WillByDefault([] (int low, int high) {
+// return low + (high - low) / 2;
+// });
+//
+// EXPECT_EQ(absl::Uniform<int>(gen, 0, 10), 5);
+// EXPECT_EQ(absl::Uniform<int>(gen, 30, 40), 35);
+//
+// At this time, only mock distributions supplied within the Abseil random
+// library are officially supported.
+//
+// EXPECT_CALL and ON_CALL need to be made within the same DLL component as
+// the call to absl::Uniform and related methods, otherwise mocking will fail
+// since the underlying implementation creates a type-specific pointer which
+// will be distinct across different DLL boundaries.
+//
+using MockingBitGen = random_internal::MockingBitGenImpl<true>;
+
+// UnvalidatedMockingBitGen
+//
+// UnvalidatedMockingBitGen is a variant of MockingBitGen which does no extra
+// validation.
+using UnvalidatedMockingBitGen ABSL_DEPRECATED("Use MockingBitGen instead") =
+ random_internal::MockingBitGenImpl<false>;
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h b/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h
new file mode 100644
index 0000000000..f4573082e1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/poisson_distribution.h
@@ -0,0 +1,261 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_POISSON_DISTRIBUTION_H_
+#define ABSL_RANDOM_POISSON_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <ostream>
+#include <type_traits>
+
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/generate_real.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::poisson_distribution:
+// Generates discrete variates conforming to a Poisson distribution.
+// p(n) = (mean^n / n!) exp(-mean)
+//
+// Depending on the parameter, the distribution selects one of the following
+// algorithms:
+// * The standard algorithm, attributed to Knuth, extended using a split method
+// for larger values
+// * The "Ratio of Uniforms as a convenient method for sampling from classical
+// discrete distributions", Stadlober, 1989.
+// http://www.sciencedirect.com/science/article/pii/0377042790903495
+//
+// NOTE: param_type.mean() is a double, which permits values larger than
+// poisson_distribution<IntType>::max(), however this should be avoided and
+// the distribution results are limited to the max() value.
+//
+// The goals of this implementation are to provide good performance while still
+// beig thread-safe: This limits the implementation to not using lgamma provided
+// by <math.h>.
+//
+template <typename IntType = int>
+class poisson_distribution {
+ public:
+ using result_type = IntType;
+
+ class param_type {
+ public:
+ using distribution_type = poisson_distribution;
+ explicit param_type(double mean = 1.0);
+
+ double mean() const { return mean_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.mean_ == b.mean_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class poisson_distribution;
+
+ double mean_;
+ double emu_; // e ^ -mean_
+ double lmu_; // ln(mean_)
+ double s_;
+ double log_k_;
+ int split_;
+
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Class-template absl::poisson_distribution<> must be "
+ "parameterized using an integral type.");
+ };
+
+ poisson_distribution() : poisson_distribution(1.0) {}
+
+ explicit poisson_distribution(double mean) : param_(mean) {}
+
+ explicit poisson_distribution(const param_type& p) : param_(p) {}
+
+ void reset() {}
+
+ // generating functions
+ template <typename URBG>
+ result_type operator()(URBG& g) { // NOLINT(runtime/references)
+ return (*this)(g, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ param_type param() const { return param_; }
+ void param(const param_type& p) { param_ = p; }
+
+ result_type(min)() const { return 0; }
+ result_type(max)() const { return (std::numeric_limits<result_type>::max)(); }
+
+ double mean() const { return param_.mean(); }
+
+ friend bool operator==(const poisson_distribution& a,
+ const poisson_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const poisson_distribution& a,
+ const poisson_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+ random_internal::FastUniformBits<uint64_t> fast_u64_;
+};
+
+// -----------------------------------------------------------------------------
+// Implementation details follow
+// -----------------------------------------------------------------------------
+
+template <typename IntType>
+poisson_distribution<IntType>::param_type::param_type(double mean)
+ : mean_(mean), split_(0) {
+ assert(mean >= 0);
+ assert(mean <=
+ static_cast<double>((std::numeric_limits<result_type>::max)()));
+ // As a defensive measure, avoid large values of the mean. The rejection
+ // algorithm used does not support very large values well. It my be worth
+ // changing algorithms to better deal with these cases.
+ assert(mean <= 1e10);
+ if (mean_ < 10) {
+ // For small lambda, use the knuth method.
+ split_ = 1;
+ emu_ = std::exp(-mean_);
+ } else if (mean_ <= 50) {
+ // Use split-knuth method.
+ split_ = 1 + static_cast<int>(mean_ / 10.0);
+ emu_ = std::exp(-mean_ / static_cast<double>(split_));
+ } else {
+ // Use ratio of uniforms method.
+ constexpr double k2E = 0.7357588823428846;
+ constexpr double kSA = 0.4494580810294493;
+
+ lmu_ = std::log(mean_);
+ double a = mean_ + 0.5;
+ s_ = kSA + std::sqrt(k2E * a);
+ const double mode = std::ceil(mean_) - 1;
+ log_k_ = lmu_ * mode - absl::random_internal::StirlingLogFactorial(mode);
+ }
+}
+
+template <typename IntType>
+template <typename URBG>
+typename poisson_distribution<IntType>::result_type
+poisson_distribution<IntType>::operator()(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+ using random_internal::GenerateSignedTag;
+
+ if (p.split_ != 0) {
+ // Use Knuth's algorithm with range splitting to avoid floating-point
+ // errors. Knuth's algorithm is: Ui is a sequence of uniform variates on
+ // (0,1); return the number of variates required for product(Ui) <
+ // exp(-lambda).
+ //
+ // The expected number of variates required for Knuth's method can be
+ // computed as follows:
+ // The expected value of U is 0.5, so solving for 0.5^n < exp(-lambda) gives
+ // the expected number of uniform variates
+ // required for a given lambda, which is:
+ // lambda = [2, 5, 9, 10, 11, 12, 13, 14, 15, 16, 17]
+ // n = [3, 8, 13, 15, 16, 18, 19, 21, 22, 24, 25]
+ //
+ result_type n = 0;
+ for (int split = p.split_; split > 0; --split) {
+ double r = 1.0;
+ do {
+ r *= GenerateRealFromBits<double, GeneratePositiveTag, true>(
+ fast_u64_(g)); // U(-1, 0)
+ ++n;
+ } while (r > p.emu_);
+ --n;
+ }
+ return n;
+ }
+
+ // Use ratio of uniforms method.
+ //
+ // Let u ~ Uniform(0, 1), v ~ Uniform(-1, 1),
+ // a = lambda + 1/2,
+ // s = 1.5 - sqrt(3/e) + sqrt(2(lambda + 1/2)/e),
+ // x = s * v/u + a.
+ // P(floor(x) = k | u^2 < f(floor(x))/k), where
+ // f(m) = lambda^m exp(-lambda)/ m!, for 0 <= m, and f(m) = 0 otherwise,
+ // and k = max(f).
+ const double a = p.mean_ + 0.5;
+ for (;;) {
+ const double u = GenerateRealFromBits<double, GeneratePositiveTag, false>(
+ fast_u64_(g)); // U(0, 1)
+ const double v = GenerateRealFromBits<double, GenerateSignedTag, false>(
+ fast_u64_(g)); // U(-1, 1)
+
+ const double x = std::floor(p.s_ * v / u + a);
+ if (x < 0) continue; // f(negative) = 0
+ const double rhs = x * p.lmu_;
+ // clang-format off
+ double s = (x <= 1.0) ? 0.0
+ : (x == 2.0) ? 0.693147180559945
+ : absl::random_internal::StirlingLogFactorial(x);
+ // clang-format on
+ const double lhs = 2.0 * std::log(u) + p.log_k_ + s;
+ if (lhs < rhs) {
+ return x > static_cast<double>((max)())
+ ? (max)()
+ : static_cast<result_type>(x); // f(x)/k >= u^2
+ }
+ }
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const poisson_distribution<IntType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<double>::kPrecision);
+ os << x.mean();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ poisson_distribution<IntType>& x) { // NOLINT(runtime/references)
+ using param_type = typename poisson_distribution<IntType>::param_type;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ double mean = random_internal::read_floating_point<double>(is);
+ if (!is.fail()) {
+ x.param(param_type(mean));
+ }
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_POISSON_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/random.h b/contrib/restricted/abseil-cpp/absl/random/random.h
new file mode 100644
index 0000000000..767208671c
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/random.h
@@ -0,0 +1,189 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: random.h
+// -----------------------------------------------------------------------------
+//
+// This header defines the recommended Uniform Random Bit Generator (URBG)
+// types for use within the Abseil Random library. These types are not
+// suitable for security-related use-cases, but should suffice for most other
+// uses of generating random values.
+//
+// The Abseil random library provides the following URBG types:
+//
+// * BitGen, a good general-purpose bit generator, optimized for generating
+// random (but not cryptographically secure) values
+// * InsecureBitGen, a slightly faster, though less random, bit generator, for
+// cases where the existing BitGen is a drag on performance.
+
+#ifndef ABSL_RANDOM_RANDOM_H_
+#define ABSL_RANDOM_RANDOM_H_
+
+#include <random>
+
+#include "absl/random/distributions.h" // IWYU pragma: export
+#include "absl/random/internal/nonsecure_base.h" // IWYU pragma: export
+#include "absl/random/internal/pcg_engine.h" // IWYU pragma: export
+#include "absl/random/internal/pool_urbg.h"
+#include "absl/random/internal/randen_engine.h"
+#include "absl/random/seed_sequences.h" // IWYU pragma: export
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// absl::BitGen
+// -----------------------------------------------------------------------------
+//
+// `absl::BitGen` is a general-purpose random bit generator for generating
+// random values for use within the Abseil random library. Typically, you use a
+// bit generator in combination with a distribution to provide random values.
+//
+// Example:
+//
+// // Create an absl::BitGen. There is no need to seed this bit generator.
+// absl::BitGen gen;
+//
+// // Generate an integer value in the closed interval [1,6]
+// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);
+//
+// `absl::BitGen` is seeded by default with non-deterministic data to produce
+// different sequences of random values across different instances, including
+// different binary invocations. This behavior is different than the standard
+// library bit generators, which use golden values as their seeds. Default
+// construction intentionally provides no stability guarantees, to avoid
+// accidental dependence on such a property.
+//
+// `absl::BitGen` may be constructed with an optional seed sequence type,
+// conforming to [rand.req.seed_seq], which will be mixed with additional
+// non-deterministic data as detailed below.
+//
+// Example:
+//
+// // Create an absl::BitGen using an std::seed_seq seed sequence
+// std::seed_seq seq{1,2,3};
+// absl::BitGen gen_with_seed(seq);
+//
+// // Generate an integer value in the closed interval [1,6]
+// int die_roll2 = absl::uniform_int_distribution<int>(1, 6)(gen_with_seed);
+//
+// Constructing two `absl::BitGen`s with the same seed sequence in the same
+// process will produce the same sequence of variates, but need not do so across
+// multiple processes even if they're executing the same binary.
+//
+// `absl::BitGen` meets the requirements of the Uniform Random Bit Generator
+// (URBG) concept as per the C++17 standard [rand.req.urng] though differs
+// slightly with [rand.req.eng]. Like its standard library equivalents (e.g.
+// `std::mersenne_twister_engine`) `absl::BitGen` is not cryptographically
+// secure.
+//
+// This type has been optimized to perform better than Mersenne Twister
+// (https://en.wikipedia.org/wiki/Mersenne_Twister) and many other complex URBG
+// types on modern x86, ARM, and PPC architectures.
+//
+// This type is thread-compatible, but not thread-safe.
+
+// ---------------------------------------------------------------------------
+// absl::BitGen member functions
+// ---------------------------------------------------------------------------
+
+// absl::BitGen::operator()()
+//
+// Calls the BitGen, returning a generated value.
+
+// absl::BitGen::min()
+//
+// Returns the smallest possible value from this bit generator.
+
+// absl::BitGen::max()
+//
+// Returns the largest possible value from this bit generator.
+
+// absl::BitGen::discard(num)
+//
+// Advances the internal state of this bit generator by `num` times, and
+// discards the intermediate results.
+// ---------------------------------------------------------------------------
+
+using BitGen = random_internal::NonsecureURBGBase<
+ random_internal::randen_engine<uint64_t>>;
+
+// -----------------------------------------------------------------------------
+// absl::InsecureBitGen
+// -----------------------------------------------------------------------------
+//
+// `absl::InsecureBitGen` is an efficient random bit generator for generating
+// random values, recommended only for performance-sensitive use cases where
+// `absl::BitGen` is not satisfactory when compute-bounded by bit generation
+// costs.
+//
+// Example:
+//
+// // Create an absl::InsecureBitGen
+// absl::InsecureBitGen gen;
+// for (size_t i = 0; i < 1000000; i++) {
+//
+// // Generate a bunch of random values from some complex distribution
+// auto my_rnd = some_distribution(gen, 1, 1000);
+// }
+//
+// Like `absl::BitGen`, `absl::InsecureBitGen` is seeded by default with
+// non-deterministic data to produce different sequences of random values across
+// different instances, including different binary invocations. (This behavior
+// is different than the standard library bit generators, which use golden
+// values as their seeds.)
+//
+// `absl::InsecureBitGen` may be constructed with an optional seed sequence
+// type, conforming to [rand.req.seed_seq], which will be mixed with additional
+// non-deterministic data, as detailed in the `absl::BitGen` comment.
+//
+// `absl::InsecureBitGen` meets the requirements of the Uniform Random Bit
+// Generator (URBG) concept as per the C++17 standard [rand.req.urng] though
+// its implementation differs slightly with [rand.req.eng]. Like its standard
+// library equivalents (e.g. `std::mersenne_twister_engine`)
+// `absl::InsecureBitGen` is not cryptographically secure.
+//
+// Prefer `absl::BitGen` over `absl::InsecureBitGen` as the general type is
+// often fast enough for the vast majority of applications.
+
+using InsecureBitGen =
+ random_internal::NonsecureURBGBase<random_internal::pcg64_2018_engine>;
+
+// ---------------------------------------------------------------------------
+// absl::InsecureBitGen member functions
+// ---------------------------------------------------------------------------
+
+// absl::InsecureBitGen::operator()()
+//
+// Calls the InsecureBitGen, returning a generated value.
+
+// absl::InsecureBitGen::min()
+//
+// Returns the smallest possible value from this bit generator.
+
+// absl::InsecureBitGen::max()
+//
+// Returns the largest possible value from this bit generator.
+
+// absl::InsecureBitGen::discard(num)
+//
+// Advances the internal state of this bit generator by `num` times, and
+// discards the intermediate results.
+// ---------------------------------------------------------------------------
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_RANDOM_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h b/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h
new file mode 100644
index 0000000000..196833415e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/uniform_real_distribution.h
@@ -0,0 +1,202 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: uniform_real_distribution.h
+// -----------------------------------------------------------------------------
+//
+// This header defines a class for representing a uniform floating-point
+// distribution over a half-open interval [a,b). You use this distribution in
+// combination with an Abseil random bit generator to produce random values
+// according to the rules of the distribution.
+//
+// `absl::uniform_real_distribution` is a drop-in replacement for the C++11
+// `std::uniform_real_distribution` [rand.dist.uni.real] but is considerably
+// faster than the libstdc++ implementation.
+//
+// Note: the standard-library version may occasionally return `1.0` when
+// default-initialized. See https://bugs.llvm.org//show_bug.cgi?id=18767
+// `absl::uniform_real_distribution` does not exhibit this behavior.
+
+#ifndef ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
+#define ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <cstdint>
+#include <istream>
+#include <limits>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/generate_real.h"
+#include "absl/random/internal/iostream_state_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::uniform_real_distribution<T>
+//
+// This distribution produces random floating-point values uniformly distributed
+// over the half-open interval [a, b).
+//
+// Example:
+//
+// absl::BitGen gen;
+//
+// // Use the distribution to produce a value between 0.0 (inclusive)
+// // and 1.0 (exclusive).
+// double value = absl::uniform_real_distribution<double>(0, 1)(gen);
+//
+template <typename RealType = double>
+class uniform_real_distribution {
+ public:
+ using result_type = RealType;
+
+ class param_type {
+ public:
+ using distribution_type = uniform_real_distribution;
+
+ explicit param_type(result_type lo = 0, result_type hi = 1)
+ : lo_(lo), hi_(hi), range_(hi - lo) {
+ // [rand.dist.uni.real] preconditions 2 & 3
+ assert(lo <= hi);
+
+ // NOTE: For integral types, we can promote the range to an unsigned type,
+ // which gives full width of the range. However for real (fp) types, this
+ // is not possible, so value generation cannot use the full range of the
+ // real type.
+ assert(range_ <= (std::numeric_limits<result_type>::max)());
+ }
+
+ result_type a() const { return lo_; }
+ result_type b() const { return hi_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.lo_ == b.lo_ && a.hi_ == b.hi_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class uniform_real_distribution;
+ result_type lo_, hi_, range_;
+
+ static_assert(std::is_floating_point<RealType>::value,
+ "Class-template absl::uniform_real_distribution<> must be "
+ "parameterized using a floating-point type.");
+ };
+
+ uniform_real_distribution() : uniform_real_distribution(0) {}
+
+ explicit uniform_real_distribution(result_type lo, result_type hi = 1)
+ : param_(lo, hi) {}
+
+ explicit uniform_real_distribution(const param_type& param) : param_(param) {}
+
+ // uniform_real_distribution<T>::reset()
+ //
+ // Resets the uniform real distribution. Note that this function has no effect
+ // because the distribution already produces independent values.
+ void reset() {}
+
+ template <typename URBG>
+ result_type operator()(URBG& gen) { // NOLINT(runtime/references)
+ return operator()(gen, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& gen, // NOLINT(runtime/references)
+ const param_type& p);
+
+ result_type a() const { return param_.a(); }
+ result_type b() const { return param_.b(); }
+
+ param_type param() const { return param_; }
+ void param(const param_type& params) { param_ = params; }
+
+ result_type(min)() const { return a(); }
+ result_type(max)() const { return b(); }
+
+ friend bool operator==(const uniform_real_distribution& a,
+ const uniform_real_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const uniform_real_distribution& a,
+ const uniform_real_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+ random_internal::FastUniformBits<uint64_t> fast_u64_;
+};
+
+// -----------------------------------------------------------------------------
+// Implementation details follow
+// -----------------------------------------------------------------------------
+template <typename RealType>
+template <typename URBG>
+typename uniform_real_distribution<RealType>::result_type
+uniform_real_distribution<RealType>::operator()(
+ URBG& gen, const param_type& p) { // NOLINT(runtime/references)
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+ using real_type =
+ absl::conditional_t<std::is_same<RealType, float>::value, float, double>;
+
+ while (true) {
+ const result_type sample =
+ GenerateRealFromBits<real_type, GeneratePositiveTag, true>(
+ fast_u64_(gen));
+ const result_type res = p.a() + (sample * p.range_);
+ if (res < p.b() || p.range_ <= 0 || !std::isfinite(p.range_)) {
+ return res;
+ }
+ // else sample rejected, try again.
+ }
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const uniform_real_distribution<RealType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
+ os << x.a() << os.fill() << x.b();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ uniform_real_distribution<RealType>& x) { // NOLINT(runtime/references)
+ using param_type = typename uniform_real_distribution<RealType>::param_type;
+ using result_type = typename uniform_real_distribution<RealType>::result_type;
+ auto saver = random_internal::make_istream_state_saver(is);
+ auto a = random_internal::read_floating_point<result_type>(is);
+ if (is.fail()) return is;
+ auto b = random_internal::read_floating_point<result_type>(is);
+ if (!is.fail()) {
+ x.param(param_type(a, b));
+ }
+ return is;
+}
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_UNIFORM_REAL_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h b/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h
new file mode 100644
index 0000000000..03497b1b26
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/random/zipf_distribution.h
@@ -0,0 +1,272 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
+#define ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <ostream>
+#include <type_traits>
+
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/uniform_real_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::zipf_distribution produces random integer-values in the range [0, k],
+// distributed according to the unnormalized discrete probability function:
+//
+// P(x) = (v + x) ^ -q
+//
+// The parameter `v` must be greater than 0 and the parameter `q` must be
+// greater than 1. If either of these parameters take invalid values then the
+// behavior is undefined.
+//
+// IntType is the result_type generated by the generator. It must be of integral
+// type; a static_assert ensures this is the case.
+//
+// The implementation is based on W.Hormann, G.Derflinger:
+//
+// "Rejection-Inversion to Generate Variates from Monotone Discrete
+// Distributions"
+//
+// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
+//
+template <typename IntType = int>
+class zipf_distribution {
+ public:
+ using result_type = IntType;
+
+ class param_type {
+ public:
+ using distribution_type = zipf_distribution;
+
+ // Preconditions: k > 0, v > 0, q > 1
+ // The precondidtions are validated when NDEBUG is not defined via
+ // a pair of assert() directives.
+ // If NDEBUG is defined and either or both of these parameters take invalid
+ // values, the behavior of the class is undefined.
+ explicit param_type(result_type k = (std::numeric_limits<IntType>::max)(),
+ double q = 2.0, double v = 1.0);
+
+ result_type k() const { return k_; }
+ double q() const { return q_; }
+ double v() const { return v_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.k_ == b.k_ && a.q_ == b.q_ && a.v_ == b.v_;
+ }
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class zipf_distribution;
+ inline double h(double x) const;
+ inline double hinv(double x) const;
+ inline double compute_s() const;
+ inline double pow_negative_q(double x) const;
+
+ // Parameters here are exactly the same as the parameters of Algorithm ZRI
+ // in the paper.
+ IntType k_;
+ double q_;
+ double v_;
+
+ double one_minus_q_; // 1-q
+ double s_;
+ double one_minus_q_inv_; // 1 / 1-q
+ double hxm_; // h(k + 0.5)
+ double hx0_minus_hxm_; // h(x0) - h(k + 0.5)
+
+ static_assert(random_internal::IsIntegral<IntType>::value,
+ "Class-template absl::zipf_distribution<> must be "
+ "parameterized using an integral type.");
+ };
+
+ zipf_distribution()
+ : zipf_distribution((std::numeric_limits<IntType>::max)()) {}
+
+ explicit zipf_distribution(result_type k, double q = 2.0, double v = 1.0)
+ : param_(k, q, v) {}
+
+ explicit zipf_distribution(const param_type& p) : param_(p) {}
+
+ void reset() {}
+
+ template <typename URBG>
+ result_type operator()(URBG& g) { // NOLINT(runtime/references)
+ return (*this)(g, param_);
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& p);
+
+ result_type k() const { return param_.k(); }
+ double q() const { return param_.q(); }
+ double v() const { return param_.v(); }
+
+ param_type param() const { return param_; }
+ void param(const param_type& p) { param_ = p; }
+
+ result_type(min)() const { return 0; }
+ result_type(max)() const { return k(); }
+
+ friend bool operator==(const zipf_distribution& a,
+ const zipf_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const zipf_distribution& a,
+ const zipf_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+};
+
+// --------------------------------------------------------------------------
+// Implementation details follow
+// --------------------------------------------------------------------------
+
+template <typename IntType>
+zipf_distribution<IntType>::param_type::param_type(
+ typename zipf_distribution<IntType>::result_type k, double q, double v)
+ : k_(k), q_(q), v_(v), one_minus_q_(1 - q) {
+ assert(q > 1);
+ assert(v > 0);
+ assert(k > 0);
+ one_minus_q_inv_ = 1 / one_minus_q_;
+
+ // Setup for the ZRI algorithm (pg 17 of the paper).
+ // Compute: h(i max) => h(k + 0.5)
+ constexpr double kMax = 18446744073709549568.0;
+ double kd = static_cast<double>(k);
+ // TODO(absl-team): Determine if this check is needed, and if so, add a test
+ // that fails for k > kMax
+ if (kd > kMax) {
+ // Ensure that our maximum value is capped to a value which will
+ // round-trip back through double.
+ kd = kMax;
+ }
+ hxm_ = h(kd + 0.5);
+
+ // Compute: h(0)
+ const bool use_precomputed = (v == 1.0 && q == 2.0);
+ const double h0x5 = use_precomputed ? (-1.0 / 1.5) // exp(-log(1.5))
+ : h(0.5);
+ const double elogv_q = (v_ == 1.0) ? 1 : pow_negative_q(v_);
+
+ // h(0) = h(0.5) - exp(log(v) * -q)
+ hx0_minus_hxm_ = (h0x5 - elogv_q) - hxm_;
+
+ // And s
+ s_ = use_precomputed ? 0.46153846153846123 : compute_s();
+}
+
+template <typename IntType>
+double zipf_distribution<IntType>::param_type::h(double x) const {
+ // std::exp(one_minus_q_ * std::log(v_ + x)) * one_minus_q_inv_;
+ x += v_;
+ return (one_minus_q_ == -1.0)
+ ? (-1.0 / x) // -exp(-log(x))
+ : (std::exp(std::log(x) * one_minus_q_) * one_minus_q_inv_);
+}
+
+template <typename IntType>
+double zipf_distribution<IntType>::param_type::hinv(double x) const {
+ // std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)) - v_;
+ return -v_ + ((one_minus_q_ == -1.0)
+ ? (-1.0 / x) // exp(-log(-x))
+ : std::exp(one_minus_q_inv_ * std::log(one_minus_q_ * x)));
+}
+
+template <typename IntType>
+double zipf_distribution<IntType>::param_type::compute_s() const {
+ // 1 - hinv(h(1.5) - std::exp(std::log(v_ + 1) * -q_));
+ return 1.0 - hinv(h(1.5) - pow_negative_q(v_ + 1.0));
+}
+
+template <typename IntType>
+double zipf_distribution<IntType>::param_type::pow_negative_q(double x) const {
+ // std::exp(std::log(x) * -q_);
+ return q_ == 2.0 ? (1.0 / (x * x)) : std::exp(std::log(x) * -q_);
+}
+
+template <typename IntType>
+template <typename URBG>
+typename zipf_distribution<IntType>::result_type
+zipf_distribution<IntType>::operator()(
+ URBG& g, const param_type& p) { // NOLINT(runtime/references)
+ absl::uniform_real_distribution<double> uniform_double;
+ double k;
+ for (;;) {
+ const double v = uniform_double(g);
+ const double u = p.hxm_ + v * p.hx0_minus_hxm_;
+ const double x = p.hinv(u);
+ k = rint(x); // std::floor(x + 0.5);
+ if (k > static_cast<double>(p.k())) continue; // reject k > max_k
+ if (k - x <= p.s_) break;
+ const double h = p.h(k + 0.5);
+ const double r = p.pow_negative_q(p.v_ + k);
+ if (u >= h - r) break;
+ }
+ IntType ki = static_cast<IntType>(k);
+ assert(ki <= p.k_);
+ return ki;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const zipf_distribution<IntType>& x) {
+ using stream_type =
+ typename random_internal::stream_format_type<IntType>::type;
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<double>::kPrecision);
+ os << static_cast<stream_type>(x.k()) << os.fill() << x.q() << os.fill()
+ << x.v();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ zipf_distribution<IntType>& x) { // NOLINT(runtime/references)
+ using result_type = typename zipf_distribution<IntType>::result_type;
+ using param_type = typename zipf_distribution<IntType>::param_type;
+ using stream_type =
+ typename random_internal::stream_format_type<IntType>::type;
+ stream_type k;
+ double q;
+ double v;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ is >> k >> q >> v;
+ if (!is.fail()) {
+ x.param(param_type(static_cast<result_type>(k), q, v));
+ }
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_ZIPF_DISTRIBUTION_H_
diff --git a/contrib/restricted/abseil-cpp/absl/status/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/status/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..1c58023e4b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/status/.yandex_meta/licenses.list.txt
@@ -0,0 +1,20 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/status/internal/status_matchers.h b/contrib/restricted/abseil-cpp/absl/status/internal/status_matchers.h
new file mode 100644
index 0000000000..0750622e3f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/status/internal/status_matchers.h
@@ -0,0 +1,246 @@
+// Copyright 2024 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_STATUS_INTERNAL_STATUS_MATCHERS_H_
+#define ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
+
+#include <ostream> // NOLINT
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h" // gmock_for_status_matchers.h
+#include "absl/base/config.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+
+namespace absl_testing {
+ABSL_NAMESPACE_BEGIN
+namespace status_internal {
+
+inline const absl::Status& GetStatus(const absl::Status& status) {
+ return status;
+}
+
+template <typename T>
+inline const absl::Status& GetStatus(const absl::StatusOr<T>& status) {
+ return status.status();
+}
+
+////////////////////////////////////////////////////////////
+// Implementation of IsOkAndHolds().
+
+// Monomorphic implementation of matcher IsOkAndHolds(m). StatusOrType is a
+// reference to StatusOr<T>.
+template <typename StatusOrType>
+class IsOkAndHoldsMatcherImpl
+ : public ::testing::MatcherInterface<StatusOrType> {
+ public:
+ typedef
+ typename std::remove_reference<StatusOrType>::type::value_type value_type;
+
+ template <typename InnerMatcher>
+ explicit IsOkAndHoldsMatcherImpl(InnerMatcher&& inner_matcher)
+ : inner_matcher_(::testing::SafeMatcherCast<const value_type&>(
+ std::forward<InnerMatcher>(inner_matcher))) {}
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "is OK and has a value that ";
+ inner_matcher_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "isn't OK or has a value that ";
+ inner_matcher_.DescribeNegationTo(os);
+ }
+
+ bool MatchAndExplain(
+ StatusOrType actual_value,
+ ::testing::MatchResultListener* result_listener) const override {
+ if (!GetStatus(actual_value).ok()) {
+ *result_listener << "which has status " << GetStatus(actual_value);
+ return false;
+ }
+
+ // Call through to the inner matcher.
+ return inner_matcher_.MatchAndExplain(*actual_value, result_listener);
+ }
+
+ private:
+ const ::testing::Matcher<const value_type&> inner_matcher_;
+};
+
+// Implements IsOkAndHolds(m) as a polymorphic matcher.
+template <typename InnerMatcher>
+class IsOkAndHoldsMatcher {
+ public:
+ explicit IsOkAndHoldsMatcher(InnerMatcher inner_matcher)
+ : inner_matcher_(std::forward<InnerMatcher>(inner_matcher)) {}
+
+ // Converts this polymorphic matcher to a monomorphic matcher of the
+ // given type. StatusOrType can be either StatusOr<T> or a
+ // reference to StatusOr<T>.
+ template <typename StatusOrType>
+ operator ::testing::Matcher<StatusOrType>() const { // NOLINT
+ return ::testing::Matcher<StatusOrType>(
+ new IsOkAndHoldsMatcherImpl<const StatusOrType&>(inner_matcher_));
+ }
+
+ private:
+ const InnerMatcher inner_matcher_;
+};
+
+////////////////////////////////////////////////////////////
+// Implementation of StatusIs().
+
+// `StatusCode` is implicitly convertible from `int`, `absl::StatusCode`, and
+// is explicitly convertible to these types as well.
+//
+// We need this class because `absl::StatusCode` (as a scoped enum) is not
+// implicitly convertible to `int`. In order to handle use cases like
+// ```
+// StatusIs(Anyof(absl::StatusCode::kUnknown, absl::StatusCode::kCancelled))
+// ```
+// which uses polymorphic matchers, we need to unify the interfaces into
+// `Matcher<StatusCode>`.
+class StatusCode {
+ public:
+ /*implicit*/ StatusCode(int code) // NOLINT
+ : code_(static_cast<::absl::StatusCode>(code)) {}
+ /*implicit*/ StatusCode(::absl::StatusCode code) : code_(code) {} // NOLINT
+
+ explicit operator int() const { return static_cast<int>(code_); }
+
+ friend inline void PrintTo(const StatusCode& code, std::ostream* os) {
+ // TODO(b/321095377): Change this to print the status code as a string.
+ *os << static_cast<int>(code);
+ }
+
+ private:
+ ::absl::StatusCode code_;
+};
+
+// Relational operators to handle matchers like Eq, Lt, etc..
+inline bool operator==(const StatusCode& lhs, const StatusCode& rhs) {
+ return static_cast<int>(lhs) == static_cast<int>(rhs);
+}
+inline bool operator!=(const StatusCode& lhs, const StatusCode& rhs) {
+ return static_cast<int>(lhs) != static_cast<int>(rhs);
+}
+
+// StatusIs() is a polymorphic matcher. This class is the common
+// implementation of it shared by all types T where StatusIs() can be
+// used as a Matcher<T>.
+class StatusIsMatcherCommonImpl {
+ public:
+ StatusIsMatcherCommonImpl(
+ ::testing::Matcher<StatusCode> code_matcher,
+ ::testing::Matcher<absl::string_view> message_matcher)
+ : code_matcher_(std::move(code_matcher)),
+ message_matcher_(std::move(message_matcher)) {}
+
+ void DescribeTo(std::ostream* os) const;
+
+ void DescribeNegationTo(std::ostream* os) const;
+
+ bool MatchAndExplain(const absl::Status& status,
+ ::testing::MatchResultListener* result_listener) const;
+
+ private:
+ const ::testing::Matcher<StatusCode> code_matcher_;
+ const ::testing::Matcher<absl::string_view> message_matcher_;
+};
+
+// Monomorphic implementation of matcher StatusIs() for a given type
+// T. T can be Status, StatusOr<>, or a reference to either of them.
+template <typename T>
+class MonoStatusIsMatcherImpl : public ::testing::MatcherInterface<T> {
+ public:
+ explicit MonoStatusIsMatcherImpl(StatusIsMatcherCommonImpl common_impl)
+ : common_impl_(std::move(common_impl)) {}
+
+ void DescribeTo(std::ostream* os) const override {
+ common_impl_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ common_impl_.DescribeNegationTo(os);
+ }
+
+ bool MatchAndExplain(
+ T actual_value,
+ ::testing::MatchResultListener* result_listener) const override {
+ return common_impl_.MatchAndExplain(GetStatus(actual_value),
+ result_listener);
+ }
+
+ private:
+ StatusIsMatcherCommonImpl common_impl_;
+};
+
+// Implements StatusIs() as a polymorphic matcher.
+class StatusIsMatcher {
+ public:
+ template <typename StatusCodeMatcher, typename StatusMessageMatcher>
+ StatusIsMatcher(StatusCodeMatcher&& code_matcher,
+ StatusMessageMatcher&& message_matcher)
+ : common_impl_(::testing::MatcherCast<StatusCode>(
+ std::forward<StatusCodeMatcher>(code_matcher)),
+ ::testing::MatcherCast<absl::string_view>(
+ std::forward<StatusMessageMatcher>(message_matcher))) {
+ }
+
+ // Converts this polymorphic matcher to a monomorphic matcher of the
+ // given type. T can be StatusOr<>, Status, or a reference to
+ // either of them.
+ template <typename T>
+ /*implicit*/ operator ::testing::Matcher<T>() const { // NOLINT
+ return ::testing::Matcher<T>(
+ new MonoStatusIsMatcherImpl<const T&>(common_impl_));
+ }
+
+ private:
+ const StatusIsMatcherCommonImpl common_impl_;
+};
+
+// Monomorphic implementation of matcher IsOk() for a given type T.
+// T can be Status, StatusOr<>, or a reference to either of them.
+template <typename T>
+class MonoIsOkMatcherImpl : public ::testing::MatcherInterface<T> {
+ public:
+ void DescribeTo(std::ostream* os) const override { *os << "is OK"; }
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "is not OK";
+ }
+ bool MatchAndExplain(T actual_value,
+ ::testing::MatchResultListener*) const override {
+ return GetStatus(actual_value).ok();
+ }
+};
+
+// Implements IsOk() as a polymorphic matcher.
+class IsOkMatcher {
+ public:
+ template <typename T>
+ /*implicit*/ operator ::testing::Matcher<T>() const { // NOLINT
+ return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<const T&>());
+ }
+};
+
+} // namespace status_internal
+ABSL_NAMESPACE_END
+} // namespace absl_testing
+
+#endif // ABSL_STATUS_INTERNAL_STATUS_MATCHERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/strings/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..2ca3cf02e1
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/.yandex_meta/licenses.list.txt
@@ -0,0 +1,54 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2021 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2022 The Abseil Authors
+
+
+====================COPYRIGHT====================
+// Copyright 2024 The Abseil Authors
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h b/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h
new file mode 100644
index 0000000000..ca52240a14
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/cord_test_helpers.h
@@ -0,0 +1,122 @@
+//
+// Copyright 2018 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_CORD_TEST_HELPERS_H_
+#define ABSL_STRINGS_CORD_TEST_HELPERS_H_
+
+#include <cstdint>
+#include <iostream>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Cord sizes relevant for testing
+enum class TestCordSize {
+ // An empty value
+ kEmpty = 0,
+
+ // An inlined string value
+ kInlined = cord_internal::kMaxInline / 2 + 1,
+
+ // 'Well known' SSO lengths (excluding terminating zero).
+ // libstdcxx has a maximum SSO of 15, libc++ has a maximum SSO of 22.
+ kStringSso1 = 15,
+ kStringSso2 = 22,
+
+ // A string value which is too large to fit in inlined data, but small enough
+ // such that Cord prefers copying the value if possible, i.e.: not stealing
+ // std::string inputs, or referencing existing CordReps on Append, etc.
+ kSmall = cord_internal::kMaxBytesToCopy / 2 + 1,
+
+ // A string value large enough that Cord prefers to reference or steal from
+ // existing inputs rather than copying contents of the input.
+ kMedium = cord_internal::kMaxFlatLength / 2 + 1,
+
+ // A string value large enough to cause it to be stored in multiple flats.
+ kLarge = cord_internal::kMaxFlatLength * 4
+};
+
+// To string helper
+inline absl::string_view ToString(TestCordSize size) {
+ switch (size) {
+ case TestCordSize::kEmpty:
+ return "Empty";
+ case TestCordSize::kInlined:
+ return "Inlined";
+ case TestCordSize::kSmall:
+ return "Small";
+ case TestCordSize::kStringSso1:
+ return "StringSso1";
+ case TestCordSize::kStringSso2:
+ return "StringSso2";
+ case TestCordSize::kMedium:
+ return "Medium";
+ case TestCordSize::kLarge:
+ return "Large";
+ }
+ return "???";
+}
+
+// Returns the length matching the specified size
+inline size_t Length(TestCordSize size) { return static_cast<size_t>(size); }
+
+// Stream output helper
+inline std::ostream& operator<<(std::ostream& stream, TestCordSize size) {
+ return stream << ToString(size);
+}
+
+// Creates a multi-segment Cord from an iterable container of strings. The
+// resulting Cord is guaranteed to have one segment for every string in the
+// container. This allows code to be unit tested with multi-segment Cord
+// inputs.
+//
+// Example:
+//
+// absl::Cord c = absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
+// EXPECT_FALSE(c.GetFlat(&unused));
+//
+// The mechanism by which this Cord is created is an implementation detail. Any
+// implementation that produces a multi-segment Cord may produce a flat Cord in
+// the future as new optimizations are added to the Cord class.
+// MakeFragmentedCord will, however, always be updated to return a multi-segment
+// Cord.
+template <typename Container>
+Cord MakeFragmentedCord(const Container& c) {
+ Cord result;
+ for (const auto& s : c) {
+ auto* external = new std::string(s);
+ Cord tmp = absl::MakeCordFromExternal(
+ *external, [external](absl::string_view) { delete external; });
+ tmp.Prepend(result);
+ result = tmp;
+ }
+ return result;
+}
+
+inline Cord MakeFragmentedCord(std::initializer_list<absl::string_view> list) {
+ return MakeFragmentedCord<std::initializer_list<absl::string_view>>(list);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_CORD_TEST_HELPERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/cordz_test_helpers.h b/contrib/restricted/abseil-cpp/absl/strings/cordz_test_helpers.h
new file mode 100644
index 0000000000..619f13c27a
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/cordz_test_helpers.h
@@ -0,0 +1,153 @@
+// 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_STRINGS_CORDZ_TEST_HELPERS_H_
+#define ABSL_STRINGS_CORDZ_TEST_HELPERS_H_
+
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cordz_info.h"
+#include "absl/strings/internal/cordz_sample_token.h"
+#include "absl/strings/internal/cordz_statistics.h"
+#include "absl/strings/internal/cordz_update_tracker.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Returns the CordzInfo for the cord, or nullptr if the cord is not sampled.
+inline absl::Nullable<const cord_internal::CordzInfo*> GetCordzInfoForTesting(
+ const Cord& cord) {
+ if (!cord.contents_.is_tree()) return nullptr;
+ return cord.contents_.cordz_info();
+}
+
+// Returns true if the provided cordz_info is in the list of sampled cords.
+inline bool CordzInfoIsListed(
+ absl::Nonnull<const cord_internal::CordzInfo*> cordz_info,
+ cord_internal::CordzSampleToken token = {}) {
+ for (const cord_internal::CordzInfo& info : token) {
+ if (cordz_info == &info) return true;
+ }
+ return false;
+}
+
+// Matcher on Cord that verifies all of:
+// - the cord is sampled
+// - the CordzInfo of the cord is listed / discoverable.
+// - the reported CordzStatistics match the cord's actual properties
+// - the cord has an (initial) UpdateTracker count of 1 for `method`
+MATCHER_P(HasValidCordzInfoOf, method, "CordzInfo matches cord") {
+ const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);
+ if (cord_info == nullptr) {
+ *result_listener << "cord is not sampled";
+ return false;
+ }
+ if (!CordzInfoIsListed(cord_info)) {
+ *result_listener << "cord is sampled, but not listed";
+ return false;
+ }
+ cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();
+ if (stat.size != arg.size()) {
+ *result_listener << "cordz size " << stat.size
+ << " does not match cord size " << arg.size();
+ return false;
+ }
+ if (stat.update_tracker.Value(method) != 1) {
+ *result_listener << "Expected method count 1 for " << method << ", found "
+ << stat.update_tracker.Value(method);
+ return false;
+ }
+ return true;
+}
+
+// Matcher on Cord that verifies that the cord is sampled and that the CordzInfo
+// update tracker has 'method' with a call count of 'n'
+MATCHER_P2(CordzMethodCountEq, method, n,
+ absl::StrCat("CordzInfo method count equals ", n)) {
+ const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);
+ if (cord_info == nullptr) {
+ *result_listener << "cord is not sampled";
+ return false;
+ }
+ cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();
+ if (stat.update_tracker.Value(method) != n) {
+ *result_listener << "Expected method count " << n << " for " << method
+ << ", found " << stat.update_tracker.Value(method);
+ return false;
+ }
+ return true;
+}
+
+// Cordz will only update with a new rate once the previously scheduled event
+// has fired. When we disable Cordz, a long delay takes place where we won't
+// consider profiling new Cords. CordzSampleIntervalHelper will burn through
+// that interval and allow for testing that assumes that the average sampling
+// interval is a particular value.
+class CordzSamplingIntervalHelper {
+ public:
+ explicit CordzSamplingIntervalHelper(int32_t interval)
+ : orig_mean_interval_(absl::cord_internal::get_cordz_mean_interval()) {
+ absl::cord_internal::set_cordz_mean_interval(interval);
+ absl::cord_internal::cordz_set_next_sample_for_testing(interval);
+ }
+
+ ~CordzSamplingIntervalHelper() {
+ absl::cord_internal::set_cordz_mean_interval(orig_mean_interval_);
+ absl::cord_internal::cordz_set_next_sample_for_testing(orig_mean_interval_);
+ }
+
+ private:
+ int32_t orig_mean_interval_;
+};
+
+// Wrapper struct managing a small CordRep `rep`
+struct TestCordRep {
+ absl::Nonnull<cord_internal::CordRepFlat*> rep;
+
+ TestCordRep() {
+ rep = cord_internal::CordRepFlat::New(100);
+ rep->length = 100;
+ memset(rep->Data(), 1, 100);
+ }
+ ~TestCordRep() { cord_internal::CordRep::Unref(rep); }
+};
+
+// Wrapper struct managing a small CordRep `rep`, and
+// an InlineData `data` initialized with that CordRep.
+struct TestCordData {
+ TestCordRep rep;
+ cord_internal::InlineData data{rep.rep};
+};
+
+// Creates a Cord that is not sampled
+template <typename... Args>
+Cord UnsampledCord(Args... args) {
+ CordzSamplingIntervalHelper never(9999);
+ Cord cord(std::forward<Args>(args)...);
+ ABSL_ASSERT(GetCordzInfoForTesting(cord) == nullptr);
+ return cord;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_CORDZ_TEST_HELPERS_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_test_util.h b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_test_util.h
new file mode 100644
index 0000000000..18a0a19544
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/cord_rep_test_util.h
@@ -0,0 +1,205 @@
+// 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_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
+
+#include <cassert>
+#include <memory>
+#include <random>
+#include <string>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_btree.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cordrep_testing {
+
+inline cord_internal::CordRepSubstring* MakeSubstring(
+ size_t start, size_t len, cord_internal::CordRep* rep) {
+ auto* sub = new cord_internal::CordRepSubstring;
+ sub->tag = cord_internal::SUBSTRING;
+ sub->start = start;
+ sub->length = len <= 0 ? rep->length - start + len : len;
+ sub->child = rep;
+ return sub;
+}
+
+inline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) {
+ assert(value.length() <= cord_internal::kMaxFlatLength);
+ auto* flat = cord_internal::CordRepFlat::New(value.length());
+ flat->length = value.length();
+ memcpy(flat->Data(), value.data(), value.length());
+ return flat;
+}
+
+// Creates an external node for testing
+inline cord_internal::CordRepExternal* MakeExternal(absl::string_view s) {
+ struct Rep : public cord_internal::CordRepExternal {
+ std::string s;
+ explicit Rep(absl::string_view sv) : s(sv) {
+ this->tag = cord_internal::EXTERNAL;
+ this->base = s.data();
+ this->length = s.length();
+ this->releaser_invoker = [](cord_internal::CordRepExternal* self) {
+ delete static_cast<Rep*>(self);
+ };
+ }
+ };
+ return new Rep(s);
+}
+
+inline std::string CreateRandomString(size_t n) {
+ absl::string_view data =
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789~!@#$%^&*()_+=-<>?:\"{}[]|";
+ std::minstd_rand rnd;
+ std::uniform_int_distribution<size_t> dist(0, data.size() - 1);
+ std::string s(n, ' ');
+ for (size_t i = 0; i < n; ++i) {
+ s[i] = data[dist(rnd)];
+ }
+ return s;
+}
+
+// Creates an array of flats from the provided string, chopping
+// the provided string up into flats of size `chunk_size` characters
+// resulting in roughly `data.size() / chunk_size` total flats.
+inline std::vector<cord_internal::CordRep*> CreateFlatsFromString(
+ absl::string_view data, size_t chunk_size) {
+ assert(chunk_size > 0);
+ std::vector<cord_internal::CordRep*> flats;
+ for (absl::string_view s = data; !s.empty(); s.remove_prefix(chunk_size)) {
+ flats.push_back(MakeFlat(s.substr(0, chunk_size)));
+ }
+ return flats;
+}
+
+inline cord_internal::CordRepBtree* CordRepBtreeFromFlats(
+ absl::Span<cord_internal::CordRep* const> flats) {
+ assert(!flats.empty());
+ auto* node = cord_internal::CordRepBtree::Create(flats[0]);
+ for (size_t i = 1; i < flats.size(); ++i) {
+ node = cord_internal::CordRepBtree::Append(node, flats[i]);
+ }
+ return node;
+}
+
+template <typename Fn>
+inline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) {
+ fn(rep);
+ while (rep->tag == cord_internal::SUBSTRING) {
+ rep = rep->substring()->child;
+ fn(rep);
+ }
+ if (rep->tag == cord_internal::BTREE) {
+ for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
+ CordVisitReps(edge, fn);
+ }
+ }
+}
+
+template <typename Predicate>
+inline std::vector<cord_internal::CordRep*> CordCollectRepsIf(
+ Predicate&& predicate, cord_internal::CordRep* rep) {
+ std::vector<cord_internal::CordRep*> reps;
+ CordVisitReps(rep, [&reps, &predicate](cord_internal::CordRep* rep) {
+ if (predicate(rep)) reps.push_back(rep);
+ });
+ return reps;
+}
+
+inline std::vector<cord_internal::CordRep*> CordCollectReps(
+ cord_internal::CordRep* rep) {
+ std::vector<cord_internal::CordRep*> reps;
+ auto fn = [&reps](cord_internal::CordRep* rep) { reps.push_back(rep); };
+ CordVisitReps(rep, fn);
+ return reps;
+}
+
+inline void CordToString(cord_internal::CordRep* rep, std::string& s) {
+ size_t offset = 0;
+ size_t length = rep->length;
+ while (rep->tag == cord_internal::SUBSTRING) {
+ offset += rep->substring()->start;
+ rep = rep->substring()->child;
+ }
+ if (rep->tag == cord_internal::BTREE) {
+ for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
+ CordToString(edge, s);
+ }
+ } else if (rep->tag >= cord_internal::FLAT) {
+ s.append(rep->flat()->Data() + offset, length);
+ } else if (rep->tag == cord_internal::EXTERNAL) {
+ s.append(rep->external()->base + offset, length);
+ } else {
+ ABSL_RAW_LOG(FATAL, "Unsupported tag %d", rep->tag);
+ }
+}
+
+inline std::string CordToString(cord_internal::CordRep* rep) {
+ std::string s;
+ s.reserve(rep->length);
+ CordToString(rep, s);
+ return s;
+}
+
+// RAII Helper class to automatically unref reps on destruction.
+class AutoUnref {
+ public:
+ ~AutoUnref() {
+ for (CordRep* rep : unrefs_) CordRep::Unref(rep);
+ }
+
+ // Adds `rep` to the list of reps to be unreffed at destruction.
+ template <typename CordRepType>
+ CordRepType* Add(CordRepType* rep) {
+ unrefs_.push_back(rep);
+ return rep;
+ }
+
+ // Increments the reference count of `rep` by one, and adds it to
+ // the list of reps to be unreffed at destruction.
+ template <typename CordRepType>
+ CordRepType* Ref(CordRepType* rep) {
+ unrefs_.push_back(CordRep::Ref(rep));
+ return rep;
+ }
+
+ // Increments the reference count of `rep` by one if `condition` is true,
+ // and adds it to the list of reps to be unreffed at destruction.
+ template <typename CordRepType>
+ CordRepType* RefIf(bool condition, CordRepType* rep) {
+ if (condition) unrefs_.push_back(CordRep::Ref(rep));
+ return rep;
+ }
+
+ private:
+ using CordRep = absl::cord_internal::CordRep;
+
+ std::vector<CordRep*> unrefs_;
+};
+
+} // namespace cordrep_testing
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h
new file mode 100644
index 0000000000..7b18017a08
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/escaping_test_common.h
@@ -0,0 +1,133 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This test contains common things needed by both escaping_test.cc and
+// escaping_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
+
+#include <array>
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+struct base64_testcase {
+ absl::string_view plaintext;
+ absl::string_view cyphertext;
+};
+
+inline const std::array<base64_testcase, 5>& base64_strings() {
+ static const std::array<base64_testcase, 5> testcase{{
+ // Some google quotes
+ // Cyphertext created with "uuencode (GNU sharutils) 4.6.3"
+ // (Note that we're testing the websafe encoding, though, so if
+ // you add messages, be sure to run "tr -- '+/' '-_'" on the output)
+ { "I was always good at math and science, and I never realized "
+ "that was unusual or somehow undesirable. So one of the things "
+ "I care a lot about is helping to remove that stigma, "
+ "to show girls that you can be feminine, you can like the things "
+ "that girls like, but you can also be really good at technology. "
+ "You can be really good at building things."
+ " - Marissa Meyer, Newsweek, 2010-12-22" "\n",
+
+ "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
+ "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
+ "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
+ "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
+ "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
+ "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
+ "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
+ "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
+ "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" },
+
+ { "Typical first year for a new cluster: "
+ "~0.5 overheating "
+ "~1 PDU failure "
+ "~1 rack-move "
+ "~1 network rewiring "
+ "~20 rack failures "
+ "~5 racks go wonky "
+ "~8 network maintenances "
+ "~12 router reloads "
+ "~3 router failures "
+ "~dozens of minor 30-second blips for dns "
+ "~1000 individual machine failures "
+ "~thousands of hard drive failures "
+ "slow disks, bad memory, misconfigured machines, flaky machines, etc."
+ " - Jeff Dean, The Joys of Real Hardware" "\n",
+
+ "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
+ "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
+ "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
+ "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
+ "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
+ "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
+ "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
+ "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
+ "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
+ "ZWFsIEhhcmR3YXJlCg" },
+
+ { "I'm the head of the webspam team at Google. "
+ "That means that if you type your name into Google and get porn back, "
+ "it's my fault. Unless you're a porn star, in which case porn is a "
+ "completely reasonable response."
+ " - Matt Cutts, Google Plus" "\n",
+
+ "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
+ "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
+ "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
+ "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
+ "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
+ "IEdvb2dsZSBQbHVzCg" },
+
+ { "It will still be a long time before machines approach human "
+ "intelligence. "
+ "But luckily, machines don't actually have to be intelligent; "
+ "they just have to fake it. Access to a wealth of information, "
+ "combined with a rudimentary decision-making capacity, "
+ "can often be almost as useful. Of course, the results are better yet "
+ "when coupled with intelligence. A reference librarian with access to "
+ "a good search engine is a formidable tool."
+ " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
+ "\n",
+
+ "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
+ "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
+ "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
+ "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
+ "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
+ "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
+ "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
+ "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
+ "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
+ "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
+ "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
+ "NAo" },
+
+ // Degenerate edge case
+ { "",
+ "" },
+ }};
+
+ return testcase;
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h b/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h
new file mode 100644
index 0000000000..eaa88a8897
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/numbers_test_common.h
@@ -0,0 +1,184 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file contains common things needed by numbers_test.cc,
+// numbers_legacy_test.cc and numbers_benchmark.cc.
+
+#ifndef ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+#define ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
+
+#include <array>
+#include <cstdint>
+#include <limits>
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+template <typename IntType>
+inline bool Itoa(IntType value, int base, std::string* destination) {
+ destination->clear();
+ if (base <= 1 || base > 36) {
+ return false;
+ }
+
+ if (value == 0) {
+ destination->push_back('0');
+ return true;
+ }
+
+ bool negative = value < 0;
+ while (value != 0) {
+ const IntType next_value = value / base;
+ // Can't use std::abs here because of problems when IntType is unsigned.
+ int remainder =
+ static_cast<int>(value > next_value * base ? value - next_value * base
+ : next_value * base - value);
+ char c = remainder < 10 ? '0' + remainder : 'A' + remainder - 10;
+ destination->insert(0, 1, c);
+ value = next_value;
+ }
+
+ if (negative) {
+ destination->insert(0, 1, '-');
+ }
+ return true;
+}
+
+struct uint32_test_case {
+ const char* str;
+ bool expect_ok;
+ int base; // base to pass to the conversion function
+ uint32_t expected;
+};
+
+inline const std::array<uint32_test_case, 27>& strtouint32_test_cases() {
+ static const std::array<uint32_test_case, 27> test_cases{{
+ {"0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
+ {"0x34234324", true, 16, 0x34234324},
+ {"34234324", true, 16, 0x34234324},
+ {"0", true, 16, 0},
+ {" \t\n 0xffffffff", true, 16, (std::numeric_limits<uint32_t>::max)()},
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+ {" \t\n 72717222", true, 8, 072717222},
+ {" \t\n 072717222", true, 8, 072717222},
+ {" \t\n 072717228", false, 8, 07271722},
+ {"0", true, 0, 0},
+
+ // Base-10 version.
+ {"34234324", true, 0, 34234324},
+ {"4294967295", true, 0, (std::numeric_limits<uint32_t>::max)()},
+ {"34234324 \n\t", true, 10, 34234324},
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0}, // would be valid hex, but prefix is missing
+ {"34234324a", false, 0, 34234324},
+ {"34234.3", false, 0, 34234},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"4294967296", false, 0, (std::numeric_limits<uint32_t>::max)()},
+ {"0x100000000", false, 0, (std::numeric_limits<uint32_t>::max)()},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+struct uint64_test_case {
+ const char* str;
+ bool expect_ok;
+ int base;
+ uint64_t expected;
+};
+
+inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
+ static const std::array<uint64_test_case, 34> test_cases{{
+ {"0x3423432448783446", true, 16, int64_t{0x3423432448783446}},
+ {"3423432448783446", true, 16, int64_t{0x3423432448783446}},
+
+ {"0", true, 16, 0},
+ {"000", true, 0, 0},
+ {"0", true, 0, 0},
+ {" \t\n 0xffffffffffffffff", true, 16,
+ (std::numeric_limits<uint64_t>::max)()},
+
+ {"012345670123456701234", true, 8, int64_t{012345670123456701234}},
+ {"12345670123456701234", true, 8, int64_t{012345670123456701234}},
+
+ {"12845670123456701234", false, 8, 0},
+
+ // Base-10 version.
+ {"34234324487834466", true, 0, int64_t{34234324487834466}},
+
+ {" \t\n 18446744073709551615", true, 0,
+ (std::numeric_limits<uint64_t>::max)()},
+
+ {"34234324487834466 \n\t ", true, 0, int64_t{34234324487834466}},
+
+ {" \f\v 46", true, 10, 46}, // must accept weird whitespace
+
+ // Unusual base
+ {"0", true, 3, 0},
+ {"2", true, 3, 2},
+ {"11", true, 3, 4},
+
+ {"0", true, 0, 0},
+
+ // Invalid uints.
+ {"", false, 0, 0},
+ {" ", false, 0, 0},
+ {"abc", false, 0, 0},
+ {"34234324487834466a", false, 0, 0},
+ {"34234487834466.3", false, 0, 0},
+ {"-1", false, 0, 0},
+ {" -123", false, 0, 0},
+ {" \t\n -123", false, 0, 0},
+
+ // Out of bounds.
+ {"18446744073709551616", false, 10, 0},
+ {"18446744073709551616", false, 0, 0},
+ {"0x10000000000000000", false, 16,
+ (std::numeric_limits<uint64_t>::max)()},
+ {"0X10000000000000000", false, 16,
+ (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
+ {"0x10000000000000000", false, 0, (std::numeric_limits<uint64_t>::max)()},
+ {"0X10000000000000000", false, 0,
+ (std::numeric_limits<uint64_t>::max)()}, // 0X versus 0x.
+
+ {"0x1234", true, 16, 0x1234},
+
+ // Base-10 string version.
+ {"1234", true, 0, 1234},
+ {nullptr, false, 0, 0},
+ }};
+ return test_cases;
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h b/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h
new file mode 100644
index 0000000000..c37c2c3ffe
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/strings/internal/pow10_helper.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2018 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.
+//
+// This test helper library contains a table of powers of 10, to guarantee
+// precise values are computed across the full range of doubles. We can't rely
+// on the pow() function, because not all standard libraries ship a version
+// that is precise.
+#ifndef ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+#define ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
+
+#include <vector>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// Computes the precise value of 10^exp. (I.e. the nearest representable
+// double to the exact value, rounding to nearest-even in the (single) case of
+// being exactly halfway between.)
+double Pow10(int exp);
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/synchronization/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..cf662dd4fd
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/.yandex_meta/licenses.list.txt
@@ -0,0 +1,52 @@
+====================Apache-2.0====================
+ * 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2020 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2023 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/synchronization/internal/thread_pool.h b/contrib/restricted/abseil-cpp/absl/synchronization/internal/thread_pool.h
new file mode 100644
index 0000000000..5eb0bb605e
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/synchronization/internal/thread_pool.h
@@ -0,0 +1,96 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
+#define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
+
+#include <cassert>
+#include <cstddef>
+#include <functional>
+#include <queue>
+#include <thread> // NOLINT(build/c++11)
+#include <utility>
+#include <vector>
+
+#include "absl/base/thread_annotations.h"
+#include "absl/functional/any_invocable.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace synchronization_internal {
+
+// A simple ThreadPool implementation for tests.
+class ThreadPool {
+ public:
+ explicit ThreadPool(int num_threads) {
+ threads_.reserve(num_threads);
+ for (int i = 0; i < num_threads; ++i) {
+ threads_.push_back(std::thread(&ThreadPool::WorkLoop, this));
+ }
+ }
+
+ ThreadPool(const ThreadPool &) = delete;
+ ThreadPool &operator=(const ThreadPool &) = delete;
+
+ ~ThreadPool() {
+ {
+ absl::MutexLock l(&mu_);
+ for (size_t i = 0; i < threads_.size(); i++) {
+ queue_.push(nullptr); // Shutdown signal.
+ }
+ }
+ for (auto &t : threads_) {
+ t.join();
+ }
+ }
+
+ // Schedule a function to be run on a ThreadPool thread immediately.
+ void Schedule(absl::AnyInvocable<void()> func) {
+ assert(func != nullptr);
+ absl::MutexLock l(&mu_);
+ queue_.push(std::move(func));
+ }
+
+ private:
+ bool WorkAvailable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ return !queue_.empty();
+ }
+
+ void WorkLoop() {
+ while (true) {
+ absl::AnyInvocable<void()> func;
+ {
+ absl::MutexLock l(&mu_);
+ mu_.Await(absl::Condition(this, &ThreadPool::WorkAvailable));
+ func = std::move(queue_.front());
+ queue_.pop();
+ }
+ if (func == nullptr) { // Shutdown signal.
+ break;
+ }
+ func();
+ }
+ }
+
+ absl::Mutex mu_;
+ std::queue<absl::AnyInvocable<void()>> queue_ ABSL_GUARDED_BY(mu_);
+ std::vector<std::thread> threads_;
+};
+
+} // namespace synchronization_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/time/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/time/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..7c1bf3b5ad
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/time/.yandex_meta/licenses.list.txt
@@ -0,0 +1,42 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2016 Google Inc. All Rights Reserved.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================Public-Domain====================
+** This file is in the public domain, so clarified as of
diff --git a/contrib/restricted/abseil-cpp/absl/time/internal/test_util.h b/contrib/restricted/abseil-cpp/absl/time/internal/test_util.h
new file mode 100644
index 0000000000..5c4bf1f680
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/time/internal/test_util.h
@@ -0,0 +1,33 @@
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_TIME_INTERNAL_TEST_UTIL_H_
+#define ABSL_TIME_INTERNAL_TEST_UTIL_H_
+
+#include <string>
+
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace time_internal {
+
+// Loads the named timezone, but dies on any failure.
+absl::TimeZone LoadTimeZone(const std::string& name);
+
+} // namespace time_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TIME_INTERNAL_TEST_UTIL_H_
diff --git a/contrib/restricted/abseil-cpp/absl/types/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/types/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..f39e683596
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/types/.yandex_meta/licenses.list.txt
@@ -0,0 +1,24 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2018 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2019 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/types/any.h b/contrib/restricted/abseil-cpp/absl/types/any.h
new file mode 100644
index 0000000000..61f071f19b
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/types/any.h
@@ -0,0 +1,519 @@
+//
+// Copyright 2017 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// any.h
+// -----------------------------------------------------------------------------
+//
+// This header file define the `absl::any` type for holding a type-safe value
+// of any type. The 'absl::any` type is useful for providing a way to hold
+// something that is, as yet, unspecified. Such unspecified types
+// traditionally are passed between API boundaries until they are later cast to
+// their "destination" types. To cast to such a destination type, use
+// `absl::any_cast()`. Note that when casting an `absl::any`, you must cast it
+// to an explicit type; implicit conversions will throw.
+//
+// Example:
+//
+// auto a = absl::any(65);
+// absl::any_cast<int>(a); // 65
+// absl::any_cast<char>(a); // throws absl::bad_any_cast
+// absl::any_cast<std::string>(a); // throws absl::bad_any_cast
+//
+// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
+// and is designed to be a drop-in replacement for code compliant with C++17.
+//
+// Traditionally, the behavior of casting to a temporary unspecified type has
+// been accomplished with the `void *` paradigm, where the pointer was to some
+// other unspecified type. `absl::any` provides an "owning" version of `void *`
+// that avoids issues of pointer management.
+//
+// Note: just as in the case of `void *`, use of `absl::any` (and its C++17
+// version `std::any`) is a code smell indicating that your API might not be
+// constructed correctly. We have seen that most uses of `any` are unwarranted,
+// and `absl::any`, like `std::any`, is difficult to use properly. Before using
+// this abstraction, make sure that you should not instead be rewriting your
+// code to be more specific.
+//
+// Abseil has also released an `absl::variant` type (a C++11 compatible version
+// of the C++17 `std::variant`), which is generally preferred for use over
+// `absl::any`.
+#ifndef ABSL_TYPES_ANY_H_
+#define ABSL_TYPES_ANY_H_
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/utility/utility.h"
+
+#ifdef ABSL_USES_STD_ANY
+
+#include <any> // IWYU pragma: export
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+using std::any;
+using std::any_cast;
+using std::bad_any_cast;
+using std::make_any;
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#else // ABSL_USES_STD_ANY
+
+#include <algorithm>
+#include <cstddef>
+#include <initializer_list>
+#include <memory>
+#include <stdexcept>
+#include <type_traits>
+#include <typeinfo>
+#include <utility>
+
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/bad_any_cast.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class any;
+
+// swap()
+//
+// Swaps two `absl::any` values. Equivalent to `x.swap(y) where `x` and `y` are
+// `absl::any` types.
+void swap(any& x, any& y) noexcept;
+
+// make_any()
+//
+// Constructs an `absl::any` of type `T` with the given arguments.
+template <typename T, typename... Args>
+any make_any(Args&&... args);
+
+// Overload of `absl::make_any()` for constructing an `absl::any` type from an
+// initializer list.
+template <typename T, typename U, typename... Args>
+any make_any(std::initializer_list<U> il, Args&&... args);
+
+// any_cast()
+//
+// Statically casts the value of a `const absl::any` type to the given type.
+// This function will throw `absl::bad_any_cast` if the stored value type of the
+// `absl::any` does not match the cast.
+//
+// `any_cast()` can also be used to get a reference to the internal storage iff
+// a reference type is passed as its `ValueType`:
+//
+// Example:
+//
+// absl::any my_any = std::vector<int>();
+// absl::any_cast<std::vector<int>&>(my_any).push_back(42);
+template <typename ValueType>
+ValueType any_cast(const any& operand);
+
+// Overload of `any_cast()` to statically cast the value of a non-const
+// `absl::any` type to the given type. This function will throw
+// `absl::bad_any_cast` if the stored value type of the `absl::any` does not
+// match the cast.
+template <typename ValueType>
+ValueType any_cast(any& operand); // NOLINT(runtime/references)
+
+// Overload of `any_cast()` to statically cast the rvalue of an `absl::any`
+// type. This function will throw `absl::bad_any_cast` if the stored value type
+// of the `absl::any` does not match the cast.
+template <typename ValueType>
+ValueType any_cast(any&& operand);
+
+// Overload of `any_cast()` to statically cast the value of a const pointer
+// `absl::any` type to the given pointer type, or `nullptr` if the stored value
+// type of the `absl::any` does not match the cast.
+template <typename ValueType>
+const ValueType* any_cast(const any* operand) noexcept;
+
+// Overload of `any_cast()` to statically cast the value of a pointer
+// `absl::any` type to the given pointer type, or `nullptr` if the stored value
+// type of the `absl::any` does not match the cast.
+template <typename ValueType>
+ValueType* any_cast(any* operand) noexcept;
+
+// -----------------------------------------------------------------------------
+// absl::any
+// -----------------------------------------------------------------------------
+//
+// An `absl::any` object provides the facility to either store an instance of a
+// type, known as the "contained object", or no value. An `absl::any` is used to
+// store values of types that are unknown at compile time. The `absl::any`
+// object, when containing a value, must contain a value type; storing a
+// reference type is neither desired nor supported.
+//
+// An `absl::any` can only store a type that is copy-constructible; move-only
+// types are not allowed within an `any` object.
+//
+// Example:
+//
+// auto a = absl::any(65); // Literal, copyable
+// auto b = absl::any(std::vector<int>()); // Default-initialized, copyable
+// std::unique_ptr<Foo> my_foo;
+// auto c = absl::any(std::move(my_foo)); // Error, not copy-constructible
+//
+// Note that `absl::any` makes use of decayed types (`absl::decay_t` in this
+// context) to remove const-volatile qualifiers (known as "cv qualifiers"),
+// decay functions to function pointers, etc. We essentially "decay" a given
+// type into its essential type.
+//
+// `absl::any` makes use of decayed types when determining the basic type `T` of
+// the value to store in the any's contained object. In the documentation below,
+// we explicitly denote this by using the phrase "a decayed type of `T`".
+//
+// Example:
+//
+// const int a = 4;
+// absl::any foo(a); // Decay ensures we store an "int", not a "const int&".
+//
+// void my_function() {}
+// absl::any bar(my_function); // Decay ensures we store a function pointer.
+//
+// `absl::any` is a C++11 compatible version of the C++17 `std::any` abstraction
+// and is designed to be a drop-in replacement for code compliant with C++17.
+class any {
+ private:
+ template <typename T>
+ struct IsInPlaceType;
+
+ public:
+ // Constructors
+
+ // Constructs an empty `absl::any` object (`any::has_value()` will return
+ // `false`).
+ constexpr any() noexcept;
+
+ // Copy constructs an `absl::any` object with a "contained object" of the
+ // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
+ // `false`.
+ any(const any& other)
+ : obj_(other.has_value() ? other.obj_->Clone()
+ : std::unique_ptr<ObjInterface>()) {}
+
+ // Move constructs an `absl::any` object with a "contained object" of the
+ // passed type of `other` (or an empty `absl::any` if `other.has_value()` is
+ // `false`).
+ any(any&& other) noexcept = default;
+
+ // Constructs an `absl::any` object with a "contained object" of the decayed
+ // type of `T`, which is initialized via `std::forward<T>(value)`.
+ //
+ // This constructor will not participate in overload resolution if the
+ // decayed type of `T` is not copy-constructible.
+ template <
+ typename T, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<!absl::disjunction<
+ std::is_same<any, VT>, IsInPlaceType<VT>,
+ absl::negation<std::is_copy_constructible<VT> > >::value>* = nullptr>
+ any(T&& value) : obj_(new Obj<VT>(in_place, std::forward<T>(value))) {}
+
+ // Constructs an `absl::any` object with a "contained object" of the decayed
+ // type of `T`, which is initialized via `std::forward<T>(value)`.
+ template <typename T, typename... Args, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<absl::conjunction<
+ std::is_copy_constructible<VT>,
+ std::is_constructible<VT, Args...>>::value>* = nullptr>
+ explicit any(in_place_type_t<T> /*tag*/, Args&&... args)
+ : obj_(new Obj<VT>(in_place, std::forward<Args>(args)...)) {}
+
+ // Constructs an `absl::any` object with a "contained object" of the passed
+ // type `VT` as a decayed type of `T`. `VT` is initialized as if
+ // direct-non-list-initializing an object of type `VT` with the arguments
+ // `initializer_list, std::forward<Args>(args)...`.
+ template <
+ typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<
+ absl::conjunction<std::is_copy_constructible<VT>,
+ std::is_constructible<VT, std::initializer_list<U>&,
+ Args...>>::value>* = nullptr>
+ explicit any(in_place_type_t<T> /*tag*/, std::initializer_list<U> ilist,
+ Args&&... args)
+ : obj_(new Obj<VT>(in_place, ilist, std::forward<Args>(args)...)) {}
+
+ // Assignment operators
+
+ // Copy assigns an `absl::any` object with a "contained object" of the
+ // passed type.
+ any& operator=(const any& rhs) {
+ any(rhs).swap(*this);
+ return *this;
+ }
+
+ // Move assigns an `absl::any` object with a "contained object" of the
+ // passed type. `rhs` is left in a valid but otherwise unspecified state.
+ any& operator=(any&& rhs) noexcept {
+ any(std::move(rhs)).swap(*this);
+ return *this;
+ }
+
+ // Assigns an `absl::any` object with a "contained object" of the passed type.
+ template <typename T, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<absl::conjunction<
+ absl::negation<std::is_same<VT, any>>,
+ std::is_copy_constructible<VT>>::value>* = nullptr>
+ any& operator=(T&& rhs) {
+ any tmp(in_place_type_t<VT>(), std::forward<T>(rhs));
+ tmp.swap(*this);
+ return *this;
+ }
+
+ // Modifiers
+
+ // any::emplace()
+ //
+ // Emplaces a value within an `absl::any` object by calling `any::reset()`,
+ // initializing the contained value as if direct-non-list-initializing an
+ // object of type `VT` with the arguments `std::forward<Args>(args)...`, and
+ // returning a reference to the new contained value.
+ //
+ // Note: If an exception is thrown during the call to `VT`'s constructor,
+ // `*this` does not contain a value, and any previously contained value has
+ // been destroyed.
+ template <
+ typename T, typename... Args, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<std::is_copy_constructible<VT>::value &&
+ std::is_constructible<VT, Args...>::value>* = nullptr>
+ VT& emplace(Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ reset(); // NOTE: reset() is required here even in the world of exceptions.
+ Obj<VT>* const object_ptr =
+ new Obj<VT>(in_place, std::forward<Args>(args)...);
+ obj_ = std::unique_ptr<ObjInterface>(object_ptr);
+ return object_ptr->value;
+ }
+
+ // Overload of `any::emplace()` to emplace a value within an `absl::any`
+ // object by calling `any::reset()`, initializing the contained value as if
+ // direct-non-list-initializing an object of type `VT` with the arguments
+ // `initializer_list, std::forward<Args>(args)...`, and returning a reference
+ // to the new contained value.
+ //
+ // Note: If an exception is thrown during the call to `VT`'s constructor,
+ // `*this` does not contain a value, and any previously contained value has
+ // been destroyed. The function shall not participate in overload resolution
+ // unless `is_copy_constructible_v<VT>` is `true` and
+ // `is_constructible_v<VT, initializer_list<U>&, Args...>` is `true`.
+ template <
+ typename T, typename U, typename... Args, typename VT = absl::decay_t<T>,
+ absl::enable_if_t<std::is_copy_constructible<VT>::value &&
+ std::is_constructible<VT, std::initializer_list<U>&,
+ Args...>::value>* = nullptr>
+ VT& emplace(std::initializer_list<U> ilist,
+ Args&&... args) ABSL_ATTRIBUTE_LIFETIME_BOUND {
+ reset(); // NOTE: reset() is required here even in the world of exceptions.
+ Obj<VT>* const object_ptr =
+ new Obj<VT>(in_place, ilist, std::forward<Args>(args)...);
+ obj_ = std::unique_ptr<ObjInterface>(object_ptr);
+ return object_ptr->value;
+ }
+
+ // any::reset()
+ //
+ // Resets the state of the `absl::any` object, destroying the contained object
+ // if present.
+ void reset() noexcept { obj_ = nullptr; }
+
+ // any::swap()
+ //
+ // Swaps the passed value and the value of this `absl::any` object.
+ void swap(any& other) noexcept { obj_.swap(other.obj_); }
+
+ // Observers
+
+ // any::has_value()
+ //
+ // Returns `true` if the `any` object has a contained value, otherwise
+ // returns `false`.
+ bool has_value() const noexcept { return obj_ != nullptr; }
+
+#ifdef ABSL_INTERNAL_HAS_RTTI
+ // Returns: typeid(T) if *this has a contained object of type T, otherwise
+ // typeid(void).
+ const std::type_info& type() const noexcept {
+ if (has_value()) {
+ return obj_->Type();
+ }
+
+ return typeid(void);
+ }
+#endif // ABSL_INTERNAL_HAS_RTTI
+
+ private:
+ // Tagged type-erased abstraction for holding a cloneable object.
+ class ObjInterface {
+ public:
+ virtual ~ObjInterface() = default;
+ virtual std::unique_ptr<ObjInterface> Clone() const = 0;
+ virtual const void* ObjTypeId() const noexcept = 0;
+#ifdef ABSL_INTERNAL_HAS_RTTI
+ virtual const std::type_info& Type() const noexcept = 0;
+#endif // ABSL_INTERNAL_HAS_RTTI
+ };
+
+ // Hold a value of some queryable type, with an ability to Clone it.
+ template <typename T>
+ class Obj : public ObjInterface {
+ public:
+ template <typename... Args>
+ explicit Obj(in_place_t /*tag*/, Args&&... args)
+ : value(std::forward<Args>(args)...) {}
+
+ std::unique_ptr<ObjInterface> Clone() const final {
+ return std::unique_ptr<ObjInterface>(new Obj(in_place, value));
+ }
+
+ const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
+
+#ifdef ABSL_INTERNAL_HAS_RTTI
+ const std::type_info& Type() const noexcept final { return typeid(T); }
+#endif // ABSL_INTERNAL_HAS_RTTI
+
+ T value;
+ };
+
+ std::unique_ptr<ObjInterface> CloneObj() const {
+ if (!obj_) return nullptr;
+ return obj_->Clone();
+ }
+
+ template <typename T>
+ constexpr static const void* IdForType() {
+ // Note: This type dance is to make the behavior consistent with typeid.
+ using NormalizedType =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+
+ return base_internal::FastTypeId<NormalizedType>();
+ }
+
+ const void* GetObjTypeId() const {
+ return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
+ }
+
+ // `absl::any` nonmember functions //
+
+ // Description at the declaration site (top of file).
+ template <typename ValueType>
+ friend ValueType any_cast(const any& operand);
+
+ // Description at the declaration site (top of file).
+ template <typename ValueType>
+ friend ValueType any_cast(any& operand); // NOLINT(runtime/references)
+
+ // Description at the declaration site (top of file).
+ template <typename T>
+ friend const T* any_cast(const any* operand) noexcept;
+
+ // Description at the declaration site (top of file).
+ template <typename T>
+ friend T* any_cast(any* operand) noexcept;
+
+ std::unique_ptr<ObjInterface> obj_;
+};
+
+// -----------------------------------------------------------------------------
+// Implementation Details
+// -----------------------------------------------------------------------------
+
+constexpr any::any() noexcept = default;
+
+template <typename T>
+struct any::IsInPlaceType : std::false_type {};
+
+template <typename T>
+struct any::IsInPlaceType<in_place_type_t<T>> : std::true_type {};
+
+inline void swap(any& x, any& y) noexcept { x.swap(y); }
+
+// Description at the declaration site (top of file).
+template <typename T, typename... Args>
+any make_any(Args&&... args) {
+ return any(in_place_type_t<T>(), std::forward<Args>(args)...);
+}
+
+// Description at the declaration site (top of file).
+template <typename T, typename U, typename... Args>
+any make_any(std::initializer_list<U> il, Args&&... args) {
+ return any(in_place_type_t<T>(), il, std::forward<Args>(args)...);
+}
+
+// Description at the declaration site (top of file).
+template <typename ValueType>
+ValueType any_cast(const any& operand) {
+ using U = typename std::remove_cv<
+ typename std::remove_reference<ValueType>::type>::type;
+ static_assert(std::is_constructible<ValueType, const U&>::value,
+ "Invalid ValueType");
+ auto* const result = (any_cast<U>)(&operand);
+ if (result == nullptr) {
+ any_internal::ThrowBadAnyCast();
+ }
+ return static_cast<ValueType>(*result);
+}
+
+// Description at the declaration site (top of file).
+template <typename ValueType>
+ValueType any_cast(any& operand) { // NOLINT(runtime/references)
+ using U = typename std::remove_cv<
+ typename std::remove_reference<ValueType>::type>::type;
+ static_assert(std::is_constructible<ValueType, U&>::value,
+ "Invalid ValueType");
+ auto* result = (any_cast<U>)(&operand);
+ if (result == nullptr) {
+ any_internal::ThrowBadAnyCast();
+ }
+ return static_cast<ValueType>(*result);
+}
+
+// Description at the declaration site (top of file).
+template <typename ValueType>
+ValueType any_cast(any&& operand) {
+ using U = typename std::remove_cv<
+ typename std::remove_reference<ValueType>::type>::type;
+ static_assert(std::is_constructible<ValueType, U>::value,
+ "Invalid ValueType");
+ return static_cast<ValueType>(std::move((any_cast<U&>)(operand)));
+}
+
+// Description at the declaration site (top of file).
+template <typename T>
+const T* any_cast(const any* operand) noexcept {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return operand && operand->GetObjTypeId() == any::IdForType<U>()
+ ? std::addressof(
+ static_cast<const any::Obj<U>*>(operand->obj_.get())->value)
+ : nullptr;
+}
+
+// Description at the declaration site (top of file).
+template <typename T>
+T* any_cast(any* operand) noexcept {
+ using U =
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type;
+ return operand && operand->GetObjTypeId() == any::IdForType<U>()
+ ? std::addressof(
+ static_cast<any::Obj<U>*>(operand->obj_.get())->value)
+ : nullptr;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_USES_STD_ANY
+
+#endif // ABSL_TYPES_ANY_H_
diff --git a/contrib/restricted/abseil-cpp/absl/utility/.yandex_meta/licenses.list.txt b/contrib/restricted/abseil-cpp/absl/utility/.yandex_meta/licenses.list.txt
new file mode 100644
index 0000000000..9c355ce9b6
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/utility/.yandex_meta/licenses.list.txt
@@ -0,0 +1,34 @@
+====================Apache-2.0====================
+// 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.
+
+
+====================Apache-2.0====================
+// 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.
+
+
+====================COPYRIGHT====================
+// Copyright 2017 The Abseil Authors.
+
+
+====================COPYRIGHT====================
+// Copyright 2023 The Abseil Authors.
diff --git a/contrib/restricted/abseil-cpp/absl/utility/internal/if_constexpr.h b/contrib/restricted/abseil-cpp/absl/utility/internal/if_constexpr.h
new file mode 100644
index 0000000000..7a26311daa
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/absl/utility/internal/if_constexpr.h
@@ -0,0 +1,70 @@
+// 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.
+
+// The IfConstexpr and IfConstexprElse utilities in this file are meant to be
+// used to emulate `if constexpr` in pre-C++17 mode in library implementation.
+// The motivation is to allow for avoiding complex SFINAE.
+//
+// The functions passed in must depend on the type(s) of the object(s) that
+// require SFINAE. For example:
+// template<typename T>
+// int MaybeFoo(T& t) {
+// if constexpr (HasFoo<T>::value) return t.foo();
+// return 0;
+// }
+//
+// can be written in pre-C++17 as:
+//
+// template<typename T>
+// int MaybeFoo(T& t) {
+// int i = 0;
+// absl::utility_internal::IfConstexpr<HasFoo<T>::value>(
+// [&](const auto& fooer) { i = fooer.foo(); }, t);
+// return i;
+// }
+
+#ifndef ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
+#define ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
+
+#include <tuple>
+#include <utility>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace utility_internal {
+
+template <bool condition, typename TrueFunc, typename FalseFunc,
+ typename... Args>
+auto IfConstexprElse(TrueFunc&& true_func, FalseFunc&& false_func,
+ Args&&... args) {
+ return std::get<condition>(std::forward_as_tuple(
+ std::forward<FalseFunc>(false_func), std::forward<TrueFunc>(true_func)))(
+ std::forward<Args>(args)...);
+}
+
+template <bool condition, typename Func, typename... Args>
+void IfConstexpr(Func&& func, Args&&... args) {
+ IfConstexprElse<condition>(std::forward<Func>(func), [](auto&&...){},
+ std::forward<Args>(args)...);
+}
+
+} // namespace utility_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_UTILITY_INTERNAL_IF_CONSTEXPR_H_
diff --git a/contrib/restricted/abseil-cpp/patches/fix-cuda-10.patch b/contrib/restricted/abseil-cpp/patches/fix-cuda-10.patch
new file mode 100644
index 0000000000..4b8f880600
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/patches/fix-cuda-10.patch
@@ -0,0 +1,11 @@
+--- a/absl/types/compare.h (index)
++++ b/absl/types/compare.h (working tree)
+@@ -69,7 +69,7 @@ using value_type = int8_t;
+
+ class OnlyLiteralZero {
+ public:
+-#if ABSL_HAVE_ATTRIBUTE(enable_if)
++#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__CUDACC__)
+ // On clang, we can avoid triggering modernize-use-nullptr by only enabling
+ // this overload when the value is a compile time integer constant equal to 0.
+ //
diff --git a/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch b/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch
new file mode 100644
index 0000000000..6c2740f66f
--- /dev/null
+++ b/contrib/restricted/abseil-cpp/patches/pr1728-fix-ndk-r25.patch
@@ -0,0 +1,87 @@
+From 90a8bda23077508ca208e7afc535da1e2c7d59ae Mon Sep 17 00:00:00 2001
+From: Yuriy Chernyshov <thegeorg@yandex-team.com>
+Date: Thu, 25 Jul 2024 22:50:40 +0300
+Subject: [PATCH 1/3] Workaround broken compilation against NDK r25
+
+---
+ absl/time/time.h | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/absl/time/time.h b/absl/time/time.h
+index f133c2d2ca8..15edbb4a667 100644
+--- a/absl/time/time.h
++++ b/absl/time/time.h
+@@ -76,9 +76,9 @@ struct timeval;
+ #endif
+ #include <chrono> // NOLINT(build/c++11)
+
+-#ifdef __cpp_impl_three_way_comparison
++#ifdef __cpp_lib_three_way_comparison
+ #include <compare>
+-#endif // __cpp_impl_three_way_comparison
++#endif // __cpp_lib_three_way_comparison
+
+ #include <cmath>
+ #include <cstdint>
+@@ -313,12 +313,12 @@ class Duration {
+
+ // Relational Operators
+
+-#ifdef __cpp_impl_three_way_comparison
++#ifdef __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
+ Duration lhs, Duration rhs);
+
+-#endif // __cpp_impl_three_way_comparison
++#endif // __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
+ Duration rhs);
+@@ -853,9 +853,9 @@ class Time {
+ friend constexpr Time time_internal::FromUnixDuration(Duration d);
+ friend constexpr Duration time_internal::ToUnixDuration(Time t);
+
+-#ifdef __cpp_impl_three_way_comparison
++#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::strong_ordering operator<=>(Time lhs, Time rhs);
+-#endif // __cpp_impl_three_way_comparison
++#endif // __cpp_lib_three_way_comparison
+
+ friend constexpr bool operator<(Time lhs, Time rhs);
+ friend constexpr bool operator==(Time lhs, Time rhs);
+@@ -868,14 +868,14 @@ class Time {
+ };
+
+ // Relational Operators
+-#ifdef __cpp_impl_three_way_comparison
++#ifdef __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
+ Time lhs, Time rhs) {
+ return lhs.rep_ <=> rhs.rep_;
+ }
+
+-#endif // __cpp_impl_three_way_comparison
++#endif // __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Time lhs, Time rhs) {
+ return lhs.rep_ < rhs.rep_;
+@@ -1753,7 +1753,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator<(Duration lhs,
+ }
+
+
+-#ifdef __cpp_impl_three_way_comparison
++#ifdef __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
+ Duration lhs, Duration rhs) {
+@@ -1769,7 +1769,7 @@ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr std::strong_ordering operator<=>(
+ : lhs_lo <=> rhs_lo;
+ }
+
+-#endif // __cpp_impl_three_way_comparison
++#endif // __cpp_lib_three_way_comparison
+
+ ABSL_ATTRIBUTE_CONST_FUNCTION constexpr bool operator==(Duration lhs,
+ Duration rhs) {