summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBilly Donahue <billy.donahue@mongodb.com>2021-07-02 16:49:37 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-07-13 17:39:36 +0000
commitdefbe4582778e3da3abdc23c73ef7639543ab380 (patch)
tree65b9be91aa0357fa411b63d0a31d694a6f3908de
parent129b132138d1e129ef1a3cee31fe0da4b19c8c48 (diff)
downloadmongo-defbe4582778e3da3abdc23c73ef7639543ab380.tar.gz
SERVER-51476 upgrade to Abseil 20210324.1
-rw-r--r--README.third_party.md2
-rw-r--r--etc/third_party_components.yml1
-rw-r--r--src/third_party/abseil-cpp-master/SConscript1
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/BUILD.bazel25
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilDll.cmake526
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilHelpers.cmake441
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/CMakeLists.txt.in15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/DownloadGTest.cmake32
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/CMakeLists.txt.in14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/DownloadGTest.cmake41
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/README.md28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/abslConfig.cmake.in8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/simple.cc23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/test.sh96
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/CONTRIBUTING.md9
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/FAQ.md164
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/LICENSE7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/LTS.md13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/README.md45
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/UPGRADES.md17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/WORKSPACE52
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/BUILD.bazel49
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/abseil.podspec.gen.py229
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/BUILD.bazel14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm.h19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container.h124
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container_test.cc154
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/equal_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/BUILD.bazel435
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/attributes.h201
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/bit_cast_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once.h19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once_test.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/casts.h42
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config.h354
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/const_init.h7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.cc129
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.h776
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/exception_safety_testing_test.cc24
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_a.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_b.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook.h57
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test.cc35
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.cc32
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h34
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits.h193
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits_test.cc97
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cmake_thread_test.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.cc30
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.h21
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/direct_mmap.h16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/dynamic_annotations.h398
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian.h77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian_test.cc28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver.h43
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver_test.cc45
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.cc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.h19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_testing.h2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.cc93
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.h130
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased_test.cc199
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id.h48
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id_test.cc123
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/hide_ptr.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/identity.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable.h2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable_testing.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/invoke.h49
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.cc56
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc_test.cc28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_scheduling.h40
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/per_thread_tls.h14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.cc53
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.h211
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc79
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_test.cc177
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/pretty_function.h2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.cc76
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.h47
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scheduling_mode.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.cc81
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.h45
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env_test.cc99
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.cc84
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.h83
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_akaros.inc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_linux.inc34
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_posix.inc12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.cc17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.h26
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_win32.inc12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.cc88
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.h39
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_benchmark.cc29
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_test.cc88
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.cc93
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.h23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo_test.cc31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_annotations.h271
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.cc36
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.h114
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_test.cc15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.cc122
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/tsan_mutex_interface.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unaligned_access.h245
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unique_small_name_test.cc77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.cc45
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.h15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/invoke_test.cc131
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.cc27
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.h70
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity_test.cc204
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/macros.h174
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization.h105
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization_test.cc129
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/options.h238
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/policy_checks.h14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/port.h3
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/raw_logging_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/spinlock_test_common.cc25
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/thread_annotations.h248
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/base/throw_delegate_test.cc15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/BUILD.bazel66
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup.h140
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup_test.cc267
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/internal/cleanup.h81
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/compiler_config_setting.bzl39
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/BUILD.bazel402
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_benchmark.cc701
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_map.h768
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_set.h683
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.cc2899
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.h166
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array.h104
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_benchmark.cc11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc102
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_test.cc203
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map.h46
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map_test.cc127
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set.h31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set_test.cc60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector.h1377
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_benchmark.cc590
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_exception_safety_test.cc508
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_test.cc311
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree.h2620
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree_container.h682
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/common.h206
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple.h165
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple_test.cc226
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory.h141
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory_test.cc75
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/counting_allocator.h114
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults.h24
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc110
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.cc10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.h13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits.h35
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.cc274
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.h322
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc377
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/have_sse.h21
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/inlined_vector.h967
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout.h27
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_benchmark.cc122
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_test.cc568
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_map.h11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h648
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc79
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc396
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc590
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_test.cc520
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.h16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/tracked.h7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h147
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_members_test.h87
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h49
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_test.cc20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h153
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_members_test.h86
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_test.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map.h31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map_test.cc65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set.h55
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set_test.cc50
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake81
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake159
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_copts.bzl159
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/configure_copts.bzl80
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/copts.py229
-rwxr-xr-xsrc/third_party/abseil-cpp-master/abseil-cpp/absl/copts/generate_copts.py3
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/BUILD.bazel113
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.cc61
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler_test.cc36
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.cc20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.h7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.cc146
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle_test.cc40
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.cc54
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.h11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_config.h60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc54
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/symbolize.h44
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.cc25
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.cc23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.h28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_disable.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_fail_test.cc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_test.cc10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.cc5
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.h36
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_darwin.inc101
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_elf.inc203
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_test.cc76
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_unimplemented.inc7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_win32.inc23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/BUILD.bazel538
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.cc34
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.h200
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag_test.cc231
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config.h76
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config_test.cc61
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/declare.h65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.cc38
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.h398
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.cc168
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.lds13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test.cc945
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test_defs.cc24
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/commandlineflag.h68
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.cc581
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.h747
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/parse.h59
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util.h62
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util_test.cc46
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.cc65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.h61
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.cc60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.h50
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name_test.cc61
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/registry.h97
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock.h187
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock_test.cc169
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.cc518
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.h104
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage_test.cc493
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.cc241
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.h264
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling_test.cc904
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.cc823
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.h60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse_test.cc929
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.cc350
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.h90
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection_test.cc265
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.cc65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.h43
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.cc165
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.h135
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config_test.cc205
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/BUILD.bazel93
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front.h184
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front_test.cc231
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref.h139
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_benchmark.cc142
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_test.cc257
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/front_binder.h95
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/function_ref.h106
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/BUILD.bazel65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash.h47
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_benchmark.cc254
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_test.cc589
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_testing.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.cc31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.h28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.cc51
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.h467
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/print_hash_of.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/spy_hash_state.h23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.cc111
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.h48
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash_test.cc486
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/BUILD.bazel18
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory.h36
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_exception_safety_test.cc13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_test.cc44
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/BUILD.bazel23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits.h389
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits_test.cc464
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/BUILD.bazel51
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits.h177
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits_test.cc573
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.cc201
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.h413
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_benchmark.cc163
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_have_intrinsic.inc286
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_no_intrinsic.inc292
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_stream_test.cc731
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_test.cc788
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/bits.h358
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/representation.h55
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/BUILD.bazel514
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/benchmarks.cc383
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution.h200
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution_test.cc217
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution.h427
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution_test.cc601
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref.h181
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref_test.cc102
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.cc98
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.h247
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution_test.cc250
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions.h452
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions_test.cc455
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/examples_test.cc99
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution.h165
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution_test.cc418
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.cc104
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.h275
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution_test.cc563
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/generators_test.cc179
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/BUILD.bazel739
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.cc232
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.h89
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square_test.cc365
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_caller.h92
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.cc418
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.h113
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util_test.cc193
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq.h92
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc204
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits.h268
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc336
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath.h57
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath_test.cc97
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc143
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real.h146
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real_test.cc496
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver.h245
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc372
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_helpers.h134
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_overload_set.h100
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.cc804
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.h172
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark_test.cc77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base.h150
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base_test.cc245
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine.h308
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine_test.cc638
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/platform.h171
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.cc254
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.h131
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg_test.cc182
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.cc91
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.h102
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_benchmarks.cc174
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.cc221
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.h33
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine.h232
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine_test.cc656
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.cc573
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.h50
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes_test.cc104
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_round_keys.cc462
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.cc457
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.h40
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow_test.cc64
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_test.cc70
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_traits.h88
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq.h167
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq_test.cc168
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.cc219
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.h104
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material_test.cc202
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/sequence_urbg.h60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits.h101
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits_test.cc126
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper.h244
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper_test.cc279
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply.h111
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply_test.cc65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution.h257
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc280
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions.h266
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions_test.cc72
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen.h240
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen_test.cc392
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution.h258
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution_test.cc573
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/random.h189
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.cc46
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.h55
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.cc29
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.h110
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences_test.cc126
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution.h275
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution_test.cc259
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution.h202
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution_test.cc349
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution.h271
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution_test.cc427
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/BUILD.bazel103
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/status_internal.h69
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/statusor_internal.h396
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.cc452
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.h878
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.cc38
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.h51
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_test.cc484
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.cc71
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.h760
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor_test.cc1811
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/BUILD.bazel201
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.cc10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.h11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_test.cc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.cc26
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.h10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_benchmark.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_test.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.cc1953
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.h1394
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_reader_test.cc173
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_test.cc1572
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test.cc1715
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test_helpers.h60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.cc288
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.h22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_test.cc86
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.cc10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.h14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc59
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.cc26
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.h5
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.cc83
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.h543
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_flat.h146
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.cc897
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.h589
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h114
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.cc180
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.h58
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping_test_common.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/numbers_test_common.h13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.h20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized.h13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/stl_type_traits.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.cc391
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.h242
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg_test.cc31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.cc68
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.h88
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind_test.cc64
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker.h46
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker_test.cc100
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/convert_test.cc865
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.cc73
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.h395
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension_test.cc37
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc1106
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.h22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.h19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output_test.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.cc209
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.h173
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser_test.cc120
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_join_internal.h17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_split_internal.h67
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant.h64
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant_test.cc60
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.h7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8_test.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.cc13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.h35
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match_test.cc23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.cc347
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.h134
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_benchmark.cc25
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_test.cc234
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.cc77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.h47
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_benchmark.cc51
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_test.cc102
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format.h369
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc228
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join.h84
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_benchmark.cc5
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_test.cc20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.cc9
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.h44
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_benchmark.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_test.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.cc8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.h92
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_benchmark.cc28
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_test.cc108
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.h226
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_benchmark.cc54
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_test.cc182
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip_test.cc5
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.h157
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute_test.cc26
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-1.txt3
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-2.txt1
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/BUILD.bazel77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc38
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.h9
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/futex.h154
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.cc11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/kernel_timeout.h63
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc318
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc259
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.h20
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/thread_pool.h11
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.cc284
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.h58
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/lifetime_test.cc12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.cc412
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.h242
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_benchmark.cc229
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_test.cc100
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.cc13
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.h14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification_test.cc14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/BUILD.bazel18
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.cc111
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.h78
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_benchmark.cc22
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_test.cc174
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.cc290
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_benchmark.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_test.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration.cc178
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_benchmark.cc19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_test.cc33
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format.cc89
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_benchmark.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_test.cc17
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/BUILD.bazel62
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h15
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h176
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h31
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc1256
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc49
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc54
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h5
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc282
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc517
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc67
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h7
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc393
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h23
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc145
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc49
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc1301
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h6
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/tzfile.h65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc77
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/version2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab19
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_chrono.inc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_posix.inc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.cc10
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.h4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.cc35
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.h134
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_benchmark.cc2
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_test.cc149
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_zone_test.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/BUILD.bazel171
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any.h61
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_exception_safety_test.cc14
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_test.cc81
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.cc8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.h12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.cc8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.h12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.cc8
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.h12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare.h600
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare_test.cc389
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_aliases.h447
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_archetype.h978
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_profile.h931
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing.h1386
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_helpers.h391
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_test.cc1556
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/optional.h396
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/parentheses.h34
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/span.h128
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/transform_args.h246
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/variant.h86
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.cc16
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.h472
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_exception_safety_test.cc12
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_test.cc125
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span.h304
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span_test.cc72
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant.h50
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_benchmark.cc4
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_exception_safety_test.cc30
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_test.cc273
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/BUILD.bazel26
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility.h115
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility_test.cc35
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/absl_alternate_options.h29
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_common.sh25
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_install_test.sh43
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh99
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh97
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh95
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh91
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_docker_containers.sh21
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh89
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh95
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh65
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc_alpine_cmake.sh64
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_bazel.sh54
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_cmake.sh56
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/conanfile.py51
-rw-r--r--src/third_party/abseil-cpp-master/abseil-cpp/create_lts.py121
-rwxr-xr-xsrc/third_party/abseil-cpp-master/scripts/import.sh2
702 files changed, 104279 insertions, 12663 deletions
diff --git a/README.third_party.md b/README.third_party.md
index c0317988766..5c3ad24d2bc 100644
--- a/README.third_party.md
+++ b/README.third_party.md
@@ -21,7 +21,7 @@ a notice will be included in
| Name | License | Upstream Version | Vendored Version | Emits persisted data | Distributed in Release Binaries |
| ---------------------------| ----------------- | ---------------- | ------------------| :------------------: | :-----------------------------: |
-| [abseil-cpp] | Apache-2.0 | | 070f6e47b3 | | ✗ |
+| [abseil-cpp] | Apache-2.0 | 20210324.1 | 20210324.1 | | ✗ |
| Aladdin MD5 | Zlib | | Unknown | ✗ | ✗ |
| [ASIO] | BSL-1.0 | 1.16.1 | b0926b61b0 | | ✗ |
| [benchmark] | Apache-2.0 | 1.5.2 | 1.5.2 | | |
diff --git a/etc/third_party_components.yml b/etc/third_party_components.yml
index 4312bd4b083..15ef849fab6 100644
--- a/etc/third_party_components.yml
+++ b/etc/third_party_components.yml
@@ -45,7 +45,6 @@ components:
release_monitoring_id: 115295
local_directory_path: src/third_party/abseil-cpp-master
team_owner: "Service Architecture"
- upgrade_suppression: TODO SERVER-51476
# Note: abseil exists in Black Duck, but not OpenHub
Aladdin MD5:
diff --git a/src/third_party/abseil-cpp-master/SConscript b/src/third_party/abseil-cpp-master/SConscript
index 99f6a378c1b..ad6caeb01d1 100644
--- a/src/third_party/abseil-cpp-master/SConscript
+++ b/src/third_party/abseil-cpp-master/SConscript
@@ -9,6 +9,7 @@ env.Library(
source=[
"abseil-cpp/absl/hash/internal/city.cc",
"abseil-cpp/absl/hash/internal/hash.cc",
+ "abseil-cpp/absl/hash/internal/wyhash.cc",
]
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/BUILD.bazel
new file mode 100644
index 00000000000..79fb0ecd73e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/BUILD.bazel
@@ -0,0 +1,25 @@
+#
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"]) # Apache 2.0
+
+# Expose license for external usage through bazel.
+exports_files([
+ "AUTHORS",
+ "LICENSE",
+])
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilDll.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilDll.cmake
new file mode 100644
index 00000000000..253c73ff4df
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilDll.cmake
@@ -0,0 +1,526 @@
+include(CMakeParseArguments)
+include(GNUInstallDirs)
+
+set(ABSL_INTERNAL_DLL_FILES
+ "algorithm/algorithm.h"
+ "algorithm/container.h"
+ "base/attributes.h"
+ "base/call_once.h"
+ "base/casts.h"
+ "base/config.h"
+ "base/const_init.h"
+ "base/dynamic_annotations.h"
+ "base/internal/atomic_hook.h"
+ "base/internal/cycleclock.cc"
+ "base/internal/cycleclock.h"
+ "base/internal/direct_mmap.h"
+ "base/internal/dynamic_annotations.h"
+ "base/internal/endian.h"
+ "base/internal/errno_saver.h"
+ "base/internal/exponential_biased.cc"
+ "base/internal/exponential_biased.h"
+ "base/internal/fast_type_id.h"
+ "base/internal/hide_ptr.h"
+ "base/internal/identity.h"
+ "base/internal/invoke.h"
+ "base/internal/inline_variable.h"
+ "base/internal/low_level_alloc.cc"
+ "base/internal/low_level_alloc.h"
+ "base/internal/low_level_scheduling.h"
+ "base/internal/per_thread_tls.h"
+ "base/internal/periodic_sampler.cc"
+ "base/internal/periodic_sampler.h"
+ "base/internal/pretty_function.h"
+ "base/internal/raw_logging.cc"
+ "base/internal/raw_logging.h"
+ "base/internal/scheduling_mode.h"
+ "base/internal/scoped_set_env.cc"
+ "base/internal/scoped_set_env.h"
+ "base/internal/strerror.h"
+ "base/internal/strerror.cc"
+ "base/internal/spinlock.cc"
+ "base/internal/spinlock.h"
+ "base/internal/spinlock_wait.cc"
+ "base/internal/spinlock_wait.h"
+ "base/internal/sysinfo.cc"
+ "base/internal/sysinfo.h"
+ "base/internal/thread_annotations.h"
+ "base/internal/thread_identity.cc"
+ "base/internal/thread_identity.h"
+ "base/internal/throw_delegate.cc"
+ "base/internal/throw_delegate.h"
+ "base/internal/tsan_mutex_interface.h"
+ "base/internal/unaligned_access.h"
+ "base/internal/unscaledcycleclock.cc"
+ "base/internal/unscaledcycleclock.h"
+ "base/log_severity.cc"
+ "base/log_severity.h"
+ "base/macros.h"
+ "base/optimization.h"
+ "base/options.h"
+ "base/policy_checks.h"
+ "base/port.h"
+ "base/thread_annotations.h"
+ "cleanup/cleanup.h"
+ "cleanup/internal/cleanup.h"
+ "container/btree_map.h"
+ "container/btree_set.h"
+ "container/fixed_array.h"
+ "container/flat_hash_map.h"
+ "container/flat_hash_set.h"
+ "container/inlined_vector.h"
+ "container/internal/btree.h"
+ "container/internal/btree_container.h"
+ "container/internal/common.h"
+ "container/internal/compressed_tuple.h"
+ "container/internal/container_memory.h"
+ "container/internal/counting_allocator.h"
+ "container/internal/hash_function_defaults.h"
+ "container/internal/hash_policy_traits.h"
+ "container/internal/hashtable_debug.h"
+ "container/internal/hashtable_debug_hooks.h"
+ "container/internal/hashtablez_sampler.cc"
+ "container/internal/hashtablez_sampler.h"
+ "container/internal/hashtablez_sampler_force_weak_definition.cc"
+ "container/internal/have_sse.h"
+ "container/internal/inlined_vector.h"
+ "container/internal/layout.h"
+ "container/internal/node_hash_policy.h"
+ "container/internal/raw_hash_map.h"
+ "container/internal/raw_hash_set.cc"
+ "container/internal/raw_hash_set.h"
+ "container/internal/tracked.h"
+ "container/node_hash_map.h"
+ "container/node_hash_set.h"
+ "debugging/failure_signal_handler.cc"
+ "debugging/failure_signal_handler.h"
+ "debugging/leak_check.h"
+ "debugging/leak_check_disable.cc"
+ "debugging/stacktrace.cc"
+ "debugging/stacktrace.h"
+ "debugging/symbolize.cc"
+ "debugging/symbolize.h"
+ "debugging/internal/address_is_readable.cc"
+ "debugging/internal/address_is_readable.h"
+ "debugging/internal/demangle.cc"
+ "debugging/internal/demangle.h"
+ "debugging/internal/elf_mem_image.cc"
+ "debugging/internal/elf_mem_image.h"
+ "debugging/internal/examine_stack.cc"
+ "debugging/internal/examine_stack.h"
+ "debugging/internal/stack_consumption.cc"
+ "debugging/internal/stack_consumption.h"
+ "debugging/internal/stacktrace_config.h"
+ "debugging/internal/symbolize.h"
+ "debugging/internal/vdso_support.cc"
+ "debugging/internal/vdso_support.h"
+ "functional/internal/front_binder.h"
+ "functional/bind_front.h"
+ "functional/function_ref.h"
+ "functional/internal/function_ref.h"
+ "hash/hash.h"
+ "hash/internal/city.h"
+ "hash/internal/city.cc"
+ "hash/internal/hash.h"
+ "hash/internal/hash.cc"
+ "hash/internal/spy_hash_state.h"
+ "hash/internal/wyhash.h"
+ "hash/internal/wyhash.cc"
+ "memory/memory.h"
+ "meta/type_traits.h"
+ "numeric/bits.h"
+ "numeric/int128.cc"
+ "numeric/int128.h"
+ "numeric/internal/bits.h"
+ "numeric/internal/representation.h"
+ "random/bernoulli_distribution.h"
+ "random/beta_distribution.h"
+ "random/bit_gen_ref.h"
+ "random/discrete_distribution.cc"
+ "random/discrete_distribution.h"
+ "random/distributions.h"
+ "random/exponential_distribution.h"
+ "random/gaussian_distribution.cc"
+ "random/gaussian_distribution.h"
+ "random/internal/distribution_caller.h"
+ "random/internal/fastmath.h"
+ "random/internal/fast_uniform_bits.h"
+ "random/internal/generate_real.h"
+ "random/internal/iostream_state_saver.h"
+ "random/internal/mock_helpers.h"
+ "random/internal/nonsecure_base.h"
+ "random/internal/pcg_engine.h"
+ "random/internal/platform.h"
+ "random/internal/pool_urbg.cc"
+ "random/internal/pool_urbg.h"
+ "random/internal/randen.cc"
+ "random/internal/randen.h"
+ "random/internal/randen_detect.cc"
+ "random/internal/randen_detect.h"
+ "random/internal/randen_engine.h"
+ "random/internal/randen_hwaes.cc"
+ "random/internal/randen_hwaes.h"
+ "random/internal/randen_round_keys.cc"
+ "random/internal/randen_slow.cc"
+ "random/internal/randen_slow.h"
+ "random/internal/randen_traits.h"
+ "random/internal/salted_seed_seq.h"
+ "random/internal/seed_material.cc"
+ "random/internal/seed_material.h"
+ "random/internal/sequence_urbg.h"
+ "random/internal/traits.h"
+ "random/internal/uniform_helper.h"
+ "random/internal/wide_multiply.h"
+ "random/log_uniform_int_distribution.h"
+ "random/poisson_distribution.h"
+ "random/random.h"
+ "random/seed_gen_exception.cc"
+ "random/seed_gen_exception.h"
+ "random/seed_sequences.cc"
+ "random/seed_sequences.h"
+ "random/uniform_int_distribution.h"
+ "random/uniform_real_distribution.h"
+ "random/zipf_distribution.h"
+ "status/internal/status_internal.h"
+ "status/internal/statusor_internal.h"
+ "status/status.h"
+ "status/status.cc"
+ "status/statusor.h"
+ "status/statusor.cc"
+ "status/status_payload_printer.h"
+ "status/status_payload_printer.cc"
+ "strings/ascii.cc"
+ "strings/ascii.h"
+ "strings/charconv.cc"
+ "strings/charconv.h"
+ "strings/cord.cc"
+ "strings/cord.h"
+ "strings/escaping.cc"
+ "strings/escaping.h"
+ "strings/internal/cord_internal.cc"
+ "strings/internal/cord_internal.h"
+ "strings/internal/cord_rep_flat.h"
+ "strings/internal/cord_rep_ring.cc"
+ "strings/internal/cord_rep_ring.h"
+ "strings/internal/cord_rep_ring_reader.h"
+ "strings/internal/charconv_bigint.cc"
+ "strings/internal/charconv_bigint.h"
+ "strings/internal/charconv_parse.cc"
+ "strings/internal/charconv_parse.h"
+ "strings/internal/stl_type_traits.h"
+ "strings/internal/string_constant.h"
+ "strings/match.cc"
+ "strings/match.h"
+ "strings/numbers.cc"
+ "strings/numbers.h"
+ "strings/str_format.h"
+ "strings/str_cat.cc"
+ "strings/str_cat.h"
+ "strings/str_join.h"
+ "strings/str_replace.cc"
+ "strings/str_replace.h"
+ "strings/str_split.cc"
+ "strings/str_split.h"
+ "strings/string_view.cc"
+ "strings/string_view.h"
+ "strings/strip.h"
+ "strings/substitute.cc"
+ "strings/substitute.h"
+ "strings/internal/char_map.h"
+ "strings/internal/escaping.h"
+ "strings/internal/escaping.cc"
+ "strings/internal/memutil.cc"
+ "strings/internal/memutil.h"
+ "strings/internal/ostringstream.cc"
+ "strings/internal/ostringstream.h"
+ "strings/internal/pow10_helper.cc"
+ "strings/internal/pow10_helper.h"
+ "strings/internal/resize_uninitialized.h"
+ "strings/internal/str_format/arg.cc"
+ "strings/internal/str_format/arg.h"
+ "strings/internal/str_format/bind.cc"
+ "strings/internal/str_format/bind.h"
+ "strings/internal/str_format/checker.h"
+ "strings/internal/str_format/extension.cc"
+ "strings/internal/str_format/extension.h"
+ "strings/internal/str_format/float_conversion.cc"
+ "strings/internal/str_format/float_conversion.h"
+ "strings/internal/str_format/output.cc"
+ "strings/internal/str_format/output.h"
+ "strings/internal/str_format/parser.cc"
+ "strings/internal/str_format/parser.h"
+ "strings/internal/str_join_internal.h"
+ "strings/internal/str_split_internal.h"
+ "strings/internal/utf8.cc"
+ "strings/internal/utf8.h"
+ "synchronization/barrier.cc"
+ "synchronization/barrier.h"
+ "synchronization/blocking_counter.cc"
+ "synchronization/blocking_counter.h"
+ "synchronization/mutex.cc"
+ "synchronization/mutex.h"
+ "synchronization/notification.cc"
+ "synchronization/notification.h"
+ "synchronization/internal/create_thread_identity.cc"
+ "synchronization/internal/create_thread_identity.h"
+ "synchronization/internal/futex.h"
+ "synchronization/internal/graphcycles.cc"
+ "synchronization/internal/graphcycles.h"
+ "synchronization/internal/kernel_timeout.h"
+ "synchronization/internal/per_thread_sem.cc"
+ "synchronization/internal/per_thread_sem.h"
+ "synchronization/internal/thread_pool.h"
+ "synchronization/internal/waiter.cc"
+ "synchronization/internal/waiter.h"
+ "time/civil_time.cc"
+ "time/civil_time.h"
+ "time/clock.cc"
+ "time/clock.h"
+ "time/duration.cc"
+ "time/format.cc"
+ "time/time.cc"
+ "time/time.h"
+ "time/internal/cctz/include/cctz/civil_time.h"
+ "time/internal/cctz/include/cctz/civil_time_detail.h"
+ "time/internal/cctz/include/cctz/time_zone.h"
+ "time/internal/cctz/include/cctz/zone_info_source.h"
+ "time/internal/cctz/src/civil_time_detail.cc"
+ "time/internal/cctz/src/time_zone_fixed.cc"
+ "time/internal/cctz/src/time_zone_fixed.h"
+ "time/internal/cctz/src/time_zone_format.cc"
+ "time/internal/cctz/src/time_zone_if.cc"
+ "time/internal/cctz/src/time_zone_if.h"
+ "time/internal/cctz/src/time_zone_impl.cc"
+ "time/internal/cctz/src/time_zone_impl.h"
+ "time/internal/cctz/src/time_zone_info.cc"
+ "time/internal/cctz/src/time_zone_info.h"
+ "time/internal/cctz/src/time_zone_libc.cc"
+ "time/internal/cctz/src/time_zone_libc.h"
+ "time/internal/cctz/src/time_zone_lookup.cc"
+ "time/internal/cctz/src/time_zone_posix.cc"
+ "time/internal/cctz/src/time_zone_posix.h"
+ "time/internal/cctz/src/tzfile.h"
+ "time/internal/cctz/src/zone_info_source.cc"
+ "types/any.h"
+ "types/bad_any_cast.cc"
+ "types/bad_any_cast.h"
+ "types/bad_optional_access.cc"
+ "types/bad_optional_access.h"
+ "types/bad_variant_access.cc"
+ "types/bad_variant_access.h"
+ "types/compare.h"
+ "types/internal/conformance_aliases.h"
+ "types/internal/conformance_archetype.h"
+ "types/internal/conformance_profile.h"
+ "types/internal/parentheses.h"
+ "types/internal/transform_args.h"
+ "types/internal/variant.h"
+ "types/optional.h"
+ "types/internal/optional.h"
+ "types/span.h"
+ "types/internal/span.h"
+ "types/variant.h"
+ "utility/utility.h"
+)
+
+set(ABSL_INTERNAL_DLL_TARGETS
+ "stacktrace"
+ "symbolize"
+ "examine_stack"
+ "failure_signal_handler"
+ "debugging_internal"
+ "demangle_internal"
+ "leak_check"
+ "leak_check_disable"
+ "stack_consumption"
+ "debugging"
+ "hash"
+ "spy_hash_state"
+ "city"
+ "memory"
+ "strings"
+ "strings_internal"
+ "cord"
+ "str_format"
+ "str_format_internal"
+ "pow10_helper"
+ "int128"
+ "numeric"
+ "utility"
+ "any"
+ "bad_any_cast"
+ "bad_any_cast_impl"
+ "span"
+ "optional"
+ "bad_optional_access"
+ "bad_variant_access"
+ "variant"
+ "compare"
+ "algorithm"
+ "algorithm_container"
+ "graphcycles_internal"
+ "kernel_timeout_internal"
+ "synchronization"
+ "thread_pool"
+ "bind_front"
+ "function_ref"
+ "atomic_hook"
+ "log_severity"
+ "raw_logging_internal"
+ "spinlock_wait"
+ "config"
+ "dynamic_annotations"
+ "core_headers"
+ "malloc_internal"
+ "base_internal"
+ "base"
+ "throw_delegate"
+ "pretty_function"
+ "endian"
+ "bits"
+ "exponential_biased"
+ "periodic_sampler"
+ "scoped_set_env"
+ "type_traits"
+ "meta"
+ "random_random"
+ "random_bit_gen_ref"
+ "random_distributions"
+ "random_seed_gen_exception"
+ "random_seed_sequences"
+ "random_internal_traits"
+ "random_internal_distribution_caller"
+ "random_internal_distributions"
+ "random_internal_fast_uniform_bits"
+ "random_internal_seed_material"
+ "random_internal_pool_urbg"
+ "random_internal_explicit_seed_seq"
+ "random_internal_sequence_urbg"
+ "random_internal_salted_seed_seq"
+ "random_internal_iostream_state_saver"
+ "random_internal_generate_real"
+ "random_internal_wide_multiply"
+ "random_internal_fastmath"
+ "random_internal_nonsecure_base"
+ "random_internal_pcg_engine"
+ "random_internal_randen_engine"
+ "random_internal_platform"
+ "random_internal_randen"
+ "random_internal_randen_slow"
+ "random_internal_randen_hwaes"
+ "random_internal_randen_hwaes_impl"
+ "random_internal_uniform_helper"
+ "status"
+ "time"
+ "civil_time"
+ "time_zone"
+ "container"
+ "btree"
+ "compressed_tuple"
+ "fixed_array"
+ "inlined_vector_internal"
+ "inlined_vector"
+ "counting_allocator"
+ "flat_hash_map"
+ "flat_hash_set"
+ "node_hash_map"
+ "node_hash_set"
+ "container_memory"
+ "hash_function_defaults"
+ "hash_policy_traits"
+ "hashtablez_sampler"
+ "hashtable_debug"
+ "hashtable_debug_hooks"
+ "have_sse"
+ "node_hash_policy"
+ "raw_hash_map"
+ "container_common"
+ "raw_hash_set"
+ "layout"
+ "tracked"
+)
+
+function(absl_internal_dll_contains)
+ cmake_parse_arguments(ABSL_INTERNAL_DLL
+ ""
+ "OUTPUT;TARGET"
+ ""
+ ${ARGN}
+ )
+
+ STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET})
+
+ list(FIND
+ ABSL_INTERNAL_DLL_TARGETS
+ "${_target}"
+ _index)
+
+ if (${_index} GREATER -1)
+ set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE)
+ else()
+ set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(absl_internal_dll_targets)
+ cmake_parse_arguments(ABSL_INTERNAL_DLL
+ ""
+ "OUTPUT"
+ "DEPS"
+ ${ARGN}
+ )
+
+ set(_deps "")
+ foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS)
+ absl_internal_dll_contains(TARGET ${dep} OUTPUT _contains)
+ if (_contains)
+ list(APPEND _deps abseil_dll)
+ else()
+ list(APPEND _deps ${dep})
+ endif()
+ endforeach()
+
+ # Because we may have added the DLL multiple times
+ list(REMOVE_DUPLICATES _deps)
+ set(${ABSL_INTERNAL_DLL_OUTPUT} "${_deps}" PARENT_SCOPE)
+endfunction()
+
+function(absl_make_dll)
+ add_library(
+ abseil_dll
+ SHARED
+ "${ABSL_INTERNAL_DLL_FILES}"
+ )
+ target_link_libraries(
+ abseil_dll
+ PRIVATE
+ ${ABSL_DEFAULT_LINKOPTS}
+ )
+ set_property(TARGET abseil_dll PROPERTY LINKER_LANGUAGE "CXX")
+ target_include_directories(
+ abseil_dll
+ PUBLIC
+ "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+
+ target_compile_options(
+ abseil_dll
+ PRIVATE
+ ${ABSL_DEFAULT_COPTS}
+ )
+
+ target_compile_definitions(
+ abseil_dll
+ PRIVATE
+ ABSL_BUILD_DLL
+ NOMINMAX
+ INTERFACE
+ ${ABSL_CC_LIB_DEFINES}
+ )
+ install(TARGETS abseil_dll EXPORT ${PROJECT_NAME}Targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+endfunction()
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilHelpers.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilHelpers.cmake
index e4289c11689..54fb8df3963 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilHelpers.cmake
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/AbseilHelpers.cmake
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -16,60 +16,18 @@
include(CMakeParseArguments)
include(AbseilConfigureCopts)
+include(AbseilDll)
# The IDE folder for Abseil that will be used if Abseil is included in a CMake
# project that sets
# set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# For example, Visual Studio supports folders.
-set(ABSL_IDE_FOLDER Abseil)
+if(NOT DEFINED ABSL_IDE_FOLDER)
+ set(ABSL_IDE_FOLDER Abseil)
+endif()
+# absl_cc_library()
#
-# create a library in the absl namespace
-#
-# parameters
-# SOURCES : sources files for the library
-# PUBLIC_LIBRARIES: targets and flags for linking phase
-# PRIVATE_COMPILE_FLAGS: compile flags for the library. Will not be exported.
-# EXPORT_NAME: export name for the absl:: target export
-# TARGET: target name
-#
-# create a target associated to <NAME>
-# libraries are installed under CMAKE_INSTALL_FULL_LIBDIR by default
-#
-function(absl_library)
- cmake_parse_arguments(ABSL_LIB
- "DISABLE_INSTALL" # keep that in case we want to support installation one day
- "TARGET;EXPORT_NAME"
- "SOURCES;PUBLIC_LIBRARIES;PRIVATE_COMPILE_FLAGS"
- ${ARGN}
- )
-
- set(_NAME ${ABSL_LIB_TARGET})
- string(TOUPPER ${_NAME} _UPPER_NAME)
-
- add_library(${_NAME} STATIC ${ABSL_LIB_SOURCES})
-
- target_compile_options(${_NAME}
- PRIVATE
- ${ABSL_LIB_PRIVATE_COMPILE_FLAGS}
- ${ABSL_DEFAULT_COPTS}
- )
- target_link_libraries(${_NAME} PUBLIC ${ABSL_LIB_PUBLIC_LIBRARIES})
- target_include_directories(${_NAME}
- PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} ${ABSL_LIB_PUBLIC_INCLUDE_DIRS}
- PRIVATE ${ABSL_LIB_PRIVATE_INCLUDE_DIRS}
- )
- # Add all Abseil targets to a a folder in the IDE for organization.
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
-
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
-
- if(ABSL_LIB_EXPORT_NAME)
- add_library(absl::${ABSL_LIB_EXPORT_NAME} ALIAS ${_NAME})
- endif()
-endfunction()
-
# CMake function to imitate Bazel's cc_library rule.
#
# Parameters:
@@ -80,13 +38,13 @@ endfunction()
# COPTS: List of private compile options
# DEFINES: List of public defines
# LINKOPTS: List of link options
-# PUBLIC: Add this so that this library will be exported under absl:: (see Note).
+# PUBLIC: Add this so that this library will be exported under absl::
# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal.
-# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake.
+# TESTONLY: When added, this target will only be built if BUILD_TESTING=ON.
#
# Note:
-# By default, absl_cc_library will always create a library named absl_internal_${NAME},
-# and alias target absl::${NAME}.
+# By default, absl_cc_library will always create a library named absl_${NAME},
+# and alias target absl::${NAME}. The absl:: form should always be used.
# This is to reduce namespace pollution.
#
# absl_cc_library(
@@ -103,21 +61,18 @@ endfunction()
# SRCS
# "b.cc"
# DEPS
-# absl_internal_awesome # not "awesome"!
+# absl::awesome # not "awesome" !
+# PUBLIC
# )
#
-# If PUBLIC is set, absl_cc_library will instead create a target named
-# absl_${NAME} and still an alias absl::${NAME}.
-#
# absl_cc_library(
# NAME
# main_lib
# ...
-# PUBLIC
+# DEPS
+# absl::fantastic_lib
# )
#
-# User can then use the library as absl::main_lib (although absl_main_lib is defined too).
-#
# TODO: Implement "ALWAYSLINK"
function(absl_cc_library)
cmake_parse_arguments(ABSL_CC_LIB
@@ -127,60 +82,223 @@ function(absl_cc_library)
${ARGN}
)
- if (NOT ABSL_CC_LIB_TESTONLY OR ABSL_RUN_TESTS)
- if (ABSL_CC_LIB_PUBLIC)
- set(_NAME "absl_${ABSL_CC_LIB_NAME}")
- else()
- set(_NAME "absl_internal_${ABSL_CC_LIB_NAME}")
+ if(ABSL_CC_LIB_TESTONLY AND NOT BUILD_TESTING)
+ return()
+ endif()
+
+ if(ABSL_ENABLE_INSTALL)
+ set(_NAME "${ABSL_CC_LIB_NAME}")
+ else()
+ set(_NAME "absl_${ABSL_CC_LIB_NAME}")
+ endif()
+
+ # Check if this is a header-only library
+ # Note that as of February 2019, many popular OS's (for example, Ubuntu
+ # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't
+ # use list(FILTER...)
+ set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
+ foreach(src_file IN LISTS ABSL_CC_SRCS)
+ if(${src_file} MATCHES ".*\\.(h|inc)")
+ list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}")
endif()
+ endforeach()
+
+ if(ABSL_CC_SRCS STREQUAL "")
+ set(ABSL_CC_LIB_IS_INTERFACE 1)
+ else()
+ set(ABSL_CC_LIB_IS_INTERFACE 0)
+ endif()
- # Check if this is a header-only library
- set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}")
- list(FILTER ABSL_CC_SRCS EXCLUDE REGEX ".*\\.h")
- if ("${ABSL_CC_SRCS}" STREQUAL "")
+ # Determine this build target's relationship to the DLL. It's one of four things:
+ # 1. "dll" -- This target is part of the DLL
+ # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL.
+ # Note that we assume any target not in the DLL depends on the
+ # DLL. This is not a technical necessity but a convenience
+ # which happens to be true, because nearly every target is
+ # part of the DLL.
+ # 3. "shared" -- This is a shared library, perhaps on a non-windows platform
+ # where DLL doesn't make sense.
+ # 4. "static" -- This target does not depend on the DLL and should be built
+ # statically.
+ if (${ABSL_BUILD_DLL})
+ if(ABSL_ENABLE_INSTALL)
+ absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
+ else()
+ absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll)
+ endif()
+ if (${_in_dll})
+ # This target should be replaced by the DLL
+ set(_build_type "dll")
set(ABSL_CC_LIB_IS_INTERFACE 1)
else()
- set(ABSL_CC_LIB_IS_INTERFACE 0)
+ # Building a DLL, but this target is not part of the DLL
+ set(_build_type "dll_dep")
+ endif()
+ elseif(BUILD_SHARED_LIBS)
+ set(_build_type "shared")
+ else()
+ set(_build_type "static")
+ endif()
+
+ # Generate a pkg-config file for every library:
+ if(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
+ if(NOT ABSL_CC_LIB_TESTONLY)
+ if(absl_VERSION)
+ set(PC_VERSION "${absl_VERSION}")
+ else()
+ set(PC_VERSION "head")
+ endif()
+ foreach(dep ${ABSL_CC_LIB_DEPS})
+ if(${dep} MATCHES "^absl::(.*)")
+ # Join deps with commas.
+ if(PC_DEPS)
+ set(PC_DEPS "${PC_DEPS},")
+ endif()
+ set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}")
+ endif()
+ endforeach()
+ foreach(cflag ${ABSL_CC_LIB_COPTS})
+ if(${cflag} MATCHES "^(-Wno|/wd)")
+ # These flags are needed to suppress warnings that might fire in our headers.
+ set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
+ elseif(${cflag} MATCHES "^(-W|/w[1234eo])")
+ # Don't impose our warnings on others.
+ else()
+ set(PC_CFLAGS "${PC_CFLAGS} ${cflag}")
+ endif()
+ endforeach()
+ FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\
+prefix=${CMAKE_INSTALL_PREFIX}\n\
+exec_prefix=\${prefix}\n\
+libdir=\${prefix}/${CMAKE_INSTALL_LIBDIR}\n\
+includedir=\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}\n\
+\n\
+Name: absl_${_NAME}\n\
+Description: Abseil ${_NAME} library\n\
+URL: https://abseil.io/\n\
+Version: ${PC_VERSION}\n\
+Requires:${PC_DEPS}\n\
+Libs: -L\${libdir} $<JOIN:${ABSL_CC_LIB_LINKOPTS}, > $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\
+Cflags: -I\${includedir}${PC_CFLAGS}\n")
+ INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc"
+ DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif()
+ endif()
- if(NOT ABSL_CC_LIB_IS_INTERFACE)
+ if(NOT ABSL_CC_LIB_IS_INTERFACE)
+ if(_build_type STREQUAL "dll_dep")
+ # This target depends on the DLL. When adding dependencies to this target,
+ # any depended-on-target which is contained inside the DLL is replaced
+ # with a dependency on the DLL.
add_library(${_NAME} STATIC "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
- target_include_directories(${_NAME}
- PUBLIC ${ABSL_COMMON_INCLUDE_DIRS})
- target_compile_options(${_NAME}
- PRIVATE ${ABSL_CC_LIB_COPTS})
+ absl_internal_dll_targets(
+ DEPS ${ABSL_CC_LIB_DEPS}
+ OUTPUT _dll_deps
+ )
target_link_libraries(${_NAME}
- PUBLIC ${ABSL_CC_LIB_DEPS}
- PRIVATE ${ABSL_CC_LIB_LINKOPTS}
+ PUBLIC ${_dll_deps}
+ PRIVATE
+ ${ABSL_CC_LIB_LINKOPTS}
+ ${ABSL_DEFAULT_LINKOPTS}
)
- target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
- # Add all Abseil targets to a a folder in the IDE for organization.
- if(ABSL_CC_LIB_PUBLIC)
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
- elseif(ABSL_CC_LIB_TESTONLY)
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
+ if (ABSL_CC_LIB_TESTONLY)
+ set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1")
else()
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
+ set(_gtest_link_define)
endif()
- # INTERFACE libraries can't have the CXX_STANDARD property set
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
- else()
- # Generating header-only library
- add_library(${_NAME} INTERFACE)
- target_include_directories(${_NAME}
- INTERFACE ${ABSL_COMMON_INCLUDE_DIRS})
+ target_compile_definitions(${_NAME}
+ PUBLIC
+ ABSL_CONSUME_DLL
+ "${_gtest_link_define}"
+ )
+
+ elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
+ add_library(${_NAME} "")
+ target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS})
target_link_libraries(${_NAME}
- INTERFACE ${ABSL_CC_LIB_DEPS} ${ABSL_CC_LIB_LINKOPTS}
+ PUBLIC ${ABSL_CC_LIB_DEPS}
+ PRIVATE
+ ${ABSL_CC_LIB_LINKOPTS}
+ ${ABSL_DEFAULT_LINKOPTS}
)
- target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
+ else()
+ message(FATAL_ERROR "Invalid build type: ${_build_type}")
endif()
- add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})
+ # Linker language can be inferred from sources, but in the case of DLLs we
+ # don't have any .cc files so it would be ambiguous. We could set it
+ # explicitly only in the case of DLLs but, because "CXX" is always the
+ # correct linker language for static or for shared libraries, we set it
+ # unconditionally.
+ set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX")
+
+ target_include_directories(${_NAME}
+ PUBLIC
+ "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+ target_compile_options(${_NAME}
+ PRIVATE ${ABSL_CC_LIB_COPTS})
+ target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES})
+
+ # Add all Abseil targets to a a folder in the IDE for organization.
+ if(ABSL_CC_LIB_PUBLIC)
+ set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
+ elseif(ABSL_CC_LIB_TESTONLY)
+ set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
+ else()
+ set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
+ endif()
+
+ # INTERFACE libraries can't have the CXX_STANDARD property set
+ set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
+ set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+
+ # When being installed, we lose the absl_ prefix. We want to put it back
+ # to have properly named lib files. This is a no-op when we are not being
+ # installed.
+ if(ABSL_ENABLE_INSTALL)
+ set_target_properties(${_NAME} PROPERTIES
+ OUTPUT_NAME "absl_${_NAME}"
+ SOVERSION "2103.0.1"
+ )
+ endif()
+ else()
+ # Generating header-only library
+ add_library(${_NAME} INTERFACE)
+ target_include_directories(${_NAME}
+ INTERFACE
+ "$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
+ $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ )
+
+ if (_build_type STREQUAL "dll")
+ set(ABSL_CC_LIB_DEPS abseil_dll)
+ endif()
+
+ target_link_libraries(${_NAME}
+ INTERFACE
+ ${ABSL_CC_LIB_DEPS}
+ ${ABSL_CC_LIB_LINKOPTS}
+ ${ABSL_DEFAULT_LINKOPTS}
+ )
+ target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
endif()
+
+ # TODO currently we don't install googletest alongside abseil sources, so
+ # installed abseil can't be tested.
+ if(NOT ABSL_CC_LIB_TESTONLY AND ABSL_ENABLE_INSTALL)
+ install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ )
+ endif()
+
+ add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME})
endfunction()
# absl_cc_test()
@@ -221,7 +339,7 @@ endfunction()
# gtest_main
# )
function(absl_cc_test)
- if(NOT ABSL_RUN_TESTS)
+ if(NOT BUILD_TESTING)
return()
endif()
@@ -233,23 +351,42 @@ function(absl_cc_test)
)
set(_NAME "absl_${ABSL_CC_TEST_NAME}")
+
add_executable(${_NAME} "")
target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS})
target_include_directories(${_NAME}
PUBLIC ${ABSL_COMMON_INCLUDE_DIRS}
PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
)
- target_compile_definitions(${_NAME}
- PUBLIC ${ABSL_CC_TEST_DEFINES}
- )
+
+ if (${ABSL_BUILD_DLL})
+ target_compile_definitions(${_NAME}
+ PUBLIC
+ ${ABSL_CC_TEST_DEFINES}
+ ABSL_CONSUME_DLL
+ GTEST_LINKED_AS_SHARED_LIBRARY=1
+ )
+
+ # Replace dependencies on targets inside the DLL with abseil_dll itself.
+ absl_internal_dll_targets(
+ DEPS ${ABSL_CC_TEST_DEPS}
+ OUTPUT ABSL_CC_TEST_DEPS
+ )
+ else()
+ target_compile_definitions(${_NAME}
+ PUBLIC
+ ${ABSL_CC_TEST_DEFINES}
+ )
+ endif()
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_TEST_COPTS}
)
+
target_link_libraries(${_NAME}
PUBLIC ${ABSL_CC_TEST_DEPS}
PRIVATE ${ABSL_CC_TEST_LINKOPTS}
)
- # Add all Abseil targets to a a folder in the IDE for organization.
+ # Add all Abseil targets to a folder in the IDE for organization.
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
@@ -258,116 +395,10 @@ function(absl_cc_test)
add_test(NAME ${_NAME} COMMAND ${_NAME})
endfunction()
-#
-# header only virtual target creation
-#
-function(absl_header_library)
- cmake_parse_arguments(ABSL_HO_LIB
- "DISABLE_INSTALL"
- "EXPORT_NAME;TARGET"
- "PUBLIC_LIBRARIES;PRIVATE_COMPILE_FLAGS;PUBLIC_INCLUDE_DIRS;PRIVATE_INCLUDE_DIRS"
- ${ARGN}
- )
-
- set(_NAME ${ABSL_HO_LIB_TARGET})
-
- set(__dummy_header_only_lib_file "${CMAKE_CURRENT_BINARY_DIR}/${_NAME}_header_only_dummy.cc")
-
- if(NOT EXISTS ${__dummy_header_only_lib_file})
- file(WRITE ${__dummy_header_only_lib_file}
- "/* generated file for header-only cmake target */
-
- namespace absl {
-
- // single meaningless symbol
- void ${_NAME}__header_fakesym() {}
- } // namespace absl
- "
- )
- endif()
-
-
- add_library(${_NAME} ${__dummy_header_only_lib_file})
- target_link_libraries(${_NAME} PUBLIC ${ABSL_HO_LIB_PUBLIC_LIBRARIES})
- target_include_directories(${_NAME}
- PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} ${ABSL_HO_LIB_PUBLIC_INCLUDE_DIRS}
- PRIVATE ${ABSL_HO_LIB_PRIVATE_INCLUDE_DIRS}
- )
-
- # Add all Abseil targets to a a folder in the IDE for organization.
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
-
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
-
- if(ABSL_HO_LIB_EXPORT_NAME)
- add_library(absl::${ABSL_HO_LIB_EXPORT_NAME} ALIAS ${_NAME})
- endif()
-
-endfunction()
-
-#
-# create an abseil unit_test and add it to the executed test list
-#
-# parameters
-# TARGET: target name prefix
-# SOURCES: sources files for the tests
-# PUBLIC_LIBRARIES: targets and flags for linking phase.
-# PRIVATE_COMPILE_FLAGS: compile flags for the test. Will not be exported.
-#
-# create a target associated to <NAME>_bin
-#
-# all tests will be register for execution with add_test()
-#
-# test compilation and execution is disable when ABSL_RUN_TESTS=OFF
-#
-function(absl_test)
-
- cmake_parse_arguments(ABSL_TEST
- ""
- "TARGET"
- "SOURCES;PUBLIC_LIBRARIES;PRIVATE_COMPILE_FLAGS;PUBLIC_INCLUDE_DIRS"
- ${ARGN}
- )
-
-
- if(ABSL_RUN_TESTS)
-
- set(_NAME "absl_${ABSL_TEST_TARGET}")
- string(TOUPPER ${_NAME} _UPPER_NAME)
-
- add_executable(${_NAME} ${ABSL_TEST_SOURCES})
-
- target_compile_options(${_NAME}
- PRIVATE
- ${ABSL_TEST_PRIVATE_COMPILE_FLAGS}
- ${ABSL_TEST_COPTS}
- )
- target_link_libraries(${_NAME} PUBLIC ${ABSL_TEST_PUBLIC_LIBRARIES} ${ABSL_TEST_COMMON_LIBRARIES})
- target_include_directories(${_NAME}
- PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} ${ABSL_TEST_PUBLIC_INCLUDE_DIRS}
- PRIVATE ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}
- )
-
- # Add all Abseil targets to a a folder in the IDE for organization.
- set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER})
-
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
-
- add_test(NAME ${_NAME} COMMAND ${_NAME})
- endif(ABSL_RUN_TESTS)
-
-endfunction()
-
-
-
function(check_target my_target)
-
if(NOT TARGET ${my_target})
message(FATAL_ERROR " ABSL: compiling absl requires a ${my_target} CMake target in your project,
see CMake/README.md for more details")
endif(NOT TARGET ${my_target})
-
endfunction()
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/CMakeLists.txt.in b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/CMakeLists.txt.in
deleted file mode 100644
index d60a33e9ac6..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/CMakeLists.txt.in
+++ /dev/null
@@ -1,15 +0,0 @@
-cmake_minimum_required(VERSION 2.8.2)
-
-project(googletest-download NONE)
-
-include(ExternalProject)
-ExternalProject_Add(googletest
- GIT_REPOSITORY https://github.com/google/googletest.git
- GIT_TAG master
- SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
- BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
- CONFIGURE_COMMAND ""
- BUILD_COMMAND ""
- INSTALL_COMMAND ""
- TEST_COMMAND ""
-) \ No newline at end of file
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/DownloadGTest.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/DownloadGTest.cmake
deleted file mode 100644
index 3c682aef07f..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/DownloadGTest.cmake
+++ /dev/null
@@ -1,32 +0,0 @@
-# Downloads and unpacks googletest at configure time. Based on the instructions
-# at https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
-
-# Download the latest googletest from Github master
-configure_file(
- ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
- ${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt
-)
-
-# Configure and build the downloaded googletest source
-execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download )
-if(result)
- message(FATAL_ERROR "CMake step for googletest failed: ${result}")
-endif()
-
-execute_process(COMMAND ${CMAKE_COMMAND} --build .
- RESULT_VARIABLE result
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
-if(result)
- message(FATAL_ERROR "Build step for googletest failed: ${result}")
-endif()
-
-# Prevent overriding the parent project's compiler/linker settings on Windows
-set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
-
-# Add googletest directly to our build. This defines the gtest and gtest_main
-# targets.
-add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
- ${CMAKE_BINARY_DIR}/googletest-build
- EXCLUDE_FROM_ALL)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/CMakeLists.txt.in b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/CMakeLists.txt.in
new file mode 100644
index 00000000000..5769e3a97b6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/CMakeLists.txt.in
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.2)
+
+project(googletest-external NONE)
+
+include(ExternalProject)
+ExternalProject_Add(googletest
+ URL "${absl_gtest_download_url}" # May be empty
+ SOURCE_DIR "${absl_gtest_src_dir}"
+ BINARY_DIR "${absl_gtest_build_dir}"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/DownloadGTest.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/DownloadGTest.cmake
new file mode 100644
index 00000000000..9d071c91701
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/Googletest/DownloadGTest.cmake
@@ -0,0 +1,41 @@
+# Integrates googletest at configure time. Based on the instructions at
+# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
+
+# Set up the external googletest project, downloading the latest from Github
+# master if requested.
+configure_file(
+ ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
+ ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt
+)
+
+set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+set(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+if (BUILD_SHARED_LIBS)
+ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1")
+endif()
+
+# Configure and build the googletest source.
+execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external )
+if(result)
+ message(FATAL_ERROR "CMake step for googletest failed: ${result}")
+endif()
+
+execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external)
+if(result)
+ message(FATAL_ERROR "Build step for googletest failed: ${result}")
+endif()
+
+set(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS})
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+
+# Prevent overriding the parent project's compiler/linker settings on Windows
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+
+# Add googletest directly to our build. This defines the gtest and gtest_main
+# targets.
+add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/README.md b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/README.md
index 79bbe24d5ad..5eee8171d93 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/README.md
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/README.md
@@ -3,7 +3,7 @@
Abseil comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt))
that can be used on a wide range of platforms ("C" stands for cross-platform.).
If you don't have CMake installed already, you can download it for free from
-<http://www.cmake.org/>.
+<https://www.cmake.org/>.
CMake works by generating native makefiles or build projects that can
be used in the compiler environment of your choice.
@@ -37,20 +37,12 @@ section of your executable or of your library.<br>
Here is a short CMakeLists.txt example of a project file using Abseil.
```cmake
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.5)
project(my_project)
-set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ ${CMAKE_CXX_FLAGS}")
-
-if(MSVC)
- # /wd4005 macro-redefinition
- # /wd4068 unknown pragma
- # /wd4244 conversion from 'type1' to 'type2'
- # /wd4267 conversion from 'size_t' to 'type2'
- # /wd4800 force value to bool 'true' or 'false' (performance warning)
- add_compile_options(/wd4005 /wd4068 /wd4244 /wd4267 /wd4800)
- add_definitions(/DNOMINMAX /DWIN32_LEAN_AND_MEAN=1 /D_CRT_SECURE_NO_WARNINGS)
-endif()
+# Pick the C++ standard to compile with.
+# Abseil currently supports C++11, C++14, and C++17.
+set(CMAKE_CXX_STANDARD 11)
add_subdirectory(abseil-cpp)
@@ -60,7 +52,7 @@ target_link_libraries(my_exe absl::base absl::synchronization absl::strings)
### Running Abseil Tests with CMake
-Use the `-DABSL_RUN_TESTS=ON` flag to run Abseil tests. Note that if the `-DBUILD_TESTING=OFF` flag is passed then Abseil tests will not be run.
+Use the `-DBUILD_TESTING=ON` flag to run Abseil tests.
You will need to provide Abseil with a Googletest dependency. There are two
options for how to do this:
@@ -78,7 +70,7 @@ For example, to run just the Abseil tests, you could use this script:
cd path/to/abseil-cpp
mkdir build
cd build
-cmake -DABSL_USE_GOOGLETEST_HEAD=ON -DABSL_RUN_TESTS=ON ..
+cmake -DBUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..
make -j
ctest
```
@@ -93,13 +85,15 @@ https://github.com/abseil/abseil-cpp/issues/109 for more information.
Here's a non-exhaustive list of Abseil CMake public targets:
```cmake
-absl::base
absl::algorithm
-absl::container
+absl::base
absl::debugging
+absl::flat_hash_map
+absl::flags
absl::memory
absl::meta
absl::numeric
+absl::random_random
absl::strings
absl::synchronization
absl::time
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/abslConfig.cmake.in b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/abslConfig.cmake.in
new file mode 100644
index 00000000000..62d246d01e0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/abslConfig.cmake.in
@@ -0,0 +1,8 @@
+# absl CMake configuration file.
+
+include(CMakeFindDependencyMacro)
+find_dependency(Threads)
+
+@PACKAGE_INIT@
+
+include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/simple.cc b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/simple.cc
new file mode 100644
index 00000000000..e9e352912ba
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/simple.cc
@@ -0,0 +1,23 @@
+//
+// 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.
+
+#include <iostream>
+#include "absl/strings/substitute.h"
+
+int main(int argc, char** argv) {
+ for (int i = 0; i < argc; ++i) {
+ std::cout << absl::Substitute("Arg $0: $1\n", i, argv[i]);
+ }
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/test.sh b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/test.sh
new file mode 100644
index 00000000000..a3d39773a15
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CMake/install_test_project/test.sh
@@ -0,0 +1,96 @@
+#!/bin/bash
+#
+# 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.
+#
+# Unit and integration tests for Abseil LTS CMake installation
+
+# Fail on any error. Treat unset variables an error. Print commands as executed.
+set -euox pipefail
+
+source ci/cmake_common.sh
+
+absl_dir=/abseil-cpp
+absl_build_dir=/buildfs
+project_dir="${absl_dir}"/CMake/install_test_project
+project_build_dir=/buildfs/project-build
+
+build_shared_libs="OFF"
+if [ "${LINK_TYPE:-}" = "DYNAMIC" ]; then
+ build_shared_libs="ON"
+fi
+
+# Run the LTS transformations
+./create_lts.py 99998877
+
+# Install Abseil
+pushd "${absl_build_dir}"
+cmake "${absl_dir}" \
+ -DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}" \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DBUILD_TESTING=ON \
+ -DBUILD_SHARED_LIBS="${build_shared_libs}"
+make -j $(nproc)
+ctest -j $(nproc)
+make install
+ldconfig
+popd
+
+# Test the project against the installed Abseil
+mkdir -p "${project_build_dir}"
+pushd "${project_build_dir}"
+cmake "${project_dir}"
+cmake --build . --target simple
+
+output="$(${project_build_dir}/simple "printme" 2>&1)"
+if [[ "${output}" != *"Arg 1: printme"* ]]; then
+ echo "Faulty output on simple project:"
+ echo "${output}"
+ exit 1
+fi
+
+popd
+
+if ! grep absl::strings "/usr/local/lib/cmake/absl/abslTargets.cmake"; then
+ cat "/usr/local/lib/cmake/absl/abslTargets.cmake"
+ echo "CMake targets named incorrectly"
+ exit 1
+fi
+
+pushd "${HOME}"
+cat > hello-abseil.cc << EOF
+#include <cstdlib>
+
+#include "absl/strings/str_format.h"
+
+int main(int argc, char **argv) {
+ absl::PrintF("Hello Abseil!\n");
+ return EXIT_SUCCESS;
+}
+EOF
+
+if [ "${LINK_TYPE:-}" != "DYNAMIC" ]; then
+ pc_args=($(pkg-config --cflags --libs --static absl_str_format))
+ g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}"
+else
+ pc_args=($(pkg-config --cflags --libs absl_str_format))
+ g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}"
+fi
+hello="$(./hello-abseil)"
+[[ "${hello}" == "Hello Abseil!" ]]
+
+popd
+
+echo "Install test complete!"
+exit 0
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/CONTRIBUTING.md b/src/third_party/abseil-cpp-master/abseil-cpp/CONTRIBUTING.md
index f4cb4a29ed0..9dadae93760 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/CONTRIBUTING.md
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/CONTRIBUTING.md
@@ -123,10 +123,13 @@ will be expected to conform to the style outlined
## Running Tests
-Use "bazel test <>" functionality to run the unit tests.
+If you have [Bazel](https://bazel.build/) installed, use `bazel test
+--test_tag_filters="-benchmark" ...` to run the unit tests.
-Prerequisites for building and running tests are listed in
-[README.md](README.md)
+If you are running the Linux operating system and have
+[Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh`
+scripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci)
+directory to test Abseil under a variety of conditions.
## Abseil Committers
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/FAQ.md b/src/third_party/abseil-cpp-master/abseil-cpp/FAQ.md
new file mode 100644
index 00000000000..78028fc09f1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/FAQ.md
@@ -0,0 +1,164 @@
+# Abseil FAQ
+
+## Is Abseil the right home for my utility library?
+
+Most often the answer to the question is "no." As both the [About
+Abseil](https://abseil.io/about/) page and our [contributing
+guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines)
+explain, Abseil contains a variety of core C++ library code that is widely used
+at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be
+used as a dependency by Google's open source C++ projects. While we do hope that
+Abseil is also useful to the C++ community at large, this added constraint also
+means that we are unlikely to accept a contribution of utility code that isn't
+already widely used by Google.
+
+## How to I set the C++ dialect used to build Abseil?
+
+The short answer is that whatever mechanism you choose, you need to make sure
+that you set this option consistently at the global level for your entire
+project. If, for example, you want to set the C++ dialect to C++17, with
+[Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the
+compiler, there several ways to do this:
+* Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build
+ --cxxopt=-std=c++17 ...`)
+* Set the environment variable `BAZEL_CXXOPTS` (for example,
+ `BAZEL_CXXOPTS=-std=c++17`)
+* Add `build --cxxopt=-std=c++17` to your [`.bazelrc`
+ file](https://docs.bazel.build/versions/master/guide.html#bazelrc)
+
+If you are using CMake as the build system, you'll need to add a line like
+`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. See the
+[CMake build
+instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md)
+for more information.
+
+For a longer answer to this question and to understand why some other approaches
+don't work, see the answer to ["What is ABI and why don't you recommend using a
+pre-compiled version of
+Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil)
+
+## What is ABI and why don't you recommend using a pre-compiled version of Abseil?
+
+For the purposes of this discussion, you can think of
+[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the
+compiled representation of the interfaces in code. This is in contrast to
+[API](https://en.wikipedia.org/wiki/Application_programming_interface), which
+you can think of as the interfaces as defined by the code itself. [Abseil has a
+strong promise of API compatibility, but does not make any promise of ABI
+compatibility](https://abseil.io/about/compatibility). Let's take a look at what
+this means in practice.
+
+You might be tempted to do something like this in a
+[Bazel](https://bazel.build/) `BUILD` file:
+
+```
+# DON'T DO THIS!!!
+cc_library(
+ name = "my_library",
+ srcs = ["my_library.cc"],
+ copts = ["-std=c++17"], # May create a mixed-mode compile!
+ deps = ["@com_google_absl//absl/strings"],
+)
+```
+
+Applying `-std=c++17` to an individual target in your `BUILD` file is going to
+compile that specific target in C++17 mode, but it isn't going to ensure the
+Abseil library is built in C++17 mode, since the Abseil library itself is a
+different build target. If your code includes an Abseil header, then your
+program may contain conflicting definitions of the same
+class/function/variable/enum, etc. As a rule, all compile options that affect
+the ABI of a program need to be applied to the entire build on a global basis.
+
+C++ has something called the [One Definition
+Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't
+allow multiple definitions of the same class/function/variable/enum, etc. ODR
+violations sometimes result in linker errors, but linkers do not always catch
+violations. Uncaught ODR violations can result in strange runtime behaviors or
+crashes that can be hard to debug.
+
+If you build the Abseil library and your code using different compile options
+that affect ABI, there is a good chance you will run afoul of the One Definition
+Rule. Examples of GCC compile options that affect ABI include (but aren't
+limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`),
+code generation flags (e.g. `-fexceptions`), and preprocessor defines
+(e.g. `-DNDEBUG`).
+
+If you use a pre-compiled version of Abseil, (for example, from your Linux
+distribution package manager or from something like
+[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to
+ensure ABI compatibility across the components of your program. The only way you
+can be sure your program is going to be correct regarding ABI is to ensure
+you've used the exact same compile options as were used to build the
+pre-compiled library. This does not mean that Abseil cannot work as part of a
+Linux distribution since a knowledgeable binary packager will have ensured that
+all packages have been built with consistent compile options. This is one of the
+reasons we warn against - though do not outright reject - using Abseil as a
+pre-compiled library.
+
+Another possible way that you might afoul of ABI issues is if you accidentally
+include two versions of Abseil in your program. Multiple versions of Abseil can
+end up within the same binary if your program uses the Abseil library and
+another library also transitively depends on Abseil (resulting in what is
+sometimes called the diamond dependency problem). In cases such as this you must
+structure your build so that all libraries use the same version of Abseil.
+[Abseil's strong promise of API compatibility between
+releases](https://abseil.io/about/compatibility) means the latest "HEAD" release
+of Abseil is almost certainly the right choice if you are doing as we recommend
+and building all of your code from source.
+
+For these reasons we recommend you avoid pre-compiled code and build the Abseil
+library yourself in a consistent manner with the rest of your code.
+
+## What is "live at head" and how do I do it?
+
+From Abseil's point-of-view, "live at head" means that every Abseil source
+release (which happens on an almost daily basis) is either API compatible with
+the previous release, or comes with an automated tool that you can run over code
+to make it compatible. In practice, the need to use an automated tool is
+extremely rare. This means that upgrading from one source release to another
+should be a routine practice that can and should be performed often.
+
+We recommend you update to the [latest commit in the `master` branch of
+Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as
+possible. Not only will you pick up bug fixes more quickly, but if you have good
+automated testing, you will catch and be able to fix any [Hyrum's
+Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis
+instead of being overwhelmed by them and having difficulty isolating them if you
+wait longer between updates.
+
+If you are using the [Bazel](https://bazel.build/) build system and its
+[external dependencies](https://docs.bazel.build/versions/master/external.html)
+feature, updating the
+[`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive)
+rule in your
+[`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for
+`com_google_abseil` to point to the [latest commit in the `master` branch of
+Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to
+do. For example, on February 11, 2020, the latest commit to the master branch
+was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you
+would add the following snippet to your `WORKSPACE` file:
+
+```
+http_archive(
+ name = "com_google_absl",
+ urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"], # 2020-02-11T18:50:53Z
+ strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea",
+ sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87",
+)
+```
+
+To get the `sha256` of this URL, run `curl -sL --output -
+https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip
+| sha256sum -`.
+
+You can commit the updated `WORKSPACE` file to your source control every time
+you update, and if you have good automated testing, you might even consider
+automating this.
+
+One thing we don't recommend is using GitHub's `master.zip` files (for example
+[https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)),
+which are always the latest commit in the `master` branch, to implement live at
+head. Since these `master.zip` URLs are not versioned, you will lose build
+reproducibility. In addition, some build systems, including Bazel, will simply
+cache this file, which means you won't actually be updating to the latest
+release until your cache is cleared or invalidated.
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/LICENSE b/src/third_party/abseil-cpp-master/abseil-cpp/LICENSE
index fef7d967815..ccd61dcfe3d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/LICENSE
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/LICENSE
@@ -1,7 +1,7 @@
Apache License
Version 2.0, January 2004
- http://www.apache.org/licenses/
+ https://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
@@ -193,12 +193,11 @@
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
- http://www.apache.org/licenses/LICENSE-2.0
+ 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.
-
- \ No newline at end of file
+
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/LTS.md b/src/third_party/abseil-cpp-master/abseil-cpp/LTS.md
deleted file mode 100644
index 385b4f062bf..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/LTS.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Long Term Support (LTS) Branches
-
-This repository contains periodic snapshots of the Abseil codebase that are
-Long Term Support (LTS) branches. An LTS branch allows you to use a known
-version of Abseil without interfering with other projects which may also, in
-turn, use Abseil. (For more information about our releases, see the
-[Abseil Release Management](https://abseil.io/about/releases) guide.)
-
-## LTS Branches
-
-The following lists LTS branches and the dates on which they have been released:
-
-* [LTS Branch June 20, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_20/)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/README.md b/src/third_party/abseil-cpp-master/abseil-cpp/README.md
index e9362be2d31..264c4b3feae 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/README.md
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/README.md
@@ -9,7 +9,9 @@ standard library.
- [About Abseil](#about)
- [Quickstart](#quickstart)
- [Building Abseil](#build)
+- [Support](#support)
- [Codemap](#codemap)
+- [Releases](#releases)
- [License](#license)
- [Links](#links)
@@ -42,14 +44,22 @@ the Abseil code, running tests, and getting a simple binary working.
<a name="build"></a>
## Building Abseil
-[Bazel](http://bazel.build) is the official build system for Abseil,
-which is supported on most major platforms (Linux, Windows, MacOS, for example)
-and compilers. See the [quickstart](https://abseil.io/docs/cpp/quickstart) for
-more information on building Abseil using the Bazel build system.
+[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official
+build systems for Abseil.
-<a name="cmake"></a>
-If you require CMake support, please check the
-[CMake build instructions](CMake/README.md).
+See the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information
+on building Abseil using the Bazel build system.
+
+If you require CMake support, please check the [CMake build
+instructions](CMake/README.md) and [CMake
+Quickstart](https://abseil.io/docs/cpp/quickstart-cmake).
+
+## Support
+
+Abseil is officially supported on many platforms. See the [Abseil
+platform support
+guide](https://abseil.io/docs/cpp/platforms/platforms) for details on
+supported operating systems, compilers, CPUs, etc.
## Codemap
@@ -62,6 +72,9 @@ Abseil contains the following C++ library components:
* [`algorithm`](absl/algorithm/)
<br /> The `algorithm` library contains additions to the C++ `<algorithm>`
library and container-based versions of such algorithms.
+* [`cleanup`](absl/cleanup/)
+ <br /> The `cleanup` library contains the control-flow-construct-like type
+ `absl::Cleanup` which is used for executing a callback on scope exit.
* [`container`](absl/container/)
<br /> The `container` library contains additional STL-style containers,
including Abseil's unordered "Swiss table" containers.
@@ -79,6 +92,9 @@ Abseil contains the following C++ library components:
available within C++14 and C++17 versions of the C++ `<type_traits>` library.
* [`numeric`](absl/numeric/)
<br /> The `numeric` library contains C++11-compatible 128-bit integers.
+* [`status`](absl/status/)
+ <br /> The `status` contains abstractions for error handling, specifically
+ `absl::Status` and `absl::StatusOr<T>`.
* [`strings`](absl/strings/)
<br /> The `strings` library contains a variety of strings routines and
utilities, including a C++11-compatible version of the C++17
@@ -97,6 +113,15 @@ Abseil contains the following C++ library components:
* [`utility`](absl/utility/)
<br /> The `utility` library contains utility and helper code.
+## Releases
+
+Abseil recommends users "live-at-head" (update to the latest commit from the
+master branch as often as possible). However, we realize this philosophy doesn't
+work for every project, so we also provide [Long Term Support
+Releases](https://github.com/abseil/abseil-cpp/releases) to which we backport
+fixes for severe bugs. See our [release
+management](https://abseil.io/about/releases) document for more details.
+
## License
The Abseil C++ library is licensed under the terms of the Apache
@@ -106,9 +131,9 @@ license. See [LICENSE](LICENSE) for more information.
For more information about Abseil:
-* Consult our [Abseil Introduction](http://abseil.io/about/intro)
-* Read [Why Adopt Abseil](http://abseil.io/about/philosophy) to understand our
+* Consult our [Abseil Introduction](https://abseil.io/about/intro)
+* Read [Why Adopt Abseil](https://abseil.io/about/philosophy) to understand our
design philosophy.
* Peruse our
- [Abseil Compatibility Guarantees](http://abseil.io/about/compatibility) to
+ [Abseil Compatibility Guarantees](https://abseil.io/about/compatibility) to
understand both what we promise to you, and what we expect of you in return.
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/UPGRADES.md b/src/third_party/abseil-cpp-master/abseil-cpp/UPGRADES.md
new file mode 100644
index 00000000000..35599d0878d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/UPGRADES.md
@@ -0,0 +1,17 @@
+# C++ Upgrade Tools
+
+Abseil may occassionally release API-breaking changes. As noted in our
+[Compatibility Guidelines][compatibility-guide], we will aim to provide a tool
+to do the work of effecting such API-breaking changes, when absolutely
+necessary.
+
+These tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on
+https://abseil.io.
+
+For more information, the [C++ Automated Upgrade Guide][api-upgrades-guide]
+outlines this process.
+
+[compatibility-guide]: https://abseil.io/about/compatibility
+[api-upgrades-guide]: https://abseil.io/docs/cpp/tools/api-upgrades
+[upgrade-tools]: https://abseil.io/docs/cpp/tools/upgrades/
+
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/WORKSPACE b/src/third_party/abseil-cpp-master/abseil-cpp/WORKSPACE
index 72ef13980c2..258d23b5642 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/WORKSPACE
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/WORKSPACE
@@ -1,29 +1,45 @@
+#
+# 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.
+#
+
workspace(name = "com_google_absl")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-# Bazel toolchains
-http_archive(
- name = "bazel_toolchains",
- urls = [
- "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/bc09b995c137df042bb80a395b73d7ce6f26afbe.tar.gz",
- "https://github.com/bazelbuild/bazel-toolchains/archive/bc09b995c137df042bb80a395b73d7ce6f26afbe.tar.gz",
- ],
- strip_prefix = "bazel-toolchains-bc09b995c137df042bb80a395b73d7ce6f26afbe",
- sha256 = "4329663fe6c523425ad4d3c989a8ac026b04e1acedeceb56aa4b190fa7f3973c",
-)
-
# GoogleTest/GoogleMock framework. Used by most unit-tests.
http_archive(
- name = "com_google_googletest",
- urls = ["https://github.com/google/googletest/archive/b4d4438df9479675a632b2f11125e57133822ece.zip"], # 2018-07-16
- strip_prefix = "googletest-b4d4438df9479675a632b2f11125e57133822ece",
- sha256 = "5aaa5d566517cae711e2a3505ea9a6438be1b37fcaae0ebcb96ccba9aa56f23a",
+ name = "com_google_googletest",
+ # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh.
+ urls = ["https://github.com/google/googletest/archive/8567b09290fe402cf01923e2131c5635b8ed851b.zip"], # 2020-06-12T22:24:28Z
+ strip_prefix = "googletest-8567b09290fe402cf01923e2131c5635b8ed851b",
+ sha256 = "9a8a166eb6a56c7b3d7b19dc2c946fe4778fd6f21c7a12368ad3b836d8f1be48",
)
# Google benchmark.
http_archive(
name = "com_github_google_benchmark",
- urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
- strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
- sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
+ urls = ["https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip"], # 2020-11-26T11:14:03Z
+ strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
+ sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
+)
+
+# C++ rules for Bazel.
+http_archive(
+ name = "rules_cc",
+ sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d",
+ strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
+ urls = [
+ "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
+ ],
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/BUILD.bazel
index edd0274c5d8..c9d4a2da8a3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/BUILD.bazel
@@ -5,47 +5,68 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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.
-#
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
-
-load(":compiler_config_setting.bzl", "create_llvm_config")
+licenses(["notice"])
-create_llvm_config(
- name = "llvm_compiler",
+config_setting(
+ name = "clang_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "clang",
+ },
visibility = [":__subpackages__"],
)
-# following configs are based on mapping defined in: https://git.io/v5Ijz
config_setting(
- name = "ios",
- values = {
- "cpu": "darwin",
+ name = "msvc_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "msvc-cl",
},
visibility = [":__subpackages__"],
)
config_setting(
- name = "windows",
- values = {
- "cpu": "x64_windows",
+ name = "clang-cl_compiler",
+ flag_values = {
+ "@bazel_tools//tools/cpp:compiler": "clang-cl",
},
visibility = [":__subpackages__"],
)
config_setting(
+ name = "osx",
+ constraint_values = [
+ "@bazel_tools//platforms:osx",
+ ],
+)
+
+config_setting(
+ name = "ios",
+ constraint_values = [
+ "@bazel_tools//platforms:ios",
+ ],
+)
+
+config_setting(
name = "ppc",
values = {
"cpu": "ppc",
},
visibility = [":__subpackages__"],
)
+
+config_setting(
+ name = "wasm",
+ values = {
+ "cpu": "wasm32",
+ },
+ visibility = [":__subpackages__"],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/abseil.podspec.gen.py b/src/third_party/abseil-cpp-master/abseil-cpp/absl/abseil.podspec.gen.py
new file mode 100644
index 00000000000..63752980d09
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/abseil.podspec.gen.py
@@ -0,0 +1,229 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""This script generates abseil.podspec from all BUILD.bazel files.
+
+This is expected to run on abseil git repository with Bazel 1.0 on Linux.
+It recursively analyzes BUILD.bazel files using query command of Bazel to
+dump its build rules in XML format. From these rules, it constructs podspec
+structure.
+"""
+
+import argparse
+import collections
+import os
+import re
+import subprocess
+import xml.etree.ElementTree
+
+# Template of root podspec.
+SPEC_TEMPLATE = """
+# This file has been automatically generated from a script.
+# Please make modifications to `abseil.podspec.gen.py` instead.
+Pod::Spec.new do |s|
+ s.name = 'abseil'
+ s.version = '${version}'
+ s.summary = 'Abseil Common Libraries (C++) from Google'
+ s.homepage = 'https://abseil.io'
+ s.license = 'Apache License, Version 2.0'
+ s.authors = { 'Abseil Team' => 'abseil-io@googlegroups.com' }
+ s.source = {
+ :git => 'https://github.com/abseil/abseil-cpp.git',
+ :tag => '${tag}',
+ }
+ s.module_name = 'absl'
+ s.header_mappings_dir = 'absl'
+ s.header_dir = 'absl'
+ s.libraries = 'c++'
+ s.compiler_flags = '-Wno-everything'
+ s.pod_target_xcconfig = {
+ 'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"',
+ 'USE_HEADERMAP' => 'NO',
+ 'ALWAYS_SEARCH_USER_PATHS' => 'NO',
+ }
+ s.ios.deployment_target = '9.0'
+ s.osx.deployment_target = '10.10'
+ s.tvos.deployment_target = '9.0'
+ s.watchos.deployment_target = '2.0'
+"""
+
+# Rule object representing the rule of Bazel BUILD.
+Rule = collections.namedtuple(
+ "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly")
+
+
+def get_elem_value(elem, name):
+ """Returns the value of XML element with the given name."""
+ for child in elem:
+ if child.attrib.get("name") != name:
+ continue
+ if child.tag == "string":
+ return child.attrib.get("value")
+ if child.tag == "boolean":
+ return child.attrib.get("value") == "true"
+ if child.tag == "list":
+ return [nested_child.attrib.get("value") for nested_child in child]
+ raise "Cannot recognize tag: " + child.tag
+ return None
+
+
+def normalize_paths(paths):
+ """Returns the list of normalized path."""
+ # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"]
+ return [path.lstrip("/").replace(":", "/") for path in paths]
+
+
+def parse_rule(elem, package):
+ """Returns a rule from bazel XML rule."""
+ return Rule(
+ type=elem.attrib["class"],
+ name=get_elem_value(elem, "name"),
+ package=package,
+ srcs=normalize_paths(get_elem_value(elem, "srcs") or []),
+ hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []),
+ textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []),
+ deps=get_elem_value(elem, "deps") or [],
+ visibility=get_elem_value(elem, "visibility") or [],
+ testonly=get_elem_value(elem, "testonly") or False)
+
+
+def read_build(package):
+ """Runs bazel query on given package file and returns all cc rules."""
+ result = subprocess.check_output(
+ ["bazel", "query", package + ":all", "--output", "xml"])
+ root = xml.etree.ElementTree.fromstring(result)
+ return [
+ parse_rule(elem, package)
+ for elem in root
+ if elem.tag == "rule" and elem.attrib["class"].startswith("cc_")
+ ]
+
+
+def collect_rules(root_path):
+ """Collects and returns all rules from root path recursively."""
+ rules = []
+ for cur, _, _ in os.walk(root_path):
+ build_path = os.path.join(cur, "BUILD.bazel")
+ if os.path.exists(build_path):
+ rules.extend(read_build("//" + cur))
+ return rules
+
+
+def relevant_rule(rule):
+ """Returns true if a given rule is relevant when generating a podspec."""
+ return (
+ # cc_library only (ignore cc_test, cc_binary)
+ rule.type == "cc_library" and
+ # ignore empty rule
+ (rule.hdrs + rule.textual_hdrs + rule.srcs) and
+ # ignore test-only rule
+ not rule.testonly)
+
+
+def get_spec_var(depth):
+ """Returns the name of variable for spec with given depth."""
+ return "s" if depth == 0 else "s{}".format(depth)
+
+
+def get_spec_name(label):
+ """Converts the label of bazel rule to the name of podspec."""
+ assert label.startswith("//absl/"), "{} doesn't start with //absl/".format(
+ label)
+ # e.g. //absl/apple/banana -> abseil/apple/banana
+ return "abseil/" + label[7:]
+
+
+def write_podspec(f, rules, args):
+ """Writes a podspec from given rules and args."""
+ rule_dir = build_rule_directory(rules)["abseil"]
+ # Write root part with given arguments
+ spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)],
+ SPEC_TEMPLATE).lstrip()
+ f.write(spec)
+ # Write all target rules
+ write_podspec_map(f, rule_dir, 0)
+ f.write("end\n")
+
+
+def build_rule_directory(rules):
+ """Builds a tree-style rule directory from given rules."""
+ rule_dir = {}
+ for rule in rules:
+ cur = rule_dir
+ for frag in get_spec_name(rule.package).split("/"):
+ cur = cur.setdefault(frag, {})
+ cur[rule.name] = rule
+ return rule_dir
+
+
+def write_podspec_map(f, cur_map, depth):
+ """Writes podspec from rule map recursively."""
+ for key, value in sorted(cur_map.items()):
+ indent = " " * (depth + 1)
+ f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format(
+ indent=indent,
+ key=key,
+ var0=get_spec_var(depth),
+ var1=get_spec_var(depth + 1)))
+ if isinstance(value, dict):
+ write_podspec_map(f, value, depth + 1)
+ else:
+ write_podspec_rule(f, value, depth + 1)
+ f.write("{indent}end\n".format(indent=indent))
+
+
+def write_podspec_rule(f, rule, depth):
+ """Writes podspec from given rule."""
+ indent = " " * (depth + 1)
+ spec_var = get_spec_var(depth)
+ # Puts all files in hdrs, textual_hdrs, and srcs into source_files.
+ # Since CocoaPods treats header_files a bit differently from bazel,
+ # this won't generate a header_files field so that all source_files
+ # are considered as header files.
+ srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs))
+ write_indented_list(
+ f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var),
+ srcs)
+ # Writes dependencies of this rule.
+ for dep in sorted(rule.deps):
+ name = get_spec_name(dep.replace(":", "/"))
+ f.write("{indent}{var}.dependency '{dep}'\n".format(
+ indent=indent, var=spec_var, dep=name))
+
+
+def write_indented_list(f, leading, values):
+ """Writes leading values in an indented style."""
+ f.write(leading)
+ f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values))
+ f.write("\n")
+
+
+def generate(args):
+ """Generates a podspec file from all BUILD files under absl directory."""
+ rules = filter(relevant_rule, collect_rules("absl"))
+ with open(args.output, "wt") as f:
+ write_podspec(f, rules, vars(args))
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Generates abseil.podspec from BUILD.bazel")
+ parser.add_argument(
+ "-v", "--version", help="The version of podspec", required=True)
+ parser.add_argument(
+ "-t",
+ "--tag",
+ default=None,
+ help="The name of git tag (default: version)")
+ parser.add_argument(
+ "-o",
+ "--output",
+ default="abseil.podspec",
+ help="The name of output file (default: abseil.podspec)")
+ args = parser.parse_args()
+ if args.tag is None:
+ args.tag = args.version
+ generate(args)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/BUILD.bazel
index 4314ee86928..a3002b7dcd5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,20 +14,26 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "algorithm",
hdrs = ["algorithm.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ ],
)
cc_test(
@@ -35,6 +41,7 @@ cc_test(
size = "small",
srcs = ["algorithm_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":algorithm",
"@com_google_googletest//:gtest_main",
@@ -45,6 +52,7 @@ cc_test(
name = "algorithm_benchmark",
srcs = ["equal_benchmark.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":algorithm",
@@ -59,6 +67,7 @@ cc_library(
"container.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":algorithm",
"//absl/base:core_headers",
@@ -70,6 +79,7 @@ cc_test(
name = "container_test",
srcs = ["container_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":container",
"//absl/base",
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm.h
index 3d6586439fe..e9b47338727 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,7 +26,10 @@
#include <iterator>
#include <type_traits>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace algorithm_internal {
@@ -84,6 +87,8 @@ It RotateImpl(It first, It middle, It last, std::false_type) {
} // namespace algorithm_internal
+// equal()
+//
// Compares the equality of two ranges specified by pairs of iterators, using
// the given predicate, returning true iff for each corresponding iterator i1
// and i2 in the first and second range respectively, pred(*i1, *i2) == true
@@ -94,7 +99,7 @@ It RotateImpl(It first, It middle, It last, std::false_type) {
// then the predicate is never invoked and the function returns false.
//
// This is a C++11-compatible implementation of C++14 `std::equal`. See
-// http://en.cppreference.com/w/cpp/algorithm/equal for more information.
+// https://en.cppreference.com/w/cpp/algorithm/equal for more information.
template <typename InputIter1, typename InputIter2, typename Pred>
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
InputIter2 last2, Pred&& pred) {
@@ -104,8 +109,8 @@ bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
typename std::iterator_traits<InputIter2>::iterator_category{});
}
-// Performs comparison of two ranges specified by pairs of iterators using
-// operator==.
+// Overload of equal() that performs comparison of two ranges specified by pairs
+// of iterators using operator==.
template <typename InputIter1, typename InputIter2>
bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
InputIter2 last2) {
@@ -113,6 +118,8 @@ bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2,
algorithm_internal::EqualTo{});
}
+// linear_search()
+//
// Performs a linear search for `value` using the iterator `first` up to
// but not including `last`, returning true if [`first`, `last`) contains an
// element equal to `value`.
@@ -126,6 +133,8 @@ bool linear_search(InputIterator first, InputIterator last,
return std::find(first, last, value) != last;
}
+// rotate()
+//
// Performs a left rotation on a range of elements (`first`, `last`) such that
// `middle` is now the first element. `rotate()` returns an iterator pointing to
// the first element before rotation. This function is exactly the same as
@@ -135,7 +144,6 @@ bool linear_search(InputIterator first, InputIterator last,
// The complexity of this algorithm is the same as that of `std::rotate`, but if
// `ForwardIterator` is not a random-access iterator, then `absl::rotate`
// performs an additional pass over the range to construct the return value.
-
template <typename ForwardIterator>
ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator last) {
@@ -145,6 +153,7 @@ ForwardIterator rotate(ForwardIterator first, ForwardIterator middle,
ForwardIterator>());
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_ALGORITHM_ALGORITHM_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm_test.cc
index e4322bc4f20..81fccb61353 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/algorithm_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container.h
index 6d5f6630f71..6398438f08c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -36,7 +36,6 @@
// For template parameter and variable naming, `C` indicates the container type
// to which the function is applied, `Pred` indicates the predicate object type
// to be used by the function and `T` indicates the applicable element type.
-//
#ifndef ABSL_ALGORITHM_CONTAINER_H_
#define ABSL_ALGORITHM_CONTAINER_H_
@@ -56,6 +55,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_algorithm_internal {
// NOTE: it is important to defer to ADL lookup for building with C++ modules,
@@ -90,10 +90,10 @@ using ContainerPointerType =
// lookup of std::begin and std::end, i.e.
// using std::begin;
// using std::end;
-// std::foo(begin(c), end(c);
+// std::foo(begin(c), end(c));
// becomes
// std::foo(container_algorithm_internal::begin(c),
-// container_algorithm_internal::end(c));
+// container_algorithm_internal::end(c));
// These are meant for internal use only.
template <typename C>
@@ -113,6 +113,18 @@ template <class Key, class Hash, class KeyEqual, class Allocator>
struct IsUnorderedContainer<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
: std::true_type {};
+// container_algorithm_internal::c_size. It is meant for internal use only.
+
+template <class C>
+auto c_size(C& c) -> decltype(c.size()) {
+ return c.size();
+}
+
+template <class T, std::size_t N>
+constexpr std::size_t c_size(T (&)[N]) {
+ return N;
+}
+
} // namespace container_algorithm_internal
// PUBLIC API
@@ -176,7 +188,7 @@ bool c_any_of(const C& c, Pred&& pred) {
// c_none_of()
//
// Container-based version of the <algorithm> `std::none_of()` function to
-// test if no elements in a container fulfil a condition.
+// test if no elements in a container fulfill a condition.
template <typename C, typename Pred>
bool c_none_of(const C& c, Pred&& pred) {
return std::none_of(container_algorithm_internal::c_begin(c),
@@ -257,7 +269,8 @@ container_algorithm_internal::ContainerIter<Sequence1> c_find_end(
// c_find_first_of()
//
// Container-based version of the <algorithm> `std::find_first_of()` function to
-// find the first elements in an ordered set within a container.
+// find the first element within the container that is also within the options
+// container.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIter<C1> c_find_first_of(C1& container,
C2& options) {
@@ -327,24 +340,45 @@ container_algorithm_internal::ContainerDifferenceType<const C> c_count_if(
// c_mismatch()
//
// Container-based version of the <algorithm> `std::mismatch()` function to
-// return the first element where two ordered containers differ.
+// return the first element where two ordered containers differ. Applies `==` to
+// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2) {
- return std::mismatch(container_algorithm_internal::c_begin(c1),
- container_algorithm_internal::c_end(c1),
- container_algorithm_internal::c_begin(c2));
+ auto first1 = container_algorithm_internal::c_begin(c1);
+ auto last1 = container_algorithm_internal::c_end(c1);
+ auto first2 = container_algorithm_internal::c_begin(c2);
+ auto last2 = container_algorithm_internal::c_end(c2);
+
+ for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+ // Negates equality because Cpp17EqualityComparable doesn't require clients
+ // to overload both `operator==` and `operator!=`.
+ if (!(*first1 == *first2)) {
+ break;
+ }
+ }
+
+ return std::make_pair(first1, first2);
}
// Overload of c_mismatch() for using a predicate evaluation other than `==` as
-// the function's test condition.
+// the function's test condition. Applies `pred`to the first N elements of `c1`
+// and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) {
- return std::mismatch(container_algorithm_internal::c_begin(c1),
- container_algorithm_internal::c_end(c1),
- container_algorithm_internal::c_begin(c2),
- std::forward<BinaryPredicate>(pred));
+c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
+ auto first1 = container_algorithm_internal::c_begin(c1);
+ auto last1 = container_algorithm_internal::c_end(c1);
+ auto first2 = container_algorithm_internal::c_begin(c2);
+ auto last2 = container_algorithm_internal::c_end(c2);
+
+ for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+ if (!pred(*first1, *first2)) {
+ break;
+ }
+ }
+
+ return std::make_pair(first1, first2);
}
// c_equal()
@@ -366,7 +400,8 @@ c_mismatch(C1& c1, C2& c2, BinaryPredicate&& pred) {
template <typename C1, typename C2>
bool c_equal(const C1& c1, const C2& c2) {
- return ((c1.size() == c2.size()) &&
+ return ((container_algorithm_internal::c_size(c1) ==
+ container_algorithm_internal::c_size(c2)) &&
std::equal(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2)));
@@ -376,7 +411,8 @@ bool c_equal(const C1& c1, const C2& c2) {
// the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
bool c_equal(const C1& c1, const C2& c2, BinaryPredicate&& pred) {
- return ((c1.size() == c2.size()) &&
+ return ((container_algorithm_internal::c_size(c1) ==
+ container_algorithm_internal::c_size(c2)) &&
std::equal(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -511,15 +547,33 @@ OutputIterator c_move(C&& src, OutputIterator dest) {
container_algorithm_internal::c_end(src), dest);
}
+// c_move_backward()
+//
+// Container-based version of the <algorithm> `std::move_backward()` function to
+// move a container's elements into an iterator in reverse order.
+template <typename C, typename BidirectionalIterator>
+BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) {
+ return std::move_backward(container_algorithm_internal::c_begin(src),
+ container_algorithm_internal::c_end(src), dest);
+}
+
// c_swap_ranges()
//
// Container-based version of the <algorithm> `std::swap_ranges()` function to
-// swap a container's elements with another container's elements.
+// swap a container's elements with another container's elements. Swaps the
+// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
template <typename C1, typename C2>
container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
- return std::swap_ranges(container_algorithm_internal::c_begin(c1),
- container_algorithm_internal::c_end(c1),
- container_algorithm_internal::c_begin(c2));
+ auto first1 = container_algorithm_internal::c_begin(c1);
+ auto last1 = container_algorithm_internal::c_end(c1);
+ auto first2 = container_algorithm_internal::c_begin(c2);
+ auto last2 = container_algorithm_internal::c_end(c2);
+
+ using std::swap;
+ for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
+ swap(*first1, *first2);
+ }
+ return first2;
}
// c_transform()
@@ -537,16 +591,23 @@ OutputIterator c_transform(const InputSequence& input, OutputIterator output,
}
// Overload of c_transform() for performing a transformation using a binary
-// predicate.
+// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
+// where N = min(size(c1), size(c2)).
template <typename InputSequence1, typename InputSequence2,
typename OutputIterator, typename BinaryOp>
OutputIterator c_transform(const InputSequence1& input1,
const InputSequence2& input2, OutputIterator output,
BinaryOp&& binary_op) {
- return std::transform(container_algorithm_internal::c_begin(input1),
- container_algorithm_internal::c_end(input1),
- container_algorithm_internal::c_begin(input2), output,
- std::forward<BinaryOp>(binary_op));
+ auto first1 = container_algorithm_internal::c_begin(input1);
+ auto last1 = container_algorithm_internal::c_end(input1);
+ auto first2 = container_algorithm_internal::c_begin(input2);
+ auto last2 = container_algorithm_internal::c_end(input2);
+ for (; first1 != last1 && first2 != last2;
+ ++first1, (void)++first2, ++output) {
+ *output = binary_op(*first1, *first2);
+ }
+
+ return output;
}
// c_replace()
@@ -648,7 +709,6 @@ container_algorithm_internal::ContainerIter<C> c_generate_n(C& c, Size n,
// and `unique()` are omitted, because it's not clear whether or not such
// functions should call erase on their supplied sequences afterwards. Either
// behavior would be surprising for a different set of users.
-//
// c_remove_copy()
//
@@ -919,9 +979,10 @@ void c_partial_sort(
// c_partial_sort_copy()
//
// Container-based version of the <algorithm> `std::partial_sort_copy()`
-// function to sort elements within a container such that elements before
-// `middle` are sorted in ascending order, and return the result within an
-// iterator.
+// function to sort the elements in the given range `result` within the larger
+// `sequence` in ascending order (and using `result` as the output parameter).
+// At most min(result.last - result.first, sequence.last - sequence.first)
+// elements from the sequence will be stored in the result.
template <typename C, typename RandomAccessContainer>
container_algorithm_internal::ContainerIter<RandomAccessContainer>
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
@@ -1697,6 +1758,7 @@ OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first,
output_first, std::forward<BinaryOp>(op));
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_ALGORITHM_CONTAINER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container_test.cc
index 1502b17f863..605afc8040d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/container_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -57,9 +57,7 @@ class NonMutatingTest : public testing::Test {
};
struct AccumulateCalls {
- void operator()(int value) {
- calls.push_back(value);
- }
+ void operator()(int value) { calls.push_back(value); }
std::vector<int> calls;
};
@@ -68,7 +66,6 @@ bool BinPredicate(int v1, int v2) { return v1 < v2; }
bool Equals(int v1, int v2) { return v1 == v2; }
bool IsOdd(int x) { return x % 2 != 0; }
-
TEST_F(NonMutatingTest, Distance) {
EXPECT_EQ(container_.size(), absl::c_distance(container_));
EXPECT_EQ(sequence_.size(), absl::c_distance(sequence_));
@@ -151,35 +148,118 @@ TEST_F(NonMutatingTest, CountIf) {
}
TEST_F(NonMutatingTest, Mismatch) {
- absl::c_mismatch(container_, sequence_);
- absl::c_mismatch(sequence_, container_);
+ // Testing necessary as absl::c_mismatch executes logic.
+ {
+ auto result = absl::c_mismatch(vector_, sequence_);
+ EXPECT_EQ(result.first, vector_.end());
+ EXPECT_EQ(result.second, sequence_.end());
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_);
+ EXPECT_EQ(result.first, sequence_.end());
+ EXPECT_EQ(result.second, vector_.end());
+ }
+
+ sequence_.back() = 5;
+ {
+ auto result = absl::c_mismatch(vector_, sequence_);
+ EXPECT_EQ(result.first, std::prev(vector_.end()));
+ EXPECT_EQ(result.second, std::prev(sequence_.end()));
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_);
+ EXPECT_EQ(result.first, std::prev(sequence_.end()));
+ EXPECT_EQ(result.second, std::prev(vector_.end()));
+ }
+
+ sequence_.pop_back();
+ {
+ auto result = absl::c_mismatch(vector_, sequence_);
+ EXPECT_EQ(result.first, std::prev(vector_.end()));
+ EXPECT_EQ(result.second, sequence_.end());
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_);
+ EXPECT_EQ(result.first, sequence_.end());
+ EXPECT_EQ(result.second, std::prev(vector_.end()));
+ }
+ {
+ struct NoNotEquals {
+ constexpr bool operator==(NoNotEquals) const { return true; }
+ constexpr bool operator!=(NoNotEquals) const = delete;
+ };
+ std::vector<NoNotEquals> first;
+ std::list<NoNotEquals> second;
+
+ // Check this still compiles.
+ absl::c_mismatch(first, second);
+ }
}
TEST_F(NonMutatingTest, MismatchWithPredicate) {
- absl::c_mismatch(container_, sequence_, BinPredicate);
- absl::c_mismatch(sequence_, container_, BinPredicate);
+ // Testing necessary as absl::c_mismatch executes logic.
+ {
+ auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+ EXPECT_EQ(result.first, vector_.begin());
+ EXPECT_EQ(result.second, sequence_.begin());
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+ EXPECT_EQ(result.first, sequence_.begin());
+ EXPECT_EQ(result.second, vector_.begin());
+ }
+
+ sequence_.front() = 0;
+ {
+ auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+ EXPECT_EQ(result.first, vector_.begin());
+ EXPECT_EQ(result.second, sequence_.begin());
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+ EXPECT_EQ(result.first, std::next(sequence_.begin()));
+ EXPECT_EQ(result.second, std::next(vector_.begin()));
+ }
+
+ sequence_.clear();
+ {
+ auto result = absl::c_mismatch(vector_, sequence_, BinPredicate);
+ EXPECT_EQ(result.first, vector_.begin());
+ EXPECT_EQ(result.second, sequence_.end());
+ }
+ {
+ auto result = absl::c_mismatch(sequence_, vector_, BinPredicate);
+ EXPECT_EQ(result.first, sequence_.end());
+ EXPECT_EQ(result.second, vector_.begin());
+ }
}
TEST_F(NonMutatingTest, Equal) {
EXPECT_TRUE(absl::c_equal(vector_, sequence_));
EXPECT_TRUE(absl::c_equal(sequence_, vector_));
+ EXPECT_TRUE(absl::c_equal(sequence_, array_));
+ EXPECT_TRUE(absl::c_equal(array_, vector_));
// Test that behavior appropriately differs from that of equal().
std::vector<int> vector_plus = {1, 2, 3};
vector_plus.push_back(4);
EXPECT_FALSE(absl::c_equal(vector_plus, sequence_));
EXPECT_FALSE(absl::c_equal(sequence_, vector_plus));
+ EXPECT_FALSE(absl::c_equal(array_, vector_plus));
}
TEST_F(NonMutatingTest, EqualWithPredicate) {
EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals));
EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals));
+ EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals));
+ EXPECT_TRUE(absl::c_equal(vector_, array_, Equals));
// Test that behavior appropriately differs from that of equal().
std::vector<int> vector_plus = {1, 2, 3};
vector_plus.push_back(4);
EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals));
EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals));
+ EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals));
}
TEST_F(NonMutatingTest, IsPermutation) {
@@ -513,11 +593,9 @@ TEST_F(SortingTest, IsSortedUntil) {
TEST_F(SortingTest, NthElement) {
std::vector<int> unsorted = {2, 4, 1, 3};
absl::c_nth_element(unsorted, unsorted.begin() + 2);
- EXPECT_THAT(unsorted,
- ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
+ EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3)));
absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater<int>());
- EXPECT_THAT(unsorted,
- ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
+ EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2)));
}
TEST(MutatingTest, IsPartitioned) {
@@ -636,6 +714,19 @@ TEST(MutatingTest, Move) {
Pointee(5)));
}
+TEST(MutatingTest, MoveBackward) {
+ std::vector<std::unique_ptr<int>> actual;
+ actual.emplace_back(absl::make_unique<int>(1));
+ actual.emplace_back(absl::make_unique<int>(2));
+ actual.emplace_back(absl::make_unique<int>(3));
+ actual.emplace_back(absl::make_unique<int>(4));
+ actual.emplace_back(absl::make_unique<int>(5));
+ auto subrange = absl::MakeSpan(actual.data(), 3);
+ absl::c_move_backward(subrange, actual.end());
+ EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2),
+ Pointee(3)));
+}
+
TEST(MutatingTest, MoveWithRvalue) {
auto MakeRValueSrc = [] {
std::vector<std::unique_ptr<int>> src;
@@ -657,6 +748,15 @@ TEST(MutatingTest, SwapRanges) {
absl::c_swap_ranges(odds, evens);
EXPECT_THAT(odds, ElementsAre(1, 3, 5));
EXPECT_THAT(evens, ElementsAre(2, 4, 6));
+
+ odds.pop_back();
+ absl::c_swap_ranges(odds, evens);
+ EXPECT_THAT(odds, ElementsAre(2, 4));
+ EXPECT_THAT(evens, ElementsAre(1, 3, 6));
+
+ absl::c_swap_ranges(evens, odds);
+ EXPECT_THAT(odds, ElementsAre(1, 3));
+ EXPECT_THAT(evens, ElementsAre(2, 4, 6));
}
TEST_F(NonMutatingTest, Transform) {
@@ -671,6 +771,20 @@ TEST_F(NonMutatingTest, Transform) {
EXPECT_EQ(std::vector<int>({1, 5, 4}), z);
*end = 7;
EXPECT_EQ(std::vector<int>({1, 5, 4, 7}), z);
+
+ z.clear();
+ y.pop_back();
+ end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+ EXPECT_EQ(std::vector<int>({1, 5}), z);
+ *end = 7;
+ EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
+
+ z.clear();
+ std::swap(x, y);
+ end = absl::c_transform(x, y, std::back_inserter(z), std::plus<int>());
+ EXPECT_EQ(std::vector<int>({1, 5}), z);
+ *end = 7;
+ EXPECT_EQ(std::vector<int>({1, 5, 7}), z);
}
TEST(MutatingTest, Replace) {
@@ -736,10 +850,9 @@ MATCHER_P2(IsElement, key, value, "") {
TEST(MutatingTest, StableSort) {
std::vector<Element> test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}};
absl::c_stable_sort(test_vector);
- EXPECT_THAT(
- test_vector,
- ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
- IsElement(2, 0), IsElement(2, 2)));
+ EXPECT_THAT(test_vector,
+ ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1),
+ IsElement(2, 0), IsElement(2, 2)));
}
TEST(MutatingTest, StableSortWithPredicate) {
@@ -747,10 +860,9 @@ TEST(MutatingTest, StableSortWithPredicate) {
absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) {
return e2 < e1;
});
- EXPECT_THAT(
- test_vector,
- ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
- IsElement(1, 1), IsElement(1, 0)));
+ EXPECT_THAT(test_vector,
+ ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2),
+ IsElement(1, 1), IsElement(1, 0)));
}
TEST(MutatingTest, ReplaceCopyIf) {
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/equal_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/equal_benchmark.cc
index 19c0780ccd1..7bf62c9a7f5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/equal_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/algorithm/equal_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/BUILD.bazel
index 2717df0c93a..65ff0ddef9f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,17 +14,71 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
- "ABSL_EXCEPTIONS_FLAG",
- "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
+
+cc_library(
+ name = "atomic_hook",
+ hdrs = ["internal/atomic_hook.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ":core_headers",
+ ],
+)
+
+cc_library(
+ name = "errno_saver",
+ hdrs = ["internal/errno_saver.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [":config"],
+)
+
+cc_library(
+ name = "log_severity",
+ srcs = ["log_severity.cc"],
+ hdrs = ["log_severity.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":core_headers",
+ ],
+)
+
+cc_library(
+ name = "raw_logging_internal",
+ srcs = ["internal/raw_logging.cc"],
+ hdrs = ["internal/raw_logging.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":atomic_hook",
+ ":config",
+ ":core_headers",
+ ":log_severity",
+ ],
+)
cc_library(
name = "spinlock_wait",
@@ -35,36 +89,51 @@ cc_library(
"internal/spinlock_wait.cc",
"internal/spinlock_win32.inc",
],
- hdrs = [
- "internal/scheduling_mode.h",
- "internal/spinlock_wait.h",
- ],
+ hdrs = ["internal/spinlock_wait.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/base:__pkg__",
],
- deps = [":core_headers"],
+ deps = [
+ ":base_internal",
+ ":core_headers",
+ ":errno_saver",
+ ],
)
cc_library(
name = "config",
hdrs = [
"config.h",
+ "options.h",
"policy_checks.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
)
cc_library(
name = "dynamic_annotations",
- srcs = ["dynamic_annotations.cc"],
- hdrs = ["dynamic_annotations.h"],
+ srcs = [
+ "internal/dynamic_annotations.h",
+ ],
+ hdrs = [
+ "dynamic_annotations.h",
+ ],
copts = ABSL_DEFAULT_COPTS,
- defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":core_headers",
+ ],
)
cc_library(
name = "core_headers",
+ srcs = [
+ "internal/thread_annotations.h",
+ ],
hdrs = [
"attributes.h",
"const_init.h",
@@ -74,6 +143,7 @@ cc_library(
"thread_annotations.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
],
@@ -89,15 +159,22 @@ cc_library(
"internal/low_level_alloc.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = select({
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
+ "//absl:wasm": [],
+ "//conditions:default": ["-pthread"],
+ }) + ABSL_DEFAULT_LINKOPTS,
visibility = [
- "//absl:__subpackages__",
+ "//visibility:public",
],
deps = [
":base",
+ ":base_internal",
":config",
":core_headers",
":dynamic_annotations",
- ":spinlock_wait",
+ ":raw_logging_internal",
],
)
@@ -111,16 +188,20 @@ cc_library(
"internal/scheduling_mode.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
+ deps = [
+ ":config",
+ "//absl/meta:type_traits",
+ ],
)
cc_library(
name = "base",
srcs = [
"internal/cycleclock.cc",
- "internal/raw_logging.cc",
"internal/spinlock.cc",
"internal/sysinfo.cc",
"internal/thread_identity.cc",
@@ -129,25 +210,49 @@ cc_library(
hdrs = [
"call_once.h",
"casts.h",
- "internal/atomic_hook.h",
"internal/cycleclock.h",
"internal/low_level_scheduling.h",
"internal/per_thread_tls.h",
- "internal/raw_logging.h",
"internal/spinlock.h",
"internal/sysinfo.h",
"internal/thread_identity.h",
"internal/tsan_mutex_interface.h",
"internal/unscaledcycleclock.h",
- "log_severity.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = select({
+ "//absl:msvc_compiler": [
+ "-DEFAULTLIB:advapi32.lib",
+ ],
+ "//absl:clang-cl_compiler": [
+ "-DEFAULTLIB:advapi32.lib",
+ ],
+ "//absl:wasm": [],
+ "//conditions:default": ["-pthread"],
+ }) + ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":atomic_hook",
":base_internal",
":config",
":core_headers",
":dynamic_annotations",
+ ":log_severity",
+ ":raw_logging_internal",
":spinlock_wait",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
+ name = "atomic_hook_test_helper",
+ testonly = 1,
+ srcs = ["internal/atomic_hook_test_helper.cc"],
+ hdrs = ["internal/atomic_hook_test_helper.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":atomic_hook",
+ ":core_headers",
],
)
@@ -156,8 +261,10 @@ cc_test(
size = "small",
srcs = ["internal/atomic_hook_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":base",
+ ":atomic_hook",
+ ":atomic_hook_test_helper",
":core_headers",
"@com_google_googletest//:gtest_main",
],
@@ -170,6 +277,7 @@ cc_test(
"bit_cast_test.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
":core_headers",
@@ -181,33 +289,48 @@ cc_library(
name = "throw_delegate",
srcs = ["internal/throw_delegate.cc"],
hdrs = ["internal/throw_delegate.h"],
- copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
- ":base",
":config",
+ ":raw_logging_internal",
],
)
cc_test(
name = "throw_delegate_test",
srcs = ["throw_delegate_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":config",
":throw_delegate",
"@com_google_googletest//:gtest_main",
],
)
+cc_test(
+ name = "errno_saver_test",
+ size = "small",
+ srcs = ["internal/errno_saver_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":errno_saver",
+ ":strerror",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
cc_library(
name = "exception_testing",
testonly = 1,
hdrs = ["internal/exception_testing.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
@@ -220,6 +343,7 @@ cc_library(
cc_library(
name = "pretty_function",
hdrs = ["internal/pretty_function.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//absl:__subpackages__"],
)
@@ -228,8 +352,8 @@ cc_library(
testonly = 1,
srcs = ["internal/exception_safety_testing.cc"],
hdrs = ["internal/exception_safety_testing.h"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
":pretty_function",
@@ -244,8 +368,8 @@ cc_library(
cc_test(
name = "exception_safety_testing_test",
srcs = ["exception_safety_testing_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":exception_safety_testing",
"//absl/memory",
@@ -263,6 +387,7 @@ cc_test(
"internal/inline_variable_testing.h",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base_internal",
"@com_google_googletest//:gtest_main",
@@ -274,6 +399,7 @@ cc_test(
size = "small",
srcs = ["invoke_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base_internal",
"//absl/memory",
@@ -289,10 +415,12 @@ cc_library(
testonly = 1,
srcs = ["spinlock_test_common.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
+ ":base_internal",
+ ":config",
":core_headers",
- ":spinlock_wait",
"//absl/synchronization",
"@com_google_googletest//:gtest",
],
@@ -304,11 +432,12 @@ cc_test(
size = "medium",
srcs = ["spinlock_test_common.cc"],
copts = ABSL_TEST_COPTS,
- tags = ["no_test_wasm"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
+ ":base_internal",
+ ":config",
":core_headers",
- ":spinlock_wait",
"//absl/synchronization",
"@com_google_googletest//:gtest_main",
],
@@ -318,13 +447,15 @@ cc_library(
name = "spinlock_benchmark_common",
testonly = 1,
srcs = ["internal/spinlock_benchmark.cc"],
- copts = ABSL_DEFAULT_COPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/base:__pkg__",
],
deps = [
":base",
":base_internal",
+ ":raw_logging_internal",
"//absl/synchronization",
"@com_github_google_benchmark//:benchmark_main",
],
@@ -335,6 +466,8 @@ cc_binary(
name = "spinlock_benchmark",
testonly = 1,
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
":spinlock_benchmark_common",
@@ -348,7 +481,9 @@ cc_library(
"internal/unaligned_access.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":base",
":config",
":core_headers",
],
@@ -359,7 +494,6 @@ cc_test(
srcs = ["internal/endian_test.cc"],
copts = ABSL_TEST_COPTS,
deps = [
- ":base",
":config",
":endian",
"@com_google_googletest//:gtest_main",
@@ -370,9 +504,7 @@ cc_test(
name = "config_test",
srcs = ["config_test.cc"],
copts = ABSL_TEST_COPTS,
- tags = [
- "no_test_wasm",
- ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":config",
"//absl/synchronization:thread_pool",
@@ -384,9 +516,7 @@ cc_test(
name = "call_once_test",
srcs = ["call_once_test.cc"],
copts = ABSL_TEST_COPTS,
- tags = [
- "no_test_wasm",
- ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
":core_headers",
@@ -399,8 +529,9 @@ cc_test(
name = "raw_logging_test",
srcs = ["raw_logging_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":base",
+ ":raw_logging_internal",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
@@ -411,6 +542,7 @@ cc_test(
size = "small",
srcs = ["internal/sysinfo_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
"//absl/synchronization",
@@ -420,15 +552,17 @@ cc_test(
cc_test(
name = "low_level_alloc_test",
- size = "small",
+ size = "medium",
srcs = ["internal/low_level_alloc_test.cc"],
copts = ABSL_TEST_COPTS,
- linkopts = select({
- "//absl:windows": [],
- "//conditions:default": ["-pthread"],
- }),
- tags = ["no_test_ios_x86_64"],
- deps = [":malloc_internal"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "no_test_ios_x86_64",
+ ],
+ deps = [
+ ":malloc_internal",
+ "//absl/container:node_hash_map",
+ ],
)
cc_test(
@@ -436,13 +570,7 @@ cc_test(
size = "small",
srcs = ["internal/thread_identity_test.cc"],
copts = ABSL_TEST_COPTS,
- linkopts = select({
- "//absl:windows": [],
- "//conditions:default": ["-pthread"],
- }),
- tags = [
- "no_test_wasm",
- ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":base",
":core_headers",
@@ -455,6 +583,7 @@ cc_test(
name = "thread_identity_benchmark",
srcs = ["internal/thread_identity_benchmark.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
@@ -465,21 +594,207 @@ cc_test(
)
cc_library(
- name = "bits",
- hdrs = ["internal/bits.h"],
+ name = "exponential_biased",
+ srcs = ["internal/exponential_biased.cc"],
+ hdrs = ["internal/exponential_biased.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
- deps = [":core_headers"],
+ deps = [
+ ":config",
+ ":core_headers",
+ ],
)
cc_test(
- name = "bits_test",
+ name = "exponential_biased_test",
size = "small",
- srcs = ["internal/bits_test.cc"],
+ srcs = ["internal/exponential_biased_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
deps = [
- ":bits",
+ ":exponential_biased",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "periodic_sampler",
+ srcs = ["internal/periodic_sampler.cc"],
+ hdrs = ["internal/periodic_sampler.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":core_headers",
+ ":exponential_biased",
+ ],
+)
+
+cc_test(
+ name = "periodic_sampler_test",
+ size = "small",
+ srcs = ["internal/periodic_sampler_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":core_headers",
+ ":periodic_sampler",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_binary(
+ name = "periodic_sampler_benchmark",
+ testonly = 1,
+ srcs = ["internal/periodic_sampler_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":core_headers",
+ ":periodic_sampler",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
+cc_library(
+ name = "scoped_set_env",
+ testonly = 1,
+ srcs = ["internal/scoped_set_env.cc"],
+ hdrs = ["internal/scoped_set_env.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ":raw_logging_internal",
+ ],
+)
+
+cc_test(
+ name = "scoped_set_env_test",
+ size = "small",
+ srcs = ["internal/scoped_set_env_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":scoped_set_env",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "log_severity_test",
+ size = "small",
+ srcs = ["log_severity_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":log_severity",
+ "//absl/flags:flag_internal",
+ "//absl/flags:marshalling",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "strerror",
+ srcs = ["internal/strerror.cc"],
+ hdrs = ["internal/strerror.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ":core_headers",
+ ":errno_saver",
+ ],
+)
+
+cc_test(
+ name = "strerror_test",
+ size = "small",
+ srcs = ["internal/strerror_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":strerror",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_binary(
+ name = "strerror_benchmark",
+ testonly = 1,
+ srcs = ["internal/strerror_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":strerror",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
+cc_library(
+ name = "fast_type_id",
+ hdrs = ["internal/fast_type_id.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ],
+)
+
+cc_test(
+ name = "fast_type_id_test",
+ size = "small",
+ srcs = ["internal/fast_type_id_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":fast_type_id",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "unique_small_name_test",
+ size = "small",
+ srcs = ["internal/unique_small_name_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ linkstatic = 1,
+ deps = [
+ ":core_headers",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "optimization_test",
+ size = "small",
+ srcs = ["optimization_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":core_headers",
+ "//absl/types:optional",
"@com_google_googletest//:gtest_main",
],
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/attributes.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/attributes.h
index 291ad89ee78..cf2cb5501e3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/attributes.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/attributes.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,8 +18,6 @@
// These macros are used within Abseil and allow the compiler to optimize, where
// applicable, certain function calls.
//
-// This file is used for both C and C++!
-//
// Most macros here are exposing GCC or Clang features, and are stubbed out for
// other compilers.
//
@@ -32,34 +30,12 @@
// of them are not supported in older version of Clang. Thus, we check
// `__has_attribute()` first. If the check fails, we check if we are on GCC and
// assume the attribute exists on GCC (which is verified on GCC 4.7).
-//
-// -----------------------------------------------------------------------------
-// Sanitizer Attributes
-// -----------------------------------------------------------------------------
-//
-// Sanitizer-related attributes are not "defined" in this file (and indeed
-// are not defined as such in any file). To utilize the following
-// sanitizer-related attributes within your builds, define the following macros
-// within your build using a `-D` flag, along with the given value for
-// `-fsanitize`:
-//
-// * `ADDRESS_SANITIZER` + `-fsanitize=address` (Clang, GCC 4.8)
-// * `MEMORY_SANITIZER` + `-fsanitize=memory` (Clang-only)
-// * `THREAD_SANITIZER + `-fsanitize=thread` (Clang, GCC 4.8+)
-// * `UNDEFINED_BEHAVIOR_SANITIZER` + `-fsanitize=undefined` (Clang, GCC 4.9+)
-// * `CONTROL_FLOW_INTEGRITY` + -fsanitize=cfi (Clang-only)
-//
-// Example:
-//
-// // Enable branches in the Abseil code that are tagged for ASan:
-// $ bazel build --copt=-DADDRESS_SANITIZER --copt=-fsanitize=address
-// --linkopt=-fsanitize=address *target*
-//
-// Since these macro names are only supported by GCC and Clang, we only check
-// for `__GNUC__` (GCC or Clang) and the above macros.
+
#ifndef ABSL_BASE_ATTRIBUTES_H_
#define ABSL_BASE_ATTRIBUTES_H_
+#include "absl/base/config.h"
+
// ABSL_HAVE_ATTRIBUTE
//
// A function-like feature checking macro that is a wrapper around
@@ -80,7 +56,7 @@
//
// A function-like feature checking macro that accepts C++11 style attributes.
// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6
-// (http://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
+// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't
// find `__has_cpp_attribute`, will evaluate to 0.
#if defined(__cplusplus) && defined(__has_cpp_attribute)
// NOTE: requiring __cplusplus above should not be necessary, but
@@ -102,7 +78,7 @@
//
// Tells the compiler to perform `printf` format string checking if the
// compiler supports it; see the 'format' attribute in
-// <http://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
+// <https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html>.
//
// Note: As the GCC manual states, "[s]ince non-static C++ methods
// have an implicit 'this' argument, the arguments of such methods
@@ -143,7 +119,7 @@
#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls))
-#elif defined(__GNUC__) && !defined(__clang__)
+#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL \
__attribute__((optimize("no-optimize-sibling-calls")))
@@ -157,10 +133,12 @@
// Tags a function as weak for the purposes of compilation and linking.
// Weak attributes currently do not work properly in LLVM's Windows backend,
// so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
-// for futher information.
-#if (ABSL_HAVE_ATTRIBUTE(weak) || \
+// for further information.
+// The MinGW compiler doesn't complain about the weak attribute until the link
+// step, presumably because Windows doesn't use ELF binaries.
+#if (ABSL_HAVE_ATTRIBUTE(weak) || \
(defined(__GNUC__) && !defined(__clang__))) && \
- !(defined(__llvm__) && defined(_WIN32))
+ !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -232,7 +210,7 @@
// out of bounds or does other scary things with memory.
// NOTE: GCC supports AddressSanitizer(asan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__) && defined(ADDRESS_SANITIZER)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
@@ -240,13 +218,13 @@
// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
//
-// Tells the MemorySanitizer to relax the handling of a given function. All
-// "Use of uninitialized value" warnings from such functions will be suppressed,
-// and all values loaded from memory will be considered fully initialized.
-// This attribute is similar to the ADDRESS_SANITIZER attribute above, but deals
-// with initialized-ness rather than addressability issues.
+// Tells the MemorySanitizer to relax the handling of a given function. All "Use
+// of uninitialized value" warnings from such functions will be suppressed, and
+// all values loaded from memory will be considered fully initialized. This
+// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute
+// above, but deals with initialized-ness rather than addressability issues.
// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
-#if defined(__GNUC__) && defined(MEMORY_SANITIZER)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
@@ -257,7 +235,7 @@
// Tells the ThreadSanitizer to not instrument a given function.
// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8.
// https://gcc.gnu.org/gcc-4.8/changes.html
-#if defined(__GNUC__) && defined(THREAD_SANITIZER)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
@@ -269,8 +247,10 @@
// where certain behavior (eg. division by zero) is being used intentionally.
// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9.
// https://gcc.gnu.org/gcc-4.9/changes.html
-#if defined(__GNUC__) && \
- (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)
+#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
+ __attribute__((no_sanitize_undefined))
+#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize("undefined")))
#else
@@ -281,12 +261,23 @@
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
-#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
#endif
+// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+//
+// Tells the SafeStack to not instrument a given function.
+// See https://clang.llvm.org/docs/SafeStack.html for details.
+#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
+ __attribute__((no_sanitize("safe-stack")))
+#else
+#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK
+#endif
+
// ABSL_ATTRIBUTE_RETURNS_NONNULL
//
// Tells the compiler that a particular function never returns a null pointer.
@@ -494,8 +485,10 @@
// packages/targets, as this may lead to conflicting definitions of functions at
// link-time.
//
+// XRay isn't currently supported on Android:
+// https://github.com/android/ndk/issues/368
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \
- !defined(ABSL_NO_XRAY_ATTRIBUTES)
+ !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__)
#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]]
#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]]
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args)
@@ -550,7 +543,19 @@
// ABSL_ATTRIBUTE_PACKED
//
-// Prevents the compiler from padding a structure to natural alignment
+// Instructs the compiler not to use natural alignment for a tagged data
+// structure, but instead to reduce its alignment to 1. This attribute can
+// either be applied to members of a structure or to a structure in its
+// entirety. Applying this attribute (judiciously) to a structure in its
+// entirety to optimize the memory footprint of very commonly-used structs is
+// fine. Do not apply this attribute to a structure in its entirety if the
+// purpose is to control the offsets of the members in the structure. Instead,
+// apply this attribute only to structure members that need it.
+//
+// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the
+// natural alignment of structure members not annotated is preserved. Aligned
+// member accesses are faster than non-aligned member accesses even if the
+// targeted microprocessor supports non-aligned accesses.
#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__))
#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__))
#else
@@ -567,6 +572,86 @@
#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes)
#endif
+// ABSL_FALLTHROUGH_INTENDED
+//
+// Annotates implicit fall-through between switch labels, allowing a case to
+// indicate intentional fallthrough and turn off warnings about any lack of a
+// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
+// a semicolon and can be used in most places where `break` can, provided that
+// no statements exist between it and the next switch label.
+//
+// Example:
+//
+// switch (x) {
+// case 40:
+// case 41:
+// if (truth_is_out_there) {
+// ++x;
+// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations
+// // in comments
+// } else {
+// return x;
+// }
+// case 42:
+// ...
+//
+// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED
+// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
+// when performing switch labels fall-through diagnostic
+// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
+// for details:
+// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
+//
+// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
+// has no effect on diagnostics. In any case this macro has no effect on runtime
+// behavior and performance of code.
+
+#ifdef ABSL_FALLTHROUGH_INTENDED
+#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
+#endif
+
+// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
+#if defined(__clang__) && defined(__has_warning)
+#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
+#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
+#endif
+#elif defined(__GNUC__) && __GNUC__ >= 7
+#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
+#endif
+
+#ifndef ABSL_FALLTHROUGH_INTENDED
+#define ABSL_FALLTHROUGH_INTENDED \
+ do { \
+ } while (0)
+#endif
+
+// ABSL_DEPRECATED()
+//
+// Marks a deprecated class, struct, enum, function, method and variable
+// declarations. The macro argument is used as a custom diagnostic message (e.g.
+// suggestion of a better alternative).
+//
+// Examples:
+//
+// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
+//
+// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...}
+//
+// template <typename T>
+// ABSL_DEPRECATED("Use DoThat() instead")
+// void DoThis();
+//
+// Every usage of a deprecated entity will trigger a warning when compiled with
+// clang's `-Wdeprecated-declarations` option. This option is turned off by
+// default, but the warnings will be reported by clang-tidy.
+#if defined(__clang__) && defined(__cplusplus) && __cplusplus >= 201103L
+#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
+#endif
+
+#ifndef ABSL_DEPRECATED
+#define ABSL_DEPRECATED(message)
+#endif
+
// ABSL_CONST_INIT
//
// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will
@@ -588,10 +673,30 @@
//
// Note that this attribute is redundant if the variable is declared constexpr.
#if ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
-// NOLINTNEXTLINE(whitespace/braces)
#define ABSL_CONST_INIT [[clang::require_constant_initialization]]
#else
#define ABSL_CONST_INIT
#endif // ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization)
+// ABSL_ATTRIBUTE_PURE_FUNCTION
+//
+// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure"
+// functions. A function is pure if its return value is only a function of its
+// arguments. The pure attribute prohibits a function from modifying the state
+// of the program that is observable by means other than inspecting the
+// function's return value. Declaring such functions with the pure attribute
+// allows the compiler to avoid emitting some calls in repeated invocations of
+// the function with the same argument values.
+//
+// Example:
+//
+// ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
+#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure)
+#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]]
+#elif ABSL_HAVE_ATTRIBUTE(pure)
+#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure))
+#else
+#define ABSL_ATTRIBUTE_PURE_FUNCTION
+#endif
+
#endif // ABSL_BASE_ATTRIBUTES_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/bit_cast_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/bit_cast_test.cc
index 8cd878d756e..8a3a41ea023 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/bit_cast_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/bit_cast_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "absl/base/macros.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
template <int N>
@@ -104,4 +105,5 @@ TEST(BitCast, Double) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once.h
index f6c8ebb2f79..96109f537cb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -29,6 +29,7 @@
#include <atomic>
#include <cstdint>
#include <type_traits>
+#include <utility>
#include "absl/base/internal/invoke.h"
#include "absl/base/internal/low_level_scheduling.h"
@@ -36,9 +37,11 @@
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/spinlock_wait.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
class once_flag;
@@ -140,12 +143,13 @@ enum {
};
template <typename Callable, typename... Args>
+ABSL_ATTRIBUTE_NOINLINE
void CallOnceImpl(std::atomic<uint32_t>* control,
base_internal::SchedulingMode scheduling_mode, Callable&& fn,
Args&&... args) {
#ifndef NDEBUG
{
- uint32_t old_control = control->load(std::memory_order_acquire);
+ uint32_t old_control = control->load(std::memory_order_relaxed);
if (old_control != kOnceInit &&
old_control != kOnceRunning &&
old_control != kOnceWaiter &&
@@ -163,16 +167,18 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
// Must do this before potentially modifying control word's state.
base_internal::SchedulingHelper maybe_disable_scheduling(scheduling_mode);
// Short circuit the simplest case to avoid procedure call overhead.
+ // The base_internal::SpinLockWait() call returns either kOnceInit or
+ // kOnceDone. If it returns kOnceDone, it must have loaded the control word
+ // with std::memory_order_acquire and seen a value of kOnceDone.
uint32_t old_control = kOnceInit;
if (control->compare_exchange_strong(old_control, kOnceRunning,
- std::memory_order_acquire,
std::memory_order_relaxed) ||
base_internal::SpinLockWait(control, ABSL_ARRAYSIZE(trans), trans,
scheduling_mode) == kOnceInit) {
- base_internal::Invoke(std::forward<Callable>(fn),
+ base_internal::invoke(std::forward<Callable>(fn),
std::forward<Args>(args)...);
- old_control = control->load(std::memory_order_relaxed);
- control->store(base_internal::kOnceDone, std::memory_order_release);
+ old_control =
+ control->exchange(base_internal::kOnceDone, std::memory_order_release);
if (old_control == base_internal::kOnceWaiter) {
base_internal::SpinLockWake(control, true);
}
@@ -207,6 +213,7 @@ void call_once(absl::once_flag& flag, Callable&& fn, Args&&... args) {
}
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CALL_ONCE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once_test.cc
index 183b92efa32..11d26c44d1a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/call_once_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,17 +24,18 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
absl::once_flag once;
ABSL_CONST_INIT Mutex counters_mu(absl::kConstInit);
-int running_thread_count GUARDED_BY(counters_mu) = 0;
-int call_once_invoke_count GUARDED_BY(counters_mu) = 0;
-int call_once_finished_count GUARDED_BY(counters_mu) = 0;
-int call_once_return_count GUARDED_BY(counters_mu) = 0;
-bool done_blocking GUARDED_BY(counters_mu) = false;
+int running_thread_count ABSL_GUARDED_BY(counters_mu) = 0;
+int call_once_invoke_count ABSL_GUARDED_BY(counters_mu) = 0;
+int call_once_finished_count ABSL_GUARDED_BY(counters_mu) = 0;
+int call_once_return_count ABSL_GUARDED_BY(counters_mu) = 0;
+bool done_blocking ABSL_GUARDED_BY(counters_mu) = false;
// Function to be called from absl::call_once. Waits for a notification.
void WaitAndIncrement() {
@@ -60,7 +61,7 @@ void ThreadBody() {
}
// Returns true if all threads are set up for the test.
-bool ThreadsAreSetup(void*) EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
+bool ThreadsAreSetup(void*) ABSL_EXCLUSIVE_LOCKS_REQUIRED(counters_mu) {
// All ten threads must be running, and WaitAndIncrement should be blocked.
return running_thread_count == 10 && call_once_invoke_count == 1;
}
@@ -102,4 +103,5 @@ TEST(CallOnceTest, ExecutionCount) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/casts.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/casts.h
index 1eef6a616d6..83c691265ff 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/casts.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/casts.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,31 +27,25 @@
#include <cstring>
#include <memory>
#include <type_traits>
+#include <utility>
#include "absl/base/internal/identity.h"
#include "absl/base/macros.h"
+#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace internal_casts {
-// NOTE: Not a fully compliant implementation of `std::is_trivially_copyable`.
-// TODO(calabrese) Branch on implementations that directly provide
-// `std::is_trivially_copyable`, create a more rigorous workaround, and publicly
-// expose in meta/type_traits.
-template <class T>
-struct is_trivially_copyable
- : std::integral_constant<
- bool, std::is_destructible<T>::value&& __has_trivial_destructor(T) &&
- __has_trivial_copy(T) && __has_trivial_assign(T)> {};
-
template <class Dest, class Source>
struct is_bitcastable
- : std::integral_constant<bool,
- sizeof(Dest) == sizeof(Source) &&
- is_trivially_copyable<Source>::value &&
- is_trivially_copyable<Dest>::value &&
- std::is_default_constructible<Dest>::value> {};
+ : std::integral_constant<
+ bool,
+ sizeof(Dest) == sizeof(Source) &&
+ type_traits_internal::is_trivially_copyable<Source>::value &&
+ type_traits_internal::is_trivially_copyable<Dest>::value &&
+ std::is_default_constructible<Dest>::value> {};
} // namespace internal_casts
@@ -165,16 +159,19 @@ inline Dest bit_cast(const Source& source) {
return dest;
}
-// NOTE: This overload is only picked if the requirements of bit_cast are not
-// met. It is therefore UB, but is provided temporarily as previous versions of
-// this function template were unchecked. Do not use this in new code.
+// NOTE: This overload is only picked if the requirements of bit_cast are
+// not met. It is therefore UB, but is provided temporarily as previous
+// versions of this function template were unchecked. Do not use this in
+// new code.
template <
typename Dest, typename Source,
typename std::enable_if<
- !internal_casts::is_bitcastable<Dest, Source>::value, int>::type = 0>
+ !internal_casts::is_bitcastable<Dest, Source>::value,
+ int>::type = 0>
ABSL_DEPRECATED(
- "absl::bit_cast type requirements were violated. Update the types being "
- "used such that they are the same size and are both TriviallyCopyable.")
+ "absl::bit_cast type requirements were violated. Update the types "
+ "being used such that they are the same size and are both "
+ "TriviallyCopyable.")
inline Dest bit_cast(const Source& source) {
static_assert(sizeof(Dest) == sizeof(Source),
"Source and destination types should have equal sizes.");
@@ -184,6 +181,7 @@ inline Dest bit_cast(const Source& source) {
return dest;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CASTS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config.h
index db4c4539022..95449969e7a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -63,8 +63,78 @@
#include <TargetConditionals.h>
#endif
+#include "absl/base/options.h"
#include "absl/base/policy_checks.h"
+// Helper macro to convert a CPP variable to a string literal.
+#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
+#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
+
+// -----------------------------------------------------------------------------
+// Abseil namespace annotations
+// -----------------------------------------------------------------------------
+
+// ABSL_NAMESPACE_BEGIN/ABSL_NAMESPACE_END
+//
+// An annotation placed at the beginning/end of each `namespace absl` scope.
+// This is used to inject an inline namespace.
+//
+// The proper way to write Abseil code in the `absl` namespace is:
+//
+// namespace absl {
+// ABSL_NAMESPACE_BEGIN
+//
+// void Foo(); // absl::Foo().
+//
+// ABSL_NAMESPACE_END
+// } // namespace absl
+//
+// Users of Abseil should not use these macros, because users of Abseil should
+// not write `namespace absl {` in their own code for any reason. (Abseil does
+// not support forward declarations of its own types, nor does it support
+// user-provided specialization of Abseil templates. Code that violates these
+// rules may be broken without warning.)
+#if !defined(ABSL_OPTION_USE_INLINE_NAMESPACE) || \
+ !defined(ABSL_OPTION_INLINE_NAMESPACE_NAME)
+#error options.h is misconfigured.
+#endif
+
+// Check that ABSL_OPTION_INLINE_NAMESPACE_NAME is neither "head" nor ""
+#if defined(__cplusplus) && ABSL_OPTION_USE_INLINE_NAMESPACE == 1
+
+#define ABSL_INTERNAL_INLINE_NAMESPACE_STR \
+ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME)
+
+static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != '\0',
+ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
+ "not be empty.");
+static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
+ ABSL_INTERNAL_INLINE_NAMESPACE_STR[1] != 'e' ||
+ ABSL_INTERNAL_INLINE_NAMESPACE_STR[2] != 'a' ||
+ ABSL_INTERNAL_INLINE_NAMESPACE_STR[3] != 'd' ||
+ ABSL_INTERNAL_INLINE_NAMESPACE_STR[4] != '\0',
+ "options.h misconfigured: ABSL_OPTION_INLINE_NAMESPACE_NAME must "
+ "be changed to a new, unique identifier name.");
+
+#endif
+
+#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
+#define ABSL_NAMESPACE_BEGIN
+#define ABSL_NAMESPACE_END
+#define ABSL_INTERNAL_C_SYMBOL(x) x
+#elif ABSL_OPTION_USE_INLINE_NAMESPACE == 1
+#define ABSL_NAMESPACE_BEGIN \
+ inline namespace ABSL_OPTION_INLINE_NAMESPACE_NAME {
+#define ABSL_NAMESPACE_END }
+#define ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v) x##_##v
+#define ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, v) \
+ ABSL_INTERNAL_C_SYMBOL_HELPER_2(x, v)
+#define ABSL_INTERNAL_C_SYMBOL(x) \
+ ABSL_INTERNAL_C_SYMBOL_HELPER_1(x, ABSL_OPTION_INLINE_NAMESPACE_NAME)
+#else
+#error options.h is misconfigured.
+#endif
+
// -----------------------------------------------------------------------------
// Compiler Feature Checks
// -----------------------------------------------------------------------------
@@ -84,6 +154,18 @@
#define ABSL_HAVE_BUILTIN(x) 0
#endif
+#if defined(__is_identifier)
+#define ABSL_INTERNAL_HAS_KEYWORD(x) !(__is_identifier(x))
+#else
+#define ABSL_INTERNAL_HAS_KEYWORD(x) 0
+#endif
+
+#ifdef __has_feature
+#define ABSL_HAVE_FEATURE(f) __has_feature(f)
+#else
+#define ABSL_HAVE_FEATURE(f) 0
+#endif
+
// ABSL_HAVE_TLS is defined to 1 when __thread should be supported.
// We assume __thread is supported on Linux when compiled with Clang or compiled
// against libstdc++ with _GLIBCXX_HAVE_TLS defined.
@@ -118,20 +200,33 @@
// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
-// either libc++ or libstdc++, and Visual Studio.
+// either libc++ or libstdc++, and Visual Studio (but not NVCC).
#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE)
#error ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE cannot be directly set
#elif defined(ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE)
#error ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE cannot directly set
#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
(!defined(__clang__) && defined(__GNUC__) && \
- (__GNUC__ > 5 || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)) && \
+ (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)) && \
(defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \
- defined(_MSC_VER)
+ (defined(_MSC_VER) && !defined(__NVCC__))
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
#endif
+// ABSL_HAVE_SOURCE_LOCATION_CURRENT
+//
+// Indicates whether `absl::SourceLocation::current()` will return useful
+// information in some contexts.
+#ifndef ABSL_HAVE_SOURCE_LOCATION_CURRENT
+#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
+ ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
+#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
+#elif defined(__GNUC__) && __GNUC__ >= 5
+#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
+#endif
+#endif
+
// ABSL_HAVE_THREAD_LOCAL
//
// Checks whether C++11's `thread_local` storage duration specifier is
@@ -145,11 +240,9 @@
// * Xcode 9.3 started disallowing `thread_local` for 32-bit iOS simulator
// targeting iOS 9.x.
// * Xcode 10 moves the deployment target check for iOS < 9.0 to link time
-// making __has_feature unreliable there.
+// making ABSL_HAVE_FEATURE unreliable there.
//
-// Otherwise, `__has_feature` is only supported by Clang so it has be inside
-// `defined(__APPLE__)` check.
-#if __has_feature(cxx_thread_local) && \
+#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
@@ -191,15 +284,13 @@
// * On Clang:
// * Building using Clang for Windows, where the Clang runtime library has
// 128-bit support only on LP64 architectures, but Windows is LLP64.
-// * Building for aarch64, where __int128 exists but has exhibits a sporadic
-// compiler crashing bug.
// * On Nvidia's nvcc:
// * nvcc also defines __GNUC__ and __SIZEOF_INT128__, but not all versions
// actually support __int128.
#ifdef ABSL_HAVE_INTRINSIC_INT128
#error ABSL_HAVE_INTRINSIC_INT128 cannot be directly set
#elif defined(__SIZEOF_INT128__)
-#if (defined(__clang__) && !defined(_WIN32) && !defined(__aarch64__)) || \
+#if (defined(__clang__) && !defined(_WIN32)) || \
(defined(__CUDACC__) && __CUDACC_VER_MAJOR__ >= 9) || \
(defined(__GNUC__) && !defined(__clang__) && !defined(__CUDACC__))
#define ABSL_HAVE_INTRINSIC_INT128 1
@@ -230,13 +321,19 @@
#error ABSL_HAVE_EXCEPTIONS cannot be directly set.
#elif defined(__clang__)
-// TODO(calabrese)
-// Switch to using __cpp_exceptions when we no longer support versions < 3.6.
-// For details on this check, see:
-// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
-#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
+// Clang >= 3.6
+#if ABSL_HAVE_FEATURE(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
-#endif // defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
+#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
+#else
+// Clang < 3.6
+// http://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html#the-exceptions-macro
+#if defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
+#define ABSL_HAVE_EXCEPTIONS 1
+#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
+#endif // __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
// Handle remaining special cases and default to exceptions being supported.
#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
@@ -255,7 +352,7 @@
// Linux and Linux-derived __linux__
// Android __ANDROID__ (implies __linux__)
// Linux (non-Android) __linux__ && !__ANDROID__
-// Darwin (Mac OS X and iOS) __APPLE__
+// Darwin (macOS and iOS) __APPLE__
// Akaros (http://akaros.org) __ros__
// Windows _WIN32
// NaCL __native_client__
@@ -275,7 +372,7 @@
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
- defined(__ASYLO__)
+ defined(__ASYLO__) || defined(__myriad2__)
#define ABSL_HAVE_MMAP 1
#endif
@@ -290,6 +387,15 @@
#define ABSL_HAVE_PTHREAD_GETSCHEDPARAM 1
#endif
+// ABSL_HAVE_SCHED_GETCPU
+//
+// Checks whether sched_getcpu is available.
+#ifdef ABSL_HAVE_SCHED_GETCPU
+#error ABSL_HAVE_SCHED_GETCPU cannot be directly set
+#elif defined(__linux__)
+#define ABSL_HAVE_SCHED_GETCPU 1
+#endif
+
// ABSL_HAVE_SCHED_YIELD
//
// Checks whether the platform implements sched_yield(2) as defined in
@@ -302,7 +408,7 @@
// ABSL_HAVE_SEMAPHORE_H
//
-// Checks whether the platform supports the <semaphore.h> header and sem_open(3)
+// Checks whether the platform supports the <semaphore.h> header and sem_init(3)
// family of functions as standardized in POSIX.1-2001.
//
// Note: While Apple provides <semaphore.h> for both iOS and macOS, it is
@@ -329,8 +435,15 @@
#define ABSL_HAVE_ALARM 1
#elif defined(_MSC_VER)
// feature tests for Microsoft's library
+#elif defined(__MINGW32__)
+// mingw32 doesn't provide alarm(2):
+// https://osdn.net/projects/mingw/scm/git/mingw-org-wsl/blobs/5.2-trunk/mingwrt/include/unistd.h
+// mingw-w64 provides a no-op implementation:
+// https://sourceforge.net/p/mingw-w64/mingw-w64/ci/master/tree/mingw-w64-crt/misc/alarm.c
#elif defined(__EMSCRIPTEN__)
// emscripten doesn't support signals
+#elif defined(__Fuchsia__)
+// Signals don't exist on fuchsia.
#elif defined(__native_client__)
#else
// other standard libraries
@@ -365,16 +478,25 @@
#error "absl endian detection needs to be set up for your compiler"
#endif
-// MacOS 10.13 doesn't let you use <any>, <optional>, or <variant> even though
-// the headers exist and are publicly noted to work. See
+// macOS 10.13 and iOS 10.11 don't let you use <any>, <optional>, or <variant>
+// even though the headers exist and are publicly noted to work. See
// https://github.com/abseil/abseil-cpp/issues/207 and
// https://developer.apple.com/documentation/xcode_release_notes/xcode_10_release_notes
+// libc++ spells out the availability requirements in the file
+// llvm-project/libcxx/include/__config via the #define
+// _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS.
#if defined(__APPLE__) && defined(_LIBCPP_VERSION) && \
- defined(__MAC_OS_X_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 101400
-#define ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES 1
+ ((defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 101400) || \
+ (defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ < 120000) || \
+ (defined(__ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 50000) || \
+ (defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
+ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
+#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
#else
-#define ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES 0
+#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
#endif
// ABSL_HAVE_STD_ANY
@@ -385,8 +507,8 @@
#endif
#ifdef __has_include
-#if __has_include(<any>) && __cplusplus >= 201703L && \
- ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
+#if __has_include(<any>) && defined(__cplusplus) && __cplusplus >= 201703L && \
+ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_ANY 1
#endif
#endif
@@ -399,8 +521,8 @@
#endif
#ifdef __has_include
-#if __has_include(<optional>) && __cplusplus >= 201703L && \
- ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
+#if __has_include(<optional>) && defined(__cplusplus) && \
+ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_OPTIONAL 1
#endif
#endif
@@ -413,8 +535,8 @@
#endif
#ifdef __has_include
-#if __has_include(<variant>) && __cplusplus >= 201703L && \
- ABSL_INTERNAL_MACOS_HAS_CXX_17_TYPES
+#if __has_include(<variant>) && defined(__cplusplus) && \
+ __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_VARIANT 1
#endif
#endif
@@ -427,7 +549,8 @@
#endif
#ifdef __has_include
-#if __has_include(<string_view>) && __cplusplus >= 201703L
+#if __has_include(<string_view>) && defined(__cplusplus) && \
+ __cplusplus >= 201703L
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
#endif
@@ -439,14 +562,77 @@
// not correctly set by MSVC, so we use `_MSVC_LANG` to check the language
// version.
// TODO(zhangxy): fix tests before enabling aliasing for `std::any`.
-#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
- ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
+#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
+ ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || \
+ (defined(__cplusplus) && __cplusplus > 201402))
// #define ABSL_HAVE_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
+// ABSL_USES_STD_ANY
+//
+// Indicates whether absl::any is an alias for std::any.
+#if !defined(ABSL_OPTION_USE_STD_ANY)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_ANY == 0 || \
+ (ABSL_OPTION_USE_STD_ANY == 2 && !defined(ABSL_HAVE_STD_ANY))
+#undef ABSL_USES_STD_ANY
+#elif ABSL_OPTION_USE_STD_ANY == 1 || \
+ (ABSL_OPTION_USE_STD_ANY == 2 && defined(ABSL_HAVE_STD_ANY))
+#define ABSL_USES_STD_ANY 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_OPTIONAL
+//
+// Indicates whether absl::optional is an alias for std::optional.
+#if !defined(ABSL_OPTION_USE_STD_OPTIONAL)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_OPTIONAL == 0 || \
+ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && !defined(ABSL_HAVE_STD_OPTIONAL))
+#undef ABSL_USES_STD_OPTIONAL
+#elif ABSL_OPTION_USE_STD_OPTIONAL == 1 || \
+ (ABSL_OPTION_USE_STD_OPTIONAL == 2 && defined(ABSL_HAVE_STD_OPTIONAL))
+#define ABSL_USES_STD_OPTIONAL 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_VARIANT
+//
+// Indicates whether absl::variant is an alias for std::variant.
+#if !defined(ABSL_OPTION_USE_STD_VARIANT)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_VARIANT == 0 || \
+ (ABSL_OPTION_USE_STD_VARIANT == 2 && !defined(ABSL_HAVE_STD_VARIANT))
+#undef ABSL_USES_STD_VARIANT
+#elif ABSL_OPTION_USE_STD_VARIANT == 1 || \
+ (ABSL_OPTION_USE_STD_VARIANT == 2 && defined(ABSL_HAVE_STD_VARIANT))
+#define ABSL_USES_STD_VARIANT 1
+#else
+#error options.h is misconfigured.
+#endif
+
+// ABSL_USES_STD_STRING_VIEW
+//
+// Indicates whether absl::string_view is an alias for std::string_view.
+#if !defined(ABSL_OPTION_USE_STD_STRING_VIEW)
+#error options.h is misconfigured.
+#elif ABSL_OPTION_USE_STD_STRING_VIEW == 0 || \
+ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \
+ !defined(ABSL_HAVE_STD_STRING_VIEW))
+#undef ABSL_USES_STD_STRING_VIEW
+#elif ABSL_OPTION_USE_STD_STRING_VIEW == 1 || \
+ (ABSL_OPTION_USE_STD_STRING_VIEW == 2 && \
+ defined(ABSL_HAVE_STD_STRING_VIEW))
+#define ABSL_USES_STD_STRING_VIEW 1
+#else
+#error options.h is misconfigured.
+#endif
+
// In debug mode, MSVC 2017's std::variant throws a EXCEPTION_ACCESS_VIOLATION
// SEH exception from emplace for variant<SomeStruct> when constructing the
// struct can throw. This defeats some of variant_test and
@@ -455,4 +641,102 @@
#define ABSL_INTERNAL_MSVC_2017_DBG_MODE
#endif
+// ABSL_INTERNAL_MANGLED_NS
+// ABSL_INTERNAL_MANGLED_BACKREFERENCE
+//
+// Internal macros for building up mangled names in our internal fork of CCTZ.
+// This implementation detail is only needed and provided for the MSVC build.
+//
+// These macros both expand to string literals. ABSL_INTERNAL_MANGLED_NS is
+// the mangled spelling of the `absl` namespace, and
+// ABSL_INTERNAL_MANGLED_BACKREFERENCE is a back-reference integer representing
+// the proper count to skip past the CCTZ fork namespace names. (This number
+// is one larger when there is an inline namespace name to skip.)
+#if defined(_MSC_VER)
+#if ABSL_OPTION_USE_INLINE_NAMESPACE == 0
+#define ABSL_INTERNAL_MANGLED_NS "absl"
+#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "5"
+#else
+#define ABSL_INTERNAL_MANGLED_NS \
+ ABSL_INTERNAL_TOKEN_STR(ABSL_OPTION_INLINE_NAMESPACE_NAME) "@absl"
+#define ABSL_INTERNAL_MANGLED_BACKREFERENCE "6"
+#endif
+#endif
+
+#undef ABSL_INTERNAL_HAS_KEYWORD
+
+// ABSL_DLL
+//
+// When building Abseil as a DLL, this macro expands to `__declspec(dllexport)`
+// so we can annotate symbols appropriately as being exported. When used in
+// headers consuming a DLL, this macro expands to `__declspec(dllimport)` so
+// that consumers know the symbol is defined inside the DLL. In all other cases,
+// the macro expands to nothing.
+#if defined(_MSC_VER)
+#if defined(ABSL_BUILD_DLL)
+#define ABSL_DLL __declspec(dllexport)
+#elif defined(ABSL_CONSUME_DLL)
+#define ABSL_DLL __declspec(dllimport)
+#else
+#define ABSL_DLL
+#endif
+#else
+#define ABSL_DLL
+#endif // defined(_MSC_VER)
+
+// ABSL_HAVE_MEMORY_SANITIZER
+//
+// MemorySanitizer (MSan) is a detector of uninitialized reads. It consists of
+// a compiler instrumentation module and a run-time library.
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#error "ABSL_HAVE_MEMORY_SANITIZER cannot be directly set."
+#elif defined(MEMORY_SANITIZER)
+// The MEMORY_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#elif defined(__SANITIZE_MEMORY__)
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#elif !defined(__native_client__) && ABSL_HAVE_FEATURE(memory_sanitizer)
+#define ABSL_HAVE_MEMORY_SANITIZER 1
+#endif
+
+// ABSL_HAVE_THREAD_SANITIZER
+//
+// ThreadSanitizer (TSan) is a fast data race detector.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#error "ABSL_HAVE_THREAD_SANITIZER cannot be directly set."
+#elif defined(THREAD_SANITIZER)
+// The THREAD_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#elif defined(__SANITIZE_THREAD__)
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(thread_sanitizer)
+#define ABSL_HAVE_THREAD_SANITIZER 1
+#endif
+
+// ABSL_HAVE_ADDRESS_SANITIZER
+//
+// AddressSanitizer (ASan) is a fast memory error detector.
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#error "ABSL_HAVE_ADDRESS_SANITIZER cannot be directly set."
+#elif defined(ADDRESS_SANITIZER)
+// The ADDRESS_SANITIZER macro is deprecated but we will continue to honor it
+// for now.
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#elif defined(__SANITIZE_ADDRESS__)
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#elif ABSL_HAVE_FEATURE(address_sanitizer)
+#define ABSL_HAVE_ADDRESS_SANITIZER 1
+#endif
+
+// ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
+//
+// Class template argument deduction is a language feature added in C++17.
+#ifdef ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION
+#error "ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION cannot be directly set."
+#elif defined(__cpp_deduction_guides)
+#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
+#endif
+
#endif // ABSL_BASE_CONFIG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config_test.cc
index c839712a537..7e0c033de59 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/config_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/const_init.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/const_init.h
index fc88b2672e2..16520b61d95 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/const_init.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/const_init.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,8 @@
#ifndef ABSL_BASE_CONST_INIT_H_
#define ABSL_BASE_CONST_INIT_H_
+#include "absl/base/config.h"
+
// In general, objects with static storage duration (such as global variables)
// can trigger tricky object lifetime situations. Attempting to access them
// from the constructors or destructors of other global objects can result in
@@ -60,14 +62,15 @@
//
// The absl::kConstInit tag should only be used to define objects with static
// or thread_local storage duration.
-//
namespace absl {
+ABSL_NAMESPACE_BEGIN
enum ConstInitType {
kConstInit,
};
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_CONST_INIT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.cc
deleted file mode 100644
index 08c27e511f0..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "absl/base/dynamic_annotations.h"
-
-#ifndef __has_feature
-#define __has_feature(x) 0
-#endif
-
-/* Compiler-based ThreadSanitizer defines
- DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL = 1
- and provides its own definitions of the functions. */
-
-#ifndef DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL
-# define DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL 0
-#endif
-
-/* Each function is empty and called (via a macro) only in debug mode.
- The arguments are captured by dynamic tools at runtime. */
-
-#if DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 && !defined(__native_client__)
-
-#if __has_feature(memory_sanitizer)
-#include <sanitizer/msan_interface.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void AnnotateRWLockCreate(const char *, int,
- const volatile void *){}
-void AnnotateRWLockDestroy(const char *, int,
- const volatile void *){}
-void AnnotateRWLockAcquired(const char *, int,
- const volatile void *, long){}
-void AnnotateRWLockReleased(const char *, int,
- const volatile void *, long){}
-void AnnotateBenignRace(const char *, int,
- const volatile void *,
- const char *){}
-void AnnotateBenignRaceSized(const char *, int,
- const volatile void *,
- size_t,
- const char *) {}
-void AnnotateThreadName(const char *, int,
- const char *){}
-void AnnotateIgnoreReadsBegin(const char *, int){}
-void AnnotateIgnoreReadsEnd(const char *, int){}
-void AnnotateIgnoreWritesBegin(const char *, int){}
-void AnnotateIgnoreWritesEnd(const char *, int){}
-void AnnotateEnableRaceDetection(const char *, int, int){}
-void AnnotateMemoryIsInitialized(const char *, int,
- const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
- __msan_unpoison(mem, size);
-#else
- (void)mem;
- (void)size;
-#endif
-}
-
-void AnnotateMemoryIsUninitialized(const char *, int,
- const volatile void *mem, size_t size) {
-#if __has_feature(memory_sanitizer)
- __msan_allocated_memory(mem, size);
-#else
- (void)mem;
- (void)size;
-#endif
-}
-
-static int GetRunningOnValgrind(void) {
-#ifdef RUNNING_ON_VALGRIND
- if (RUNNING_ON_VALGRIND) return 1;
-#endif
- char *running_on_valgrind_str = getenv("RUNNING_ON_VALGRIND");
- if (running_on_valgrind_str) {
- return strcmp(running_on_valgrind_str, "0") != 0;
- }
- return 0;
-}
-
-/* See the comments in dynamic_annotations.h */
-int RunningOnValgrind(void) {
- static volatile int running_on_valgrind = -1;
- int local_running_on_valgrind = running_on_valgrind;
- /* C doesn't have thread-safe initialization of statics, and we
- don't want to depend on pthread_once here, so hack it. */
- ANNOTATE_BENIGN_RACE(&running_on_valgrind, "safe hack");
- if (local_running_on_valgrind == -1)
- running_on_valgrind = local_running_on_valgrind = GetRunningOnValgrind();
- return local_running_on_valgrind;
-}
-
-/* See the comments in dynamic_annotations.h */
-double ValgrindSlowdown(void) {
- /* Same initialization hack as in RunningOnValgrind(). */
- static volatile double slowdown = 0.0;
- double local_slowdown = slowdown;
- ANNOTATE_BENIGN_RACE(&slowdown, "safe hack");
- if (RunningOnValgrind() == 0) {
- return 1.0;
- }
- if (local_slowdown == 0.0) {
- char *env = getenv("VALGRIND_SLOWDOWN");
- slowdown = local_slowdown = env ? atof(env) : 50.0;
- }
- return local_slowdown;
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-#endif /* DYNAMIC_ANNOTATIONS_EXTERNAL_IMPL == 0 */
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.h
index 7e328d9622c..880cbf6e926 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/dynamic_annotations.h
@@ -1,388 +1,496 @@
-/*
- * 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
- *
- * http://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 defines dynamic annotations for use with dynamic analysis
- tool such as valgrind, PIN, etc.
-
- Dynamic annotation is a source code annotation that affects
- the generated code (that is, the annotation is not a comment).
- Each such annotation is attached to a particular
- instruction and/or to a particular object (address) in the program.
-
- The annotations that should be used by users are macros in all upper-case
- (e.g., ANNOTATE_THREAD_NAME).
-
- Actual implementation of these macros may differ depending on the
- dynamic analysis tool being used.
-
- This file supports the following configurations:
- - Dynamic Annotations enabled (with static thread-safety warnings disabled).
- In this case, macros expand to functions implemented by Thread Sanitizer,
- when building with TSan. When not provided an external implementation,
- dynamic_annotations.cc provides no-op implementations.
-
- - Static Clang thread-safety warnings enabled.
- When building with a Clang compiler that supports thread-safety warnings,
- a subset of annotations can be statically-checked at compile-time. We
- expand these macros to static-inline functions that can be analyzed for
- thread-safety, but afterwards elided when building the final binary.
-
- - All annotations are disabled.
- If neither Dynamic Annotations nor Clang thread-safety warnings are
- enabled, then all annotation-macros expand to empty. */
+// 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 defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ABSL_ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+// In this case, macros expand to functions implemented by Thread Sanitizer,
+// when building with TSan. When not provided an external implementation,
+// dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+// When building with a Clang compiler that supports thread-safety warnings,
+// a subset of annotations can be statically-checked at compile-time. We
+// expand these macros to static-inline functions that can be analyzed for
+// thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+// If neither Dynamic Annotations nor Clang thread-safety warnings are
+// enabled, then all annotation-macros expand to empty.
#ifndef ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
-#ifndef DYNAMIC_ANNOTATIONS_ENABLED
-# define DYNAMIC_ANNOTATIONS_ENABLED 0
-#endif
+#include <stddef.h>
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0
-
- /* -------------------------------------------------------------
- Annotations that suppress errors. It is usually better to express the
- program's synchronization using the other annotations, but these can
- be used when all else fails. */
-
- /* Report that we may have a benign race at "pointer", with size
- "sizeof(*(pointer))". "pointer" must be a non-void* pointer. Insert at the
- point where "pointer" has been allocated, preferably close to the point
- where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC. */
- #define ANNOTATE_BENIGN_RACE(pointer, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, pointer, \
- sizeof(*(pointer)), description)
-
- /* Same as ANNOTATE_BENIGN_RACE(address, description), but applies to
- the memory range [address, address+size). */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
- AnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description)
-
- /* Enable (enable!=0) or disable (enable==0) race detection for all threads.
- This annotation could be useful if you want to skip expensive race analysis
- during some period of program execution, e.g. during initialization. */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
- AnnotateEnableRaceDetection(__FILE__, __LINE__, enable)
-
- /* -------------------------------------------------------------
- Annotations useful for debugging. */
-
- /* Report the current thread name to a race detector. */
- #define ANNOTATE_THREAD_NAME(name) \
- AnnotateThreadName(__FILE__, __LINE__, name)
-
- /* -------------------------------------------------------------
- Annotations useful when implementing locks. They are not
- normally needed by modules that merely use locks.
- The "lock" argument is a pointer to the lock object. */
-
- /* Report that a lock has been created at address "lock". */
- #define ANNOTATE_RWLOCK_CREATE(lock) \
- AnnotateRWLockCreate(__FILE__, __LINE__, lock)
-
- /* Report that a linker initialized lock has been created at address "lock".
- */
-#ifdef THREAD_SANITIZER
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
- AnnotateRWLockCreateStatic(__FILE__, __LINE__, lock)
-#else
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#ifdef __cplusplus
+#include "absl/base/macros.h"
#endif
- /* Report that the lock at address "lock" is about to be destroyed. */
- #define ANNOTATE_RWLOCK_DESTROY(lock) \
- AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
+// TODO(rogeeff): Remove after the backward compatibility period.
+#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
- /* Report that the lock at address "lock" has been acquired.
- is_w=1 for writer lock, is_w=0 for reader lock. */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
- AnnotateRWLockAcquired(__FILE__, __LINE__, lock, is_w)
+// -------------------------------------------------------------------------
+// Decide which features are enabled.
- /* Report that the lock at address "lock" is about to be released. */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
- AnnotateRWLockReleased(__FILE__, __LINE__, lock, is_w)
+#ifdef ABSL_HAVE_THREAD_SANITIZER
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
- #define ANNOTATE_RWLOCK_CREATE(lock) /* empty */
- #define ANNOTATE_RWLOCK_CREATE_STATIC(lock) /* empty */
- #define ANNOTATE_RWLOCK_DESTROY(lock) /* empty */
- #define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) /* empty */
- #define ANNOTATE_RWLOCK_RELEASED(lock, is_w) /* empty */
- #define ANNOTATE_BENIGN_RACE(address, description) /* empty */
- #define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) /* empty */
- #define ANNOTATE_THREAD_NAME(name) /* empty */
- #define ANNOTATE_ENABLE_RACE_DETECTION(enable) /* empty */
+#else
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
-/* These annotations are also made available to LLVM's Memory Sanitizer */
-#if DYNAMIC_ANNOTATIONS_ENABLED == 1 || defined(MEMORY_SANITIZER)
- #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
- AnnotateMemoryIsInitialized(__FILE__, __LINE__, address, size)
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
- #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
- AnnotateMemoryIsUninitialized(__FILE__, __LINE__, address, size)
+#if defined(__clang__)
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
+#if !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#endif
#else
- #define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) /* empty */
- #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) /* empty */
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED || MEMORY_SANITIZER */
-/* TODO(delesley) -- Replace __CLANG_SUPPORT_DYN_ANNOTATION__ with the
- appropriate feature ID. */
-#if defined(__clang__) && (!defined(SWIG)) \
- && defined(__CLANG_SUPPORT_DYN_ANNOTATION__)
-
- #if DYNAMIC_ANNOTATIONS_ENABLED == 0
- #define ANNOTALYSIS_ENABLED
- #endif
-
- /* When running in opt-mode, GCC will issue a warning, if these attributes are
- compiled. Only include them when compiling using Clang. */
- #define ATTRIBUTE_IGNORE_READS_BEGIN \
- __attribute((exclusive_lock_function("*")))
- #define ATTRIBUTE_IGNORE_READS_END \
- __attribute((unlock_function("*")))
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#endif
+
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+ ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+
+#endif // ABSL_HAVE_THREAD_SANITIZER
+
+#ifdef __cplusplus
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
#else
- #define ATTRIBUTE_IGNORE_READS_BEGIN /* empty */
- #define ATTRIBUTE_IGNORE_READS_END /* empty */
-#endif /* defined(__clang__) && ... */
+#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
+#define ABSL_INTERNAL_END_EXTERN_C // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
+#endif
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0) || defined(ANNOTALYSIS_ENABLED)
- #define ANNOTATIONS_ENABLED
+// -------------------------------------------------------------------------
+// Define race annotations.
+
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+// Some of the symbols used in this section (e.g. AnnotateBenignRaceSized) are
+// defined by the compiler-based santizer implementation, not by the Abseil
+// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ABSL_ANNOTATE_BENIGN_RACE_STATIC.
+#define ABSL_ANNOTATE_BENIGN_RACE(pointer, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ABSL_ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+ (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ABSL_ANNOTATE_THREAD_NAME(name) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+ (__FILE__, __LINE__, lock)
+#else
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_ANNOTATE_RWLOCK_CREATE(lock)
#endif
-#if (DYNAMIC_ANNOTATIONS_ENABLED != 0)
+// Report that the lock at address `lock` is about to be destroyed.
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Apply ABSL_ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var##_annotator { \
+ public: \
+ static_var##_annotator() { \
+ ABSL_ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+ #static_var ": " description); \
+ } \
+ }; \
+ static static_var##_annotator the##static_var##_annotator; \
+ } // namespace
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateRWLockCreate(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockCreateStatic(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockDestroy(const char* file, int line,
+ const volatile void* lock);
+void AnnotateRWLockAcquired(const char* file, int line,
+ const volatile void* lock, long is_w); // NOLINT
+void AnnotateRWLockReleased(const char* file, int line,
+ const volatile void* lock, long is_w); // NOLINT
+void AnnotateBenignRace(const char* file, int line,
+ const volatile void* address, const char* description);
+void AnnotateBenignRaceSized(const char* file, int line,
+ const volatile void* address, size_t size,
+ const char* description);
+void AnnotateThreadName(const char* file, int line, const char* name);
+void AnnotateEnableRaceDetection(const char* file, int line, int enable);
+ABSL_INTERNAL_END_EXTERN_C
+
+#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ABSL_ANNOTATE_RWLOCK_CREATE(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_DESTROY(lock) // empty
+#define ABSL_ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
+#define ABSL_ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE(address, description) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
+#define ABSL_ANNOTATE_THREAD_NAME(name) // empty
+#define ABSL_ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
+#define ABSL_ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
+
+#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+
+#include <sanitizer/msan_interface.h>
+
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ __msan_unpoison(address, size)
+
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ __msan_allocated_memory(address, size)
+
+#else // !defined(ABSL_HAVE_MEMORY_SANITIZER)
+
+// TODO(rogeeff): remove this branch
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#else
- /* Request the analysis tool to ignore all reads in the current thread
- until ANNOTATE_IGNORE_READS_END is called.
- Useful to ignore intentional racey reads, while still checking
- other reads and all writes.
- See also ANNOTATE_UNPROTECTED_READ. */
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
+#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
- /* Stop ignoring reads. */
- #define ANNOTATE_IGNORE_READS_END() \
- AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+#endif
+
+#endif // ABSL_HAVE_MEMORY_SANITIZER
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
+
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+ __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+ __attribute((unlock_function("*")))
+
+#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
- /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead. */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
- /* Stop ignoring writes. */
- #define ANNOTATE_IGNORE_WRITES_END() \
- AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
-/* Clang provides limited support for static thread-safety analysis
- through a feature called Annotalysis. We configure macro-definitions
- according to whether Annotalysis support is available. */
-#elif defined(ANNOTALYSIS_ENABLED)
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+// Some of the symbols used in this section (e.g. AnnotateIgnoreReadsBegin) are
+// defined by the compiler-based implementation, not by the Abseil
+// library. Therefore they do not use ABSL_INTERNAL_C_SYMBOL.
- #define ANNOTATE_IGNORE_READS_BEGIN() \
- StaticAnnotateIgnoreReadsBegin(__FILE__, __LINE__)
+// Request the analysis tool to ignore all reads in the current thread until
+// ABSL_ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ABSL_ANNOTATE_UNPROTECTED_READ.
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin) \
+ (__FILE__, __LINE__)
- #define ANNOTATE_IGNORE_READS_END() \
- StaticAnnotateIgnoreReadsEnd(__FILE__, __LINE__)
+// Stop ignoring reads.
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
+ (__FILE__, __LINE__)
- #define ANNOTATE_IGNORE_WRITES_BEGIN() \
- StaticAnnotateIgnoreWritesBegin(__FILE__, __LINE__)
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreReadsBegin(const char* file, int line)
+ ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE;
+void AnnotateIgnoreReadsEnd(const char* file,
+ int line) ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE;
+ABSL_INTERNAL_END_EXTERN_C
- #define ANNOTATE_IGNORE_WRITES_END() \
- StaticAnnotateIgnoreWritesEnd(__FILE__, __LINE__)
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
+
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED( \
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
+ ()
+
+#define ABSL_ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED( \
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
+ ()
+
+ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalAnnotateIgnoreReadsBegin)()
+ ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE {}
+
+ABSL_INTERNAL_STATIC_INLINE void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalAnnotateIgnoreReadsEnd)()
+ ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE {}
#else
- #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_END() /* empty */
- #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_WRITES_END() /* empty */
+
+#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
+
#endif
-/* Implement the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
- primitive annotations defined above. */
-#if defined(ANNOTATIONS_ENABLED)
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
- /* Start ignoring all memory accesses (both reads and writes). */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
- do { \
- ANNOTATE_IGNORE_READS_BEGIN(); \
- ANNOTATE_IGNORE_WRITES_BEGIN(); \
- }while (0)
+// Similar to ABSL_ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
- /* Stop ignoring both reads and writes. */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
- do { \
- ANNOTATE_IGNORE_WRITES_END(); \
- ANNOTATE_IGNORE_READS_END(); \
- }while (0)
+// Stop ignoring writes.
+#define ABSL_ANNOTATE_IGNORE_WRITES_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+// Function prototypes of annotations provided by the compiler-based sanitizer
+// implementation.
+ABSL_INTERNAL_BEGIN_EXTERN_C
+void AnnotateIgnoreWritesBegin(const char* file, int line);
+void AnnotateIgnoreWritesEnd(const char* file, int line);
+ABSL_INTERNAL_END_EXTERN_C
#else
- #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
- #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
-#endif
-/* Use the macros above rather than using these functions directly. */
-#include <stddef.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-void AnnotateRWLockCreate(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockCreateStatic(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockDestroy(const char *file, int line,
- const volatile void *lock);
-void AnnotateRWLockAcquired(const char *file, int line,
- const volatile void *lock, long is_w); /* NOLINT */
-void AnnotateRWLockReleased(const char *file, int line,
- const volatile void *lock, long is_w); /* NOLINT */
-void AnnotateBenignRace(const char *file, int line,
- const volatile void *address,
- const char *description);
-void AnnotateBenignRaceSized(const char *file, int line,
- const volatile void *address,
- size_t size,
- const char *description);
-void AnnotateThreadName(const char *file, int line,
- const char *name);
-void AnnotateEnableRaceDetection(const char *file, int line, int enable);
-void AnnotateMemoryIsInitialized(const char *file, int line,
- const volatile void *mem, size_t size);
-void AnnotateMemoryIsUninitialized(const char *file, int line,
- const volatile void *mem, size_t size);
-
-/* Annotations expand to these functions, when Dynamic Annotations are enabled.
- These functions are either implemented as no-op calls, if no Sanitizer is
- attached, or provided with externally-linked implementations by a library
- like ThreadSanitizer. */
-void AnnotateIgnoreReadsBegin(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_BEGIN;
-void AnnotateIgnoreReadsEnd(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_END;
-void AnnotateIgnoreWritesBegin(const char *file, int line);
-void AnnotateIgnoreWritesEnd(const char *file, int line);
-
-#if defined(ANNOTALYSIS_ENABLED)
-/* When Annotalysis is enabled without Dynamic Annotations, the use of
- static-inline functions allows the annotations to be read at compile-time,
- while still letting the compiler elide the functions from the final build.
-
- TODO(delesley) -- The exclusive lock here ignores writes as well, but
- allows IGNORE_READS_AND_WRITES to work properly. */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-static inline void StaticAnnotateIgnoreReadsBegin(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_BEGIN { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreReadsEnd(const char *file, int line)
- ATTRIBUTE_IGNORE_READS_END { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesBegin(
- const char *file, int line) { (void)file; (void)line; }
-static inline void StaticAnnotateIgnoreWritesEnd(
- const char *file, int line) { (void)file; (void)line; }
-#pragma GCC diagnostic pop
+#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
+
#endif
-/* Return non-zero value if running under valgrind.
-
- If "valgrind.h" is included into dynamic_annotations.cc,
- the regular valgrind mechanism will be used.
- See http://valgrind.org/docs/manual/manual-core-adv.html about
- RUNNING_ON_VALGRIND and other valgrind "client requests".
- The file "valgrind.h" may be obtained by doing
- svn co svn://svn.valgrind.org/valgrind/trunk/include
-
- If for some reason you can't use "valgrind.h" or want to fake valgrind,
- there are two ways to make this function return non-zero:
- - Use environment variable: export RUNNING_ON_VALGRIND=1
- - Make your tool intercept the function RunningOnValgrind() and
- change its return value.
- */
-int RunningOnValgrind(void);
-
-/* ValgrindSlowdown returns:
- * 1.0, if (RunningOnValgrind() == 0)
- * 50.0, if (RunningOnValgrind() != 0 && getenv("VALGRIND_SLOWDOWN") == NULL)
- * atof(getenv("VALGRIND_SLOWDOWN")) otherwise
- This function can be used to scale timeout values:
- EXAMPLE:
- for (;;) {
- DoExpensiveBackgroundTask();
- SleepForSeconds(5 * ValgrindSlowdown());
- }
- */
-double ValgrindSlowdown(void);
+// -------------------------------------------------------------------------
+// Define the ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+// Instead of doing
+// ABSL_ANNOTATE_IGNORE_READS_BEGIN();
+// ... = x;
+// ABSL_ANNOTATE_IGNORE_READS_END();
+// one can use
+// ... = ABSL_ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ABSL_ANNOTATE_IGNORE_READS_BEGIN(); \
+ ABSL_ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ } while (0)
+
+// Stop ignoring both reads and writes.
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ABSL_ANNOTATE_IGNORE_WRITES_END(); \
+ ABSL_ANNOTATE_IGNORE_READS_END(); \
+ } while (0)
#ifdef __cplusplus
-}
-#endif
+// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
+ absl::base_internal::AnnotateUnprotectedRead(x)
-/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
- Instead of doing
- ANNOTATE_IGNORE_READS_BEGIN();
- ... = x;
- ANNOTATE_IGNORE_READS_END();
- one can use
- ... = ANNOTATE_UNPROTECTED_READ(x); */
-#if defined(__cplusplus) && defined(ANNOTATIONS_ENABLED)
template <typename T>
-inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */
- ANNOTATE_IGNORE_READS_BEGIN();
+inline T AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
+ ABSL_ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
- ANNOTATE_IGNORE_READS_END();
+ ABSL_ANNOTATE_IGNORE_READS_END();
return res;
- }
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif
+
#else
- #define ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
+#define ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
+#define ABSL_ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#endif
+
+#ifdef __cplusplus
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+ABSL_INTERNAL_BEGIN_EXTERN_C
+int RunningOnValgrind();
+double ValgrindSlowdown();
+ABSL_INTERNAL_END_EXTERN_C
+#else
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+ABSL_DEPRECATED(
+ "Don't use this interface. It is misleading and is being deleted.")
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline int RunningOnValgrind() { return 0; }
+ABSL_DEPRECATED(
+ "Don't use this interface. It is misleading and is being deleted.")
+ABSL_ATTRIBUTE_ALWAYS_INLINE inline double ValgrindSlowdown() { return 1.0; }
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+using absl::base_internal::RunningOnValgrind;
+using absl::base_internal::ValgrindSlowdown;
+#endif
#endif
-#if DYNAMIC_ANNOTATIONS_ENABLED != 0 && defined(__cplusplus)
- /* Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable. */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
- namespace { \
- class static_var ## _annotator { \
- public: \
- static_var ## _annotator() { \
- ANNOTATE_BENIGN_RACE_SIZED(&static_var, \
- sizeof(static_var), \
- # static_var ": " description); \
- } \
- }; \
- static static_var ## _annotator the ## static_var ## _annotator;\
- } // namespace
-#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
- #define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) /* empty */
-#endif /* DYNAMIC_ANNOTATIONS_ENABLED */
-
-#ifdef ADDRESS_SANITIZER
-/* Describe the current state of a contiguous container such as e.g.
- * std::vector or std::string. For more details see
- * sanitizer/common_interface_defs.h, which is provided by the compiler. */
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
#include <sanitizer/common_interface_defs.h>
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name) \
- struct { char x[8] __attribute__ ((aligned (8))); } name
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
+ struct { \
+ char x[8] __attribute__((aligned(8))); \
+ } name
+
#else
-#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
-#define ADDRESS_SANITIZER_REDZONE(name)
-#endif // ADDRESS_SANITIZER
-/* Undefine the macros intended only in this file. */
-#undef ANNOTALYSIS_ENABLED
-#undef ANNOTATIONS_ENABLED
-#undef ATTRIBUTE_IGNORE_READS_BEGIN
-#undef ATTRIBUTE_IGNORE_READS_END
+#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) // empty
+#define ABSL_ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
+
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
-#endif /* ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ */
+#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/exception_safety_testing_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/exception_safety_testing_test.cc
index 7518264d2ec..a59be29e919 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/exception_safety_testing_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/exception_safety_testing_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,8 @@
#include "absl/base/internal/exception_safety_testing.h"
+#ifdef ABSL_HAVE_EXCEPTIONS
+
#include <cstddef>
#include <exception>
#include <iostream>
@@ -326,17 +328,15 @@ TEST(ThrowingValueTest, NonThrowingDelete) {
UnsetCountdown();
}
-using Storage =
- absl::aligned_storage_t<sizeof(ThrowingValue<>), alignof(ThrowingValue<>)>;
-
TEST(ThrowingValueTest, NonThrowingPlacementDelete) {
constexpr int kArrayLen = 2;
// We intentionally create extra space to store the tag allocated by placement
// new[].
constexpr int kStorageLen = 4;
- Storage buf;
- Storage array_buf[kStorageLen];
+ alignas(ThrowingValue<>) unsigned char buf[sizeof(ThrowingValue<>)];
+ alignas(ThrowingValue<>) unsigned char
+ array_buf[sizeof(ThrowingValue<>[kStorageLen])];
auto* placed = new (&buf) ThrowingValue<>(1);
auto placed_array = new (&array_buf) ThrowingValue<>[kArrayLen];
@@ -900,12 +900,12 @@ TEST(ConstructorTrackerTest, CreatedAfter) {
}
TEST(ConstructorTrackerTest, NotDestroyedAfter) {
- absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
+ alignas(Tracked) unsigned char storage[sizeof(Tracked)];
EXPECT_NONFATAL_FAILURE(
{
exceptions_internal::ConstructorTracker ct(
exceptions_internal::countdown);
- new (&storage) Tracked;
+ new (&storage) Tracked();
},
"not destroyed");
}
@@ -922,11 +922,11 @@ TEST(ConstructorTrackerTest, DestroyedTwice) {
TEST(ConstructorTrackerTest, ConstructedTwice) {
exceptions_internal::ConstructorTracker ct(exceptions_internal::countdown);
- absl::aligned_storage_t<sizeof(Tracked), alignof(Tracked)> storage;
+ alignas(Tracked) unsigned char storage[sizeof(Tracked)];
EXPECT_NONFATAL_FAILURE(
{
- new (&storage) Tracked;
- new (&storage) Tracked;
+ new (&storage) Tracked();
+ new (&storage) Tracked();
reinterpret_cast<Tracked*>(&storage)->~Tracked();
},
"re-constructed");
@@ -952,3 +952,5 @@ TEST(ThrowingAllocatorTraitsTest, Assignablility) {
} // namespace
} // namespace testing
+
+#endif // ABSL_HAVE_EXCEPTIONS
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test.cc
index 5499189a3da..37a40e1e40a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace inline_variable_testing_internal {
namespace {
@@ -59,4 +60,5 @@ TEST(InlineVariableTest, FunPtrType) {
} // namespace
} // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_a.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_a.cc
index a3bf3b68b3c..f96a58d9b42 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_a.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_a.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/base/internal/inline_variable_testing.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace inline_variable_testing_internal {
const Foo& get_foo_a() { return inline_variable_foo; }
@@ -22,4 +23,5 @@ const Foo& get_foo_a() { return inline_variable_foo; }
const int& get_int_a() { return inline_variable_int; }
} // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_b.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_b.cc
index b4b9393a558..038adc30a9f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_b.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/inline_variable_test_b.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/base/internal/inline_variable_testing.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace inline_variable_testing_internal {
const Foo& get_foo_b() { return inline_variable_foo; }
@@ -22,4 +23,5 @@ const Foo& get_foo_b() { return inline_variable_foo; }
const int& get_int_b() { return inline_variable_int; }
} // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook.h
index b458511b0c7..ae21cd7fe50 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook.h
@@ -4,14 +4,13 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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_H_
#define ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
@@ -21,28 +20,51 @@
#include <cstdint>
#include <utility>
-#ifdef _MSC_FULL_VER
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 0
+#else
+#define ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT 1
+#endif
+
+#if defined(_MSC_VER)
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 0
#else
#define ABSL_HAVE_WORKING_ATOMIC_POINTER 1
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
template <typename T>
class AtomicHook;
-// AtomicHook is a helper class, templatized on a raw function pointer type, for
-// implementing Abseil customization hooks. It is a callable object that
-// dispatches to the registered hook.
+// To workaround AtomicHook not being constant-initializable on some platforms,
+// prefer to annotate instances with `ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES`
+// instead of `ABSL_CONST_INIT`.
+#if ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_CONST_INIT
+#else
+#define ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+#endif
+
+// `AtomicHook` is a helper class, templatized on a raw function pointer type,
+// for implementing Abseil customization hooks. It is a callable object that
+// dispatches to the registered hook. Objects of type `AtomicHook` must have
+// static or thread storage duration.
//
// A default constructed object performs a no-op (and returns a default
// constructed object) if no hook has been registered.
//
-// Hooks can be pre-registered via constant initialization, for example,
-// ABSL_CONST_INIT static AtomicHook<void(*)()> my_hook(DefaultAction);
-// and then changed at runtime via a call to Store().
+// Hooks can be pre-registered via constant initialization, for example:
+//
+// ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static AtomicHook<void(*)()>
+// my_hook(DefaultAction);
+//
+// and then changed at runtime via a call to `Store()`.
//
// Reads and writes guarantee memory_order_acquire/memory_order_release
// semantics.
@@ -57,12 +79,23 @@ class AtomicHook<ReturnType (*)(Args...)> {
// Constructs an object that by default dispatches to/returns the
// pre-registered default_fn when no hook has been registered at runtime.
-#if ABSL_HAVE_WORKING_ATOMIC_POINTER
+#if ABSL_HAVE_WORKING_ATOMIC_POINTER && ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
explicit constexpr AtomicHook(FnPtr default_fn)
: hook_(default_fn), default_fn_(default_fn) {}
-#else
+#elif ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
explicit constexpr AtomicHook(FnPtr default_fn)
: hook_(kUninitialized), default_fn_(default_fn) {}
+#else
+ // As of January 2020, on all known versions of MSVC this constructor runs in
+ // the global constructor sequence. If `Store()` is called by a dynamic
+ // initializer, we want to preserve the value, even if this constructor runs
+ // after the call to `Store()`. If not, `hook_` will be
+ // zero-initialized by the linker and we have no need to set it.
+ // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+ explicit constexpr AtomicHook(FnPtr default_fn)
+ : /* hook_(deliberately omitted), */ default_fn_(default_fn) {
+ static_assert(kUninitialized == 0, "here we rely on zero-initialization");
+ }
#endif
// Stores the provided function pointer as the value for this hook.
@@ -158,8 +191,10 @@ class AtomicHook<ReturnType (*)(Args...)> {
};
#undef ABSL_HAVE_WORKING_ATOMIC_POINTER
+#undef ABSL_HAVE_WORKING_CONSTEXPR_STATIC_INIT
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ATOMIC_HOOK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test.cc
index cf7407573a5..e577a8fd930 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,16 +14,22 @@
#include "absl/base/internal/atomic_hook.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook_test_helper.h"
namespace {
+using ::testing::Eq;
+
int value = 0;
void TestHook(int x) { value = x; }
TEST(AtomicHookTest, NoDefaultFunction) {
- ABSL_CONST_INIT static absl::base_internal::AtomicHook<void(*)(int)> hook;
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+ void (*)(int)>
+ hook;
value = 0;
// Test the default DummyFunction.
@@ -49,8 +55,9 @@ TEST(AtomicHookTest, NoDefaultFunction) {
TEST(AtomicHookTest, WithDefaultFunction) {
// Set the default value to TestHook at compile-time.
- ABSL_CONST_INIT static absl::base_internal::AtomicHook<void (*)(int)> hook(
- TestHook);
+ ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+ void (*)(int)>
+ hook(TestHook);
value = 0;
// Test the default value is TestHook.
@@ -67,4 +74,24 @@ TEST(AtomicHookTest, WithDefaultFunction) {
EXPECT_EQ(value, 2);
}
+ABSL_CONST_INIT int override_func_calls = 0;
+void OverrideFunc() { override_func_calls++; }
+static struct OverrideInstaller {
+ OverrideInstaller() { absl::atomic_hook_internal::func.Store(OverrideFunc); }
+} override_installer;
+
+TEST(AtomicHookTest, DynamicInitFromAnotherTU) {
+ // MSVC 14.2 doesn't do constexpr static init correctly; in particular it
+ // tends to sequence static init (i.e. defaults) of `AtomicHook` objects
+ // after their dynamic init (i.e. overrides), overwriting whatever value was
+ // written during dynamic init. This regression test validates the fix.
+ // https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+ EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));
+ EXPECT_THAT(override_func_calls, Eq(0));
+ absl::atomic_hook_internal::func();
+ EXPECT_THAT(absl::atomic_hook_internal::default_func_calls, Eq(0));
+ EXPECT_THAT(override_func_calls, Eq(1));
+ EXPECT_THAT(absl::atomic_hook_internal::func.Load(), Eq(OverrideFunc));
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.cc
new file mode 100644
index 00000000000..537d47cd2d2
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.cc
@@ -0,0 +1,32 @@
+// 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.
+
+#include "absl/base/internal/atomic_hook_test_helper.h"
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace atomic_hook_internal {
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<VoidF>
+ func(DefaultFunc);
+ABSL_CONST_INIT int default_func_calls = 0;
+void DefaultFunc() { default_func_calls++; }
+void RegisterFunc(VoidF f) { func.Store(f); }
+
+} // namespace atomic_hook_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/atomic_hook_test_helper.h
new file mode 100644
index 00000000000..3e72b4977d2
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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_ATOMIC_HOOK_TEST_HELPER_H_
+#define ABSL_BASE_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_ATOMIC_HOOK_TEST_HELPER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits.h
deleted file mode 100644
index bc7faaee3b2..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits.h
+++ /dev/null
@@ -1,193 +0,0 @@
-// 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
-//
-// http://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_BITS_H_
-#define ABSL_BASE_INTERNAL_BITS_H_
-
-// This file contains bitwise ops which are implementation details of various
-// absl libraries.
-
-#include <cstdint>
-
-// Clang on Windows has __builtin_clzll; otherwise we need to use the
-// windows intrinsic functions.
-#if defined(_MSC_VER)
-#include <intrin.h>
-#if defined(_M_X64)
-#pragma intrinsic(_BitScanReverse64)
-#pragma intrinsic(_BitScanForward64)
-#endif
-#pragma intrinsic(_BitScanReverse)
-#pragma intrinsic(_BitScanForward)
-#endif
-
-#include "absl/base/attributes.h"
-
-#if defined(_MSC_VER)
-// We can achieve something similar to attribute((always_inline)) with MSVC by
-// using the __forceinline keyword, however this is not perfect. MSVC is
-// much less aggressive about inlining, and even with the __forceinline keyword.
-#define ABSL_BASE_INTERNAL_FORCEINLINE __forceinline
-#else
-// Use default attribute inline.
-#define ABSL_BASE_INTERNAL_FORCEINLINE inline ABSL_ATTRIBUTE_ALWAYS_INLINE
-#endif
-
-
-namespace absl {
-namespace base_internal {
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64Slow(uint64_t n) {
- int zeroes = 60;
- if (n >> 32) zeroes -= 32, n >>= 32;
- if (n >> 16) zeroes -= 16, n >>= 16;
- if (n >> 8) zeroes -= 8, n >>= 8;
- if (n >> 4) zeroes -= 4, n >>= 4;
- return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros64(uint64_t n) {
-#if defined(_MSC_VER) && defined(_M_X64)
- // MSVC does not have __buitin_clzll. Use _BitScanReverse64.
- unsigned long result = 0; // NOLINT(runtime/int)
- if (_BitScanReverse64(&result, n)) {
- return 63 - result;
- }
- return 64;
-#elif defined(_MSC_VER)
- // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
- unsigned long result = 0; // NOLINT(runtime/int)
- if ((n >> 32) && _BitScanReverse(&result, n >> 32)) {
- return 31 - result;
- }
- if (_BitScanReverse(&result, n)) {
- return 63 - result;
- }
- return 64;
-#elif defined(__GNUC__)
- // Use __builtin_clzll, which uses the following instructions:
- // x86: bsr
- // ARM64: clz
- // PPC: cntlzd
- static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
- "__builtin_clzll does not take 64-bit arg");
-
- // Handle 0 as a special case because __builtin_clzll(0) is undefined.
- if (n == 0) {
- return 64;
- }
- return __builtin_clzll(n);
-#else
- return CountLeadingZeros64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32Slow(uint64_t n) {
- int zeroes = 28;
- if (n >> 16) zeroes -= 16, n >>= 16;
- if (n >> 8) zeroes -= 8, n >>= 8;
- if (n >> 4) zeroes -= 4, n >>= 4;
- return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[n] + zeroes;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountLeadingZeros32(uint32_t n) {
-#if defined(_MSC_VER)
- unsigned long result = 0; // NOLINT(runtime/int)
- if (_BitScanReverse(&result, n)) {
- return 31 - result;
- }
- return 32;
-#elif defined(__GNUC__)
- // Use __builtin_clz, which uses the following instructions:
- // x86: bsr
- // ARM64: clz
- // PPC: cntlzd
- static_assert(sizeof(int) == sizeof(n),
- "__builtin_clz does not take 32-bit arg");
-
- // Handle 0 as a special case because __builtin_clz(0) is undefined.
- if (n == 0) {
- return 32;
- }
- return __builtin_clz(n);
-#else
- return CountLeadingZeros32Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64Slow(uint64_t n) {
- int c = 63;
- n &= ~n + 1;
- if (n & 0x00000000FFFFFFFF) c -= 32;
- if (n & 0x0000FFFF0000FFFF) c -= 16;
- if (n & 0x00FF00FF00FF00FF) c -= 8;
- if (n & 0x0F0F0F0F0F0F0F0F) c -= 4;
- if (n & 0x3333333333333333) c -= 2;
- if (n & 0x5555555555555555) c -= 1;
- return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero64(uint64_t n) {
-#if defined(_MSC_VER) && defined(_M_X64)
- unsigned long result = 0; // NOLINT(runtime/int)
- _BitScanForward64(&result, n);
- return result;
-#elif defined(_MSC_VER)
- unsigned long result = 0; // NOLINT(runtime/int)
- if (static_cast<uint32_t>(n) == 0) {
- _BitScanForward(&result, n >> 32);
- return result + 32;
- }
- _BitScanForward(&result, n);
- return result;
-#elif defined(__GNUC__)
- static_assert(sizeof(unsigned long long) == sizeof(n), // NOLINT(runtime/int)
- "__builtin_ctzll does not take 64-bit arg");
- return __builtin_ctzll(n);
-#else
- return CountTrailingZerosNonZero64Slow(n);
-#endif
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32Slow(uint32_t n) {
- int c = 31;
- n &= ~n + 1;
- if (n & 0x0000FFFF) c -= 16;
- if (n & 0x00FF00FF) c -= 8;
- if (n & 0x0F0F0F0F) c -= 4;
- if (n & 0x33333333) c -= 2;
- if (n & 0x55555555) c -= 1;
- return c;
-}
-
-ABSL_BASE_INTERNAL_FORCEINLINE int CountTrailingZerosNonZero32(uint32_t n) {
-#if defined(_MSC_VER)
- unsigned long result = 0; // NOLINT(runtime/int)
- _BitScanForward(&result, n);
- return result;
-#elif defined(__GNUC__)
- static_assert(sizeof(int) == sizeof(n),
- "__builtin_ctz does not take 32-bit arg");
- return __builtin_ctz(n);
-#else
- return CountTrailingZerosNonZero32Slow(n);
-#endif
-}
-
-#undef ABSL_BASE_INTERNAL_FORCEINLINE
-
-} // namespace base_internal
-} // namespace absl
-
-#endif // ABSL_BASE_INTERNAL_BITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits_test.cc
deleted file mode 100644
index e5d991d6725..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/bits_test.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "absl/base/internal/bits.h"
-
-#include "gtest/gtest.h"
-
-namespace {
-
-int CLZ64(uint64_t n) {
- int fast = absl::base_internal::CountLeadingZeros64(n);
- int slow = absl::base_internal::CountLeadingZeros64Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros64) {
- EXPECT_EQ(64, CLZ64(uint64_t{}));
- EXPECT_EQ(0, CLZ64(~uint64_t{}));
-
- for (int index = 0; index < 64; index++) {
- uint64_t x = static_cast<uint64_t>(1) << index;
- const auto cnt = 63 - index;
- ASSERT_EQ(cnt, CLZ64(x)) << index;
- ASSERT_EQ(cnt, CLZ64(x + x - 1)) << index;
- }
-}
-
-int CLZ32(uint32_t n) {
- int fast = absl::base_internal::CountLeadingZeros32(n);
- int slow = absl::base_internal::CountLeadingZeros32Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountLeadingZeros32) {
- EXPECT_EQ(32, CLZ32(uint32_t{}));
- EXPECT_EQ(0, CLZ32(~uint32_t{}));
-
- for (int index = 0; index < 32; index++) {
- uint32_t x = static_cast<uint32_t>(1) << index;
- const auto cnt = 31 - index;
- ASSERT_EQ(cnt, CLZ32(x)) << index;
- ASSERT_EQ(cnt, CLZ32(x + x - 1)) << index;
- ASSERT_EQ(CLZ64(x), CLZ32(x) + 32);
- }
-}
-
-int CTZ64(uint64_t n) {
- int fast = absl::base_internal::CountTrailingZerosNonZero64(n);
- int slow = absl::base_internal::CountTrailingZerosNonZero64Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero64) {
- EXPECT_EQ(0, CTZ64(~uint64_t{}));
-
- for (int index = 0; index < 64; index++) {
- uint64_t x = static_cast<uint64_t>(1) << index;
- const auto cnt = index;
- ASSERT_EQ(cnt, CTZ64(x)) << index;
- ASSERT_EQ(cnt, CTZ64(~(x - 1))) << index;
- }
-}
-
-int CTZ32(uint32_t n) {
- int fast = absl::base_internal::CountTrailingZerosNonZero32(n);
- int slow = absl::base_internal::CountTrailingZerosNonZero32Slow(n);
- EXPECT_EQ(fast, slow) << n;
- return fast;
-}
-
-TEST(BitsTest, CountTrailingZerosNonZero32) {
- EXPECT_EQ(0, CTZ32(~uint32_t{}));
-
- for (int index = 0; index < 32; index++) {
- uint32_t x = static_cast<uint32_t>(1) << index;
- const auto cnt = index;
- ASSERT_EQ(cnt, CTZ32(x)) << index;
- ASSERT_EQ(cnt, CTZ32(~(x - 1))) << index;
- }
-}
-
-
-} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cmake_thread_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cmake_thread_test.cc
new file mode 100644
index 00000000000..f70bb24eb7b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cmake_thread_test.cc
@@ -0,0 +1,22 @@
+// 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.
+
+#include <iostream>
+#include "absl/base/internal/thread_identity.h"
+
+int main() {
+ auto* tid = absl::base_internal::CurrentThreadIdentityIfPresent();
+ // Make sure the above call can't be optimized out
+ std::cout << (void*)tid << std::endl;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.cc
index a742df01f94..0e65005b891 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,11 +22,13 @@
#include "absl/base/internal/cycleclock.h"
+#include <atomic>
#include <chrono> // NOLINT(build/c++11)
#include "absl/base/internal/unscaledcycleclock.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
#if ABSL_USE_UNSCALED_CYCLECLOCK
@@ -52,17 +54,40 @@ static constexpr int32_t kShift = 2;
#endif
static constexpr double kFrequencyScale = 1.0 / (1 << kShift);
+static std::atomic<CycleClockSourceFunc> cycle_clock_source;
+
+CycleClockSourceFunc LoadCycleClockSource() {
+ // Optimize for the common case (no callback) by first doing a relaxed load;
+ // this is significantly faster on non-x86 platforms.
+ if (cycle_clock_source.load(std::memory_order_relaxed) == nullptr) {
+ return nullptr;
+ }
+ // This corresponds to the store(std::memory_order_release) in
+ // CycleClockSource::Register, and makes sure that any updates made prior to
+ // registering the callback are visible to this thread before the callback is
+ // invoked.
+ return cycle_clock_source.load(std::memory_order_acquire);
+}
} // namespace
int64_t CycleClock::Now() {
- return base_internal::UnscaledCycleClock::Now() >> kShift;
+ auto fn = LoadCycleClockSource();
+ if (fn == nullptr) {
+ return base_internal::UnscaledCycleClock::Now() >> kShift;
+ }
+ return fn() >> kShift;
}
double CycleClock::Frequency() {
return kFrequencyScale * base_internal::UnscaledCycleClock::Frequency();
}
+void CycleClockSource::Register(CycleClockSourceFunc source) {
+ // Corresponds to the load(std::memory_order_acquire) in LoadCycleClockSource.
+ cycle_clock_source.store(source, std::memory_order_release);
+}
+
#else
int64_t CycleClock::Now() {
@@ -78,4 +103,5 @@ double CycleClock::Frequency() {
#endif
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.h
index 60e971583c5..a18b5844456 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/cycleclock.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,7 +28,6 @@
// not necessarily "CPU cycles" and code should not rely on that behavior, even
// if experimentally observed.
//
-//
// An arbitrary offset may have been added to the counter at power on.
//
// On some platforms, the rate and offset of the counter may differ
@@ -45,7 +44,10 @@
#include <cstdint>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// -----------------------------------------------------------------------------
@@ -71,7 +73,22 @@ class CycleClock {
CycleClock& operator=(const CycleClock&) = delete;
};
+using CycleClockSourceFunc = int64_t (*)();
+
+class CycleClockSource {
+ private:
+ // CycleClockSource::Register()
+ //
+ // Register a function that provides an alternate source for the unscaled CPU
+ // cycle count value. The source function must be async signal safe, must not
+ // call CycleClock::Now(), and must have a frequency that matches that of the
+ // unscaled clock used by CycleClock. A nullptr value resets CycleClock to use
+ // the default source.
+ static void Register(CycleClockSourceFunc source);
+};
+
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_CYCLECLOCK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/direct_mmap.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/direct_mmap.h
index 654a6007270..274054cd5a8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/direct_mmap.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/direct_mmap.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -61,7 +61,12 @@ extern "C" void* __mmap2(void*, size_t, int, int, int, size_t);
#endif
#endif // __BIONIC__
+#if defined(__NR_mmap2) && !defined(SYS_mmap2)
+#define SYS_mmap2 __NR_mmap2
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Platform specific logic extracted from
@@ -69,9 +74,13 @@ namespace base_internal {
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
off64_t offset) noexcept {
#if defined(__i386__) || defined(__ARM_ARCH_3__) || defined(__ARM_EABI__) || \
+ defined(__m68k__) || defined(__sh__) || \
+ (defined(__hppa__) && !defined(__LP64__)) || \
(defined(__mips__) && _MIPS_SIM == _MIPS_SIM_ABI32) || \
(defined(__PPC__) && !defined(__PPC64__)) || \
- (defined(__s390__) && !defined(__s390x__))
+ (defined(__riscv) && __riscv_xlen == 32) || \
+ (defined(__s390__) && !defined(__s390x__)) || \
+ (defined(__sparc__) && !defined(__arch64__))
// On these architectures, implement mmap with mmap2.
static int pagesize = 0;
if (pagesize == 0) {
@@ -128,6 +137,7 @@ inline int DirectMunmap(void* start, size_t length) {
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#else // !__linux__
@@ -136,6 +146,7 @@ inline int DirectMunmap(void* start, size_t length) {
// actual mmap()/munmap() methods.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
inline void* DirectMmap(void* start, size_t length, int prot, int flags, int fd,
@@ -148,6 +159,7 @@ inline int DirectMunmap(void* start, size_t length) {
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // __linux__
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/dynamic_annotations.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/dynamic_annotations.h
new file mode 100644
index 00000000000..b23c5ec1c41
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/dynamic_annotations.h
@@ -0,0 +1,398 @@
+// 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 defines dynamic annotations for use with dynamic analysis tool
+// such as valgrind, PIN, etc.
+//
+// Dynamic annotation is a source code annotation that affects the generated
+// code (that is, the annotation is not a comment). Each such annotation is
+// attached to a particular instruction and/or to a particular object (address)
+// in the program.
+//
+// The annotations that should be used by users are macros in all upper-case
+// (e.g., ANNOTATE_THREAD_NAME).
+//
+// Actual implementation of these macros may differ depending on the dynamic
+// analysis tool being used.
+//
+// This file supports the following configurations:
+// - Dynamic Annotations enabled (with static thread-safety warnings disabled).
+// In this case, macros expand to functions implemented by Thread Sanitizer,
+// when building with TSan. When not provided an external implementation,
+// dynamic_annotations.cc provides no-op implementations.
+//
+// - Static Clang thread-safety warnings enabled.
+// When building with a Clang compiler that supports thread-safety warnings,
+// a subset of annotations can be statically-checked at compile-time. We
+// expand these macros to static-inline functions that can be analyzed for
+// thread-safety, but afterwards elided when building the final binary.
+//
+// - All annotations are disabled.
+// If neither Dynamic Annotations nor Clang thread-safety warnings are
+// enabled, then all annotation-macros expand to empty.
+
+#ifndef ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+#define ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
+
+#include <stddef.h>
+
+#include "absl/base/config.h"
+
+// -------------------------------------------------------------------------
+// Decide which features are enabled
+
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+#define DYNAMIC_ANNOTATIONS_ENABLED 0
+#endif
+
+#if defined(__clang__) && !defined(SWIG)
+#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
+#endif
+
+#if DYNAMIC_ANNOTATIONS_ENABLED != 0
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED 1
+
+#else
+
+#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
+#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+
+// Clang provides limited support for static thread-safety analysis through a
+// feature called Annotalysis. We configure macro-definitions according to
+// whether Annotalysis support is available. When running in opt-mode, GCC
+// will issue a warning, if these attributes are compiled. Only include them
+// when compiling using Clang.
+
+// ANNOTALYSIS_ENABLED == 1 when IGNORE_READ_ATTRIBUTE_ENABLED == 1
+#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED \
+ defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
+#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
+ ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#endif
+
+// Memory annotations are also made available to LLVM's Memory Sanitizer
+#if defined(ABSL_HAVE_MEMORY_SANITIZER) && !defined(__native_client__)
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 1
+#endif
+
+#ifndef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#define ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED 0
+#endif
+
+#ifdef __cplusplus
+#define ABSL_INTERNAL_BEGIN_EXTERN_C extern "C" {
+#define ABSL_INTERNAL_END_EXTERN_C } // extern "C"
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) ::F
+#define ABSL_INTERNAL_STATIC_INLINE inline
+#else
+#define ABSL_INTERNAL_BEGIN_EXTERN_C // empty
+#define ABSL_INTERNAL_END_EXTERN_C // empty
+#define ABSL_INTERNAL_GLOBAL_SCOPED(F) F
+#define ABSL_INTERNAL_STATIC_INLINE static inline
+#endif
+
+// -------------------------------------------------------------------------
+// Define race annotations.
+
+#if ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 1
+
+// -------------------------------------------------------------
+// Annotations that suppress errors. It is usually better to express the
+// program's synchronization using the other annotations, but these can be used
+// when all else fails.
+
+// Report that we may have a benign race at `pointer`, with size
+// "sizeof(*(pointer))". `pointer` must be a non-void* pointer. Insert at the
+// point where `pointer` has been allocated, preferably close to the point
+// where the race happens. See also ANNOTATE_BENIGN_RACE_STATIC.
+#define ANNOTATE_BENIGN_RACE(pointer, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, pointer, sizeof(*(pointer)), description)
+
+// Same as ANNOTATE_BENIGN_RACE(`address`, `description`), but applies to
+// the memory range [`address`, `address`+`size`).
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateBenignRaceSized) \
+ (__FILE__, __LINE__, address, size, description)
+
+// Enable (`enable`!=0) or disable (`enable`==0) race detection for all threads.
+// This annotation could be useful if you want to skip expensive race analysis
+// during some period of program execution, e.g. during initialization.
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateEnableRaceDetection) \
+ (__FILE__, __LINE__, enable)
+
+// -------------------------------------------------------------
+// Annotations useful for debugging.
+
+// Report the current thread `name` to a race detector.
+#define ANNOTATE_THREAD_NAME(name) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateThreadName)(__FILE__, __LINE__, name)
+
+// -------------------------------------------------------------
+// Annotations useful when implementing locks. They are not normally needed by
+// modules that merely use locks. The `lock` argument is a pointer to the lock
+// object.
+
+// Report that a lock has been created at address `lock`.
+#define ANNOTATE_RWLOCK_CREATE(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreate)(__FILE__, __LINE__, lock)
+
+// Report that a linker initialized lock has been created at address `lock`.
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockCreateStatic) \
+ (__FILE__, __LINE__, lock)
+#else
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) ANNOTATE_RWLOCK_CREATE(lock)
+#endif
+
+// Report that the lock at address `lock` is about to be destroyed.
+#define ANNOTATE_RWLOCK_DESTROY(lock) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockDestroy)(__FILE__, __LINE__, lock)
+
+// Report that the lock at address `lock` has been acquired.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockAcquired) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Report that the lock at address `lock` is about to be released.
+// `is_w`=1 for writer lock, `is_w`=0 for reader lock.
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateRWLockReleased) \
+ (__FILE__, __LINE__, lock, is_w)
+
+// Apply ANNOTATE_BENIGN_RACE_SIZED to a static variable `static_var`.
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) \
+ namespace { \
+ class static_var##_annotator { \
+ public: \
+ static_var##_annotator() { \
+ ANNOTATE_BENIGN_RACE_SIZED(&static_var, sizeof(static_var), \
+ #static_var ": " description); \
+ } \
+ }; \
+ static static_var##_annotator the##static_var##_annotator; \
+ } // namespace
+
+#else // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED == 0
+
+#define ANNOTATE_RWLOCK_CREATE(lock) // empty
+#define ANNOTATE_RWLOCK_CREATE_STATIC(lock) // empty
+#define ANNOTATE_RWLOCK_DESTROY(lock) // empty
+#define ANNOTATE_RWLOCK_ACQUIRED(lock, is_w) // empty
+#define ANNOTATE_RWLOCK_RELEASED(lock, is_w) // empty
+#define ANNOTATE_BENIGN_RACE(address, description) // empty
+#define ANNOTATE_BENIGN_RACE_SIZED(address, size, description) // empty
+#define ANNOTATE_THREAD_NAME(name) // empty
+#define ANNOTATE_ENABLE_RACE_DETECTION(enable) // empty
+#define ANNOTATE_BENIGN_RACE_STATIC(static_var, description) // empty
+
+#endif // ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define memory annotations.
+
+#if ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 1
+
+#include <sanitizer/msan_interface.h>
+
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ __msan_unpoison(address, size)
+
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ __msan_allocated_memory(address, size)
+
+#else // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED == 0
+
+#if DYNAMIC_ANNOTATIONS_ENABLED == 1
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ do { \
+ (void)(address); \
+ (void)(size); \
+ } while (0)
+#else
+#define ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
+#define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
+#endif
+
+#endif // ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END attributes.
+
+#if defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE \
+ __attribute((exclusive_lock_function("*")))
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE \
+ __attribute((unlock_function("*")))
+
+#else // !defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+#define ABSL_INTERNAL_IGNORE_READS_BEGIN_ATTRIBUTE // empty
+#define ABSL_INTERNAL_IGNORE_READS_END_ATTRIBUTE // empty
+
+#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
+
+// -------------------------------------------------------------------------
+// Define IGNORE_READS_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED == 1
+
+// Request the analysis tool to ignore all reads in the current thread until
+// ANNOTATE_IGNORE_READS_END is called. Useful to ignore intentional racey
+// reads, while still checking other reads and all writes.
+// See also ANNOTATE_UNPROTECTED_READ.
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsBegin)(__FILE__, __LINE__)
+
+// Stop ignoring reads.
+#define ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd)(__FILE__, __LINE__)
+
+#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+
+// When Annotalysis is enabled without Dynamic Annotations, the use of
+// static-inline functions allows the annotations to be read at compile-time,
+// while still letting the compiler elide the functions from the final build.
+//
+// TODO(delesley) -- The exclusive lock here ignores writes as well, but
+// allows IGNORE_READS_AND_WRITES to work properly.
+
+#define ANNOTATE_IGNORE_READS_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsBegin)()
+
+#define ANNOTATE_IGNORE_READS_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AbslInternalAnnotateIgnoreReadsEnd)()
+
+#else
+
+#define ANNOTATE_IGNORE_READS_BEGIN() // empty
+#define ANNOTATE_IGNORE_READS_END() // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define IGNORE_WRITES_BEGIN/_END annotations.
+
+#if ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED == 1
+
+// Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead.
+#define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesBegin)(__FILE__, __LINE__)
+
+// Stop ignoring writes.
+#define ANNOTATE_IGNORE_WRITES_END() \
+ ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreWritesEnd)(__FILE__, __LINE__)
+
+#else
+
+#define ANNOTATE_IGNORE_WRITES_BEGIN() // empty
+#define ANNOTATE_IGNORE_WRITES_END() // empty
+
+#endif
+
+// -------------------------------------------------------------------------
+// Define the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+// primitive annotations defined above.
+//
+// Instead of doing
+// ANNOTATE_IGNORE_READS_BEGIN();
+// ... = x;
+// ANNOTATE_IGNORE_READS_END();
+// one can use
+// ... = ANNOTATE_UNPROTECTED_READ(x);
+
+#if defined(ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED)
+
+// Start ignoring all memory accesses (both reads and writes).
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() \
+ do { \
+ ANNOTATE_IGNORE_READS_BEGIN(); \
+ ANNOTATE_IGNORE_WRITES_BEGIN(); \
+ } while (0)
+
+// Stop ignoring both reads and writes.
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ } while (0)
+
+#ifdef __cplusplus
+// ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+#define ANNOTATE_UNPROTECTED_READ(x) \
+ absl::base_internal::AnnotateUnprotectedRead(x)
+
+#endif
+
+#else
+
+#define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() // empty
+#define ANNOTATE_IGNORE_READS_AND_WRITES_END() // empty
+#define ANNOTATE_UNPROTECTED_READ(x) (x)
+
+#endif
+
+// -------------------------------------------------------------------------
+// Address sanitizer annotations
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+// Describe the current state of a contiguous container such as e.g.
+// std::vector or std::string. For more details see
+// sanitizer/common_interface_defs.h, which is provided by the compiler.
+#include <sanitizer/common_interface_defs.h>
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+ __sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name) \
+ struct { \
+ char x[8] __attribute__((aligned(8))); \
+ } name
+
+#else
+
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid)
+#define ADDRESS_SANITIZER_REDZONE(name) static_assert(true, "")
+
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
+
+// -------------------------------------------------------------------------
+// Undefine the macros intended only for this file.
+
+#undef ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_MEMORY_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#undef ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED
+#undef ABSL_INTERNAL_BEGIN_EXTERN_C
+#undef ABSL_INTERNAL_END_EXTERN_C
+#undef ABSL_INTERNAL_STATIC_INLINE
+
+#endif // ABSL_BASE_INTERNAL_DYNAMIC_ANNOTATIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian.h
index d5dc51adb56..dad0e9aeb0d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,9 +19,6 @@
// The following guarantees declaration of the byte swap functions
#ifdef _MSC_VER
#include <stdlib.h> // NOLINT(build/include)
-#elif defined(__APPLE__)
-// Mac OS X / Darwin features
-#include <libkern/OSByteOrder.h>
#elif defined(__FreeBSD__)
#include <sys/endian.h>
#elif defined(__GLIBC__)
@@ -29,11 +26,13 @@
#endif
#include <cstdint>
+#include "absl/base/casts.h"
#include "absl/base/config.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Use compiler byte-swapping intrinsics if they are available. 32-bit
// and 64-bit versions are available in Clang and GCC as of GCC 4.3.0.
@@ -63,11 +62,6 @@ inline uint16_t gbswap_16(uint16_t host_int) {
return _byteswap_ushort(host_int);
}
-#elif defined(__APPLE__)
-inline uint64_t gbswap_64(uint64_t host_int) { return OSSwapInt16(host_int); }
-inline uint32_t gbswap_32(uint32_t host_int) { return OSSwapInt32(host_int); }
-inline uint16_t gbswap_16(uint16_t host_int) { return OSSwapInt64(host_int); }
-
#else
inline uint64_t gbswap_64(uint64_t host_int) {
#if defined(__GNUC__) && defined(__x86_64__) && !defined(__APPLE__)
@@ -75,7 +69,7 @@ inline uint64_t gbswap_64(uint64_t host_int) {
if (__builtin_constant_p(host_int)) {
return __bswap_constant_64(host_int);
} else {
- register uint64_t result;
+ uint64_t result;
__asm__("bswap %0" : "=r"(result) : "0"(host_int));
return result;
}
@@ -113,7 +107,7 @@ inline uint16_t gbswap_16(uint16_t host_int) {
#endif
}
-#endif // intrinics available
+#endif // intrinsics available
#ifdef ABSL_IS_LITTLE_ENDIAN
@@ -180,6 +174,36 @@ inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
+inline uint8_t FromHost(uint8_t x) { return x; }
+inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
+inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
+inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
+inline uint8_t ToHost(uint8_t x) { return x; }
+inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
+inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
+inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
+
+inline int8_t FromHost(int8_t x) { return x; }
+inline int16_t FromHost(int16_t x) {
+ return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t FromHost(int32_t x) {
+ return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t FromHost(int64_t x) {
+ return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
+}
+inline int8_t ToHost(int8_t x) { return x; }
+inline int16_t ToHost(int16_t x) {
+ return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t ToHost(int32_t x) {
+ return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t ToHost(int64_t x) {
+ return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
+}
+
// Functions to do unaligned loads and stores in little-endian order.
inline uint16_t Load16(const void *p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
@@ -240,6 +264,36 @@ inline constexpr bool IsLittleEndian() { return false; }
#endif /* ENDIAN */
+inline uint8_t FromHost(uint8_t x) { return x; }
+inline uint16_t FromHost(uint16_t x) { return FromHost16(x); }
+inline uint32_t FromHost(uint32_t x) { return FromHost32(x); }
+inline uint64_t FromHost(uint64_t x) { return FromHost64(x); }
+inline uint8_t ToHost(uint8_t x) { return x; }
+inline uint16_t ToHost(uint16_t x) { return ToHost16(x); }
+inline uint32_t ToHost(uint32_t x) { return ToHost32(x); }
+inline uint64_t ToHost(uint64_t x) { return ToHost64(x); }
+
+inline int8_t FromHost(int8_t x) { return x; }
+inline int16_t FromHost(int16_t x) {
+ return bit_cast<int16_t>(FromHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t FromHost(int32_t x) {
+ return bit_cast<int32_t>(FromHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t FromHost(int64_t x) {
+ return bit_cast<int64_t>(FromHost64(bit_cast<uint64_t>(x)));
+}
+inline int8_t ToHost(int8_t x) { return x; }
+inline int16_t ToHost(int16_t x) {
+ return bit_cast<int16_t>(ToHost16(bit_cast<uint16_t>(x)));
+}
+inline int32_t ToHost(int32_t x) {
+ return bit_cast<int32_t>(ToHost32(bit_cast<uint32_t>(x)));
+}
+inline int64_t ToHost(int64_t x) {
+ return bit_cast<int64_t>(ToHost64(bit_cast<uint64_t>(x)));
+}
+
// Functions to do unaligned loads and stores in big-endian order.
inline uint16_t Load16(const void *p) {
return ToHost16(ABSL_INTERNAL_UNALIGNED_LOAD16(p));
@@ -267,6 +321,7 @@ inline void Store64(void *p, uint64_t v) {
} // namespace big_endian
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_ENDIAN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian_test.cc
index e27691553bc..a1691b1f82c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/endian_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +24,7 @@
#include "absl/base/config.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
const uint64_t kInitialNumber{0x0123456789abcdef};
@@ -53,24 +54,22 @@ const uint32_t k32ValueBE{0x67452301};
const uint16_t k16ValueBE{0x2301};
#endif
-template<typename T>
-std::vector<T> GenerateAllValuesForType() {
- std::vector<T> result;
- T next = std::numeric_limits<T>::min();
- while (true) {
- result.push_back(next);
- if (next == std::numeric_limits<T>::max()) {
- return result;
- }
- ++next;
+std::vector<uint16_t> GenerateAllUint16Values() {
+ std::vector<uint16_t> result;
+ result.reserve(size_t{1} << (sizeof(uint16_t) * 8));
+ for (uint32_t i = std::numeric_limits<uint16_t>::min();
+ i <= std::numeric_limits<uint16_t>::max(); ++i) {
+ result.push_back(static_cast<uint16_t>(i));
}
+ return result;
}
template<typename T>
-std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
+std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {
std::vector<T> result;
+ result.reserve(num_values_to_test);
std::mt19937_64 rng(kRandomSeed);
- for (size_t i = 0; i < numValuesToTest; ++i) {
+ for (size_t i = 0; i < num_values_to_test; ++i) {
result.push_back(rng());
}
return result;
@@ -147,7 +146,7 @@ void Swap64(char* bytes) {
}
TEST(EndianessTest, Uint16) {
- GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
+ GBSwapHelper(GenerateAllUint16Values(), &Swap16);
}
TEST(EndianessTest, Uint32) {
@@ -260,4 +259,5 @@ TEST(EndianessTest, big_endian) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver.h
new file mode 100644
index 00000000000..251de510fc9
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver.h
@@ -0,0 +1,43 @@
+// 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_ERRNO_SAVER_H_
+#define ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
+
+#include <cerrno>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// `ErrnoSaver` captures the value of `errno` upon construction and restores it
+// upon deletion. It is used in low-level code and must be super fast. Do not
+// add instrumentation, even in debug modes.
+class ErrnoSaver {
+ public:
+ ErrnoSaver() : saved_errno_(errno) {}
+ ~ErrnoSaver() { errno = saved_errno_; }
+ int operator()() const { return saved_errno_; }
+
+ private:
+ const int saved_errno_;
+};
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_ERRNO_SAVER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver_test.cc
new file mode 100644
index 00000000000..e9b742c588b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/errno_saver_test.cc
@@ -0,0 +1,45 @@
+// 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.
+
+#include "absl/base/internal/errno_saver.h"
+
+#include <cerrno>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/strerror.h"
+
+namespace {
+using ::testing::Eq;
+
+struct ErrnoPrinter {
+ int no;
+};
+std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {
+ return os << absl::base_internal::StrError(ep.no) << " [" << ep.no << "]";
+}
+bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }
+
+TEST(ErrnoSaverTest, Works) {
+ errno = EDOM;
+ {
+ absl::base_internal::ErrnoSaver errno_saver;
+ EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
+ errno = ERANGE;
+ EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{ERANGE}));
+ EXPECT_THAT(ErrnoPrinter{errno_saver()}, Eq(ErrnoPrinter{EDOM}));
+ }
+ EXPECT_THAT(ErrnoPrinter{errno}, Eq(ErrnoPrinter{EDOM}));
+}
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.cc
index 8207b7d7b9a..6ccac41864b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,8 @@
#include "absl/base/internal/exception_safety_testing.h"
+#ifdef ABSL_HAVE_EXCEPTIONS
+
#include "gtest/gtest.h"
#include "absl/meta/type_traits.h"
@@ -73,3 +75,5 @@ std::string GetSpecString(AllocSpec spec) {
} // namespace exceptions_internal
} // namespace testing
+
+#endif // ABSL_HAVE_EXCEPTIONS
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.h
index d4d41a8a73a..6ba89d05dfc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_safety_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,10 @@
#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>
@@ -27,7 +31,6 @@
#include <unordered_map>
#include "gtest/gtest.h"
-#include "absl/base/config.h"
#include "absl/base/internal/pretty_function.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
@@ -169,8 +172,10 @@ class ConstructorTracker {
return current_tracker_instance_ != nullptr;
}
- static std::string ErrorMessage(void* address, const std::string& address_description,
- int countdown, const std::string& error_description) {
+ 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"
@@ -556,8 +561,8 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
// We provide both regular and templated operator delete because if only the
// templated version is provided as we did with operator new, the compiler has
// no way of knowing which overload of operator delete to call. See
- // http://en.cppreference.com/w/cpp/memory/new/operator_delete and
- // http://en.cppreference.com/w/cpp/language/delete for the gory details.
+ // https://en.cppreference.com/w/cpp/memory/new/operator_delete and
+ // https://en.cppreference.com/w/cpp/language/delete for the gory details.
void operator delete(void* p) noexcept { ::operator delete(p); }
template <typename... Args>
@@ -1091,4 +1096,6 @@ class ExceptionSafetyTestBuilder {
} // namespace testing
+#endif // ABSL_HAVE_EXCEPTIONS
+
#endif // ABSL_BASE_INTERNAL_EXCEPTION_SAFETY_TESTING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_testing.h
index 0cf7918e4c6..01b54655711 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exception_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.cc
new file mode 100644
index 00000000000..1b30c061e3b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.cc
@@ -0,0 +1,93 @@
+// 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.
+
+#include "absl/base/internal/exponential_biased.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <atomic>
+#include <cmath>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// The algorithm generates a random number between 0 and 1 and applies the
+// inverse cumulative distribution function for an exponential. Specifically:
+// Let m be the inverse of the sample period, then the probability
+// distribution function is m*exp(-mx) so the CDF is
+// p = 1 - exp(-mx), so
+// q = 1 - p = exp(-mx)
+// log_e(q) = -mx
+// -log_e(q)/m = x
+// log_2(q) * (-log_e(2) * 1/m) = x
+// In the code, q is actually in the range 1 to 2**26, hence the -26 below
+int64_t ExponentialBiased::GetSkipCount(int64_t mean) {
+ if (ABSL_PREDICT_FALSE(!initialized_)) {
+ Initialize();
+ }
+
+ uint64_t rng = NextRandom(rng_);
+ rng_ = rng;
+
+ // Take the top 26 bits as the random number
+ // (This plus the 1<<58 sampling bound give a max possible step of
+ // 5194297183973780480 bytes.)
+ // The uint32_t cast is to prevent a (hard-to-reproduce) NAN
+ // under piii debug for some binaries.
+ double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0;
+ // Put the computed p-value through the CDF of a geometric.
+ double interval = bias_ + (std::log2(q) - 26) * (-std::log(2.0) * mean);
+ // Very large values of interval overflow int64_t. To avoid that, we will
+ // cheat and clamp any huge values to (int64_t max)/2. This is a potential
+ // source of bias, but the mean would need to be such a large value that it's
+ // not likely to come up. For example, with a mean of 1e18, the probability of
+ // hitting this condition is about 1/1000. For a mean of 1e17, standard
+ // calculators claim that this event won't happen.
+ if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) {
+ // Assume huge values are bias neutral, retain bias for next call.
+ return std::numeric_limits<int64_t>::max() / 2;
+ }
+ double value = std::round(interval);
+ bias_ = interval - value;
+ return value;
+}
+
+int64_t ExponentialBiased::GetStride(int64_t mean) {
+ return GetSkipCount(mean - 1) + 1;
+}
+
+void ExponentialBiased::Initialize() {
+ // We don't get well distributed numbers from `this` so we call NextRandom() a
+ // bunch to mush the bits around. We use a global_rand to handle the case
+ // where the same thread (by memory address) gets created and destroyed
+ // repeatedly.
+ ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0);
+ uint64_t r = reinterpret_cast<uint64_t>(this) +
+ global_rand.fetch_add(1, std::memory_order_relaxed);
+ for (int i = 0; i < 20; ++i) {
+ r = NextRandom(r);
+ }
+ rng_ = r;
+ initialized_ = true;
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.h
new file mode 100644
index 00000000000..94f79a3378d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased.h
@@ -0,0 +1,130 @@
+// 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_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
+#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
+
+#include <stdint.h>
+
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// ExponentialBiased provides a small and fast random number generator for a
+// rounded exponential distribution. This generator manages very little state,
+// and imposes no synchronization overhead. This makes it useful in specialized
+// scenarios requiring minimum overhead, such as stride based periodic sampling.
+//
+// ExponentialBiased provides two closely related functions, GetSkipCount() and
+// GetStride(), both returning a rounded integer defining a number of events
+// required before some event with a given mean probability occurs.
+//
+// The distribution is useful to generate a random wait time or some periodic
+// event with a given mean probability. For example, if an action is supposed to
+// happen on average once every 'N' events, then we can get a random 'stride'
+// counting down how long before the event to happen. For example, if we'd want
+// to sample one in every 1000 'Frobber' calls, our code could look like this:
+//
+// Frobber::Frobber() {
+// stride_ = exponential_biased_.GetStride(1000);
+// }
+//
+// void Frobber::Frob(int arg) {
+// if (--stride == 0) {
+// SampleFrob(arg);
+// stride_ = exponential_biased_.GetStride(1000);
+// }
+// ...
+// }
+//
+// The rounding of the return value creates a bias, especially for smaller means
+// where the distribution of the fraction is not evenly distributed. We correct
+// this bias by tracking the fraction we rounded up or down on each iteration,
+// effectively tracking the distance between the cumulative value, and the
+// rounded cumulative value. For example, given a mean of 2:
+//
+// raw = 1.63076, cumulative = 1.63076, rounded = 2, bias = -0.36923
+// raw = 0.14624, cumulative = 1.77701, rounded = 2, bias = 0.14624
+// raw = 4.93194, cumulative = 6.70895, rounded = 7, bias = -0.06805
+// raw = 0.24206, cumulative = 6.95101, rounded = 7, bias = 0.24206
+// etc...
+//
+// Adjusting with rounding bias is relatively trivial:
+//
+// double value = bias_ + exponential_distribution(mean)();
+// double rounded_value = std::round(value);
+// bias_ = value - rounded_value;
+// return rounded_value;
+//
+// This class is thread-compatible.
+class ExponentialBiased {
+ public:
+ // The number of bits set by NextRandom.
+ static constexpr int kPrngNumBits = 48;
+
+ // `GetSkipCount()` returns the number of events to skip before some chosen
+ // event happens. For example, randomly tossing a coin, we will on average
+ // throw heads once before we get tails. We can simulate random coin tosses
+ // using GetSkipCount() as:
+ //
+ // ExponentialBiased eb;
+ // for (...) {
+ // int number_of_heads_before_tail = eb.GetSkipCount(1);
+ // for (int flips = 0; flips < number_of_heads_before_tail; ++flips) {
+ // printf("head...");
+ // }
+ // printf("tail\n");
+ // }
+ //
+ int64_t GetSkipCount(int64_t mean);
+
+ // GetStride() returns the number of events required for a specific event to
+ // happen. See the class comments for a usage example. `GetStride()` is
+ // equivalent to `GetSkipCount(mean - 1) + 1`. When to use `GetStride()` or
+ // `GetSkipCount()` depends mostly on what best fits the use case.
+ int64_t GetStride(int64_t mean);
+
+ // Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1]
+ //
+ // This is public to enable testing.
+ static uint64_t NextRandom(uint64_t rnd);
+
+ private:
+ void Initialize();
+
+ uint64_t rng_{0};
+ double bias_{0};
+ bool initialized_{false};
+};
+
+// Returns the next prng value.
+// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48
+// This is the lrand64 generator.
+inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) {
+ const uint64_t prng_mult = uint64_t{0x5DEECE66D};
+ const uint64_t prng_add = 0xB;
+ const uint64_t prng_mod_power = 48;
+ const uint64_t prng_mod_mask =
+ ~((~static_cast<uint64_t>(0)) << prng_mod_power);
+ return (prng_mult * rnd + prng_add) & prng_mod_mask;
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased_test.cc
new file mode 100644
index 00000000000..075583ca6fd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/exponential_biased_test.cc
@@ -0,0 +1,199 @@
+// 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.
+
+#include "absl/base/internal/exponential_biased.h"
+
+#include <stddef.h>
+
+#include <cmath>
+#include <cstdint>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
+
+using ::testing::Ge;
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+MATCHER_P2(IsBetween, a, b,
+ absl::StrCat(std::string(negation ? "isn't" : "is"), " between ", a,
+ " and ", b)) {
+ return a <= arg && arg <= b;
+}
+
+// Tests of the quality of the random numbers generated
+// This uses the Anderson Darling test for uniformity.
+// See "Evaluating the Anderson-Darling Distribution" by Marsaglia
+// for details.
+
+// Short cut version of ADinf(z), z>0 (from Marsaglia)
+// This returns the p-value for Anderson Darling statistic in
+// the limit as n-> infinity. For finite n, apply the error fix below.
+double AndersonDarlingInf(double z) {
+ if (z < 2) {
+ return exp(-1.2337141 / z) / sqrt(z) *
+ (2.00012 +
+ (0.247105 -
+ (0.0649821 - (0.0347962 - (0.011672 - 0.00168691 * z) * z) * z) *
+ z) *
+ z);
+ }
+ return exp(
+ -exp(1.0776 -
+ (2.30695 -
+ (0.43424 - (0.082433 - (0.008056 - 0.0003146 * z) * z) * z) * z) *
+ z));
+}
+
+// Corrects the approximation error in AndersonDarlingInf for small values of n
+// Add this to AndersonDarlingInf to get a better approximation
+// (from Marsaglia)
+double AndersonDarlingErrFix(int n, double x) {
+ if (x > 0.8) {
+ return (-130.2137 +
+ (745.2337 -
+ (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) *
+ x) /
+ n;
+ }
+ double cutoff = 0.01265 + 0.1757 / n;
+ if (x < cutoff) {
+ double t = x / cutoff;
+ t = sqrt(t) * (1 - t) * (49 * t - 102);
+ return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n;
+ } else {
+ double t = (x - cutoff) / (0.8 - cutoff);
+ t = -0.00022633 +
+ (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * t) * t) * t) * t) *
+ t;
+ return t * (0.04213 + 0.01365 / n) / n;
+ }
+}
+
+// Returns the AndersonDarling p-value given n and the value of the statistic
+double AndersonDarlingPValue(int n, double z) {
+ double ad = AndersonDarlingInf(z);
+ double errfix = AndersonDarlingErrFix(n, ad);
+ return ad + errfix;
+}
+
+double AndersonDarlingStatistic(const std::vector<double>& random_sample) {
+ int n = random_sample.size();
+ double ad_sum = 0;
+ for (int i = 0; i < n; i++) {
+ ad_sum += (2 * i + 1) *
+ std::log(random_sample[i] * (1 - random_sample[n - 1 - i]));
+ }
+ double ad_statistic = -n - 1 / static_cast<double>(n) * ad_sum;
+ return ad_statistic;
+}
+
+// Tests if the array of doubles is uniformly distributed.
+// Returns the p-value of the Anderson Darling Statistic
+// for the given set of sorted random doubles
+// See "Evaluating the Anderson-Darling Distribution" by
+// Marsaglia and Marsaglia for details.
+double AndersonDarlingTest(const std::vector<double>& random_sample) {
+ double ad_statistic = AndersonDarlingStatistic(random_sample);
+ double p = AndersonDarlingPValue(random_sample.size(), ad_statistic);
+ return p;
+}
+
+TEST(ExponentialBiasedTest, CoinTossDemoWithGetSkipCount) {
+ ExponentialBiased eb;
+ for (int runs = 0; runs < 10; ++runs) {
+ for (int flips = eb.GetSkipCount(1); flips > 0; --flips) {
+ printf("head...");
+ }
+ printf("tail\n");
+ }
+ int heads = 0;
+ for (int i = 0; i < 10000000; i += 1 + eb.GetSkipCount(1)) {
+ ++heads;
+ }
+ printf("Heads = %d (%f%%)\n", heads, 100.0 * heads / 10000000);
+}
+
+TEST(ExponentialBiasedTest, SampleDemoWithStride) {
+ ExponentialBiased eb;
+ int stride = eb.GetStride(10);
+ int samples = 0;
+ for (int i = 0; i < 10000000; ++i) {
+ if (--stride == 0) {
+ ++samples;
+ stride = eb.GetStride(10);
+ }
+ }
+ printf("Samples = %d (%f%%)\n", samples, 100.0 * samples / 10000000);
+}
+
+
+// Testing that NextRandom generates uniform random numbers. Applies the
+// Anderson-Darling test for uniformity
+TEST(ExponentialBiasedTest, TestNextRandom) {
+ for (auto n : std::vector<int>({
+ 10, // Check short-range correlation
+ 100, 1000,
+ 10000 // Make sure there's no systemic error
+ })) {
+ uint64_t x = 1;
+ // This assumes that the prng returns 48 bit numbers
+ uint64_t max_prng_value = static_cast<uint64_t>(1) << 48;
+ // Initialize.
+ for (int i = 1; i <= 20; i++) {
+ x = ExponentialBiased::NextRandom(x);
+ }
+ std::vector<uint64_t> int_random_sample(n);
+ // Collect samples
+ for (int i = 0; i < n; i++) {
+ int_random_sample[i] = x;
+ x = ExponentialBiased::NextRandom(x);
+ }
+ // First sort them...
+ std::sort(int_random_sample.begin(), int_random_sample.end());
+ std::vector<double> random_sample(n);
+ // Convert them to uniform randoms (in the range [0,1])
+ for (int i = 0; i < n; i++) {
+ random_sample[i] =
+ static_cast<double>(int_random_sample[i]) / max_prng_value;
+ }
+ // Now compute the Anderson-Darling statistic
+ double ad_pvalue = AndersonDarlingTest(random_sample);
+ EXPECT_GT(std::min(ad_pvalue, 1 - ad_pvalue), 0.0001)
+ << "prng is not uniform: n = " << n << " p = " << ad_pvalue;
+ }
+}
+
+// The generator needs to be available as a thread_local and as a static
+// variable.
+TEST(ExponentialBiasedTest, InitializationModes) {
+ ABSL_CONST_INIT static ExponentialBiased eb_static;
+ EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
+
+#ifdef ABSL_HAVE_THREAD_LOCAL
+ thread_local ExponentialBiased eb_thread;
+ EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
+#endif
+
+ ExponentialBiased eb_stack;
+ EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0));
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id.h
new file mode 100644
index 00000000000..3db59e83745
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id.h
@@ -0,0 +1,48 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+#define ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+template <typename Type>
+struct FastTypeTag {
+ constexpr static char dummy_var = 0;
+};
+
+template <typename Type>
+constexpr char FastTypeTag<Type>::dummy_var;
+
+// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
+// passed-in type. These are meant to be good match for keys into maps or
+// straight up comparisons.
+using FastTypeIdType = const void*;
+
+template <typename Type>
+constexpr inline FastTypeIdType FastTypeId() {
+ return &FastTypeTag<Type>::dummy_var;
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_FAST_TYPE_ID_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id_test.cc
new file mode 100644
index 00000000000..16f3c1458bd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/fast_type_id_test.cc
@@ -0,0 +1,123 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/fast_type_id.h"
+
+#include <cstdint>
+#include <map>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace {
+namespace bi = absl::base_internal;
+
+// NOLINTNEXTLINE
+#define PRIM_TYPES(A) \
+ A(bool) \
+ A(short) \
+ A(unsigned short) \
+ A(int) \
+ A(unsigned int) \
+ A(long) \
+ A(unsigned long) \
+ A(long long) \
+ A(unsigned long long) \
+ A(float) \
+ A(double) \
+ A(long double)
+
+TEST(FastTypeIdTest, PrimitiveTypes) {
+ bi::FastTypeIdType type_ids[] = {
+#define A(T) bi::FastTypeId<T>(),
+ PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const T>(),
+ PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<volatile T>(),
+ PRIM_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const volatile T>(),
+ PRIM_TYPES(A)
+#undef A
+ };
+ size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
+
+ for (int i = 0; i < total_type_ids; ++i) {
+ EXPECT_EQ(type_ids[i], type_ids[i]);
+ for (int j = 0; j < i; ++j) {
+ EXPECT_NE(type_ids[i], type_ids[j]);
+ }
+ }
+}
+
+#define FIXED_WIDTH_TYPES(A) \
+ A(int8_t) \
+ A(uint8_t) \
+ A(int16_t) \
+ A(uint16_t) \
+ A(int32_t) \
+ A(uint32_t) \
+ A(int64_t) \
+ A(uint64_t)
+
+TEST(FastTypeIdTest, FixedWidthTypes) {
+ bi::FastTypeIdType type_ids[] = {
+#define A(T) bi::FastTypeId<T>(),
+ FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const T>(),
+ FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<volatile T>(),
+ FIXED_WIDTH_TYPES(A)
+#undef A
+#define A(T) bi::FastTypeId<const volatile T>(),
+ FIXED_WIDTH_TYPES(A)
+#undef A
+ };
+ size_t total_type_ids = sizeof(type_ids) / sizeof(bi::FastTypeIdType);
+
+ for (int i = 0; i < total_type_ids; ++i) {
+ EXPECT_EQ(type_ids[i], type_ids[i]);
+ for (int j = 0; j < i; ++j) {
+ EXPECT_NE(type_ids[i], type_ids[j]);
+ }
+ }
+}
+
+TEST(FastTypeIdTest, AliasTypes) {
+ using int_alias = int;
+ EXPECT_EQ(bi::FastTypeId<int_alias>(), bi::FastTypeId<int>());
+}
+
+TEST(FastTypeIdTest, TemplateSpecializations) {
+ EXPECT_NE(bi::FastTypeId<std::vector<int>>(),
+ bi::FastTypeId<std::vector<long>>());
+
+ EXPECT_NE((bi::FastTypeId<std::map<int, float>>()),
+ (bi::FastTypeId<std::map<int, double>>()));
+}
+
+struct Base {};
+struct Derived : Base {};
+struct PDerived : private Base {};
+
+TEST(FastTypeIdTest, Inheritance) {
+ EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<Derived>());
+ EXPECT_NE(bi::FastTypeId<Base>(), bi::FastTypeId<PDerived>());
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/hide_ptr.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/hide_ptr.h
index 45cf438912c..1dba80909a9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/hide_ptr.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/hide_ptr.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,7 +17,10 @@
#include <cstdint>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Arbitrary value with high bits set. Xor'ing with it is unlikely
@@ -42,6 +45,7 @@ inline T* UnhidePtr(uintptr_t hidden) {
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_HIDE_PTR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/identity.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/identity.h
index a1a5d70a84d..a3154ed7bc5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/identity.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/identity.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,7 +16,10 @@
#ifndef ABSL_BASE_INTERNAL_IDENTITY_H_
#define ABSL_BASE_INTERNAL_IDENTITY_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace internal {
template <typename T>
@@ -28,6 +31,7 @@ template <typename T>
using identity_t = typename identity<T>::type;
} // namespace internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_IDENTITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable.h
index f7bb8c56525..130d8c2476d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable_testing.h
index a0dd2bb28a4..3856b9f80f2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/inline_variable_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#include "absl/base/internal/inline_variable.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace inline_variable_testing_internal {
struct Foo {
@@ -39,6 +40,7 @@ const int& get_int_a();
const int& get_int_b();
} // namespace inline_variable_testing_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INLINE_VARIABLE_TESTING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/invoke.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/invoke.h
index 8c3f4f60637..5c71f328234 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/invoke.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/invoke.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-// absl::base_internal::Invoke(f, args...) is an implementation of
+// absl::base_internal::invoke(f, args...) is an implementation of
// INVOKE(f, args...) from section [func.require] of the C++ standard.
//
// [func.require]
@@ -29,7 +29,7 @@
// is not one of the types described in the previous item;
// 5. f(t1, t2, ..., tN) in all other cases.
//
-// The implementation is SFINAE-friendly: substitution failure within Invoke()
+// The implementation is SFINAE-friendly: substitution failure within invoke()
// isn't an error.
#ifndef ABSL_BASE_INTERNAL_INVOKE_H_
@@ -39,10 +39,13 @@
#include <type_traits>
#include <utility>
+#include "absl/meta/type_traits.h"
+
// The following code is internal implementation detail. See the comment at the
// top of this file for the API documentation.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// The five classes below each implement one of the clauses from the definition
@@ -67,15 +70,11 @@ struct MemFunAndRef : StrippedAccept<MemFunAndRef> {
template <typename... Args>
struct AcceptImpl : std::false_type {};
- template <typename R, typename C, typename... Params, typename Obj,
- typename... Args>
- struct AcceptImpl<R (C::*)(Params...), Obj, Args...>
- : std::is_base_of<C, Obj> {};
-
- template <typename R, typename C, typename... Params, typename Obj,
- typename... Args>
- struct AcceptImpl<R (C::*)(Params...) const, Obj, Args...>
- : std::is_base_of<C, Obj> {};
+ template <typename MemFunType, typename C, typename Obj, typename... Args>
+ struct AcceptImpl<MemFunType C::*, Obj, Args...>
+ : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
+ absl::is_function<MemFunType>::value> {
+ };
template <typename MemFun, typename Obj, typename... Args>
static decltype((std::declval<Obj>().*
@@ -92,15 +91,11 @@ struct MemFunAndPtr : StrippedAccept<MemFunAndPtr> {
template <typename... Args>
struct AcceptImpl : std::false_type {};
- template <typename R, typename C, typename... Params, typename Ptr,
- typename... Args>
- struct AcceptImpl<R (C::*)(Params...), Ptr, Args...>
- : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
-
- template <typename R, typename C, typename... Params, typename Ptr,
- typename... Args>
- struct AcceptImpl<R (C::*)(Params...) const, Ptr, Args...>
- : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
+ template <typename MemFunType, typename C, typename Ptr, typename... Args>
+ struct AcceptImpl<MemFunType C::*, Ptr, Args...>
+ : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
+ absl::is_function<MemFunType>::value> {
+ };
template <typename MemFun, typename Ptr, typename... Args>
static decltype(((*std::declval<Ptr>()).*
@@ -119,7 +114,9 @@ struct DataMemAndRef : StrippedAccept<DataMemAndRef> {
struct AcceptImpl : std::false_type {};
template <typename R, typename C, typename Obj>
- struct AcceptImpl<R C::*, Obj> : std::is_base_of<C, Obj> {};
+ struct AcceptImpl<R C::*, Obj>
+ : std::integral_constant<bool, std::is_base_of<C, Obj>::value &&
+ !absl::is_function<R>::value> {};
template <typename DataMem, typename Ref>
static decltype(std::declval<Ref>().*std::declval<DataMem>()) Invoke(
@@ -136,7 +133,8 @@ struct DataMemAndPtr : StrippedAccept<DataMemAndPtr> {
template <typename R, typename C, typename Ptr>
struct AcceptImpl<R C::*, Ptr>
- : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value> {};
+ : std::integral_constant<bool, !std::is_base_of<C, Ptr>::value &&
+ !absl::is_function<R>::value> {};
template <typename DataMem, typename Ptr>
static decltype((*std::declval<Ptr>()).*std::declval<DataMem>()) Invoke(
@@ -172,17 +170,18 @@ struct Invoker {
// The result type of Invoke<F, Args...>.
template <typename F, typename... Args>
-using InvokeT = decltype(Invoker<F, Args...>::type::Invoke(
+using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
std::declval<F>(), std::declval<Args>()...));
// Invoke(f, args...) is an implementation of INVOKE(f, args...) from section
// [func.require] of the C++ standard.
template <typename F, typename... Args>
-InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
+invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
std::forward<Args>(args)...);
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_INVOKE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.cc
index 4af9c05da0d..229ab9162d1 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -63,6 +63,7 @@
#endif // __APPLE__
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// A first-fit allocator with amortized logarithmic free() time.
@@ -203,32 +204,33 @@ struct LowLevelAlloc::Arena {
base_internal::SpinLock mu;
// Head of free list, sorted by address
- AllocList freelist GUARDED_BY(mu);
+ AllocList freelist ABSL_GUARDED_BY(mu);
// Count of allocated blocks
- int32_t allocation_count GUARDED_BY(mu);
+ int32_t allocation_count ABSL_GUARDED_BY(mu);
// flags passed to NewArena
const uint32_t flags;
// Result of sysconf(_SC_PAGESIZE)
const size_t pagesize;
// Lowest power of two >= max(16, sizeof(AllocList))
- const size_t roundup;
+ const size_t round_up;
// Smallest allocation block size
const size_t min_size;
// PRNG state
- uint32_t random GUARDED_BY(mu);
+ uint32_t random ABSL_GUARDED_BY(mu);
};
namespace {
-using ArenaStorage = std::aligned_storage<sizeof(LowLevelAlloc::Arena),
- alignof(LowLevelAlloc::Arena)>::type;
-
// Static storage space for the lazily-constructed, default global arena
// instances. We require this space because the whole point of LowLevelAlloc
// is to avoid relying on malloc/new.
-ArenaStorage default_arena_storage;
-ArenaStorage unhooked_arena_storage;
+alignas(LowLevelAlloc::Arena) unsigned char default_arena_storage[sizeof(
+ LowLevelAlloc::Arena)];
+alignas(LowLevelAlloc::Arena) unsigned char unhooked_arena_storage[sizeof(
+ LowLevelAlloc::Arena)];
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
-ArenaStorage unhooked_async_sig_safe_arena_storage;
+alignas(
+ LowLevelAlloc::Arena) unsigned char unhooked_async_sig_safe_arena_storage
+ [sizeof(LowLevelAlloc::Arena)];
#endif
// We must use LowLevelCallOnce here to construct the global arenas, rather than
@@ -275,10 +277,10 @@ static const uintptr_t kMagicAllocated = 0x4c833e95U;
static const uintptr_t kMagicUnallocated = ~kMagicAllocated;
namespace {
-class SCOPED_LOCKABLE ArenaLock {
+class ABSL_SCOPED_LOCKABLE ArenaLock {
public:
explicit ArenaLock(LowLevelAlloc::Arena *arena)
- EXCLUSIVE_LOCK_FUNCTION(arena->mu)
+ ABSL_EXCLUSIVE_LOCK_FUNCTION(arena->mu)
: arena_(arena) {
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if ((arena->flags & LowLevelAlloc::kAsyncSignalSafe) != 0) {
@@ -290,11 +292,14 @@ class SCOPED_LOCKABLE ArenaLock {
arena_->mu.Lock();
}
~ArenaLock() { ABSL_RAW_CHECK(left_, "haven't left Arena region"); }
- void Leave() UNLOCK_FUNCTION() {
+ void Leave() ABSL_UNLOCK_FUNCTION() {
arena_->mu.Unlock();
#ifndef ABSL_LOW_LEVEL_ALLOC_ASYNC_SIGNAL_SAFE_MISSING
if (mask_valid_) {
- pthread_sigmask(SIG_SETMASK, &mask_, nullptr);
+ const int err = pthread_sigmask(SIG_SETMASK, &mask_, nullptr);
+ if (err != 0) {
+ ABSL_RAW_LOG(FATAL, "pthread_sigmask failed: %d", err);
+ }
}
#endif
left_ = true;
@@ -333,11 +338,11 @@ size_t GetPageSize() {
size_t RoundedUpBlockSize() {
// Round up block sizes to a power of two close to the header size.
- size_t roundup = 16;
- while (roundup < sizeof(AllocList::Header)) {
- roundup += roundup;
+ size_t round_up = 16;
+ while (round_up < sizeof(AllocList::Header)) {
+ round_up += round_up;
}
- return roundup;
+ return round_up;
}
} // namespace
@@ -347,8 +352,8 @@ LowLevelAlloc::Arena::Arena(uint32_t flags_value)
allocation_count(0),
flags(flags_value),
pagesize(GetPageSize()),
- roundup(RoundedUpBlockSize()),
- min_size(2 * roundup),
+ round_up(RoundedUpBlockSize()),
+ min_size(2 * round_up),
random(0) {
freelist.header.size = 0;
freelist.header.magic =
@@ -444,7 +449,7 @@ static inline uintptr_t RoundUp(uintptr_t addr, uintptr_t align) {
// that the freelist is in the correct order, that it
// consists of regions marked "unallocated", and that no two regions
// are adjacent in memory (they should have been coalesced).
-// L < arena->mu
+// L >= arena->mu
static AllocList *Next(int i, AllocList *prev, LowLevelAlloc::Arena *arena) {
ABSL_RAW_CHECK(i < prev->levels, "too few levels in Next()");
AllocList *next = prev->next[i];
@@ -505,8 +510,6 @@ void LowLevelAlloc::Free(void *v) {
if (v != nullptr) {
AllocList *f = reinterpret_cast<AllocList *>(
reinterpret_cast<char *>(v) - sizeof (f->header));
- ABSL_RAW_CHECK(f->header.magic == Magic(kMagicAllocated, &f->header),
- "bad magic number in Free()");
LowLevelAlloc::Arena *arena = f->header.arena;
ArenaLock section(arena);
AddToFreelist(v, arena);
@@ -525,7 +528,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
ArenaLock section(arena);
// round up with header
size_t req_rnd = RoundUp(CheckedAdd(request, sizeof (s->header)),
- arena->roundup);
+ arena->round_up);
for (;;) { // loop until we find a suitable region
// find the minimum levels that a block of this size must have
int i = LLA_SkiplistLevels(req_rnd, arena->min_size, nullptr) - 1;
@@ -595,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
section.Leave();
result = &s->levels;
}
- ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
+ ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
return result;
}
@@ -611,6 +614,7 @@ void *LowLevelAlloc::AllocWithArena(size_t request, Arena *arena) {
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.h
index fba9466a757..db91951c825 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
// IWYU pragma: private, include "base/low_level_alloc.h"
#include <sys/types.h>
+
#include <cstdint>
#include "absl/base/attributes.h"
@@ -54,6 +55,7 @@
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
class LowLevelAlloc {
@@ -118,5 +120,7 @@ class LowLevelAlloc {
};
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_ALLOC_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
index cf2b363299f..31abb888a6f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,7 +21,14 @@
#include <unordered_map>
#include <utility>
+#ifdef __EMSCRIPTEN__
+#include <emscripten.h>
+#endif
+
+#include "absl/container/node_hash_map.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
@@ -74,7 +81,7 @@ static bool using_low_level_alloc = false;
// allocations and deallocations are reported via the MallocHook
// interface.
static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
- typedef std::unordered_map<int, BlockDesc> AllocMap;
+ typedef absl::node_hash_map<int, BlockDesc> AllocMap;
AllocMap allocated;
AllocMap::iterator it;
BlockDesc block_desc;
@@ -137,6 +144,7 @@ static void Test(bool use_new_arena, bool call_malloc_hook, int n) {
TEST_ASSERT(LowLevelAlloc::DeleteArena(arena));
}
}
+
// LowLevelAlloc is designed to be safe to call before main().
static struct BeforeMain {
BeforeMain() {
@@ -148,10 +156,26 @@ static struct BeforeMain {
} // namespace
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
int main(int argc, char *argv[]) {
// The actual test runs in the global constructor of `before_main`.
printf("PASS\n");
+#ifdef __EMSCRIPTEN__
+ // clang-format off
+// This is JS here. Don't try to format it.
+ MAIN_THREAD_EM_ASM({
+ if (ENVIRONMENT_IS_WEB) {
+ if (typeof TEST_FINISH === 'function') {
+ TEST_FINISH($0);
+ } else {
+ console.error('Attempted to exit with status ' + $0);
+ console.error('But TEST_FINSIHED is not a function.');
+ }
+ }
+ }, 0);
+// clang-format on
+#endif
return 0;
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_scheduling.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_scheduling.h
index e716f2b49fa..9baccc0659b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_scheduling.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/low_level_scheduling.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#ifndef ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
#define ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
+#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/macros.h"
@@ -28,6 +29,14 @@ extern "C" bool __google_disable_rescheduling(void);
extern "C" void __google_enable_rescheduling(bool disable_result);
namespace absl {
+ABSL_NAMESPACE_BEGIN
+class CondVar;
+class Mutex;
+
+namespace synchronization_internal {
+int MutexDelay(int32_t c, int mode);
+} // namespace synchronization_internal
+
namespace base_internal {
class SchedulingHelper; // To allow use of SchedulingGuard.
@@ -52,6 +61,8 @@ class SchedulingGuard {
public:
// Returns true iff the calling thread may be cooperatively rescheduled.
static bool ReschedulingIsAllowed();
+ SchedulingGuard(const SchedulingGuard&) = delete;
+ SchedulingGuard& operator=(const SchedulingGuard&) = delete;
private:
// Disable cooperative rescheduling of the calling thread. It may still
@@ -75,17 +86,29 @@ class SchedulingGuard {
bool disabled;
};
- // Access to SchedulingGuard is explicitly white-listed.
+ // A scoped helper to enable rescheduling temporarily.
+ // REQUIRES: destructor must run in same thread as constructor.
+ class ScopedEnable {
+ public:
+ ScopedEnable();
+ ~ScopedEnable();
+
+ private:
+ int scheduling_disabled_depth_;
+ };
+
+ // Access to SchedulingGuard is explicitly permitted.
+ friend class absl::CondVar;
+ friend class absl::Mutex;
friend class SchedulingHelper;
friend class SpinLock;
-
- SchedulingGuard(const SchedulingGuard&) = delete;
- SchedulingGuard& operator=(const SchedulingGuard&) = delete;
+ friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
};
//------------------------------------------------------------------------------
// End of public interfaces.
//------------------------------------------------------------------------------
+
inline bool SchedulingGuard::ReschedulingIsAllowed() {
return false;
}
@@ -98,7 +121,14 @@ inline void SchedulingGuard::EnableRescheduling(bool /* disable_result */) {
return;
}
+inline SchedulingGuard::ScopedEnable::ScopedEnable()
+ : scheduling_disabled_depth_(0) {}
+inline SchedulingGuard::ScopedEnable::~ScopedEnable() {
+ ABSL_RAW_CHECK(scheduling_disabled_depth_ == 0, "disable unused warning");
+}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_LOW_LEVEL_SCHEDULING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/per_thread_tls.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/per_thread_tls.h
index 2428bdc1238..cf5e97a0470 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/per_thread_tls.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/per_thread_tls.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,13 +16,17 @@
#define ABSL_BASE_INTERNAL_PER_THREAD_TLS_H_
// This header defines two macros:
+//
// If the platform supports thread-local storage:
-// ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
-// thread-local variable ABSL_PER_THREAD_TLS is 1
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is the C keyword needed to declare a
+// thread-local variable
+// * ABSL_PER_THREAD_TLS is 1
//
// Otherwise:
-// ABSL_PER_THREAD_TLS_KEYWORD is empty
-// ABSL_PER_THREAD_TLS is 0
+//
+// * ABSL_PER_THREAD_TLS_KEYWORD is empty
+// * ABSL_PER_THREAD_TLS is 0
//
// Microsoft C supports thread-local storage.
// GCC supports it if the appropriate version of glibc is available,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.cc
new file mode 100644
index 00000000000..520dabbaa00
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.cc
@@ -0,0 +1,53 @@
+// 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.
+
+#include "absl/base/internal/periodic_sampler.h"
+
+#include <atomic>
+
+#include "absl/base/internal/exponential_biased.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept {
+ return rng_.GetStride(period);
+}
+
+bool PeriodicSamplerBase::SubtleConfirmSample() noexcept {
+ int current_period = period();
+
+ // Deal with period case 0 (always off) and 1 (always on)
+ if (ABSL_PREDICT_FALSE(current_period < 2)) {
+ stride_ = 0;
+ return current_period == 1;
+ }
+
+ // Check if this is the first call to Sample()
+ if (ABSL_PREDICT_FALSE(stride_ == 1)) {
+ stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
+ if (static_cast<int64_t>(stride_) < -1) {
+ ++stride_;
+ return false;
+ }
+ }
+
+ stride_ = static_cast<uint64_t>(-GetExponentialBiased(current_period));
+ return true;
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.h
new file mode 100644
index 00000000000..f8a86796b11
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler.h
@@ -0,0 +1,211 @@
+// 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_BASE_INTERNAL_PERIODIC_SAMPLER_H_
+#define ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
+
+#include <stdint.h>
+
+#include <atomic>
+
+#include "absl/base/internal/exponential_biased.h"
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// PeriodicSamplerBase provides the basic period sampler implementation.
+//
+// This is the base class for the templated PeriodicSampler class, which holds
+// a global std::atomic value identified by a user defined tag, such that
+// each specific PeriodSampler implementation holds its own global period.
+//
+// PeriodicSamplerBase is thread-compatible except where stated otherwise.
+class PeriodicSamplerBase {
+ public:
+ // PeriodicSamplerBase is trivial / copyable / movable / destructible.
+ PeriodicSamplerBase() = default;
+ PeriodicSamplerBase(PeriodicSamplerBase&&) = default;
+ PeriodicSamplerBase(const PeriodicSamplerBase&) = default;
+
+ // Returns true roughly once every `period` calls. This is established by a
+ // randomly picked `stride` that is counted down on each call to `Sample`.
+ // This stride is picked such that the probability of `Sample()` returning
+ // true is 1 in `period`.
+ inline bool Sample() noexcept;
+
+ // The below methods are intended for optimized use cases where the
+ // size of the inlined fast path code is highly important. Applications
+ // should use the `Sample()` method unless they have proof that their
+ // specific use case requires the optimizations offered by these methods.
+ //
+ // An example of such a use case is SwissTable sampling. All sampling checks
+ // are in inlined SwissTable methods, and the number of call sites is huge.
+ // In this case, the inlined code size added to each translation unit calling
+ // SwissTable methods is non-trivial.
+ //
+ // The `SubtleMaybeSample()` function spuriously returns true even if the
+ // function should not be sampled, applications MUST match each call to
+ // 'SubtleMaybeSample()' returning true with a `SubtleConfirmSample()` call,
+ // and use the result of the latter as the sampling decision.
+ // In other words: the code should logically be equivalent to:
+ //
+ // if (SubtleMaybeSample() && SubtleConfirmSample()) {
+ // // Sample this call
+ // }
+ //
+ // In the 'inline-size' optimized case, the `SubtleConfirmSample()` call can
+ // be placed out of line, for example, the typical use case looks as follows:
+ //
+ // // --- frobber.h -----------
+ // void FrobberSampled();
+ //
+ // inline void FrobberImpl() {
+ // // ...
+ // }
+ //
+ // inline void Frobber() {
+ // if (ABSL_PREDICT_FALSE(sampler.SubtleMaybeSample())) {
+ // FrobberSampled();
+ // } else {
+ // FrobberImpl();
+ // }
+ // }
+ //
+ // // --- frobber.cc -----------
+ // void FrobberSampled() {
+ // if (!sampler.SubtleConfirmSample())) {
+ // // Spurious false positive
+ // FrobberImpl();
+ // return;
+ // }
+ //
+ // // Sampled execution
+ // // ...
+ // }
+ inline bool SubtleMaybeSample() noexcept;
+ bool SubtleConfirmSample() noexcept;
+
+ protected:
+ // We explicitly don't use a virtual destructor as this class is never
+ // virtually destroyed, and it keeps the class trivial, which avoids TLS
+ // prologue and epilogue code for our TLS instances.
+ ~PeriodicSamplerBase() = default;
+
+ // Returns the next stride for our sampler.
+ // This function is virtual for testing purposes only.
+ virtual int64_t GetExponentialBiased(int period) noexcept;
+
+ private:
+ // Returns the current period of this sampler. Thread-safe.
+ virtual int period() const noexcept = 0;
+
+ // Keep and decrement stride_ as an unsigned integer, but compare the value
+ // to zero casted as a signed int. clang and msvc do not create optimum code
+ // if we use signed for the combined decrement and sign comparison.
+ //
+ // Below 3 alternative options, all compiles generate the best code
+ // using the unsigned increment <---> signed int comparison option.
+ //
+ // Option 1:
+ // int64_t stride_;
+ // if (ABSL_PREDICT_TRUE(++stride_ < 0)) { ... }
+ //
+ // GCC x64 (OK) : https://gcc.godbolt.org/z/R5MzzA
+ // GCC ppc (OK) : https://gcc.godbolt.org/z/z7NZAt
+ // Clang x64 (BAD): https://gcc.godbolt.org/z/t4gPsd
+ // ICC x64 (OK) : https://gcc.godbolt.org/z/rE6s8W
+ // MSVC x64 (OK) : https://gcc.godbolt.org/z/ARMXqS
+ //
+ // Option 2:
+ // int64_t stride_ = 0;
+ // if (ABSL_PREDICT_TRUE(--stride_ >= 0)) { ... }
+ //
+ // GCC x64 (OK) : https://gcc.godbolt.org/z/jSQxYK
+ // GCC ppc (OK) : https://gcc.godbolt.org/z/VJdYaA
+ // Clang x64 (BAD): https://gcc.godbolt.org/z/Xm4NjX
+ // ICC x64 (OK) : https://gcc.godbolt.org/z/4snaFd
+ // MSVC x64 (BAD): https://gcc.godbolt.org/z/BgnEKE
+ //
+ // Option 3:
+ // uint64_t stride_;
+ // if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) { ... }
+ //
+ // GCC x64 (OK) : https://gcc.godbolt.org/z/bFbfPy
+ // GCC ppc (OK) : https://gcc.godbolt.org/z/S9KkUE
+ // Clang x64 (OK) : https://gcc.godbolt.org/z/UYzRb4
+ // ICC x64 (OK) : https://gcc.godbolt.org/z/ptTNfD
+ // MSVC x64 (OK) : https://gcc.godbolt.org/z/76j4-5
+ uint64_t stride_ = 0;
+ ExponentialBiased rng_;
+};
+
+inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {
+ // See comments on `stride_` for the unsigned increment / signed compare.
+ if (ABSL_PREDICT_TRUE(static_cast<int64_t>(++stride_) < 0)) {
+ return false;
+ }
+ return true;
+}
+
+inline bool PeriodicSamplerBase::Sample() noexcept {
+ return ABSL_PREDICT_FALSE(SubtleMaybeSample()) ? SubtleConfirmSample()
+ : false;
+}
+
+// PeriodicSampler is a concreted periodic sampler implementation.
+// The user provided Tag identifies the implementation, and is required to
+// isolate the global state of this instance from other instances.
+//
+// Typical use case:
+//
+// struct HashTablezTag {};
+// thread_local PeriodicSampler sampler;
+//
+// void HashTableSamplingLogic(...) {
+// if (sampler.Sample()) {
+// HashTableSlowSamplePath(...);
+// }
+// }
+//
+template <typename Tag, int default_period = 0>
+class PeriodicSampler final : public PeriodicSamplerBase {
+ public:
+ ~PeriodicSampler() = default;
+
+ int period() const noexcept final {
+ return period_.load(std::memory_order_relaxed);
+ }
+
+ // Sets the global period for this sampler. Thread-safe.
+ // Setting a period of 0 disables the sampler, i.e., every call to Sample()
+ // will return false. Setting a period of 1 puts the sampler in 'always on'
+ // mode, i.e., every call to Sample() returns true.
+ static void SetGlobalPeriod(int period) {
+ period_.store(period, std::memory_order_relaxed);
+ }
+
+ private:
+ static std::atomic<int> period_;
+};
+
+template <typename Tag, int default_period>
+std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
new file mode 100644
index 00000000000..5ad469ce79c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
@@ -0,0 +1,79 @@
+// 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.
+
+#include "benchmark/benchmark.h"
+#include "absl/base/internal/periodic_sampler.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+template <typename Sampler>
+void BM_Sample(Sampler* sampler, benchmark::State& state) {
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(sampler);
+ benchmark::DoNotOptimize(sampler->Sample());
+ }
+}
+
+template <typename Sampler>
+void BM_SampleMinunumInlined(Sampler* sampler, benchmark::State& state) {
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(sampler);
+ if (ABSL_PREDICT_FALSE(sampler->SubtleMaybeSample())) {
+ benchmark::DoNotOptimize(sampler->SubtleConfirmSample());
+ }
+ }
+}
+
+void BM_PeriodicSampler_TinySample(benchmark::State& state) {
+ struct Tag {};
+ PeriodicSampler<Tag, 10> sampler;
+ BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_TinySample);
+
+void BM_PeriodicSampler_ShortSample(benchmark::State& state) {
+ struct Tag {};
+ PeriodicSampler<Tag, 1024> sampler;
+ BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_ShortSample);
+
+void BM_PeriodicSampler_LongSample(benchmark::State& state) {
+ struct Tag {};
+ PeriodicSampler<Tag, 1024 * 1024> sampler;
+ BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_LongSample);
+
+void BM_PeriodicSampler_LongSampleMinunumInlined(benchmark::State& state) {
+ struct Tag {};
+ PeriodicSampler<Tag, 1024 * 1024> sampler;
+ BM_SampleMinunumInlined(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_LongSampleMinunumInlined);
+
+void BM_PeriodicSampler_Disabled(benchmark::State& state) {
+ struct Tag {};
+ PeriodicSampler<Tag, 0> sampler;
+ BM_Sample(&sampler, state);
+}
+BENCHMARK(BM_PeriodicSampler_Disabled);
+
+} // namespace
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
new file mode 100644
index 00000000000..3b301e37ab9
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
@@ -0,0 +1,177 @@
+// 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.
+
+#include "absl/base/internal/periodic_sampler.h"
+
+#include <thread> // NOLINT(build/c++11)
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/macros.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+using testing::Eq;
+using testing::Return;
+using testing::StrictMock;
+
+class MockPeriodicSampler : public PeriodicSamplerBase {
+ public:
+ virtual ~MockPeriodicSampler() = default;
+
+ MOCK_METHOD(int, period, (), (const, noexcept));
+ MOCK_METHOD(int64_t, GetExponentialBiased, (int), (noexcept));
+};
+
+TEST(PeriodicSamplerBaseTest, Sample) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(16));
+ EXPECT_CALL(sampler, GetExponentialBiased(16))
+ .WillOnce(Return(2))
+ .WillOnce(Return(3))
+ .WillOnce(Return(4));
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, ImmediatelySample) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
+ EXPECT_CALL(sampler, GetExponentialBiased(16))
+ .WillOnce(Return(1))
+ .WillOnce(Return(2))
+ .WillOnce(Return(3));
+
+ EXPECT_TRUE(sampler.Sample());
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Disabled) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(0));
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, AlwaysOn) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).Times(3).WillRepeatedly(Return(1));
+
+ EXPECT_TRUE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Disable) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).WillOnce(Return(16));
+ EXPECT_CALL(sampler, GetExponentialBiased(16)).WillOnce(Return(3));
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+
+ EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(0));
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerBaseTest, Enable) {
+ StrictMock<MockPeriodicSampler> sampler;
+
+ EXPECT_CALL(sampler, period()).WillOnce(Return(0));
+ EXPECT_FALSE(sampler.Sample());
+
+ EXPECT_CALL(sampler, period()).Times(2).WillRepeatedly(Return(16));
+ EXPECT_CALL(sampler, GetExponentialBiased(16))
+ .Times(2)
+ .WillRepeatedly(Return(3));
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_TRUE(sampler.Sample());
+
+ EXPECT_FALSE(sampler.Sample());
+ EXPECT_FALSE(sampler.Sample());
+}
+
+TEST(PeriodicSamplerTest, ConstructConstInit) {
+ struct Tag {};
+ ABSL_CONST_INIT static PeriodicSampler<Tag> sampler;
+ (void)sampler;
+}
+
+TEST(PeriodicSamplerTest, DefaultPeriod0) {
+ struct Tag {};
+ PeriodicSampler<Tag> sampler;
+ EXPECT_THAT(sampler.period(), Eq(0));
+}
+
+TEST(PeriodicSamplerTest, DefaultPeriod) {
+ struct Tag {};
+ PeriodicSampler<Tag, 100> sampler;
+ EXPECT_THAT(sampler.period(), Eq(100));
+}
+
+TEST(PeriodicSamplerTest, SetGlobalPeriod) {
+ struct Tag1 {};
+ struct Tag2 {};
+ PeriodicSampler<Tag1, 25> sampler1;
+ PeriodicSampler<Tag2, 50> sampler2;
+
+ EXPECT_THAT(sampler1.period(), Eq(25));
+ EXPECT_THAT(sampler2.period(), Eq(50));
+
+ std::thread thread([] {
+ PeriodicSampler<Tag1, 25> sampler1;
+ PeriodicSampler<Tag2, 50> sampler2;
+ EXPECT_THAT(sampler1.period(), Eq(25));
+ EXPECT_THAT(sampler2.period(), Eq(50));
+ sampler1.SetGlobalPeriod(10);
+ sampler2.SetGlobalPeriod(20);
+ });
+ thread.join();
+
+ EXPECT_THAT(sampler1.period(), Eq(10));
+ EXPECT_THAT(sampler2.period(), Eq(20));
+}
+
+} // namespace
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/pretty_function.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/pretty_function.h
index 01b0547bd08..35d51676dc2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/pretty_function.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/pretty_function.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.cc
index d9485a66cc6..074e026adbb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -36,9 +36,10 @@
// This preprocessor token is also defined in raw_io.cc. If you need to copy
// this, consider moving both to config.h instead.
#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(__Fuchsia__) || defined(__native_client__)
-#include <unistd.h>
+ defined(__Fuchsia__) || defined(__native_client__) || \
+ defined(__EMSCRIPTEN__) || defined(__ASYLO__)
+#include <unistd.h>
#define ABSL_HAVE_POSIX_WRITE 1
#define ABSL_LOW_LEVEL_WRITE_SUPPORTED 1
@@ -66,26 +67,32 @@
#undef ABSL_HAVE_RAW_IO
#endif
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace raw_logging_internal {
+namespace {
+
// TODO(gfalcon): We want raw-logging to work on as many platforms as possible.
-// Explicitly #error out when not ABSL_LOW_LEVEL_WRITE_SUPPORTED, except for a
-// whitelisted set of platforms for which we expect not to be able to raw log.
+// Explicitly `#error` out when not `ABSL_LOW_LEVEL_WRITE_SUPPORTED`, except for
+// a selected set of platforms for which we expect not to be able to raw log.
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
- absl::raw_logging_internal::LogPrefixHook> log_prefix_hook;
-ABSL_CONST_INIT static absl::base_internal::AtomicHook<
- absl::raw_logging_internal::AbortHook> abort_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+ absl::base_internal::AtomicHook<LogPrefixHook>
+ log_prefix_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+ absl::base_internal::AtomicHook<AbortHook>
+ abort_hook;
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
-static const char kTruncated[] = " ... (message truncated)\n";
+constexpr char kTruncated[] = " ... (message truncated)\n";
// sprintf the format to the buffer, adjusting *buf and *size to reflect the
// consumed bytes, and return whether the message fit without truncation. If
// truncation occurred, if possible leave room in the buffer for the message
// kTruncated[].
-inline static bool VADoRawLog(char** buf, int* size, const char* format,
- va_list ap) ABSL_PRINTF_ATTRIBUTE(3, 0);
-inline static bool VADoRawLog(char** buf, int* size,
- const char* format, va_list ap) {
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap)
+ ABSL_PRINTF_ATTRIBUTE(3, 0);
+bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
int n = vsnprintf(*buf, *size, format, ap);
bool result = true;
if (n < 0 || n > *size) {
@@ -93,7 +100,7 @@ inline static bool VADoRawLog(char** buf, int* size,
if (static_cast<size_t>(*size) > sizeof(kTruncated)) {
n = *size - sizeof(kTruncated); // room for truncation message
} else {
- n = 0; // no room for truncation message
+ n = 0; // no room for truncation message
}
}
*size -= n;
@@ -102,9 +109,7 @@ inline static bool VADoRawLog(char** buf, int* size,
}
#endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
-static constexpr int kLogBufSize = 3000;
-
-namespace {
+constexpr int kLogBufSize = 3000;
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
@@ -163,7 +168,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
} else {
DoRawLog(&buf, &size, "%s", kTruncated);
}
- absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
+ SafeWriteToStderr(buffer, strlen(buffer));
}
#else
static_cast<void>(format);
@@ -178,10 +183,18 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
}
}
+// Non-formatting version of RawLog().
+//
+// TODO(gfalcon): When string_view no longer depends on base, change this
+// interface to take its message as a string_view instead.
+void DefaultInternalLog(absl::LogSeverity severity, const char* file, int line,
+ const std::string& message) {
+ RawLog(severity, file, line, "%.*s", static_cast<int>(message.size()),
+ message.data());
+}
+
} // namespace
-namespace absl {
-namespace raw_logging_internal {
void SafeWriteToStderr(const char *s, size_t len) {
#if defined(ABSL_HAVE_SYSCALL_WRITE)
syscall(SYS_write, STDERR_FILENO, s, len);
@@ -197,8 +210,6 @@ void SafeWriteToStderr(const char *s, size_t len) {
}
void RawLog(absl::LogSeverity severity, const char* file, int line,
- const char* format, ...) ABSL_PRINTF_ATTRIBUTE(4, 5);
-void RawLog(absl::LogSeverity severity, const char* file, int line,
const char* format, ...) {
va_list ap;
va_start(ap, format);
@@ -206,15 +217,6 @@ void RawLog(absl::LogSeverity severity, const char* file, int line,
va_end(ap);
}
-// Non-formatting version of RawLog().
-//
-// TODO(gfalcon): When string_view no longer depends on base, change this
-// interface to take its message as a string_view instead.
-static void DefaultInternalLog(absl::LogSeverity severity, const char* file,
- int line, const std::string& message) {
- RawLog(severity, file, line, "%s", message.c_str());
-}
-
bool RawLoggingFullySupported() {
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
return true;
@@ -223,12 +225,18 @@ bool RawLoggingFullySupported() {
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}
-ABSL_CONST_INIT absl::base_internal::AtomicHook<InternalLogFunction>
- internal_log_function(DefaultInternalLog);
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
+ absl::base_internal::AtomicHook<InternalLogFunction>
+ internal_log_function(DefaultInternalLog);
+
+void RegisterLogPrefixHook(LogPrefixHook func) { log_prefix_hook.Store(func); }
+
+void RegisterAbortHook(AbortHook func) { abort_hook.Store(func); }
void RegisterInternalLogFunction(InternalLogFunction func) {
internal_log_function.Store(func);
}
} // namespace raw_logging_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.h
index 79a7bb9b2f7..2bf7aabac14 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/raw_logging.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,9 +22,11 @@
#include <string>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/atomic_hook.h"
#include "absl/base/log_severity.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
// This is similar to LOG(severity) << format..., but
@@ -38,6 +40,7 @@
// ABSL_RAW_LOG(ERROR, "Failed foo with %i: %s", status, error);
// This will print an almost standard log line like this to stderr only:
// E0821 211317 file.cc:123] RAW: Failed foo with 22: bad_file
+
#define ABSL_RAW_LOG(severity, ...) \
do { \
constexpr const char* absl_raw_logging_internal_basename = \
@@ -69,23 +72,23 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message) \
- do { \
- constexpr const char* absl_raw_logging_internal_basename = \
- ::absl::raw_logging_internal::Basename(__FILE__, \
- sizeof(__FILE__) - 1); \
- ::absl::raw_logging_internal::internal_log_function( \
- ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_basename, __LINE__, message); \
+#define ABSL_INTERNAL_LOG(severity, message) \
+ do { \
+ constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
+ ::absl::raw_logging_internal::internal_log_function( \
+ ABSL_RAW_LOGGING_INTERNAL_##severity, \
+ absl_raw_logging_internal_filename, __LINE__, message); \
+ if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
+ ABSL_INTERNAL_UNREACHABLE; \
} while (0)
-#define ABSL_INTERNAL_CHECK(condition, message) \
- do { \
- if (ABSL_PREDICT_FALSE(!(condition))) { \
+#define ABSL_INTERNAL_CHECK(condition, message) \
+ do { \
+ if (ABSL_PREDICT_FALSE(!(condition))) { \
std::string death_message = "Check " #condition " failed: "; \
death_message += std::string(message); \
- ABSL_INTERNAL_LOG(FATAL, death_message); \
- } \
+ ABSL_INTERNAL_LOG(FATAL, death_message); \
+ } \
} while (0)
#define ABSL_RAW_LOGGING_INTERNAL_INFO ::absl::LogSeverity::kInfo
@@ -96,6 +99,7 @@
::absl::NormalizeLogSeverity(severity)
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace raw_logging_internal {
// Helper function to implement ABSL_RAW_LOG
@@ -156,7 +160,7 @@ using LogPrefixHook = bool (*)(absl::LogSeverity severity, const char* file,
//
// 'file' and 'line' are the file and line number where the ABSL_RAW_LOG macro
// was located.
-// The null-terminated logged message lives in the buffer between 'buf_start'
+// The NUL-terminated logged message lives in the buffer between 'buf_start'
// and 'buf_end'. 'prefix_end' points to the first non-prefix character of the
// buffer (as written by the LogPrefixHook.)
using AbortHook = void (*)(const char* file, int line, const char* buf_start,
@@ -170,11 +174,22 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
const char* file, int line,
const std::string& message);
-extern base_internal::AtomicHook<InternalLogFunction> internal_log_function;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
+ InternalLogFunction>
+ internal_log_function;
+// Registers hooks of the above types. Only a single hook of each type may be
+// registered. It is an error to call these functions multiple times with
+// different input arguments.
+//
+// These functions are safe to call at any point during initialization; they do
+// not block or malloc, and are async-signal safe.
+void RegisterLogPrefixHook(LogPrefixHook func);
+void RegisterAbortHook(AbortHook func);
void RegisterInternalLogFunction(InternalLogFunction func);
} // namespace raw_logging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_RAW_LOGGING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scheduling_mode.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scheduling_mode.h
index 1b6497ad875..8be5ab6dd3c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scheduling_mode.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scheduling_mode.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,7 +18,10 @@
#ifndef ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
#define ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Used to describe how a thread may be scheduled. Typically associated with
@@ -49,6 +52,7 @@ enum SchedulingMode {
};
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SCHEDULING_MODE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.cc
new file mode 100644
index 00000000000..8a934cb5119
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.cc
@@ -0,0 +1,81 @@
+// 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.
+
+#include "absl/base/internal/scoped_set_env.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <cstdlib>
+
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+namespace {
+
+#ifdef _WIN32
+const int kMaxEnvVarValueSize = 1024;
+#endif
+
+void SetEnvVar(const char* name, const char* value) {
+#ifdef _WIN32
+ SetEnvironmentVariableA(name, value);
+#else
+ if (value == nullptr) {
+ ::unsetenv(name);
+ } else {
+ ::setenv(name, value, 1);
+ }
+#endif
+}
+
+} // namespace
+
+ScopedSetEnv::ScopedSetEnv(const char* var_name, const char* new_value)
+ : var_name_(var_name), was_unset_(false) {
+#ifdef _WIN32
+ char buf[kMaxEnvVarValueSize];
+ auto get_res = GetEnvironmentVariableA(var_name_.c_str(), buf, sizeof(buf));
+ ABSL_INTERNAL_CHECK(get_res < sizeof(buf), "value exceeds buffer size");
+
+ if (get_res == 0) {
+ was_unset_ = (GetLastError() == ERROR_ENVVAR_NOT_FOUND);
+ } else {
+ old_value_.assign(buf, get_res);
+ }
+
+ SetEnvironmentVariableA(var_name_.c_str(), new_value);
+#else
+ const char* val = ::getenv(var_name_.c_str());
+ if (val == nullptr) {
+ was_unset_ = true;
+ } else {
+ old_value_ = val;
+ }
+#endif
+
+ SetEnvVar(var_name_.c_str(), new_value);
+}
+
+ScopedSetEnv::~ScopedSetEnv() {
+ SetEnvVar(var_name_.c_str(), was_unset_ ? nullptr : old_value_.c_str());
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.h
new file mode 100644
index 00000000000..19ec7b5d8a0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env.h
@@ -0,0 +1,45 @@
+//
+// 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_BASE_INTERNAL_SCOPED_SET_ENV_H_
+#define ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+class ScopedSetEnv {
+ public:
+ ScopedSetEnv(const char* var_name, const char* new_value);
+ ~ScopedSetEnv();
+
+ private:
+ std::string var_name_;
+ std::string old_value_;
+
+ // True if the environment variable was initially not set.
+ bool was_unset_;
+};
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_SCOPED_SET_ENV_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env_test.cc
new file mode 100644
index 00000000000..5cbad246c64
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/scoped_set_env_test.cc
@@ -0,0 +1,99 @@
+// 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.
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/scoped_set_env.h"
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+std::string GetEnvVar(const char* name) {
+#ifdef _WIN32
+ char buf[1024];
+ auto get_res = GetEnvironmentVariableA(name, buf, sizeof(buf));
+ if (get_res >= sizeof(buf)) {
+ return "TOO_BIG";
+ }
+
+ if (get_res == 0) {
+ return "UNSET";
+ }
+
+ return std::string(buf, get_res);
+#else
+ const char* val = ::getenv(name);
+ if (val == nullptr) {
+ return "UNSET";
+ }
+
+ return val;
+#endif
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToString) {
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetNonExistingVarToNull) {
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToString) {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "new_value");
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "new_value");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+TEST(ScopedSetEnvTest, SetExistingVarToNull) {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", "value");
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+
+ {
+ ScopedSetEnv scoped_set("SCOPED_SET_ENV_TEST_VAR", nullptr);
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "UNSET");
+ }
+
+ EXPECT_EQ(GetEnvVar("SCOPED_SET_ENV_TEST_VAR"), "value");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.cc
index 28ba1af7ebb..35c0696a345 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -54,10 +54,11 @@
// holder to acquire the lock. There may be outstanding waiter(s).
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
-ABSL_CONST_INIT static base_internal::AtomicHook<void (*)(const void *lock,
- int64_t wait_cycles)>
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static base_internal::AtomicHook<void (*)(
+ const void *lock, int64_t wait_cycles)>
submit_profile_data;
void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
@@ -65,35 +66,19 @@ void RegisterSpinLockProfiler(void (*fn)(const void *contendedlock,
submit_profile_data.Store(fn);
}
+// Static member variable definitions.
+constexpr uint32_t SpinLock::kSpinLockHeld;
+constexpr uint32_t SpinLock::kSpinLockCooperative;
+constexpr uint32_t SpinLock::kSpinLockDisabledScheduling;
+constexpr uint32_t SpinLock::kSpinLockSleeper;
+constexpr uint32_t SpinLock::kWaitTimeMask;
+
// Uncommon constructors.
SpinLock::SpinLock(base_internal::SchedulingMode mode)
: lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
-SpinLock::SpinLock(base_internal::LinkerInitialized,
- base_internal::SchedulingMode mode) {
- ABSL_TSAN_MUTEX_CREATE(this, 0);
- if (IsCooperative(mode)) {
- InitLinkerInitializedAndCooperative();
- }
- // Otherwise, lockword_ is already initialized.
-}
-
-// Static (linker initialized) spinlocks always start life as functional
-// non-cooperative locks. When their static constructor does run, it will call
-// this initializer to augment the lockword with the cooperative bit. By
-// actually taking the lock when we do this we avoid the need for an atomic
-// operation in the regular unlock path.
-//
-// SlowLock() must be careful to re-test for this bit so that any outstanding
-// waiters may be upgraded to cooperative status.
-void SpinLock::InitLinkerInitializedAndCooperative() {
- Lock();
- lockword_.fetch_or(kSpinLockCooperative, std::memory_order_relaxed);
- Unlock();
-}
-
// Monitor the lock to see if its value changes within some time period
// (adaptive_spin_count loop iterations). The last value read from the lock
// is returned from the method.
@@ -120,6 +105,14 @@ void SpinLock::SlowLock() {
if ((lock_value & kSpinLockHeld) == 0) {
return;
}
+
+ base_internal::SchedulingMode scheduling_mode;
+ if ((lock_value & kSpinLockCooperative) != 0) {
+ scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
+ } else {
+ scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
+ }
+
// The lock was not obtained initially, so this thread needs to wait for
// it. Record the current timestamp in the local variable wait_start_time
// so the total wait time can be stored in the lockword once this thread
@@ -132,8 +125,9 @@ void SpinLock::SlowLock() {
// it as having a sleeper.
if ((lock_value & kWaitTimeMask) == 0) {
// Here, just "mark" that the thread is going to sleep. Don't store the
- // lock wait time in the lock as that will cause the current lock
- // owner to think it experienced contention.
+ // lock wait time in the lock -- the lock word stores the amount of time
+ // that the current holder waited before acquiring the lock, not the wait
+ // time of any thread currently waiting to acquire it.
if (lockword_.compare_exchange_strong(
lock_value, lock_value | kSpinLockSleeper,
std::memory_order_relaxed, std::memory_order_relaxed)) {
@@ -147,15 +141,17 @@ void SpinLock::SlowLock() {
// this thread obtains the lock.
lock_value = TryLockInternal(lock_value, wait_cycles);
continue; // Skip the delay at the end of the loop.
+ } else if ((lock_value & kWaitTimeMask) == 0) {
+ // The lock is still held, without a waiter being marked, but something
+ // else about the lock word changed, causing our CAS to fail. For
+ // example, a new lock holder may have acquired the lock with
+ // kSpinLockDisabledScheduling set, whereas the previous holder had not
+ // set that flag. In this case, attempt again to mark ourselves as a
+ // waiter.
+ continue;
}
}
- base_internal::SchedulingMode scheduling_mode;
- if ((lock_value & kSpinLockCooperative) != 0) {
- scheduling_mode = base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL;
- } else {
- scheduling_mode = base_internal::SCHEDULE_KERNEL_ONLY;
- }
// SpinLockDelay() calls into fiber scheduler, we need to see
// synchronization there to avoid false positives.
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
@@ -189,30 +185,32 @@ void SpinLock::SlowUnlock(uint32_t lock_value) {
// We use the upper 29 bits of the lock word to store the time spent waiting to
// acquire this lock. This is reported by contentionz profiling. Since the
// lower bits of the cycle counter wrap very quickly on high-frequency
-// processors we divide to reduce the granularity to 2^PROFILE_TIMESTAMP_SHIFT
+// processors we divide to reduce the granularity to 2^kProfileTimestampShift
// sized units. On a 4Ghz machine this will lose track of wait times greater
// than (2^29/4 Ghz)*128 =~ 17.2 seconds. Such waits should be extremely rare.
-enum { PROFILE_TIMESTAMP_SHIFT = 7 };
-enum { LOCKWORD_RESERVED_SHIFT = 3 }; // We currently reserve the lower 3 bits.
+static constexpr int kProfileTimestampShift = 7;
+
+// We currently reserve the lower 3 bits.
+static constexpr int kLockwordReservedShift = 3;
uint32_t SpinLock::EncodeWaitCycles(int64_t wait_start_time,
int64_t wait_end_time) {
static const int64_t kMaxWaitTime =
- std::numeric_limits<uint32_t>::max() >> LOCKWORD_RESERVED_SHIFT;
+ std::numeric_limits<uint32_t>::max() >> kLockwordReservedShift;
int64_t scaled_wait_time =
- (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
+ (wait_end_time - wait_start_time) >> kProfileTimestampShift;
// Return a representation of the time spent waiting that can be stored in
// the lock word's upper bits.
uint32_t clamped = static_cast<uint32_t>(
- std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
+ std::min(scaled_wait_time, kMaxWaitTime) << kLockwordReservedShift);
if (clamped == 0) {
return kSpinLockSleeper; // Just wake waiters, but don't record contention.
}
// Bump up value if necessary to avoid returning kSpinLockSleeper.
const uint32_t kMinWaitTime =
- kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
+ kSpinLockSleeper + (1 << kLockwordReservedShift);
if (clamped == kSpinLockSleeper) {
return kMinWaitTime;
}
@@ -223,9 +221,9 @@ uint64_t SpinLock::DecodeWaitCycles(uint32_t lock_value) {
// Cast to uint32_t first to ensure bits [63:32] are cleared.
const uint64_t scaled_wait_time =
static_cast<uint32_t>(lock_value & kWaitTimeMask);
- return scaled_wait_time
- << (PROFILE_TIMESTAMP_SHIFT - LOCKWORD_RESERVED_SHIFT);
+ return scaled_wait_time << (kProfileTimestampShift - kLockwordReservedShift);
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.h
index eb3eec9cd0a..c73b5e09670 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,11 +15,8 @@
//
// Most users requiring mutual exclusion should use Mutex.
-// SpinLock is provided for use in three situations:
+// SpinLock is provided for use in two situations:
// - for use in code that Mutex itself depends on
-// - to get a faster fast-path release under low contention (without an
-// atomic read-modify-write) In return, SpinLock has worse behaviour under
-// contention, which is why Mutex is preferred in most situations.
// - for async signal safety (see below)
// SpinLock is async signal safe. If a spinlock is used within a signal
@@ -32,9 +29,11 @@
#include <stdint.h>
#include <sys/types.h>
+
#include <atomic>
#include "absl/base/attributes.h"
+#include "absl/base/const_init.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/low_level_scheduling.h"
#include "absl/base/internal/raw_logging.h"
@@ -45,38 +44,34 @@
#include "absl/base/thread_annotations.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
-class LOCKABLE SpinLock {
+class ABSL_LOCKABLE SpinLock {
public:
SpinLock() : lockword_(kSpinLockCooperative) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
- // Special constructor for use with static SpinLock objects. E.g.,
- //
- // static SpinLock lock(base_internal::kLinkerInitialized);
- //
- // When intialized using this constructor, we depend on the fact
- // that the linker has already initialized the memory appropriately.
- // A SpinLock constructed like this can be freely used from global
- // initializers without worrying about the order in which global
- // initializers run.
- explicit SpinLock(base_internal::LinkerInitialized) {
- // Does nothing; lockword_ is already initialized
- ABSL_TSAN_MUTEX_CREATE(this, 0);
- }
-
// Constructors that allow non-cooperative spinlocks to be created for use
// inside thread schedulers. Normal clients should not use these.
explicit SpinLock(base_internal::SchedulingMode mode);
- SpinLock(base_internal::LinkerInitialized,
- base_internal::SchedulingMode mode);
+ // Constructor for global SpinLock instances. See absl/base/const_init.h.
+ constexpr SpinLock(absl::ConstInitType, base_internal::SchedulingMode mode)
+ : lockword_(IsCooperative(mode) ? kSpinLockCooperative : 0) {}
+
+ // For global SpinLock instances prefer trivial destructor when possible.
+ // Default but non-trivial destructor in some build configurations causes an
+ // extra static initializer.
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
~SpinLock() { ABSL_TSAN_MUTEX_DESTROY(this, __tsan_mutex_not_static); }
+#else
+ ~SpinLock() = default;
+#endif
// Acquire this SpinLock.
- inline void Lock() EXCLUSIVE_LOCK_FUNCTION() {
+ inline void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_LOCK(this, 0);
if (!TryLockImpl()) {
SlowLock();
@@ -88,7 +83,7 @@ class LOCKABLE SpinLock {
// acquisition was successful. If the lock was not acquired, false is
// returned. If this SpinLock is free at the time of the call, TryLock
// will return true with high probability.
- inline bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ inline bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
ABSL_TSAN_MUTEX_PRE_LOCK(this, __tsan_mutex_try_lock);
bool res = TryLockImpl();
ABSL_TSAN_MUTEX_POST_LOCK(
@@ -98,7 +93,7 @@ class LOCKABLE SpinLock {
}
// Release this SpinLock, which must be held by the calling thread.
- inline void Unlock() UNLOCK_FUNCTION() {
+ inline void Unlock() ABSL_UNLOCK_FUNCTION() {
ABSL_TSAN_MUTEX_PRE_UNLOCK(this, 0);
uint32_t lock_value = lockword_.load(std::memory_order_relaxed);
lock_value = lockword_.exchange(lock_value & kSpinLockCooperative,
@@ -142,14 +137,27 @@ class LOCKABLE SpinLock {
//
// bit[0] encodes whether a lock is being held.
// bit[1] encodes whether a lock uses cooperative scheduling.
- // bit[2] encodes whether a lock disables scheduling.
+ // bit[2] encodes whether the current lock holder disabled scheduling when
+ // acquiring the lock. Only set when kSpinLockHeld is also set.
// bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
- enum { kSpinLockHeld = 1 };
- enum { kSpinLockCooperative = 2 };
- enum { kSpinLockDisabledScheduling = 4 };
- enum { kSpinLockSleeper = 8 };
- enum { kWaitTimeMask = // Includes kSpinLockSleeper.
- ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling) };
+ // This is set by the lock holder to indicate how long it waited on
+ // the lock before eventually acquiring it. The number of cycles is
+ // encoded as a 29-bit unsigned int, or in the case that the current
+ // holder did not wait but another waiter is queued, the LSB
+ // (kSpinLockSleeper) is set. The implementation does not explicitly
+ // track the number of queued waiters beyond this. It must always be
+ // assumed that waiters may exist if the current holder was required to
+ // queue.
+ //
+ // Invariant: if the lock is not held, the value is either 0 or
+ // kSpinLockCooperative.
+ static constexpr uint32_t kSpinLockHeld = 1;
+ static constexpr uint32_t kSpinLockCooperative = 2;
+ static constexpr uint32_t kSpinLockDisabledScheduling = 4;
+ static constexpr uint32_t kSpinLockSleeper = 8;
+ // Includes kSpinLockSleeper.
+ static constexpr uint32_t kWaitTimeMask =
+ ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling);
// Returns true if the provided scheduling mode is cooperative.
static constexpr bool IsCooperative(
@@ -158,7 +166,6 @@ class LOCKABLE SpinLock {
}
uint32_t TryLockInternal(uint32_t lock_value, uint32_t wait_cycles);
- void InitLinkerInitializedAndCooperative();
void SlowLock() ABSL_ATTRIBUTE_COLD;
void SlowUnlock(uint32_t lock_value) ABSL_ATTRIBUTE_COLD;
uint32_t SpinLoop();
@@ -176,13 +183,13 @@ class LOCKABLE SpinLock {
// Corresponding locker object that arranges to acquire a spinlock for
// the duration of a C++ scope.
-class SCOPED_LOCKABLE SpinLockHolder {
+class ABSL_SCOPED_LOCKABLE SpinLockHolder {
public:
- inline explicit SpinLockHolder(SpinLock* l) EXCLUSIVE_LOCK_FUNCTION(l)
+ inline explicit SpinLockHolder(SpinLock* l) ABSL_EXCLUSIVE_LOCK_FUNCTION(l)
: lock_(l) {
l->Lock();
}
- inline ~SpinLockHolder() UNLOCK_FUNCTION() { lock_->Unlock(); }
+ inline ~SpinLockHolder() ABSL_UNLOCK_FUNCTION() { lock_->Unlock(); }
SpinLockHolder(const SpinLockHolder&) = delete;
SpinLockHolder& operator=(const SpinLockHolder&) = delete;
@@ -222,11 +229,10 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
}
}
- if (lockword_.compare_exchange_strong(
+ if (!lockword_.compare_exchange_strong(
lock_value,
kSpinLockHeld | lock_value | wait_cycles | sched_disabled_bit,
std::memory_order_acquire, std::memory_order_relaxed)) {
- } else {
base_internal::SchedulingGuard::EnableRescheduling(sched_disabled_bit != 0);
}
@@ -234,6 +240,7 @@ inline uint32_t SpinLock::TryLockInternal(uint32_t lock_value,
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SPINLOCK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_akaros.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_akaros.inc
index 051c8cf87fb..7b0cada4f13 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_akaros.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_akaros.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,7 +20,7 @@
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */,
int /* loop */, absl::base_internal::SchedulingMode /* mode */) {
// In Akaros, one must take care not to call anything that could cause a
@@ -29,7 +29,7 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
// arbitrary code.
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_benchmark.cc
index 907d3e2745b..0451c65f955 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_linux.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_linux.inc
index 94c861dc6ca..202f7cdfc8a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_linux.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_linux.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,12 +19,12 @@
#include <unistd.h>
#include <atomic>
-#include <cerrno>
#include <climits>
#include <cstdint>
#include <ctime>
#include "absl/base/attributes.h"
+#include "absl/base/internal/errno_saver.h"
// The SpinLock lockword is `std::atomic<uint32_t>`. Here we assert that
// `std::atomic<uint32_t>` is bitwise equivalent of the `int` expected
@@ -46,26 +46,28 @@ static_assert(sizeof(std::atomic<uint32_t>) == sizeof(int),
#endif
#endif
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode) {
- if (loop != 0) {
- int save_errno = errno;
- struct timespec tm;
- tm.tv_sec = 0;
- // Increase the delay; we expect (but do not rely on) explicit wakeups.
- // We don't rely on explicit wakeups because we intentionally allow for
- // a race on the kSpinLockSleeper bit.
- tm.tv_nsec = 16 * absl::base_internal::SpinLockSuggestedDelayNS(loop);
- syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
- errno = save_errno;
- }
+ absl::base_internal::ErrnoSaver errno_saver;
+ struct timespec tm;
+ tm.tv_sec = 0;
+ tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
+ syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(std::atomic<uint32_t> *w,
- bool all) {
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ std::atomic<uint32_t> *w, bool all) {
syscall(SYS_futex, w, FUTEX_WAKE | FUTEX_PRIVATE_FLAG, all ? INT_MAX : 1, 0);
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_posix.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_posix.inc
index 0098c1c7601..4f6f887d993 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_posix.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_posix.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,19 +15,20 @@
// This file is a Posix-specific part of spinlock_wait.cc
#include <sched.h>
+
#include <atomic>
#include <ctime>
-#include <cerrno>
+#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/port.h"
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
absl::base_internal::SchedulingMode /* mode */) {
- int save_errno = errno;
+ absl::base_internal::ErrnoSaver errno_saver;
if (loop == 0) {
} else if (loop == 1) {
sched_yield();
@@ -37,10 +38,9 @@ ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
tm.tv_nsec = absl::base_internal::SpinLockSuggestedDelayNS(loop);
nanosleep(&tm, nullptr);
}
- errno = save_errno;
}
-ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.cc
index 365a7939494..fa824be1c00 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -32,6 +32,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// See spinlock_wait.h for spec.
@@ -65,18 +66,16 @@ int SpinLockSuggestedDelayNS(int loop) {
r = 0x5deece66dLL * r + 0xb; // numbers from nrand48()
delay_rand.store(r, std::memory_order_relaxed);
- r <<= 16; // 48-bit random number now in top 48-bits.
if (loop < 0 || loop > 32) { // limit loop to 0..32
loop = 32;
}
- // loop>>3 cannot exceed 4 because loop cannot exceed 32.
- // Select top 20..24 bits of lower 48 bits,
- // giving approximately 0ms to 16ms.
- // Mean is exponential in loop for first 32 iterations, then 8ms.
- // The futex path multiplies this by 16, since we expect explicit wakeups
- // almost always on that path.
- return static_cast<int>(r >> (44 - (loop >> 3)));
+ const int kMinDelay = 128 << 10; // 128us
+ // Double delay every 8 iterations, up to 16x (2ms).
+ int delay = kMinDelay << (loop / 8);
+ // Randomize in delay..2*delay range, for resulting 128us..4ms range.
+ return delay | ((delay - 1) & static_cast<int>(r));
}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.h
index 5c6cc7fdba4..579bd09fa0f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_wait.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +24,7 @@
#include "absl/base/internal/scheduling_mode.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// SpinLockWait() waits until it can perform one of several transitions from
@@ -42,18 +43,16 @@ uint32_t SpinLockWait(std::atomic<uint32_t> *w, int n,
const SpinLockWaitTransition trans[],
SchedulingMode scheduling_mode);
-// If possible, wake some thread that has called SpinLockDelay(w, ...). If
-// "all" is true, wake all such threads. This call is a hint, and on some
-// systems it may be a no-op; threads calling SpinLockDelay() will always wake
-// eventually even if SpinLockWake() is never called.
+// If possible, wake some thread that has called SpinLockDelay(w, ...). If `all`
+// is true, wake all such threads. On some systems, this may be a no-op; on
+// those systems, threads calling SpinLockDelay() will always wake eventually
+// even if SpinLockWake() is never called.
void SpinLockWake(std::atomic<uint32_t> *w, bool all);
// Wait for an appropriate spin delay on iteration "loop" of a
// spin loop on location *w, whose previously observed value was "value".
// SpinLockDelay() may do nothing, may yield the CPU, may sleep a clock tick,
-// or may wait for a delay that can be truncated by a call to SpinLockWake(w).
-// In all cases, it must return in bounded time even if SpinLockWake() is not
-// called.
+// or may wait for a call to SpinLockWake(w).
void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
base_internal::SchedulingMode scheduling_mode);
@@ -62,6 +61,7 @@ void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
int SpinLockSuggestedDelayNS(int loop);
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
@@ -71,21 +71,23 @@ int SpinLockSuggestedDelayNS(int loop);
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, bool all);
-void AbslInternalSpinLockDelay(
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,
+ bool all);
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode);
}
inline void absl::base_internal::SpinLockWake(std::atomic<uint32_t> *w,
bool all) {
- AbslInternalSpinLockWake(w, all);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);
}
inline void absl::base_internal::SpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode scheduling_mode) {
- AbslInternalSpinLockDelay(w, value, loop, scheduling_mode);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)
+ (w, value, loop, scheduling_mode);
}
#endif // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_win32.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_win32.inc
index 32c8fc0bb51..9d224813a54 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_win32.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/spinlock_win32.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,9 +20,9 @@
extern "C" {
-void AbslInternalSpinLockDelay(std::atomic<uint32_t>* /* lock_word */,
- uint32_t /* value */, int loop,
- absl::base_internal::SchedulingMode /* mode */) {
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
+ absl::base_internal::SchedulingMode /* mode */) {
if (loop == 0) {
} else if (loop == 1) {
Sleep(0);
@@ -31,7 +31,7 @@ void AbslInternalSpinLockDelay(std::atomic<uint32_t>* /* lock_word */,
}
}
-void AbslInternalSpinLockWake(std::atomic<uint32_t>* /* lock_word */,
- bool /* all */) {}
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.cc
new file mode 100644
index 00000000000..0d6226fd0a1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.cc
@@ -0,0 +1,88 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/strerror.h"
+
+#include <array>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/internal/errno_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+namespace {
+
+const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
+#if defined(_WIN32)
+ int rc = strerror_s(buf, buflen, errnum);
+ buf[buflen - 1] = '\0'; // guarantee NUL termination
+ if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
+ return buf;
+#else
+ // The type of `ret` is platform-specific; both of these branches must compile
+ // either way but only one will execute on any given platform:
+ auto ret = strerror_r(errnum, buf, buflen);
+ if (std::is_same<decltype(ret), int>::value) {
+ // XSI `strerror_r`; `ret` is `int`:
+ if (ret) *buf = '\0';
+ return buf;
+ } else {
+ // GNU `strerror_r`; `ret` is `char *`:
+ return reinterpret_cast<const char*>(ret);
+ }
+#endif
+}
+
+std::string StrErrorInternal(int errnum) {
+ char buf[100];
+ const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
+ if (*str == '\0') {
+ snprintf(buf, sizeof buf, "Unknown error %d", errnum);
+ str = buf;
+ }
+ return str;
+}
+
+// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
+// to `StrErrorAdaptor()` if the value is larger than this.
+constexpr int kSysNerr = 135;
+
+std::array<std::string, kSysNerr>* NewStrErrorTable() {
+ auto* table = new std::array<std::string, kSysNerr>;
+ for (int i = 0; i < static_cast<int>(table->size()); ++i) {
+ (*table)[i] = StrErrorInternal(i);
+ }
+ return table;
+}
+
+} // namespace
+
+std::string StrError(int errnum) {
+ absl::base_internal::ErrnoSaver errno_saver;
+ static const auto* table = NewStrErrorTable();
+ if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
+ return (*table)[errnum];
+ }
+ return StrErrorInternal(errnum);
+}
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.h
new file mode 100644
index 00000000000..350097366ee
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror.h
@@ -0,0 +1,39 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_BASE_INTERNAL_STRERROR_H_
+#define ABSL_BASE_INTERNAL_STRERROR_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+
+// A portable and thread-safe alternative to C89's `strerror`.
+//
+// The C89 specification of `strerror` is not suitable for use in a
+// multi-threaded application as the returned string may be changed by calls to
+// `strerror` from another thread. The many non-stdlib alternatives differ
+// enough in their names, availability, and semantics to justify this wrapper
+// around them. `errno` will not be modified by a call to `absl::StrError`.
+std::string StrError(int errnum);
+
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_STRERROR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_benchmark.cc
new file mode 100644
index 00000000000..c9ab14a89db
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_benchmark.cc
@@ -0,0 +1,29 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cerrno>
+#include <cstdio>
+#include <string>
+
+#include "absl/base/internal/strerror.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+void BM_AbslStrError(benchmark::State& state) {
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(absl::base_internal::StrError(ERANGE));
+ }
+}
+BENCHMARK(BM_AbslStrError);
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_test.cc
new file mode 100644
index 00000000000..e32d5b5c9be
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/strerror_test.cc
@@ -0,0 +1,88 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/internal/strerror.h"
+
+#include <atomic>
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include <thread> // NOLINT(build/c++11)
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/match.h"
+
+namespace {
+using ::testing::AnyOf;
+using ::testing::Eq;
+
+TEST(StrErrorTest, ValidErrorCode) {
+ errno = ERANGE;
+ EXPECT_THAT(absl::base_internal::StrError(EDOM), Eq(strerror(EDOM)));
+ EXPECT_THAT(errno, Eq(ERANGE));
+}
+
+TEST(StrErrorTest, InvalidErrorCode) {
+ errno = ERANGE;
+ EXPECT_THAT(absl::base_internal::StrError(-1),
+ AnyOf(Eq("No error information"), Eq("Unknown error -1")));
+ EXPECT_THAT(errno, Eq(ERANGE));
+}
+
+TEST(StrErrorTest, MultipleThreads) {
+ // In this test, we will start up 2 threads and have each one call
+ // StrError 1000 times, each time with a different errnum. We
+ // expect that StrError(errnum) will return a string equal to the
+ // one returned by strerror(errnum), if the code is known. Since
+ // strerror is known to be thread-hostile, collect all the expected
+ // strings up front.
+ const int kNumCodes = 1000;
+ std::vector<std::string> expected_strings(kNumCodes);
+ for (int i = 0; i < kNumCodes; ++i) {
+ expected_strings[i] = strerror(i);
+ }
+
+ std::atomic_int counter(0);
+ auto thread_fun = [&]() {
+ for (int i = 0; i < kNumCodes; ++i) {
+ ++counter;
+ errno = ERANGE;
+ const std::string value = absl::base_internal::StrError(i);
+ // EXPECT_* could change errno. Stash it first.
+ int check_err = errno;
+ EXPECT_THAT(check_err, Eq(ERANGE));
+ // Only the GNU implementation is guaranteed to provide the
+ // string "Unknown error nnn". POSIX doesn't say anything.
+ if (!absl::StartsWith(value, "Unknown error ")) {
+ EXPECT_THAT(value, Eq(expected_strings[i]));
+ }
+ }
+ };
+
+ const int kNumThreads = 100;
+ std::vector<std::thread> threads;
+ for (int i = 0; i < kNumThreads; ++i) {
+ threads.push_back(std::thread(thread_fun));
+ }
+ for (auto& thread : threads) {
+ thread.join();
+ }
+
+ EXPECT_THAT(counter, Eq(kNumThreads * kNumCodes));
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.cc
index db41bacc844..4a3b205034a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,7 +17,6 @@
#include "absl/base/attributes.h"
#ifdef _WIN32
-#include <shlwapi.h>
#include <windows.h>
#else
#include <fcntl.h>
@@ -40,6 +39,7 @@
#endif
#include <string.h>
+
#include <cassert>
#include <cstdint>
#include <cstdio>
@@ -51,17 +51,16 @@
#include <vector>
#include "absl/base/call_once.h"
+#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
#include "absl/base/internal/unscaledcycleclock.h"
+#include "absl/base/thread_annotations.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
-static once_flag init_system_info_once;
-static int num_cpus = 0;
-static double nominal_cpu_frequency = 1.0; // 0.0 might be dangerous.
-
static int GetNumCPUs() {
#if defined(__myriad2__)
return 1;
@@ -76,16 +75,32 @@ static int GetNumCPUs() {
#if defined(_WIN32)
static double GetNominalCPUFrequency() {
- DWORD data;
- DWORD data_size = sizeof(data);
- #pragma comment(lib, "shlwapi.lib") // For SHGetValue().
- if (SUCCEEDED(
- SHGetValueA(HKEY_LOCAL_MACHINE,
- "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
- "~MHz", nullptr, &data, &data_size))) {
- return data * 1e6; // Value is MHz.
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ // UWP apps don't have access to the registry and currently don't provide an
+ // API informing about CPU nominal frequency.
+ return 1.0;
+#else
+#pragma comment(lib, "advapi32.lib") // For Reg* functions.
+ HKEY key;
+ // Use the Reg* functions rather than the SH functions because shlwapi.dll
+ // pulls in gdi32.dll which makes process destruction much more costly.
+ if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+ "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0,
+ KEY_READ, &key) == ERROR_SUCCESS) {
+ DWORD type = 0;
+ DWORD data = 0;
+ DWORD data_size = sizeof(data);
+ auto result = RegQueryValueExA(key, "~MHz", 0, &type,
+ reinterpret_cast<LPBYTE>(&data), &data_size);
+ RegCloseKey(key);
+ if (result == ERROR_SUCCESS && type == REG_DWORD &&
+ data_size == sizeof(data)) {
+ return data * 1e6; // Value is MHz.
+ }
}
return 1.0;
+#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
}
#elif defined(CTL_HW) && defined(HW_CPU_FREQ)
@@ -256,28 +271,34 @@ static double GetNominalCPUFrequency() {
#endif
-// InitializeSystemInfo() may be called before main() and before
-// malloc is properly initialized, therefore this must not allocate
-// memory.
-static void InitializeSystemInfo() {
- num_cpus = GetNumCPUs();
- nominal_cpu_frequency = GetNominalCPUFrequency();
-}
+ABSL_CONST_INIT static once_flag init_num_cpus_once;
+ABSL_CONST_INIT static int num_cpus = 0;
+// NumCPUs() may be called before main() and before malloc is properly
+// initialized, therefore this must not allocate memory.
int NumCPUs() {
- base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+ base_internal::LowLevelCallOnce(
+ &init_num_cpus_once, []() { num_cpus = GetNumCPUs(); });
return num_cpus;
}
+// A default frequency of 0.0 might be dangerous if it is used in division.
+ABSL_CONST_INIT static once_flag init_nominal_cpu_frequency_once;
+ABSL_CONST_INIT static double nominal_cpu_frequency = 1.0;
+
+// NominalCPUFrequency() may be called before main() and before malloc is
+// properly initialized, therefore this must not allocate memory.
double NominalCPUFrequency() {
- base_internal::LowLevelCallOnce(&init_system_info_once, InitializeSystemInfo);
+ base_internal::LowLevelCallOnce(
+ &init_nominal_cpu_frequency_once,
+ []() { nominal_cpu_frequency = GetNominalCPUFrequency(); });
return nominal_cpu_frequency;
}
#if defined(_WIN32)
pid_t GetTID() {
- return GetCurrentThreadId();
+ return pid_t{GetCurrentThreadId()};
}
#elif defined(__linux__)
@@ -325,15 +346,16 @@ pid_t GetTID() {
#else
// Fallback implementation of GetTID using pthread_getspecific.
-static once_flag tid_once;
-static pthread_key_t tid_key;
-static absl::base_internal::SpinLock tid_lock(
- absl::base_internal::kLinkerInitialized);
+ABSL_CONST_INIT static once_flag tid_once;
+ABSL_CONST_INIT static pthread_key_t tid_key;
+ABSL_CONST_INIT static absl::base_internal::SpinLock tid_lock(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
// We set a bit per thread in this array to indicate that an ID is in
// use. ID 0 is unused because it is the default value returned by
// pthread_getspecific().
-static std::vector<uint32_t>* tid_array GUARDED_BY(tid_lock) = nullptr;
+ABSL_CONST_INIT static std::vector<uint32_t> *tid_array
+ ABSL_GUARDED_BY(tid_lock) = nullptr;
static constexpr int kBitsPerWord = 32; // tid_array is uint32_t.
// Returns the TID to tid_array.
@@ -400,5 +422,18 @@ pid_t GetTID() {
#endif
+// GetCachedTID() caches the thread ID in thread-local storage (which is a
+// userspace construct) to avoid unnecessary system calls. Without this caching,
+// it can take roughly 98ns, while it takes roughly 1ns with this caching.
+pid_t GetCachedTID() {
+#ifdef ABSL_HAVE_THREAD_LOCAL
+ static thread_local pid_t thread_id = GetTID();
+ return thread_id;
+#else
+ return GetTID();
+#endif // ABSL_HAVE_THREAD_LOCAL
+}
+
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.h
index 5bd1c500bd5..119cf1f0e85 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,13 +26,15 @@
#ifndef _WIN32
#include <sys/types.h>
-#else
-#include <intsafe.h>
#endif
+#include <cstdint>
+
+#include "absl/base/config.h"
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Nominal core processor cycles per second of each processor. This is _not_
@@ -51,13 +53,22 @@ int NumCPUs();
// On Linux, you may send a signal to the resulting ID with kill(). However,
// it is recommended for portability that you use pthread_kill() instead.
#ifdef _WIN32
-// On Windows, process id and thread id are of the same type according to
-// the return types of GetProcessId() and GetThreadId() are both DWORD.
-using pid_t = DWORD;
+// On Windows, process id and thread id are of the same type according to the
+// return types of GetProcessId() and GetThreadId() are both DWORD, an unsigned
+// 32-bit type.
+using pid_t = uint32_t;
#endif
pid_t GetTID();
+// Like GetTID(), but caches the result in thread-local storage in order
+// to avoid unnecessary system calls. Note that there are some cases where
+// one must call through to GetTID directly, which is why this exists as a
+// separate function. For example, GetCachedTID() is not safe to call in
+// an asynchronous signal-handling context nor right after a call to fork().
+pid_t GetCachedTID();
+
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_SYSINFO_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo_test.cc
index e0d9aab9bc2..5f9e45f6aa8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/sysinfo_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,6 +28,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
@@ -36,17 +37,28 @@ TEST(SysinfoTest, NumCPUs) {
<< "NumCPUs() should not have the default value of 0";
}
+// Ensure that NominalCPUFrequency returns a reasonable value, or 1.00 on
+// platforms where the CPU frequency is not available through sysfs.
+//
+// POWER is particularly problematic here; some Linux kernels expose the CPU
+// frequency, while others do not. Since we can't predict a priori what a given
+// machine is going to do, just disable this test on POWER on Linux.
+#if !(defined(__linux) && (defined(__ppc64__) || defined(__PPC64__)))
TEST(SysinfoTest, NominalCPUFrequency) {
-#if !(defined(__aarch64__) && defined(__linux__))
- EXPECT_GE(NominalCPUFrequency(), 1000.0)
- << "NominalCPUFrequency() did not return a reasonable value";
-#else
- // TODO(absl-team): Aarch64 cannot read the CPU frequency from sysfs, so we
- // get back 1.0. Fix once the value is available.
+ // Linux only exposes the CPU frequency on certain architectures, and
+ // Emscripten doesn't expose it at all.
+#if defined(__linux__) && \
+ (defined(__aarch64__) || defined(__hppa__) || defined(__mips__) || \
+ defined(__riscv) || defined(__s390x__)) || \
+ defined(__EMSCRIPTEN__)
EXPECT_EQ(NominalCPUFrequency(), 1.0)
<< "CPU frequency detection was fixed! Please update unittest.";
+#else
+ EXPECT_GE(NominalCPUFrequency(), 1000.0)
+ << "NominalCPUFrequency() did not return a reasonable value";
#endif
}
+#endif
TEST(SysinfoTest, GetTID) {
EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test.
@@ -58,8 +70,8 @@ TEST(SysinfoTest, GetTID) {
#endif
// Test that TIDs are unique to each thread.
// Uses a few loops to exercise implementations that reallocate IDs.
- for (int i = 0; i < 32; ++i) {
- constexpr int kNumThreads = 64;
+ for (int i = 0; i < 10; ++i) {
+ constexpr int kNumThreads = 10;
Barrier all_threads_done(kNumThreads);
std::vector<std::thread> threads;
@@ -95,4 +107,5 @@ TEST(SysinfoTest, LinuxGetTID) {
} // namespace
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_annotations.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_annotations.h
new file mode 100644
index 00000000000..4dab6a9c150
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_annotations.h
@@ -0,0 +1,271 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: thread_annotations.h
+// -----------------------------------------------------------------------------
+//
+// WARNING: This is a backwards compatible header and it will be removed after
+// the migration to prefixed thread annotations is finished; please include
+// "absl/base/thread_annotations.h".
+//
+// This header file contains macro definitions for thread safety annotations
+// that allow developers to document the locking policies of multi-threaded
+// code. The annotations can also help program analysis tools to identify
+// potential thread safety issues.
+//
+// These annotations are implemented using compiler attributes. Using the macros
+// defined here instead of raw attributes allow for portability and future
+// compatibility.
+//
+// When referring to mutexes in the arguments of the attributes, you should
+// use variable names or more complex expressions (e.g. my_object->mutex_)
+// that evaluate to a concrete mutex object whenever possible. If the mutex
+// you want to refer to is not in scope, you may use a member pointer
+// (e.g. &MyClass::mutex_) to refer to a mutex in some (unknown) object.
+
+#ifndef ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
+#define ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
+
+#if defined(__clang__)
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
+#else
+#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
+#endif
+
+// GUARDED_BY()
+//
+// Documents if a shared field or global variable needs to be protected by a
+// mutex. GUARDED_BY() allows the user to specify a particular mutex that
+// should be held when accessing the annotated variable.
+//
+// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to
+// local variables, a local variable and its associated mutex can often be
+// combined into a small class or struct, thereby allowing the annotation.
+//
+// Example:
+//
+// class Foo {
+// Mutex mu_;
+// int p1_ GUARDED_BY(mu_);
+// ...
+// };
+#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+
+// PT_GUARDED_BY()
+//
+// Documents if the memory location pointed to by a pointer should be guarded
+// by a mutex when dereferencing the pointer.
+//
+// Example:
+// class Foo {
+// Mutex mu_;
+// int *p1_ PT_GUARDED_BY(mu_);
+// ...
+// };
+//
+// Note that a pointer variable to a shared memory location could itself be a
+// shared variable.
+//
+// Example:
+//
+// // `q_`, guarded by `mu1_`, points to a shared memory location that is
+// // guarded by `mu2_`:
+// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
+#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+
+// ACQUIRED_AFTER() / ACQUIRED_BEFORE()
+//
+// Documents the acquisition order between locks that can be held
+// simultaneously by a thread. For any two locks that need to be annotated
+// to establish an acquisition order, only one of them needs the annotation.
+// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
+// and ACQUIRED_BEFORE.)
+//
+// As with GUARDED_BY, this is only applicable to mutexes that are shared
+// fields or global variables.
+//
+// Example:
+//
+// Mutex m1_;
+// Mutex m2_ ACQUIRED_AFTER(m1_);
+#define ACQUIRED_AFTER(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+#define ACQUIRED_BEFORE(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+
+// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED()
+//
+// Documents a function that expects a mutex to be held prior to entry.
+// The mutex is expected to be held both on entry to, and exit from, the
+// function.
+//
+// An exclusive lock allows read-write access to the guarded data member(s), and
+// only one thread can acquire a lock exclusively at any one time. A shared lock
+// allows read-only access, and any number of threads can acquire a shared lock
+// concurrently.
+//
+// Generally, non-const methods should be annotated with
+// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
+// SHARED_LOCKS_REQUIRED.
+//
+// Example:
+//
+// Mutex mu1, mu2;
+// int a GUARDED_BY(mu1);
+// int b GUARDED_BY(mu2);
+//
+// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
+// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
+#define EXCLUSIVE_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
+
+#define SHARED_LOCKS_REQUIRED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
+
+// LOCKS_EXCLUDED()
+//
+// Documents the locks acquired in the body of the function. These locks
+// cannot be held when calling this function (as Abseil's `Mutex` locks are
+// non-reentrant).
+#define LOCKS_EXCLUDED(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+// LOCK_RETURNED()
+//
+// Documents a function that returns a mutex without acquiring it. For example,
+// a public getter method that returns a pointer to a private mutex should
+// be annotated with LOCK_RETURNED.
+#define LOCK_RETURNED(x) \
+ THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+// LOCKABLE
+//
+// Documents if a class/type is a lockable type (such as the `Mutex` class).
+#define LOCKABLE \
+ THREAD_ANNOTATION_ATTRIBUTE__(lockable)
+
+// SCOPED_LOCKABLE
+//
+// Documents if a class does RAII locking (such as the `MutexLock` class).
+// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is
+// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
+// arguments; the analysis will assume that the destructor unlocks whatever the
+// constructor locked.
+#define SCOPED_LOCKABLE \
+ THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+// EXCLUSIVE_LOCK_FUNCTION()
+//
+// Documents functions that acquire a lock in the body of a function, and do
+// not release it.
+#define EXCLUSIVE_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
+
+// SHARED_LOCK_FUNCTION()
+//
+// Documents functions that acquire a shared (reader) lock in the body of a
+// function, and do not release it.
+#define SHARED_LOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
+
+// UNLOCK_FUNCTION()
+//
+// Documents functions that expect a lock to be held on entry to the function,
+// and release it in the body of the function.
+#define UNLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
+
+// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION()
+//
+// Documents functions that try to acquire a lock, and return success or failure
+// (or a non-boolean value that can be interpreted as a boolean).
+// The first argument should be `true` for functions that return `true` on
+// success, or `false` for functions that return `false` on success. The second
+// argument specifies the mutex that is locked on success. If unspecified, this
+// mutex is assumed to be `this`.
+#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
+
+#define SHARED_TRYLOCK_FUNCTION(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
+
+// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK()
+//
+// Documents functions that dynamically check to see if a lock is held, and fail
+// if it is not held.
+#define ASSERT_EXCLUSIVE_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
+
+#define ASSERT_SHARED_LOCK(...) \
+ THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
+
+// NO_THREAD_SAFETY_ANALYSIS
+//
+// Turns off thread safety checking within the body of a particular function.
+// This annotation is used to mark functions that are known to be correct, but
+// the locking behavior is more complicated than the analyzer can handle.
+#define NO_THREAD_SAFETY_ANALYSIS \
+ THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+
+//------------------------------------------------------------------------------
+// Tool-Supplied Annotations
+//------------------------------------------------------------------------------
+
+// TS_UNCHECKED should be placed around lock expressions that are not valid
+// C++ syntax, but which are present for documentation purposes. These
+// annotations will be ignored by the analysis.
+#define TS_UNCHECKED(x) ""
+
+// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
+// It is used by automated tools to mark and disable invalid expressions.
+// The annotation should either be fixed, or changed to TS_UNCHECKED.
+#define TS_FIXME(x) ""
+
+// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
+// a particular function. However, this attribute is used to mark functions
+// that are incorrect and need to be fixed. It is used by automated tools to
+// avoid breaking the build when the analysis is updated.
+// Code owners are expected to eventually fix the routine.
+#define NO_THREAD_SAFETY_ANALYSIS_FIXME NO_THREAD_SAFETY_ANALYSIS
+
+// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY
+// annotation that needs to be fixed, because it is producing thread safety
+// warning. It disables the GUARDED_BY.
+#define GUARDED_BY_FIXME(x)
+
+// Disables warnings for a single read operation. This can be used to avoid
+// warnings when it is known that the read is not actually involved in a race,
+// but the compiler cannot confirm that.
+#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
+
+
+namespace thread_safety_analysis {
+
+// Takes a reference to a guarded data member, and returns an unguarded
+// reference.
+template <typename T>
+inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
+ return v;
+}
+
+template <typename T>
+inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
+ return v;
+}
+
+} // namespace thread_safety_analysis
+
+#endif // ABSL_BASE_INTERNAL_THREAD_ANNOTATIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.cc
index cff9c1b4f4d..6ea010ed0d3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,11 +23,13 @@
#include <cassert>
#include <memory>
+#include "absl/base/attributes.h"
#include "absl/base/call_once.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
#if ABSL_THREAD_IDENTITY_MODE != ABSL_THREAD_IDENTITY_MODE_USE_CPP11
@@ -52,10 +54,17 @@ void AllocateThreadIdentityKey(ThreadIdentityReclaimerFunction reclaimer) {
// exist within a process (via dlopen() or similar), references to
// thread_identity_ptr from each instance of the code will refer to
// *different* instances of this ptr.
-#ifdef __GNUC__
+// Apple platforms have the visibility attribute, but issue a compile warning
+// that protected visibility is unsupported.
+#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
__attribute__((visibility("protected")))
-#endif // __GNUC__
- ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr;
+#endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
+#if ABSL_PER_THREAD_TLS
+// Prefer __thread to thread_local as benchmarks indicate it is a bit faster.
+ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr = nullptr;
+#elif defined(ABSL_HAVE_THREAD_LOCAL)
+thread_local ThreadIdentity* thread_identity_ptr = nullptr;
+#endif // ABSL_PER_THREAD_TLS
#endif // TLS or CPP11
void SetCurrentThreadIdentity(
@@ -69,8 +78,8 @@ void SetCurrentThreadIdentity(
absl::call_once(init_thread_identity_key_once, AllocateThreadIdentityKey,
reclaimer);
-#ifdef __EMSCRIPTEN__
- // Emscripten PThread implementation does not support signals.
+#if defined(__EMSCRIPTEN__) || defined(__MINGW32__)
+ // Emscripten and MinGW pthread implementations does not support signals.
// See https://kripken.github.io/emscripten-site/docs/porting/pthreads.html
// for more information.
pthread_setspecific(thread_identity_pthread_key,
@@ -89,7 +98,7 @@ void SetCurrentThreadIdentity(
pthread_setspecific(thread_identity_pthread_key,
reinterpret_cast<void*>(identity));
pthread_sigmask(SIG_SETMASK, &curr_signals, nullptr);
-#endif // !__EMSCRIPTEN__
+#endif // !__EMSCRIPTEN__ && !__MINGW32__
#elif ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS
// NOTE: Not async-safe. But can be open-coded.
@@ -107,6 +116,18 @@ void SetCurrentThreadIdentity(
#endif
}
+#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
+ ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+
+// Please see the comment on `CurrentThreadIdentityIfPresent` in
+// thread_identity.h. Because DLLs cannot expose thread_local variables in
+// headers, we opt for the correct-but-slower option of placing the definition
+// of this function only in a translation unit inside DLL.
+#if defined(ABSL_BUILD_DLL) || defined(ABSL_CONSUME_DLL)
+ThreadIdentity* CurrentThreadIdentityIfPresent() { return thread_identity_ptr; }
+#endif
+#endif
+
void ClearCurrentThreadIdentity() {
#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
@@ -130,4 +151,5 @@ ThreadIdentity* CurrentThreadIdentityIfPresent() {
#endif
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.h
index a51722f9d82..9ee651a3a6e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,9 +30,12 @@
#include <atomic>
#include <cstdint>
+#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
struct SynchLocksHeld;
struct SynchWaitParams;
@@ -42,9 +45,9 @@ namespace base_internal {
class SpinLock;
struct ThreadIdentity;
-// Used by the implementation of base::Mutex and base::CondVar.
+// Used by the implementation of absl::Mutex and absl::CondVar.
struct PerThreadSynch {
- // The internal representation of base::Mutex and base::CondVar rely
+ // The internal representation of absl::Mutex and absl::CondVar rely
// on the alignment of PerThreadSynch. Both store the address of the
// PerThreadSynch in the high-order bits of their internal state,
// which means the low kLowZeroBits of the address of PerThreadSynch
@@ -67,30 +70,28 @@ struct PerThreadSynch {
// is using this PerThreadSynch as a terminator. Its
// skip field must not be filled in because the loop
// might then skip over the terminator.
-
- // The wait parameters of the current wait. waitp is null if the
- // thread is not waiting. Transitions from null to non-null must
- // occur before the enqueue commit point (state = kQueued in
- // Enqueue() and CondVarEnqueue()). Transitions from non-null to
- // null must occur after the wait is finished (state = kAvailable in
- // Mutex::Block() and CondVar::WaitCommon()). This field may be
- // changed only by the thread that describes this PerThreadSynch. A
- // special case is Fer(), which calls Enqueue() on another thread,
- // but with an identical SynchWaitParams pointer, thus leaving the
- // pointer unchanged.
- SynchWaitParams *waitp;
-
- bool suppress_fatal_errors; // If true, try to proceed even in the face of
- // broken invariants. This is used within fatal
- // signal handlers to improve the chances of
- // debug logging information being output
- // successfully.
-
- intptr_t readers; // Number of readers in mutex.
- int priority; // Priority of thread (updated every so often).
-
- // When priority will next be read (cycles).
- int64_t next_priority_read_cycles;
+ bool wake; // This thread is to be woken from a Mutex.
+ // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
+ // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
+ //
+ // The value of "x->cond_waiter" is meaningless if "x" is not on a
+ // Mutex waiter list.
+ bool cond_waiter;
+ bool maybe_unlocking; // Valid at head of Mutex waiter queue;
+ // true if UnlockSlow could be searching
+ // for a waiter to wake. Used for an optimization
+ // in Enqueue(). true is always a valid value.
+ // Can be reset to false when the unlocker or any
+ // writer releases the lock, or a reader fully
+ // releases the lock. It may not be set to false
+ // by a reader that decrements the count to
+ // non-zero. protected by mutex spinlock
+ bool suppress_fatal_errors; // If true, try to proceed even in the face
+ // of broken invariants. This is used within
+ // fatal signal handlers to improve the
+ // chances of debug logging information being
+ // output successfully.
+ int priority; // Priority of thread (updated every so often).
// State values:
// kAvailable: This PerThreadSynch is available.
@@ -109,30 +110,30 @@ struct PerThreadSynch {
};
std::atomic<State> state;
- bool maybe_unlocking; // Valid at head of Mutex waiter queue;
- // true if UnlockSlow could be searching
- // for a waiter to wake. Used for an optimization
- // in Enqueue(). true is always a valid value.
- // Can be reset to false when the unlocker or any
- // writer releases the lock, or a reader fully releases
- // the lock. It may not be set to false by a reader
- // that decrements the count to non-zero.
- // protected by mutex spinlock
+ // The wait parameters of the current wait. waitp is null if the
+ // thread is not waiting. Transitions from null to non-null must
+ // occur before the enqueue commit point (state = kQueued in
+ // Enqueue() and CondVarEnqueue()). Transitions from non-null to
+ // null must occur after the wait is finished (state = kAvailable in
+ // Mutex::Block() and CondVar::WaitCommon()). This field may be
+ // changed only by the thread that describes this PerThreadSynch. A
+ // special case is Fer(), which calls Enqueue() on another thread,
+ // but with an identical SynchWaitParams pointer, thus leaving the
+ // pointer unchanged.
+ SynchWaitParams* waitp;
- bool wake; // This thread is to be woken from a Mutex.
+ intptr_t readers; // Number of readers in mutex.
- // If "x" is on a waiter list for a mutex, "x->cond_waiter" is true iff the
- // waiter is waiting on the mutex as part of a CV Wait or Mutex Await.
- //
- // The value of "x->cond_waiter" is meaningless if "x" is not on a
- // Mutex waiter list.
- bool cond_waiter;
+ // When priority will next be read (cycles).
+ int64_t next_priority_read_cycles;
// Locks held; used during deadlock detection.
// Allocated in Synch_GetAllLocks() and freed in ReclaimThreadIdentity().
SynchLocksHeld *all_locks;
};
+// The instances of this class are allocated in NewThreadIdentity() with an
+// alignment of PerThreadSynch::kAlignment.
struct ThreadIdentity {
// Must be the first member. The Mutex implementation requires that
// the PerThreadSynch object associated with each thread is
@@ -142,7 +143,7 @@ struct ThreadIdentity {
// Private: Reserved for absl::synchronization_internal::Waiter.
struct WaiterState {
- char data[128];
+ alignas(void*) char data[128];
} waiter_state;
// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
@@ -208,9 +209,11 @@ void ClearCurrentThreadIdentity();
#error ABSL_THREAD_IDENTITY_MODE cannot be direcly set
#elif defined(ABSL_FORCE_THREAD_IDENTITY_MODE)
#define ABSL_THREAD_IDENTITY_MODE ABSL_FORCE_THREAD_IDENTITY_MODE
-#elif defined(_WIN32)
+#elif defined(_WIN32) && !defined(__MINGW32__)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
+#elif defined(__APPLE__) && defined(ABSL_HAVE_THREAD_LOCAL)
+#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
+#elif ABSL_PER_THREAD_TLS && defined(__GOOGLE_GRTE_VERSION__) && \
(__GOOGLE_GRTE_VERSION__ >= 20140228L)
// Support for async-safe TLS was specifically added in GRTEv4. It's not
// present in the upstream eglibc.
@@ -224,11 +227,26 @@ void ClearCurrentThreadIdentity();
#if ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_TLS || \
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity* thread_identity_ptr;
+#if ABSL_PER_THREAD_TLS
+ABSL_CONST_INIT extern ABSL_PER_THREAD_TLS_KEYWORD ThreadIdentity*
+ thread_identity_ptr;
+#elif defined(ABSL_HAVE_THREAD_LOCAL)
+ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
+#else
+#error Thread-local storage not detected on this platform
+#endif
+// thread_local variables cannot be in headers exposed by DLLs. However, it is
+// important for performance reasons in general that
+// `CurrentThreadIdentityIfPresent` be inlined. This is not possible across a
+// DLL boundary so, with DLLs, we opt to have the function not be inlined. Note
+// that `CurrentThreadIdentityIfPresent` is declared above so we can exclude
+// this entire inline definition when compiling as a DLL.
+#if !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL)
inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
return thread_identity_ptr;
}
+#endif
#elif ABSL_THREAD_IDENTITY_MODE != \
ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
@@ -236,5 +254,7 @@ inline ThreadIdentity* CurrentThreadIdentityIfPresent() {
#endif
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_BASE_INTERNAL_THREAD_IDENTITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc
index 242522b4418..0ae10f2b1e8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_test.cc
index ecb8af68982..46a6f743462 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/thread_identity_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,17 +21,18 @@
#include "absl/base/attributes.h"
#include "absl/base/internal/spinlock.h"
#include "absl/base/macros.h"
+#include "absl/base/thread_annotations.h"
#include "absl/synchronization/internal/per_thread_sem.h"
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
-// protects num_identities_reused
-static absl::base_internal::SpinLock map_lock(
- absl::base_internal::kLinkerInitialized);
-static int num_identities_reused;
+ABSL_CONST_INIT static absl::base_internal::SpinLock map_lock(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static int num_identities_reused ABSL_GUARDED_BY(map_lock);
static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);
@@ -74,7 +75,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
// - If a thread implementation chooses to recycle threads, that
// correct re-initialization occurs.
static const int kNumLoops = 3;
- static const int kNumThreads = 400;
+ static const int kNumThreads = 32;
for (int iter = 0; iter < kNumLoops; iter++) {
std::vector<std::thread> threads;
for (int i = 0; i < kNumThreads; ++i) {
@@ -89,6 +90,7 @@ TEST(ThreadIdentityTest, BasicIdentityWorksThreaded) {
// We should have recycled ThreadIdentity objects above; while (external)
// library threads allocating their own identities may preclude some
// reuse, we should have sufficient repetitions to exclude this.
+ absl::base_internal::SpinLockHolder l(&map_lock);
EXPECT_LT(kNumThreads, num_identities_reused);
}
@@ -123,4 +125,5 @@ TEST(ThreadIdentityTest, ReusedThreadIdentityMutexTest) {
} // namespace
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.cc
index 1c40efcb3cd..c260ff1eed6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,89 +18,195 @@
#include <functional>
#include <new>
#include <stdexcept>
+
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
+// NOTE: The various STL exception throwing functions are placed within the
+// #ifdef blocks so the symbols aren't exposed on platforms that don't support
+// them, such as the Android NDK. For example, ANGLE fails to link when building
+// within AOSP without them, since the STL functions don't exist.
namespace {
+#ifdef ABSL_HAVE_EXCEPTIONS
template <typename T>
[[noreturn]] void Throw(const T& error) {
-#ifdef ABSL_HAVE_EXCEPTIONS
throw error;
-#else
- ABSL_RAW_LOG(FATAL, "%s", error.what());
- std::abort();
-#endif
}
+#endif
} // namespace
void ThrowStdLogicError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::logic_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdLogicError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::logic_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdInvalidArgument(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::invalid_argument(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdInvalidArgument(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::invalid_argument(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdDomainError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::domain_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdDomainError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::domain_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdLengthError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::length_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdLengthError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::length_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdOutOfRange(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::out_of_range(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdOutOfRange(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::out_of_range(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdRuntimeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::runtime_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdRuntimeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::runtime_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdRangeError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::range_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdRangeError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::range_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdOverflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::overflow_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdOverflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::overflow_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
void ThrowStdUnderflowError(const std::string& what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::underflow_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg.c_str());
+ std::abort();
+#endif
}
void ThrowStdUnderflowError(const char* what_arg) {
+#ifdef ABSL_HAVE_EXCEPTIONS
Throw(std::underflow_error(what_arg));
+#else
+ ABSL_RAW_LOG(FATAL, "%s", what_arg);
+ std::abort();
+#endif
}
-void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
+void ThrowStdBadFunctionCall() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ Throw(std::bad_function_call());
+#else
+ std::abort();
+#endif
+}
-void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
+void ThrowStdBadAlloc() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ Throw(std::bad_alloc());
+#else
+ std::abort();
+#endif
+}
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.h
index 70e2d7709e5..075f5272543 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/throw_delegate.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,7 +19,10 @@
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// Helper functions that allow throwing exceptions consistently from anywhere.
@@ -66,6 +69,7 @@ namespace base_internal {
// [[noreturn]] void ThrowStdBadArrayNewLength();
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_BASE_INTERNAL_THROW_DELEGATE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/tsan_mutex_interface.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
index 6bb4faedb87..39207d8a5c4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,6 +19,8 @@
#ifndef ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
#define ABSL_BASE_INTERNAL_TSAN_MUTEX_INTERFACE_H_
+#include "absl/base/config.h"
+
// ABSL_INTERNAL_HAVE_TSAN_INTERFACE
// Macro intended only for internal use.
//
@@ -28,7 +30,7 @@
#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
#endif
-#if defined(THREAD_SANITIZER) && defined(__has_include)
+#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
#if __has_include(<sanitizer/tsan_interface.h>)
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unaligned_access.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unaligned_access.h
index d2aa8853f43..093dd9b499f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unaligned_access.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unaligned_access.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,255 +18,21 @@
#define ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
#include <string.h>
+
#include <cstdint>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
// unaligned APIs
// Portable handling of unaligned loads, stores, and copies.
-// On some platforms, like ARM, the copy functions can be more efficient
-// then a load and a store.
-//
-// It is possible to implement all of these these using constant-length memcpy
-// calls, which is portable and will usually be inlined into simple loads and
-// stores if the architecture supports it. However, such inlining usually
-// happens in a pass that's quite late in compilation, which means the resulting
-// loads and stores cannot participate in many other optimizations, leading to
-// overall worse code.
// The unaligned API is C++ only. The declarations use C++ features
// (namespaces, inline) which are absent or incompatible in C.
#if defined(__cplusplus)
-
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
- defined(MEMORY_SANITIZER)
-// Consider we have an unaligned load/store of 4 bytes from address 0x...05.
-// AddressSanitizer will treat it as a 3-byte access to the range 05:07 and
-// will miss a bug if 08 is the first unaddressable byte.
-// ThreadSanitizer will also treat this as a 3-byte access to 05:07 and will
-// miss a race between this access and some other accesses to 08.
-// MemorySanitizer will correctly propagate the shadow on unaligned stores
-// and correctly report bugs on unaligned loads, but it may not properly
-// update and report the origin of the uninitialized memory.
-// For all three tools, replacing an unaligned access with a tool-specific
-// callback solves the problem.
-
-// Make sure uint16_t/uint32_t/uint64_t are defined.
-#include <stdint.h>
-
-extern "C" {
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-void __sanitizer_unaligned_store64(void *p, uint64_t v);
-} // extern "C"
-
-namespace absl {
-namespace base_internal {
-
-inline uint16_t UnalignedLoad16(const void *p) {
- return __sanitizer_unaligned_load16(p);
-}
-
-inline uint32_t UnalignedLoad32(const void *p) {
- return __sanitizer_unaligned_load32(p);
-}
-
-inline uint64_t UnalignedLoad64(const void *p) {
- return __sanitizer_unaligned_load64(p);
-}
-
-inline void UnalignedStore16(void *p, uint16_t v) {
- __sanitizer_unaligned_store16(p, v);
-}
-
-inline void UnalignedStore32(void *p, uint32_t v) {
- __sanitizer_unaligned_store32(p, v);
-}
-
-inline void UnalignedStore64(void *p, uint64_t v) {
- __sanitizer_unaligned_store64(p, v);
-}
-
-} // namespace base_internal
-} // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
- (absl::base_internal::UnalignedLoad16(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
- (absl::base_internal::UnalignedLoad32(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
- (absl::base_internal::UnalignedLoad64(_p))
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
- (absl::base_internal::UnalignedStore16(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
- (absl::base_internal::UnalignedStore32(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
- (absl::base_internal::UnalignedStore64(_p, _val))
-
-#elif defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ABSL_FORCE_ALIGNED_ACCESS)
-
-namespace absl {
-namespace base_internal {
-
-inline uint16_t UnalignedLoad16(const void *p) {
- uint16_t t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint32_t UnalignedLoad32(const void *p) {
- uint32_t t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline uint64_t UnalignedLoad64(const void *p) {
- uint64_t t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline void UnalignedStore16(void *p, uint16_t v) { memcpy(p, &v, sizeof v); }
-
-inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
-
-inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
-
-} // namespace base_internal
-} // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
- (absl::base_internal::UnalignedLoad16(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
- (absl::base_internal::UnalignedLoad32(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
- (absl::base_internal::UnalignedLoad64(_p))
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
- (absl::base_internal::UnalignedStore16(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
- (absl::base_internal::UnalignedStore32(_p, _val))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
- (absl::base_internal::UnalignedStore64(_p, _val))
-
-#elif defined(__x86_64__) || defined(_M_X64) || defined(__i386) || \
- defined(_M_IX86) || defined(__ppc__) || defined(__PPC__) || \
- defined(__ppc64__) || defined(__PPC64__)
-
-// x86 and x86-64 can perform unaligned loads/stores directly;
-// modern PowerPC hardware can also do unaligned integer loads and stores;
-// but note: the FPU still sends unaligned loads and stores to a trap handler!
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
- (*reinterpret_cast<const uint16_t *>(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
- (*reinterpret_cast<const uint32_t *>(_p))
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
- (*reinterpret_cast<const uint64_t *>(_p))
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
- (*reinterpret_cast<uint16_t *>(_p) = (_val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
- (*reinterpret_cast<uint32_t *>(_p) = (_val))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
- (*reinterpret_cast<uint64_t *>(_p) = (_val))
-
-#elif defined(__arm__) && \
- !defined(__ARM_ARCH_5__) && \
- !defined(__ARM_ARCH_5T__) && \
- !defined(__ARM_ARCH_5TE__) && \
- !defined(__ARM_ARCH_5TEJ__) && \
- !defined(__ARM_ARCH_6__) && \
- !defined(__ARM_ARCH_6J__) && \
- !defined(__ARM_ARCH_6K__) && \
- !defined(__ARM_ARCH_6Z__) && \
- !defined(__ARM_ARCH_6ZK__) && \
- !defined(__ARM_ARCH_6T2__)
-
-
-// ARMv7 and newer support native unaligned accesses, but only of 16-bit
-// and 32-bit values (not 64-bit); older versions either raise a fatal signal,
-// do an unaligned read and rotate the words around a bit, or do the reads very
-// slowly (trip through kernel mode). There's no simple #define that says just
-// "ARMv7 or higher", so we have to filter away all ARMv5 and ARMv6
-// sub-architectures. Newer gcc (>= 4.6) set an __ARM_FEATURE_ALIGNED #define,
-// so in time, maybe we can move on to that.
-//
-// This is a mess, but there's not much we can do about it.
-//
-// To further complicate matters, only LDR instructions (single reads) are
-// allowed to be unaligned, not LDRD (two reads) or LDM (many reads). Unless we
-// explicitly tell the compiler that these accesses can be unaligned, it can and
-// will combine accesses. On armcc, the way to signal this is done by accessing
-// through the type (uint32_t __packed *), but GCC has no such attribute
-// (it ignores __attribute__((packed)) on individual variables). However,
-// we can tell it that a _struct_ is unaligned, which has the same effect,
-// so we do that.
-
-namespace absl {
-namespace base_internal {
-
-struct Unaligned16Struct {
- uint16_t value;
- uint8_t dummy; // To make the size non-power-of-two.
-} ABSL_ATTRIBUTE_PACKED;
-
-struct Unaligned32Struct {
- uint32_t value;
- uint8_t dummy; // To make the size non-power-of-two.
-} ABSL_ATTRIBUTE_PACKED;
-
-} // namespace base_internal
-} // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
- ((reinterpret_cast<const ::absl::base_internal::Unaligned16Struct *>(_p)) \
- ->value)
-#define ABSL_INTERNAL_UNALIGNED_LOAD32(_p) \
- ((reinterpret_cast<const ::absl::base_internal::Unaligned32Struct *>(_p)) \
- ->value)
-
-#define ABSL_INTERNAL_UNALIGNED_STORE16(_p, _val) \
- ((reinterpret_cast< ::absl::base_internal::Unaligned16Struct *>(_p)) \
- ->value = (_val))
-#define ABSL_INTERNAL_UNALIGNED_STORE32(_p, _val) \
- ((reinterpret_cast< ::absl::base_internal::Unaligned32Struct *>(_p)) \
- ->value = (_val))
-
-namespace absl {
-namespace base_internal {
-
-inline uint64_t UnalignedLoad64(const void *p) {
- uint64_t t;
- memcpy(&t, p, sizeof t);
- return t;
-}
-
-inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
-
-} // namespace base_internal
-} // namespace absl
-
-#define ABSL_INTERNAL_UNALIGNED_LOAD64(_p) \
- (absl::base_internal::UnalignedLoad64(_p))
-#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
- (absl::base_internal::UnalignedStore64(_p, _val))
-
-#else
-
-// ABSL_INTERNAL_NEED_ALIGNED_LOADS is defined when the underlying platform
-// doesn't support unaligned access.
-#define ABSL_INTERNAL_NEED_ALIGNED_LOADS
-
-// These functions are provided for architectures that don't support
-// unaligned loads and stores.
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
inline uint16_t UnalignedLoad16(const void *p) {
@@ -294,6 +60,7 @@ inline void UnalignedStore32(void *p, uint32_t v) { memcpy(p, &v, sizeof v); }
inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#define ABSL_INTERNAL_UNALIGNED_LOAD16(_p) \
@@ -310,8 +77,6 @@ inline void UnalignedStore64(void *p, uint64_t v) { memcpy(p, &v, sizeof v); }
#define ABSL_INTERNAL_UNALIGNED_STORE64(_p, _val) \
(absl::base_internal::UnalignedStore64(_p, _val))
-#endif
-
#endif // defined(__cplusplus), end of unaligned API
#endif // ABSL_BASE_INTERNAL_UNALIGNED_ACCESS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unique_small_name_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unique_small_name_test.cc
new file mode 100644
index 00000000000..ff8c2b3fb42
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unique_small_name_test.cc
@@ -0,0 +1,77 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "absl/base/optimization.h"
+#include "absl/strings/string_view.h"
+
+// This test by itself does not do anything fancy, but it serves as binary I can
+// query in shell test.
+
+namespace {
+
+template <class T>
+void DoNotOptimize(const T& var) {
+#ifdef __GNUC__
+ asm volatile("" : "+m"(const_cast<T&>(var)));
+#else
+ std::cout << (void*)&var;
+#endif
+}
+
+int very_long_int_variable_name ABSL_INTERNAL_UNIQUE_SMALL_NAME() = 0;
+char very_long_str_variable_name[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = "abc";
+
+TEST(UniqueSmallName, NonAutomaticVar) {
+ EXPECT_EQ(very_long_int_variable_name, 0);
+ EXPECT_EQ(absl::string_view(very_long_str_variable_name), "abc");
+}
+
+int VeryLongFreeFunctionName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+TEST(UniqueSmallName, FreeFunction) {
+ DoNotOptimize(&VeryLongFreeFunctionName);
+
+ EXPECT_EQ(VeryLongFreeFunctionName(), 456);
+}
+
+int VeryLongFreeFunctionName() { return 456; }
+
+struct VeryLongStructName {
+ explicit VeryLongStructName(int i);
+
+ int VeryLongMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+ static int VeryLongStaticMethodName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+
+ private:
+ int fld;
+};
+
+TEST(UniqueSmallName, Struct) {
+ VeryLongStructName var(10);
+
+ DoNotOptimize(var);
+ DoNotOptimize(&VeryLongStructName::VeryLongMethodName);
+ DoNotOptimize(&VeryLongStructName::VeryLongStaticMethodName);
+
+ EXPECT_EQ(var.VeryLongMethodName(), 10);
+ EXPECT_EQ(VeryLongStructName::VeryLongStaticMethodName(), 123);
+}
+
+VeryLongStructName::VeryLongStructName(int i) : fld(i) {}
+int VeryLongStructName::VeryLongMethodName() { return fld; }
+int VeryLongStructName::VeryLongStaticMethodName() { return 123; }
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
index a12d68bd10a..1545288cf2d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,12 +21,18 @@
#endif
#if defined(__powerpc__) || defined(__ppc__)
+#ifdef __GLIBC__
#include <sys/platform/ppc.h>
+#elif defined(__FreeBSD__)
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#endif
#endif
#include "absl/base/internal/sysinfo.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
#if defined(__i386__)
@@ -56,11 +62,43 @@ double UnscaledCycleClock::Frequency() {
#elif defined(__powerpc__) || defined(__ppc__)
int64_t UnscaledCycleClock::Now() {
+#ifdef __GLIBC__
return __ppc_get_timebase();
+#else
+#ifdef __powerpc64__
+ int64_t tbr;
+ asm volatile("mfspr %0, 268" : "=r"(tbr));
+ return tbr;
+#else
+ int32_t tbu, tbl, tmp;
+ asm volatile(
+ "0:\n"
+ "mftbu %[hi32]\n"
+ "mftb %[lo32]\n"
+ "mftbu %[tmp]\n"
+ "cmpw %[tmp],%[hi32]\n"
+ "bne 0b\n"
+ : [ hi32 ] "=r"(tbu), [ lo32 ] "=r"(tbl), [ tmp ] "=r"(tmp));
+ return (static_cast<int64_t>(tbu) << 32) | tbl;
+#endif
+#endif
}
double UnscaledCycleClock::Frequency() {
+#ifdef __GLIBC__
return __ppc_get_timebase_freq();
+#elif defined(__FreeBSD__)
+ static once_flag init_timebase_frequency_once;
+ static double timebase_frequency = 0.0;
+ base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() {
+ size_t length = sizeof(timebase_frequency);
+ sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency,
+ &length, nullptr, 0);
+ });
+ return timebase_frequency;
+#else
+#error Must implement UnscaledCycleClock::Frequency()
+#endif
}
#elif defined(__aarch64__)
@@ -85,9 +123,7 @@ double UnscaledCycleClock::Frequency() {
#pragma intrinsic(__rdtsc)
-int64_t UnscaledCycleClock::Now() {
- return __rdtsc();
-}
+int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
double UnscaledCycleClock::Frequency() {
return base_internal::NominalCPUFrequency();
@@ -96,6 +132,7 @@ double UnscaledCycleClock::Frequency() {
#endif
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.h
index 049f1cace98..82f2c87a95a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/internal/unscaledcycleclock.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,8 +15,8 @@
// UnscaledCycleClock
// An UnscaledCycleClock yields the value and frequency of a cycle counter
// that increments at a rate that is approximately constant.
-// This class is for internal / whitelisted use only, you should consider
-// using CycleClock instead.
+// This class is for internal use only, you should consider using CycleClock
+// instead.
//
// Notes:
// The cycle counter frequency is not necessarily the core clock frequency.
@@ -59,7 +59,8 @@
// CycleClock that runs at atleast 1 MHz. We've found some Android
// ARM64 devices where this is not the case, so we disable it by
// default on Android ARM64.
-#if defined(__native_client__) || TARGET_OS_IPHONE || \
+#if defined(__native_client__) || \
+ (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
(defined(__ANDROID__) && defined(__aarch64__))
#define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0
#else
@@ -83,7 +84,9 @@
defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
class UnscaledCycleClockWrapperForGetCurrentTime;
} // namespace time_internal
@@ -106,14 +109,16 @@ class UnscaledCycleClock {
// value.
static double Frequency();
- // Whitelisted friends.
+ // Allowed users
friend class base_internal::CycleClock;
friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
};
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_USE_UNSCALED_CYCLECLOCK
#endif // ABSL_BASE_INTERNAL_UNSCALEDCYCLECLOCK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/invoke_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/invoke_test.cc
index 466bf114a58..bcdef36c3bf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/invoke_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/invoke_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
@@ -70,6 +71,10 @@ struct OverloadedFunctor {
struct Class {
int Method(int a, int b) { return a - b; }
int ConstMethod(int a, int b) const { return a - b; }
+ int RefMethod(int a, int b) & { return a - b; }
+ int RefRefMethod(int a, int b) && { return a - b; }
+ int NoExceptMethod(int a, int b) noexcept { return a - b; }
+ int VolatileMethod(int a, int b) volatile { return a - b; }
int member;
};
@@ -81,113 +86,136 @@ struct FlipFlop {
int member;
};
-// CallMaybeWithArg(f) resolves either to Invoke(f) or Invoke(f, 42), depending
+// CallMaybeWithArg(f) resolves either to invoke(f) or invoke(f, 42), depending
// on which one is valid.
template <typename F>
-decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
- return Invoke(f);
+decltype(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
+ const F& f) {
+ return base_internal::invoke(f);
}
template <typename F>
-decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
- return Invoke(f, 42);
+decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
+ const F& f) {
+ return base_internal::invoke(f, 42);
}
TEST(InvokeTest, Function) {
- EXPECT_EQ(1, Invoke(Function, 3, 2));
- EXPECT_EQ(1, Invoke(&Function, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
}
TEST(InvokeTest, NonCopyableArgument) {
- EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
+ EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
}
TEST(InvokeTest, NonCopyableResult) {
- EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
+ EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
}
-TEST(InvokeTest, VoidResult) {
- Invoke(NoOp);
-}
+TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
TEST(InvokeTest, ConstFunctor) {
- EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
}
TEST(InvokeTest, MutableFunctor) {
MutableFunctor f;
- EXPECT_EQ(1, Invoke(f, 3, 2));
- EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
}
TEST(InvokeTest, EphemeralFunctor) {
EphemeralFunctor f;
- EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
- EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
}
TEST(InvokeTest, OverloadedFunctor) {
OverloadedFunctor f;
const OverloadedFunctor& cf = f;
- EXPECT_EQ("&", Invoke(f));
- EXPECT_EQ("& 42", Invoke(f, " 42"));
+ EXPECT_EQ("&", base_internal::invoke(f));
+ EXPECT_EQ("& 42", base_internal::invoke(f, " 42"));
+
+ EXPECT_EQ("const&", base_internal::invoke(cf));
+ EXPECT_EQ("const& 42", base_internal::invoke(cf, " 42"));
- EXPECT_EQ("const&", Invoke(cf));
- EXPECT_EQ("const& 42", Invoke(cf, " 42"));
+ EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
- EXPECT_EQ("&&", Invoke(std::move(f)));
- EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
+ OverloadedFunctor f2;
+ EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
}
TEST(InvokeTest, ReferenceWrapper) {
ConstFunctor cf;
MutableFunctor mf;
- EXPECT_EQ(1, Invoke(std::cref(cf), 3, 2));
- EXPECT_EQ(1, Invoke(std::ref(cf), 3, 2));
- EXPECT_EQ(1, Invoke(std::ref(mf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::cref(cf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::ref(cf), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(std::ref(mf), 3, 2));
}
TEST(InvokeTest, MemberFunction) {
std::unique_ptr<Class> p(new Class);
std::unique_ptr<const Class> cp(new Class);
- EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, p, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, p.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, *p, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp, 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, cp.get(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, *cp, 3, 2));
-
- EXPECT_EQ(1, Invoke(&Class::Method, make_unique<Class>(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<Class>(), 3, 2));
- EXPECT_EQ(1, Invoke(&Class::ConstMethod, make_unique<const Class>(), 3, 2));
+ std::unique_ptr<volatile Class> vp(new Class);
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::Method, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefMethod, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::RefRefMethod, std::move(*p), 3,
+ 2)); // NOLINT
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::NoExceptMethod, *p, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *p, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, cp.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, *cp, 3, 2));
+
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *p, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp, 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, vp.get(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::VolatileMethod, *vp, 3, 2));
+
+ EXPECT_EQ(1,
+ base_internal::invoke(&Class::Method, make_unique<Class>(), 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod, make_unique<Class>(),
+ 3, 2));
+ EXPECT_EQ(1, base_internal::invoke(&Class::ConstMethod,
+ make_unique<const Class>(), 3, 2));
}
TEST(InvokeTest, DataMember) {
std::unique_ptr<Class> p(new Class{42});
std::unique_ptr<const Class> cp(new Class{42});
- EXPECT_EQ(42, Invoke(&Class::member, p));
- EXPECT_EQ(42, Invoke(&Class::member, *p));
- EXPECT_EQ(42, Invoke(&Class::member, p.get()));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, p));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, *p));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, p.get()));
- Invoke(&Class::member, p) = 42;
- Invoke(&Class::member, p.get()) = 42;
+ base_internal::invoke(&Class::member, p) = 42;
+ base_internal::invoke(&Class::member, p.get()) = 42;
- EXPECT_EQ(42, Invoke(&Class::member, cp));
- EXPECT_EQ(42, Invoke(&Class::member, *cp));
- EXPECT_EQ(42, Invoke(&Class::member, cp.get()));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, cp));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, *cp));
+ EXPECT_EQ(42, base_internal::invoke(&Class::member, cp.get()));
}
TEST(InvokeTest, FlipFlop) {
FlipFlop obj = {42};
// This call could resolve to (obj.*&FlipFlop::ConstMethod)() or
// ((*obj).*&FlipFlop::ConstMethod)(). We verify that it's the former.
- EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
- EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
+ EXPECT_EQ(42, base_internal::invoke(&FlipFlop::ConstMethod, obj));
+ EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
}
TEST(InvokeTest, SfinaeFriendly) {
@@ -197,4 +225,5 @@ TEST(InvokeTest, SfinaeFriendly) {
} // namespace
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.cc
new file mode 100644
index 00000000000..72312afd367
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.cc
@@ -0,0 +1,27 @@
+// 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.
+
+#include "absl/base/log_severity.h"
+
+#include <ostream>
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+std::ostream& operator<<(std::ostream& os, absl::LogSeverity s) {
+ if (s == absl::NormalizeLogSeverity(s)) return os << absl::LogSeverityName(s);
+ return os << "absl::LogSeverity(" << static_cast<int>(s) << ")";
+}
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.h
index 5770d3629e7..2236422462f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity.h
@@ -4,27 +4,68 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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_LOG_SEVERITY_H_
-#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#ifndef ABSL_BASE_LOG_SEVERITY_H_
+#define ABSL_BASE_LOG_SEVERITY_H_
#include <array>
+#include <ostream>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
-// Four severity levels are defined. Logging APIs should terminate the program
+// absl::LogSeverity
+//
+// Four severity levels are defined. Logging APIs should terminate the program
// when a message is logged at severity `kFatal`; the other levels have no
// special semantics.
+//
+// Values other than the four defined levels (e.g. produced by `static_cast`)
+// are valid, but their semantics when passed to a function, macro, or flag
+// depend on the function, macro, or flag. The usual behavior is to normalize
+// such values to a defined severity level, however in some cases values other
+// than the defined levels are useful for comparison.
+//
+// Example:
+//
+// // Effectively disables all logging:
+// SetMinLogLevel(static_cast<absl::LogSeverity>(100));
+//
+// Abseil flags may be defined with type `LogSeverity`. Dependency layering
+// constraints require that the `AbslParseFlag()` overload be declared and
+// defined in the flags library itself rather than here. The `AbslUnparseFlag()`
+// overload is defined there as well for consistency.
+//
+// absl::LogSeverity Flag String Representation
+//
+// An `absl::LogSeverity` has a string representation used for parsing
+// command-line flags based on the enumerator name (e.g. `kFatal`) or
+// its unprefixed name (without the `k`) in any case-insensitive form. (E.g.
+// "FATAL", "fatal" or "Fatal" are all valid.) Unparsing such flags produces an
+// unprefixed string representation in all caps (e.g. "FATAL") or an integer.
+//
+// Additionally, the parser accepts arbitrary integers (as if the type were
+// `int`).
+//
+// Examples:
+//
+// --my_log_level=kInfo
+// --my_log_level=INFO
+// --my_log_level=info
+// --my_log_level=0
+//
+// Unparsing a flag produces the same result as `absl::LogSeverityName()` for
+// the standard levels and a base-ten integer otherwise.
enum class LogSeverity : int {
kInfo = 0,
kWarning = 1,
@@ -32,6 +73,8 @@ enum class LogSeverity : int {
kFatal = 3,
};
+// LogSeverities()
+//
// Returns an iterable of all standard `absl::LogSeverity` values, ordered from
// least to most severe.
constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
@@ -39,8 +82,10 @@ constexpr std::array<absl::LogSeverity, 4> LogSeverities() {
absl::LogSeverity::kError, absl::LogSeverity::kFatal}};
}
+// LogSeverityName()
+//
// Returns the all-caps string representation (e.g. "INFO") of the specified
-// severity level if it is one of the normal levels and "UNKNOWN" otherwise.
+// severity level if it is one of the standard levels and "UNKNOWN" otherwise.
constexpr const char* LogSeverityName(absl::LogSeverity s) {
return s == absl::LogSeverity::kInfo
? "INFO"
@@ -51,6 +96,8 @@ constexpr const char* LogSeverityName(absl::LogSeverity s) {
: s == absl::LogSeverity::kFatal ? "FATAL" : "UNKNOWN";
}
+// NormalizeLogSeverity()
+//
// Values less than `kInfo` normalize to `kInfo`; values greater than `kFatal`
// normalize to `kError` (**NOT** `kFatal`).
constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
@@ -59,9 +106,16 @@ constexpr absl::LogSeverity NormalizeLogSeverity(absl::LogSeverity s) {
: s > absl::LogSeverity::kFatal ? absl::LogSeverity::kError : s;
}
constexpr absl::LogSeverity NormalizeLogSeverity(int s) {
- return NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
+ return absl::NormalizeLogSeverity(static_cast<absl::LogSeverity>(s));
}
+// operator<<
+//
+// The exact representation of a streamed `absl::LogSeverity` is deliberately
+// unspecified; do not rely on it.
+std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
+
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#endif // ABSL_BASE_LOG_SEVERITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity_test.cc
new file mode 100644
index 00000000000..2c6872b00a6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/log_severity_test.cc
@@ -0,0 +1,204 @@
+// 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.
+
+#include "absl/base/log_severity.h"
+
+#include <cstdint>
+#include <ios>
+#include <limits>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <tuple>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+using ::testing::Eq;
+using ::testing::IsFalse;
+using ::testing::IsTrue;
+using ::testing::TestWithParam;
+using ::testing::Values;
+
+std::string StreamHelper(absl::LogSeverity value) {
+ std::ostringstream stream;
+ stream << value;
+ return stream.str();
+}
+
+TEST(StreamTest, Works) {
+ EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(-100)),
+ Eq("absl::LogSeverity(-100)"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverity::kInfo), Eq("INFO"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverity::kWarning), Eq("WARNING"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverity::kError), Eq("ERROR"));
+ EXPECT_THAT(StreamHelper(absl::LogSeverity::kFatal), Eq("FATAL"));
+ EXPECT_THAT(StreamHelper(static_cast<absl::LogSeverity>(4)),
+ Eq("absl::LogSeverity(4)"));
+}
+
+static_assert(
+ absl::flags_internal::FlagUseOneWordStorage<absl::LogSeverity>::value,
+ "Flags of type absl::LogSeverity ought to be lock-free.");
+
+using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>;
+INSTANTIATE_TEST_SUITE_P(
+ Instantiation, ParseFlagFromOutOfRangeIntegerTest,
+ Values(static_cast<int64_t>(std::numeric_limits<int>::min()) - 1,
+ static_cast<int64_t>(std::numeric_limits<int>::max()) + 1));
+TEST_P(ParseFlagFromOutOfRangeIntegerTest, ReturnsError) {
+ const std::string to_parse = absl::StrCat(GetParam());
+ absl::LogSeverity value;
+ std::string error;
+ EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value;
+}
+
+using ParseFlagFromAlmostOutOfRangeIntegerTest = TestWithParam<int>;
+INSTANTIATE_TEST_SUITE_P(Instantiation,
+ ParseFlagFromAlmostOutOfRangeIntegerTest,
+ Values(std::numeric_limits<int>::min(),
+ std::numeric_limits<int>::max()));
+TEST_P(ParseFlagFromAlmostOutOfRangeIntegerTest, YieldsExpectedValue) {
+ const auto expected = static_cast<absl::LogSeverity>(GetParam());
+ const std::string to_parse = absl::StrCat(GetParam());
+ absl::LogSeverity value;
+ std::string error;
+ ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;
+ EXPECT_THAT(value, Eq(expected));
+}
+
+using ParseFlagFromIntegerMatchingEnumeratorTest =
+ TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>;
+INSTANTIATE_TEST_SUITE_P(
+ Instantiation, ParseFlagFromIntegerMatchingEnumeratorTest,
+ Values(std::make_tuple("0", absl::LogSeverity::kInfo),
+ std::make_tuple(" 0", absl::LogSeverity::kInfo),
+ std::make_tuple("-0", absl::LogSeverity::kInfo),
+ std::make_tuple("+0", absl::LogSeverity::kInfo),
+ std::make_tuple("00", absl::LogSeverity::kInfo),
+ std::make_tuple("0 ", absl::LogSeverity::kInfo),
+ std::make_tuple("0x0", absl::LogSeverity::kInfo),
+ std::make_tuple("1", absl::LogSeverity::kWarning),
+ std::make_tuple("+1", absl::LogSeverity::kWarning),
+ std::make_tuple("2", absl::LogSeverity::kError),
+ std::make_tuple("3", absl::LogSeverity::kFatal)));
+TEST_P(ParseFlagFromIntegerMatchingEnumeratorTest, YieldsExpectedValue) {
+ const absl::string_view to_parse = std::get<0>(GetParam());
+ const absl::LogSeverity expected = std::get<1>(GetParam());
+ absl::LogSeverity value;
+ std::string error;
+ ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;
+ EXPECT_THAT(value, Eq(expected));
+}
+
+using ParseFlagFromOtherIntegerTest =
+ TestWithParam<std::tuple<absl::string_view, int>>;
+INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromOtherIntegerTest,
+ Values(std::make_tuple("-1", -1),
+ std::make_tuple("4", 4),
+ std::make_tuple("010", 10),
+ std::make_tuple("0x10", 16)));
+TEST_P(ParseFlagFromOtherIntegerTest, YieldsExpectedValue) {
+ const absl::string_view to_parse = std::get<0>(GetParam());
+ const auto expected = static_cast<absl::LogSeverity>(std::get<1>(GetParam()));
+ absl::LogSeverity value;
+ std::string error;
+ ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;
+ EXPECT_THAT(value, Eq(expected));
+}
+
+using ParseFlagFromEnumeratorTest =
+ TestWithParam<std::tuple<absl::string_view, absl::LogSeverity>>;
+INSTANTIATE_TEST_SUITE_P(
+ Instantiation, ParseFlagFromEnumeratorTest,
+ Values(std::make_tuple("INFO", absl::LogSeverity::kInfo),
+ std::make_tuple("info", absl::LogSeverity::kInfo),
+ std::make_tuple("kInfo", absl::LogSeverity::kInfo),
+ std::make_tuple("iNfO", absl::LogSeverity::kInfo),
+ std::make_tuple("kInFo", absl::LogSeverity::kInfo),
+ std::make_tuple("WARNING", absl::LogSeverity::kWarning),
+ std::make_tuple("warning", absl::LogSeverity::kWarning),
+ std::make_tuple("kWarning", absl::LogSeverity::kWarning),
+ std::make_tuple("WaRnInG", absl::LogSeverity::kWarning),
+ std::make_tuple("KwArNiNg", absl::LogSeverity::kWarning),
+ std::make_tuple("ERROR", absl::LogSeverity::kError),
+ std::make_tuple("error", absl::LogSeverity::kError),
+ std::make_tuple("kError", absl::LogSeverity::kError),
+ std::make_tuple("eRrOr", absl::LogSeverity::kError),
+ std::make_tuple("kErRoR", absl::LogSeverity::kError),
+ std::make_tuple("FATAL", absl::LogSeverity::kFatal),
+ std::make_tuple("fatal", absl::LogSeverity::kFatal),
+ std::make_tuple("kFatal", absl::LogSeverity::kFatal),
+ std::make_tuple("FaTaL", absl::LogSeverity::kFatal),
+ std::make_tuple("KfAtAl", absl::LogSeverity::kFatal)));
+TEST_P(ParseFlagFromEnumeratorTest, YieldsExpectedValue) {
+ const absl::string_view to_parse = std::get<0>(GetParam());
+ const absl::LogSeverity expected = std::get<1>(GetParam());
+ absl::LogSeverity value;
+ std::string error;
+ ASSERT_THAT(absl::ParseFlag(to_parse, &value, &error), IsTrue()) << error;
+ EXPECT_THAT(value, Eq(expected));
+}
+
+using ParseFlagFromGarbageTest = TestWithParam<absl::string_view>;
+INSTANTIATE_TEST_SUITE_P(Instantiation, ParseFlagFromGarbageTest,
+ Values("", "\0", " ", "garbage", "kkinfo", "I"));
+TEST_P(ParseFlagFromGarbageTest, ReturnsError) {
+ const absl::string_view to_parse = GetParam();
+ absl::LogSeverity value;
+ std::string error;
+ EXPECT_THAT(absl::ParseFlag(to_parse, &value, &error), IsFalse()) << value;
+}
+
+using UnparseFlagToEnumeratorTest =
+ TestWithParam<std::tuple<absl::LogSeverity, absl::string_view>>;
+INSTANTIATE_TEST_SUITE_P(
+ Instantiation, UnparseFlagToEnumeratorTest,
+ Values(std::make_tuple(absl::LogSeverity::kInfo, "INFO"),
+ std::make_tuple(absl::LogSeverity::kWarning, "WARNING"),
+ std::make_tuple(absl::LogSeverity::kError, "ERROR"),
+ std::make_tuple(absl::LogSeverity::kFatal, "FATAL")));
+TEST_P(UnparseFlagToEnumeratorTest, ReturnsExpectedValueAndRoundTrips) {
+ const absl::LogSeverity to_unparse = std::get<0>(GetParam());
+ const absl::string_view expected = std::get<1>(GetParam());
+ const std::string stringified_value = absl::UnparseFlag(to_unparse);
+ EXPECT_THAT(stringified_value, Eq(expected));
+ absl::LogSeverity reparsed_value;
+ std::string error;
+ EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error),
+ IsTrue());
+ EXPECT_THAT(reparsed_value, Eq(to_unparse));
+}
+
+using UnparseFlagToOtherIntegerTest = TestWithParam<int>;
+INSTANTIATE_TEST_SUITE_P(Instantiation, UnparseFlagToOtherIntegerTest,
+ Values(std::numeric_limits<int>::min(), -1, 4,
+ std::numeric_limits<int>::max()));
+TEST_P(UnparseFlagToOtherIntegerTest, ReturnsExpectedValueAndRoundTrips) {
+ const absl::LogSeverity to_unparse =
+ static_cast<absl::LogSeverity>(GetParam());
+ const std::string expected = absl::StrCat(GetParam());
+ const std::string stringified_value = absl::UnparseFlag(to_unparse);
+ EXPECT_THAT(stringified_value, Eq(expected));
+ absl::LogSeverity reparsed_value;
+ std::string error;
+ EXPECT_THAT(absl::ParseFlag(stringified_value, &reparsed_value, &error),
+ IsTrue());
+ EXPECT_THAT(reparsed_value, Eq(to_unparse));
+}
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/macros.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/macros.h
index 9e7ab375eed..3e085a916bb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/macros.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/macros.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,7 +24,6 @@
// This code is compiled directly on many platforms, including client
// platforms like Windows, Mac, and embedded systems. Before making
// any changes here, make sure that you're not breaking any platforms.
-//
#ifndef ABSL_BASE_MACROS_H_
#define ABSL_BASE_MACROS_H_
@@ -32,6 +31,9 @@
#include <cassert>
#include <cstddef>
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
// ABSL_ARRAYSIZE()
@@ -43,122 +45,22 @@
(sizeof(::absl::macros_internal::ArraySizeHelper(array)))
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace macros_internal {
// Note: this internal template function declaration is used by ABSL_ARRAYSIZE.
// The function doesn't need a definition, as we only use its type.
template <typename T, size_t N>
auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
} // namespace macros_internal
+ABSL_NAMESPACE_END
} // namespace absl
-// kLinkerInitialized
-//
-// An enum used only as a constructor argument to indicate that a variable has
-// static storage duration, and that the constructor should do nothing to its
-// state. Use of this macro indicates to the reader that it is legal to
-// declare a static instance of the class, provided the constructor is given
-// the absl::base_internal::kLinkerInitialized argument.
-//
-// Normally, it is unsafe to declare a static variable that has a constructor or
-// a destructor because invocation order is undefined. However, if the type can
-// be zero-initialized (which the loader does for static variables) into a valid
-// state and the type's destructor does not affect storage, then a constructor
-// for static initialization can be declared.
-//
-// Example:
-// // Declaration
-// explicit MyClass(absl::base_internal:LinkerInitialized x) {}
-//
-// // Invocation
-// static MyClass my_global(absl::base_internal::kLinkerInitialized);
-namespace absl {
-namespace base_internal {
-enum LinkerInitialized {
- kLinkerInitialized = 0,
-};
-} // namespace base_internal
-} // namespace absl
-
-// ABSL_FALLTHROUGH_INTENDED
-//
-// Annotates implicit fall-through between switch labels, allowing a case to
-// indicate intentional fallthrough and turn off warnings about any lack of a
-// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by
-// a semicolon and can be used in most places where `break` can, provided that
-// no statements exist between it and the next switch label.
-//
-// Example:
-//
-// switch (x) {
-// case 40:
-// case 41:
-// if (truth_is_out_there) {
-// ++x;
-// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations
-// // in comments
-// } else {
-// return x;
-// }
-// case 42:
-// ...
-//
-// Notes: when compiled with clang in C++11 mode, the ABSL_FALLTHROUGH_INTENDED
-// macro is expanded to the [[clang::fallthrough]] attribute, which is analysed
-// when performing switch labels fall-through diagnostic
-// (`-Wimplicit-fallthrough`). See clang documentation on language extensions
-// for details:
-// http://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
-//
-// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro
-// has no effect on diagnostics. In any case this macro has no effect on runtime
-// behavior and performance of code.
-#ifdef ABSL_FALLTHROUGH_INTENDED
-#error "ABSL_FALLTHROUGH_INTENDED should not be defined."
-#endif
-
-// TODO(zhangxy): Use c++17 standard [[fallthrough]] macro, when supported.
-#if defined(__clang__) && defined(__has_warning)
-#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
-#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
-#endif
-#elif defined(__GNUC__) && __GNUC__ >= 7
-#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
-#endif
-
-#ifndef ABSL_FALLTHROUGH_INTENDED
-#define ABSL_FALLTHROUGH_INTENDED \
- do { \
- } while (0)
-#endif
-
-// ABSL_DEPRECATED()
-//
-// Marks a deprecated class, struct, enum, function, method and variable
-// declarations. The macro argument is used as a custom diagnostic message (e.g.
-// suggestion of a better alternative).
-//
-// Example:
-//
-// class ABSL_DEPRECATED("Use Bar instead") Foo {...};
-// ABSL_DEPRECATED("Use Baz instead") void Bar() {...}
-//
-// Every usage of a deprecated entity will trigger a warning when compiled with
-// clang's `-Wdeprecated-declarations` option. This option is turned off by
-// default, but the warnings will be reported by clang-tidy.
-#if defined(__clang__) && __cplusplus >= 201103L
-#define ABSL_DEPRECATED(message) __attribute__((deprecated(message)))
-#endif
-
-#ifndef ABSL_DEPRECATED
-#define ABSL_DEPRECATED(message)
-#endif
-
// ABSL_BAD_CALL_IF()
//
// Used on a function overload to trap bad calls: any call that matches the
// overload will cause a compile-time error. This macro uses a clang-specific
// "enable_if" attribute, as described at
-// http://clang.llvm.org/docs/AttributeReference.html#enable-if
+// https://clang.llvm.org/docs/AttributeReference.html#enable-if
//
// Overloads which use this macro should be bracketed by
// `#ifdef ABSL_BAD_CALL_IF`.
@@ -171,12 +73,9 @@ enum LinkerInitialized {
// ABSL_BAD_CALL_IF(c <= -1 || c > 255,
// "'c' must have the value of an unsigned char or EOF");
// #endif // ABSL_BAD_CALL_IF
-
-#if defined(__clang__)
-# if __has_attribute(enable_if)
-# define ABSL_BAD_CALL_IF(expr, msg) \
- __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
-# endif
+#if ABSL_HAVE_ATTRIBUTE(enable_if)
+#define ABSL_BAD_CALL_IF(expr, msg) \
+ __attribute__((enable_if(expr, "Bad call trap"), unavailable(msg)))
#endif
// ABSL_ASSERT()
@@ -192,13 +91,49 @@ enum LinkerInitialized {
// This macro is inspired by
// https://akrzemi1.wordpress.com/2017/05/18/asserts-in-constexpr-functions/
#if defined(NDEBUG)
-#define ABSL_ASSERT(expr) (false ? (void)(expr) : (void)0)
+#define ABSL_ASSERT(expr) \
+ (false ? static_cast<void>(expr) : static_cast<void>(0))
#else
-#define ABSL_ASSERT(expr) \
- (ABSL_PREDICT_TRUE((expr)) ? (void)0 \
+#define ABSL_ASSERT(expr) \
+ (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
: [] { assert(false && #expr); }()) // NOLINT
#endif
+// `ABSL_INTERNAL_HARDENING_ABORT()` controls how `ABSL_HARDENING_ASSERT()`
+// aborts the program in release mode (when NDEBUG is defined). The
+// implementation should abort the program as quickly as possible and ideally it
+// should not be possible to ignore the abort request.
+#if (ABSL_HAVE_BUILTIN(__builtin_trap) && \
+ ABSL_HAVE_BUILTIN(__builtin_unreachable)) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_HARDENING_ABORT() \
+ do { \
+ __builtin_trap(); \
+ __builtin_unreachable(); \
+ } while (false)
+#else
+#define ABSL_INTERNAL_HARDENING_ABORT() abort()
+#endif
+
+// ABSL_HARDENING_ASSERT()
+//
+// `ABSL_HARDENING_ASSERT()` is like `ABSL_ASSERT()`, but used to implement
+// runtime assertions that should be enabled in hardened builds even when
+// `NDEBUG` is defined.
+//
+// When `NDEBUG` is not defined, `ABSL_HARDENING_ASSERT()` is identical to
+// `ABSL_ASSERT()`.
+//
+// See `ABSL_OPTION_HARDENED` in `absl/base/options.h` for more information on
+// hardened mode.
+#if ABSL_OPTION_HARDENED == 1 && defined(NDEBUG)
+#define ABSL_HARDENING_ASSERT(expr) \
+ (ABSL_PREDICT_TRUE((expr)) ? static_cast<void>(0) \
+ : [] { ABSL_INTERNAL_HARDENING_ABORT(); }())
+#else
+#define ABSL_HARDENING_ASSERT(expr) ABSL_ASSERT(expr)
+#endif
+
#ifdef ABSL_HAVE_EXCEPTIONS
#define ABSL_INTERNAL_TRY try
#define ABSL_INTERNAL_CATCH_ANY catch (...)
@@ -209,4 +144,15 @@ enum LinkerInitialized {
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
+// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
+// reaches one has undefined behavior, and the compiler may optimize
+// accordingly.
+#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_UNREACHABLE __assume(0)
+#else
+#define ABSL_INTERNAL_UNREACHABLE
+#endif
+
#endif // ABSL_BASE_MACROS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization.h
index 2fddfc800c1..d090be12868 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,13 +22,15 @@
#ifndef ABSL_BASE_OPTIMIZATION_H_
#define ABSL_BASE_OPTIMIZATION_H_
+#include <assert.h>
+
#include "absl/base/config.h"
// ABSL_BLOCK_TAIL_CALL_OPTIMIZATION
//
-// Instructs the compiler to avoid optimizing tail-call recursion. Use of this
-// macro is useful when you wish to preserve the existing function order within
-// a stack trace for logging, debugging, or profiling purposes.
+// Instructs the compiler to avoid optimizing tail-call recursion. This macro is
+// useful when you wish to preserve the existing function order within a stack
+// trace for logging, debugging, or profiling purposes.
//
// Example:
//
@@ -104,16 +106,17 @@
// Cacheline aligning objects properly allows constructive memory sharing and
// prevents destructive (or "false") memory sharing.
//
-// NOTE: this macro should be replaced with usage of `alignas()` using
+// NOTE: callers should replace uses of this macro with `alignas()` using
// `std::hardware_constructive_interference_size` and/or
-// `std::hardware_destructive_interference_size` when available within C++17.
+// `std::hardware_destructive_interference_size` when C++17 becomes available to
+// them.
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.
//
-// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to
-// `__attribute__((aligned(ABSL_CACHELINE_SIZE)))`. For compilers where this is
-// not known to work, the macro expands to nothing.
+// On some compilers, `ABSL_CACHELINE_ALIGNED` expands to an `__attribute__`
+// or `__declspec` attribute. For compilers where this is not known to work,
+// the macro expands to nothing.
//
// No further guarantees are made here. The result of applying the macro
// to variables and types is always implementation-defined.
@@ -122,6 +125,14 @@
// of causing bugs that are difficult to diagnose, crash, etc. It does not
// of itself guarantee that objects are aligned to a cache line.
//
+// NOTE: Some compilers are picky about the locations of annotations such as
+// this attribute, so prefer to put it at the beginning of your declaration.
+// For example,
+//
+// ABSL_CACHELINE_ALIGNED static Foo* foo = ...
+//
+// class ABSL_CACHELINE_ALIGNED Bar { ...
+//
// Recommendations:
//
// 1) Consult compiler documentation; this comment is not kept in sync as
@@ -131,8 +142,10 @@
// 3) Prefer applying this attribute to individual variables. Avoid
// applying it to types. This tends to localize the effect.
#define ABSL_CACHELINE_ALIGNED __attribute__((aligned(ABSL_CACHELINE_SIZE)))
-
-#else // not GCC
+#elif defined(_MSC_VER)
+#define ABSL_CACHELINE_SIZE 64
+#define ABSL_CACHELINE_ALIGNED __declspec(align(ABSL_CACHELINE_SIZE))
+#else
#define ABSL_CACHELINE_SIZE 64
#define ABSL_CACHELINE_ALIGNED
#endif
@@ -153,13 +166,79 @@
// Compilers can use the information that a certain branch is not likely to be
// taken (for instance, a CHECK failure) to optimize for the common case in
// the absence of better information (ie. compiling gcc with `-fprofile-arcs`).
+//
+// Recommendation: Modern CPUs dynamically predict branch execution paths,
+// typically with accuracy greater than 97%. As a result, annotating every
+// branch in a codebase is likely counterproductive; however, annotating
+// specific branches that are both hot and consistently mispredicted is likely
+// to yield performance improvements.
#if ABSL_HAVE_BUILTIN(__builtin_expect) || \
(defined(__GNUC__) && !defined(__clang__))
-#define ABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0))
-#define ABSL_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
+#define ABSL_PREDICT_TRUE(x) (__builtin_expect(false || (x), true))
#else
#define ABSL_PREDICT_FALSE(x) (x)
#define ABSL_PREDICT_TRUE(x) (x)
#endif
+// ABSL_INTERNAL_ASSUME(cond)
+// Informs the compiler that a condition is always true and that it can assume
+// it to be true for optimization purposes. The call has undefined behavior if
+// the condition is false.
+// In !NDEBUG mode, the condition is checked with an assert().
+// NOTE: The expression must not have side effects, as it will only be evaluated
+// in some compilation modes and not others.
+//
+// Example:
+//
+// int x = ...;
+// ABSL_INTERNAL_ASSUME(x >= 0);
+// // The compiler can optimize the division to a simple right shift using the
+// // assumption specified above.
+// int y = x / 16;
+//
+#if !defined(NDEBUG)
+#define ABSL_INTERNAL_ASSUME(cond) assert(cond)
+#elif ABSL_HAVE_BUILTIN(__builtin_assume)
+#define ABSL_INTERNAL_ASSUME(cond) __builtin_assume(cond)
+#elif defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
+#define ABSL_INTERNAL_ASSUME(cond) \
+ do { \
+ if (!(cond)) __builtin_unreachable(); \
+ } while (0)
+#elif defined(_MSC_VER)
+#define ABSL_INTERNAL_ASSUME(cond) __assume(cond)
+#else
+#define ABSL_INTERNAL_ASSUME(cond) \
+ do { \
+ static_cast<void>(false && (cond)); \
+ } while (0)
+#endif
+
+// ABSL_INTERNAL_UNIQUE_SMALL_NAME(cond)
+// This macro forces small unique name on a static file level symbols like
+// static local variables or static functions. This is intended to be used in
+// macro definitions to optimize the cost of generated code. Do NOT use it on
+// symbols exported from translation unit since it may cause a link time
+// conflict.
+//
+// Example:
+//
+// #define MY_MACRO(txt)
+// namespace {
+// char VeryVeryLongVarName[] ABSL_INTERNAL_UNIQUE_SMALL_NAME() = txt;
+// const char* VeryVeryLongFuncName() ABSL_INTERNAL_UNIQUE_SMALL_NAME();
+// const char* VeryVeryLongFuncName() { return txt; }
+// }
+//
+
+#if defined(__GNUC__)
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x) #x
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME1(x) ABSL_INTERNAL_UNIQUE_SMALL_NAME2(x)
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+ asm(ABSL_INTERNAL_UNIQUE_SMALL_NAME1(.absl.__COUNTER__))
+#else
+#define ABSL_INTERNAL_UNIQUE_SMALL_NAME()
+#endif
+
#endif // ABSL_BASE_OPTIMIZATION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization_test.cc
new file mode 100644
index 00000000000..e83369f3226
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/optimization_test.cc
@@ -0,0 +1,129 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/base/optimization.h"
+
+#include "gtest/gtest.h"
+#include "absl/types/optional.h"
+
+namespace {
+
+// Tests for the ABSL_PREDICT_TRUE and ABSL_PREDICT_FALSE macros.
+// The tests only verify that the macros are functionally correct - i.e. code
+// behaves as if they weren't used. They don't try to check their impact on
+// optimization.
+
+TEST(PredictTest, PredictTrue) {
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(true));
+ EXPECT_FALSE(ABSL_PREDICT_TRUE(false));
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(1 == 1));
+ EXPECT_FALSE(ABSL_PREDICT_TRUE(1 == 2));
+
+ if (ABSL_PREDICT_TRUE(false)) ADD_FAILURE();
+ if (!ABSL_PREDICT_TRUE(true)) ADD_FAILURE();
+
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(true) && true);
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(true) || false);
+}
+
+TEST(PredictTest, PredictFalse) {
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(true));
+ EXPECT_FALSE(ABSL_PREDICT_FALSE(false));
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(1 == 1));
+ EXPECT_FALSE(ABSL_PREDICT_FALSE(1 == 2));
+
+ if (ABSL_PREDICT_FALSE(false)) ADD_FAILURE();
+ if (!ABSL_PREDICT_FALSE(true)) ADD_FAILURE();
+
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(true) && true);
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(true) || false);
+}
+
+TEST(PredictTest, OneEvaluation) {
+ // Verify that the expression is only evaluated once.
+ int x = 0;
+ if (ABSL_PREDICT_TRUE((++x) == 0)) ADD_FAILURE();
+ EXPECT_EQ(x, 1);
+ if (ABSL_PREDICT_FALSE((++x) == 0)) ADD_FAILURE();
+ EXPECT_EQ(x, 2);
+}
+
+TEST(PredictTest, OperatorOrder) {
+ // Verify that operator order inside and outside the macro behaves well.
+ // These would fail for a naive '#define ABSL_PREDICT_TRUE(x) x'
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(1 && 2) == true);
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(1 && 2) == true);
+ EXPECT_TRUE(!ABSL_PREDICT_TRUE(1 == 2));
+ EXPECT_TRUE(!ABSL_PREDICT_FALSE(1 == 2));
+}
+
+TEST(PredictTest, Pointer) {
+ const int x = 3;
+ const int *good_intptr = &x;
+ const int *null_intptr = nullptr;
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(good_intptr));
+ EXPECT_FALSE(ABSL_PREDICT_TRUE(null_intptr));
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(good_intptr));
+ EXPECT_FALSE(ABSL_PREDICT_FALSE(null_intptr));
+}
+
+TEST(PredictTest, Optional) {
+ // Note: An optional's truth value is the value's existence, not its truth.
+ absl::optional<bool> has_value(false);
+ absl::optional<bool> no_value;
+ EXPECT_TRUE(ABSL_PREDICT_TRUE(has_value));
+ EXPECT_FALSE(ABSL_PREDICT_TRUE(no_value));
+ EXPECT_TRUE(ABSL_PREDICT_FALSE(has_value));
+ EXPECT_FALSE(ABSL_PREDICT_FALSE(no_value));
+}
+
+class ImplictlyConvertibleToBool {
+ public:
+ explicit ImplictlyConvertibleToBool(bool value) : value_(value) {}
+ operator bool() const { // NOLINT(google-explicit-constructor)
+ return value_;
+ }
+
+ private:
+ bool value_;
+};
+
+TEST(PredictTest, ImplicitBoolConversion) {
+ const ImplictlyConvertibleToBool is_true(true);
+ const ImplictlyConvertibleToBool is_false(false);
+ if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
+ if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
+ if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
+ if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
+}
+
+class ExplictlyConvertibleToBool {
+ public:
+ explicit ExplictlyConvertibleToBool(bool value) : value_(value) {}
+ explicit operator bool() const { return value_; }
+
+ private:
+ bool value_;
+};
+
+TEST(PredictTest, ExplicitBoolConversion) {
+ const ExplictlyConvertibleToBool is_true(true);
+ const ExplictlyConvertibleToBool is_false(false);
+ if (!ABSL_PREDICT_TRUE(is_true)) ADD_FAILURE();
+ if (ABSL_PREDICT_TRUE(is_false)) ADD_FAILURE();
+ if (!ABSL_PREDICT_FALSE(is_true)) ADD_FAILURE();
+ if (ABSL_PREDICT_FALSE(is_false)) ADD_FAILURE();
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/options.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/options.h
new file mode 100644
index 00000000000..eca879af005
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/options.h
@@ -0,0 +1,238 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: options.h
+// -----------------------------------------------------------------------------
+//
+// This file contains Abseil configuration options for setting specific
+// implementations instead of letting Abseil determine which implementation to
+// use at compile-time. Setting these options may be useful for package or build
+// managers who wish to guarantee ABI stability within binary builds (which are
+// otherwise difficult to enforce).
+//
+// *** IMPORTANT NOTICE FOR PACKAGE MANAGERS: It is important that
+// maintainers of package managers who wish to package Abseil read and
+// understand this file! ***
+//
+// Abseil contains a number of possible configuration endpoints, based on
+// parameters such as the detected platform, language version, or command-line
+// flags used to invoke the underlying binary. As is the case with all
+// libraries, binaries which contain Abseil code must ensure that separate
+// packages use the same compiled copy of Abseil to avoid a diamond dependency
+// problem, which can occur if two packages built with different Abseil
+// configuration settings are linked together. Diamond dependency problems in
+// C++ may manifest as violations to the One Definition Rule (ODR) (resulting in
+// linker errors), or undefined behavior (resulting in crashes).
+//
+// Diamond dependency problems can be avoided if all packages utilize the same
+// exact version of Abseil. Building from source code with the same compilation
+// parameters is the easiest way to avoid such dependency problems. However, for
+// package managers who cannot control such compilation parameters, we are
+// providing the file to allow you to inject ABI (Application Binary Interface)
+// stability across builds. Settings options in this file will neither change
+// API nor ABI, providing a stable copy of Abseil between packages.
+//
+// Care must be taken to keep options within these configurations isolated
+// from any other dynamic settings, such as command-line flags which could alter
+// these options. This file is provided specifically to help build and package
+// managers provide a stable copy of Abseil within their libraries and binaries;
+// other developers should not have need to alter the contents of this file.
+//
+// -----------------------------------------------------------------------------
+// Usage
+// -----------------------------------------------------------------------------
+//
+// For any particular package release, set the appropriate definitions within
+// this file to whatever value makes the most sense for your package(s). Note
+// that, by default, most of these options, at the moment, affect the
+// implementation of types; future options may affect other implementation
+// details.
+//
+// NOTE: the defaults within this file all assume that Abseil can select the
+// proper Abseil implementation at compile-time, which will not be sufficient
+// to guarantee ABI stability to package managers.
+
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
+// Include a standard library header to allow configuration based on the
+// standard library in use.
+#ifdef __cplusplus
+#include <ciso646>
+#endif
+
+// -----------------------------------------------------------------------------
+// Type Compatibility Options
+// -----------------------------------------------------------------------------
+//
+// ABSL_OPTION_USE_STD_ANY
+//
+// This option controls whether absl::any is implemented as an alias to
+// std::any, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation. This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::any. This requires that all code
+// using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::any is available. This option is
+// useful when you are building your entire program, including all of its
+// dependencies, from source. It should not be used otherwise -- for example,
+// if you are distributing Abseil in a binary package manager -- since in
+// mode 2, absl::any will name a different type, with a different mangled name
+// and binary layout, depending on the compiler flags passed by the end user.
+// For more info, see https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro. To check in the preprocessor if
+// absl::any is a typedef of std::any, use the feature macro ABSL_USES_STD_ANY.
+
+#define ABSL_OPTION_USE_STD_ANY 2
+
+
+// ABSL_OPTION_USE_STD_OPTIONAL
+//
+// This option controls whether absl::optional is implemented as an alias to
+// std::optional, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation. This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::optional. This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::optional is available. This option
+// is useful when you are building your program from source. It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::optional will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user. For more info, see
+// https://abseil.io/about/design/dropin-types.
+
+// User code should not inspect this macro. To check in the preprocessor if
+// absl::optional is a typedef of std::optional, use the feature macro
+// ABSL_USES_STD_OPTIONAL.
+
+#define ABSL_OPTION_USE_STD_OPTIONAL 2
+
+
+// ABSL_OPTION_USE_STD_STRING_VIEW
+//
+// This option controls whether absl::string_view is implemented as an alias to
+// std::string_view, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation. This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::string_view. This requires that
+// all code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::string_view is available. This
+// option is useful when you are building your program from source. It should
+// not be used otherwise -- for example, if you are distributing Abseil in a
+// binary package manager -- since in mode 2, absl::string_view will name a
+// different type, with a different mangled name and binary layout, depending on
+// the compiler flags passed by the end user. For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro. To check in the preprocessor if
+// absl::string_view is a typedef of std::string_view, use the feature macro
+// ABSL_USES_STD_STRING_VIEW.
+
+#define ABSL_OPTION_USE_STD_STRING_VIEW 2
+
+// ABSL_OPTION_USE_STD_VARIANT
+//
+// This option controls whether absl::variant is implemented as an alias to
+// std::variant, or as an independent implementation.
+//
+// A value of 0 means to use Abseil's implementation. This requires only C++11
+// support, and is expected to work on every toolchain we support.
+//
+// A value of 1 means to use an alias to std::variant. This requires that all
+// code using Abseil is built in C++17 mode or later.
+//
+// A value of 2 means to detect the C++ version being used to compile Abseil,
+// and use an alias only if a working std::variant is available. This option
+// is useful when you are building your program from source. It should not be
+// used otherwise -- for example, if you are distributing Abseil in a binary
+// package manager -- since in mode 2, absl::variant will name a different
+// type, with a different mangled name and binary layout, depending on the
+// compiler flags passed by the end user. For more info, see
+// https://abseil.io/about/design/dropin-types.
+//
+// User code should not inspect this macro. To check in the preprocessor if
+// absl::variant is a typedef of std::variant, use the feature macro
+// ABSL_USES_STD_VARIANT.
+
+#define ABSL_OPTION_USE_STD_VARIANT 2
+
+
+// ABSL_OPTION_USE_INLINE_NAMESPACE
+// ABSL_OPTION_INLINE_NAMESPACE_NAME
+//
+// These options controls whether all entities in the absl namespace are
+// contained within an inner inline namespace. This does not affect the
+// user-visible API of Abseil, but it changes the mangled names of all symbols.
+//
+// This can be useful as a version tag if you are distributing Abseil in
+// precompiled form. This will prevent a binary library build of Abseil with
+// one inline namespace being used with headers configured with a different
+// inline namespace name. Binary packagers are reminded that Abseil does not
+// guarantee any ABI stability in Abseil, so any update of Abseil or
+// configuration change in such a binary package should be combined with a
+// new, unique value for the inline namespace name.
+//
+// A value of 0 means not to use inline namespaces.
+//
+// A value of 1 means to use an inline namespace with the given name inside
+// namespace absl. If this is set, ABSL_OPTION_INLINE_NAMESPACE_NAME must also
+// be changed to a new, unique identifier name. In particular "head" is not
+// allowed.
+
+#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20210324
+
+// ABSL_OPTION_HARDENED
+//
+// This option enables a "hardened" build in release mode (in this context,
+// release mode is defined as a build where the `NDEBUG` macro is defined).
+//
+// A value of 0 means that "hardened" mode is not enabled.
+//
+// A value of 1 means that "hardened" mode is enabled.
+//
+// Hardened builds have additional security checks enabled when `NDEBUG` is
+// defined. Defining `NDEBUG` is normally used to turn `assert()` macro into a
+// no-op, as well as disabling other bespoke program consistency checks. By
+// defining ABSL_OPTION_HARDENED to 1, a select set of checks remain enabled in
+// release mode. These checks guard against programming errors that may lead to
+// security vulnerabilities. In release mode, when one of these programming
+// errors is encountered, the program will immediately abort, possibly without
+// any attempt at logging.
+//
+// The checks enabled by this option are not free; they do incur runtime cost.
+//
+// The checks enabled by this option are always active when `NDEBUG` is not
+// defined, even in the case when ABSL_OPTION_HARDENED is defined to 0. The
+// checks enabled by this option may abort the program in a different way and
+// log additional information when `NDEBUG` is not defined.
+
+#define ABSL_OPTION_HARDENED 0
+
+#endif // ABSL_BASE_OPTIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/policy_checks.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/policy_checks.h
index 0a07fc035e1..06b32439168 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/policy_checks.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/policy_checks.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -41,7 +41,7 @@
#endif
// -----------------------------------------------------------------------------
-// Compiler Check
+// Toolchain Check
// -----------------------------------------------------------------------------
// We support MSVC++ 14.0 update 2 and later.
@@ -82,16 +82,6 @@
// Standard Library Check
// -----------------------------------------------------------------------------
-// We have chosen glibc 2.12 as the minimum as it was tagged for release
-// in May, 2010 and includes some functionality used in Google software
-// (for instance pthread_setname_np):
-// https://sourceware.org/ml/libc-alpha/2010-05/msg00000.html
-#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
-#if !__GLIBC_PREREQ(2, 12)
-#error "Minimum required version of glibc is 2.12."
-#endif
-#endif
-
#if defined(_STLPORT_VERSION)
#error "STLPort is not supported."
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/port.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/port.h
index 1c67257fd8f..5bc4d6cd95d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/port.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/port.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,6 @@
//
// This files is a forwarding header for other headers containing various
// portability macros and functions.
-// This file is used for both C and C++!
#ifndef ABSL_BASE_PORT_H_
#define ABSL_BASE_PORT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/raw_logging_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/raw_logging_test.cc
index b21cf651758..3d30bd38611 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/raw_logging_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/raw_logging_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/spinlock_test_common.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/spinlock_test_common.cc
index 191708130f3..2b572c5b3ff 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/spinlock_test_common.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/spinlock_test_common.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,10 +20,12 @@
#include <limits>
#include <random>
#include <thread> // NOLINT(build/c++11)
+#include <type_traits>
#include <vector>
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/low_level_scheduling.h"
#include "absl/base/internal/scheduling_mode.h"
#include "absl/base/internal/spinlock.h"
@@ -36,6 +38,7 @@ constexpr int32_t kNumThreads = 10;
constexpr int32_t kIters = 1000;
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace base_internal {
// This is defined outside of anonymous namespace so that it can be
@@ -54,13 +57,11 @@ namespace {
static constexpr int kArrayLength = 10;
static uint32_t values[kArrayLength];
-static SpinLock static_spinlock(base_internal::kLinkerInitialized);
-static SpinLock static_cooperative_spinlock(
- base_internal::kLinkerInitialized,
- base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
-static SpinLock static_noncooperative_spinlock(
- base_internal::kLinkerInitialized, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static SpinLock static_cooperative_spinlock(
+ absl::kConstInit, base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL);
+ABSL_CONST_INIT static SpinLock static_noncooperative_spinlock(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
// Simple integer hash function based on the public domain lookup2 hash.
// http://burtleburtle.net/bob/c/lookup2.c
@@ -91,6 +92,7 @@ static void TestFunction(int thread_salt, SpinLock* spinlock) {
static void ThreadedTest(SpinLock* spinlock) {
std::vector<std::thread> threads;
+ threads.reserve(kNumThreads);
for (int i = 0; i < kNumThreads; ++i) {
threads.push_back(std::thread(TestFunction, i, spinlock));
}
@@ -104,6 +106,10 @@ static void ThreadedTest(SpinLock* spinlock) {
}
}
+#ifndef ABSL_HAVE_THREAD_SANITIZER
+static_assert(std::is_trivially_destructible<SpinLock>(), "");
+#endif
+
TEST(SpinLock, StackNonCooperativeDisablesScheduling) {
SpinLock spinlock(base_internal::SCHEDULE_KERNEL_ONLY);
spinlock.Lock();
@@ -189,9 +195,7 @@ TEST(SpinLock, WaitCyclesEncoding) {
SpinLockTest::DecodeWaitCycles(before_max_value);
EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
}
-TEST(SpinLockWithThreads, StaticSpinLock) {
- ThreadedTest(&static_spinlock);
-}
+
TEST(SpinLockWithThreads, StackSpinLock) {
SpinLock spinlock;
ThreadedTest(&spinlock);
@@ -264,4 +268,5 @@ TEST(SpinLockWithThreads, DoesNotDeadlock) {
} // namespace
} // namespace base_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/thread_annotations.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/thread_annotations.h
index 2241ace4a47..9695f6de67a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/thread_annotations.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/thread_annotations.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,7 +21,6 @@
// code. The annotations can also help program analysis tools to identify
// potential thread safety issues.
//
-//
// These annotations are implemented using compiler attributes. Using the macros
// defined here instead of raw attributes allow for portability and future
// compatibility.
@@ -34,19 +33,19 @@
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
-#if defined(__clang__)
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
-#else
-#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op
-#endif
-// GUARDED_BY()
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+// TODO(mbonadei): Remove after the backward compatibility period.
+#include "absl/base/internal/thread_annotations.h" // IWYU pragma: export
+
+// ABSL_GUARDED_BY()
//
// Documents if a shared field or global variable needs to be protected by a
-// mutex. GUARDED_BY() allows the user to specify a particular mutex that
+// mutex. ABSL_GUARDED_BY() allows the user to specify a particular mutex that
// should be held when accessing the annotated variable.
//
-// Although this annotation (and PT_GUARDED_BY, below) cannot be applied to
+// Although this annotation (and ABSL_PT_GUARDED_BY, below) cannot be applied to
// local variables, a local variable and its associated mutex can often be
// combined into a small class or struct, thereby allowing the annotation.
//
@@ -54,12 +53,16 @@
//
// class Foo {
// Mutex mu_;
-// int p1_ GUARDED_BY(mu_);
+// int p1_ ABSL_GUARDED_BY(mu_);
// ...
// };
-#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
+#if ABSL_HAVE_ATTRIBUTE(guarded_by)
+#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
+#else
+#define ABSL_GUARDED_BY(x)
+#endif
-// PT_GUARDED_BY()
+// ABSL_PT_GUARDED_BY()
//
// Documents if the memory location pointed to by a pointer should be guarded
// by a mutex when dereferencing the pointer.
@@ -67,7 +70,7 @@
// Example:
// class Foo {
// Mutex mu_;
-// int *p1_ PT_GUARDED_BY(mu_);
+// int *p1_ ABSL_PT_GUARDED_BY(mu_);
// ...
// };
//
@@ -78,31 +81,41 @@
//
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
// // guarded by `mu2_`:
-// int *q_ GUARDED_BY(mu1_) PT_GUARDED_BY(mu2_);
-#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
+// int *q_ ABSL_GUARDED_BY(mu1_) ABSL_PT_GUARDED_BY(mu2_);
+#if ABSL_HAVE_ATTRIBUTE(pt_guarded_by)
+#define ABSL_PT_GUARDED_BY(x) __attribute__((pt_guarded_by(x)))
+#else
+#define ABSL_PT_GUARDED_BY(x)
+#endif
-// ACQUIRED_AFTER() / ACQUIRED_BEFORE()
+// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
//
// Documents the acquisition order between locks that can be held
// simultaneously by a thread. For any two locks that need to be annotated
// to establish an acquisition order, only one of them needs the annotation.
-// (i.e. You don't have to annotate both locks with both ACQUIRED_AFTER
-// and ACQUIRED_BEFORE.)
+// (i.e. You don't have to annotate both locks with both ABSL_ACQUIRED_AFTER
+// and ABSL_ACQUIRED_BEFORE.)
//
-// As with GUARDED_BY, this is only applicable to mutexes that are shared
+// As with ABSL_GUARDED_BY, this is only applicable to mutexes that are shared
// fields or global variables.
//
// Example:
//
// Mutex m1_;
-// Mutex m2_ ACQUIRED_AFTER(m1_);
-#define ACQUIRED_AFTER(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+// Mutex m2_ ABSL_ACQUIRED_AFTER(m1_);
+#if ABSL_HAVE_ATTRIBUTE(acquired_after)
+#define ABSL_ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_AFTER(...)
+#endif
-#define ACQUIRED_BEFORE(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(acquired_before)
+#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
+#else
+#define ABSL_ACQUIRED_BEFORE(...)
+#endif
-// EXCLUSIVE_LOCKS_REQUIRED() / SHARED_LOCKS_REQUIRED()
+// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
//
// Documents a function that expects a mutex to be held prior to entry.
// The mutex is expected to be held both on entry to, and exit from, the
@@ -114,77 +127,108 @@
// concurrently.
//
// Generally, non-const methods should be annotated with
-// EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
-// SHARED_LOCKS_REQUIRED.
+// ABSL_EXCLUSIVE_LOCKS_REQUIRED, while const methods should be annotated with
+// ABSL_SHARED_LOCKS_REQUIRED.
//
// Example:
//
// Mutex mu1, mu2;
-// int a GUARDED_BY(mu1);
-// int b GUARDED_BY(mu2);
-//
-// void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
-// void bar() const SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
-#define EXCLUSIVE_LOCKS_REQUIRED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
+// int a ABSL_GUARDED_BY(mu1);
+// int b ABSL_GUARDED_BY(mu2);
+//
+// void foo() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) { ... }
+// void bar() const ABSL_SHARED_LOCKS_REQUIRED(mu1, mu2) { ... }
+#if ABSL_HAVE_ATTRIBUTE(exclusive_locks_required)
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
+ __attribute__((exclusive_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCKS_REQUIRED(...)
+#endif
-#define SHARED_LOCKS_REQUIRED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(shared_locks_required)
+#define ABSL_SHARED_LOCKS_REQUIRED(...) \
+ __attribute__((shared_locks_required(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCKS_REQUIRED(...)
+#endif
-// LOCKS_EXCLUDED()
+// ABSL_LOCKS_EXCLUDED()
//
// Documents the locks acquired in the body of the function. These locks
// cannot be held when calling this function (as Abseil's `Mutex` locks are
// non-reentrant).
-#define LOCKS_EXCLUDED(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
+#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
+#else
+#define ABSL_LOCKS_EXCLUDED(...)
+#endif
-// LOCK_RETURNED()
+// ABSL_LOCK_RETURNED()
//
// Documents a function that returns a mutex without acquiring it. For example,
// a public getter method that returns a pointer to a private mutex should
-// be annotated with LOCK_RETURNED.
-#define LOCK_RETURNED(x) \
- THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+// be annotated with ABSL_LOCK_RETURNED.
+#if ABSL_HAVE_ATTRIBUTE(lock_returned)
+#define ABSL_LOCK_RETURNED(x) __attribute__((lock_returned(x)))
+#else
+#define ABSL_LOCK_RETURNED(x)
+#endif
-// LOCKABLE
+// ABSL_LOCKABLE
//
// Documents if a class/type is a lockable type (such as the `Mutex` class).
-#define LOCKABLE \
- THREAD_ANNOTATION_ATTRIBUTE__(lockable)
+#if ABSL_HAVE_ATTRIBUTE(lockable)
+#define ABSL_LOCKABLE __attribute__((lockable))
+#else
+#define ABSL_LOCKABLE
+#endif
-// SCOPED_LOCKABLE
+// ABSL_SCOPED_LOCKABLE
//
// Documents if a class does RAII locking (such as the `MutexLock` class).
// The constructor should use `LOCK_FUNCTION()` to specify the mutex that is
// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
// arguments; the analysis will assume that the destructor unlocks whatever the
// constructor locked.
-#define SCOPED_LOCKABLE \
- THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
+#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
+#else
+#define ABSL_SCOPED_LOCKABLE
+#endif
-// EXCLUSIVE_LOCK_FUNCTION()
+// ABSL_EXCLUSIVE_LOCK_FUNCTION()
//
// Documents functions that acquire a lock in the body of a function, and do
// not release it.
-#define EXCLUSIVE_LOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_lock_function)
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
+ __attribute__((exclusive_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...)
+#endif
-// SHARED_LOCK_FUNCTION()
+// ABSL_SHARED_LOCK_FUNCTION()
//
// Documents functions that acquire a shared (reader) lock in the body of a
// function, and do not release it.
-#define SHARED_LOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(shared_lock_function)
+#define ABSL_SHARED_LOCK_FUNCTION(...) \
+ __attribute__((shared_lock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_LOCK_FUNCTION(...)
+#endif
-// UNLOCK_FUNCTION()
+// ABSL_UNLOCK_FUNCTION()
//
// Documents functions that expect a lock to be held on entry to the function,
// and release it in the body of the function.
-#define UNLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(unlock_function)
+#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
+#else
+#define ABSL_UNLOCK_FUNCTION(...)
+#endif
-// EXCLUSIVE_TRYLOCK_FUNCTION() / SHARED_TRYLOCK_FUNCTION()
+// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
//
// Documents functions that try to acquire a lock, and return success or failure
// (or a non-boolean value that can be interpreted as a boolean).
@@ -192,76 +236,100 @@
// success, or `false` for functions that return `false` on success. The second
// argument specifies the mutex that is locked on success. If unspecified, this
// mutex is assumed to be `this`.
-#define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(exclusive_trylock_function)
+#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+ __attribute__((exclusive_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(...)
+#endif
-#define SHARED_TRYLOCK_FUNCTION(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(shared_trylock_function)
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
+ __attribute__((shared_trylock_function(__VA_ARGS__)))
+#else
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...)
+#endif
-// ASSERT_EXCLUSIVE_LOCK() / ASSERT_SHARED_LOCK()
+// ABSL_ASSERT_EXCLUSIVE_LOCK() / ABSL_ASSERT_SHARED_LOCK()
//
// Documents functions that dynamically check to see if a lock is held, and fail
// if it is not held.
-#define ASSERT_EXCLUSIVE_LOCK(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(assert_exclusive_lock)
+#define ABSL_ASSERT_EXCLUSIVE_LOCK(...) \
+ __attribute__((assert_exclusive_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_EXCLUSIVE_LOCK(...)
+#endif
-#define ASSERT_SHARED_LOCK(...) \
- THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
+#if ABSL_HAVE_ATTRIBUTE(assert_shared_lock)
+#define ABSL_ASSERT_SHARED_LOCK(...) \
+ __attribute__((assert_shared_lock(__VA_ARGS__)))
+#else
+#define ABSL_ASSERT_SHARED_LOCK(...)
+#endif
-// NO_THREAD_SAFETY_ANALYSIS
+// ABSL_NO_THREAD_SAFETY_ANALYSIS
//
// Turns off thread safety checking within the body of a particular function.
// This annotation is used to mark functions that are known to be correct, but
// the locking behavior is more complicated than the analyzer can handle.
-#define NO_THREAD_SAFETY_ANALYSIS \
- THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
+#if ABSL_HAVE_ATTRIBUTE(no_thread_safety_analysis)
+#define ABSL_NO_THREAD_SAFETY_ANALYSIS \
+ __attribute__((no_thread_safety_analysis))
+#else
+#define ABSL_NO_THREAD_SAFETY_ANALYSIS
+#endif
//------------------------------------------------------------------------------
// Tool-Supplied Annotations
//------------------------------------------------------------------------------
-// TS_UNCHECKED should be placed around lock expressions that are not valid
+// ABSL_TS_UNCHECKED should be placed around lock expressions that are not valid
// C++ syntax, but which are present for documentation purposes. These
// annotations will be ignored by the analysis.
-#define TS_UNCHECKED(x) ""
+#define ABSL_TS_UNCHECKED(x) ""
-// TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
+// ABSL_TS_FIXME is used to mark lock expressions that are not valid C++ syntax.
// It is used by automated tools to mark and disable invalid expressions.
-// The annotation should either be fixed, or changed to TS_UNCHECKED.
-#define TS_FIXME(x) ""
+// The annotation should either be fixed, or changed to ABSL_TS_UNCHECKED.
+#define ABSL_TS_FIXME(x) ""
-// Like NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body of
-// a particular function. However, this attribute is used to mark functions
+// Like ABSL_NO_THREAD_SAFETY_ANALYSIS, this turns off checking within the body
+// of a particular function. However, this attribute is used to mark functions
// that are incorrect and need to be fixed. It is used by automated tools to
// avoid breaking the build when the analysis is updated.
// Code owners are expected to eventually fix the routine.
-#define NO_THREAD_SAFETY_ANALYSIS_FIXME NO_THREAD_SAFETY_ANALYSIS
+#define ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME ABSL_NO_THREAD_SAFETY_ANALYSIS
-// Similar to NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a GUARDED_BY
-// annotation that needs to be fixed, because it is producing thread safety
-// warning. It disables the GUARDED_BY.
-#define GUARDED_BY_FIXME(x)
+// Similar to ABSL_NO_THREAD_SAFETY_ANALYSIS_FIXME, this macro marks a
+// ABSL_GUARDED_BY annotation that needs to be fixed, because it is producing
+// thread safety warning. It disables the ABSL_GUARDED_BY.
+#define ABSL_GUARDED_BY_FIXME(x)
// Disables warnings for a single read operation. This can be used to avoid
// warnings when it is known that the read is not actually involved in a race,
// but the compiler cannot confirm that.
-#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
-
+#define ABSL_TS_UNCHECKED_READ(x) absl::base_internal::ts_unchecked_read(x)
-namespace thread_safety_analysis {
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
// Takes a reference to a guarded data member, and returns an unguarded
// reference.
+// Do not use this function directly, use ABSL_TS_UNCHECKED_READ instead.
template <typename T>
-inline const T& ts_unchecked_read(const T& v) NO_THREAD_SAFETY_ANALYSIS {
+inline const T& ts_unchecked_read(const T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
}
template <typename T>
-inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
+inline T& ts_unchecked_read(T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
}
-} // namespace thread_safety_analysis
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // namespace absl
#endif // ABSL_BASE_THREAD_ANNOTATIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/throw_delegate_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/throw_delegate_test.cc
index 0f15df0492b..5ba4ce55e6d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/throw_delegate_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/base/throw_delegate_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#include <new>
#include <stdexcept>
+#include "absl/base/config.h"
#include "gtest/gtest.h"
namespace {
@@ -38,31 +39,43 @@ constexpr const char* what_arg = "The quick brown fox jumps over the lazy dog";
template <typename E>
void ExpectThrowChar(void (*f)(const char*)) {
+#ifdef ABSL_HAVE_EXCEPTIONS
try {
f(what_arg);
FAIL() << "Didn't throw";
} catch (const E& e) {
EXPECT_STREQ(e.what(), what_arg);
}
+#else
+ EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg);
+#endif
}
template <typename E>
void ExpectThrowString(void (*f)(const std::string&)) {
+#ifdef ABSL_HAVE_EXCEPTIONS
try {
f(what_arg);
FAIL() << "Didn't throw";
} catch (const E& e) {
EXPECT_STREQ(e.what(), what_arg);
}
+#else
+ EXPECT_DEATH_IF_SUPPORTED(f(what_arg), what_arg);
+#endif
}
template <typename E>
void ExpectThrowNoWhat(void (*f)()) {
+#ifdef ABSL_HAVE_EXCEPTIONS
try {
f();
FAIL() << "Didn't throw";
} catch (const E& e) {
}
+#else
+ EXPECT_DEATH_IF_SUPPORTED(f(), "");
+#endif
}
TEST(ThrowHelper, Test) {
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/BUILD.bazel
new file mode 100644
index 00000000000..5cca898f32f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/BUILD.bazel
@@ -0,0 +1,66 @@
+# 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.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "cleanup_internal",
+ hdrs = ["internal/cleanup.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:base_internal",
+ "//absl/base:core_headers",
+ "//absl/utility",
+ ],
+)
+
+cc_library(
+ name = "cleanup",
+ hdrs = [
+ "cleanup.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":cleanup_internal",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_test(
+ name = "cleanup_test",
+ size = "small",
+ srcs = [
+ "cleanup_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":cleanup",
+ "//absl/base:config",
+ "//absl/utility",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup.h
new file mode 100644
index 00000000000..61b53d5531a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup.h
@@ -0,0 +1,140 @@
+// Copyright 2021 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: cleanup.h
+// -----------------------------------------------------------------------------
+//
+// `absl::Cleanup` implements the scope guard idiom, invoking the contained
+// callback's `operator()() &&` on scope exit.
+//
+// Example:
+//
+// ```
+// absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
+// FILE* source_file = fopen(source_path, "r");
+// if (source_file == nullptr) {
+// return absl::NotFoundError("No source file"); // No cleanups execute
+// }
+//
+// // C++17 style cleanup using class template argument deduction
+// absl::Cleanup source_closer = [source_file] { fclose(source_file); };
+//
+// FILE* sink_file = fopen(sink_path, "w");
+// if (sink_file == nullptr) {
+// return absl::NotFoundError("No sink file"); // First cleanup executes
+// }
+//
+// // C++11 style cleanup using the factory function
+// auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
+//
+// Data data;
+// while (ReadData(source_file, &data)) {
+// if (!data.IsGood()) {
+// absl::Status result = absl::FailedPreconditionError("Read bad data");
+// return result; // Both cleanups execute
+// }
+// SaveData(sink_file, &data);
+// }
+//
+// return absl::OkStatus(); // Both cleanups execute
+// }
+// ```
+//
+// Methods:
+//
+// `std::move(cleanup).Cancel()` will prevent the callback from executing.
+//
+// `std::move(cleanup).Invoke()` will execute the callback early, before
+// destruction, and prevent the callback from executing in the destructor.
+//
+// Usage:
+//
+// `absl::Cleanup` is not an interface type. It is only intended to be used
+// within the body of a function. It is not a value type and instead models a
+// control flow construct. Check out `defer` in Golang for something similar.
+
+#ifndef ABSL_CLEANUP_CLEANUP_H_
+#define ABSL_CLEANUP_CLEANUP_H_
+
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/macros.h"
+#include "absl/cleanup/internal/cleanup.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename Arg, typename Callback = void()>
+class ABSL_MUST_USE_RESULT Cleanup final {
+ static_assert(cleanup_internal::WasDeduced<Arg>(),
+ "Explicit template parameters are not supported.");
+
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
+ "Callbacks that return values are not supported.");
+
+ public:
+ Cleanup(Callback callback) // NOLINT
+ : storage_(std::move(callback), /* is_callback_engaged = */ true) {}
+
+ Cleanup(Cleanup&& other) = default;
+
+ void Cancel() && {
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
+ storage_.DisengageCallback();
+ }
+
+ void Invoke() && {
+ ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
+ storage_.DisengageCallback();
+ storage_.InvokeCallback();
+ }
+
+ ~Cleanup() {
+ if (storage_.IsCallbackEngaged()) {
+ storage_.InvokeCallback();
+ }
+ }
+
+ private:
+ cleanup_internal::Storage<Callback> storage_;
+};
+
+// `absl::Cleanup c = /* callback */;`
+//
+// C++17 type deduction API for creating an instance of `absl::Cleanup`
+#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+template <typename Callback>
+Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
+#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+
+// `auto c = absl::MakeCleanup(/* callback */);`
+//
+// C++11 type deduction API for creating an instance of `absl::Cleanup`
+template <typename... Args, typename Callback>
+absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
+ static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
+ "Explicit template parameters are not supported.");
+
+ static_assert(cleanup_internal::ReturnsVoid<Callback>(),
+ "Callbacks that return values are not supported.");
+
+ return {std::move(callback)};
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CLEANUP_CLEANUP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup_test.cc
new file mode 100644
index 00000000000..792595d6cd8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/cleanup_test.cc
@@ -0,0 +1,267 @@
+// 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.
+
+#include "absl/cleanup/cleanup.h"
+
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/utility/utility.h"
+
+namespace {
+
+using Tag = absl::cleanup_internal::Tag;
+
+template <typename Type1, typename Type2>
+constexpr bool IsSame() {
+ return (std::is_same<Type1, Type2>::value);
+}
+
+struct IdentityFactory {
+ template <typename Callback>
+ static Callback AsCallback(Callback callback) {
+ return Callback(std::move(callback));
+ }
+};
+
+// `FunctorClass` is a type used for testing `absl::Cleanup`. It is intended to
+// represent users that make their own move-only callback types outside of
+// `std::function` and lambda literals.
+class FunctorClass {
+ using Callback = std::function<void()>;
+
+ public:
+ explicit FunctorClass(Callback callback) : callback_(std::move(callback)) {}
+
+ FunctorClass(FunctorClass&& other)
+ : callback_(absl::exchange(other.callback_, Callback())) {}
+
+ FunctorClass(const FunctorClass&) = delete;
+
+ FunctorClass& operator=(const FunctorClass&) = delete;
+
+ FunctorClass& operator=(FunctorClass&&) = delete;
+
+ void operator()() const& = delete;
+
+ void operator()() && {
+ ASSERT_TRUE(callback_);
+ callback_();
+ callback_ = nullptr;
+ }
+
+ private:
+ Callback callback_;
+};
+
+struct FunctorClassFactory {
+ template <typename Callback>
+ static FunctorClass AsCallback(Callback callback) {
+ return FunctorClass(std::move(callback));
+ }
+};
+
+struct StdFunctionFactory {
+ template <typename Callback>
+ static std::function<void()> AsCallback(Callback callback) {
+ return std::function<void()>(std::move(callback));
+ }
+};
+
+using CleanupTestParams =
+ ::testing::Types<IdentityFactory, FunctorClassFactory, StdFunctionFactory>;
+template <typename>
+struct CleanupTest : public ::testing::Test {};
+TYPED_TEST_SUITE(CleanupTest, CleanupTestParams);
+
+bool fn_ptr_called = false;
+void FnPtrFunction() { fn_ptr_called = true; }
+
+TYPED_TEST(CleanupTest, FactoryProducesCorrectType) {
+ {
+ auto callback = TypeParam::AsCallback([] {});
+ auto cleanup = absl::MakeCleanup(std::move(callback));
+
+ static_assert(
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
+ "");
+ }
+
+ {
+ auto cleanup = absl::MakeCleanup(&FnPtrFunction);
+
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
+ }
+
+ {
+ auto cleanup = absl::MakeCleanup(FnPtrFunction);
+
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
+ }
+}
+
+#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+TYPED_TEST(CleanupTest, CTADProducesCorrectType) {
+ {
+ auto callback = TypeParam::AsCallback([] {});
+ absl::Cleanup cleanup = std::move(callback);
+
+ static_assert(
+ IsSame<absl::Cleanup<Tag, decltype(callback)>, decltype(cleanup)>(),
+ "");
+ }
+
+ {
+ absl::Cleanup cleanup = &FnPtrFunction;
+
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
+ }
+
+ {
+ absl::Cleanup cleanup = FnPtrFunction;
+
+ static_assert(IsSame<absl::Cleanup<Tag, void (*)()>, decltype(cleanup)>(),
+ "");
+ }
+}
+
+TYPED_TEST(CleanupTest, FactoryAndCTADProduceSameType) {
+ {
+ auto callback = IdentityFactory::AsCallback([] {});
+ auto factory_cleanup = absl::MakeCleanup(callback);
+ absl::Cleanup deduction_cleanup = callback;
+
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
+ }
+
+ {
+ auto factory_cleanup =
+ absl::MakeCleanup(FunctorClassFactory::AsCallback([] {}));
+ absl::Cleanup deduction_cleanup = FunctorClassFactory::AsCallback([] {});
+
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
+ }
+
+ {
+ auto factory_cleanup =
+ absl::MakeCleanup(StdFunctionFactory::AsCallback([] {}));
+ absl::Cleanup deduction_cleanup = StdFunctionFactory::AsCallback([] {});
+
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
+ }
+
+ {
+ auto factory_cleanup = absl::MakeCleanup(&FnPtrFunction);
+ absl::Cleanup deduction_cleanup = &FnPtrFunction;
+
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
+ }
+
+ {
+ auto factory_cleanup = absl::MakeCleanup(FnPtrFunction);
+ absl::Cleanup deduction_cleanup = FnPtrFunction;
+
+ static_assert(
+ IsSame<decltype(factory_cleanup), decltype(deduction_cleanup)>(), "");
+ }
+}
+#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
+
+TYPED_TEST(CleanupTest, BasicUsage) {
+ bool called = false;
+
+ {
+ auto cleanup =
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+ }
+
+ EXPECT_TRUE(called); // Destructor should invoke the callback
+}
+
+TYPED_TEST(CleanupTest, BasicUsageWithFunctionPointer) {
+ fn_ptr_called = false;
+
+ {
+ auto cleanup = absl::MakeCleanup(TypeParam::AsCallback(&FnPtrFunction));
+ EXPECT_FALSE(fn_ptr_called); // Constructor shouldn't invoke the callback
+ }
+
+ EXPECT_TRUE(fn_ptr_called); // Destructor should invoke the callback
+}
+
+TYPED_TEST(CleanupTest, Cancel) {
+ bool called = false;
+
+ {
+ auto cleanup =
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+
+ std::move(cleanup).Cancel();
+ EXPECT_FALSE(called); // Cancel shouldn't invoke the callback
+ }
+
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
+}
+
+TYPED_TEST(CleanupTest, Invoke) {
+ bool called = false;
+
+ {
+ auto cleanup =
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+
+ std::move(cleanup).Invoke();
+ EXPECT_TRUE(called); // Invoke should invoke the callback
+
+ called = false; // Reset tracker before destructor runs
+ }
+
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
+}
+
+TYPED_TEST(CleanupTest, Move) {
+ bool called = false;
+
+ {
+ auto moved_from_cleanup =
+ absl::MakeCleanup(TypeParam::AsCallback([&called] { called = true; }));
+ EXPECT_FALSE(called); // Constructor shouldn't invoke the callback
+
+ {
+ auto moved_to_cleanup = std::move(moved_from_cleanup);
+ EXPECT_FALSE(called); // Move shouldn't invoke the callback
+ }
+
+ EXPECT_TRUE(called); // Destructor should invoke the callback
+
+ called = false; // Reset tracker before destructor runs
+ }
+
+ EXPECT_FALSE(called); // Destructor shouldn't invoke the callback
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/internal/cleanup.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/internal/cleanup.h
new file mode 100644
index 00000000000..b4c40737472
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/cleanup/internal/cleanup.h
@@ -0,0 +1,81 @@
+// Copyright 2021 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_
+#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace cleanup_internal {
+
+struct Tag {};
+
+template <typename Arg, typename... Args>
+constexpr bool WasDeduced() {
+ return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
+ (sizeof...(Args) == 0);
+}
+
+template <typename Callback>
+constexpr bool ReturnsVoid() {
+ return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
+}
+
+template <typename Callback>
+class Storage {
+ public:
+ Storage() = delete;
+
+ Storage(Callback callback, bool is_callback_engaged)
+ : callback_(std::move(callback)),
+ is_callback_engaged_(is_callback_engaged) {}
+
+ Storage(Storage&& other)
+ : callback_(std::move(other.callback_)),
+ is_callback_engaged_(
+ absl::exchange(other.is_callback_engaged_, false)) {}
+
+ Storage(const Storage& other) = delete;
+
+ Storage& operator=(Storage&& other) = delete;
+
+ Storage& operator=(const Storage& other) = delete;
+
+ bool IsCallbackEngaged() const { return is_callback_engaged_; }
+
+ void DisengageCallback() { is_callback_engaged_ = false; }
+
+ void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
+ std::move(callback_)();
+ }
+
+ private:
+ Callback callback_;
+ bool is_callback_engaged_;
+};
+
+} // namespace cleanup_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/compiler_config_setting.bzl b/src/third_party/abseil-cpp-master/abseil-cpp/absl/compiler_config_setting.bzl
deleted file mode 100644
index b77c4f563b9..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/compiler_config_setting.bzl
+++ /dev/null
@@ -1,39 +0,0 @@
-#
-# 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
-#
-# http://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.
-#
-
-"""Creates config_setting that allows selecting based on 'compiler' value."""
-
-def create_llvm_config(name, visibility):
- # The "do_not_use_tools_cpp_compiler_present" attribute exists to
- # distinguish between older versions of Bazel that do not support
- # "@bazel_tools//tools/cpp:compiler" flag_value, and newer ones that do.
- # In the future, the only way to select on the compiler will be through
- # flag_values{"@bazel_tools//tools/cpp:compiler"} and the else branch can
- # be removed.
- if hasattr(cc_common, "do_not_use_tools_cpp_compiler_present"):
- native.config_setting(
- name = name,
- flag_values = {
- "@bazel_tools//tools/cpp:compiler": "llvm",
- },
- visibility = visibility,
- )
- else:
- native.config_setting(
- name = name,
- values = {"compiler": "llvm"},
- visibility = visibility,
- )
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/BUILD.bazel
index b9d1025a260..f22fdc606f0 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,22 +14,23 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
- "ABSL_EXCEPTIONS_FLAG",
- "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "compressed_tuple",
hdrs = ["internal/compressed_tuple.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/utility",
],
@@ -39,9 +40,13 @@ cc_test(
name = "compressed_tuple_test",
srcs = ["internal/compressed_tuple_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":compressed_tuple",
+ ":test_instance_tracker",
"//absl/memory",
+ "//absl/types:any",
+ "//absl/types:optional",
"//absl/utility",
"@com_google_googletest//:gtest_main",
],
@@ -51,9 +56,11 @@ cc_library(
name = "fixed_array",
hdrs = ["fixed_array.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":compressed_tuple",
"//absl/algorithm",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
"//absl/base:throw_delegate",
@@ -64,23 +71,12 @@ cc_library(
cc_test(
name = "fixed_array_test",
srcs = ["fixed_array_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
- deps = [
- ":fixed_array",
- "//absl/base:exception_testing",
- "//absl/hash:hash_testing",
- "//absl/memory",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "fixed_array_test_noexceptions",
- srcs = ["fixed_array_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":counting_allocator",
":fixed_array",
+ "//absl/base:config",
"//absl/base:exception_testing",
"//absl/hash:hash_testing",
"//absl/memory",
@@ -91,10 +87,11 @@ cc_test(
cc_test(
name = "fixed_array_exception_safety_test",
srcs = ["fixed_array_exception_safety_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":fixed_array",
+ "//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
@@ -104,6 +101,7 @@ cc_test(
name = "fixed_array_benchmark",
srcs = ["fixed_array_benchmark.cc"],
copts = ABSL_TEST_COPTS + ["$(STACK_FRAME_UNLIMITED)"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":fixed_array",
@@ -112,10 +110,26 @@ cc_test(
)
cc_library(
+ name = "inlined_vector_internal",
+ hdrs = ["internal/inlined_vector.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":compressed_tuple",
+ "//absl/base:core_headers",
+ "//absl/memory",
+ "//absl/meta:type_traits",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
name = "inlined_vector",
hdrs = ["inlined_vector.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":inlined_vector_internal",
"//absl/algorithm",
"//absl/base:core_headers",
"//absl/base:throw_delegate",
@@ -123,17 +137,29 @@ cc_library(
],
)
+cc_library(
+ name = "counting_allocator",
+ testonly = 1,
+ hdrs = ["internal/counting_allocator.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+ deps = ["//absl/base:config"],
+)
+
cc_test(
name = "inlined_vector_test",
srcs = ["inlined_vector_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":counting_allocator",
":inlined_vector",
":test_instance_tracker",
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:exception_testing",
+ "//absl/base:raw_logging_internal",
"//absl/hash:hash_testing",
"//absl/memory",
"//absl/strings",
@@ -142,32 +168,29 @@ cc_test(
)
cc_test(
- name = "inlined_vector_test_noexceptions",
- srcs = ["inlined_vector_test.cc"],
+ name = "inlined_vector_benchmark",
+ srcs = ["inlined_vector_benchmark.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
deps = [
":inlined_vector",
- ":test_instance_tracker",
- "//absl/base",
"//absl/base:core_headers",
- "//absl/base:exception_testing",
- "//absl/hash:hash_testing",
- "//absl/memory",
+ "//absl/base:raw_logging_internal",
"//absl/strings",
- "@com_google_googletest//:gtest_main",
+ "@com_github_google_benchmark//:benchmark_main",
],
)
cc_test(
- name = "inlined_vector_benchmark",
- srcs = ["inlined_vector_benchmark.cc"],
+ name = "inlined_vector_exception_safety_test",
+ srcs = ["inlined_vector_exception_safety_test.cc"],
copts = ABSL_TEST_COPTS,
- tags = ["benchmark"],
deps = [
":inlined_vector",
- "//absl/base",
- "//absl/strings",
- "@com_github_google_benchmark//:benchmark_main",
+ "//absl/base:config",
+ "//absl/base:exception_safety_testing",
+ "@com_google_googletest//:gtest_main",
],
)
@@ -177,15 +200,18 @@ cc_library(
srcs = ["internal/test_instance_tracker.cc"],
hdrs = ["internal/test_instance_tracker.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
+ deps = ["//absl/types:compare"],
)
cc_test(
name = "test_instance_tracker_test",
srcs = ["internal/test_instance_tracker_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":test_instance_tracker",
"@com_google_googletest//:gtest_main",
@@ -210,6 +236,7 @@ cc_library(
name = "flat_hash_map",
hdrs = ["flat_hash_map.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":container_memory",
":hash_function_defaults",
@@ -222,14 +249,17 @@ cc_library(
cc_test(
name = "flat_hash_map_test",
srcs = ["flat_hash_map_test.cc"],
- copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":flat_hash_map",
":hash_generator_testing",
":unordered_map_constructor_test",
":unordered_map_lookup_test",
+ ":unordered_map_members_test",
":unordered_map_modifiers_test",
+ "//absl/base:raw_logging_internal",
"//absl/types:any",
"@com_google_googletest//:gtest_main",
],
@@ -239,6 +269,7 @@ cc_library(
name = "flat_hash_set",
hdrs = ["flat_hash_set.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":container_memory",
":hash_function_defaults",
@@ -253,13 +284,16 @@ cc_test(
name = "flat_hash_set_test",
srcs = ["flat_hash_set_test.cc"],
copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":flat_hash_set",
":hash_generator_testing",
":unordered_set_constructor_test",
":unordered_set_lookup_test",
+ ":unordered_set_members_test",
":unordered_set_modifiers_test",
+ "//absl/base:raw_logging_internal",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest_main",
@@ -270,6 +304,7 @@ cc_library(
name = "node_hash_map",
hdrs = ["node_hash_map.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":container_memory",
":hash_function_defaults",
@@ -283,7 +318,8 @@ cc_library(
cc_test(
name = "node_hash_map_test",
srcs = ["node_hash_map_test.cc"],
- copts = ABSL_TEST_COPTS + ["-DUNORDERED_MAP_CXX17"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":hash_generator_testing",
@@ -291,6 +327,7 @@ cc_test(
":tracked",
":unordered_map_constructor_test",
":unordered_map_lookup_test",
+ ":unordered_map_members_test",
":unordered_map_modifiers_test",
"@com_google_googletest//:gtest_main",
],
@@ -300,6 +337,7 @@ cc_library(
name = "node_hash_set",
hdrs = ["node_hash_set.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_function_defaults",
":node_hash_policy",
@@ -313,12 +351,13 @@ cc_test(
name = "node_hash_set_test",
srcs = ["node_hash_set_test.cc"],
copts = ABSL_TEST_COPTS + ["-DUNORDERED_SET_CXX17"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
- ":hash_generator_testing",
":node_hash_set",
":unordered_set_constructor_test",
":unordered_set_lookup_test",
+ ":unordered_set_members_test",
":unordered_set_modifiers_test",
"@com_google_googletest//:gtest_main",
],
@@ -328,8 +367,11 @@ cc_library(
name = "container_memory",
hdrs = ["internal/container_memory.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ "//absl/base:config",
"//absl/memory",
+ "//absl/meta:type_traits",
"//absl/utility",
],
)
@@ -338,9 +380,11 @@ cc_test(
name = "container_memory_test",
srcs = ["internal/container_memory_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":container_memory",
+ ":test_instance_tracker",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
@@ -350,10 +394,12 @@ cc_library(
name = "hash_function_defaults",
hdrs = ["internal/hash_function_defaults.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:config",
"//absl/hash",
"//absl/strings",
+ "//absl/strings:cord",
],
)
@@ -361,11 +407,15 @@ cc_test(
name = "hash_function_defaults_test",
srcs = ["internal/hash_function_defaults_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS,
deps = [
":hash_function_defaults",
"//absl/hash",
+ "//absl/random",
"//absl/strings",
+ "//absl/strings:cord",
+ "//absl/strings:cord_test_helpers",
"@com_google_googletest//:gtest_main",
],
)
@@ -376,8 +426,10 @@ cc_library(
srcs = ["internal/hash_generator_testing.cc"],
hdrs = ["internal/hash_generator_testing.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_testing",
+ "//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
],
@@ -388,6 +440,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/hash_policy_testing.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/hash",
"//absl/strings",
@@ -398,6 +451,7 @@ cc_test(
name = "hash_policy_testing_test",
srcs = ["internal/hash_policy_testing_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_testing",
"@com_google_googletest//:gtest_main",
@@ -408,6 +462,7 @@ cc_library(
name = "hash_policy_traits",
hdrs = ["internal/hash_policy_traits.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = ["//absl/meta:type_traits"],
)
@@ -415,6 +470,7 @@ cc_test(
name = "hash_policy_traits_test",
srcs = ["internal/hash_policy_traits_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_traits",
"@com_google_googletest//:gtest_main",
@@ -425,6 +481,7 @@ cc_library(
name = "hashtable_debug",
hdrs = ["internal/hashtable_debug.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hashtable_debug_hooks",
],
@@ -434,18 +491,61 @@ cc_library(
name = "hashtable_debug_hooks",
hdrs = ["internal/hashtable_debug_hooks.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ ],
+)
+
+cc_library(
+ name = "hashtablez_sampler",
+ srcs = [
+ "internal/hashtablez_sampler.cc",
+ "internal/hashtablez_sampler_force_weak_definition.cc",
+ ],
+ hdrs = ["internal/hashtablez_sampler.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":have_sse",
+ "//absl/base",
+ "//absl/base:core_headers",
+ "//absl/base:exponential_biased",
+ "//absl/debugging:stacktrace",
+ "//absl/memory",
+ "//absl/synchronization",
+ "//absl/utility",
+ ],
+)
+
+cc_test(
+ name = "hashtablez_sampler_test",
+ srcs = ["internal/hashtablez_sampler_test.cc"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":hashtablez_sampler",
+ ":have_sse",
+ "//absl/base:core_headers",
+ "//absl/synchronization",
+ "//absl/synchronization:thread_pool",
+ "//absl/time",
+ "@com_google_googletest//:gtest_main",
+ ],
)
cc_library(
name = "node_hash_policy",
hdrs = ["internal/node_hash_policy.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/base:config"],
)
cc_test(
name = "node_hash_policy_test",
srcs = ["internal/node_hash_policy_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_policy_traits",
":node_hash_policy",
@@ -457,6 +557,7 @@ cc_library(
name = "raw_hash_map",
hdrs = ["internal/raw_hash_map.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":container_memory",
":raw_hash_set",
@@ -468,6 +569,19 @@ cc_library(
name = "have_sse",
hdrs = ["internal/have_sse.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+)
+
+cc_library(
+ name = "common",
+ hdrs = ["internal/common.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/meta:type_traits",
+ "//absl/types:optional",
+ ],
)
cc_library(
@@ -475,20 +589,22 @@ cc_library(
srcs = ["internal/raw_hash_set.cc"],
hdrs = ["internal/raw_hash_set.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":common",
":compressed_tuple",
":container_memory",
":hash_policy_traits",
":hashtable_debug_hooks",
+ ":hashtablez_sampler",
":have_sse",
":layout",
- "//absl/base:bits",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/memory",
"//absl/meta:type_traits",
- "//absl/types:optional",
+ "//absl/numeric:bits",
"//absl/utility",
],
)
@@ -506,17 +622,59 @@ cc_test(
":hashtable_debug",
":raw_hash_set",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
+cc_binary(
+ name = "raw_hash_set_benchmark",
+ testonly = 1,
+ srcs = ["internal/raw_hash_set_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":hash_function_defaults",
+ ":raw_hash_set",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings:str_format",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
+cc_binary(
+ name = "raw_hash_set_probe_benchmark",
+ testonly = 1,
+ srcs = ["internal/raw_hash_set_probe_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = select({
+ "//conditions:default": [],
+ }) + ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":flat_hash_map",
+ ":hash_function_defaults",
+ ":hashtable_debug",
+ ":raw_hash_set",
+ "//absl/random",
+ "//absl/random:distributions",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ ],
+)
+
cc_test(
name = "raw_hash_set_allocator_test",
size = "small",
srcs = ["internal/raw_hash_set_allocator_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":raw_hash_set",
":tracked",
@@ -529,7 +687,9 @@ cc_library(
name = "layout",
hdrs = ["internal/layout.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
"//absl/strings",
@@ -543,22 +703,44 @@ cc_test(
size = "small",
srcs = ["internal/layout_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS,
visibility = ["//visibility:private"],
deps = [
":layout",
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/types:span",
"@com_google_googletest//:gtest_main",
],
)
+cc_binary(
+ name = "layout_benchmark",
+ testonly = 1,
+ srcs = ["internal/layout_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":layout",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
cc_library(
name = "tracked",
testonly = 1,
hdrs = ["internal/tracked.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ ],
)
cc_library(
@@ -566,6 +748,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_map_constructor_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
@@ -578,6 +761,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_map_lookup_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
@@ -590,6 +774,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_map_modifiers_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
@@ -602,9 +787,35 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_set_constructor_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
+ "//absl/meta:type_traits",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_library(
+ name = "unordered_set_members_test",
+ testonly = 1,
+ hdrs = ["internal/unordered_set_members_test.h"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/meta:type_traits",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_library(
+ name = "unordered_map_members_test",
+ testonly = 1,
+ hdrs = ["internal/unordered_map_members_test.h"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/meta:type_traits",
"@com_google_googletest//:gtest",
],
)
@@ -614,6 +825,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_set_lookup_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
@@ -626,6 +838,7 @@ cc_library(
testonly = 1,
hdrs = ["internal/unordered_set_modifiers_test.h"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash_generator_testing",
":hash_policy_testing",
@@ -637,10 +850,12 @@ cc_test(
name = "unordered_set_test",
srcs = ["internal/unordered_set_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":unordered_set_constructor_test",
":unordered_set_lookup_test",
+ ":unordered_set_members_test",
":unordered_set_modifiers_test",
"@com_google_googletest//:gtest_main",
],
@@ -650,11 +865,112 @@ cc_test(
name = "unordered_map_test",
srcs = ["internal/unordered_map_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":unordered_map_constructor_test",
":unordered_map_lookup_test",
+ ":unordered_map_members_test",
":unordered_map_modifiers_test",
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "btree",
+ srcs = [
+ "internal/btree.h",
+ "internal/btree_container.h",
+ ],
+ hdrs = [
+ "btree_map.h",
+ "btree_set.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:public"],
+ deps = [
+ ":common",
+ ":compressed_tuple",
+ ":container_memory",
+ ":layout",
+ "//absl/base:core_headers",
+ "//absl/base:throw_delegate",
+ "//absl/memory",
+ "//absl/meta:type_traits",
+ "//absl/strings",
+ "//absl/strings:cord",
+ "//absl/types:compare",
+ "//absl/utility",
+ ],
+)
+
+cc_library(
+ name = "btree_test_common",
+ testonly = 1,
+ hdrs = ["btree_test.h"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":btree",
+ ":flat_hash_set",
+ "//absl/strings",
+ "//absl/strings:cord",
+ "//absl/time",
+ ],
+)
+
+cc_test(
+ name = "btree_test",
+ size = "large",
+ srcs = [
+ "btree_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ shard_count = 10,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":btree",
+ ":btree_test_common",
+ ":counting_allocator",
+ ":test_instance_tracker",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/flags:flag",
+ "//absl/hash:hash_testing",
+ "//absl/memory",
+ "//absl/meta:type_traits",
+ "//absl/strings",
+ "//absl/types:compare",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_binary(
+ name = "btree_benchmark",
+ testonly = 1,
+ srcs = [
+ "btree_benchmark.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":btree",
+ ":btree_test_common",
+ ":flat_hash_map",
+ ":flat_hash_set",
+ ":hashtable_debug",
+ "//absl/base:raw_logging_internal",
+ "//absl/flags:flag",
+ "//absl/hash",
+ "//absl/memory",
+ "//absl/strings:cord",
+ "//absl/strings:str_format",
+ "//absl/time",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_benchmark.cc
new file mode 100644
index 00000000000..65b6790b71e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_benchmark.cc
@@ -0,0 +1,701 @@
+// 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.
+
+#include <stdint.h>
+
+#include <algorithm>
+#include <functional>
+#include <map>
+#include <numeric>
+#include <random>
+#include <set>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "benchmark/benchmark.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/btree_test.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/container/internal/hashtable_debug.h"
+#include "absl/flags/flag.h"
+#include "absl/hash/hash.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_format.h"
+#include "absl/time/time.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+constexpr size_t kBenchmarkValues = 1 << 20;
+
+// How many times we add and remove sub-batches in one batch of *AddRem
+// benchmarks.
+constexpr size_t kAddRemBatchSize = 1 << 2;
+
+// Generates n values in the range [0, 4 * n].
+template <typename V>
+std::vector<V> GenerateValues(int n) {
+ constexpr int kSeed = 23;
+ return GenerateValuesWithSeed<V>(n, 4 * n, kSeed);
+}
+
+// Benchmark insertion of values into a container.
+template <typename T>
+void BM_InsertImpl(benchmark::State& state, bool sorted) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ if (sorted) {
+ std::sort(values.begin(), values.end());
+ }
+ T container(values.begin(), values.end());
+
+ // Remove and re-insert 10% of the keys per batch.
+ const int batch_size = (kBenchmarkValues + 9) / 10;
+ while (state.KeepRunningBatch(batch_size)) {
+ state.PauseTiming();
+ const auto i = static_cast<int>(state.iterations());
+
+ for (int j = i; j < i + batch_size; j++) {
+ int x = j % kBenchmarkValues;
+ container.erase(key_of_value(values[x]));
+ }
+
+ state.ResumeTiming();
+
+ for (int j = i; j < i + batch_size; j++) {
+ int x = j % kBenchmarkValues;
+ container.insert(values[x]);
+ }
+ }
+}
+
+template <typename T>
+void BM_Insert(benchmark::State& state) {
+ BM_InsertImpl<T>(state, false);
+}
+
+template <typename T>
+void BM_InsertSorted(benchmark::State& state) {
+ BM_InsertImpl<T>(state, true);
+}
+
+// Benchmark inserting the first few elements in a container. In b-tree, this is
+// when the root node grows.
+template <typename T>
+void BM_InsertSmall(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+
+ const int kSize = 8;
+ std::vector<V> values = GenerateValues<V>(kSize);
+ T container;
+
+ while (state.KeepRunningBatch(kSize)) {
+ for (int i = 0; i < kSize; ++i) {
+ benchmark::DoNotOptimize(container.insert(values[i]));
+ }
+ state.PauseTiming();
+ // Do not measure the time it takes to clear the container.
+ container.clear();
+ state.ResumeTiming();
+ }
+}
+
+template <typename T>
+void BM_LookupImpl(benchmark::State& state, bool sorted) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ if (sorted) {
+ std::sort(values.begin(), values.end());
+ }
+ T container(values.begin(), values.end());
+
+ while (state.KeepRunning()) {
+ int idx = state.iterations() % kBenchmarkValues;
+ benchmark::DoNotOptimize(container.find(key_of_value(values[idx])));
+ }
+}
+
+// Benchmark lookup of values in a container.
+template <typename T>
+void BM_Lookup(benchmark::State& state) {
+ BM_LookupImpl<T>(state, false);
+}
+
+// Benchmark lookup of values in a full container, meaning that values
+// are inserted in-order to take advantage of biased insertion, which
+// yields a full tree.
+template <typename T>
+void BM_FullLookup(benchmark::State& state) {
+ BM_LookupImpl<T>(state, true);
+}
+
+// Benchmark deletion of values from a container.
+template <typename T>
+void BM_Delete(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ T container(values.begin(), values.end());
+
+ // Remove and re-insert 10% of the keys per batch.
+ const int batch_size = (kBenchmarkValues + 9) / 10;
+ while (state.KeepRunningBatch(batch_size)) {
+ const int i = state.iterations();
+
+ for (int j = i; j < i + batch_size; j++) {
+ int x = j % kBenchmarkValues;
+ container.erase(key_of_value(values[x]));
+ }
+
+ state.PauseTiming();
+ for (int j = i; j < i + batch_size; j++) {
+ int x = j % kBenchmarkValues;
+ container.insert(values[x]);
+ }
+ state.ResumeTiming();
+ }
+}
+
+// Benchmark deletion of multiple values from a container.
+template <typename T>
+void BM_DeleteRange(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ T container(values.begin(), values.end());
+
+ // Remove and re-insert 10% of the keys per batch.
+ const int batch_size = (kBenchmarkValues + 9) / 10;
+ while (state.KeepRunningBatch(batch_size)) {
+ const int i = state.iterations();
+
+ const int start_index = i % kBenchmarkValues;
+
+ state.PauseTiming();
+ {
+ std::vector<V> removed;
+ removed.reserve(batch_size);
+ auto itr = container.find(key_of_value(values[start_index]));
+ auto start = itr;
+ for (int j = 0; j < batch_size; j++) {
+ if (itr == container.end()) {
+ state.ResumeTiming();
+ container.erase(start, itr);
+ state.PauseTiming();
+ itr = container.begin();
+ start = itr;
+ }
+ removed.push_back(*itr++);
+ }
+
+ state.ResumeTiming();
+ container.erase(start, itr);
+ state.PauseTiming();
+
+ container.insert(removed.begin(), removed.end());
+ }
+ state.ResumeTiming();
+ }
+}
+
+// Benchmark steady-state insert (into first half of range) and remove (from
+// second half of range), treating the container approximately like a queue with
+// log-time access for all elements. This benchmark does not test the case where
+// insertion and removal happen in the same region of the tree. This benchmark
+// counts two value constructors.
+template <typename T>
+void BM_QueueAddRem(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+ ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance");
+
+ T container;
+
+ const size_t half = kBenchmarkValues / 2;
+ std::vector<int> remove_keys(half);
+ std::vector<int> add_keys(half);
+
+ // We want to do the exact same work repeatedly, and the benchmark can end
+ // after a different number of iterations depending on the speed of the
+ // individual run so we use a large batch size here and ensure that we do
+ // deterministic work every batch.
+ while (state.KeepRunningBatch(half * kAddRemBatchSize)) {
+ state.PauseTiming();
+
+ container.clear();
+
+ for (size_t i = 0; i < half; ++i) {
+ remove_keys[i] = i;
+ add_keys[i] = i;
+ }
+ constexpr int kSeed = 5;
+ std::mt19937_64 rand(kSeed);
+ std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+ std::shuffle(add_keys.begin(), add_keys.end(), rand);
+
+ // Note needs lazy generation of values.
+ Generator<V> g(kBenchmarkValues * kAddRemBatchSize);
+
+ for (size_t i = 0; i < half; ++i) {
+ container.insert(g(add_keys[i]));
+ container.insert(g(half + remove_keys[i]));
+ }
+
+ // There are three parts each of size "half":
+ // 1 is being deleted from [offset - half, offset)
+ // 2 is standing [offset, offset + half)
+ // 3 is being inserted into [offset + half, offset + 2 * half)
+ size_t offset = 0;
+
+ for (size_t i = 0; i < kAddRemBatchSize; ++i) {
+ std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+ std::shuffle(add_keys.begin(), add_keys.end(), rand);
+ offset += half;
+
+ state.ResumeTiming();
+ for (size_t idx = 0; idx < half; ++idx) {
+ container.erase(key_of_value(g(offset - half + remove_keys[idx])));
+ container.insert(g(offset + half + add_keys[idx]));
+ }
+ state.PauseTiming();
+ }
+ state.ResumeTiming();
+ }
+}
+
+// Mixed insertion and deletion in the same range using pre-constructed values.
+template <typename T>
+void BM_MixedAddRem(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+ ABSL_RAW_CHECK(kBenchmarkValues % 2 == 0, "for performance");
+
+ T container;
+
+ // Create two random shuffles
+ std::vector<int> remove_keys(kBenchmarkValues);
+ std::vector<int> add_keys(kBenchmarkValues);
+
+ // We want to do the exact same work repeatedly, and the benchmark can end
+ // after a different number of iterations depending on the speed of the
+ // individual run so we use a large batch size here and ensure that we do
+ // deterministic work every batch.
+ while (state.KeepRunningBatch(kBenchmarkValues * kAddRemBatchSize)) {
+ state.PauseTiming();
+
+ container.clear();
+
+ constexpr int kSeed = 7;
+ std::mt19937_64 rand(kSeed);
+
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues * 2);
+
+ // Insert the first half of the values (already in random order)
+ container.insert(values.begin(), values.begin() + kBenchmarkValues);
+
+ // Insert the first half of the values (already in random order)
+ for (size_t i = 0; i < kBenchmarkValues; ++i) {
+ // remove_keys and add_keys will be swapped before each round,
+ // therefore fill add_keys here w/ the keys being inserted, so
+ // they'll be the first to be removed.
+ remove_keys[i] = i + kBenchmarkValues;
+ add_keys[i] = i;
+ }
+
+ for (size_t i = 0; i < kAddRemBatchSize; ++i) {
+ remove_keys.swap(add_keys);
+ std::shuffle(remove_keys.begin(), remove_keys.end(), rand);
+ std::shuffle(add_keys.begin(), add_keys.end(), rand);
+
+ state.ResumeTiming();
+ for (size_t idx = 0; idx < kBenchmarkValues; ++idx) {
+ container.erase(key_of_value(values[remove_keys[idx]]));
+ container.insert(values[add_keys[idx]]);
+ }
+ state.PauseTiming();
+ }
+ state.ResumeTiming();
+ }
+}
+
+// Insertion at end, removal from the beginning. This benchmark
+// counts two value constructors.
+// TODO(ezb): we could add a GenerateNext version of generator that could reduce
+// noise for string-like types.
+template <typename T>
+void BM_Fifo(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+
+ T container;
+ // Need lazy generation of values as state.max_iterations is large.
+ Generator<V> g(kBenchmarkValues + state.max_iterations);
+
+ for (int i = 0; i < kBenchmarkValues; i++) {
+ container.insert(g(i));
+ }
+
+ while (state.KeepRunning()) {
+ container.erase(container.begin());
+ container.insert(container.end(), g(state.iterations() + kBenchmarkValues));
+ }
+}
+
+// Iteration (forward) through the tree
+template <typename T>
+void BM_FwdIter(benchmark::State& state) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ using R = typename T::value_type const*;
+
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ T container(values.begin(), values.end());
+
+ auto iter = container.end();
+
+ R r = nullptr;
+
+ while (state.KeepRunning()) {
+ if (iter == container.end()) iter = container.begin();
+ r = &(*iter);
+ ++iter;
+ }
+
+ benchmark::DoNotOptimize(r);
+}
+
+// Benchmark random range-construction of a container.
+template <typename T>
+void BM_RangeConstructionImpl(benchmark::State& state, bool sorted) {
+ using V = typename remove_pair_const<typename T::value_type>::type;
+
+ std::vector<V> values = GenerateValues<V>(kBenchmarkValues);
+ if (sorted) {
+ std::sort(values.begin(), values.end());
+ }
+ {
+ T container(values.begin(), values.end());
+ }
+
+ while (state.KeepRunning()) {
+ T container(values.begin(), values.end());
+ benchmark::DoNotOptimize(container);
+ }
+}
+
+template <typename T>
+void BM_InsertRangeRandom(benchmark::State& state) {
+ BM_RangeConstructionImpl<T>(state, false);
+}
+
+template <typename T>
+void BM_InsertRangeSorted(benchmark::State& state) {
+ BM_RangeConstructionImpl<T>(state, true);
+}
+
+#define STL_ORDERED_TYPES(value) \
+ using stl_set_##value = std::set<value>; \
+ using stl_map_##value = std::map<value, intptr_t>; \
+ using stl_multiset_##value = std::multiset<value>; \
+ using stl_multimap_##value = std::multimap<value, intptr_t>
+
+using StdString = std::string;
+STL_ORDERED_TYPES(int32_t);
+STL_ORDERED_TYPES(int64_t);
+STL_ORDERED_TYPES(StdString);
+STL_ORDERED_TYPES(Cord);
+STL_ORDERED_TYPES(Time);
+
+#define STL_UNORDERED_TYPES(value) \
+ using stl_unordered_set_##value = std::unordered_set<value>; \
+ using stl_unordered_map_##value = std::unordered_map<value, intptr_t>; \
+ using flat_hash_set_##value = flat_hash_set<value>; \
+ using flat_hash_map_##value = flat_hash_map<value, intptr_t>; \
+ using stl_unordered_multiset_##value = std::unordered_multiset<value>; \
+ using stl_unordered_multimap_##value = \
+ std::unordered_multimap<value, intptr_t>
+
+#define STL_UNORDERED_TYPES_CUSTOM_HASH(value, hash) \
+ using stl_unordered_set_##value = std::unordered_set<value, hash>; \
+ using stl_unordered_map_##value = std::unordered_map<value, intptr_t, hash>; \
+ using flat_hash_set_##value = flat_hash_set<value, hash>; \
+ using flat_hash_map_##value = flat_hash_map<value, intptr_t, hash>; \
+ using stl_unordered_multiset_##value = std::unordered_multiset<value, hash>; \
+ using stl_unordered_multimap_##value = \
+ std::unordered_multimap<value, intptr_t, hash>
+
+STL_UNORDERED_TYPES_CUSTOM_HASH(Cord, absl::Hash<absl::Cord>);
+
+STL_UNORDERED_TYPES(int32_t);
+STL_UNORDERED_TYPES(int64_t);
+STL_UNORDERED_TYPES(StdString);
+STL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>);
+
+#define BTREE_TYPES(value) \
+ using btree_256_set_##value = \
+ btree_set<value, std::less<value>, std::allocator<value>>; \
+ using btree_256_map_##value = \
+ btree_map<value, intptr_t, std::less<value>, \
+ std::allocator<std::pair<const value, intptr_t>>>; \
+ using btree_256_multiset_##value = \
+ btree_multiset<value, std::less<value>, std::allocator<value>>; \
+ using btree_256_multimap_##value = \
+ btree_multimap<value, intptr_t, std::less<value>, \
+ std::allocator<std::pair<const value, intptr_t>>>
+
+BTREE_TYPES(int32_t);
+BTREE_TYPES(int64_t);
+BTREE_TYPES(StdString);
+BTREE_TYPES(Cord);
+BTREE_TYPES(Time);
+
+#define MY_BENCHMARK4(type, func) \
+ void BM_##type##_##func(benchmark::State& state) { BM_##func<type>(state); } \
+ BENCHMARK(BM_##type##_##func)
+
+#define MY_BENCHMARK3(type) \
+ MY_BENCHMARK4(type, Insert); \
+ MY_BENCHMARK4(type, InsertSorted); \
+ MY_BENCHMARK4(type, InsertSmall); \
+ MY_BENCHMARK4(type, Lookup); \
+ MY_BENCHMARK4(type, FullLookup); \
+ MY_BENCHMARK4(type, Delete); \
+ MY_BENCHMARK4(type, DeleteRange); \
+ MY_BENCHMARK4(type, QueueAddRem); \
+ MY_BENCHMARK4(type, MixedAddRem); \
+ MY_BENCHMARK4(type, Fifo); \
+ MY_BENCHMARK4(type, FwdIter); \
+ MY_BENCHMARK4(type, InsertRangeRandom); \
+ MY_BENCHMARK4(type, InsertRangeSorted)
+
+#define MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type) \
+ MY_BENCHMARK3(stl_##type); \
+ MY_BENCHMARK3(stl_unordered_##type); \
+ MY_BENCHMARK3(btree_256_##type)
+
+#define MY_BENCHMARK2(type) \
+ MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(type); \
+ MY_BENCHMARK3(flat_hash_##type)
+
+// Define MULTI_TESTING to see benchmarks for multi-containers also.
+//
+// You can use --copt=-DMULTI_TESTING.
+#ifdef MULTI_TESTING
+#define MY_BENCHMARK(type) \
+ MY_BENCHMARK2(set_##type); \
+ MY_BENCHMARK2(map_##type); \
+ MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multiset_##type); \
+ MY_BENCHMARK2_SUPPORTS_MULTI_ONLY(multimap_##type)
+#else
+#define MY_BENCHMARK(type) \
+ MY_BENCHMARK2(set_##type); \
+ MY_BENCHMARK2(map_##type)
+#endif
+
+MY_BENCHMARK(int32_t);
+MY_BENCHMARK(int64_t);
+MY_BENCHMARK(StdString);
+MY_BENCHMARK(Cord);
+MY_BENCHMARK(Time);
+
+// Define a type whose size and cost of moving are independently customizable.
+// When sizeof(value_type) increases, we expect btree to no longer have as much
+// cache-locality advantage over STL. When cost of moving increases, we expect
+// btree to actually do more work than STL because it has to move values around
+// and STL doesn't have to.
+template <int Size, int Copies>
+struct BigType {
+ BigType() : BigType(0) {}
+ explicit BigType(int x) { std::iota(values.begin(), values.end(), x); }
+
+ void Copy(const BigType& other) {
+ for (int i = 0; i < Size && i < Copies; ++i) values[i] = other.values[i];
+ // If Copies > Size, do extra copies.
+ for (int i = Size, idx = 0; i < Copies; ++i) {
+ int64_t tmp = other.values[idx];
+ benchmark::DoNotOptimize(tmp);
+ idx = idx + 1 == Size ? 0 : idx + 1;
+ }
+ }
+
+ BigType(const BigType& other) { Copy(other); }
+ BigType& operator=(const BigType& other) {
+ Copy(other);
+ return *this;
+ }
+
+ // Compare only the first Copies elements if Copies is less than Size.
+ bool operator<(const BigType& other) const {
+ return std::lexicographical_compare(
+ values.begin(), values.begin() + std::min(Size, Copies),
+ other.values.begin(), other.values.begin() + std::min(Size, Copies));
+ }
+ bool operator==(const BigType& other) const {
+ return std::equal(values.begin(), values.begin() + std::min(Size, Copies),
+ other.values.begin());
+ }
+
+ // Support absl::Hash.
+ template <typename State>
+ friend State AbslHashValue(State h, const BigType& b) {
+ for (int i = 0; i < Size && i < Copies; ++i)
+ h = State::combine(std::move(h), b.values[i]);
+ return h;
+ }
+
+ std::array<int64_t, Size> values;
+};
+
+#define BIG_TYPE_BENCHMARKS(SIZE, COPIES) \
+ using stl_set_size##SIZE##copies##COPIES = std::set<BigType<SIZE, COPIES>>; \
+ using stl_map_size##SIZE##copies##COPIES = \
+ std::map<BigType<SIZE, COPIES>, intptr_t>; \
+ using stl_multiset_size##SIZE##copies##COPIES = \
+ std::multiset<BigType<SIZE, COPIES>>; \
+ using stl_multimap_size##SIZE##copies##COPIES = \
+ std::multimap<BigType<SIZE, COPIES>, intptr_t>; \
+ using stl_unordered_set_size##SIZE##copies##COPIES = \
+ std::unordered_set<BigType<SIZE, COPIES>, \
+ absl::Hash<BigType<SIZE, COPIES>>>; \
+ using stl_unordered_map_size##SIZE##copies##COPIES = \
+ std::unordered_map<BigType<SIZE, COPIES>, intptr_t, \
+ absl::Hash<BigType<SIZE, COPIES>>>; \
+ using flat_hash_set_size##SIZE##copies##COPIES = \
+ flat_hash_set<BigType<SIZE, COPIES>>; \
+ using flat_hash_map_size##SIZE##copies##COPIES = \
+ flat_hash_map<BigType<SIZE, COPIES>, intptr_t>; \
+ using stl_unordered_multiset_size##SIZE##copies##COPIES = \
+ std::unordered_multiset<BigType<SIZE, COPIES>, \
+ absl::Hash<BigType<SIZE, COPIES>>>; \
+ using stl_unordered_multimap_size##SIZE##copies##COPIES = \
+ std::unordered_multimap<BigType<SIZE, COPIES>, intptr_t, \
+ absl::Hash<BigType<SIZE, COPIES>>>; \
+ using btree_256_set_size##SIZE##copies##COPIES = \
+ btree_set<BigType<SIZE, COPIES>>; \
+ using btree_256_map_size##SIZE##copies##COPIES = \
+ btree_map<BigType<SIZE, COPIES>, intptr_t>; \
+ using btree_256_multiset_size##SIZE##copies##COPIES = \
+ btree_multiset<BigType<SIZE, COPIES>>; \
+ using btree_256_multimap_size##SIZE##copies##COPIES = \
+ btree_multimap<BigType<SIZE, COPIES>, intptr_t>; \
+ MY_BENCHMARK(size##SIZE##copies##COPIES)
+
+// Define BIG_TYPE_TESTING to see benchmarks for more big types.
+//
+// You can use --copt=-DBIG_TYPE_TESTING.
+#ifndef NODESIZE_TESTING
+#ifdef BIG_TYPE_TESTING
+BIG_TYPE_BENCHMARKS(1, 4);
+BIG_TYPE_BENCHMARKS(4, 1);
+BIG_TYPE_BENCHMARKS(4, 4);
+BIG_TYPE_BENCHMARKS(1, 8);
+BIG_TYPE_BENCHMARKS(8, 1);
+BIG_TYPE_BENCHMARKS(8, 8);
+BIG_TYPE_BENCHMARKS(1, 16);
+BIG_TYPE_BENCHMARKS(16, 1);
+BIG_TYPE_BENCHMARKS(16, 16);
+BIG_TYPE_BENCHMARKS(1, 32);
+BIG_TYPE_BENCHMARKS(32, 1);
+BIG_TYPE_BENCHMARKS(32, 32);
+#else
+BIG_TYPE_BENCHMARKS(32, 32);
+#endif
+#endif
+
+// Benchmark using unique_ptrs to large value types. In order to be able to use
+// the same benchmark code as the other types, use a type that holds a
+// unique_ptr and has a copy constructor.
+template <int Size>
+struct BigTypePtr {
+ BigTypePtr() : BigTypePtr(0) {}
+ explicit BigTypePtr(int x) {
+ ptr = absl::make_unique<BigType<Size, Size>>(x);
+ }
+ BigTypePtr(const BigTypePtr& other) {
+ ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
+ }
+ BigTypePtr(BigTypePtr&& other) noexcept = default;
+ BigTypePtr& operator=(const BigTypePtr& other) {
+ ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
+ }
+ BigTypePtr& operator=(BigTypePtr&& other) noexcept = default;
+
+ bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; }
+ bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; }
+
+ std::unique_ptr<BigType<Size, Size>> ptr;
+};
+
+template <int Size>
+double ContainerInfo(const btree_set<BigTypePtr<Size>>& b) {
+ const double bytes_used =
+ b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);
+ const double bytes_per_value = bytes_used / b.size();
+ BtreeContainerInfoLog(b, bytes_used, bytes_per_value);
+ return bytes_per_value;
+}
+template <int Size>
+double ContainerInfo(const btree_map<int, BigTypePtr<Size>>& b) {
+ const double bytes_used =
+ b.bytes_used() + b.size() * sizeof(BigType<Size, Size>);
+ const double bytes_per_value = bytes_used / b.size();
+ BtreeContainerInfoLog(b, bytes_used, bytes_per_value);
+ return bytes_per_value;
+}
+
+#define BIG_TYPE_PTR_BENCHMARKS(SIZE) \
+ using stl_set_size##SIZE##copies##SIZE##ptr = std::set<BigType<SIZE, SIZE>>; \
+ using stl_map_size##SIZE##copies##SIZE##ptr = \
+ std::map<int, BigType<SIZE, SIZE>>; \
+ using stl_unordered_set_size##SIZE##copies##SIZE##ptr = \
+ std::unordered_set<BigType<SIZE, SIZE>, \
+ absl::Hash<BigType<SIZE, SIZE>>>; \
+ using stl_unordered_map_size##SIZE##copies##SIZE##ptr = \
+ std::unordered_map<int, BigType<SIZE, SIZE>>; \
+ using flat_hash_set_size##SIZE##copies##SIZE##ptr = \
+ flat_hash_set<BigType<SIZE, SIZE>>; \
+ using flat_hash_map_size##SIZE##copies##SIZE##ptr = \
+ flat_hash_map<int, BigTypePtr<SIZE>>; \
+ using btree_256_set_size##SIZE##copies##SIZE##ptr = \
+ btree_set<BigTypePtr<SIZE>>; \
+ using btree_256_map_size##SIZE##copies##SIZE##ptr = \
+ btree_map<int, BigTypePtr<SIZE>>; \
+ MY_BENCHMARK3(stl_set_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(stl_unordered_set_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(flat_hash_set_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(btree_256_set_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(stl_map_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(stl_unordered_map_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(flat_hash_map_size##SIZE##copies##SIZE##ptr); \
+ MY_BENCHMARK3(btree_256_map_size##SIZE##copies##SIZE##ptr)
+
+BIG_TYPE_PTR_BENCHMARKS(32);
+
+} // namespace
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_map.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_map.h
new file mode 100644
index 00000000000..ea49d446280
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_map.h
@@ -0,0 +1,768 @@
+// 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.
+//
+// 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()` and `erase()` return a valid iterator at the current
+// position.
+
+#ifndef ABSL_CONTAINER_BTREE_MAP_H_
+#define ABSL_CONTAINER_BTREE_MAP_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
+
+// 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 btree_map
+ : public container_internal::btree_map_container<
+ container_internal::btree<container_internal::map_params<
+ Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*Multi=*/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. 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::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 is provided 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 is provided 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 is provided a
+ // compatible heterogeneous comparator.
+ using Base::find;
+
+ // 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.
+template <typename K, typename V, typename C, typename A, typename Pred>
+void erase_if(btree_map<K, V, C, A> &map, Pred pred) {
+ for (auto it = map.begin(); it != map.end();) {
+ if (pred(*it)) {
+ it = map.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+// 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 btree_multimap
+ : public container_internal::btree_multimap_container<
+ container_internal::btree<container_internal::map_params<
+ Key, Value, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*Multi=*/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::merge()
+ //
+ // Extracts elements from a given `source` btree_multimap into this
+ // `btree_multimap`. If the destination `btree_multimap` already contains an
+ // element with an equivalent key, that element is not extracted.
+ 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 is provided 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 is provided 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 is provided a
+ // compatible heterogeneous comparator.
+ using Base::find;
+
+ // 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.
+template <typename K, typename V, typename C, typename A, typename Pred>
+void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) {
+ for (auto it = map.begin(); it != map.end();) {
+ if (pred(*it)) {
+ it = map.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_BTREE_MAP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_set.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_set.h
new file mode 100644
index 00000000000..21ef0a032a8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_set.h
@@ -0,0 +1,683 @@
+// 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.
+//
+// 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()` and `erase()` return a valid iterator at the current
+// position.
+
+#ifndef ABSL_CONTAINER_BTREE_SET_H_
+#define ABSL_CONTAINER_BTREE_SET_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
+
+// 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 btree_set
+ : public container_internal::btree_set_container<
+ container_internal::btree<container_internal::set_params<
+ Key, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*Multi=*/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. 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::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 is provided 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 is provided 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 is provided a
+ // compatible heterogeneous comparator.
+ using Base::find;
+
+ // 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.
+template <typename K, typename C, typename A, typename Pred>
+void erase_if(btree_set<K, C, A> &set, Pred pred) {
+ for (auto it = set.begin(); it != set.end();) {
+ if (pred(*it)) {
+ it = set.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+// 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 btree_multiset
+ : public container_internal::btree_multiset_container<
+ container_internal::btree<container_internal::set_params<
+ Key, Compare, Alloc, /*TargetNodeSize=*/256,
+ /*Multi=*/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::merge()
+ //
+ // Extracts elements from a given `source` btree_multiset into this
+ // `btree_multiset`. If the destination `btree_multiset` already contains an
+ // element with an equivalent key, that element is not extracted.
+ 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 is provided 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 is provided 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 is provided a
+ // compatible heterogeneous comparator.
+ using Base::find;
+
+ // 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.
+template <typename K, typename C, typename A, typename Pred>
+void erase_if(btree_multiset<K, C, A> &set, Pred pred) {
+ for (auto it = set.begin(); it != set.end();) {
+ if (pred(*it)) {
+ it = set.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_BTREE_SET_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.cc
new file mode 100644
index 00000000000..74337df2c14
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.cc
@@ -0,0 +1,2899 @@
+// 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.
+
+#include "absl/container/btree_test.h"
+
+#include <cstdint>
+#include <limits>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/internal/counting_allocator.h"
+#include "absl/container/internal/test_instance_tracker.h"
+#include "absl/flags/flag.h"
+#include "absl/hash/hash_testing.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/compare.h"
+
+ABSL_FLAG(int, test_values, 10000, "The number of values to use for tests");
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+using ::absl::test_internal::CopyableMovableInstance;
+using ::absl::test_internal::InstanceTracker;
+using ::absl::test_internal::MovableOnlyInstance;
+using ::testing::ElementsAre;
+using ::testing::ElementsAreArray;
+using ::testing::IsEmpty;
+using ::testing::IsNull;
+using ::testing::Pair;
+using ::testing::SizeIs;
+
+template <typename T, typename U>
+void CheckPairEquals(const T &x, const U &y) {
+ ABSL_INTERNAL_CHECK(x == y, "Values are unequal.");
+}
+
+template <typename T, typename U, typename V, typename W>
+void CheckPairEquals(const std::pair<T, U> &x, const std::pair<V, W> &y) {
+ CheckPairEquals(x.first, y.first);
+ CheckPairEquals(x.second, y.second);
+}
+} // namespace
+
+// The base class for a sorted associative container checker. TreeType is the
+// container type to check and CheckerType is the container type to check
+// against. TreeType is expected to be btree_{set,map,multiset,multimap} and
+// CheckerType is expected to be {set,map,multiset,multimap}.
+template <typename TreeType, typename CheckerType>
+class base_checker {
+ public:
+ using key_type = typename TreeType::key_type;
+ using value_type = typename TreeType::value_type;
+ using key_compare = typename TreeType::key_compare;
+ using pointer = typename TreeType::pointer;
+ using const_pointer = typename TreeType::const_pointer;
+ using reference = typename TreeType::reference;
+ using const_reference = typename TreeType::const_reference;
+ using size_type = typename TreeType::size_type;
+ using difference_type = typename TreeType::difference_type;
+ using iterator = typename TreeType::iterator;
+ using const_iterator = typename TreeType::const_iterator;
+ using reverse_iterator = typename TreeType::reverse_iterator;
+ using const_reverse_iterator = typename TreeType::const_reverse_iterator;
+
+ public:
+ base_checker() : const_tree_(tree_) {}
+ base_checker(const base_checker &other)
+ : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
+ template <typename InputIterator>
+ base_checker(InputIterator b, InputIterator e)
+ : tree_(b, e), const_tree_(tree_), checker_(b, e) {}
+
+ iterator begin() { return tree_.begin(); }
+ const_iterator begin() const { return tree_.begin(); }
+ iterator end() { return tree_.end(); }
+ const_iterator end() const { return tree_.end(); }
+ reverse_iterator rbegin() { return tree_.rbegin(); }
+ const_reverse_iterator rbegin() const { return tree_.rbegin(); }
+ reverse_iterator rend() { return tree_.rend(); }
+ const_reverse_iterator rend() const { return tree_.rend(); }
+
+ template <typename IterType, typename CheckerIterType>
+ IterType iter_check(IterType tree_iter, CheckerIterType checker_iter) const {
+ if (tree_iter == tree_.end()) {
+ ABSL_INTERNAL_CHECK(checker_iter == checker_.end(),
+ "Checker iterator not at end.");
+ } else {
+ CheckPairEquals(*tree_iter, *checker_iter);
+ }
+ return tree_iter;
+ }
+ template <typename IterType, typename CheckerIterType>
+ IterType riter_check(IterType tree_iter, CheckerIterType checker_iter) const {
+ if (tree_iter == tree_.rend()) {
+ ABSL_INTERNAL_CHECK(checker_iter == checker_.rend(),
+ "Checker iterator not at rend.");
+ } else {
+ CheckPairEquals(*tree_iter, *checker_iter);
+ }
+ return tree_iter;
+ }
+ void value_check(const value_type &v) {
+ typename KeyOfValue<typename TreeType::key_type,
+ typename TreeType::value_type>::type key_of_value;
+ const key_type &key = key_of_value(v);
+ CheckPairEquals(*find(key), v);
+ lower_bound(key);
+ upper_bound(key);
+ equal_range(key);
+ contains(key);
+ count(key);
+ }
+ void erase_check(const key_type &key) {
+ EXPECT_FALSE(tree_.contains(key));
+ EXPECT_EQ(tree_.find(key), const_tree_.end());
+ EXPECT_FALSE(const_tree_.contains(key));
+ EXPECT_EQ(const_tree_.find(key), tree_.end());
+ EXPECT_EQ(tree_.equal_range(key).first,
+ const_tree_.equal_range(key).second);
+ }
+
+ iterator lower_bound(const key_type &key) {
+ return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
+ }
+ const_iterator lower_bound(const key_type &key) const {
+ return iter_check(tree_.lower_bound(key), checker_.lower_bound(key));
+ }
+ iterator upper_bound(const key_type &key) {
+ return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
+ }
+ const_iterator upper_bound(const key_type &key) const {
+ return iter_check(tree_.upper_bound(key), checker_.upper_bound(key));
+ }
+ std::pair<iterator, iterator> equal_range(const key_type &key) {
+ std::pair<typename CheckerType::iterator, typename CheckerType::iterator>
+ checker_res = checker_.equal_range(key);
+ std::pair<iterator, iterator> tree_res = tree_.equal_range(key);
+ iter_check(tree_res.first, checker_res.first);
+ iter_check(tree_res.second, checker_res.second);
+ return tree_res;
+ }
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_type &key) const {
+ std::pair<typename CheckerType::const_iterator,
+ typename CheckerType::const_iterator>
+ checker_res = checker_.equal_range(key);
+ std::pair<const_iterator, const_iterator> tree_res = tree_.equal_range(key);
+ iter_check(tree_res.first, checker_res.first);
+ iter_check(tree_res.second, checker_res.second);
+ return tree_res;
+ }
+ iterator find(const key_type &key) {
+ return iter_check(tree_.find(key), checker_.find(key));
+ }
+ const_iterator find(const key_type &key) const {
+ return iter_check(tree_.find(key), checker_.find(key));
+ }
+ bool contains(const key_type &key) const { return find(key) != end(); }
+ size_type count(const key_type &key) const {
+ size_type res = checker_.count(key);
+ EXPECT_EQ(res, tree_.count(key));
+ return res;
+ }
+
+ base_checker &operator=(const base_checker &other) {
+ tree_ = other.tree_;
+ checker_ = other.checker_;
+ return *this;
+ }
+
+ int erase(const key_type &key) {
+ int size = tree_.size();
+ int res = checker_.erase(key);
+ EXPECT_EQ(res, tree_.count(key));
+ EXPECT_EQ(res, tree_.erase(key));
+ EXPECT_EQ(tree_.count(key), 0);
+ EXPECT_EQ(tree_.size(), size - res);
+ erase_check(key);
+ return res;
+ }
+ iterator erase(iterator iter) {
+ key_type key = iter.key();
+ int size = tree_.size();
+ int count = tree_.count(key);
+ auto checker_iter = checker_.lower_bound(key);
+ for (iterator tmp(tree_.lower_bound(key)); tmp != iter; ++tmp) {
+ ++checker_iter;
+ }
+ auto checker_next = checker_iter;
+ ++checker_next;
+ checker_.erase(checker_iter);
+ iter = tree_.erase(iter);
+ EXPECT_EQ(tree_.size(), checker_.size());
+ EXPECT_EQ(tree_.size(), size - 1);
+ EXPECT_EQ(tree_.count(key), count - 1);
+ if (count == 1) {
+ erase_check(key);
+ }
+ return iter_check(iter, checker_next);
+ }
+
+ void erase(iterator begin, iterator end) {
+ int size = tree_.size();
+ int count = std::distance(begin, end);
+ auto checker_begin = checker_.lower_bound(begin.key());
+ for (iterator tmp(tree_.lower_bound(begin.key())); tmp != begin; ++tmp) {
+ ++checker_begin;
+ }
+ auto checker_end =
+ end == tree_.end() ? checker_.end() : checker_.lower_bound(end.key());
+ if (end != tree_.end()) {
+ for (iterator tmp(tree_.lower_bound(end.key())); tmp != end; ++tmp) {
+ ++checker_end;
+ }
+ }
+ const auto checker_ret = checker_.erase(checker_begin, checker_end);
+ const auto tree_ret = tree_.erase(begin, end);
+ EXPECT_EQ(std::distance(checker_.begin(), checker_ret),
+ std::distance(tree_.begin(), tree_ret));
+ EXPECT_EQ(tree_.size(), checker_.size());
+ EXPECT_EQ(tree_.size(), size - count);
+ }
+
+ void clear() {
+ tree_.clear();
+ checker_.clear();
+ }
+ void swap(base_checker &other) {
+ tree_.swap(other.tree_);
+ checker_.swap(other.checker_);
+ }
+
+ void verify() const {
+ tree_.verify();
+ EXPECT_EQ(tree_.size(), checker_.size());
+
+ // Move through the forward iterators using increment.
+ auto checker_iter = checker_.begin();
+ const_iterator tree_iter(tree_.begin());
+ for (; tree_iter != tree_.end(); ++tree_iter, ++checker_iter) {
+ CheckPairEquals(*tree_iter, *checker_iter);
+ }
+
+ // Move through the forward iterators using decrement.
+ for (int n = tree_.size() - 1; n >= 0; --n) {
+ iter_check(tree_iter, checker_iter);
+ --tree_iter;
+ --checker_iter;
+ }
+ EXPECT_EQ(tree_iter, tree_.begin());
+ EXPECT_EQ(checker_iter, checker_.begin());
+
+ // Move through the reverse iterators using increment.
+ auto checker_riter = checker_.rbegin();
+ const_reverse_iterator tree_riter(tree_.rbegin());
+ for (; tree_riter != tree_.rend(); ++tree_riter, ++checker_riter) {
+ CheckPairEquals(*tree_riter, *checker_riter);
+ }
+
+ // Move through the reverse iterators using decrement.
+ for (int n = tree_.size() - 1; n >= 0; --n) {
+ riter_check(tree_riter, checker_riter);
+ --tree_riter;
+ --checker_riter;
+ }
+ EXPECT_EQ(tree_riter, tree_.rbegin());
+ EXPECT_EQ(checker_riter, checker_.rbegin());
+ }
+
+ const TreeType &tree() const { return tree_; }
+
+ size_type size() const {
+ EXPECT_EQ(tree_.size(), checker_.size());
+ return tree_.size();
+ }
+ size_type max_size() const { return tree_.max_size(); }
+ bool empty() const {
+ EXPECT_EQ(tree_.empty(), checker_.empty());
+ return tree_.empty();
+ }
+
+ protected:
+ TreeType tree_;
+ const TreeType &const_tree_;
+ CheckerType checker_;
+};
+
+namespace {
+// A checker for unique sorted associative containers. TreeType is expected to
+// be btree_{set,map} and CheckerType is expected to be {set,map}.
+template <typename TreeType, typename CheckerType>
+class unique_checker : public base_checker<TreeType, CheckerType> {
+ using super_type = base_checker<TreeType, CheckerType>;
+
+ public:
+ using iterator = typename super_type::iterator;
+ using value_type = typename super_type::value_type;
+
+ public:
+ unique_checker() : super_type() {}
+ unique_checker(const unique_checker &other) : super_type(other) {}
+ template <class InputIterator>
+ unique_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
+ unique_checker &operator=(const unique_checker &) = default;
+
+ // Insertion routines.
+ std::pair<iterator, bool> insert(const value_type &v) {
+ int size = this->tree_.size();
+ std::pair<typename CheckerType::iterator, bool> checker_res =
+ this->checker_.insert(v);
+ std::pair<iterator, bool> tree_res = this->tree_.insert(v);
+ CheckPairEquals(*tree_res.first, *checker_res.first);
+ EXPECT_EQ(tree_res.second, checker_res.second);
+ EXPECT_EQ(this->tree_.size(), this->checker_.size());
+ EXPECT_EQ(this->tree_.size(), size + tree_res.second);
+ return tree_res;
+ }
+ iterator insert(iterator position, const value_type &v) {
+ int size = this->tree_.size();
+ std::pair<typename CheckerType::iterator, bool> checker_res =
+ this->checker_.insert(v);
+ iterator tree_res = this->tree_.insert(position, v);
+ CheckPairEquals(*tree_res, *checker_res.first);
+ EXPECT_EQ(this->tree_.size(), this->checker_.size());
+ EXPECT_EQ(this->tree_.size(), size + checker_res.second);
+ return tree_res;
+ }
+ template <typename InputIterator>
+ void insert(InputIterator b, InputIterator e) {
+ for (; b != e; ++b) {
+ insert(*b);
+ }
+ }
+};
+
+// A checker for multiple sorted associative containers. TreeType is expected
+// to be btree_{multiset,multimap} and CheckerType is expected to be
+// {multiset,multimap}.
+template <typename TreeType, typename CheckerType>
+class multi_checker : public base_checker<TreeType, CheckerType> {
+ using super_type = base_checker<TreeType, CheckerType>;
+
+ public:
+ using iterator = typename super_type::iterator;
+ using value_type = typename super_type::value_type;
+
+ public:
+ multi_checker() : super_type() {}
+ multi_checker(const multi_checker &other) : super_type(other) {}
+ template <class InputIterator>
+ multi_checker(InputIterator b, InputIterator e) : super_type(b, e) {}
+ multi_checker &operator=(const multi_checker &) = default;
+
+ // Insertion routines.
+ iterator insert(const value_type &v) {
+ int size = this->tree_.size();
+ auto checker_res = this->checker_.insert(v);
+ iterator tree_res = this->tree_.insert(v);
+ CheckPairEquals(*tree_res, *checker_res);
+ EXPECT_EQ(this->tree_.size(), this->checker_.size());
+ EXPECT_EQ(this->tree_.size(), size + 1);
+ return tree_res;
+ }
+ iterator insert(iterator position, const value_type &v) {
+ int size = this->tree_.size();
+ auto checker_res = this->checker_.insert(v);
+ iterator tree_res = this->tree_.insert(position, v);
+ CheckPairEquals(*tree_res, *checker_res);
+ EXPECT_EQ(this->tree_.size(), this->checker_.size());
+ EXPECT_EQ(this->tree_.size(), size + 1);
+ return tree_res;
+ }
+ template <typename InputIterator>
+ void insert(InputIterator b, InputIterator e) {
+ for (; b != e; ++b) {
+ insert(*b);
+ }
+ }
+};
+
+template <typename T, typename V>
+void DoTest(const char *name, T *b, const std::vector<V> &values) {
+ typename KeyOfValue<typename T::key_type, V>::type key_of_value;
+
+ T &mutable_b = *b;
+ const T &const_b = *b;
+
+ // Test insert.
+ for (int i = 0; i < values.size(); ++i) {
+ mutable_b.insert(values[i]);
+ mutable_b.value_check(values[i]);
+ }
+ ASSERT_EQ(mutable_b.size(), values.size());
+
+ const_b.verify();
+
+ // Test copy constructor.
+ T b_copy(const_b);
+ EXPECT_EQ(b_copy.size(), const_b.size());
+ for (int i = 0; i < values.size(); ++i) {
+ CheckPairEquals(*b_copy.find(key_of_value(values[i])), values[i]);
+ }
+
+ // Test range constructor.
+ T b_range(const_b.begin(), const_b.end());
+ EXPECT_EQ(b_range.size(), const_b.size());
+ for (int i = 0; i < values.size(); ++i) {
+ CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
+ }
+
+ // Test range insertion for values that already exist.
+ b_range.insert(b_copy.begin(), b_copy.end());
+ b_range.verify();
+
+ // Test range insertion for new values.
+ b_range.clear();
+ b_range.insert(b_copy.begin(), b_copy.end());
+ EXPECT_EQ(b_range.size(), b_copy.size());
+ for (int i = 0; i < values.size(); ++i) {
+ CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
+ }
+
+ // Test assignment to self. Nothing should change.
+ b_range.operator=(b_range);
+ EXPECT_EQ(b_range.size(), b_copy.size());
+
+ // Test assignment of new values.
+ b_range.clear();
+ b_range = b_copy;
+ EXPECT_EQ(b_range.size(), b_copy.size());
+
+ // Test swap.
+ b_range.clear();
+ b_range.swap(b_copy);
+ EXPECT_EQ(b_copy.size(), 0);
+ EXPECT_EQ(b_range.size(), const_b.size());
+ for (int i = 0; i < values.size(); ++i) {
+ CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
+ }
+ b_range.swap(b_copy);
+
+ // Test non-member function swap.
+ swap(b_range, b_copy);
+ EXPECT_EQ(b_copy.size(), 0);
+ EXPECT_EQ(b_range.size(), const_b.size());
+ for (int i = 0; i < values.size(); ++i) {
+ CheckPairEquals(*b_range.find(key_of_value(values[i])), values[i]);
+ }
+ swap(b_range, b_copy);
+
+ // Test erase via values.
+ for (int i = 0; i < values.size(); ++i) {
+ mutable_b.erase(key_of_value(values[i]));
+ // Erasing a non-existent key should have no effect.
+ ASSERT_EQ(mutable_b.erase(key_of_value(values[i])), 0);
+ }
+
+ const_b.verify();
+ EXPECT_EQ(const_b.size(), 0);
+
+ // Test erase via iterators.
+ mutable_b = b_copy;
+ for (int i = 0; i < values.size(); ++i) {
+ mutable_b.erase(mutable_b.find(key_of_value(values[i])));
+ }
+
+ const_b.verify();
+ EXPECT_EQ(const_b.size(), 0);
+
+ // Test insert with hint.
+ for (int i = 0; i < values.size(); i++) {
+ mutable_b.insert(mutable_b.upper_bound(key_of_value(values[i])), values[i]);
+ }
+
+ const_b.verify();
+
+ // Test range erase.
+ mutable_b.erase(mutable_b.begin(), mutable_b.end());
+ EXPECT_EQ(mutable_b.size(), 0);
+ const_b.verify();
+
+ // First half.
+ mutable_b = b_copy;
+ typename T::iterator mutable_iter_end = mutable_b.begin();
+ for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_end;
+ mutable_b.erase(mutable_b.begin(), mutable_iter_end);
+ EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 2);
+ const_b.verify();
+
+ // Second half.
+ mutable_b = b_copy;
+ typename T::iterator mutable_iter_begin = mutable_b.begin();
+ for (int i = 0; i < values.size() / 2; ++i) ++mutable_iter_begin;
+ mutable_b.erase(mutable_iter_begin, mutable_b.end());
+ EXPECT_EQ(mutable_b.size(), values.size() / 2);
+ const_b.verify();
+
+ // Second quarter.
+ mutable_b = b_copy;
+ mutable_iter_begin = mutable_b.begin();
+ for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_begin;
+ mutable_iter_end = mutable_iter_begin;
+ for (int i = 0; i < values.size() / 4; ++i) ++mutable_iter_end;
+ mutable_b.erase(mutable_iter_begin, mutable_iter_end);
+ EXPECT_EQ(mutable_b.size(), values.size() - values.size() / 4);
+ const_b.verify();
+
+ mutable_b.clear();
+}
+
+template <typename T>
+void ConstTest() {
+ using value_type = typename T::value_type;
+ typename KeyOfValue<typename T::key_type, value_type>::type key_of_value;
+
+ T mutable_b;
+ const T &const_b = mutable_b;
+
+ // Insert a single value into the container and test looking it up.
+ value_type value = Generator<value_type>(2)(2);
+ mutable_b.insert(value);
+ EXPECT_TRUE(mutable_b.contains(key_of_value(value)));
+ EXPECT_NE(mutable_b.find(key_of_value(value)), const_b.end());
+ EXPECT_TRUE(const_b.contains(key_of_value(value)));
+ EXPECT_NE(const_b.find(key_of_value(value)), mutable_b.end());
+ EXPECT_EQ(*const_b.lower_bound(key_of_value(value)), value);
+ EXPECT_EQ(const_b.upper_bound(key_of_value(value)), const_b.end());
+ EXPECT_EQ(*const_b.equal_range(key_of_value(value)).first, value);
+
+ // We can only create a non-const iterator from a non-const container.
+ typename T::iterator mutable_iter(mutable_b.begin());
+ EXPECT_EQ(mutable_iter, const_b.begin());
+ EXPECT_NE(mutable_iter, const_b.end());
+ EXPECT_EQ(const_b.begin(), mutable_iter);
+ EXPECT_NE(const_b.end(), mutable_iter);
+ typename T::reverse_iterator mutable_riter(mutable_b.rbegin());
+ EXPECT_EQ(mutable_riter, const_b.rbegin());
+ EXPECT_NE(mutable_riter, const_b.rend());
+ EXPECT_EQ(const_b.rbegin(), mutable_riter);
+ EXPECT_NE(const_b.rend(), mutable_riter);
+
+ // We can create a const iterator from a non-const iterator.
+ typename T::const_iterator const_iter(mutable_iter);
+ EXPECT_EQ(const_iter, mutable_b.begin());
+ EXPECT_NE(const_iter, mutable_b.end());
+ EXPECT_EQ(mutable_b.begin(), const_iter);
+ EXPECT_NE(mutable_b.end(), const_iter);
+ typename T::const_reverse_iterator const_riter(mutable_riter);
+ EXPECT_EQ(const_riter, mutable_b.rbegin());
+ EXPECT_NE(const_riter, mutable_b.rend());
+ EXPECT_EQ(mutable_b.rbegin(), const_riter);
+ EXPECT_NE(mutable_b.rend(), const_riter);
+
+ // Make sure various methods can be invoked on a const container.
+ const_b.verify();
+ ASSERT_TRUE(!const_b.empty());
+ EXPECT_EQ(const_b.size(), 1);
+ EXPECT_GT(const_b.max_size(), 0);
+ EXPECT_TRUE(const_b.contains(key_of_value(value)));
+ EXPECT_EQ(const_b.count(key_of_value(value)), 1);
+}
+
+template <typename T, typename C>
+void BtreeTest() {
+ ConstTest<T>();
+
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ const std::vector<V> random_values = GenerateValuesWithSeed<V>(
+ absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
+ testing::GTEST_FLAG(random_seed));
+
+ unique_checker<T, C> container;
+
+ // Test key insertion/deletion in sorted order.
+ std::vector<V> sorted_values(random_values);
+ std::sort(sorted_values.begin(), sorted_values.end());
+ DoTest("sorted: ", &container, sorted_values);
+
+ // Test key insertion/deletion in reverse sorted order.
+ std::reverse(sorted_values.begin(), sorted_values.end());
+ DoTest("rsorted: ", &container, sorted_values);
+
+ // Test key insertion/deletion in random order.
+ DoTest("random: ", &container, random_values);
+}
+
+template <typename T, typename C>
+void BtreeMultiTest() {
+ ConstTest<T>();
+
+ using V = typename remove_pair_const<typename T::value_type>::type;
+ const std::vector<V> random_values = GenerateValuesWithSeed<V>(
+ absl::GetFlag(FLAGS_test_values), 4 * absl::GetFlag(FLAGS_test_values),
+ testing::GTEST_FLAG(random_seed));
+
+ multi_checker<T, C> container;
+
+ // Test keys in sorted order.
+ std::vector<V> sorted_values(random_values);
+ std::sort(sorted_values.begin(), sorted_values.end());
+ DoTest("sorted: ", &container, sorted_values);
+
+ // Test keys in reverse sorted order.
+ std::reverse(sorted_values.begin(), sorted_values.end());
+ DoTest("rsorted: ", &container, sorted_values);
+
+ // Test keys in random order.
+ DoTest("random: ", &container, random_values);
+
+ // Test keys in random order w/ duplicates.
+ std::vector<V> duplicate_values(random_values);
+ duplicate_values.insert(duplicate_values.end(), random_values.begin(),
+ random_values.end());
+ DoTest("duplicates:", &container, duplicate_values);
+
+ // Test all identical keys.
+ std::vector<V> identical_values(100);
+ std::fill(identical_values.begin(), identical_values.end(),
+ Generator<V>(2)(2));
+ DoTest("identical: ", &container, identical_values);
+}
+
+template <typename T>
+struct PropagatingCountingAlloc : public CountingAllocator<T> {
+ 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 Base = CountingAllocator<T>;
+ using Base::Base;
+
+ template <typename U>
+ explicit PropagatingCountingAlloc(const PropagatingCountingAlloc<U> &other)
+ : Base(other.bytes_used_) {}
+
+ template <typename U>
+ struct rebind {
+ using other = PropagatingCountingAlloc<U>;
+ };
+};
+
+template <typename T>
+void BtreeAllocatorTest() {
+ using value_type = typename T::value_type;
+
+ int64_t bytes1 = 0, bytes2 = 0;
+ PropagatingCountingAlloc<T> allocator1(&bytes1);
+ PropagatingCountingAlloc<T> allocator2(&bytes2);
+ Generator<value_type> generator(1000);
+
+ // Test that we allocate properly aligned memory. If we don't, then Layout
+ // will assert fail.
+ auto unused1 = allocator1.allocate(1);
+ auto unused2 = allocator2.allocate(1);
+
+ // Test copy assignment
+ {
+ T b1(typename T::key_compare(), allocator1);
+ T b2(typename T::key_compare(), allocator2);
+
+ int64_t original_bytes1 = bytes1;
+ b1.insert(generator(0));
+ EXPECT_GT(bytes1, original_bytes1);
+
+ // This should propagate the allocator.
+ b1 = b2;
+ EXPECT_EQ(b1.size(), 0);
+ EXPECT_EQ(b2.size(), 0);
+ EXPECT_EQ(bytes1, original_bytes1);
+
+ for (int i = 1; i < 1000; i++) {
+ b1.insert(generator(i));
+ }
+
+ // We should have allocated out of allocator2.
+ EXPECT_GT(bytes2, bytes1);
+ }
+
+ // Test move assignment
+ {
+ T b1(typename T::key_compare(), allocator1);
+ T b2(typename T::key_compare(), allocator2);
+
+ int64_t original_bytes1 = bytes1;
+ b1.insert(generator(0));
+ EXPECT_GT(bytes1, original_bytes1);
+
+ // This should propagate the allocator.
+ b1 = std::move(b2);
+ EXPECT_EQ(b1.size(), 0);
+ EXPECT_EQ(bytes1, original_bytes1);
+
+ for (int i = 1; i < 1000; i++) {
+ b1.insert(generator(i));
+ }
+
+ // We should have allocated out of allocator2.
+ EXPECT_GT(bytes2, bytes1);
+ }
+
+ // Test swap
+ {
+ T b1(typename T::key_compare(), allocator1);
+ T b2(typename T::key_compare(), allocator2);
+
+ int64_t original_bytes1 = bytes1;
+ b1.insert(generator(0));
+ EXPECT_GT(bytes1, original_bytes1);
+
+ // This should swap the allocators.
+ swap(b1, b2);
+ EXPECT_EQ(b1.size(), 0);
+ EXPECT_EQ(b2.size(), 1);
+ EXPECT_GT(bytes1, original_bytes1);
+
+ for (int i = 1; i < 1000; i++) {
+ b1.insert(generator(i));
+ }
+
+ // We should have allocated out of allocator2.
+ EXPECT_GT(bytes2, bytes1);
+ }
+
+ allocator1.deallocate(unused1, 1);
+ allocator2.deallocate(unused2, 1);
+}
+
+template <typename T>
+void BtreeMapTest() {
+ using value_type = typename T::value_type;
+ using mapped_type = typename T::mapped_type;
+
+ mapped_type m = Generator<mapped_type>(0)(0);
+ (void)m;
+
+ T b;
+
+ // Verify we can insert using operator[].
+ for (int i = 0; i < 1000; i++) {
+ value_type v = Generator<value_type>(1000)(i);
+ b[v.first] = v.second;
+ }
+ EXPECT_EQ(b.size(), 1000);
+
+ // Test whether we can use the "->" operator on iterators and
+ // reverse_iterators. This stresses the btree_map_params::pair_pointer
+ // mechanism.
+ EXPECT_EQ(b.begin()->first, Generator<value_type>(1000)(0).first);
+ EXPECT_EQ(b.begin()->second, Generator<value_type>(1000)(0).second);
+ EXPECT_EQ(b.rbegin()->first, Generator<value_type>(1000)(999).first);
+ EXPECT_EQ(b.rbegin()->second, Generator<value_type>(1000)(999).second);
+}
+
+template <typename T>
+void BtreeMultiMapTest() {
+ using mapped_type = typename T::mapped_type;
+ mapped_type m = Generator<mapped_type>(0)(0);
+ (void)m;
+}
+
+template <typename K, int N = 256>
+void SetTest() {
+ EXPECT_EQ(
+ sizeof(absl::btree_set<K>),
+ 2 * sizeof(void *) + sizeof(typename absl::btree_set<K>::size_type));
+ using BtreeSet = absl::btree_set<K>;
+ using CountingBtreeSet =
+ absl::btree_set<K, std::less<K>, PropagatingCountingAlloc<K>>;
+ BtreeTest<BtreeSet, std::set<K>>();
+ BtreeAllocatorTest<CountingBtreeSet>();
+}
+
+template <typename K, int N = 256>
+void MapTest() {
+ EXPECT_EQ(
+ sizeof(absl::btree_map<K, K>),
+ 2 * sizeof(void *) + sizeof(typename absl::btree_map<K, K>::size_type));
+ using BtreeMap = absl::btree_map<K, K>;
+ using CountingBtreeMap =
+ absl::btree_map<K, K, std::less<K>,
+ PropagatingCountingAlloc<std::pair<const K, K>>>;
+ BtreeTest<BtreeMap, std::map<K, K>>();
+ BtreeAllocatorTest<CountingBtreeMap>();
+ BtreeMapTest<BtreeMap>();
+}
+
+TEST(Btree, set_int32) { SetTest<int32_t>(); }
+TEST(Btree, set_int64) { SetTest<int64_t>(); }
+TEST(Btree, set_string) { SetTest<std::string>(); }
+TEST(Btree, set_cord) { SetTest<absl::Cord>(); }
+TEST(Btree, set_pair) { SetTest<std::pair<int, int>>(); }
+TEST(Btree, map_int32) { MapTest<int32_t>(); }
+TEST(Btree, map_int64) { MapTest<int64_t>(); }
+TEST(Btree, map_string) { MapTest<std::string>(); }
+TEST(Btree, map_cord) { MapTest<absl::Cord>(); }
+TEST(Btree, map_pair) { MapTest<std::pair<int, int>>(); }
+
+template <typename K, int N = 256>
+void MultiSetTest() {
+ EXPECT_EQ(
+ sizeof(absl::btree_multiset<K>),
+ 2 * sizeof(void *) + sizeof(typename absl::btree_multiset<K>::size_type));
+ using BtreeMSet = absl::btree_multiset<K>;
+ using CountingBtreeMSet =
+ absl::btree_multiset<K, std::less<K>, PropagatingCountingAlloc<K>>;
+ BtreeMultiTest<BtreeMSet, std::multiset<K>>();
+ BtreeAllocatorTest<CountingBtreeMSet>();
+}
+
+template <typename K, int N = 256>
+void MultiMapTest() {
+ EXPECT_EQ(sizeof(absl::btree_multimap<K, K>),
+ 2 * sizeof(void *) +
+ sizeof(typename absl::btree_multimap<K, K>::size_type));
+ using BtreeMMap = absl::btree_multimap<K, K>;
+ using CountingBtreeMMap =
+ absl::btree_multimap<K, K, std::less<K>,
+ PropagatingCountingAlloc<std::pair<const K, K>>>;
+ BtreeMultiTest<BtreeMMap, std::multimap<K, K>>();
+ BtreeMultiMapTest<BtreeMMap>();
+ BtreeAllocatorTest<CountingBtreeMMap>();
+}
+
+TEST(Btree, multiset_int32) { MultiSetTest<int32_t>(); }
+TEST(Btree, multiset_int64) { MultiSetTest<int64_t>(); }
+TEST(Btree, multiset_string) { MultiSetTest<std::string>(); }
+TEST(Btree, multiset_cord) { MultiSetTest<absl::Cord>(); }
+TEST(Btree, multiset_pair) { MultiSetTest<std::pair<int, int>>(); }
+TEST(Btree, multimap_int32) { MultiMapTest<int32_t>(); }
+TEST(Btree, multimap_int64) { MultiMapTest<int64_t>(); }
+TEST(Btree, multimap_string) { MultiMapTest<std::string>(); }
+TEST(Btree, multimap_cord) { MultiMapTest<absl::Cord>(); }
+TEST(Btree, multimap_pair) { MultiMapTest<std::pair<int, int>>(); }
+
+struct CompareIntToString {
+ bool operator()(const std::string &a, const std::string &b) const {
+ return a < b;
+ }
+ bool operator()(const std::string &a, int b) const {
+ return a < absl::StrCat(b);
+ }
+ bool operator()(int a, const std::string &b) const {
+ return absl::StrCat(a) < b;
+ }
+ using is_transparent = void;
+};
+
+struct NonTransparentCompare {
+ template <typename T, typename U>
+ bool operator()(const T &t, const U &u) const {
+ // Treating all comparators as transparent can cause inefficiencies (see
+ // N3657 C++ proposal). Test that for comparators without 'is_transparent'
+ // alias (like this one), we do not attempt heterogeneous lookup.
+ EXPECT_TRUE((std::is_same<T, U>()));
+ return t < u;
+ }
+};
+
+template <typename T>
+bool CanEraseWithEmptyBrace(T t, decltype(t.erase({})) *) {
+ return true;
+}
+
+template <typename T>
+bool CanEraseWithEmptyBrace(T, ...) {
+ return false;
+}
+
+template <typename T>
+void TestHeterogeneous(T table) {
+ auto lb = table.lower_bound("3");
+ EXPECT_EQ(lb, table.lower_bound(3));
+ EXPECT_NE(lb, table.lower_bound(4));
+ EXPECT_EQ(lb, table.lower_bound({"3"}));
+ EXPECT_NE(lb, table.lower_bound({}));
+
+ auto ub = table.upper_bound("3");
+ EXPECT_EQ(ub, table.upper_bound(3));
+ EXPECT_NE(ub, table.upper_bound(5));
+ EXPECT_EQ(ub, table.upper_bound({"3"}));
+ EXPECT_NE(ub, table.upper_bound({}));
+
+ auto er = table.equal_range("3");
+ EXPECT_EQ(er, table.equal_range(3));
+ EXPECT_NE(er, table.equal_range(4));
+ EXPECT_EQ(er, table.equal_range({"3"}));
+ EXPECT_NE(er, table.equal_range({}));
+
+ auto it = table.find("3");
+ EXPECT_EQ(it, table.find(3));
+ EXPECT_NE(it, table.find(4));
+ EXPECT_EQ(it, table.find({"3"}));
+ EXPECT_NE(it, table.find({}));
+
+ EXPECT_TRUE(table.contains(3));
+ EXPECT_FALSE(table.contains(4));
+ EXPECT_TRUE(table.count({"3"}));
+ EXPECT_FALSE(table.contains({}));
+
+ EXPECT_EQ(1, table.count(3));
+ EXPECT_EQ(0, table.count(4));
+ EXPECT_EQ(1, table.count({"3"}));
+ EXPECT_EQ(0, table.count({}));
+
+ auto copy = table;
+ copy.erase(3);
+ EXPECT_EQ(table.size() - 1, copy.size());
+ copy.erase(4);
+ EXPECT_EQ(table.size() - 1, copy.size());
+ copy.erase({"5"});
+ EXPECT_EQ(table.size() - 2, copy.size());
+ EXPECT_FALSE(CanEraseWithEmptyBrace(table, nullptr));
+
+ // Also run it with const T&.
+ if (std::is_class<T>()) TestHeterogeneous<const T &>(table);
+}
+
+TEST(Btree, HeterogeneousLookup) {
+ TestHeterogeneous(btree_set<std::string, CompareIntToString>{"1", "3", "5"});
+ TestHeterogeneous(btree_map<std::string, int, CompareIntToString>{
+ {"1", 1}, {"3", 3}, {"5", 5}});
+ TestHeterogeneous(
+ btree_multiset<std::string, CompareIntToString>{"1", "3", "5"});
+ TestHeterogeneous(btree_multimap<std::string, int, CompareIntToString>{
+ {"1", 1}, {"3", 3}, {"5", 5}});
+
+ // Only maps have .at()
+ btree_map<std::string, int, CompareIntToString> map{
+ {"", -1}, {"1", 1}, {"3", 3}, {"5", 5}};
+ EXPECT_EQ(1, map.at(1));
+ EXPECT_EQ(3, map.at({"3"}));
+ EXPECT_EQ(-1, map.at({}));
+ const auto &cmap = map;
+ EXPECT_EQ(1, cmap.at(1));
+ EXPECT_EQ(3, cmap.at({"3"}));
+ EXPECT_EQ(-1, cmap.at({}));
+}
+
+TEST(Btree, NoHeterogeneousLookupWithoutAlias) {
+ using StringSet = absl::btree_set<std::string, NonTransparentCompare>;
+ StringSet s;
+ ASSERT_TRUE(s.insert("hello").second);
+ ASSERT_TRUE(s.insert("world").second);
+ EXPECT_TRUE(s.end() == s.find("blah"));
+ EXPECT_TRUE(s.begin() == s.lower_bound("hello"));
+ EXPECT_EQ(1, s.count("world"));
+ EXPECT_TRUE(s.contains("hello"));
+ EXPECT_TRUE(s.contains("world"));
+ EXPECT_FALSE(s.contains("blah"));
+
+ using StringMultiSet =
+ absl::btree_multiset<std::string, NonTransparentCompare>;
+ StringMultiSet ms;
+ ms.insert("hello");
+ ms.insert("world");
+ ms.insert("world");
+ EXPECT_TRUE(ms.end() == ms.find("blah"));
+ EXPECT_TRUE(ms.begin() == ms.lower_bound("hello"));
+ EXPECT_EQ(2, ms.count("world"));
+ EXPECT_TRUE(ms.contains("hello"));
+ EXPECT_TRUE(ms.contains("world"));
+ EXPECT_FALSE(ms.contains("blah"));
+}
+
+TEST(Btree, DefaultTransparent) {
+ {
+ // `int` does not have a default transparent comparator.
+ // The input value is converted to key_type.
+ btree_set<int> s = {1};
+ double d = 1.1;
+ EXPECT_EQ(s.begin(), s.find(d));
+ EXPECT_TRUE(s.contains(d));
+ }
+
+ {
+ // `std::string` has heterogeneous support.
+ btree_set<std::string> s = {"A"};
+ EXPECT_EQ(s.begin(), s.find(absl::string_view("A")));
+ EXPECT_TRUE(s.contains(absl::string_view("A")));
+ }
+}
+
+class StringLike {
+ public:
+ StringLike() = default;
+
+ StringLike(const char *s) : s_(s) { // NOLINT
+ ++constructor_calls_;
+ }
+
+ bool operator<(const StringLike &a) const { return s_ < a.s_; }
+
+ static void clear_constructor_call_count() { constructor_calls_ = 0; }
+
+ static int constructor_calls() { return constructor_calls_; }
+
+ private:
+ static int constructor_calls_;
+ std::string s_;
+};
+
+int StringLike::constructor_calls_ = 0;
+
+TEST(Btree, HeterogeneousLookupDoesntDegradePerformance) {
+ using StringSet = absl::btree_set<StringLike>;
+ StringSet s;
+ for (int i = 0; i < 100; ++i) {
+ ASSERT_TRUE(s.insert(absl::StrCat(i).c_str()).second);
+ }
+ StringLike::clear_constructor_call_count();
+ s.find("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.contains("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.count("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.lower_bound("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.upper_bound("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.equal_range("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+
+ StringLike::clear_constructor_call_count();
+ s.erase("50");
+ ASSERT_EQ(1, StringLike::constructor_calls());
+}
+
+// Verify that swapping btrees swaps the key comparison functors and that we can
+// use non-default constructible comparators.
+struct SubstringLess {
+ SubstringLess() = delete;
+ explicit SubstringLess(int length) : n(length) {}
+ bool operator()(const std::string &a, const std::string &b) const {
+ return absl::string_view(a).substr(0, n) <
+ absl::string_view(b).substr(0, n);
+ }
+ int n;
+};
+
+TEST(Btree, SwapKeyCompare) {
+ using SubstringSet = absl::btree_set<std::string, SubstringLess>;
+ SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type());
+ SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type());
+
+ ASSERT_TRUE(s1.insert("a").second);
+ ASSERT_FALSE(s1.insert("aa").second);
+
+ ASSERT_TRUE(s2.insert("a").second);
+ ASSERT_TRUE(s2.insert("aa").second);
+ ASSERT_FALSE(s2.insert("aaa").second);
+
+ swap(s1, s2);
+
+ ASSERT_TRUE(s1.insert("b").second);
+ ASSERT_TRUE(s1.insert("bb").second);
+ ASSERT_FALSE(s1.insert("bbb").second);
+
+ ASSERT_TRUE(s2.insert("b").second);
+ ASSERT_FALSE(s2.insert("bb").second);
+}
+
+TEST(Btree, UpperBoundRegression) {
+ // Regress a bug where upper_bound would default-construct a new key_compare
+ // instead of copying the existing one.
+ using SubstringSet = absl::btree_set<std::string, SubstringLess>;
+ SubstringSet my_set(SubstringLess(3));
+ my_set.insert("aab");
+ my_set.insert("abb");
+ // We call upper_bound("aaa"). If this correctly uses the length 3
+ // comparator, aaa < aab < abb, so we should get aab as the result.
+ // If it instead uses the default-constructed length 2 comparator,
+ // aa == aa < ab, so we'll get abb as our result.
+ SubstringSet::iterator it = my_set.upper_bound("aaa");
+ ASSERT_TRUE(it != my_set.end());
+ EXPECT_EQ("aab", *it);
+}
+
+TEST(Btree, Comparison) {
+ const int kSetSize = 1201;
+ absl::btree_set<int64_t> my_set;
+ for (int i = 0; i < kSetSize; ++i) {
+ my_set.insert(i);
+ }
+ absl::btree_set<int64_t> my_set_copy(my_set);
+ EXPECT_TRUE(my_set_copy == my_set);
+ EXPECT_TRUE(my_set == my_set_copy);
+ EXPECT_FALSE(my_set_copy != my_set);
+ EXPECT_FALSE(my_set != my_set_copy);
+
+ my_set.insert(kSetSize);
+ EXPECT_FALSE(my_set_copy == my_set);
+ EXPECT_FALSE(my_set == my_set_copy);
+ EXPECT_TRUE(my_set_copy != my_set);
+ EXPECT_TRUE(my_set != my_set_copy);
+
+ my_set.erase(kSetSize - 1);
+ EXPECT_FALSE(my_set_copy == my_set);
+ EXPECT_FALSE(my_set == my_set_copy);
+ EXPECT_TRUE(my_set_copy != my_set);
+ EXPECT_TRUE(my_set != my_set_copy);
+
+ absl::btree_map<std::string, int64_t> my_map;
+ for (int i = 0; i < kSetSize; ++i) {
+ my_map[std::string(i, 'a')] = i;
+ }
+ absl::btree_map<std::string, int64_t> my_map_copy(my_map);
+ EXPECT_TRUE(my_map_copy == my_map);
+ EXPECT_TRUE(my_map == my_map_copy);
+ EXPECT_FALSE(my_map_copy != my_map);
+ EXPECT_FALSE(my_map != my_map_copy);
+
+ ++my_map_copy[std::string(7, 'a')];
+ EXPECT_FALSE(my_map_copy == my_map);
+ EXPECT_FALSE(my_map == my_map_copy);
+ EXPECT_TRUE(my_map_copy != my_map);
+ EXPECT_TRUE(my_map != my_map_copy);
+
+ my_map_copy = my_map;
+ my_map["hello"] = kSetSize;
+ EXPECT_FALSE(my_map_copy == my_map);
+ EXPECT_FALSE(my_map == my_map_copy);
+ EXPECT_TRUE(my_map_copy != my_map);
+ EXPECT_TRUE(my_map != my_map_copy);
+
+ my_map.erase(std::string(kSetSize - 1, 'a'));
+ EXPECT_FALSE(my_map_copy == my_map);
+ EXPECT_FALSE(my_map == my_map_copy);
+ EXPECT_TRUE(my_map_copy != my_map);
+ EXPECT_TRUE(my_map != my_map_copy);
+}
+
+TEST(Btree, RangeCtorSanity) {
+ std::vector<int> ivec;
+ ivec.push_back(1);
+ std::map<int, int> imap;
+ imap.insert(std::make_pair(1, 2));
+ absl::btree_multiset<int> tmset(ivec.begin(), ivec.end());
+ absl::btree_multimap<int, int> tmmap(imap.begin(), imap.end());
+ absl::btree_set<int> tset(ivec.begin(), ivec.end());
+ absl::btree_map<int, int> tmap(imap.begin(), imap.end());
+ EXPECT_EQ(1, tmset.size());
+ EXPECT_EQ(1, tmmap.size());
+ EXPECT_EQ(1, tset.size());
+ EXPECT_EQ(1, tmap.size());
+}
+
+} // namespace
+
+class BtreeNodePeer {
+ public:
+ // Yields the size of a leaf node with a specific number of values.
+ template <typename ValueType>
+ constexpr static size_t GetTargetNodeSize(size_t target_values_per_node) {
+ return btree_node<
+ set_params<ValueType, std::less<ValueType>, std::allocator<ValueType>,
+ /*TargetNodeSize=*/256, // This parameter isn't used here.
+ /*Multi=*/false>>::SizeWithNSlots(target_values_per_node);
+ }
+
+ // Yields the number of slots in a (non-root) leaf node for this btree.
+ template <typename Btree>
+ constexpr static size_t GetNumSlotsPerNode() {
+ return btree_node<typename Btree::params_type>::kNodeSlots;
+ }
+
+ template <typename Btree>
+ constexpr static size_t GetMaxFieldType() {
+ return std::numeric_limits<
+ typename btree_node<typename Btree::params_type>::field_type>::max();
+ }
+
+ template <typename Btree>
+ constexpr static bool UsesLinearNodeSearch() {
+ return btree_node<typename Btree::params_type>::use_linear_search::value;
+ }
+};
+
+namespace {
+
+class BtreeMapTest : public ::testing::Test {
+ public:
+ struct Key {};
+ struct Cmp {
+ template <typename T>
+ bool operator()(T, T) const {
+ return false;
+ }
+ };
+
+ struct KeyLin {
+ using absl_btree_prefer_linear_node_search = std::true_type;
+ };
+ struct CmpLin : Cmp {
+ using absl_btree_prefer_linear_node_search = std::true_type;
+ };
+
+ struct KeyBin {
+ using absl_btree_prefer_linear_node_search = std::false_type;
+ };
+ struct CmpBin : Cmp {
+ using absl_btree_prefer_linear_node_search = std::false_type;
+ };
+
+ template <typename K, typename C>
+ static bool IsLinear() {
+ return BtreeNodePeer::UsesLinearNodeSearch<absl::btree_map<K, int, C>>();
+ }
+};
+
+TEST_F(BtreeMapTest, TestLinearSearchPreferredForKeyLinearViaAlias) {
+ // Test requesting linear search by directly exporting an alias.
+ EXPECT_FALSE((IsLinear<Key, Cmp>()));
+ EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+ EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+ EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+}
+
+TEST_F(BtreeMapTest, LinearChoiceTree) {
+ // Cmp has precedence, and is forcing binary
+ EXPECT_FALSE((IsLinear<Key, CmpBin>()));
+ EXPECT_FALSE((IsLinear<KeyLin, CmpBin>()));
+ EXPECT_FALSE((IsLinear<KeyBin, CmpBin>()));
+ EXPECT_FALSE((IsLinear<int, CmpBin>()));
+ EXPECT_FALSE((IsLinear<std::string, CmpBin>()));
+ // Cmp has precedence, and is forcing linear
+ EXPECT_TRUE((IsLinear<Key, CmpLin>()));
+ EXPECT_TRUE((IsLinear<KeyLin, CmpLin>()));
+ EXPECT_TRUE((IsLinear<KeyBin, CmpLin>()));
+ EXPECT_TRUE((IsLinear<int, CmpLin>()));
+ EXPECT_TRUE((IsLinear<std::string, CmpLin>()));
+ // Cmp has no preference, Key determines linear vs binary.
+ EXPECT_FALSE((IsLinear<Key, Cmp>()));
+ EXPECT_TRUE((IsLinear<KeyLin, Cmp>()));
+ EXPECT_FALSE((IsLinear<KeyBin, Cmp>()));
+ // arithmetic key w/ std::less or std::greater: linear
+ EXPECT_TRUE((IsLinear<int, std::less<int>>()));
+ EXPECT_TRUE((IsLinear<double, std::greater<double>>()));
+ // arithmetic key w/ custom compare: binary
+ EXPECT_FALSE((IsLinear<int, Cmp>()));
+ // non-arithmetic key: binary
+ EXPECT_FALSE((IsLinear<std::string, std::less<std::string>>()));
+}
+
+TEST(Btree, BtreeMapCanHoldMoveOnlyTypes) {
+ absl::btree_map<std::string, std::unique_ptr<std::string>> m;
+
+ std::unique_ptr<std::string> &v = m["A"];
+ EXPECT_TRUE(v == nullptr);
+ v.reset(new std::string("X"));
+
+ auto iter = m.find("A");
+ EXPECT_EQ("X", *iter->second);
+}
+
+TEST(Btree, InitializerListConstructor) {
+ absl::btree_set<std::string> set({"a", "b"});
+ EXPECT_EQ(set.count("a"), 1);
+ EXPECT_EQ(set.count("b"), 1);
+
+ absl::btree_multiset<int> mset({1, 1, 4});
+ EXPECT_EQ(mset.count(1), 2);
+ EXPECT_EQ(mset.count(4), 1);
+
+ absl::btree_map<int, int> map({{1, 5}, {2, 10}});
+ EXPECT_EQ(map[1], 5);
+ EXPECT_EQ(map[2], 10);
+
+ absl::btree_multimap<int, int> mmap({{1, 5}, {1, 10}});
+ auto range = mmap.equal_range(1);
+ auto it = range.first;
+ ASSERT_NE(it, range.second);
+ EXPECT_EQ(it->second, 5);
+ ASSERT_NE(++it, range.second);
+ EXPECT_EQ(it->second, 10);
+ EXPECT_EQ(++it, range.second);
+}
+
+TEST(Btree, InitializerListInsert) {
+ absl::btree_set<std::string> set;
+ set.insert({"a", "b"});
+ EXPECT_EQ(set.count("a"), 1);
+ EXPECT_EQ(set.count("b"), 1);
+
+ absl::btree_multiset<int> mset;
+ mset.insert({1, 1, 4});
+ EXPECT_EQ(mset.count(1), 2);
+ EXPECT_EQ(mset.count(4), 1);
+
+ absl::btree_map<int, int> map;
+ map.insert({{1, 5}, {2, 10}});
+ // Test that inserting one element using an initializer list also works.
+ map.insert({3, 15});
+ EXPECT_EQ(map[1], 5);
+ EXPECT_EQ(map[2], 10);
+ EXPECT_EQ(map[3], 15);
+
+ absl::btree_multimap<int, int> mmap;
+ mmap.insert({{1, 5}, {1, 10}});
+ auto range = mmap.equal_range(1);
+ auto it = range.first;
+ ASSERT_NE(it, range.second);
+ EXPECT_EQ(it->second, 5);
+ ASSERT_NE(++it, range.second);
+ EXPECT_EQ(it->second, 10);
+ EXPECT_EQ(++it, range.second);
+}
+
+template <typename Compare, typename K>
+void AssertKeyCompareToAdapted() {
+ using Adapted = typename key_compare_to_adapter<Compare>::type;
+ static_assert(!std::is_same<Adapted, Compare>::value,
+ "key_compare_to_adapter should have adapted this comparator.");
+ static_assert(
+ std::is_same<absl::weak_ordering,
+ absl::result_of_t<Adapted(const K &, const K &)>>::value,
+ "Adapted comparator should be a key-compare-to comparator.");
+}
+template <typename Compare, typename K>
+void AssertKeyCompareToNotAdapted() {
+ using Unadapted = typename key_compare_to_adapter<Compare>::type;
+ static_assert(
+ std::is_same<Unadapted, Compare>::value,
+ "key_compare_to_adapter shouldn't have adapted this comparator.");
+ static_assert(
+ std::is_same<bool,
+ absl::result_of_t<Unadapted(const K &, const K &)>>::value,
+ "Un-adapted comparator should return bool.");
+}
+
+TEST(Btree, KeyCompareToAdapter) {
+ AssertKeyCompareToAdapted<std::less<std::string>, std::string>();
+ AssertKeyCompareToAdapted<std::greater<std::string>, std::string>();
+ AssertKeyCompareToAdapted<std::less<absl::string_view>, absl::string_view>();
+ AssertKeyCompareToAdapted<std::greater<absl::string_view>,
+ absl::string_view>();
+ AssertKeyCompareToAdapted<std::less<absl::Cord>, absl::Cord>();
+ AssertKeyCompareToAdapted<std::greater<absl::Cord>, absl::Cord>();
+ AssertKeyCompareToNotAdapted<std::less<int>, int>();
+ AssertKeyCompareToNotAdapted<std::greater<int>, int>();
+}
+
+TEST(Btree, RValueInsert) {
+ InstanceTracker tracker;
+
+ absl::btree_set<MovableOnlyInstance> set;
+ set.insert(MovableOnlyInstance(1));
+ set.insert(MovableOnlyInstance(3));
+ MovableOnlyInstance two(2);
+ set.insert(set.find(MovableOnlyInstance(3)), std::move(two));
+ auto it = set.find(MovableOnlyInstance(2));
+ ASSERT_NE(it, set.end());
+ ASSERT_NE(++it, set.end());
+ EXPECT_EQ(it->value(), 3);
+
+ absl::btree_multiset<MovableOnlyInstance> mset;
+ MovableOnlyInstance zero(0);
+ MovableOnlyInstance zero2(0);
+ mset.insert(std::move(zero));
+ mset.insert(mset.find(MovableOnlyInstance(0)), std::move(zero2));
+ EXPECT_EQ(mset.count(MovableOnlyInstance(0)), 2);
+
+ absl::btree_map<int, MovableOnlyInstance> map;
+ std::pair<const int, MovableOnlyInstance> p1 = {1, MovableOnlyInstance(5)};
+ std::pair<const int, MovableOnlyInstance> p2 = {2, MovableOnlyInstance(10)};
+ std::pair<const int, MovableOnlyInstance> p3 = {3, MovableOnlyInstance(15)};
+ map.insert(std::move(p1));
+ map.insert(std::move(p3));
+ map.insert(map.find(3), std::move(p2));
+ ASSERT_NE(map.find(2), map.end());
+ EXPECT_EQ(map.find(2)->second.value(), 10);
+
+ absl::btree_multimap<int, MovableOnlyInstance> mmap;
+ std::pair<const int, MovableOnlyInstance> p4 = {1, MovableOnlyInstance(5)};
+ std::pair<const int, MovableOnlyInstance> p5 = {1, MovableOnlyInstance(10)};
+ mmap.insert(std::move(p4));
+ mmap.insert(mmap.find(1), std::move(p5));
+ auto range = mmap.equal_range(1);
+ auto it1 = range.first;
+ ASSERT_NE(it1, range.second);
+ EXPECT_EQ(it1->second.value(), 10);
+ ASSERT_NE(++it1, range.second);
+ EXPECT_EQ(it1->second.value(), 5);
+ EXPECT_EQ(++it1, range.second);
+
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.swaps(), 0);
+}
+
+// A btree set with a specific number of values per node.
+template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
+class SizedBtreeSet
+ : public btree_set_container<btree<
+ set_params<Key, Cmp, std::allocator<Key>,
+ BtreeNodePeer::GetTargetNodeSize<Key>(TargetValuesPerNode),
+ /*Multi=*/false>>> {
+ using Base = typename SizedBtreeSet::btree_set_container;
+
+ public:
+ SizedBtreeSet() {}
+ using Base::Base;
+};
+
+template <typename Set>
+void ExpectOperationCounts(const int expected_moves,
+ const int expected_comparisons,
+ const std::vector<int> &values,
+ InstanceTracker *tracker, Set *set) {
+ for (const int v : values) set->insert(MovableOnlyInstance(v));
+ set->clear();
+ EXPECT_EQ(tracker->moves(), expected_moves);
+ EXPECT_EQ(tracker->comparisons(), expected_comparisons);
+ EXPECT_EQ(tracker->copies(), 0);
+ EXPECT_EQ(tracker->swaps(), 0);
+ tracker->ResetCopiesMovesSwaps();
+}
+
+// Note: when the values in this test change, it is expected to have an impact
+// on performance.
+TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
+ InstanceTracker tracker;
+ // Note: this is minimum number of values per node.
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4> set4;
+ // Note: this is the default number of values per node for a set of int32s
+ // (with 64-bit pointers).
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100> set100;
+
+ // Don't depend on flags for random values because then the expectations will
+ // fail if the flags change.
+ std::vector<int> values =
+ GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
+
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
+ if (sizeof(void *) == 8) {
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
+ BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
+ }
+
+ // Test key insertion/deletion in random order.
+ ExpectOperationCounts(56540, 134212, values, &tracker, &set4);
+ ExpectOperationCounts(386718, 129807, values, &tracker, &set61);
+ ExpectOperationCounts(586761, 130310, values, &tracker, &set100);
+
+ // Test key insertion/deletion in sorted order.
+ std::sort(values.begin(), values.end());
+ ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
+ ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
+ ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
+
+ // Test key insertion/deletion in reverse sorted order.
+ std::reverse(values.begin(), values.end());
+ ExpectOperationCounts(54949, 127531, values, &tracker, &set4);
+ ExpectOperationCounts(338813, 118266, values, &tracker, &set61);
+ ExpectOperationCounts(534529, 125279, values, &tracker, &set100);
+}
+
+struct MovableOnlyInstanceThreeWayCompare {
+ absl::weak_ordering operator()(const MovableOnlyInstance &a,
+ const MovableOnlyInstance &b) const {
+ return a.compare(b);
+ }
+};
+
+// Note: when the values in this test change, it is expected to have an impact
+// on performance.
+TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
+ InstanceTracker tracker;
+ // Note: this is minimum number of values per node.
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4,
+ MovableOnlyInstanceThreeWayCompare>
+ set4;
+ // Note: this is the default number of values per node for a set of int32s
+ // (with 64-bit pointers).
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,
+ MovableOnlyInstanceThreeWayCompare>
+ set61;
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/100,
+ MovableOnlyInstanceThreeWayCompare>
+ set100;
+
+ // Don't depend on flags for random values because then the expectations will
+ // fail if the flags change.
+ std::vector<int> values =
+ GenerateValuesWithSeed<int>(10000, 1 << 22, /*seed=*/23);
+
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set4)>(), 4);
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>(), 61);
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<decltype(set100)>(), 100);
+ if (sizeof(void *) == 8) {
+ EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
+ BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
+ }
+
+ // Test key insertion/deletion in random order.
+ ExpectOperationCounts(56540, 124221, values, &tracker, &set4);
+ ExpectOperationCounts(386718, 119816, values, &tracker, &set61);
+ ExpectOperationCounts(586761, 120319, values, &tracker, &set100);
+
+ // Test key insertion/deletion in sorted order.
+ std::sort(values.begin(), values.end());
+ ExpectOperationCounts(24972, 85563, values, &tracker, &set4);
+ ExpectOperationCounts(20208, 87757, values, &tracker, &set61);
+ ExpectOperationCounts(20124, 96583, values, &tracker, &set100);
+
+ // Test key insertion/deletion in reverse sorted order.
+ std::reverse(values.begin(), values.end());
+ ExpectOperationCounts(54949, 117532, values, &tracker, &set4);
+ ExpectOperationCounts(338813, 108267, values, &tracker, &set61);
+ ExpectOperationCounts(534529, 115280, values, &tracker, &set100);
+}
+
+struct NoDefaultCtor {
+ int num;
+ explicit NoDefaultCtor(int i) : num(i) {}
+
+ friend bool operator<(const NoDefaultCtor &a, const NoDefaultCtor &b) {
+ return a.num < b.num;
+ }
+};
+
+TEST(Btree, BtreeMapCanHoldNoDefaultCtorTypes) {
+ absl::btree_map<NoDefaultCtor, NoDefaultCtor> m;
+
+ for (int i = 1; i <= 99; ++i) {
+ SCOPED_TRACE(i);
+ EXPECT_TRUE(m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i)).second);
+ }
+ EXPECT_FALSE(m.emplace(NoDefaultCtor(78), NoDefaultCtor(0)).second);
+
+ auto iter99 = m.find(NoDefaultCtor(99));
+ ASSERT_NE(iter99, m.end());
+ EXPECT_EQ(iter99->second.num, 1);
+
+ auto iter1 = m.find(NoDefaultCtor(1));
+ ASSERT_NE(iter1, m.end());
+ EXPECT_EQ(iter1->second.num, 99);
+
+ auto iter50 = m.find(NoDefaultCtor(50));
+ ASSERT_NE(iter50, m.end());
+ EXPECT_EQ(iter50->second.num, 50);
+
+ auto iter25 = m.find(NoDefaultCtor(25));
+ ASSERT_NE(iter25, m.end());
+ EXPECT_EQ(iter25->second.num, 75);
+}
+
+TEST(Btree, BtreeMultimapCanHoldNoDefaultCtorTypes) {
+ absl::btree_multimap<NoDefaultCtor, NoDefaultCtor> m;
+
+ for (int i = 1; i <= 99; ++i) {
+ SCOPED_TRACE(i);
+ m.emplace(NoDefaultCtor(i), NoDefaultCtor(100 - i));
+ }
+
+ auto iter99 = m.find(NoDefaultCtor(99));
+ ASSERT_NE(iter99, m.end());
+ EXPECT_EQ(iter99->second.num, 1);
+
+ auto iter1 = m.find(NoDefaultCtor(1));
+ ASSERT_NE(iter1, m.end());
+ EXPECT_EQ(iter1->second.num, 99);
+
+ auto iter50 = m.find(NoDefaultCtor(50));
+ ASSERT_NE(iter50, m.end());
+ EXPECT_EQ(iter50->second.num, 50);
+
+ auto iter25 = m.find(NoDefaultCtor(25));
+ ASSERT_NE(iter25, m.end());
+ EXPECT_EQ(iter25->second.num, 75);
+}
+
+TEST(Btree, MapAt) {
+ absl::btree_map<int, int> map = {{1, 2}, {2, 4}};
+ EXPECT_EQ(map.at(1), 2);
+ EXPECT_EQ(map.at(2), 4);
+ map.at(2) = 8;
+ const absl::btree_map<int, int> &const_map = map;
+ EXPECT_EQ(const_map.at(1), 2);
+ EXPECT_EQ(const_map.at(2), 8);
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(map.at(3), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(map.at(3), "absl::btree_map::at");
+#endif
+}
+
+TEST(Btree, BtreeMultisetEmplace) {
+ const int value_to_insert = 123456;
+ absl::btree_multiset<int> s;
+ auto iter = s.emplace(value_to_insert);
+ ASSERT_NE(iter, s.end());
+ EXPECT_EQ(*iter, value_to_insert);
+ auto iter2 = s.emplace(value_to_insert);
+ EXPECT_NE(iter2, iter);
+ ASSERT_NE(iter2, s.end());
+ EXPECT_EQ(*iter2, value_to_insert);
+ auto result = s.equal_range(value_to_insert);
+ EXPECT_EQ(std::distance(result.first, result.second), 2);
+}
+
+TEST(Btree, BtreeMultisetEmplaceHint) {
+ const int value_to_insert = 123456;
+ absl::btree_multiset<int> s;
+ auto iter = s.emplace(value_to_insert);
+ ASSERT_NE(iter, s.end());
+ EXPECT_EQ(*iter, value_to_insert);
+ auto emplace_iter = s.emplace_hint(iter, value_to_insert);
+ EXPECT_NE(emplace_iter, iter);
+ ASSERT_NE(emplace_iter, s.end());
+ EXPECT_EQ(*emplace_iter, value_to_insert);
+}
+
+TEST(Btree, BtreeMultimapEmplace) {
+ const int key_to_insert = 123456;
+ const char value0[] = "a";
+ absl::btree_multimap<int, std::string> s;
+ auto iter = s.emplace(key_to_insert, value0);
+ ASSERT_NE(iter, s.end());
+ EXPECT_EQ(iter->first, key_to_insert);
+ EXPECT_EQ(iter->second, value0);
+ const char value1[] = "b";
+ auto iter2 = s.emplace(key_to_insert, value1);
+ EXPECT_NE(iter2, iter);
+ ASSERT_NE(iter2, s.end());
+ EXPECT_EQ(iter2->first, key_to_insert);
+ EXPECT_EQ(iter2->second, value1);
+ auto result = s.equal_range(key_to_insert);
+ EXPECT_EQ(std::distance(result.first, result.second), 2);
+}
+
+TEST(Btree, BtreeMultimapEmplaceHint) {
+ const int key_to_insert = 123456;
+ const char value0[] = "a";
+ absl::btree_multimap<int, std::string> s;
+ auto iter = s.emplace(key_to_insert, value0);
+ ASSERT_NE(iter, s.end());
+ EXPECT_EQ(iter->first, key_to_insert);
+ EXPECT_EQ(iter->second, value0);
+ const char value1[] = "b";
+ auto emplace_iter = s.emplace_hint(iter, key_to_insert, value1);
+ EXPECT_NE(emplace_iter, iter);
+ ASSERT_NE(emplace_iter, s.end());
+ EXPECT_EQ(emplace_iter->first, key_to_insert);
+ EXPECT_EQ(emplace_iter->second, value1);
+}
+
+TEST(Btree, ConstIteratorAccessors) {
+ absl::btree_set<int> set;
+ for (int i = 0; i < 100; ++i) {
+ set.insert(i);
+ }
+
+ auto it = set.cbegin();
+ auto r_it = set.crbegin();
+ for (int i = 0; i < 100; ++i, ++it, ++r_it) {
+ ASSERT_EQ(*it, i);
+ ASSERT_EQ(*r_it, 99 - i);
+ }
+ EXPECT_EQ(it, set.cend());
+ EXPECT_EQ(r_it, set.crend());
+}
+
+TEST(Btree, StrSplitCompatible) {
+ const absl::btree_set<std::string> split_set = absl::StrSplit("a,b,c", ',');
+ const absl::btree_set<std::string> expected_set = {"a", "b", "c"};
+
+ EXPECT_EQ(split_set, expected_set);
+}
+
+// We can't use EXPECT_EQ/etc. to compare absl::weak_ordering because they
+// convert literal 0 to int and absl::weak_ordering can only be compared with
+// literal 0. Defining this function allows for avoiding ClangTidy warnings.
+bool Identity(const bool b) { return b; }
+
+TEST(Btree, ValueComp) {
+ absl::btree_set<int> s;
+ EXPECT_TRUE(s.value_comp()(1, 2));
+ EXPECT_FALSE(s.value_comp()(2, 2));
+ EXPECT_FALSE(s.value_comp()(2, 1));
+
+ absl::btree_map<int, int> m1;
+ EXPECT_TRUE(m1.value_comp()(std::make_pair(1, 0), std::make_pair(2, 0)));
+ EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(2, 0)));
+ EXPECT_FALSE(m1.value_comp()(std::make_pair(2, 0), std::make_pair(1, 0)));
+
+ absl::btree_map<std::string, int> m2;
+ EXPECT_TRUE(Identity(
+ m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)) < 0));
+ EXPECT_TRUE(Identity(
+ m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)) == 0));
+ EXPECT_TRUE(Identity(
+ m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)) > 0));
+}
+
+TEST(Btree, DefaultConstruction) {
+ absl::btree_set<int> s;
+ absl::btree_map<int, int> m;
+ absl::btree_multiset<int> ms;
+ absl::btree_multimap<int, int> mm;
+
+ EXPECT_TRUE(s.empty());
+ EXPECT_TRUE(m.empty());
+ EXPECT_TRUE(ms.empty());
+ EXPECT_TRUE(mm.empty());
+}
+
+TEST(Btree, SwissTableHashable) {
+ static constexpr int kValues = 10000;
+ std::vector<int> values(kValues);
+ std::iota(values.begin(), values.end(), 0);
+ std::vector<std::pair<int, int>> map_values;
+ for (int v : values) map_values.emplace_back(v, -v);
+
+ using set = absl::btree_set<int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+ set{},
+ set{1},
+ set{2},
+ set{1, 2},
+ set{2, 1},
+ set(values.begin(), values.end()),
+ set(values.rbegin(), values.rend()),
+ }));
+
+ using mset = absl::btree_multiset<int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+ mset{},
+ mset{1},
+ mset{1, 1},
+ mset{2},
+ mset{2, 2},
+ mset{1, 2},
+ mset{1, 1, 2},
+ mset{1, 2, 2},
+ mset{1, 1, 2, 2},
+ mset(values.begin(), values.end()),
+ mset(values.rbegin(), values.rend()),
+ }));
+
+ using map = absl::btree_map<int, int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+ map{},
+ map{{1, 0}},
+ map{{1, 1}},
+ map{{2, 0}},
+ map{{2, 2}},
+ map{{1, 0}, {2, 1}},
+ map(map_values.begin(), map_values.end()),
+ map(map_values.rbegin(), map_values.rend()),
+ }));
+
+ using mmap = absl::btree_multimap<int, int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+ mmap{},
+ mmap{{1, 0}},
+ mmap{{1, 1}},
+ mmap{{1, 0}, {1, 1}},
+ mmap{{1, 1}, {1, 0}},
+ mmap{{2, 0}},
+ mmap{{2, 2}},
+ mmap{{1, 0}, {2, 1}},
+ mmap(map_values.begin(), map_values.end()),
+ mmap(map_values.rbegin(), map_values.rend()),
+ }));
+}
+
+TEST(Btree, ComparableSet) {
+ absl::btree_set<int> s1 = {1, 2};
+ absl::btree_set<int> s2 = {2, 3};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_LE(s1, s1);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+ EXPECT_GE(s1, s1);
+}
+
+TEST(Btree, ComparableSetsDifferentLength) {
+ absl::btree_set<int> s1 = {1, 2};
+ absl::btree_set<int> s2 = {1, 2, 3};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+}
+
+TEST(Btree, ComparableMultiset) {
+ absl::btree_multiset<int> s1 = {1, 2};
+ absl::btree_multiset<int> s2 = {2, 3};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_LE(s1, s1);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+ EXPECT_GE(s1, s1);
+}
+
+TEST(Btree, ComparableMap) {
+ absl::btree_map<int, int> s1 = {{1, 2}};
+ absl::btree_map<int, int> s2 = {{2, 3}};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_LE(s1, s1);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+ EXPECT_GE(s1, s1);
+}
+
+TEST(Btree, ComparableMultimap) {
+ absl::btree_multimap<int, int> s1 = {{1, 2}};
+ absl::btree_multimap<int, int> s2 = {{2, 3}};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_LE(s1, s1);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+ EXPECT_GE(s1, s1);
+}
+
+TEST(Btree, ComparableSetWithCustomComparator) {
+ // As specified by
+ // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf section
+ // [container.requirements.general].12, ordering associative containers always
+ // uses default '<' operator
+ // - even if otherwise the container uses custom functor.
+ absl::btree_set<int, std::greater<int>> s1 = {1, 2};
+ absl::btree_set<int, std::greater<int>> s2 = {2, 3};
+ EXPECT_LT(s1, s2);
+ EXPECT_LE(s1, s2);
+ EXPECT_LE(s1, s1);
+ EXPECT_GT(s2, s1);
+ EXPECT_GE(s2, s1);
+ EXPECT_GE(s1, s1);
+}
+
+TEST(Btree, EraseReturnsIterator) {
+ absl::btree_set<int> set = {1, 2, 3, 4, 5};
+ auto result_it = set.erase(set.begin(), set.find(3));
+ EXPECT_EQ(result_it, set.find(3));
+ result_it = set.erase(set.find(5));
+ EXPECT_EQ(result_it, set.end());
+}
+
+TEST(Btree, ExtractAndInsertNodeHandleSet) {
+ absl::btree_set<int> src1 = {1, 2, 3, 4, 5};
+ auto nh = src1.extract(src1.find(3));
+ EXPECT_THAT(src1, ElementsAre(1, 2, 4, 5));
+ absl::btree_set<int> other;
+ absl::btree_set<int>::insert_return_type res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(3));
+ EXPECT_EQ(res.position, other.find(3));
+ EXPECT_TRUE(res.inserted);
+ EXPECT_TRUE(res.node.empty());
+
+ absl::btree_set<int> src2 = {3, 4};
+ nh = src2.extract(src2.find(3));
+ EXPECT_THAT(src2, ElementsAre(4));
+ res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(3));
+ EXPECT_EQ(res.position, other.find(3));
+ EXPECT_FALSE(res.inserted);
+ ASSERT_FALSE(res.node.empty());
+ EXPECT_EQ(res.node.value(), 3);
+}
+
+template <typename Set>
+void TestExtractWithTrackingForSet() {
+ InstanceTracker tracker;
+ {
+ Set s;
+ // Add enough elements to make sure we test internal nodes too.
+ const size_t kSize = 1000;
+ while (s.size() < kSize) {
+ s.insert(MovableOnlyInstance(s.size()));
+ }
+ for (int i = 0; i < kSize; ++i) {
+ // Extract with key
+ auto nh = s.extract(MovableOnlyInstance(i));
+ EXPECT_EQ(s.size(), kSize - 1);
+ EXPECT_EQ(nh.value().value(), i);
+ // Insert with node
+ s.insert(std::move(nh));
+ EXPECT_EQ(s.size(), kSize);
+
+ // Extract with iterator
+ auto it = s.find(MovableOnlyInstance(i));
+ nh = s.extract(it);
+ EXPECT_EQ(s.size(), kSize - 1);
+ EXPECT_EQ(nh.value().value(), i);
+ // Insert with node and hint
+ s.insert(s.begin(), std::move(nh));
+ EXPECT_EQ(s.size(), kSize);
+ }
+ }
+ EXPECT_EQ(0, tracker.instances());
+}
+
+template <typename Map>
+void TestExtractWithTrackingForMap() {
+ InstanceTracker tracker;
+ {
+ Map m;
+ // Add enough elements to make sure we test internal nodes too.
+ const size_t kSize = 1000;
+ while (m.size() < kSize) {
+ m.insert(
+ {CopyableMovableInstance(m.size()), MovableOnlyInstance(m.size())});
+ }
+ for (int i = 0; i < kSize; ++i) {
+ // Extract with key
+ auto nh = m.extract(CopyableMovableInstance(i));
+ EXPECT_EQ(m.size(), kSize - 1);
+ EXPECT_EQ(nh.key().value(), i);
+ EXPECT_EQ(nh.mapped().value(), i);
+ // Insert with node
+ m.insert(std::move(nh));
+ EXPECT_EQ(m.size(), kSize);
+
+ // Extract with iterator
+ auto it = m.find(CopyableMovableInstance(i));
+ nh = m.extract(it);
+ EXPECT_EQ(m.size(), kSize - 1);
+ EXPECT_EQ(nh.key().value(), i);
+ EXPECT_EQ(nh.mapped().value(), i);
+ // Insert with node and hint
+ m.insert(m.begin(), std::move(nh));
+ EXPECT_EQ(m.size(), kSize);
+ }
+ }
+ EXPECT_EQ(0, tracker.instances());
+}
+
+TEST(Btree, ExtractTracking) {
+ TestExtractWithTrackingForSet<absl::btree_set<MovableOnlyInstance>>();
+ TestExtractWithTrackingForSet<absl::btree_multiset<MovableOnlyInstance>>();
+ TestExtractWithTrackingForMap<
+ absl::btree_map<CopyableMovableInstance, MovableOnlyInstance>>();
+ TestExtractWithTrackingForMap<
+ absl::btree_multimap<CopyableMovableInstance, MovableOnlyInstance>>();
+}
+
+TEST(Btree, ExtractAndInsertNodeHandleMultiSet) {
+ absl::btree_multiset<int> src1 = {1, 2, 3, 3, 4, 5};
+ auto nh = src1.extract(src1.find(3));
+ EXPECT_THAT(src1, ElementsAre(1, 2, 3, 4, 5));
+ absl::btree_multiset<int> other;
+ auto res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(3));
+ EXPECT_EQ(res, other.find(3));
+
+ absl::btree_multiset<int> src2 = {3, 4};
+ nh = src2.extract(src2.find(3));
+ EXPECT_THAT(src2, ElementsAre(4));
+ res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(3, 3));
+ EXPECT_EQ(res, ++other.find(3));
+}
+
+TEST(Btree, ExtractAndInsertNodeHandleMap) {
+ absl::btree_map<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
+ auto nh = src1.extract(src1.find(3));
+ EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
+ absl::btree_map<int, int> other;
+ absl::btree_map<int, int>::insert_return_type res =
+ other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
+ EXPECT_EQ(res.position, other.find(3));
+ EXPECT_TRUE(res.inserted);
+ EXPECT_TRUE(res.node.empty());
+
+ absl::btree_map<int, int> src2 = {{3, 6}};
+ nh = src2.extract(src2.find(3));
+ EXPECT_TRUE(src2.empty());
+ res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
+ EXPECT_EQ(res.position, other.find(3));
+ EXPECT_FALSE(res.inserted);
+ ASSERT_FALSE(res.node.empty());
+ EXPECT_EQ(res.node.key(), 3);
+ EXPECT_EQ(res.node.mapped(), 6);
+}
+
+TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
+ absl::btree_multimap<int, int> src1 = {{1, 2}, {3, 4}, {5, 6}};
+ auto nh = src1.extract(src1.find(3));
+ EXPECT_THAT(src1, ElementsAre(Pair(1, 2), Pair(5, 6)));
+ absl::btree_multimap<int, int> other;
+ auto res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(Pair(3, 4)));
+ EXPECT_EQ(res, other.find(3));
+
+ absl::btree_multimap<int, int> src2 = {{3, 6}};
+ nh = src2.extract(src2.find(3));
+ EXPECT_TRUE(src2.empty());
+ res = other.insert(std::move(nh));
+ EXPECT_THAT(other, ElementsAre(Pair(3, 4), Pair(3, 6)));
+ EXPECT_EQ(res, ++other.begin());
+}
+
+TEST(Btree, ExtractMultiMapEquivalentKeys) {
+ // Note: using string keys means a three-way comparator.
+ absl::btree_multimap<std::string, int> map;
+ for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) {
+ map.insert({absl::StrCat(i), j});
+ }
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ const std::string key = absl::StrCat(i);
+ auto node_handle = map.extract(key);
+ EXPECT_EQ(node_handle.key(), key);
+ EXPECT_EQ(node_handle.mapped(), 0) << i;
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ const std::string key = absl::StrCat(i);
+ auto node_handle = map.extract(key);
+ EXPECT_EQ(node_handle.key(), key);
+ EXPECT_EQ(node_handle.mapped(), 1) << i;
+ }
+}
+
+// For multisets, insert with hint also affects correctness because we need to
+// insert immediately before the hint if possible.
+struct InsertMultiHintData {
+ int key;
+ int not_key;
+ bool operator==(const InsertMultiHintData other) const {
+ return key == other.key && not_key == other.not_key;
+ }
+};
+
+struct InsertMultiHintDataKeyCompare {
+ using is_transparent = void;
+ bool operator()(const InsertMultiHintData a,
+ const InsertMultiHintData b) const {
+ return a.key < b.key;
+ }
+ bool operator()(const int a, const InsertMultiHintData b) const {
+ return a < b.key;
+ }
+ bool operator()(const InsertMultiHintData a, const int b) const {
+ return a.key < b;
+ }
+};
+
+TEST(Btree, InsertHintNodeHandle) {
+ // For unique sets, insert with hint is just a performance optimization.
+ // Test that insert works correctly when the hint is right or wrong.
+ {
+ absl::btree_set<int> src = {1, 2, 3, 4, 5};
+ auto nh = src.extract(src.find(3));
+ EXPECT_THAT(src, ElementsAre(1, 2, 4, 5));
+ absl::btree_set<int> other = {0, 100};
+ // Test a correct hint.
+ auto it = other.insert(other.lower_bound(3), std::move(nh));
+ EXPECT_THAT(other, ElementsAre(0, 3, 100));
+ EXPECT_EQ(it, other.find(3));
+
+ nh = src.extract(src.find(5));
+ // Test an incorrect hint.
+ it = other.insert(other.end(), std::move(nh));
+ EXPECT_THAT(other, ElementsAre(0, 3, 5, 100));
+ EXPECT_EQ(it, other.find(5));
+ }
+
+ absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare> src =
+ {{1, 2}, {3, 4}, {3, 5}};
+ auto nh = src.extract(src.lower_bound(3));
+ EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 4}));
+ absl::btree_multiset<InsertMultiHintData, InsertMultiHintDataKeyCompare>
+ other = {{3, 1}, {3, 2}, {3, 3}};
+ auto it = other.insert(--other.end(), std::move(nh));
+ EXPECT_THAT(
+ other, ElementsAre(InsertMultiHintData{3, 1}, InsertMultiHintData{3, 2},
+ InsertMultiHintData{3, 4}, InsertMultiHintData{3, 3}));
+ EXPECT_EQ(it, --(--other.end()));
+
+ nh = src.extract(src.find(3));
+ EXPECT_EQ(nh.value(), (InsertMultiHintData{3, 5}));
+ it = other.insert(other.begin(), std::move(nh));
+ EXPECT_THAT(other,
+ ElementsAre(InsertMultiHintData{3, 5}, InsertMultiHintData{3, 1},
+ InsertMultiHintData{3, 2}, InsertMultiHintData{3, 4},
+ InsertMultiHintData{3, 3}));
+ EXPECT_EQ(it, other.begin());
+}
+
+struct IntCompareToCmp {
+ absl::weak_ordering operator()(int a, int b) const {
+ if (a < b) return absl::weak_ordering::less;
+ if (a > b) return absl::weak_ordering::greater;
+ return absl::weak_ordering::equivalent;
+ }
+};
+
+TEST(Btree, MergeIntoUniqueContainers) {
+ absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
+ absl::btree_multiset<int> src2 = {3, 4, 4, 5};
+ absl::btree_set<int> dst;
+
+ dst.merge(src1);
+ EXPECT_TRUE(src1.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3));
+ dst.merge(src2);
+ EXPECT_THAT(src2, ElementsAre(3, 4));
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(Btree, MergeIntoUniqueContainersWithCompareTo) {
+ absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
+ absl::btree_multiset<int> src2 = {3, 4, 4, 5};
+ absl::btree_set<int, IntCompareToCmp> dst;
+
+ dst.merge(src1);
+ EXPECT_TRUE(src1.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3));
+ dst.merge(src2);
+ EXPECT_THAT(src2, ElementsAre(3, 4));
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(Btree, MergeIntoMultiContainers) {
+ absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
+ absl::btree_multiset<int> src2 = {3, 4, 4, 5};
+ absl::btree_multiset<int> dst;
+
+ dst.merge(src1);
+ EXPECT_TRUE(src1.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3));
+ dst.merge(src2);
+ EXPECT_TRUE(src2.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
+}
+
+TEST(Btree, MergeIntoMultiContainersWithCompareTo) {
+ absl::btree_set<int, IntCompareToCmp> src1 = {1, 2, 3};
+ absl::btree_multiset<int> src2 = {3, 4, 4, 5};
+ absl::btree_multiset<int, IntCompareToCmp> dst;
+
+ dst.merge(src1);
+ EXPECT_TRUE(src1.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3));
+ dst.merge(src2);
+ EXPECT_TRUE(src2.empty());
+ EXPECT_THAT(dst, ElementsAre(1, 2, 3, 3, 4, 4, 5));
+}
+
+TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
+ absl::btree_map<int, int, IntCompareToCmp> src1 = {{1, 1}, {2, 2}, {3, 3}};
+ absl::btree_multimap<int, int, std::greater<int>> src2 = {
+ {5, 5}, {4, 1}, {4, 4}, {3, 2}};
+ absl::btree_multimap<int, int> dst;
+
+ dst.merge(src1);
+ EXPECT_TRUE(src1.empty());
+ EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3)));
+ dst.merge(src2);
+ EXPECT_TRUE(src2.empty());
+ EXPECT_THAT(dst, ElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), Pair(3, 2),
+ Pair(4, 1), Pair(4, 4), Pair(5, 5)));
+}
+
+TEST(Btree, MergeIntoSetMovableOnly) {
+ absl::btree_set<MovableOnlyInstance> src;
+ src.insert(MovableOnlyInstance(1));
+ absl::btree_multiset<MovableOnlyInstance> dst1;
+ dst1.insert(MovableOnlyInstance(2));
+ absl::btree_set<MovableOnlyInstance> dst2;
+
+ // Test merge into multiset.
+ dst1.merge(src);
+
+ EXPECT_TRUE(src.empty());
+ // ElementsAre/ElementsAreArray don't work with move-only types.
+ ASSERT_THAT(dst1, SizeIs(2));
+ EXPECT_EQ(*dst1.begin(), MovableOnlyInstance(1));
+ EXPECT_EQ(*std::next(dst1.begin()), MovableOnlyInstance(2));
+
+ // Test merge into set.
+ dst2.merge(dst1);
+
+ EXPECT_TRUE(dst1.empty());
+ ASSERT_THAT(dst2, SizeIs(2));
+ EXPECT_EQ(*dst2.begin(), MovableOnlyInstance(1));
+ EXPECT_EQ(*std::next(dst2.begin()), MovableOnlyInstance(2));
+}
+
+struct KeyCompareToWeakOrdering {
+ template <typename T>
+ absl::weak_ordering operator()(const T &a, const T &b) const {
+ return a < b ? absl::weak_ordering::less
+ : a == b ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+};
+
+struct KeyCompareToStrongOrdering {
+ template <typename T>
+ absl::strong_ordering operator()(const T &a, const T &b) const {
+ return a < b ? absl::strong_ordering::less
+ : a == b ? absl::strong_ordering::equal
+ : absl::strong_ordering::greater;
+ }
+};
+
+TEST(Btree, UserProvidedKeyCompareToComparators) {
+ absl::btree_set<int, KeyCompareToWeakOrdering> weak_set = {1, 2, 3};
+ EXPECT_TRUE(weak_set.contains(2));
+ EXPECT_FALSE(weak_set.contains(4));
+
+ absl::btree_set<int, KeyCompareToStrongOrdering> strong_set = {1, 2, 3};
+ EXPECT_TRUE(strong_set.contains(2));
+ EXPECT_FALSE(strong_set.contains(4));
+}
+
+TEST(Btree, TryEmplaceBasicTest) {
+ absl::btree_map<int, std::string> m;
+
+ // Should construct a string from the literal.
+ m.try_emplace(1, "one");
+ EXPECT_EQ(1, m.size());
+
+ // Try other string constructors and const lvalue key.
+ const int key(42);
+ m.try_emplace(key, 3, 'a');
+ m.try_emplace(2, std::string("two"));
+
+ EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
+ EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, std::string>>{
+ {1, "one"}, {2, "two"}, {42, "aaa"}}));
+}
+
+TEST(Btree, TryEmplaceWithHintWorks) {
+ // Use a counting comparator here to verify that hint is used.
+ int calls = 0;
+ auto cmp = [&calls](int x, int y) {
+ ++calls;
+ return x < y;
+ };
+ using Cmp = decltype(cmp);
+
+ absl::btree_map<int, int, Cmp> m(cmp);
+ for (int i = 0; i < 128; ++i) {
+ m.emplace(i, i);
+ }
+
+ // Sanity check for the comparator
+ calls = 0;
+ m.emplace(127, 127);
+ EXPECT_GE(calls, 4);
+
+ // Try with begin hint:
+ calls = 0;
+ auto it = m.try_emplace(m.begin(), -1, -1);
+ EXPECT_EQ(129, m.size());
+ EXPECT_EQ(it, m.begin());
+ EXPECT_LE(calls, 2);
+
+ // Try with end hint:
+ calls = 0;
+ std::pair<int, int> pair1024 = {1024, 1024};
+ it = m.try_emplace(m.end(), pair1024.first, pair1024.second);
+ EXPECT_EQ(130, m.size());
+ EXPECT_EQ(it, --m.end());
+ EXPECT_LE(calls, 2);
+
+ // Try value already present, bad hint; ensure no duplicate added:
+ calls = 0;
+ it = m.try_emplace(m.end(), 16, 17);
+ EXPECT_EQ(130, m.size());
+ EXPECT_GE(calls, 4);
+ EXPECT_EQ(it, m.find(16));
+
+ // Try value already present, hint points directly to it:
+ calls = 0;
+ it = m.try_emplace(it, 16, 17);
+ EXPECT_EQ(130, m.size());
+ EXPECT_LE(calls, 2);
+ EXPECT_EQ(it, m.find(16));
+
+ m.erase(2);
+ EXPECT_EQ(129, m.size());
+ auto hint = m.find(3);
+ // Try emplace in the middle of two other elements.
+ calls = 0;
+ m.try_emplace(hint, 2, 2);
+ EXPECT_EQ(130, m.size());
+ EXPECT_LE(calls, 2);
+
+ EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
+}
+
+TEST(Btree, TryEmplaceWithBadHint) {
+ absl::btree_map<int, int> m = {{1, 1}, {9, 9}};
+
+ // Bad hint (too small), should still emplace:
+ auto it = m.try_emplace(m.begin(), 2, 2);
+ EXPECT_EQ(it, ++m.begin());
+ EXPECT_THAT(m, ElementsAreArray(
+ std::vector<std::pair<int, int>>{{1, 1}, {2, 2}, {9, 9}}));
+
+ // Bad hint, too large this time:
+ it = m.try_emplace(++(++m.begin()), 0, 0);
+ EXPECT_EQ(it, m.begin());
+ EXPECT_THAT(m, ElementsAreArray(std::vector<std::pair<int, int>>{
+ {0, 0}, {1, 1}, {2, 2}, {9, 9}}));
+}
+
+TEST(Btree, TryEmplaceMaintainsSortedOrder) {
+ absl::btree_map<int, std::string> m;
+ std::pair<int, std::string> pair5 = {5, "five"};
+
+ // Test both lvalue & rvalue emplace.
+ m.try_emplace(10, "ten");
+ m.try_emplace(pair5.first, pair5.second);
+ EXPECT_EQ(2, m.size());
+ EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
+
+ int int100{100};
+ m.try_emplace(int100, "hundred");
+ m.try_emplace(1, "one");
+ EXPECT_EQ(4, m.size());
+ EXPECT_TRUE(std::is_sorted(m.begin(), m.end()));
+}
+
+TEST(Btree, TryEmplaceWithHintAndNoValueArgsWorks) {
+ absl::btree_map<int, int> m;
+ m.try_emplace(m.end(), 1);
+ EXPECT_EQ(0, m[1]);
+}
+
+TEST(Btree, TryEmplaceWithHintAndMultipleValueArgsWorks) {
+ absl::btree_map<int, std::string> m;
+ m.try_emplace(m.end(), 1, 10, 'a');
+ EXPECT_EQ(std::string(10, 'a'), m[1]);
+}
+
+TEST(Btree, MoveAssignmentAllocatorPropagation) {
+ InstanceTracker tracker;
+
+ int64_t bytes1 = 0, bytes2 = 0;
+ PropagatingCountingAlloc<MovableOnlyInstance> allocator1(&bytes1);
+ PropagatingCountingAlloc<MovableOnlyInstance> allocator2(&bytes2);
+ std::less<MovableOnlyInstance> cmp;
+
+ // Test propagating allocator_type.
+ {
+ absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
+ PropagatingCountingAlloc<MovableOnlyInstance>>
+ set1(cmp, allocator1), set2(cmp, allocator2);
+
+ for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
+
+ tracker.ResetCopiesMovesSwaps();
+ set2 = std::move(set1);
+ EXPECT_EQ(tracker.moves(), 0);
+ }
+ // Test non-propagating allocator_type with equal allocators.
+ {
+ absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
+ CountingAllocator<MovableOnlyInstance>>
+ set1(cmp, allocator1), set2(cmp, allocator1);
+
+ for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
+
+ tracker.ResetCopiesMovesSwaps();
+ set2 = std::move(set1);
+ EXPECT_EQ(tracker.moves(), 0);
+ }
+ // Test non-propagating allocator_type with different allocators.
+ {
+ absl::btree_set<MovableOnlyInstance, std::less<MovableOnlyInstance>,
+ CountingAllocator<MovableOnlyInstance>>
+ set1(cmp, allocator1), set2(cmp, allocator2);
+
+ for (int i = 0; i < 100; ++i) set1.insert(MovableOnlyInstance(i));
+
+ tracker.ResetCopiesMovesSwaps();
+ set2 = std::move(set1);
+ EXPECT_GE(tracker.moves(), 100);
+ }
+}
+
+TEST(Btree, EmptyTree) {
+ absl::btree_set<int> s;
+ EXPECT_TRUE(s.empty());
+ EXPECT_EQ(s.size(), 0);
+ EXPECT_GT(s.max_size(), 0);
+}
+
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(Btree, EraseIf) {
+ // Test that erase_if works with all the container types and supports lambdas.
+ {
+ absl::btree_set<int> s = {1, 3, 5, 6, 100};
+ erase_if(s, [](int k) { return k > 3; });
+ EXPECT_THAT(s, ElementsAre(1, 3));
+ }
+ {
+ absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};
+ erase_if(s, [](int k) { return k <= 3; });
+ EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));
+ }
+ {
+ absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};
+ erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; });
+ EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));
+ }
+ {
+ absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},
+ {6, 6}, {6, 7}, {100, 6}};
+ erase_if(m, [](std::pair<const int, int> kv) { return kv.second == 6; });
+ EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));
+ }
+ // Test that erasing all elements from a large set works and test support for
+ // function pointers.
+ {
+ absl::btree_set<int> s;
+ for (int i = 0; i < 1000; ++i) s.insert(2 * i);
+ erase_if(s, IsEven);
+ EXPECT_THAT(s, IsEmpty());
+ }
+ // Test that erase_if supports other format of function pointers.
+ {
+ absl::btree_set<int> s = {1, 3, 5, 6, 100};
+ erase_if(s, &IsEven);
+ EXPECT_THAT(s, ElementsAre(1, 3, 5));
+ }
+}
+
+TEST(Btree, InsertOrAssign) {
+ absl::btree_map<int, int> m = {{1, 1}, {3, 3}};
+ using value_type = typename decltype(m)::value_type;
+
+ auto ret = m.insert_or_assign(4, 4);
+ EXPECT_EQ(*ret.first, value_type(4, 4));
+ EXPECT_TRUE(ret.second);
+ ret = m.insert_or_assign(3, 100);
+ EXPECT_EQ(*ret.first, value_type(3, 100));
+ EXPECT_FALSE(ret.second);
+
+ auto hint_ret = m.insert_or_assign(ret.first, 3, 200);
+ EXPECT_EQ(*hint_ret, value_type(3, 200));
+ hint_ret = m.insert_or_assign(m.find(1), 0, 1);
+ EXPECT_EQ(*hint_ret, value_type(0, 1));
+ // Test with bad hint.
+ hint_ret = m.insert_or_assign(m.end(), -1, 1);
+ EXPECT_EQ(*hint_ret, value_type(-1, 1));
+
+ EXPECT_THAT(m, ElementsAre(Pair(-1, 1), Pair(0, 1), Pair(1, 1), Pair(3, 200),
+ Pair(4, 4)));
+}
+
+TEST(Btree, InsertOrAssignMovableOnly) {
+ absl::btree_map<int, MovableOnlyInstance> m;
+ using value_type = typename decltype(m)::value_type;
+
+ auto ret = m.insert_or_assign(4, MovableOnlyInstance(4));
+ EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(4)));
+ EXPECT_TRUE(ret.second);
+ ret = m.insert_or_assign(4, MovableOnlyInstance(100));
+ EXPECT_EQ(*ret.first, value_type(4, MovableOnlyInstance(100)));
+ EXPECT_FALSE(ret.second);
+
+ auto hint_ret = m.insert_or_assign(ret.first, 3, MovableOnlyInstance(200));
+ EXPECT_EQ(*hint_ret, value_type(3, MovableOnlyInstance(200)));
+
+ EXPECT_EQ(m.size(), 2);
+}
+
+TEST(Btree, BitfieldArgument) {
+ union {
+ int n : 1;
+ };
+ n = 0;
+ absl::btree_map<int, int> m;
+ m.erase(n);
+ m.count(n);
+ m.find(n);
+ m.contains(n);
+ m.equal_range(n);
+ m.insert_or_assign(n, n);
+ m.insert_or_assign(m.end(), n, n);
+ m.try_emplace(n);
+ m.try_emplace(m.end(), n);
+ m.at(n);
+ m[n];
+}
+
+TEST(Btree, SetRangeConstructorAndInsertSupportExplicitConversionComparable) {
+ const absl::string_view names[] = {"n1", "n2"};
+
+ absl::btree_set<std::string> name_set1{std::begin(names), std::end(names)};
+ EXPECT_THAT(name_set1, ElementsAreArray(names));
+
+ absl::btree_set<std::string> name_set2;
+ name_set2.insert(std::begin(names), std::end(names));
+ EXPECT_THAT(name_set2, ElementsAreArray(names));
+}
+
+// A type that is explicitly convertible from int and counts constructor calls.
+struct ConstructorCounted {
+ explicit ConstructorCounted(int i) : i(i) { ++constructor_calls; }
+ bool operator==(int other) const { return i == other; }
+
+ int i;
+ static int constructor_calls;
+};
+int ConstructorCounted::constructor_calls = 0;
+
+struct ConstructorCountedCompare {
+ bool operator()(int a, const ConstructorCounted &b) const { return a < b.i; }
+ bool operator()(const ConstructorCounted &a, int b) const { return a.i < b; }
+ bool operator()(const ConstructorCounted &a,
+ const ConstructorCounted &b) const {
+ return a.i < b.i;
+ }
+ using is_transparent = void;
+};
+
+TEST(Btree,
+ SetRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
+ const int i[] = {0, 1, 1};
+ ConstructorCounted::constructor_calls = 0;
+
+ absl::btree_set<ConstructorCounted, ConstructorCountedCompare> set{
+ std::begin(i), std::end(i)};
+ EXPECT_THAT(set, ElementsAre(0, 1));
+ EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+
+ set.insert(std::begin(i), std::end(i));
+ EXPECT_THAT(set, ElementsAre(0, 1));
+ EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+}
+
+TEST(Btree,
+ SetRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
+ const int i[] = {0, 1};
+
+ absl::btree_set<std::vector<void *>> s1{std::begin(i), std::end(i)};
+ EXPECT_THAT(s1, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
+
+ absl::btree_set<std::vector<void *>> s2;
+ s2.insert(std::begin(i), std::end(i));
+ EXPECT_THAT(s2, ElementsAre(IsEmpty(), ElementsAre(IsNull())));
+}
+
+// libstdc++ included with GCC 4.9 has a bug in the std::pair constructors that
+// prevents explicit conversions between pair types.
+// We only run this test for the libstdc++ from GCC 7 or newer because we can't
+// reliably check the libstdc++ version prior to that release.
+#if !defined(__GLIBCXX__) || \
+ (defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 7)
+TEST(Btree, MapRangeConstructorAndInsertSupportExplicitConversionComparable) {
+ const std::pair<absl::string_view, int> names[] = {{"n1", 1}, {"n2", 2}};
+
+ absl::btree_map<std::string, int> name_map1{std::begin(names),
+ std::end(names)};
+ EXPECT_THAT(name_map1, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
+
+ absl::btree_map<std::string, int> name_map2;
+ name_map2.insert(std::begin(names), std::end(names));
+ EXPECT_THAT(name_map2, ElementsAre(Pair("n1", 1), Pair("n2", 2)));
+}
+
+TEST(Btree,
+ MapRangeConstructorAndInsertExplicitConvComparableLimitConstruction) {
+ const std::pair<int, int> i[] = {{0, 1}, {1, 2}, {1, 3}};
+ ConstructorCounted::constructor_calls = 0;
+
+ absl::btree_map<ConstructorCounted, int, ConstructorCountedCompare> map{
+ std::begin(i), std::end(i)};
+ EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
+ EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+
+ map.insert(std::begin(i), std::end(i));
+ EXPECT_THAT(map, ElementsAre(Pair(0, 1), Pair(1, 2)));
+ EXPECT_EQ(ConstructorCounted::constructor_calls, 2);
+}
+
+TEST(Btree,
+ MapRangeConstructorAndInsertSupportExplicitConversionNonComparable) {
+ const std::pair<int, int> i[] = {{0, 1}, {1, 2}};
+
+ absl::btree_map<std::vector<void *>, int> m1{std::begin(i), std::end(i)};
+ EXPECT_THAT(m1,
+ ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
+
+ absl::btree_map<std::vector<void *>, int> m2;
+ m2.insert(std::begin(i), std::end(i));
+ EXPECT_THAT(m2,
+ ElementsAre(Pair(IsEmpty(), 1), Pair(ElementsAre(IsNull()), 2)));
+}
+
+TEST(Btree, HeterogeneousTryEmplace) {
+ absl::btree_map<std::string, int> m;
+ std::string s = "key";
+ absl::string_view sv = s;
+ m.try_emplace(sv, 1);
+ EXPECT_EQ(m[s], 1);
+
+ m.try_emplace(m.end(), sv, 2);
+ EXPECT_EQ(m[s], 1);
+}
+
+TEST(Btree, HeterogeneousOperatorMapped) {
+ absl::btree_map<std::string, int> m;
+ std::string s = "key";
+ absl::string_view sv = s;
+ m[sv] = 1;
+ EXPECT_EQ(m[s], 1);
+
+ m[sv] = 2;
+ EXPECT_EQ(m[s], 2);
+}
+
+TEST(Btree, HeterogeneousInsertOrAssign) {
+ absl::btree_map<std::string, int> m;
+ std::string s = "key";
+ absl::string_view sv = s;
+ m.insert_or_assign(sv, 1);
+ EXPECT_EQ(m[s], 1);
+
+ m.insert_or_assign(m.end(), sv, 2);
+ EXPECT_EQ(m[s], 2);
+}
+#endif
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(Btree, NodeHandleMutableKeyAccess) {
+ {
+ absl::btree_map<std::string, std::string> map;
+
+ map["key1"] = "mapped";
+
+ auto nh = map.extract(map.begin());
+ nh.key().resize(3);
+ map.insert(std::move(nh));
+
+ EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+ }
+ // Also for multimap.
+ {
+ absl::btree_multimap<std::string, std::string> map;
+
+ map.emplace("key1", "mapped");
+
+ auto nh = map.extract(map.begin());
+ nh.key().resize(3);
+ map.insert(std::move(nh));
+
+ EXPECT_THAT(map, ElementsAre(Pair("key", "mapped")));
+ }
+}
+#endif
+
+struct MultiKey {
+ int i1;
+ int i2;
+};
+
+bool operator==(const MultiKey a, const MultiKey b) {
+ return a.i1 == b.i1 && a.i2 == b.i2;
+}
+
+// A heterogeneous comparator that has different equivalence classes for
+// different lookup types.
+struct MultiKeyComp {
+ using is_transparent = void;
+ bool operator()(const MultiKey a, const MultiKey b) const {
+ if (a.i1 != b.i1) return a.i1 < b.i1;
+ return a.i2 < b.i2;
+ }
+ bool operator()(const int a, const MultiKey b) const { return a < b.i1; }
+ bool operator()(const MultiKey a, const int b) const { return a.i1 < b; }
+};
+
+// A heterogeneous, three-way comparator that has different equivalence classes
+// for different lookup types.
+struct MultiKeyThreeWayComp {
+ using is_transparent = void;
+ absl::weak_ordering operator()(const MultiKey a, const MultiKey b) const {
+ if (a.i1 < b.i1) return absl::weak_ordering::less;
+ if (a.i1 > b.i1) return absl::weak_ordering::greater;
+ if (a.i2 < b.i2) return absl::weak_ordering::less;
+ if (a.i2 > b.i2) return absl::weak_ordering::greater;
+ return absl::weak_ordering::equivalent;
+ }
+ absl::weak_ordering operator()(const int a, const MultiKey b) const {
+ if (a < b.i1) return absl::weak_ordering::less;
+ if (a > b.i1) return absl::weak_ordering::greater;
+ return absl::weak_ordering::equivalent;
+ }
+ absl::weak_ordering operator()(const MultiKey a, const int b) const {
+ if (a.i1 < b) return absl::weak_ordering::less;
+ if (a.i1 > b) return absl::weak_ordering::greater;
+ return absl::weak_ordering::equivalent;
+ }
+};
+
+template <typename Compare>
+class BtreeMultiKeyTest : public ::testing::Test {};
+using MultiKeyComps = ::testing::Types<MultiKeyComp, MultiKeyThreeWayComp>;
+TYPED_TEST_SUITE(BtreeMultiKeyTest, MultiKeyComps);
+
+TYPED_TEST(BtreeMultiKeyTest, EqualRange) {
+ absl::btree_set<MultiKey, TypeParam> set;
+ for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) {
+ set.insert({i, j});
+ }
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ auto equal_range = set.equal_range(i);
+ EXPECT_EQ(equal_range.first->i1, i);
+ EXPECT_EQ(equal_range.first->i2, 0) << i;
+ EXPECT_EQ(std::distance(equal_range.first, equal_range.second), 100) << i;
+ }
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Extract) {
+ absl::btree_set<MultiKey, TypeParam> set;
+ for (int i = 0; i < 100; ++i) {
+ for (int j = 0; j < 100; ++j) {
+ set.insert({i, j});
+ }
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ auto node_handle = set.extract(i);
+ EXPECT_EQ(node_handle.value().i1, i);
+ EXPECT_EQ(node_handle.value().i2, 0) << i;
+ }
+
+ for (int i = 0; i < 100; ++i) {
+ auto node_handle = set.extract(i);
+ EXPECT_EQ(node_handle.value().i1, i);
+ EXPECT_EQ(node_handle.value().i2, 1) << i;
+ }
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Erase) {
+ absl::btree_set<MultiKey, TypeParam> set = {
+ {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+ EXPECT_EQ(set.erase(2), 2);
+ EXPECT_THAT(set, ElementsAre(MultiKey{1, 1}, MultiKey{3, 1}));
+}
+
+TYPED_TEST(BtreeMultiKeyTest, Count) {
+ const absl::btree_set<MultiKey, TypeParam> set = {
+ {1, 1}, {2, 1}, {2, 2}, {3, 1}};
+ EXPECT_EQ(set.count(2), 2);
+}
+
+TEST(Btree, AllocConstructor) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used = 0;
+ Alloc alloc(&bytes_used);
+ Set set(alloc);
+
+ set.insert({1, 2, 3});
+
+ EXPECT_THAT(set, ElementsAre(1, 2, 3));
+ EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocInitializerListConstructor) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used = 0;
+ Alloc alloc(&bytes_used);
+ Set set({1, 2, 3}, alloc);
+
+ EXPECT_THAT(set, ElementsAre(1, 2, 3));
+ EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocRangeConstructor) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used = 0;
+ Alloc alloc(&bytes_used);
+ std::vector<int> v = {1, 2, 3};
+ Set set(v.begin(), v.end(), alloc);
+
+ EXPECT_THAT(set, ElementsAre(1, 2, 3));
+ EXPECT_GT(bytes_used, set.size() * sizeof(int));
+}
+
+TEST(Btree, AllocCopyConstructor) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used1 = 0;
+ Alloc alloc1(&bytes_used1);
+ Set set1(alloc1);
+
+ set1.insert({1, 2, 3});
+
+ int64_t bytes_used2 = 0;
+ Alloc alloc2(&bytes_used2);
+ Set set2(set1, alloc2);
+
+ EXPECT_THAT(set1, ElementsAre(1, 2, 3));
+ EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+ EXPECT_GT(bytes_used1, set1.size() * sizeof(int));
+ EXPECT_EQ(bytes_used1, bytes_used2);
+}
+
+TEST(Btree, AllocMoveConstructor_SameAlloc) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used = 0;
+ Alloc alloc(&bytes_used);
+ Set set1(alloc);
+
+ set1.insert({1, 2, 3});
+
+ const int64_t original_bytes_used = bytes_used;
+ EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+ Set set2(std::move(set1), alloc);
+
+ EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+ EXPECT_EQ(bytes_used, original_bytes_used);
+}
+
+TEST(Btree, AllocMoveConstructor_DifferentAlloc) {
+ using Alloc = CountingAllocator<int>;
+ using Set = absl::btree_set<int, std::less<int>, Alloc>;
+ int64_t bytes_used1 = 0;
+ Alloc alloc1(&bytes_used1);
+ Set set1(alloc1);
+
+ set1.insert({1, 2, 3});
+
+ const int64_t original_bytes_used = bytes_used1;
+ EXPECT_GT(original_bytes_used, set1.size() * sizeof(int));
+
+ int64_t bytes_used2 = 0;
+ Alloc alloc2(&bytes_used2);
+ Set set2(std::move(set1), alloc2);
+
+ EXPECT_THAT(set2, ElementsAre(1, 2, 3));
+ // We didn't free these bytes allocated by `set1` yet.
+ EXPECT_EQ(bytes_used1, original_bytes_used);
+ EXPECT_EQ(bytes_used2, original_bytes_used);
+}
+
+} // namespace
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/btree_test.h
new file mode 100644
index 00000000000..624908072d5
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array.h
index 6da84411aed..fcb3e545b24 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -31,7 +31,6 @@
#define ABSL_CONTAINER_FIXED_ARRAY_H_
#include <algorithm>
-#include <array>
#include <cassert>
#include <cstddef>
#include <initializer_list>
@@ -42,6 +41,7 @@
#include <type_traits>
#include "absl/algorithm/algorithm.h"
+#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
@@ -51,6 +51,7 @@
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
@@ -106,13 +107,13 @@ class FixedArray {
public:
using allocator_type = typename AllocatorTraits::allocator_type;
- using value_type = typename allocator_type::value_type;
- using pointer = typename allocator_type::pointer;
- using const_pointer = typename allocator_type::const_pointer;
- using reference = typename allocator_type::reference;
- using const_reference = typename allocator_type::const_reference;
- using size_type = typename allocator_type::size_type;
- using difference_type = typename allocator_type::difference_type;
+ using value_type = typename AllocatorTraits::value_type;
+ using pointer = typename AllocatorTraits::pointer;
+ using const_pointer = typename AllocatorTraits::const_pointer;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = typename AllocatorTraits::size_type;
+ using difference_type = typename AllocatorTraits::difference_type;
using iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
@@ -217,7 +218,7 @@ class FixedArray {
// Returns a reference the ith element of the fixed array.
// REQUIRES: 0 <= i < size()
reference operator[](size_type i) {
- assert(i < size());
+ ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
@@ -225,14 +226,14 @@ class FixedArray {
// ith element of the fixed array.
// REQUIRES: 0 <= i < size()
const_reference operator[](size_type i) const {
- assert(i < size());
+ ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
// FixedArray::at
//
- // Bounds-checked access. Returns a reference to the ith element of the
- // fiexed array, or throws std::out_of_range
+ // Bounds-checked access. Returns a reference to the ith element of the fixed
+ // array, or throws std::out_of_range
reference at(size_type i) {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange("FixedArray::at failed bounds check");
@@ -252,20 +253,32 @@ class FixedArray {
// FixedArray::front()
//
// Returns a reference to the first element of the fixed array.
- reference front() { return *begin(); }
+ reference front() {
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[0];
+ }
// Overload of FixedArray::front() to return a reference to the first element
// of a fixed array of const values.
- const_reference front() const { return *begin(); }
+ const_reference front() const {
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[0];
+ }
// FixedArray::back()
//
// Returns a reference to the last element of the fixed array.
- reference back() { return *(end() - 1); }
+ reference back() {
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[size() - 1];
+ }
// Overload of FixedArray::back() to return a reference to the last element
// of a fixed array of const values.
- const_reference back() const { return *(end() - 1); }
+ const_reference back() const {
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[size() - 1];
+ }
// FixedArray::begin()
//
@@ -386,8 +399,7 @@ class FixedArray {
// error: call to int __builtin___sprintf_chk(etc...)
// will always overflow destination buffer [-Werror]
//
- template <typename OuterT = value_type,
- typename InnerT = absl::remove_extent_t<OuterT>,
+ template <typename OuterT, typename InnerT = absl::remove_extent_t<OuterT>,
size_t InnerN = std::extent<OuterT>::value>
struct StorageElementWrapper {
InnerT array[InnerN];
@@ -396,8 +408,6 @@ class FixedArray {
using StorageElement =
absl::conditional_t<std::is_array<value_type>::value,
StorageElementWrapper<value_type>, value_type>;
- using StorageElementBuffer =
- absl::aligned_storage_t<sizeof(StorageElement), alignof(StorageElement)>;
static pointer AsValueType(pointer ptr) { return ptr; }
static pointer AsValueType(StorageElementWrapper<value_type>* ptr) {
@@ -407,25 +417,25 @@ class FixedArray {
static_assert(sizeof(StorageElement) == sizeof(value_type), "");
static_assert(alignof(StorageElement) == alignof(value_type), "");
- struct NonEmptyInlinedStorage {
- StorageElement* data() {
- return reinterpret_cast<StorageElement*>(inlined_storage_.data());
- }
+ class NonEmptyInlinedStorage {
+ public:
+ StorageElement* data() { return reinterpret_cast<StorageElement*>(buff_); }
+ void AnnotateConstruct(size_type n);
+ void AnnotateDestruct(size_type n);
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
void* RedzoneBegin() { return &redzone_begin_; }
void* RedzoneEnd() { return &redzone_end_ + 1; }
-#endif // ADDRESS_SANITIZER
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
- void AnnotateConstruct(size_type);
- void AnnotateDestruct(size_type);
-
- ADDRESS_SANITIZER_REDZONE(redzone_begin_);
- std::array<StorageElementBuffer, inline_elements> inlined_storage_;
- ADDRESS_SANITIZER_REDZONE(redzone_end_);
+ private:
+ ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
+ alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
+ ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
};
- struct EmptyInlinedStorage {
+ class EmptyInlinedStorage {
+ public:
StorageElement* data() { return nullptr; }
void AnnotateConstruct(size_type) {}
void AnnotateDestruct(size_type) {}
@@ -459,9 +469,7 @@ class FixedArray {
size_type size() const { return size_alloc_.template get<0>(); }
StorageElement* begin() const { return data_; }
StorageElement* end() const { return begin() + size(); }
- allocator_type& alloc() {
- return size_alloc_.template get<1>();
- }
+ allocator_type& alloc() { return size_alloc_.template get<1>(); }
private:
static bool UsingInlinedStorage(size_type n) {
@@ -496,23 +504,29 @@ constexpr typename FixedArray<T, N, A>::size_type
template <typename T, size_t N, typename A>
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateConstruct(
typename FixedArray<T, N, A>::size_type n) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
if (!n) return;
- ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n);
- ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin());
-#endif // ADDRESS_SANITIZER
+ ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),
+ data() + n);
+ ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),
+ RedzoneBegin());
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
static_cast<void>(n); // Mark used when not in asan mode
}
template <typename T, size_t N, typename A>
void FixedArray<T, N, A>::NonEmptyInlinedStorage::AnnotateDestruct(
typename FixedArray<T, N, A>::size_type n) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
if (!n) return;
- ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd());
- ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data());
-#endif // ADDRESS_SANITIZER
+ ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,
+ RedzoneEnd());
+ ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),
+ data());
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
static_cast<void>(n); // Mark used when not in asan mode
}
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_CONTAINER_FIXED_ARRAY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_benchmark.cc
index b4f0cf2aeb0..3c7a5a72345 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_benchmark.cc
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/container/fixed_array.h"
-
#include <stddef.h>
+
#include <string>
#include "benchmark/benchmark.h"
+#include "absl/container/fixed_array.h"
namespace {
@@ -25,8 +25,9 @@ namespace {
// set an int to a constant..
class SimpleClass {
public:
- SimpleClass() : i(3) { }
+ SimpleClass() : i(3) {}
~SimpleClass() { i = 0; }
+
private:
int i;
};
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
index da63dbfe38e..e5f59299b35 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,14 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <initializer_list>
-
+#include "absl/base/config.h"
#include "absl/container/fixed_array.h"
+#ifdef ABSL_HAVE_EXCEPTIONS
+
+#include <initializer_list>
+
#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -33,10 +37,19 @@ constexpr int kUpdatedValue = 10;
using ::testing::TestThrowingCtor;
using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
+using ThrowAlloc =
+ testing::ThrowingAllocator<Thrower, testing::AllocSpec::kEverythingThrows>;
+using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using MoveThrowAlloc =
+ testing::ThrowingAllocator<MoveThrower,
+ testing::AllocSpec::kEverythingThrows>;
+
using FixedArr = absl::FixedArray<Thrower, kInlined>;
+using FixedArrWithAlloc = absl::FixedArray<Thrower, kInlined, ThrowAlloc>;
-using MoveThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
using MoveFixedArr = absl::FixedArray<MoveThrower, kInlined>;
+using MoveFixedArrWithAlloc =
+ absl::FixedArray<MoveThrower, kInlined, MoveThrowAlloc>;
TEST(FixedArrayExceptionSafety, CopyConstructor) {
auto small = FixedArr(kSmallSize);
@@ -46,6 +59,14 @@ TEST(FixedArrayExceptionSafety, CopyConstructor) {
TestThrowingCtor<FixedArr>(large);
}
+TEST(FixedArrayExceptionSafety, CopyConstructorWithAlloc) {
+ auto small = FixedArrWithAlloc(kSmallSize);
+ TestThrowingCtor<FixedArrWithAlloc>(small);
+
+ auto large = FixedArrWithAlloc(kLargeSize);
+ TestThrowingCtor<FixedArrWithAlloc>(large);
+}
+
TEST(FixedArrayExceptionSafety, MoveConstructor) {
TestThrowingCtor<FixedArr>(FixedArr(kSmallSize));
TestThrowingCtor<FixedArr>(FixedArr(kLargeSize));
@@ -55,16 +76,35 @@ TEST(FixedArrayExceptionSafety, MoveConstructor) {
TestThrowingCtor<MoveFixedArr>(MoveFixedArr(kLargeSize));
}
+TEST(FixedArrayExceptionSafety, MoveConstructorWithAlloc) {
+ TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kSmallSize));
+ TestThrowingCtor<FixedArrWithAlloc>(FixedArrWithAlloc(kLargeSize));
+
+ // TypeSpec::kNoThrowMove
+ TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kSmallSize));
+ TestThrowingCtor<MoveFixedArrWithAlloc>(MoveFixedArrWithAlloc(kLargeSize));
+}
+
TEST(FixedArrayExceptionSafety, SizeConstructor) {
TestThrowingCtor<FixedArr>(kSmallSize);
TestThrowingCtor<FixedArr>(kLargeSize);
}
+TEST(FixedArrayExceptionSafety, SizeConstructorWithAlloc) {
+ TestThrowingCtor<FixedArrWithAlloc>(kSmallSize);
+ TestThrowingCtor<FixedArrWithAlloc>(kLargeSize);
+}
+
TEST(FixedArrayExceptionSafety, SizeValueConstructor) {
TestThrowingCtor<FixedArr>(kSmallSize, Thrower());
TestThrowingCtor<FixedArr>(kLargeSize, Thrower());
}
+TEST(FixedArrayExceptionSafety, SizeValueConstructorWithAlloc) {
+ TestThrowingCtor<FixedArrWithAlloc>(kSmallSize, Thrower());
+ TestThrowingCtor<FixedArrWithAlloc>(kLargeSize, Thrower());
+}
+
TEST(FixedArrayExceptionSafety, IteratorConstructor) {
auto small = FixedArr(kSmallSize);
TestThrowingCtor<FixedArr>(small.begin(), small.end());
@@ -73,6 +113,14 @@ TEST(FixedArrayExceptionSafety, IteratorConstructor) {
TestThrowingCtor<FixedArr>(large.begin(), large.end());
}
+TEST(FixedArrayExceptionSafety, IteratorConstructorWithAlloc) {
+ auto small = FixedArrWithAlloc(kSmallSize);
+ TestThrowingCtor<FixedArrWithAlloc>(small.begin(), small.end());
+
+ auto large = FixedArrWithAlloc(kLargeSize);
+ TestThrowingCtor<FixedArrWithAlloc>(large.begin(), large.end());
+}
+
TEST(FixedArrayExceptionSafety, InitListConstructor) {
constexpr int small_inlined = 3;
using SmallFixedArr = absl::FixedArray<Thrower, small_inlined>;
@@ -86,9 +134,23 @@ TEST(FixedArrayExceptionSafety, InitListConstructor) {
Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
}
-testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
- // Marked volatile to prevent optimization. Used for running asan tests.
- volatile int sum = 0;
+TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) {
+ constexpr int small_inlined = 3;
+ using SmallFixedArrWithAlloc =
+ absl::FixedArray<Thrower, small_inlined, ThrowAlloc>;
+
+ TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{});
+ // Test inlined allocation
+ TestThrowingCtor<SmallFixedArrWithAlloc>(
+ std::initializer_list<Thrower>{Thrower{}, Thrower{}});
+ // Test out of line allocation
+ TestThrowingCtor<SmallFixedArrWithAlloc>(std::initializer_list<Thrower>{
+ Thrower{}, Thrower{}, Thrower{}, Thrower{}, Thrower{}});
+}
+
+template <typename FixedArrT>
+testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) {
+ int sum = 0;
for (const auto& thrower : *fixed_arr) {
sum += thrower.Get();
}
@@ -97,7 +159,7 @@ testing::AssertionResult ReadMemory(FixedArr* fixed_arr) {
TEST(FixedArrayExceptionSafety, Fill) {
auto test_fill = testing::MakeExceptionSafetyTester()
- .WithContracts(ReadMemory)
+ .WithContracts(ReadMemory<FixedArr>)
.WithOperation([&](FixedArr* fixed_arr_ptr) {
auto thrower =
Thrower(kUpdatedValue, testing::nothrow_ctor);
@@ -112,6 +174,28 @@ TEST(FixedArrayExceptionSafety, Fill) {
.Test());
}
+TEST(FixedArrayExceptionSafety, FillWithAlloc) {
+ auto test_fill = testing::MakeExceptionSafetyTester()
+ .WithContracts(ReadMemory<FixedArrWithAlloc>)
+ .WithOperation([&](FixedArrWithAlloc* fixed_arr_ptr) {
+ auto thrower =
+ Thrower(kUpdatedValue, testing::nothrow_ctor);
+ fixed_arr_ptr->fill(thrower);
+ });
+
+ EXPECT_TRUE(test_fill
+ .WithInitialValue(
+ FixedArrWithAlloc(kSmallSize, Thrower(kInitialValue)))
+ .Test());
+ EXPECT_TRUE(test_fill
+ .WithInitialValue(
+ FixedArrWithAlloc(kLargeSize, Thrower(kInitialValue)))
+ .Test());
+}
+
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+
+#endif // ABSL_HAVE_EXCEPTIONS
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_test.cc
index 205ff41fe11..49598e7a053 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/fixed_array_test.cc
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/container/fixed_array.h"
#include <stdio.h>
+
#include <cstring>
#include <list>
#include <memory>
@@ -26,7 +27,10 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/config.h"
#include "absl/base/internal/exception_testing.h"
+#include "absl/base/options.h"
+#include "absl/container/internal/counting_allocator.h"
#include "absl/hash/hash_testing.h"
#include "absl/memory/memory.h"
@@ -42,11 +46,7 @@ static bool IsOnStack(const ArrayType& a) {
class ConstructionTester {
public:
- ConstructionTester()
- : self_ptr_(this),
- value_(0) {
- constructions++;
- }
+ ConstructionTester() : self_ptr_(this), value_(0) { constructions++; }
~ConstructionTester() {
assert(self_ptr_ == this);
self_ptr_ = nullptr;
@@ -58,9 +58,7 @@ class ConstructionTester {
static int constructions;
static int destructions;
- void CheckConstructed() {
- assert(self_ptr_ == this);
- }
+ void CheckConstructed() { assert(self_ptr_ == this); }
void set(int value) { value_ = value; }
int get() { return value_; }
@@ -150,7 +148,7 @@ TEST(FixedArrayTest, SmallObjects) {
}
{
- // Arrays of > default size should be on the stack
+ // Arrays of > default size should be on the heap
absl::FixedArray<int, 100> array(101);
EXPECT_FALSE(IsOnStack(array));
}
@@ -160,13 +158,13 @@ TEST(FixedArrayTest, SmallObjects) {
// same amount of stack space
absl::FixedArray<int> array1(0);
absl::FixedArray<char> array2(0);
- EXPECT_LE(sizeof(array1), sizeof(array2)+100);
- EXPECT_LE(sizeof(array2), sizeof(array1)+100);
+ EXPECT_LE(sizeof(array1), sizeof(array2) + 100);
+ EXPECT_LE(sizeof(array2), sizeof(array1) + 100);
}
{
// Ensure that vectors are properly constructed inside a fixed array.
- absl::FixedArray<std::vector<int> > array(2);
+ absl::FixedArray<std::vector<int>> array(2);
EXPECT_EQ(0, array[0].size());
EXPECT_EQ(0, array[1].size());
}
@@ -193,6 +191,21 @@ TEST(FixedArrayTest, AtThrows) {
"failed bounds check");
}
+TEST(FixedArrayTest, Hardened) {
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ absl::FixedArray<int> a = {1, 2, 3};
+ EXPECT_EQ(a[2], 3);
+ EXPECT_DEATH_IF_SUPPORTED(a[3], "");
+ EXPECT_DEATH_IF_SUPPORTED(a[-1], "");
+
+ absl::FixedArray<int> empty(0);
+ EXPECT_DEATH_IF_SUPPORTED(empty[0], "");
+ EXPECT_DEATH_IF_SUPPORTED(empty[-1], "");
+ EXPECT_DEATH_IF_SUPPORTED(empty.front(), "");
+ EXPECT_DEATH_IF_SUPPORTED(empty.back(), "");
+#endif
+}
+
TEST(FixedArrayRelationalsTest, EqualArrays) {
for (int i = 0; i < 10; ++i) {
absl::FixedArray<int, 5> a1(i);
@@ -270,8 +283,8 @@ static void TestArray(int n) {
array.data()[i].set(i + 1);
}
for (int i = 0; i < n; i++) {
- EXPECT_THAT(array[i].get(), i+1);
- EXPECT_THAT(array.data()[i].get(), i+1);
+ EXPECT_THAT(array[i].get(), i + 1);
+ EXPECT_THAT(array.data()[i].get(), i + 1);
}
} // Close scope containing 'array'.
@@ -296,7 +309,7 @@ static void TestArrayOfArrays(int n) {
ASSERT_EQ(array.size(), n);
ASSERT_EQ(array.memsize(),
- sizeof(ConstructionTester) * elements_per_inner_array * n);
+ sizeof(ConstructionTester) * elements_per_inner_array * n);
ASSERT_EQ(array.begin() + n, array.end());
// Check that all elements were constructed
@@ -316,7 +329,7 @@ static void TestArrayOfArrays(int n) {
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < elements_per_inner_array; j++) {
- ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);
+ ASSERT_EQ((array[i])[j].get(), i * elements_per_inner_array + j);
ASSERT_EQ((array.data()[i])[j].get(), i * elements_per_inner_array + j);
}
}
@@ -329,8 +342,7 @@ static void TestArrayOfArrays(int n) {
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < elements_per_inner_array; j++) {
- ASSERT_EQ((array[i])[j].get(),
- (i + 1) * elements_per_inner_array + j);
+ ASSERT_EQ((array[i])[j].get(), (i + 1) * elements_per_inner_array + j);
ASSERT_EQ((array.data()[i])[j].get(),
(i + 1) * elements_per_inner_array + j);
}
@@ -343,7 +355,7 @@ static void TestArrayOfArrays(int n) {
}
TEST(IteratorConstructorTest, NonInline) {
- int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
+ int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
absl::FixedArray<int, ABSL_ARRAYSIZE(kInput) - 1> const fixed(
kInput, kInput + ABSL_ARRAYSIZE(kInput));
ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
@@ -353,7 +365,7 @@ TEST(IteratorConstructorTest, NonInline) {
}
TEST(IteratorConstructorTest, Inline) {
- int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
+ int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
absl::FixedArray<int, ABSL_ARRAYSIZE(kInput)> const fixed(
kInput, kInput + ABSL_ARRAYSIZE(kInput));
ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
@@ -363,9 +375,10 @@ TEST(IteratorConstructorTest, Inline) {
}
TEST(IteratorConstructorTest, NonPod) {
- char const* kInput[] =
- { "red", "orange", "yellow", "green", "blue", "indigo", "violet" };
- absl::FixedArray<std::string> const fixed(kInput, kInput + ABSL_ARRAYSIZE(kInput));
+ char const* kInput[] = {"red", "orange", "yellow", "green",
+ "blue", "indigo", "violet"};
+ absl::FixedArray<std::string> const fixed(kInput,
+ kInput + ABSL_ARRAYSIZE(kInput));
ASSERT_EQ(ABSL_ARRAYSIZE(kInput), fixed.size());
for (size_t i = 0; i < ABSL_ARRAYSIZE(kInput); ++i) {
ASSERT_EQ(kInput[i], fixed[i]);
@@ -380,7 +393,7 @@ TEST(IteratorConstructorTest, FromEmptyVector) {
}
TEST(IteratorConstructorTest, FromNonEmptyVector) {
- int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
+ int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
std::vector<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
absl::FixedArray<int> const fixed(items.begin(), items.end());
ASSERT_EQ(items.size(), fixed.size());
@@ -390,7 +403,7 @@ TEST(IteratorConstructorTest, FromNonEmptyVector) {
}
TEST(IteratorConstructorTest, FromBidirectionalIteratorRange) {
- int const kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
+ int const kInput[] = {2, 3, 5, 7, 11, 13, 17};
std::list<int> const items(kInput, kInput + ABSL_ARRAYSIZE(kInput));
absl::FixedArray<int> const fixed(items.begin(), items.end());
EXPECT_THAT(fixed, testing::ElementsAreArray(kInput));
@@ -507,9 +520,8 @@ struct PickyDelete {
TEST(FixedArrayTest, UsesGlobalAlloc) { absl::FixedArray<PickyDelete, 0> a(5); }
-
TEST(FixedArrayTest, Data) {
- static const int kInput[] = { 2, 3, 5, 7, 11, 13, 17 };
+ static const int kInput[] = {2, 3, 5, 7, 11, 13, 17};
absl::FixedArray<int> fa(std::begin(kInput), std::end(kInput));
EXPECT_EQ(fa.data(), &*fa.begin());
EXPECT_EQ(fa.data(), &fa[0]);
@@ -610,19 +622,16 @@ TEST(FixedArrayTest, Fill) {
empty.fill(fill_val);
}
-// TODO(johnsoncj): Investigate InlinedStorage default initialization in GCC 4.x
#ifndef __GNUC__
TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
using T = char;
constexpr auto capacity = 10;
using FixedArrType = absl::FixedArray<T, capacity>;
- using FixedArrBuffType =
- absl::aligned_storage_t<sizeof(FixedArrType), alignof(FixedArrType)>;
constexpr auto scrubbed_bits = 0x95;
constexpr auto length = capacity / 2;
- FixedArrBuffType buff;
- std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrBuffType));
+ alignas(FixedArrType) unsigned char buff[sizeof(FixedArrType)];
+ std::memset(std::addressof(buff), scrubbed_bits, sizeof(FixedArrType));
FixedArrType* arr =
::new (static_cast<void*>(std::addressof(buff))) FixedArrType(length);
@@ -631,70 +640,9 @@ TEST(FixedArrayTest, DefaultCtorDoesNotValueInit) {
}
#endif // __GNUC__
-// 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 std::allocator<T> {
- public:
- using Alloc = std::allocator<T>;
- using pointer = typename Alloc::pointer;
- using size_type = typename Alloc::size_type;
-
- CountingAllocator() : bytes_used_(nullptr), instance_count_(nullptr) {}
- explicit CountingAllocator(int64_t* b)
- : bytes_used_(b), instance_count_(nullptr) {}
- CountingAllocator(int64_t* b, int64_t* a)
- : bytes_used_(b), instance_count_(a) {}
-
- template <typename U>
- explicit CountingAllocator(const CountingAllocator<U>& x)
- : Alloc(x),
- bytes_used_(x.bytes_used_),
- instance_count_(x.instance_count_) {}
-
- pointer allocate(size_type n, const void* const hint = nullptr) {
- assert(bytes_used_ != nullptr);
- *bytes_used_ += n * sizeof(T);
- return Alloc::allocate(n, hint);
- }
-
- void deallocate(pointer p, size_type n) {
- Alloc::deallocate(p, n);
- assert(bytes_used_ != nullptr);
- *bytes_used_ -= n * sizeof(T);
- }
-
- template <typename... Args>
- void construct(pointer p, Args&&... args) {
- Alloc::construct(p, absl::forward<Args>(args)...);
- if (instance_count_) {
- *instance_count_ += 1;
- }
- }
-
- void destroy(pointer p) {
- Alloc::destroy(p);
- if (instance_count_) {
- *instance_count_ -= 1;
- }
- }
-
- template <typename U>
- class rebind {
- public:
- using other = CountingAllocator<U>;
- };
-
- int64_t* bytes_used_;
- int64_t* instance_count_;
-};
-
TEST(AllocatorSupportTest, CountInlineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
+ using Alloc = absl::container_internal::CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
@@ -715,7 +663,7 @@ TEST(AllocatorSupportTest, CountInlineAllocations) {
TEST(AllocatorSupportTest, CountOutoflineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
+ using Alloc = absl::container_internal::CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
@@ -736,7 +684,7 @@ TEST(AllocatorSupportTest, CountOutoflineAllocations) {
TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
+ using Alloc = absl::container_internal::CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
@@ -764,7 +712,7 @@ TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
+ using Alloc = absl::container_internal::CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
@@ -796,7 +744,7 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) {
using testing::SizeIs;
constexpr size_t inlined_size = 4;
- using Alloc = CountingAllocator<int>;
+ using Alloc = absl::container_internal::CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
{
@@ -820,53 +768,70 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) {
}
}
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
absl::FixedArray<int, 32> a(10);
- int *raw = a.data();
+ int* raw = a.data();
raw[0] = 0;
raw[9] = 0;
- EXPECT_DEATH(raw[-2] = 0, "container-overflow");
- EXPECT_DEATH(raw[-1] = 0, "container-overflow");
- EXPECT_DEATH(raw[10] = 0, "container-overflow");
- EXPECT_DEATH(raw[31] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-2] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[10] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[31] = 0, "container-overflow");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
absl::FixedArray<char, 17> a(12);
- char *raw = a.data();
+ char* raw = a.data();
raw[0] = 0;
raw[11] = 0;
- EXPECT_DEATH(raw[-7] = 0, "container-overflow");
- EXPECT_DEATH(raw[-1] = 0, "container-overflow");
- EXPECT_DEATH(raw[12] = 0, "container-overflow");
- EXPECT_DEATH(raw[17] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-7] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[12] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[17] = 0, "container-overflow");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
absl::FixedArray<uint64_t, 20> a(20);
- uint64_t *raw = a.data();
+ uint64_t* raw = a.data();
raw[0] = 0;
raw[19] = 0;
- EXPECT_DEATH(raw[-1] = 0, "container-overflow");
- EXPECT_DEATH(raw[20] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[20] = 0, "container-overflow");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
absl::FixedArray<ThreeInts> a(10);
- ThreeInts *raw = a.data();
+ ThreeInts* raw = a.data();
raw[0] = ThreeInts();
raw[9] = ThreeInts();
// Note: raw[-1] is pointing to 12 bytes before the container range. However,
// there is only a 8-byte red zone before the container range, so we only
// access the last 4 bytes of the struct to make sure it stays within the red
// zone.
- EXPECT_DEATH(raw[-1].z_ = 0, "container-overflow");
- EXPECT_DEATH(raw[10] = ThreeInts(), "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[-1].z_ = 0, "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), "container-overflow");
// The actual size of storage is kDefaultBytes=256, 21*12 = 252,
// so reading raw[21] should still trigger the correct warning.
- EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow");
+ EXPECT_DEATH_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow");
+}
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
+
+TEST(FixedArrayTest, AbslHashValueWorks) {
+ using V = absl::FixedArray<int>;
+ std::vector<V> cases;
+
+ // Generate a variety of vectors some of these are small enough for the inline
+ // space but are stored out of line.
+ for (int i = 0; i < 10; ++i) {
+ V v(i);
+ for (int j = 0; j < i; ++j) {
+ v[j] = j;
+ }
+ cases.push_back(v);
+ }
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
}
-#endif // ADDRESS_SANITIZER
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map.h
index cc3d8b69b7a..74def0df0e3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -42,6 +42,7 @@
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class K, class V>
struct FlatHashMapPolicy;
@@ -77,7 +78,7 @@ struct FlatHashMapPolicy;
// NOTE: A `flat_hash_map` stores its value types directly inside its
// implementation array to avoid memory indirection. Because a `flat_hash_map`
// is designed to move data when rehashed, map values will not retain pointer
-// stability. If you require pointer stability, or your values are large,
+// stability. If you require pointer stability, or if your values are large,
// consider using `absl::flat_hash_map<Key, std::unique_ptr<Value>>` instead.
// If your types are not moveable or you require pointer stability for keys,
// consider `absl::node_hash_map`.
@@ -219,8 +220,12 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// Erases the element at `position` of the `flat_hash_map`, returning
// `void`.
//
- // NOTE: this return behavior is different than that of STL containers in
- // general and `std::unordered_map` in particular.
+ // NOTE: returning `void` in this case is different than that of STL
+ // containers in general and `std::unordered_map` in particular (which
+ // return an iterator to the element following the erased element). If that
+ // iterator is needed, simply post increment the iterator:
+ //
+ // map.erase(it++);
//
// iterator erase(const_iterator first, const_iterator last):
//
@@ -229,7 +234,8 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists.
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
using Base::erase;
// flat_hash_map::insert()
@@ -356,6 +362,10 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// Inserts (via copy or move) the element of the specified key into the
// `flat_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;
// flat_hash_map::extract()
@@ -374,6 +384,11 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// key value and returns a node handle owning that extracted data. If the
// `flat_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;
// flat_hash_map::merge()
@@ -393,7 +408,7 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// for the past-the-end iterator, which is invalidated.
//
// `swap()` requires that the flat hash map's hashing and key equivalence
- // functions be Swappable, and are exchaged using unqualified calls to
+ // 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
@@ -523,29 +538,39 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
using Base::key_eq;
};
+// erase_if(flat_hash_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Predicate>
+void erase_if(flat_hash_map<K, V, H, E, A>& c, Predicate pred) {
+ container_internal::EraseIf(pred, &c);
+}
+
namespace container_internal {
template <class K, class V>
struct FlatHashMapPolicy {
- using slot_type = container_internal::slot_type<K, V>;
+ using slot_policy = container_internal::map_slot_policy<K, V>;
+ using slot_type = typename slot_policy::slot_type;
using key_type = K;
using mapped_type = V;
using init_type = std::pair</*non const*/ key_type, mapped_type>;
template <class Allocator, class... Args>
static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
- slot_type::construct(alloc, slot, std::forward<Args>(args)...);
+ slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
}
template <class Allocator>
static void destroy(Allocator* alloc, slot_type* slot) {
- slot_type::destroy(alloc, slot);
+ slot_policy::destroy(alloc, slot);
}
template <class Allocator>
static void transfer(Allocator* alloc, slot_type* new_slot,
slot_type* old_slot) {
- slot_type::transfer(alloc, new_slot, old_slot);
+ slot_policy::transfer(alloc, new_slot, old_slot);
}
template <class F, class... Args>
@@ -575,6 +600,7 @@ struct IsUnorderedContainer<
} // namespace container_algorithm_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_FLAT_HASH_MAP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map_test.cc
index 2c6f2515f86..89ec60c916e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_map_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,35 +14,60 @@
#include "absl/container/flat_hash_map.h"
+#include <memory>
+
+#include "absl/base/internal/raw_logging.h"
#include "absl/container/internal/hash_generator_testing.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"
#include "absl/types/any.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
using ::absl::container_internal::hash_internal::Enum;
using ::absl::container_internal::hash_internal::EnumClass;
using ::testing::_;
+using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
+// Check that absl::flat_hash_map works in a global constructor.
+struct BeforeMain {
+ BeforeMain() {
+ absl::flat_hash_map<int, int> x;
+ x.insert({1, 1});
+ ABSL_RAW_CHECK(x.find(0) == x.end(), "x should not contain 0");
+ auto it = x.find(1);
+ ABSL_RAW_CHECK(it != x.end(), "x should contain 1");
+ ABSL_RAW_CHECK(it->second, "1 should map to 1");
+ }
+};
+const BeforeMain before_main;
+
template <class K, class V>
-using Map =
- flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual, Alloc<>>;
+using Map = flat_hash_map<K, V, StatefulTestingHash, StatefulTestingEqual,
+ Alloc<std::pair<const K, V>>>;
static_assert(!std::is_standard_layout<NonStandardLayout>(), "");
using MapTypes =
- ::testing::Types<Map<int, int>, Map<std::string, int>, Map<Enum, std::string>,
- Map<EnumClass, int>, Map<int, NonStandardLayout>,
- Map<NonStandardLayout, int>>;
+ ::testing::Types<Map<int, int>, Map<std::string, int>,
+ Map<Enum, std::string>, Map<EnumClass, int>,
+ Map<int, NonStandardLayout>, Map<NonStandardLayout, int>>;
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, ModifiersTest, MapTypes);
+
+using UniquePtrMapTypes = ::testing::Types<Map<int, std::unique_ptr<int>>>;
+
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashMap, UniquePtrModifiersTest,
+ UniquePtrMapTypes);
TEST(FlatHashMap, StandardLayout) {
struct Int {
@@ -139,6 +164,7 @@ TEST(FlatHashMap, LazyKeyPattern) {
int conversions = 0;
int hashes = 0;
flat_hash_map<size_t, size_t, Hash, Eq> m(0, Hash{&hashes});
+ m.reserve(3);
m[LazyInt(1, &conversions)] = 1;
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 1)));
@@ -203,39 +229,60 @@ TEST(FlatHashMap, MergeExtractInsert) {
m.insert(std::move(node));
EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 17), Pair(2, 9)));
}
-#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
-TEST(FlatHashMap, Any) {
- absl::flat_hash_map<int, absl::any> m;
- m.emplace(1, 7);
- auto it = m.find(1);
- ASSERT_NE(it, m.end());
- EXPECT_EQ(7, absl::any_cast<int>(it->second));
-
- m.emplace(std::piecewise_construct, std::make_tuple(2), std::make_tuple(8));
- it = m.find(2);
- ASSERT_NE(it, m.end());
- EXPECT_EQ(8, absl::any_cast<int>(it->second));
-
- m.emplace(std::piecewise_construct, std::make_tuple(3),
- std::make_tuple(absl::any(9)));
- it = m.find(3);
- ASSERT_NE(it, m.end());
- EXPECT_EQ(9, absl::any_cast<int>(it->second));
-
- struct H {
- size_t operator()(const absl::any&) const { return 0; }
- };
- struct E {
- bool operator()(const absl::any&, const absl::any&) const { return true; }
- };
- absl::flat_hash_map<absl::any, int, H, E> m2;
- m2.emplace(1, 7);
- auto it2 = m2.find(1);
- ASSERT_NE(it2, m2.end());
- EXPECT_EQ(7, it2->second);
+
+bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }
+
+TEST(FlatHashMap, EraseIf) {
+ // Erase all elements.
+ {
+ flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, [](std::pair<const int, int>) { return true; });
+ EXPECT_THAT(s, IsEmpty());
+ }
+ // Erase no elements.
+ {
+ flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, [](std::pair<const int, int>) { return false; });
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
+ Pair(4, 4), Pair(5, 5)));
+ }
+ // Erase specific elements.
+ {
+ flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s,
+ [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; });
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
+ }
+ // Predicate is function reference.
+ {
+ flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, FirstIsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+ }
+ // Predicate is function pointer.
+ {
+ flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, &FirstIsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+ }
}
-#endif // __ANDROID__
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(FlatHashMap, NodeHandleMutableKeyAccess) {
+ flat_hash_map<std::string, std::string> map;
+
+ map["key1"] = "mapped";
+
+ auto nh = map.extract(map.begin());
+ nh.key().resize(3);
+ map.insert(std::move(nh));
+
+ EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set.h
index 84984cc4927..6b89da65714 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -40,6 +40,7 @@
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <typename T>
struct FlatHashSetPolicy;
@@ -55,9 +56,9 @@ struct FlatHashSetPolicy;
// following notable differences:
//
// * Requires keys that are CopyConstructible
-// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
-// `insert()`, provided that the set is provided a compatible heterogeneous
-// hashing function and equality operator.
+// * Supports heterogeneous lookup, through `find()` and `insert()`, provided
+// that the set is provided a compatible heterogeneous hashing function and
+// equality operator.
// * Invalidates any references and pointers to elements within the table after
// `rehash()`.
// * Contains a `capacity()` member function indicating the number of element
@@ -212,8 +213,12 @@ class flat_hash_set
// Erases the element at `position` of the `flat_hash_set`, returning
// `void`.
//
- // NOTE: this return behavior is different than that of STL containers in
- // general and `std::unordered_map` in particular.
+ // NOTE: returning `void` in this case is different than that of STL
+ // containers in general and `std::unordered_set` in particular (which
+ // return an iterator to the element following the erased element). If that
+ // iterator is needed, simply post increment the iterator:
+ //
+ // set.erase(it++);
//
// iterator erase(const_iterator first, const_iterator last):
//
@@ -222,7 +227,8 @@ class flat_hash_set
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists.
+ // Erases the element with the matching key, if it exists, returning the
+ // number of elements erased (0 or 1).
using Base::erase;
// flat_hash_set::insert()
@@ -318,7 +324,7 @@ class flat_hash_set
// flat_hash_set::merge()
//
- // Extracts elements from a given `source` flat hash map into this
+ // Extracts elements from a given `source` flat hash set into this
// `flat_hash_set`. If the destination `flat_hash_set` already contains an
// element with an equivalent key, that element is not extracted.
using Base::merge;
@@ -434,6 +440,14 @@ class flat_hash_set
using Base::key_eq;
};
+// erase_if(flat_hash_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename T, typename H, typename E, typename A, typename Predicate>
+void erase_if(flat_hash_set<T, H, E, A>& c, Predicate pred) {
+ container_internal::EraseIf(pred, &c);
+}
+
namespace container_internal {
template <class T>
@@ -484,6 +498,7 @@ struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>>
} // namespace container_algorithm_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_FLAT_HASH_SET_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set_test.cc
index e52fd532cbe..8f6f9944ca4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/flat_hash_set_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,23 +16,38 @@
#include <vector>
+#include "absl/base/internal/raw_logging.h"
#include "absl/container/internal/hash_generator_testing.h"
#include "absl/container/internal/unordered_set_constructor_test.h"
#include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
#include "absl/container/internal/unordered_set_modifiers_test.h"
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
using ::absl::container_internal::hash_internal::Enum;
using ::absl::container_internal::hash_internal::EnumClass;
+using ::testing::IsEmpty;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
using ::testing::UnorderedElementsAreArray;
+// Check that absl::flat_hash_set works in a global constructor.
+struct BeforeMain {
+ BeforeMain() {
+ absl::flat_hash_set<int> x;
+ x.insert(1);
+ ABSL_RAW_CHECK(!x.contains(0), "x should not contain 0");
+ ABSL_RAW_CHECK(x.contains(1), "x should contain 1");
+ }
+};
+const BeforeMain before_main;
+
template <class T>
using Set =
absl::flat_hash_set<T, StatefulTestingHash, StatefulTestingEqual, Alloc<T>>;
@@ -40,9 +55,10 @@ using Set =
using SetTypes =
::testing::Types<Set<int>, Set<std::string>, Set<Enum>, Set<EnumClass>>;
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(FlatHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(FlatHashSet, ModifiersTest, SetTypes);
TEST(FlatHashSet, EmplaceString) {
std::vector<std::string> v = {"a", "b"};
@@ -121,6 +137,42 @@ TEST(FlatHashSet, MergeExtractInsert) {
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
}
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(FlatHashSet, EraseIf) {
+ // Erase all elements.
+ {
+ flat_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int) { return true; });
+ EXPECT_THAT(s, IsEmpty());
+ }
+ // Erase no elements.
+ {
+ flat_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int) { return false; });
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+ }
+ // Erase specific elements.
+ {
+ flat_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int k) { return k % 2 == 1; });
+ EXPECT_THAT(s, UnorderedElementsAre(2, 4));
+ }
+ // Predicate is function reference.
+ {
+ flat_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, IsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+ }
+ // Predicate is function pointer.
+ {
+ flat_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, &IsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+ }
+}
+
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector.h
index fe228001bf2..7c18234235a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector.h
@@ -1,10 +1,10 @@
-// Copyright 2018 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -48,12 +48,14 @@
#include "absl/algorithm/algorithm.h"
#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
+#include "absl/container/internal/inlined_vector.h"
#include "absl/memory/memory.h"
namespace absl {
-
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// InlinedVector
// -----------------------------------------------------------------------------
@@ -62,170 +64,188 @@ namespace absl {
// `std::vector` for use cases where the vector's size is sufficiently small
// that it can be inlined. If the inlined vector does grow beyond its estimated
// capacity, it will trigger an initial allocation on the heap, and will behave
-// as a `std:vector`. The API of the `absl::InlinedVector` within this file is
+// as a `std::vector`. The API of the `absl::InlinedVector` within this file is
// designed to cover the same API footprint as covered by `std::vector`.
template <typename T, size_t N, typename A = std::allocator<T>>
class InlinedVector {
- static_assert(N > 0, "InlinedVector requires inline capacity greater than 0");
- constexpr static typename A::size_type inlined_capacity() {
- return static_cast<typename A::size_type>(N);
- }
+ static_assert(N > 0, "`absl::InlinedVector` requires an inlined capacity.");
- template <typename Iterator>
- using DisableIfIntegral =
- absl::enable_if_t<!std::is_integral<Iterator>::value>;
+ using Storage = inlined_vector_internal::Storage<T, N, A>;
- template <typename Iterator>
- using EnableIfInputIterator = absl::enable_if_t<std::is_convertible<
- typename std::iterator_traits<Iterator>::iterator_category,
- std::input_iterator_tag>::value>;
+ using AllocatorTraits = typename Storage::AllocatorTraits;
+ using RValueReference = typename Storage::RValueReference;
+ using MoveIterator = typename Storage::MoveIterator;
+ using IsMemcpyOk = typename Storage::IsMemcpyOk;
template <typename Iterator>
- using IteratorCategory =
- typename std::iterator_traits<Iterator>::iterator_category;
+ using IteratorValueAdapter =
+ typename Storage::template IteratorValueAdapter<Iterator>;
+ using CopyValueAdapter = typename Storage::CopyValueAdapter;
+ using DefaultValueAdapter = typename Storage::DefaultValueAdapter;
- using rvalue_reference = typename A::value_type&&;
+ template <typename Iterator>
+ using EnableIfAtLeastForwardIterator = absl::enable_if_t<
+ inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
+ template <typename Iterator>
+ using DisableIfAtLeastForwardIterator = absl::enable_if_t<
+ !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
public:
- using allocator_type = A;
- using value_type = typename allocator_type::value_type;
- using pointer = typename allocator_type::pointer;
- using const_pointer = typename allocator_type::const_pointer;
- using reference = typename allocator_type::reference;
- using const_reference = typename allocator_type::const_reference;
- using size_type = typename allocator_type::size_type;
- using difference_type = typename allocator_type::difference_type;
- using iterator = pointer;
- using const_iterator = const_pointer;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using allocator_type = typename Storage::allocator_type;
+ using value_type = typename Storage::value_type;
+ using pointer = typename Storage::pointer;
+ using const_pointer = typename Storage::const_pointer;
+ using size_type = typename Storage::size_type;
+ using difference_type = typename Storage::difference_type;
+ using reference = typename Storage::reference;
+ using const_reference = typename Storage::const_reference;
+ using iterator = typename Storage::iterator;
+ using const_iterator = typename Storage::const_iterator;
+ using reverse_iterator = typename Storage::reverse_iterator;
+ using const_reverse_iterator = typename Storage::const_reverse_iterator;
// ---------------------------------------------------------------------------
// InlinedVector Constructors and Destructor
// ---------------------------------------------------------------------------
- // Creates an empty inlined vector with a default initialized allocator.
- InlinedVector() noexcept(noexcept(allocator_type()))
- : allocator_and_tag_(allocator_type()) {}
+ // Creates an empty inlined vector with a value-initialized allocator.
+ InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}
- // Creates an empty inlined vector with a specified allocator.
+ // Creates an empty inlined vector with a copy of `alloc`.
explicit InlinedVector(const allocator_type& alloc) noexcept
- : allocator_and_tag_(alloc) {}
+ : storage_(alloc) {}
// Creates an inlined vector with `n` copies of `value_type()`.
explicit InlinedVector(size_type n,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
- InitAssign(n);
+ : storage_(alloc) {
+ storage_.Initialize(DefaultValueAdapter(), n);
}
// Creates an inlined vector with `n` copies of `v`.
InlinedVector(size_type n, const_reference v,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
- InitAssign(n, v);
+ : storage_(alloc) {
+ storage_.Initialize(CopyValueAdapter(v), n);
}
- // Creates an inlined vector of copies of the values in `init_list`.
- InlinedVector(std::initializer_list<value_type> init_list,
+ // Creates an inlined vector with copies of the elements of `list`.
+ InlinedVector(std::initializer_list<value_type> list,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
- AppendRange(init_list.begin(), init_list.end(),
- IteratorCategory<decltype(init_list.begin())>{});
- }
+ : InlinedVector(list.begin(), list.end(), alloc) {}
// Creates an inlined vector with elements constructed from the provided
- // Iterator range [`first`, `last`).
+ // forward iterator range [`first`, `last`).
//
- // NOTE: The `enable_if` prevents ambiguous interpretation between a call to
+ // NOTE: the `enable_if` prevents ambiguous interpretation between a call to
// this constructor with two integral arguments and a call to the above
// `InlinedVector(size_type, const_reference)` constructor.
- template <typename InputIterator, DisableIfIntegral<InputIterator>* = nullptr>
+ template <typename ForwardIterator,
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+ InlinedVector(ForwardIterator first, ForwardIterator last,
+ const allocator_type& alloc = allocator_type())
+ : storage_(alloc) {
+ storage_.Initialize(IteratorValueAdapter<ForwardIterator>(first),
+ std::distance(first, last));
+ }
+
+ // Creates an inlined vector with elements constructed from the provided input
+ // iterator range [`first`, `last`).
+ template <typename InputIterator,
+ DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
InlinedVector(InputIterator first, InputIterator last,
const allocator_type& alloc = allocator_type())
- : allocator_and_tag_(alloc) {
- AppendRange(first, last, IteratorCategory<InputIterator>{});
+ : storage_(alloc) {
+ std::copy(first, last, std::back_inserter(*this));
}
- // Creates a copy of `other` using `other`'s allocator.
+ // Creates an inlined vector by copying the contents of `other` using
+ // `other`'s allocator.
InlinedVector(const InlinedVector& other)
- : InlinedVector(other, other.get_allocator()) {}
+ : InlinedVector(other, *other.storage_.GetAllocPtr()) {}
- // Creates a copy of `other` but with a specified allocator.
+ // Creates an inlined vector by copying the contents of `other` using `alloc`.
InlinedVector(const InlinedVector& other, const allocator_type& alloc)
- : allocator_and_tag_(alloc) {
- reserve(other.size());
- if (allocated()) {
- UninitializedCopy(other.begin(), other.end(), allocated_space());
- tag().set_allocated_size(other.size());
+ : storage_(alloc) {
+ if (other.empty()) {
+ // Empty; nothing to do.
+ } else if (IsMemcpyOk::value && !other.storage_.GetIsAllocated()) {
+ // Memcpy-able and do not need allocation.
+ storage_.MemcpyFrom(other.storage_);
} else {
- UninitializedCopy(other.begin(), other.end(), inlined_space());
- tag().set_inline_size(other.size());
+ storage_.InitFrom(other.storage_);
}
}
- // Creates an inlined vector by moving in the contents of `other`.
+ // Creates an inlined vector by moving in the contents of `other` without
+ // allocating. If `other` contains allocated memory, the newly-created inlined
+ // vector will take ownership of that memory. However, if `other` does not
+ // contain allocated memory, the newly-created inlined vector will perform
+ // element-wise move construction of the contents of `other`.
//
- // NOTE: This move constructor does not allocate and only moves the underlying
- // objects, so its `noexcept` specification depends on whether moving the
- // underlying objects can throw or not. We assume:
- // a) move constructors should only throw due to allocation failure and
+ // NOTE: since no allocation is performed for the inlined vector in either
+ // case, the `noexcept(...)` specification depends on whether moving the
+ // underlying objects can throw. It is assumed assumed that...
+ // a) move constructors should only throw due to allocation failure.
// b) if `value_type`'s move constructor allocates, it uses the same
- // allocation function as the `InlinedVector`'s allocator, so the move
- // constructor is non-throwing if the allocator is non-throwing or
- // `value_type`'s move constructor is specified as `noexcept`.
+ // allocation function as the inlined vector's allocator.
+ // Thus, the move constructor is non-throwing if the allocator is non-throwing
+ // or `value_type`'s move constructor is specified as `noexcept`.
InlinedVector(InlinedVector&& other) noexcept(
absl::allocator_is_nothrow<allocator_type>::value ||
std::is_nothrow_move_constructible<value_type>::value)
- : allocator_and_tag_(other.allocator_and_tag_) {
- if (other.allocated()) {
- // We can just steal the underlying buffer from the source.
- // That leaves the source empty, so we clear its size.
- init_allocation(other.allocation());
- other.tag() = Tag();
+ : storage_(*other.storage_.GetAllocPtr()) {
+ if (IsMemcpyOk::value) {
+ storage_.MemcpyFrom(other.storage_);
+
+ other.storage_.SetInlinedSize(0);
+ } else if (other.storage_.GetIsAllocated()) {
+ storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
+ other.storage_.GetAllocatedCapacity());
+ storage_.SetAllocatedSize(other.storage_.GetSize());
+
+ other.storage_.SetInlinedSize(0);
} else {
- UninitializedCopy(
- std::make_move_iterator(other.inlined_space()),
- std::make_move_iterator(other.inlined_space() + other.size()),
- inlined_space());
+ IteratorValueAdapter<MoveIterator> other_values(
+ MoveIterator(other.storage_.GetInlinedData()));
+
+ inlined_vector_internal::ConstructElements(
+ storage_.GetAllocPtr(), storage_.GetInlinedData(), &other_values,
+ other.storage_.GetSize());
+
+ storage_.SetInlinedSize(other.storage_.GetSize());
}
}
- // Creates an inlined vector by moving in the contents of `other`.
+ // Creates an inlined vector by moving in the contents of `other` with a copy
+ // of `alloc`.
//
- // NOTE: This move constructor allocates and subsequently moves the underlying
- // objects, so its `noexcept` specification depends on whether the allocation
- // can throw and whether moving the underlying objects can throw. Based on the
- // same assumptions as above, the `noexcept` specification is dominated by
- // whether the allocation can throw regardless of whether `value_type`'s move
- // constructor is specified as `noexcept`.
+ // NOTE: if `other`'s allocator is not equal to `alloc`, even if `other`
+ // contains allocated memory, this move constructor will still allocate. Since
+ // allocation is performed, this constructor can only be `noexcept` if the
+ // specified allocator is also `noexcept`.
InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
absl::allocator_is_nothrow<allocator_type>::value)
- : allocator_and_tag_(alloc) {
- if (other.allocated()) {
- if (alloc == other.allocator()) {
- // We can just steal the allocation from the source.
- tag() = other.tag();
- init_allocation(other.allocation());
- other.tag() = Tag();
- } else {
- // We need to use our own allocator
- reserve(other.size());
- UninitializedCopy(std::make_move_iterator(other.begin()),
- std::make_move_iterator(other.end()),
- allocated_space());
- tag().set_allocated_size(other.size());
- }
+ : storage_(alloc) {
+ if (IsMemcpyOk::value) {
+ storage_.MemcpyFrom(other.storage_);
+
+ other.storage_.SetInlinedSize(0);
+ } else if ((*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) &&
+ other.storage_.GetIsAllocated()) {
+ storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
+ other.storage_.GetAllocatedCapacity());
+ storage_.SetAllocatedSize(other.storage_.GetSize());
+
+ other.storage_.SetInlinedSize(0);
} else {
- UninitializedCopy(
- std::make_move_iterator(other.inlined_space()),
- std::make_move_iterator(other.inlined_space() + other.size()),
- inlined_space());
- tag().set_inline_size(other.size());
+ storage_.Initialize(
+ IteratorValueAdapter<MoveIterator>(MoveIterator(other.data())),
+ other.size());
}
}
- ~InlinedVector() { clear(); }
+ ~InlinedVector() {}
// ---------------------------------------------------------------------------
// InlinedVector Member Accessors
@@ -233,72 +253,80 @@ class InlinedVector {
// `InlinedVector::empty()`
//
- // Checks if the inlined vector has no elements.
+ // Returns whether the inlined vector contains no elements.
bool empty() const noexcept { return !size(); }
// `InlinedVector::size()`
//
// Returns the number of elements in the inlined vector.
- size_type size() const noexcept { return tag().size(); }
+ size_type size() const noexcept { return storage_.GetSize(); }
// `InlinedVector::max_size()`
//
- // Returns the maximum number of elements the vector can hold.
+ // Returns the maximum number of elements the inlined vector can hold.
size_type max_size() const noexcept {
// One bit of the size storage is used to indicate whether the inlined
- // vector is allocated. As a result, the maximum size of the container that
- // we can express is half of the max for `size_type`.
+ // vector contains allocated memory. As a result, the maximum size that the
+ // inlined vector can express is half of the max for `size_type`.
return (std::numeric_limits<size_type>::max)() / 2;
}
// `InlinedVector::capacity()`
//
- // Returns the number of elements that can be stored in the inlined vector
- // without requiring a reallocation of underlying memory.
+ // Returns the number of elements that could be stored in the inlined vector
+ // without requiring a reallocation.
//
- // NOTE: For most inlined vectors, `capacity()` should equal
- // `inlined_capacity()`. For inlined vectors which exceed this capacity, they
- // will no longer be inlined and `capacity()` will equal its capacity on the
- // allocated heap.
+ // NOTE: for most inlined vectors, `capacity()` should be equal to the
+ // template parameter `N`. For inlined vectors which exceed this capacity,
+ // they will no longer be inlined and `capacity()` will equal the capactity of
+ // the allocated memory.
size_type capacity() const noexcept {
- return allocated() ? allocation().capacity() : inlined_capacity();
+ return storage_.GetIsAllocated() ? storage_.GetAllocatedCapacity()
+ : storage_.GetInlinedCapacity();
}
// `InlinedVector::data()`
//
- // Returns a `pointer` to elements of the inlined vector. This pointer can be
- // used to access and modify the contained elements.
- // Only results within the range [`0`, `size()`) are defined.
+ // Returns a `pointer` to the elements of the inlined vector. This pointer
+ // can be used to access and modify the contained elements.
+ //
+ // NOTE: only elements within [`data()`, `data() + size()`) are valid.
pointer data() noexcept {
- return allocated() ? allocated_space() : inlined_space();
+ return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
+ : storage_.GetInlinedData();
}
- // Overload of `InlinedVector::data()` to return a `const_pointer` to elements
- // of the inlined vector. This pointer can be used to access (but not modify)
- // the contained elements.
+ // Overload of `InlinedVector::data()` that returns a `const_pointer` to the
+ // elements of the inlined vector. This pointer can be used to access but not
+ // modify the contained elements.
+ //
+ // NOTE: only elements within [`data()`, `data() + size()`) are valid.
const_pointer data() const noexcept {
- return allocated() ? allocated_space() : inlined_space();
+ return storage_.GetIsAllocated() ? storage_.GetAllocatedData()
+ : storage_.GetInlinedData();
}
- // `InlinedVector::operator[]()`
+ // `InlinedVector::operator[](...)`
//
- // Returns a `reference` to the `i`th element of the inlined vector using the
- // array operator.
+ // Returns a `reference` to the `i`th element of the inlined vector.
reference operator[](size_type i) {
- assert(i < size());
+ ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
- // Overload of `InlinedVector::operator[]()` to return a `const_reference` to
- // the `i`th element of the inlined vector.
+ // Overload of `InlinedVector::operator[](...)` that returns a
+ // `const_reference` to the `i`th element of the inlined vector.
const_reference operator[](size_type i) const {
- assert(i < size());
+ ABSL_HARDENING_ASSERT(i < size());
return data()[i];
}
- // `InlinedVector::at()`
+ // `InlinedVector::at(...)`
//
// Returns a `reference` to the `i`th element of the inlined vector.
+ //
+ // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
+ // in both debug and non-debug builds, `std::out_of_range` will be thrown.
reference at(size_type i) {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
@@ -307,8 +335,11 @@ class InlinedVector {
return data()[i];
}
- // Overload of `InlinedVector::at()` to return a `const_reference` to the
- // `i`th element of the inlined vector.
+ // Overload of `InlinedVector::at(...)` that returns a `const_reference` to
+ // the `i`th element of the inlined vector.
+ //
+ // NOTE: if `i` is not within the required range of `InlinedVector::at(...)`,
+ // in both debug and non-debug builds, `std::out_of_range` will be thrown.
const_reference at(size_type i) const {
if (ABSL_PREDICT_FALSE(i >= size())) {
base_internal::ThrowStdOutOfRange(
@@ -321,30 +352,30 @@ class InlinedVector {
//
// Returns a `reference` to the first element of the inlined vector.
reference front() {
- assert(!empty());
- return at(0);
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[0];
}
- // Overload of `InlinedVector::front()` returns a `const_reference` to the
- // first element of the inlined vector.
+ // Overload of `InlinedVector::front()` that returns a `const_reference` to
+ // the first element of the inlined vector.
const_reference front() const {
- assert(!empty());
- return at(0);
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[0];
}
// `InlinedVector::back()`
//
// Returns a `reference` to the last element of the inlined vector.
reference back() {
- assert(!empty());
- return at(size() - 1);
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[size() - 1];
}
- // Overload of `InlinedVector::back()` to return a `const_reference` to the
+ // Overload of `InlinedVector::back()` that returns a `const_reference` to the
// last element of the inlined vector.
const_reference back() const {
- assert(!empty());
- return at(size() - 1);
+ ABSL_HARDENING_ASSERT(!empty());
+ return data()[size() - 1];
}
// `InlinedVector::begin()`
@@ -352,7 +383,7 @@ class InlinedVector {
// Returns an `iterator` to the beginning of the inlined vector.
iterator begin() noexcept { return data(); }
- // Overload of `InlinedVector::begin()` to return a `const_iterator` to
+ // Overload of `InlinedVector::begin()` that returns a `const_iterator` to
// the beginning of the inlined vector.
const_iterator begin() const noexcept { return data(); }
@@ -361,7 +392,7 @@ class InlinedVector {
// Returns an `iterator` to the end of the inlined vector.
iterator end() noexcept { return data() + size(); }
- // Overload of `InlinedVector::end()` to return a `const_iterator` to the
+ // Overload of `InlinedVector::end()` that returns a `const_iterator` to the
// end of the inlined vector.
const_iterator end() const noexcept { return data() + size(); }
@@ -380,7 +411,7 @@ class InlinedVector {
// Returns a `reverse_iterator` from the end of the inlined vector.
reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
- // Overload of `InlinedVector::rbegin()` to return a
+ // Overload of `InlinedVector::rbegin()` that returns a
// `const_reverse_iterator` from the end of the inlined vector.
const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
@@ -391,7 +422,7 @@ class InlinedVector {
// Returns a `reverse_iterator` from the beginning of the inlined vector.
reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
- // Overload of `InlinedVector::rend()` to return a `const_reverse_iterator`
+ // Overload of `InlinedVector::rend()` that returns a `const_reverse_iterator`
// from the beginning of the inlined vector.
const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
@@ -410,943 +441,407 @@ class InlinedVector {
// `InlinedVector::get_allocator()`
//
- // Returns a copy of the allocator of the inlined vector.
- allocator_type get_allocator() const { return allocator(); }
+ // Returns a copy of the inlined vector's allocator.
+ allocator_type get_allocator() const { return *storage_.GetAllocPtr(); }
// ---------------------------------------------------------------------------
// InlinedVector Member Mutators
// ---------------------------------------------------------------------------
- // `InlinedVector::operator=()`
+ // `InlinedVector::operator=(...)`
//
- // Replaces the contents of the inlined vector with copies of the elements in
- // the provided `std::initializer_list`.
- InlinedVector& operator=(std::initializer_list<value_type> init_list) {
- AssignRange(init_list.begin(), init_list.end(),
- IteratorCategory<decltype(init_list.begin())>{});
+ // Replaces the elements of the inlined vector with copies of the elements of
+ // `list`.
+ InlinedVector& operator=(std::initializer_list<value_type> list) {
+ assign(list.begin(), list.end());
+
return *this;
}
- // Overload of `InlinedVector::operator=()` to replace the contents of the
- // inlined vector with the contents of `other`.
+ // Overload of `InlinedVector::operator=(...)` that replaces the elements of
+ // the inlined vector with copies of the elements of `other`.
InlinedVector& operator=(const InlinedVector& other) {
- if (ABSL_PREDICT_FALSE(this == &other)) return *this;
-
- // Optimized to avoid reallocation.
- // Prefer reassignment to copy construction for elements.
- if (size() < other.size()) { // grow
- reserve(other.size());
- std::copy(other.begin(), other.begin() + size(), begin());
- std::copy(other.begin() + size(), other.end(), std::back_inserter(*this));
- } else { // maybe shrink
- erase(begin() + other.size(), end());
- std::copy(other.begin(), other.end(), begin());
+ if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
+ const_pointer other_data = other.data();
+ assign(other_data, other_data + other.size());
}
+
return *this;
}
- // Overload of `InlinedVector::operator=()` to replace the contents of the
- // inlined vector with the contents of `other`.
+ // Overload of `InlinedVector::operator=(...)` that moves the elements of
+ // `other` into the inlined vector.
//
- // NOTE: As a result of calling this overload, `other` may be empty or it's
- // contents may be left in a moved-from state.
+ // NOTE: as a result of calling this overload, `other` is left in a valid but
+ // unspecified state.
InlinedVector& operator=(InlinedVector&& other) {
- if (ABSL_PREDICT_FALSE(this == &other)) return *this;
-
- if (other.allocated()) {
- clear();
- tag().set_allocated_size(other.size());
- init_allocation(other.allocation());
- other.tag() = Tag();
- } else {
- if (allocated()) clear();
- // Both are inlined now.
- if (size() < other.size()) {
- auto mid = std::make_move_iterator(other.begin() + size());
- std::copy(std::make_move_iterator(other.begin()), mid, begin());
- UninitializedCopy(mid, std::make_move_iterator(other.end()), end());
+ if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
+ if (IsMemcpyOk::value || other.storage_.GetIsAllocated()) {
+ inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(),
+ size());
+ storage_.DeallocateIfAllocated();
+ storage_.MemcpyFrom(other.storage_);
+
+ other.storage_.SetInlinedSize(0);
} else {
- auto new_end = std::copy(std::make_move_iterator(other.begin()),
- std::make_move_iterator(other.end()), begin());
- Destroy(new_end, end());
+ storage_.Assign(IteratorValueAdapter<MoveIterator>(
+ MoveIterator(other.storage_.GetInlinedData())),
+ other.size());
}
- tag().set_inline_size(other.size());
}
+
return *this;
}
- // `InlinedVector::assign()`
+ // `InlinedVector::assign(...)`
//
// Replaces the contents of the inlined vector with `n` copies of `v`.
void assign(size_type n, const_reference v) {
- if (n <= size()) { // Possibly shrink
- std::fill_n(begin(), n, v);
- erase(begin() + n, end());
- return;
- }
- // Grow
- reserve(n);
- std::fill_n(begin(), size(), v);
- if (allocated()) {
- UninitializedFill(allocated_space() + size(), allocated_space() + n, v);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space() + size(), inlined_space() + n, v);
- tag().set_inline_size(n);
- }
+ storage_.Assign(CopyValueAdapter(v), n);
}
- // Overload of `InlinedVector::assign()` to replace the contents of the
- // inlined vector with copies of the values in the provided
- // `std::initializer_list`.
- void assign(std::initializer_list<value_type> init_list) {
- AssignRange(init_list.begin(), init_list.end(),
- IteratorCategory<decltype(init_list.begin())>{});
+ // Overload of `InlinedVector::assign(...)` that replaces the contents of the
+ // inlined vector with copies of the elements of `list`.
+ void assign(std::initializer_list<value_type> list) {
+ assign(list.begin(), list.end());
}
- // Overload of `InlinedVector::assign()` to replace the contents of the
- // inlined vector with values constructed from the range [`first`, `last`).
- template <typename InputIterator, DisableIfIntegral<InputIterator>* = nullptr>
- void assign(InputIterator first, InputIterator last) {
- AssignRange(first, last, IteratorCategory<InputIterator>{});
+ // Overload of `InlinedVector::assign(...)` to replace the contents of the
+ // inlined vector with the range [`first`, `last`).
+ //
+ // NOTE: this overload is for iterators that are "forward" category or better.
+ template <typename ForwardIterator,
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+ void assign(ForwardIterator first, ForwardIterator last) {
+ storage_.Assign(IteratorValueAdapter<ForwardIterator>(first),
+ std::distance(first, last));
}
- // `InlinedVector::resize()`
+ // Overload of `InlinedVector::assign(...)` to replace the contents of the
+ // inlined vector with the range [`first`, `last`).
//
- // Resizes the inlined vector to contain `n` elements. If `n` is smaller than
- // the inlined vector's current size, extra elements are destroyed. If `n` is
- // larger than the initial size, new elements are value-initialized.
- void resize(size_type n) {
- size_type s = size();
- if (n < s) {
- erase(begin() + n, end());
- return;
+ // NOTE: this overload is for iterators that are "input" category.
+ template <typename InputIterator,
+ DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+ void assign(InputIterator first, InputIterator last) {
+ size_type i = 0;
+ for (; i < size() && first != last; ++i, static_cast<void>(++first)) {
+ data()[i] = *first;
}
- reserve(n);
- assert(capacity() >= n);
- // Fill new space with elements constructed in-place.
- if (allocated()) {
- UninitializedFill(allocated_space() + s, allocated_space() + n);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space() + s, inlined_space() + n);
- tag().set_inline_size(n);
- }
+ erase(data() + i, data() + size());
+ std::copy(first, last, std::back_inserter(*this));
}
- // Overload of `InlinedVector::resize()` to resize the inlined vector to
- // contain `n` elements where, if `n` is larger than `size()`, the new values
- // will be copy-constructed from `v`.
- void resize(size_type n, const_reference v) {
- size_type s = size();
- if (n < s) {
- erase(begin() + n, end());
- return;
- }
- reserve(n);
- assert(capacity() >= n);
+ // `InlinedVector::resize(...)`
+ //
+ // Resizes the inlined vector to contain `n` elements.
+ //
+ // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
+ // is larger than `size()`, new elements are value-initialized.
+ void resize(size_type n) {
+ ABSL_HARDENING_ASSERT(n <= max_size());
+ storage_.Resize(DefaultValueAdapter(), n);
+ }
- // Fill new space with copies of `v`.
- if (allocated()) {
- UninitializedFill(allocated_space() + s, allocated_space() + n, v);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space() + s, inlined_space() + n, v);
- tag().set_inline_size(n);
- }
+ // Overload of `InlinedVector::resize(...)` that resizes the inlined vector to
+ // contain `n` elements.
+ //
+ // NOTE: if `n` is smaller than `size()`, extra elements are destroyed. If `n`
+ // is larger than `size()`, new elements are copied-constructed from `v`.
+ void resize(size_type n, const_reference v) {
+ ABSL_HARDENING_ASSERT(n <= max_size());
+ storage_.Resize(CopyValueAdapter(v), n);
}
- // `InlinedVector::insert()`
+ // `InlinedVector::insert(...)`
//
- // Copies `v` into `position`, returning an `iterator` pointing to the newly
+ // Inserts a copy of `v` at `pos`, returning an `iterator` to the newly
// inserted element.
- iterator insert(const_iterator position, const_reference v) {
- return emplace(position, v);
+ iterator insert(const_iterator pos, const_reference v) {
+ return emplace(pos, v);
}
- // Overload of `InlinedVector::insert()` for moving `v` into `position`,
- // returning an iterator pointing to the newly inserted element.
- iterator insert(const_iterator position, rvalue_reference v) {
- return emplace(position, std::move(v));
+ // Overload of `InlinedVector::insert(...)` that inserts `v` at `pos` using
+ // move semantics, returning an `iterator` to the newly inserted element.
+ iterator insert(const_iterator pos, RValueReference v) {
+ return emplace(pos, std::move(v));
}
- // Overload of `InlinedVector::insert()` for inserting `n` contiguous copies
- // of `v` starting at `position`. Returns an `iterator` pointing to the first
- // of the newly inserted elements.
- iterator insert(const_iterator position, size_type n, const_reference v) {
- return InsertWithCount(position, n, v);
+ // Overload of `InlinedVector::insert(...)` that inserts `n` contiguous copies
+ // of `v` starting at `pos`, returning an `iterator` pointing to the first of
+ // the newly inserted elements.
+ iterator insert(const_iterator pos, size_type n, const_reference v) {
+ ABSL_HARDENING_ASSERT(pos >= begin());
+ ABSL_HARDENING_ASSERT(pos <= end());
+
+ if (ABSL_PREDICT_TRUE(n != 0)) {
+ value_type dealias = v;
+ return storage_.Insert(pos, CopyValueAdapter(dealias), n);
+ } else {
+ return const_cast<iterator>(pos);
+ }
}
- // Overload of `InlinedVector::insert()` for copying the contents of the
- // `std::initializer_list` into the vector starting at `position`. Returns an
- // `iterator` pointing to the first of the newly inserted elements.
- iterator insert(const_iterator position,
- std::initializer_list<value_type> init_list) {
- return insert(position, init_list.begin(), init_list.end());
+ // Overload of `InlinedVector::insert(...)` that inserts copies of the
+ // elements of `list` starting at `pos`, returning an `iterator` pointing to
+ // the first of the newly inserted elements.
+ iterator insert(const_iterator pos, std::initializer_list<value_type> list) {
+ return insert(pos, list.begin(), list.end());
}
- // Overload of `InlinedVector::insert()` for inserting elements constructed
- // from the range [`first`, `last`). Returns an `iterator` pointing to the
- // first of the newly inserted elements.
+ // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
+ // `last`) starting at `pos`, returning an `iterator` pointing to the first
+ // of the newly inserted elements.
//
- // NOTE: The `enable_if` is intended to disambiguate the two three-argument
- // overloads of `insert()`.
- template <typename InputIterator,
- typename = EnableIfInputIterator<InputIterator>>
- iterator insert(const_iterator position, InputIterator first,
- InputIterator last) {
- return InsertWithRange(position, first, last,
- IteratorCategory<InputIterator>());
+ // NOTE: this overload is for iterators that are "forward" category or better.
+ template <typename ForwardIterator,
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
+ iterator insert(const_iterator pos, ForwardIterator first,
+ ForwardIterator last) {
+ ABSL_HARDENING_ASSERT(pos >= begin());
+ ABSL_HARDENING_ASSERT(pos <= end());
+
+ if (ABSL_PREDICT_TRUE(first != last)) {
+ return storage_.Insert(pos, IteratorValueAdapter<ForwardIterator>(first),
+ std::distance(first, last));
+ } else {
+ return const_cast<iterator>(pos);
+ }
}
- // `InlinedVector::emplace()`
+ // Overload of `InlinedVector::insert(...)` that inserts the range [`first`,
+ // `last`) starting at `pos`, returning an `iterator` pointing to the first
+ // of the newly inserted elements.
//
- // Constructs and inserts an object in the inlined vector at the given
- // `position`, returning an `iterator` pointing to the newly emplaced element.
- template <typename... Args>
- iterator emplace(const_iterator position, Args&&... args) {
- assert(position >= begin());
- assert(position <= end());
- if (ABSL_PREDICT_FALSE(position == end())) {
- emplace_back(std::forward<Args>(args)...);
- return end() - 1;
+ // NOTE: this overload is for iterators that are "input" category.
+ template <typename InputIterator,
+ DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
+ iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
+ ABSL_HARDENING_ASSERT(pos >= begin());
+ ABSL_HARDENING_ASSERT(pos <= end());
+
+ size_type index = std::distance(cbegin(), pos);
+ for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
+ insert(data() + i, *first);
}
- T new_t = T(std::forward<Args>(args)...);
+ return iterator(data() + index);
+ }
- auto range = ShiftRight(position, 1);
- if (range.first == range.second) {
- // constructing into uninitialized memory
- Construct(range.first, std::move(new_t));
- } else {
- // assigning into moved-from object
- *range.first = T(std::move(new_t));
- }
+ // `InlinedVector::emplace(...)`
+ //
+ // Constructs and inserts an element using `args...` in the inlined vector at
+ // `pos`, returning an `iterator` pointing to the newly emplaced element.
+ template <typename... Args>
+ iterator emplace(const_iterator pos, Args&&... args) {
+ ABSL_HARDENING_ASSERT(pos >= begin());
+ ABSL_HARDENING_ASSERT(pos <= end());
- return range.first;
+ value_type dealias(std::forward<Args>(args)...);
+ return storage_.Insert(pos,
+ IteratorValueAdapter<MoveIterator>(
+ MoveIterator(std::addressof(dealias))),
+ 1);
}
- // `InlinedVector::emplace_back()`
+ // `InlinedVector::emplace_back(...)`
//
- // Constructs and appends a new element to the end of the inlined vector,
- // returning a `reference` to the emplaced element.
+ // Constructs and inserts an element using `args...` in the inlined vector at
+ // `end()`, returning a `reference` to the newly emplaced element.
template <typename... Args>
reference emplace_back(Args&&... args) {
- size_type s = size();
- assert(s <= capacity());
- if (ABSL_PREDICT_FALSE(s == capacity())) {
- return GrowAndEmplaceBack(std::forward<Args>(args)...);
- }
- assert(s < capacity());
-
- pointer space;
- if (allocated()) {
- tag().set_allocated_size(s + 1);
- space = allocated_space();
- } else {
- tag().set_inline_size(s + 1);
- space = inlined_space();
- }
- return Construct(space + s, std::forward<Args>(args)...);
+ return storage_.EmplaceBack(std::forward<Args>(args)...);
}
- // `InlinedVector::push_back()`
+ // `InlinedVector::push_back(...)`
//
- // Appends a copy of `v` to the end of the inlined vector.
+ // Inserts a copy of `v` in the inlined vector at `end()`.
void push_back(const_reference v) { static_cast<void>(emplace_back(v)); }
- // Overload of `InlinedVector::push_back()` for moving `v` into a newly
- // appended element.
- void push_back(rvalue_reference v) {
+ // Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`
+ // using move semantics.
+ void push_back(RValueReference v) {
static_cast<void>(emplace_back(std::move(v)));
}
// `InlinedVector::pop_back()`
//
- // Destroys the element at the end of the inlined vector and shrinks the size
- // by `1` (unless the inlined vector is empty, in which case this is a no-op).
+ // Destroys the element at `back()`, reducing the size by `1`.
void pop_back() noexcept {
- assert(!empty());
- size_type s = size();
- if (allocated()) {
- Destroy(allocated_space() + s - 1, allocated_space() + s);
- tag().set_allocated_size(s - 1);
- } else {
- Destroy(inlined_space() + s - 1, inlined_space() + s);
- tag().set_inline_size(s - 1);
- }
+ ABSL_HARDENING_ASSERT(!empty());
+
+ AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1));
+ storage_.SubtractSize(1);
}
- // `InlinedVector::erase()`
+ // `InlinedVector::erase(...)`
//
- // Erases the element at `position` of the inlined vector, returning an
- // `iterator` pointing to the first element following the erased element.
+ // Erases the element at `pos`, returning an `iterator` pointing to where the
+ // erased element was located.
//
- // NOTE: May return the end iterator, which is not dereferencable.
- iterator erase(const_iterator position) {
- assert(position >= begin());
- assert(position < end());
-
- iterator pos = const_cast<iterator>(position);
- std::move(pos + 1, end(), pos);
- pop_back();
- return pos;
+ // NOTE: may return `end()`, which is not dereferencable.
+ iterator erase(const_iterator pos) {
+ ABSL_HARDENING_ASSERT(pos >= begin());
+ ABSL_HARDENING_ASSERT(pos < end());
+
+ return storage_.Erase(pos, pos + 1);
}
- // Overload of `InlinedVector::erase()` for erasing all elements in the
- // range [`from`, `to`) in the inlined vector. Returns an `iterator` pointing
- // to the first element following the range erased or the end iterator if `to`
- // was the end iterator.
+ // Overload of `InlinedVector::erase(...)` that erases every element in the
+ // range [`from`, `to`), returning an `iterator` pointing to where the first
+ // erased element was located.
+ //
+ // NOTE: may return `end()`, which is not dereferencable.
iterator erase(const_iterator from, const_iterator to) {
- assert(begin() <= from);
- assert(from <= to);
- assert(to <= end());
-
- iterator range_start = const_cast<iterator>(from);
- iterator range_end = const_cast<iterator>(to);
-
- size_type s = size();
- ptrdiff_t erase_gap = std::distance(range_start, range_end);
- if (erase_gap > 0) {
- pointer space;
- if (allocated()) {
- space = allocated_space();
- tag().set_allocated_size(s - erase_gap);
- } else {
- space = inlined_space();
- tag().set_inline_size(s - erase_gap);
- }
- std::move(range_end, space + s, range_start);
- Destroy(space + s - erase_gap, space + s);
+ ABSL_HARDENING_ASSERT(from >= begin());
+ ABSL_HARDENING_ASSERT(from <= to);
+ ABSL_HARDENING_ASSERT(to <= end());
+
+ if (ABSL_PREDICT_TRUE(from != to)) {
+ return storage_.Erase(from, to);
+ } else {
+ return const_cast<iterator>(from);
}
- return range_start;
}
// `InlinedVector::clear()`
//
- // Destroys all elements in the inlined vector, sets the size of `0` and
- // deallocates the heap allocation if the inlined vector was allocated.
+ // Destroys all elements in the inlined vector, setting the size to `0` and
+ // deallocating any held memory.
void clear() noexcept {
- size_type s = size();
- if (allocated()) {
- Destroy(allocated_space(), allocated_space() + s);
- allocation().Dealloc(allocator());
- } else if (s != 0) { // do nothing for empty vectors
- Destroy(inlined_space(), inlined_space() + s);
- }
- tag() = Tag();
+ inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(),
+ size());
+ storage_.DeallocateIfAllocated();
+
+ storage_.SetInlinedSize(0);
}
- // `InlinedVector::reserve()`
- //
- // Enlarges the underlying representation of the inlined vector so it can hold
- // at least `n` elements. This method does not change `size()` or the actual
- // contents of the vector.
+ // `InlinedVector::reserve(...)`
//
- // NOTE: If `n` does not exceed `capacity()`, `reserve()` will have no
- // effects. Otherwise, `reserve()` will reallocate, performing an n-time
- // element-wise move of everything contained.
- void reserve(size_type n) {
- if (n > capacity()) {
- // Make room for new elements
- EnlargeBy(n - size());
- }
- }
+ // Ensures that there is enough room for at least `n` elements.
+ void reserve(size_type n) { storage_.Reserve(n); }
// `InlinedVector::shrink_to_fit()`
//
- // Reduces memory usage by freeing unused memory. After this call, calls to
- // `capacity()` will be equal to `(std::max)(inlined_capacity(), size())`.
+ // Reduces memory usage by freeing unused memory. After being called, calls to
+ // `capacity()` will be equal to `max(N, size())`.
//
- // If `size() <= inlined_capacity()` and the elements are currently stored on
- // the heap, they will be moved to the inlined storage and the heap memory
+ // If `size() <= N` and the inlined vector contains allocated memory, the
+ // elements will all be moved to the inlined space and the allocated memory
// will be deallocated.
//
- // If `size() > inlined_capacity()` and `size() < capacity()` the elements
- // will be moved to a smaller heap allocation.
+ // If `size() > N` and `size() < capacity()`, the elements will be moved to a
+ // smaller allocation.
void shrink_to_fit() {
- const auto s = size();
- if (ABSL_PREDICT_FALSE(!allocated() || s == capacity())) return;
-
- if (s <= inlined_capacity()) {
- // Move the elements to the inlined storage.
- // We have to do this using a temporary, because `inlined_storage` and
- // `allocation_storage` are in a union field.
- auto temp = std::move(*this);
- assign(std::make_move_iterator(temp.begin()),
- std::make_move_iterator(temp.end()));
- return;
+ if (storage_.GetIsAllocated()) {
+ storage_.ShrinkToFit();
}
-
- // Reallocate storage and move elements.
- // We can't simply use the same approach as above, because `assign()` would
- // call into `reserve()` internally and reserve larger capacity than we need
- Allocation new_allocation(allocator(), s);
- UninitializedCopy(std::make_move_iterator(allocated_space()),
- std::make_move_iterator(allocated_space() + s),
- new_allocation.buffer());
- ResetAllocation(new_allocation, s);
}
- // `InlinedVector::swap()`
+ // `InlinedVector::swap(...)`
//
- // Swaps the contents of this inlined vector with the contents of `other`.
+ // Swaps the contents of the inlined vector with `other`.
void swap(InlinedVector& other) {
- if (ABSL_PREDICT_FALSE(this == &other)) return;
-
- using std::swap; // Augment ADL with `std::swap`.
- if (allocated() && other.allocated()) {
- // Both out of line, so just swap the tag, allocation, and allocator.
- swap(tag(), other.tag());
- swap(allocation(), other.allocation());
- swap(allocator(), other.allocator());
- return;
- }
- if (!allocated() && !other.allocated()) {
- // Both inlined: swap up to smaller size, then move remaining elements.
- InlinedVector* a = this;
- InlinedVector* b = &other;
- if (size() < other.size()) {
- swap(a, b);
- }
-
- const size_type a_size = a->size();
- const size_type b_size = b->size();
- assert(a_size >= b_size);
- // `a` is larger. Swap the elements up to the smaller array size.
- std::swap_ranges(a->inlined_space(), a->inlined_space() + b_size,
- b->inlined_space());
-
- // Move the remaining elements:
- // [`b_size`, `a_size`) from `a` -> [`b_size`, `a_size`) from `b`
- b->UninitializedCopy(a->inlined_space() + b_size,
- a->inlined_space() + a_size,
- b->inlined_space() + b_size);
- a->Destroy(a->inlined_space() + b_size, a->inlined_space() + a_size);
-
- swap(a->tag(), b->tag());
- swap(a->allocator(), b->allocator());
- assert(b->size() == a_size);
- assert(a->size() == b_size);
- return;
+ if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
+ storage_.Swap(std::addressof(other.storage_));
}
-
- // One is out of line, one is inline.
- // We first move the elements from the inlined vector into the
- // inlined space in the other vector. We then put the other vector's
- // pointer/capacity into the originally inlined vector and swap
- // the tags.
- InlinedVector* a = this;
- InlinedVector* b = &other;
- if (a->allocated()) {
- swap(a, b);
- }
- assert(!a->allocated());
- assert(b->allocated());
- const size_type a_size = a->size();
- const size_type b_size = b->size();
- // In an optimized build, `b_size` would be unused.
- static_cast<void>(b_size);
-
- // Made Local copies of `size()`, don't need `tag()` accurate anymore
- swap(a->tag(), b->tag());
-
- // Copy `b_allocation` out before `b`'s union gets clobbered by
- // `inline_space`
- Allocation b_allocation = b->allocation();
-
- b->UninitializedCopy(a->inlined_space(), a->inlined_space() + a_size,
- b->inlined_space());
- a->Destroy(a->inlined_space(), a->inlined_space() + a_size);
-
- a->allocation() = b_allocation;
-
- if (a->allocator() != b->allocator()) {
- swap(a->allocator(), b->allocator());
- }
-
- assert(b->size() == a_size);
- assert(a->size() == b_size);
}
private:
- template <typename Hash, typename OtherT, size_t OtherN, typename OtherA>
- friend Hash AbslHashValue(Hash, const InlinedVector<OtherT, OtherN, OtherA>&);
-
- // Holds whether the vector is allocated or not in the lowest bit and the size
- // in the high bits:
- // `size_ = (size << 1) | is_allocated;`
- class Tag {
- public:
- Tag() : size_(0) {}
- size_type size() const { return size_ / 2; }
- void add_size(size_type n) { size_ += n * 2; }
- void set_inline_size(size_type n) { size_ = n * 2; }
- void set_allocated_size(size_type n) { size_ = (n * 2) + 1; }
- bool allocated() const { return size_ % 2; }
-
- private:
- size_type size_;
- };
-
- // Derives from `allocator_type` to use the empty base class optimization.
- // If the `allocator_type` is stateless, we can store our instance for free.
- class AllocatorAndTag : private allocator_type {
- public:
- explicit AllocatorAndTag(const allocator_type& a) : allocator_type(a) {}
-
- Tag& tag() { return tag_; }
- const Tag& tag() const { return tag_; }
-
- allocator_type& allocator() { return *this; }
- const allocator_type& allocator() const { return *this; }
-
- private:
- Tag tag_;
- };
-
- class Allocation {
- public:
- Allocation(allocator_type& a, size_type capacity)
- : capacity_(capacity), buffer_(Create(a, capacity)) {}
-
- void Dealloc(allocator_type& a) {
- std::allocator_traits<allocator_type>::deallocate(a, buffer_, capacity_);
- }
-
- size_type capacity() const { return capacity_; }
-
- const_pointer buffer() const { return buffer_; }
+ template <typename H, typename TheT, size_t TheN, typename TheA>
+ friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
- pointer buffer() { return buffer_; }
-
- private:
- static pointer Create(allocator_type& a, size_type n) {
- return std::allocator_traits<allocator_type>::allocate(a, n);
- }
-
- size_type capacity_;
- pointer buffer_;
- };
-
- const Tag& tag() const { return allocator_and_tag_.tag(); }
-
- Tag& tag() { return allocator_and_tag_.tag(); }
-
- Allocation& allocation() {
- return reinterpret_cast<Allocation&>(rep_.allocation_storage.allocation);
- }
-
- const Allocation& allocation() const {
- return reinterpret_cast<const Allocation&>(
- rep_.allocation_storage.allocation);
- }
-
- void init_allocation(const Allocation& allocation) {
- new (&rep_.allocation_storage.allocation) Allocation(allocation);
- }
-
- // TODO(absl-team): investigate whether the reinterpret_cast is appropriate.
- pointer inlined_space() {
- return reinterpret_cast<pointer>(
- std::addressof(rep_.inlined_storage.inlined[0]));
- }
-
- const_pointer inlined_space() const {
- return reinterpret_cast<const_pointer>(
- std::addressof(rep_.inlined_storage.inlined[0]));
- }
-
- pointer allocated_space() { return allocation().buffer(); }
-
- const_pointer allocated_space() const { return allocation().buffer(); }
-
- const allocator_type& allocator() const {
- return allocator_and_tag_.allocator();
- }
-
- allocator_type& allocator() { return allocator_and_tag_.allocator(); }
-
- bool allocated() const { return tag().allocated(); }
-
- void ResetAllocation(Allocation new_allocation, size_type new_size) {
- if (allocated()) {
- Destroy(allocated_space(), allocated_space() + size());
- assert(begin() == allocated_space());
- allocation().Dealloc(allocator());
- allocation() = new_allocation;
- } else {
- Destroy(inlined_space(), inlined_space() + size());
- init_allocation(new_allocation); // bug: only init once
- }
- tag().set_allocated_size(new_size);
- }
-
- template <typename... Args>
- reference Construct(pointer p, Args&&... args) {
- std::allocator_traits<allocator_type>::construct(
- allocator(), p, std::forward<Args>(args)...);
- return *p;
- }
-
- template <typename Iterator>
- void UninitializedCopy(Iterator src, Iterator src_last, pointer dst) {
- for (; src != src_last; ++dst, ++src) Construct(dst, *src);
- }
-
- template <typename... Args>
- void UninitializedFill(pointer dst, pointer dst_last, const Args&... args) {
- for (; dst != dst_last; ++dst) Construct(dst, args...);
- }
-
- // Destroy [`from`, `to`) in place.
- void Destroy(pointer from, pointer to) {
- for (pointer cur = from; cur != to; ++cur) {
- std::allocator_traits<allocator_type>::destroy(allocator(), cur);
- }
-#if !defined(NDEBUG)
- // Overwrite unused memory with `0xab` so we can catch uninitialized usage.
- // Cast to `void*` to tell the compiler that we don't care that we might be
- // scribbling on a vtable pointer.
- if (from != to) {
- auto len = sizeof(value_type) * std::distance(from, to);
- std::memset(reinterpret_cast<void*>(from), 0xab, len);
- }
-#endif // !defined(NDEBUG)
- }
-
- // Enlarge the underlying representation so we can store `size_ + delta` elems
- // in allocated space. The size is not changed, and any newly added memory is
- // not initialized.
- void EnlargeBy(size_type delta) {
- const size_type s = size();
- assert(s <= capacity());
-
- size_type target = (std::max)(inlined_capacity(), s + delta);
-
- // Compute new capacity by repeatedly doubling current capacity
- // TODO(psrc): Check and avoid overflow?
- size_type new_capacity = capacity();
- while (new_capacity < target) {
- new_capacity <<= 1;
- }
-
- Allocation new_allocation(allocator(), new_capacity);
-
- UninitializedCopy(std::make_move_iterator(data()),
- std::make_move_iterator(data() + s),
- new_allocation.buffer());
-
- ResetAllocation(new_allocation, s);
- }
-
- // Shift all elements from `position` to `end()` by `n` places to the right.
- // If the vector needs to be enlarged, memory will be allocated.
- // Returns `iterator`s pointing to the start of the previously-initialized
- // portion and the start of the uninitialized portion of the created gap.
- // The number of initialized spots is `pair.second - pair.first`. The number
- // of raw spots is `n - (pair.second - pair.first)`.
- //
- // Updates the size of the InlinedVector internally.
- std::pair<iterator, iterator> ShiftRight(const_iterator position,
- size_type n) {
- iterator start_used = const_cast<iterator>(position);
- iterator start_raw = const_cast<iterator>(position);
- size_type s = size();
- size_type required_size = s + n;
-
- if (required_size > capacity()) {
- // Compute new capacity by repeatedly doubling current capacity
- size_type new_capacity = capacity();
- while (new_capacity < required_size) {
- new_capacity <<= 1;
- }
- // Move everyone into the new allocation, leaving a gap of `n` for the
- // requested shift.
- Allocation new_allocation(allocator(), new_capacity);
- size_type index = position - begin();
- UninitializedCopy(std::make_move_iterator(data()),
- std::make_move_iterator(data() + index),
- new_allocation.buffer());
- UninitializedCopy(std::make_move_iterator(data() + index),
- std::make_move_iterator(data() + s),
- new_allocation.buffer() + index + n);
- ResetAllocation(new_allocation, s);
-
- // New allocation means our iterator is invalid, so we'll recalculate.
- // Since the entire gap is in new space, there's no used space to reuse.
- start_raw = begin() + index;
- start_used = start_raw;
- } else {
- // If we had enough space, it's a two-part move. Elements going into
- // previously-unoccupied space need an `UninitializedCopy()`. Elements
- // going into a previously-occupied space are just a `std::move()`.
- iterator pos = const_cast<iterator>(position);
- iterator raw_space = end();
- size_type slots_in_used_space = raw_space - pos;
- size_type new_elements_in_used_space = (std::min)(n, slots_in_used_space);
- size_type new_elements_in_raw_space = n - new_elements_in_used_space;
- size_type old_elements_in_used_space =
- slots_in_used_space - new_elements_in_used_space;
-
- UninitializedCopy(
- std::make_move_iterator(pos + old_elements_in_used_space),
- std::make_move_iterator(raw_space),
- raw_space + new_elements_in_raw_space);
- std::move_backward(pos, pos + old_elements_in_used_space, raw_space);
-
- // If the gap is entirely in raw space, the used space starts where the
- // raw space starts, leaving no elements in used space. If the gap is
- // entirely in used space, the raw space starts at the end of the gap,
- // leaving all elements accounted for within the used space.
- start_used = pos;
- start_raw = pos + new_elements_in_used_space;
- }
- tag().add_size(n);
- return std::make_pair(start_used, start_raw);
- }
-
- template <typename... Args>
- reference GrowAndEmplaceBack(Args&&... args) {
- assert(size() == capacity());
- const size_type s = size();
-
- Allocation new_allocation(allocator(), 2 * capacity());
-
- reference new_element =
- Construct(new_allocation.buffer() + s, std::forward<Args>(args)...);
- UninitializedCopy(std::make_move_iterator(data()),
- std::make_move_iterator(data() + s),
- new_allocation.buffer());
-
- ResetAllocation(new_allocation, s + 1);
-
- return new_element;
- }
-
- void InitAssign(size_type n) {
- if (n > inlined_capacity()) {
- Allocation new_allocation(allocator(), n);
- init_allocation(new_allocation);
- UninitializedFill(allocated_space(), allocated_space() + n);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space(), inlined_space() + n);
- tag().set_inline_size(n);
- }
- }
-
- void InitAssign(size_type n, const_reference v) {
- if (n > inlined_capacity()) {
- Allocation new_allocation(allocator(), n);
- init_allocation(new_allocation);
- UninitializedFill(allocated_space(), allocated_space() + n, v);
- tag().set_allocated_size(n);
- } else {
- UninitializedFill(inlined_space(), inlined_space() + n, v);
- tag().set_inline_size(n);
- }
- }
-
- template <typename Iterator>
- void AssignRange(Iterator first, Iterator last, std::forward_iterator_tag) {
- auto length = std::distance(first, last);
- // Prefer reassignment to copy construction for elements.
- if (static_cast<size_type>(length) <= size()) {
- erase(std::copy(first, last, begin()), end());
- return;
- }
- reserve(length);
- iterator out = begin();
- for (; out != end(); ++first, ++out) *out = *first;
- if (allocated()) {
- UninitializedCopy(first, last, out);
- tag().set_allocated_size(length);
- } else {
- UninitializedCopy(first, last, out);
- tag().set_inline_size(length);
- }
- }
-
- template <typename Iterator>
- void AssignRange(Iterator first, Iterator last, std::input_iterator_tag) {
- // Optimized to avoid reallocation.
- // Prefer reassignment to copy construction for elements.
- iterator out = begin();
- for (; first != last && out != end(); ++first, ++out) {
- *out = *first;
- }
- erase(out, end());
- std::copy(first, last, std::back_inserter(*this));
- }
-
- template <typename Iterator>
- void AppendRange(Iterator first, Iterator last, std::forward_iterator_tag) {
- auto length = std::distance(first, last);
- reserve(size() + length);
- if (allocated()) {
- UninitializedCopy(first, last, allocated_space() + size());
- tag().set_allocated_size(size() + length);
- } else {
- UninitializedCopy(first, last, inlined_space() + size());
- tag().set_inline_size(size() + length);
- }
- }
-
- template <typename Iterator>
- void AppendRange(Iterator first, Iterator last, std::input_iterator_tag) {
- std::copy(first, last, std::back_inserter(*this));
- }
-
- iterator InsertWithCount(const_iterator position, size_type n,
- const_reference v) {
- assert(position >= begin() && position <= end());
- if (ABSL_PREDICT_FALSE(n == 0)) return const_cast<iterator>(position);
-
- value_type copy = v;
- std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
- std::fill(it_pair.first, it_pair.second, copy);
- UninitializedFill(it_pair.second, it_pair.first + n, copy);
-
- return it_pair.first;
- }
-
- template <typename ForwardIterator>
- iterator InsertWithRange(const_iterator position, ForwardIterator first,
- ForwardIterator last, std::forward_iterator_tag) {
- assert(position >= begin() && position <= end());
- if (ABSL_PREDICT_FALSE(first == last))
- return const_cast<iterator>(position);
-
- auto n = std::distance(first, last);
- std::pair<iterator, iterator> it_pair = ShiftRight(position, n);
- size_type used_spots = it_pair.second - it_pair.first;
- ForwardIterator open_spot = std::next(first, used_spots);
- std::copy(first, open_spot, it_pair.first);
- UninitializedCopy(open_spot, last, it_pair.second);
- return it_pair.first;
- }
-
- template <typename InputIterator>
- iterator InsertWithRange(const_iterator position, InputIterator first,
- InputIterator last, std::input_iterator_tag) {
- assert(position >= begin() && position <= end());
- size_type index = position - cbegin();
- size_type i = index;
- while (first != last) insert(begin() + i++, *first++);
- return begin() + index;
- }
-
- // Stores either the inlined or allocated representation
- union Rep {
- using ValueTypeBuffer =
- absl::aligned_storage_t<sizeof(value_type), alignof(value_type)>;
- using AllocationBuffer =
- absl::aligned_storage_t<sizeof(Allocation), alignof(Allocation)>;
-
- // Structs wrap the buffers to perform indirection that solves a bizarre
- // compilation error on Visual Studio (all known versions).
- struct InlinedRep {
- ValueTypeBuffer inlined[N];
- };
- struct AllocatedRep {
- AllocationBuffer allocation;
- };
-
- InlinedRep inlined_storage;
- AllocatedRep allocation_storage;
- };
-
- AllocatorAndTag allocator_and_tag_;
- Rep rep_;
+ Storage storage_;
};
// -----------------------------------------------------------------------------
// InlinedVector Non-Member Functions
// -----------------------------------------------------------------------------
-// `swap()`
+// `swap(...)`
//
-// Swaps the contents of two inlined vectors. This convenience function
-// simply calls `InlinedVector::swap()`.
+// Swaps the contents of two inlined vectors.
template <typename T, size_t N, typename A>
-void swap(InlinedVector<T, N, A>& a,
- InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
+void swap(absl::InlinedVector<T, N, A>& a,
+ absl::InlinedVector<T, N, A>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
-// `operator==()`
+// `operator==(...)`
//
-// Tests the equivalency of the contents of two inlined vectors.
+// Tests for value-equality of two inlined vectors.
template <typename T, size_t N, typename A>
-bool operator==(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
- return absl::equal(a.begin(), a.end(), b.begin(), b.end());
+bool operator==(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
+ auto a_data = a.data();
+ auto b_data = b.data();
+ return absl::equal(a_data, a_data + a.size(), b_data, b_data + b.size());
}
-// `operator!=()`
+// `operator!=(...)`
//
-// Tests the inequality of the contents of two inlined vectors.
+// Tests for value-inequality of two inlined vectors.
template <typename T, size_t N, typename A>
-bool operator!=(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
+bool operator!=(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
return !(a == b);
}
-// `operator<()`
+// `operator<(...)`
//
-// Tests whether the contents of one inlined vector are less than the contents
-// of another through a lexicographical comparison operation.
+// Tests whether the value of an inlined vector is less than the value of
+// another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
-bool operator<(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
- return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+bool operator<(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
+ auto a_data = a.data();
+ auto b_data = b.data();
+ return std::lexicographical_compare(a_data, a_data + a.size(), b_data,
+ b_data + b.size());
}
-// `operator>()`
+// `operator>(...)`
//
-// Tests whether the contents of one inlined vector are greater than the
-// contents of another through a lexicographical comparison operation.
+// Tests whether the value of an inlined vector is greater than the value of
+// another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
-bool operator>(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
+bool operator>(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
return b < a;
}
-// `operator<=()`
+// `operator<=(...)`
//
-// Tests whether the contents of one inlined vector are less than or equal to
-// the contents of another through a lexicographical comparison operation.
+// Tests whether the value of an inlined vector is less than or equal to the
+// value of another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
-bool operator<=(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
+bool operator<=(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
return !(b < a);
}
-// `operator>=()`
+// `operator>=(...)`
//
-// Tests whether the contents of one inlined vector are greater than or equal to
-// the contents of another through a lexicographical comparison operation.
+// Tests whether the value of an inlined vector is greater than or equal to the
+// value of another inlined vector using a lexicographical comparison algorithm.
template <typename T, size_t N, typename A>
-bool operator>=(const InlinedVector<T, N, A>& a,
- const InlinedVector<T, N, A>& b) {
+bool operator>=(const absl::InlinedVector<T, N, A>& a,
+ const absl::InlinedVector<T, N, A>& b) {
return !(a < b);
}
-template <typename Hash, typename T, size_t N, typename A>
-Hash AbslHashValue(Hash hash, const InlinedVector<T, N, A>& inlined_vector) {
- auto p = inlined_vector.data();
- auto n = inlined_vector.size();
- return Hash::combine(Hash::combine_contiguous(std::move(hash), p, n), n);
-}
-
-// -----------------------------------------------------------------------------
-// Implementation of InlinedVector
+// `AbslHashValue(...)`
//
-// Do not depend on any below implementation details!
-// -----------------------------------------------------------------------------
+// Provides `absl::Hash` support for `absl::InlinedVector`. It is uncommon to
+// call this directly.
+template <typename H, typename T, size_t N, typename A>
+H AbslHashValue(H h, const absl::InlinedVector<T, N, A>& a) {
+ auto size = a.size();
+ return H::combine(H::combine_contiguous(std::move(h), a.data(), size), size);
+}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INLINED_VECTOR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_benchmark.cc
index a3ad0f8ae4f..e256fad60fc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_benchmark.cc
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,56 +12,58 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/container/inlined_vector.h"
-
+#include <array>
#include <string>
#include <vector>
#include "benchmark/benchmark.h"
#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/inlined_vector.h"
#include "absl/strings/str_cat.h"
namespace {
-using IntVec = absl::InlinedVector<int, 8>;
-
void BM_InlinedVectorFill(benchmark::State& state) {
const int len = state.range(0);
+ absl::InlinedVector<int, 8> v;
+ v.reserve(len);
for (auto _ : state) {
- IntVec v;
- for (int i = 0; i < len; i++) {
+ v.resize(0); // Use resize(0) as InlinedVector releases storage on clear().
+ for (int i = 0; i < len; ++i) {
v.push_back(i);
}
+ benchmark::DoNotOptimize(v);
}
- state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
}
-BENCHMARK(BM_InlinedVectorFill)->Range(0, 1024);
+BENCHMARK(BM_InlinedVectorFill)->Range(1, 256);
void BM_InlinedVectorFillRange(benchmark::State& state) {
const int len = state.range(0);
- std::unique_ptr<int[]> ia(new int[len]);
- for (int i = 0; i < len; i++) {
- ia[i] = i;
- }
+ const std::vector<int> src(len, len);
+ absl::InlinedVector<int, 8> v;
+ v.reserve(len);
for (auto _ : state) {
- IntVec v(ia.get(), ia.get() + len);
+ benchmark::DoNotOptimize(src);
+ v.assign(src.begin(), src.end());
benchmark::DoNotOptimize(v);
}
- state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
}
-BENCHMARK(BM_InlinedVectorFillRange)->Range(0, 1024);
+BENCHMARK(BM_InlinedVectorFillRange)->Range(1, 256);
void BM_StdVectorFill(benchmark::State& state) {
const int len = state.range(0);
+ std::vector<int> v;
+ v.reserve(len);
for (auto _ : state) {
- std::vector<int> v;
- for (int i = 0; i < len; i++) {
+ v.clear();
+ for (int i = 0; i < len; ++i) {
v.push_back(i);
}
+ benchmark::DoNotOptimize(v);
}
- state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * len);
}
-BENCHMARK(BM_StdVectorFill)->Range(0, 1024);
+BENCHMARK(BM_StdVectorFill)->Range(1, 256);
// The purpose of the next two benchmarks is to verify that
// absl::InlinedVector is efficient when moving is more efficent than
@@ -81,7 +83,7 @@ int GetNonShortStringOptimizationSize() {
}
ABSL_RAW_LOG(
FATAL,
- "Failed to find a std::string larger than the short std::string optimization");
+ "Failed to find a string larger than the short string optimization");
return -1;
}
@@ -89,7 +91,7 @@ void BM_InlinedVectorFillString(benchmark::State& state) {
const int len = state.range(0);
const int no_sso = GetNonShortStringOptimizationSize();
std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
- std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+ std::string(no_sso, 'C'), std::string(no_sso, 'D')};
for (auto _ : state) {
absl::InlinedVector<std::string, 8> v;
@@ -105,7 +107,7 @@ void BM_StdVectorFillString(benchmark::State& state) {
const int len = state.range(0);
const int no_sso = GetNonShortStringOptimizationSize();
std::string strings[4] = {std::string(no_sso, 'A'), std::string(no_sso, 'B'),
- std::string(no_sso, 'C'), std::string(no_sso, 'D')};
+ std::string(no_sso, 'C'), std::string(no_sso, 'D')};
for (auto _ : state) {
std::vector<std::string> v;
@@ -124,7 +126,7 @@ struct Buffer { // some arbitrary structure for benchmarking.
void* user_data;
};
-void BM_InlinedVectorTenAssignments(benchmark::State& state) {
+void BM_InlinedVectorAssignments(benchmark::State& state) {
const int len = state.range(0);
using BufferVec = absl::InlinedVector<Buffer, 2>;
@@ -133,18 +135,25 @@ void BM_InlinedVectorTenAssignments(benchmark::State& state) {
BufferVec dst;
for (auto _ : state) {
- for (int i = 0; i < 10; ++i) {
- dst = src;
- }
+ benchmark::DoNotOptimize(dst);
+ benchmark::DoNotOptimize(src);
+ dst = src;
}
}
-BENCHMARK(BM_InlinedVectorTenAssignments)
- ->Arg(0)->Arg(1)->Arg(2)->Arg(3)->Arg(4)->Arg(20);
+BENCHMARK(BM_InlinedVectorAssignments)
+ ->Arg(0)
+ ->Arg(1)
+ ->Arg(2)
+ ->Arg(3)
+ ->Arg(4)
+ ->Arg(20);
void BM_CreateFromContainer(benchmark::State& state) {
for (auto _ : state) {
- absl::InlinedVector<int, 4> x(absl::InlinedVector<int, 4>{1, 2, 3});
- benchmark::DoNotOptimize(x);
+ absl::InlinedVector<int, 4> src{1, 2, 3};
+ benchmark::DoNotOptimize(src);
+ absl::InlinedVector<int, 4> dst(std::move(src));
+ benchmark::DoNotOptimize(dst);
}
}
BENCHMARK(BM_CreateFromContainer);
@@ -159,15 +168,14 @@ struct LargeCopyableOnly {
struct LargeCopyableSwappable {
LargeCopyableSwappable() : d(1024, 17) {}
+
LargeCopyableSwappable(const LargeCopyableSwappable& o) = default;
- LargeCopyableSwappable(LargeCopyableSwappable&& o) = delete;
LargeCopyableSwappable& operator=(LargeCopyableSwappable o) {
using std::swap;
swap(*this, o);
return *this;
}
- LargeCopyableSwappable& operator=(LargeCopyableSwappable&& o) = delete;
friend void swap(LargeCopyableSwappable& a, LargeCopyableSwappable& b) {
using std::swap;
@@ -215,6 +223,8 @@ void BM_SwapElements(benchmark::State& state) {
Vec b;
for (auto _ : state) {
using std::swap;
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
swap(a, b);
}
}
@@ -260,60 +270,44 @@ BENCHMARK_TEMPLATE(BM_Sizeof, absl::InlinedVector<std::string, 8>);
void BM_InlinedVectorIndexInlined(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
for (auto _ : state) {
- for (int i = 0; i < 1000; ++i) {
- benchmark::DoNotOptimize(v);
- benchmark::DoNotOptimize(v[4]);
- }
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v[4]);
}
- state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorIndexInlined);
void BM_InlinedVectorIndexExternal(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- for (int i = 0; i < 1000; ++i) {
- benchmark::DoNotOptimize(v);
- benchmark::DoNotOptimize(v[4]);
- }
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v[4]);
}
- state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorIndexExternal);
void BM_StdVectorIndex(benchmark::State& state) {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- for (int i = 0; i < 1000; ++i) {
- benchmark::DoNotOptimize(v);
- benchmark::DoNotOptimize(v[4]);
- }
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v[4]);
}
- state.SetItemsProcessed(1000 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_StdVectorIndex);
-#define UNROLL_2(x) \
- benchmark::DoNotOptimize(x); \
- benchmark::DoNotOptimize(x);
-
-#define UNROLL_4(x) UNROLL_2(x) UNROLL_2(x)
-#define UNROLL_8(x) UNROLL_4(x) UNROLL_4(x)
-#define UNROLL_16(x) UNROLL_8(x) UNROLL_8(x);
-
void BM_InlinedVectorDataInlined(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
for (auto _ : state) {
- UNROLL_16(v.data());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.data());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorDataInlined);
void BM_InlinedVectorDataExternal(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.data());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.data());
}
state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
@@ -322,7 +316,8 @@ BENCHMARK(BM_InlinedVectorDataExternal);
void BM_StdVectorData(benchmark::State& state) {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.data());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.data());
}
state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
@@ -331,55 +326,504 @@ BENCHMARK(BM_StdVectorData);
void BM_InlinedVectorSizeInlined(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
for (auto _ : state) {
- UNROLL_16(v.size());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.size());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorSizeInlined);
void BM_InlinedVectorSizeExternal(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.size());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.size());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorSizeExternal);
void BM_StdVectorSize(benchmark::State& state) {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.size());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.size());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_StdVectorSize);
void BM_InlinedVectorEmptyInlined(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7};
for (auto _ : state) {
- UNROLL_16(v.empty());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.empty());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorEmptyInlined);
void BM_InlinedVectorEmptyExternal(benchmark::State& state) {
absl::InlinedVector<int, 8> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.empty());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.empty());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_InlinedVectorEmptyExternal);
void BM_StdVectorEmpty(benchmark::State& state) {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (auto _ : state) {
- UNROLL_16(v.empty());
+ benchmark::DoNotOptimize(v);
+ benchmark::DoNotOptimize(v.empty());
}
- state.SetItemsProcessed(16 * static_cast<int64_t>(state.iterations()));
}
BENCHMARK(BM_StdVectorEmpty);
+constexpr size_t kInlinedCapacity = 4;
+constexpr size_t kLargeSize = kInlinedCapacity * 2;
+constexpr size_t kSmallSize = kInlinedCapacity / 2;
+constexpr size_t kBatchSize = 100;
+
+#define ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_FunctionTemplate, T) \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize); \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize)
+
+#define ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_FunctionTemplate, T) \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kLargeSize); \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kLargeSize, kSmallSize); \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kLargeSize); \
+ BENCHMARK_TEMPLATE(BM_FunctionTemplate, T, kSmallSize, kSmallSize)
+
+template <typename T>
+using InlVec = absl::InlinedVector<T, kInlinedCapacity>;
+
+struct TrivialType {
+ size_t val;
+};
+
+class NontrivialType {
+ public:
+ ABSL_ATTRIBUTE_NOINLINE NontrivialType() : val_() {
+ benchmark::DoNotOptimize(*this);
+ }
+
+ ABSL_ATTRIBUTE_NOINLINE NontrivialType(const NontrivialType& other)
+ : val_(other.val_) {
+ benchmark::DoNotOptimize(*this);
+ }
+
+ ABSL_ATTRIBUTE_NOINLINE NontrivialType& operator=(
+ const NontrivialType& other) {
+ val_ = other.val_;
+ benchmark::DoNotOptimize(*this);
+ return *this;
+ }
+
+ ABSL_ATTRIBUTE_NOINLINE ~NontrivialType() noexcept {
+ benchmark::DoNotOptimize(*this);
+ }
+
+ private:
+ size_t val_;
+};
+
+template <typename T, typename PrepareVecFn, typename TestVecFn>
+void BatchedBenchmark(benchmark::State& state, PrepareVecFn prepare_vec,
+ TestVecFn test_vec) {
+ std::array<InlVec<T>, kBatchSize> vector_batch{};
+
+ while (state.KeepRunningBatch(kBatchSize)) {
+ // Prepare batch
+ state.PauseTiming();
+ for (size_t i = 0; i < kBatchSize; ++i) {
+ prepare_vec(vector_batch.data() + i, i);
+ }
+ benchmark::DoNotOptimize(vector_batch);
+ state.ResumeTiming();
+
+ // Test batch
+ for (size_t i = 0; i < kBatchSize; ++i) {
+ test_vec(vector_batch.data() + i, i);
+ }
+ }
+}
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromSize(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ auto size = ToSize;
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+ /* test_vec = */
+ [&](void* ptr, size_t) {
+ benchmark::DoNotOptimize(size);
+ ::new (ptr) VecT(size);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSize, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromSizeRef(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ auto size = ToSize;
+ auto ref = T();
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+ /* test_vec = */
+ [&](void* ptr, size_t) {
+ benchmark::DoNotOptimize(size);
+ benchmark::DoNotOptimize(ref);
+ ::new (ptr) VecT(size, ref);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromSizeRef, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromRange(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ std::array<T, ToSize> arr{};
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+ /* test_vec = */
+ [&](void* ptr, size_t) {
+ benchmark::DoNotOptimize(arr);
+ ::new (ptr) VecT(arr.begin(), arr.end());
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromRange, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromCopy(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ VecT other_vec(ToSize);
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) { vec->~VecT(); },
+ /* test_vec = */
+ [&](void* ptr, size_t) {
+ benchmark::DoNotOptimize(other_vec);
+ ::new (ptr) VecT(other_vec);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromCopy, NontrivialType);
+
+template <typename T, size_t ToSize>
+void BM_ConstructFromMove(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ std::array<VecT, kBatchSize> vector_batch{};
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [&](InlVec<T>* vec, size_t i) {
+ vector_batch[i].clear();
+ vector_batch[i].resize(ToSize);
+ vec->~VecT();
+ },
+ /* test_vec = */
+ [&](void* ptr, size_t i) {
+ benchmark::DoNotOptimize(vector_batch[i]);
+ ::new (ptr) VecT(std::move(vector_batch[i]));
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_ConstructFromMove, NontrivialType);
+
+// Measure cost of copy-constructor+destructor.
+void BM_CopyTrivial(benchmark::State& state) {
+ const int n = state.range(0);
+ InlVec<int64_t> src(n);
+ for (auto s : state) {
+ InlVec<int64_t> copy(src);
+ benchmark::DoNotOptimize(copy);
+ }
+}
+BENCHMARK(BM_CopyTrivial)->Arg(0)->Arg(1)->Arg(kLargeSize);
+
+// Measure cost of copy-constructor+destructor.
+void BM_CopyNonTrivial(benchmark::State& state) {
+ const int n = state.range(0);
+ InlVec<InlVec<int64_t>> src(n);
+ for (auto s : state) {
+ InlVec<InlVec<int64_t>> copy(src);
+ benchmark::DoNotOptimize(copy);
+ }
+}
+BENCHMARK(BM_CopyNonTrivial)->Arg(0)->Arg(1)->Arg(kLargeSize);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_AssignSizeRef(benchmark::State& state) {
+ auto size = ToSize;
+ auto ref = T();
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(size);
+ benchmark::DoNotOptimize(ref);
+ vec->assign(size, ref);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignSizeRef, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_AssignRange(benchmark::State& state) {
+ std::array<T, ToSize> arr{};
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(arr);
+ vec->assign(arr.begin(), arr.end());
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignRange, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_AssignFromCopy(benchmark::State& state) {
+ InlVec<T> other_vec(ToSize);
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(other_vec);
+ *vec = other_vec;
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromCopy, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_AssignFromMove(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ std::array<VecT, kBatchSize> vector_batch{};
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [&](InlVec<T>* vec, size_t i) {
+ vector_batch[i].clear();
+ vector_batch[i].resize(ToSize);
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t i) {
+ benchmark::DoNotOptimize(vector_batch[i]);
+ *vec = std::move(vector_batch[i]);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_AssignFromMove, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_ResizeSize(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) { vec->resize(ToSize); });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSize, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_ResizeSizeRef(benchmark::State& state) {
+ auto t = T();
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(t);
+ vec->resize(ToSize, t);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ResizeSizeRef, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_InsertSizeRef(benchmark::State& state) {
+ auto t = T();
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(t);
+ auto* pos = vec->data() + (vec->size() / 2);
+ vec->insert(pos, t);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertSizeRef, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_InsertRange(benchmark::State& state) {
+ InlVec<T> other_vec(ToSize);
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t) {
+ benchmark::DoNotOptimize(other_vec);
+ auto* pos = vec->data() + (vec->size() / 2);
+ vec->insert(pos, other_vec.begin(), other_vec.end());
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_InsertRange, NontrivialType);
+
+template <typename T, size_t FromSize>
+void BM_EmplaceBack(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) { vec->emplace_back(); });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EmplaceBack, NontrivialType);
+
+template <typename T, size_t FromSize>
+void BM_PopBack(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) { vec->pop_back(); });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_PopBack, NontrivialType);
+
+template <typename T, size_t FromSize>
+void BM_EraseOne(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) {
+ auto* pos = vec->data() + (vec->size() / 2);
+ vec->erase(pos);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseOne, NontrivialType);
+
+template <typename T, size_t FromSize>
+void BM_EraseRange(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) {
+ auto* pos = vec->data() + (vec->size() / 2);
+ vec->erase(pos, pos + 1);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_EraseRange, NontrivialType);
+
+template <typename T, size_t FromSize>
+void BM_Clear(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */ [](InlVec<T>* vec, size_t) { vec->resize(FromSize); },
+ /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->clear(); });
+}
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, TrivialType);
+ABSL_INTERNAL_BENCHMARK_ONE_SIZE(BM_Clear, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToCapacity>
+void BM_Reserve(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [](InlVec<T>* vec, size_t) { vec->reserve(ToCapacity); });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Reserve, NontrivialType);
+
+template <typename T, size_t FromCapacity, size_t ToCapacity>
+void BM_ShrinkToFit(benchmark::State& state) {
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [](InlVec<T>* vec, size_t) {
+ vec->clear();
+ vec->resize(ToCapacity);
+ vec->reserve(FromCapacity);
+ },
+ /* test_vec = */ [](InlVec<T>* vec, size_t) { vec->shrink_to_fit(); });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_ShrinkToFit, NontrivialType);
+
+template <typename T, size_t FromSize, size_t ToSize>
+void BM_Swap(benchmark::State& state) {
+ using VecT = InlVec<T>;
+ std::array<VecT, kBatchSize> vector_batch{};
+ BatchedBenchmark<T>(
+ state,
+ /* prepare_vec = */
+ [&](InlVec<T>* vec, size_t i) {
+ vector_batch[i].clear();
+ vector_batch[i].resize(ToSize);
+ vec->resize(FromSize);
+ },
+ /* test_vec = */
+ [&](InlVec<T>* vec, size_t i) {
+ using std::swap;
+ benchmark::DoNotOptimize(vector_batch[i]);
+ swap(*vec, vector_batch[i]);
+ });
+}
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, TrivialType);
+ABSL_INTERNAL_BENCHMARK_TWO_SIZE(BM_Swap, NontrivialType);
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_exception_safety_test.cc
new file mode 100644
index 00000000000..0e6a05b5f6a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_exception_safety_test.cc
@@ -0,0 +1,508 @@
+// 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.
+
+#include "absl/container/inlined_vector.h"
+
+#include "absl/base/config.h"
+
+#if defined(ABSL_HAVE_EXCEPTIONS)
+
+#include <array>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/exception_safety_testing.h"
+
+namespace {
+
+constexpr size_t kInlinedCapacity = 4;
+constexpr size_t kLargeSize = kInlinedCapacity * 2;
+constexpr size_t kSmallSize = kInlinedCapacity / 2;
+
+using Thrower = testing::ThrowingValue<>;
+using MovableThrower = testing::ThrowingValue<testing::TypeSpec::kNoThrowMove>;
+using ThrowAlloc = testing::ThrowingAllocator<Thrower>;
+
+using ThrowerVec = absl::InlinedVector<Thrower, kInlinedCapacity>;
+using MovableThrowerVec = absl::InlinedVector<MovableThrower, kInlinedCapacity>;
+
+using ThrowAllocThrowerVec =
+ absl::InlinedVector<Thrower, kInlinedCapacity, ThrowAlloc>;
+using ThrowAllocMovableThrowerVec =
+ absl::InlinedVector<MovableThrower, kInlinedCapacity, ThrowAlloc>;
+
+// In GCC, if an element of a `std::initializer_list` throws during construction
+// the elements that were constructed before it are not destroyed. This causes
+// incorrect exception safety test failures. Thus, `testing::nothrow_ctor` is
+// required. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66139
+#define ABSL_INTERNAL_MAKE_INIT_LIST(T, N) \
+ (N > kInlinedCapacity \
+ ? std::initializer_list<T>{T(0, testing::nothrow_ctor), \
+ T(1, testing::nothrow_ctor), \
+ T(2, testing::nothrow_ctor), \
+ T(3, testing::nothrow_ctor), \
+ T(4, testing::nothrow_ctor), \
+ T(5, testing::nothrow_ctor), \
+ T(6, testing::nothrow_ctor), \
+ T(7, testing::nothrow_ctor)} \
+ \
+ : std::initializer_list<T>{T(0, testing::nothrow_ctor), \
+ T(1, testing::nothrow_ctor)})
+static_assert(kLargeSize == 8, "Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)");
+static_assert(kSmallSize == 2, "Must update ABSL_INTERNAL_MAKE_INIT_LIST(...)");
+
+template <typename TheVecT, size_t... TheSizes>
+class TestParams {
+ public:
+ using VecT = TheVecT;
+ constexpr static size_t GetSizeAt(size_t i) { return kSizes[1 + i]; }
+
+ private:
+ constexpr static size_t kSizes[1 + sizeof...(TheSizes)] = {1, TheSizes...};
+};
+
+using NoSizeTestParams =
+ ::testing::Types<TestParams<ThrowerVec>, TestParams<MovableThrowerVec>,
+ TestParams<ThrowAllocThrowerVec>,
+ TestParams<ThrowAllocMovableThrowerVec>>;
+
+using OneSizeTestParams =
+ ::testing::Types<TestParams<ThrowerVec, kLargeSize>,
+ TestParams<ThrowerVec, kSmallSize>,
+ TestParams<MovableThrowerVec, kLargeSize>,
+ TestParams<MovableThrowerVec, kSmallSize>,
+ TestParams<ThrowAllocThrowerVec, kLargeSize>,
+ TestParams<ThrowAllocThrowerVec, kSmallSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kLargeSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kSmallSize>>;
+
+using TwoSizeTestParams = ::testing::Types<
+ TestParams<ThrowerVec, kLargeSize, kLargeSize>,
+ TestParams<ThrowerVec, kLargeSize, kSmallSize>,
+ TestParams<ThrowerVec, kSmallSize, kLargeSize>,
+ TestParams<ThrowerVec, kSmallSize, kSmallSize>,
+ TestParams<MovableThrowerVec, kLargeSize, kLargeSize>,
+ TestParams<MovableThrowerVec, kLargeSize, kSmallSize>,
+ TestParams<MovableThrowerVec, kSmallSize, kLargeSize>,
+ TestParams<MovableThrowerVec, kSmallSize, kSmallSize>,
+ TestParams<ThrowAllocThrowerVec, kLargeSize, kLargeSize>,
+ TestParams<ThrowAllocThrowerVec, kLargeSize, kSmallSize>,
+ TestParams<ThrowAllocThrowerVec, kSmallSize, kLargeSize>,
+ TestParams<ThrowAllocThrowerVec, kSmallSize, kSmallSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kLargeSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kLargeSize, kSmallSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kLargeSize>,
+ TestParams<ThrowAllocMovableThrowerVec, kSmallSize, kSmallSize>>;
+
+template <typename>
+struct NoSizeTest : ::testing::Test {};
+TYPED_TEST_SUITE(NoSizeTest, NoSizeTestParams);
+
+template <typename>
+struct OneSizeTest : ::testing::Test {};
+TYPED_TEST_SUITE(OneSizeTest, OneSizeTestParams);
+
+template <typename>
+struct TwoSizeTest : ::testing::Test {};
+TYPED_TEST_SUITE(TwoSizeTest, TwoSizeTestParams);
+
+template <typename VecT>
+bool InlinedVectorInvariants(VecT* vec) {
+ if (*vec != *vec) return false;
+ if (vec->size() > vec->capacity()) return false;
+ if (vec->size() > vec->max_size()) return false;
+ if (vec->capacity() > vec->max_size()) return false;
+ if (vec->data() != std::addressof(vec->at(0))) return false;
+ if (vec->data() != vec->begin()) return false;
+ if (*vec->data() != *vec->begin()) return false;
+ if (vec->begin() > vec->end()) return false;
+ if ((vec->end() - vec->begin()) != vec->size()) return false;
+ if (std::distance(vec->begin(), vec->end()) != vec->size()) return false;
+ return true;
+}
+
+// Function that always returns false is correct, but refactoring is required
+// for clarity. It's needed to express that, as a contract, certain operations
+// should not throw at all. Execution of this function means an exception was
+// thrown and thus the test should fail.
+// TODO(johnsoncj): Add `testing::NoThrowGuarantee` to the framework
+template <typename VecT>
+bool NoThrowGuarantee(VecT* /* vec */) {
+ return false;
+}
+
+TYPED_TEST(NoSizeTest, DefaultConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using allocator_type = typename VecT::allocator_type;
+
+ testing::TestThrowingCtor<VecT>();
+
+ testing::TestThrowingCtor<VecT>(allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, SizeConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ testing::TestThrowingCtor<VecT>(size);
+
+ testing::TestThrowingCtor<VecT>(size, allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, SizeRefConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ testing::TestThrowingCtor<VecT>(size, value_type{});
+
+ testing::TestThrowingCtor<VecT>(size, value_type{}, allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, InitializerListConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ testing::TestThrowingCtor<VecT>(
+ ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size));
+
+ testing::TestThrowingCtor<VecT>(
+ ABSL_INTERNAL_MAKE_INIT_LIST(value_type, size), allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, RangeConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ std::array<value_type, size> arr{};
+
+ testing::TestThrowingCtor<VecT>(arr.begin(), arr.end());
+
+ testing::TestThrowingCtor<VecT>(arr.begin(), arr.end(), allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, CopyConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ VecT other_vec{size};
+
+ testing::TestThrowingCtor<VecT>(other_vec);
+
+ testing::TestThrowingCtor<VecT>(other_vec, allocator_type{});
+}
+
+TYPED_TEST(OneSizeTest, MoveConstructor) {
+ using VecT = typename TypeParam::VecT;
+ using allocator_type = typename VecT::allocator_type;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ if (!absl::allocator_is_nothrow<allocator_type>::value) {
+ testing::TestThrowingCtor<VecT>(VecT{size});
+
+ testing::TestThrowingCtor<VecT>(VecT{size}, allocator_type{});
+ }
+}
+
+TYPED_TEST(TwoSizeTest, Assign) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+ constexpr static auto to_size = TypeParam::GetSizeAt(1);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ *vec = ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ VecT other_vec{to_size};
+ *vec = other_vec;
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ VecT other_vec{to_size};
+ *vec = std::move(other_vec);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ value_type val{};
+ vec->assign(to_size, val);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->assign(ABSL_INTERNAL_MAKE_INIT_LIST(value_type, to_size));
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ std::array<value_type, to_size> arr{};
+ vec->assign(arr.begin(), arr.end());
+ }));
+}
+
+TYPED_TEST(TwoSizeTest, Resize) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+ constexpr static auto to_size = TypeParam::GetSizeAt(1);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>,
+ testing::strong_guarantee);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->resize(to_size); //
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->resize(to_size, value_type{}); //
+ }));
+}
+
+TYPED_TEST(OneSizeTest, Insert) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->insert(it, value_type{});
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->insert(it, value_type{});
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->end();
+ vec->insert(it, value_type{});
+ }));
+}
+
+TYPED_TEST(TwoSizeTest, Insert) {
+ using VecT = typename TypeParam::VecT;
+ using value_type = typename VecT::value_type;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+ constexpr static auto count = TypeParam::GetSizeAt(1);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->insert(it, count, value_type{});
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->insert(it, count, value_type{});
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->end();
+ vec->insert(it, count, value_type{});
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->end();
+ vec->insert(it, ABSL_INTERNAL_MAKE_INIT_LIST(value_type, count));
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ std::array<value_type, count> arr{};
+ vec->insert(it, arr.begin(), arr.end());
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ std::array<value_type, count> arr{};
+ vec->insert(it, arr.begin(), arr.end());
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->end();
+ std::array<value_type, count> arr{};
+ vec->insert(it, arr.begin(), arr.end());
+ }));
+}
+
+TYPED_TEST(OneSizeTest, EmplaceBack) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ // For testing calls to `emplace_back(...)` that reallocate.
+ VecT full_vec{size};
+ full_vec.resize(full_vec.capacity());
+
+ // For testing calls to `emplace_back(...)` that don't reallocate.
+ VecT nonfull_vec{size};
+ nonfull_vec.reserve(size + 1);
+
+ auto tester = testing::MakeExceptionSafetyTester().WithContracts(
+ InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.WithInitialValue(nonfull_vec).Test([](VecT* vec) {
+ vec->emplace_back();
+ }));
+
+ EXPECT_TRUE(tester.WithInitialValue(full_vec).Test(
+ [](VecT* vec) { vec->emplace_back(); }));
+}
+
+TYPED_TEST(OneSizeTest, PopBack) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{size})
+ .WithContracts(NoThrowGuarantee<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->pop_back(); //
+ }));
+}
+
+TYPED_TEST(OneSizeTest, Erase) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->erase(it);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->erase(it);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() - 1);
+ vec->erase(it);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->erase(it, it);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->erase(it, it);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() - 1);
+ vec->erase(it, it);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin();
+ vec->erase(it, it + 1);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() / 2);
+ vec->erase(it, it + 1);
+ }));
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ auto it = vec->begin() + (vec->size() - 1);
+ vec->erase(it, it + 1);
+ }));
+}
+
+TYPED_TEST(OneSizeTest, Clear) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{size})
+ .WithContracts(NoThrowGuarantee<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->clear(); //
+ }));
+}
+
+TYPED_TEST(TwoSizeTest, Reserve) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+ constexpr static auto to_capacity = TypeParam::GetSizeAt(1);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) { vec->reserve(to_capacity); }));
+}
+
+TYPED_TEST(OneSizeTest, ShrinkToFit) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto size = TypeParam::GetSizeAt(0);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ vec->shrink_to_fit(); //
+ }));
+}
+
+TYPED_TEST(TwoSizeTest, Swap) {
+ using VecT = typename TypeParam::VecT;
+ constexpr static auto from_size = TypeParam::GetSizeAt(0);
+ constexpr static auto to_size = TypeParam::GetSizeAt(1);
+
+ auto tester = testing::MakeExceptionSafetyTester()
+ .WithInitialValue(VecT{from_size})
+ .WithContracts(InlinedVectorInvariants<VecT>);
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ VecT other_vec{to_size};
+ vec->swap(other_vec);
+ }));
+
+ EXPECT_TRUE(tester.Test([](VecT* vec) {
+ using std::swap;
+ VecT other_vec{to_size};
+ swap(*vec, other_vec);
+ }));
+}
+
+} // namespace
+
+#endif // defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_test.cc
index 3a1ea8ac1de..98aff33498b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/inlined_vector_test.cc
@@ -1,10 +1,10 @@
-// Copyright 2017 The Abseil Authors.
+// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,6 +30,8 @@
#include "absl/base/internal/exception_testing.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/macros.h"
+#include "absl/base/options.h"
+#include "absl/container/internal/counting_allocator.h"
#include "absl/container/internal/test_instance_tracker.h"
#include "absl/hash/hash_testing.h"
#include "absl/memory/memory.h"
@@ -37,6 +39,7 @@
namespace {
+using absl::container_internal::CountingAllocator;
using absl::test_internal::CopyableMovableInstance;
using absl::test_internal::CopyableOnlyInstance;
using absl::test_internal::InstanceTracker;
@@ -68,18 +71,15 @@ MATCHER_P(ValueIs, e, "") {
// test_instance_tracker.h.
template <typename T>
class InstanceTest : public ::testing::Test {};
-TYPED_TEST_CASE_P(InstanceTest);
+TYPED_TEST_SUITE_P(InstanceTest);
// A simple reference counted class to make sure that the proper elements are
// destroyed in the erase(begin, end) test.
class RefCounted {
public:
- RefCounted(int value, int* count) : value_(value), count_(count) {
- Ref();
- }
+ RefCounted(int value, int* count) : value_(value), count_(count) { Ref(); }
- RefCounted(const RefCounted& v)
- : value_(v.value_), count_(v.count_) {
+ RefCounted(const RefCounted& v) : value_(v.value_), count_(v.count_) {
Ref();
}
@@ -138,57 +138,6 @@ static IntVec Fill(int len, int offset = 0) {
return v;
}
-// 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 std::allocator<T> {
- public:
- using Alloc = std::allocator<T>;
- using pointer = typename Alloc::pointer;
- using size_type = typename Alloc::size_type;
-
- CountingAllocator() : bytes_used_(nullptr) {}
- explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
-
- template <typename U>
- CountingAllocator(const CountingAllocator<U>& x)
- : Alloc(x), bytes_used_(x.bytes_used_) {}
-
- pointer allocate(size_type n,
- std::allocator<void>::const_pointer hint = nullptr) {
- assert(bytes_used_ != nullptr);
- *bytes_used_ += n * sizeof(T);
- return Alloc::allocate(n, hint);
- }
-
- void deallocate(pointer p, size_type n) {
- Alloc::deallocate(p, n);
- assert(bytes_used_ != nullptr);
- *bytes_used_ -= n * sizeof(T);
- }
-
- 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_;
- }
-
- friend bool operator!=(const CountingAllocator& a,
- const CountingAllocator& b) {
- return !(a == b);
- }
-
- int64_t* bytes_used_;
-};
-
TEST(IntVec, SimpleOps) {
for (int len = 0; len < 20; len++) {
IntVec v;
@@ -239,6 +188,12 @@ TEST(IntVec, SimpleOps) {
}
}
+TEST(IntVec, PopBackNoOverflow) {
+ IntVec v = {1};
+ v.pop_back();
+ EXPECT_EQ(v.size(), 0);
+}
+
TEST(IntVec, AtThrows) {
IntVec v = {1, 2, 3};
EXPECT_EQ(v.at(2), 3);
@@ -293,6 +248,16 @@ TEST(IntVec, Erase) {
}
}
+TEST(IntVec, Hardened) {
+ IntVec v;
+ Fill(&v, 10);
+ EXPECT_EQ(v[9], 9);
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ EXPECT_DEATH_IF_SUPPORTED(v[10], "");
+ EXPECT_DEATH_IF_SUPPORTED(v[-1], "");
+#endif
+}
+
// At the end of this test loop, the elements between [erase_begin, erase_end)
// should have reference counts == 0, and all others elements should have
// reference counts == 1.
@@ -333,7 +298,7 @@ TEST(RefCountedVec, EraseBeginEnd) {
}
// Check that the elements at the end are preserved.
- for (int i = erase_end; i< len; ++i) {
+ for (int i = erase_end; i < len; ++i) {
EXPECT_EQ(1, counts[i]);
}
}
@@ -595,10 +560,10 @@ TEST(IntVec, Resize) {
static const int kResizeElem = 1000000;
for (int k = 0; k < 10; k++) {
// Enlarging resize
- v.resize(len+k, kResizeElem);
- EXPECT_EQ(len+k, v.size());
- EXPECT_LE(len+k, v.capacity());
- for (int i = 0; i < len+k; i++) {
+ v.resize(len + k, kResizeElem);
+ EXPECT_EQ(len + k, v.size());
+ EXPECT_LE(len + k, v.capacity());
+ for (int i = 0; i < len + k; i++) {
if (i < len) {
EXPECT_EQ(i, v[i]);
} else {
@@ -771,22 +736,26 @@ TEST(OverheadTest, Storage) {
// In particular, ensure that std::allocator doesn't cost anything to store.
// The union should be absorbing some of the allocation bookkeeping overhead
// in the larger vectors, leaving only the size_ field as overhead.
- EXPECT_EQ(2 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 1>) - 1 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 2>) - 2 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 3>) - 3 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 4>) - 4 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 5>) - 5 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 6>) - 6 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 7>) - 7 * sizeof(int*));
- EXPECT_EQ(1 * sizeof(int*),
- sizeof(absl::InlinedVector<int*, 8>) - 8 * sizeof(int*));
+
+ struct T { void* val; };
+ size_t expected_overhead = sizeof(T);
+
+ EXPECT_EQ((2 * expected_overhead),
+ sizeof(absl::InlinedVector<T, 1>) - sizeof(T[1]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 2>) - sizeof(T[2]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 3>) - sizeof(T[3]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 4>) - sizeof(T[4]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 5>) - sizeof(T[5]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 6>) - sizeof(T[6]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 7>) - sizeof(T[7]));
+ EXPECT_EQ(expected_overhead,
+ sizeof(absl::InlinedVector<T, 8>) - sizeof(T[8]));
}
TEST(IntVec, Clear) {
@@ -826,7 +795,7 @@ TEST(IntVec, Reserve) {
TEST(StringVec, SelfRefPushBack) {
std::vector<std::string> std_v;
absl::InlinedVector<std::string, 4> v;
- const std::string s = "A quite long std::string to ensure heap.";
+ const std::string s = "A quite long string to ensure heap.";
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
@@ -841,7 +810,7 @@ TEST(StringVec, SelfRefPushBack) {
TEST(StringVec, SelfRefPushBackWithMove) {
std::vector<std::string> std_v;
absl::InlinedVector<std::string, 4> v;
- const std::string s = "A quite long std::string to ensure heap.";
+ const std::string s = "A quite long string to ensure heap.";
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
@@ -854,7 +823,7 @@ TEST(StringVec, SelfRefPushBackWithMove) {
}
TEST(StringVec, SelfMove) {
- const std::string s = "A quite long std::string to ensure heap.";
+ const std::string s = "A quite long string to ensure heap.";
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
absl::InlinedVector<std::string, 8> v;
@@ -909,7 +878,7 @@ TYPED_TEST_P(InstanceTest, Swap) {
auto min_len = std::min(l1, l2);
auto max_len = std::max(l1, l2);
for (int i = 0; i < l1; i++) a.push_back(Instance(i));
- for (int i = 0; i < l2; i++) b.push_back(Instance(100+i));
+ for (int i = 0; i < l2; i++) b.push_back(Instance(100 + i));
EXPECT_EQ(tracker.instances(), l1 + l2);
tracker.ResetCopiesMovesSwaps();
{
@@ -977,7 +946,7 @@ TEST(IntVec, EqualAndNotEqual) {
EXPECT_FALSE(a == b);
EXPECT_TRUE(a != b);
- b[i] = b[i] - 1; // Back to before
+ b[i] = b[i] - 1; // Back to before
EXPECT_TRUE(a == b);
EXPECT_FALSE(a != b);
}
@@ -1044,7 +1013,7 @@ TYPED_TEST_P(InstanceTest, CountConstructorsDestructors) {
// reserve() must not increase the number of initialized objects
SCOPED_TRACE("reserve");
- v.reserve(len+1000);
+ v.reserve(len + 1000);
EXPECT_EQ(tracker.instances(), len);
EXPECT_EQ(tracker.copies() + tracker.moves(), len);
@@ -1290,9 +1259,8 @@ void InstanceCountElemAssignWithAllocationTest() {
absl::InlinedVector<Instance, 2> v(original_contents.begin(),
original_contents.end());
v.assign(3, Instance(123));
- EXPECT_THAT(v,
- AllOf(SizeIs(3),
- ElementsAre(ValueIs(123), ValueIs(123), ValueIs(123))));
+ EXPECT_THAT(v, AllOf(SizeIs(3), ElementsAre(ValueIs(123), ValueIs(123),
+ ValueIs(123))));
EXPECT_LE(v.size(), v.capacity());
}
}
@@ -1571,8 +1539,8 @@ TYPED_TEST_P(InstanceTest, InitializerListAssign) {
SCOPED_TRACE(original_size);
absl::InlinedVector<Instance, 2> v(original_size, Instance(12345));
v.assign({Instance(3), Instance(4), Instance(5)});
- EXPECT_THAT(v, AllOf(SizeIs(3),
- ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
+ EXPECT_THAT(
+ v, AllOf(SizeIs(3), ElementsAre(ValueIs(3), ValueIs(4), ValueIs(5))));
EXPECT_LE(3, v.capacity());
}
}
@@ -1597,7 +1565,7 @@ TEST(DynamicVec, DynamicVecCompiles) {
TEST(AllocatorSupportTest, Constructors) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
- const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
int64_t allocated = 0;
MyAlloc alloc(&allocated);
{ AllocVec ABSL_ATTRIBUTE_UNUSED v; }
@@ -1613,7 +1581,7 @@ TEST(AllocatorSupportTest, Constructors) {
TEST(AllocatorSupportTest, CountAllocations) {
using MyAlloc = CountingAllocator<int>;
using AllocVec = absl::InlinedVector<int, 4, MyAlloc>;
- const int ia[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
+ const int ia[] = {0, 1, 2, 3, 4, 5, 6, 7};
int64_t allocated = 0;
MyAlloc alloc(&allocated);
{
@@ -1677,8 +1645,8 @@ TEST(AllocatorSupportTest, SwapBothAllocated) {
int64_t allocated1 = 0;
int64_t allocated2 = 0;
{
- const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
- const int ia2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
+ const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
+ const int ia2[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
MyAlloc a1(&allocated1);
MyAlloc a2(&allocated2);
AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
@@ -1702,8 +1670,8 @@ TEST(AllocatorSupportTest, SwapOneAllocated) {
int64_t allocated1 = 0;
int64_t allocated2 = 0;
{
- const int ia1[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
- const int ia2[] = { 0, 1, 2, 3 };
+ const int ia1[] = {0, 1, 2, 3, 4, 5, 6, 7};
+ const int ia2[] = {0, 1, 2, 3};
MyAlloc a1(&allocated1);
MyAlloc a2(&allocated2);
AllocVec v1(ia1, ia1 + ABSL_ARRAYSIZE(ia1), a1);
@@ -1722,67 +1690,57 @@ TEST(AllocatorSupportTest, SwapOneAllocated) {
EXPECT_THAT(allocated2, 0);
}
-TEST(AllocatorSupportTest, ScopedAllocatorWorks) {
+TEST(AllocatorSupportTest, ScopedAllocatorWorksInlined) {
using StdVector = std::vector<int, CountingAllocator<int>>;
- using MyAlloc =
- std::scoped_allocator_adaptor<CountingAllocator<StdVector>>;
- using AllocVec = absl::InlinedVector<StdVector, 4, MyAlloc>;
-
- // MSVC 2017's std::vector allocates different amounts of memory in debug
- // versus opt mode.
- int64_t test_allocated = 0;
- StdVector v(CountingAllocator<int>{&test_allocated});
- // The amount of memory allocated by a default constructed vector<int>
- auto default_std_vec_allocated = test_allocated;
- v.push_back(1);
- // The amound of memory allocated by a copy-constructed vector<int> with one
- // element.
- int64_t one_element_std_vec_copy_allocated = test_allocated;
+ using Alloc = CountingAllocator<StdVector>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
+ using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
- int64_t allocated = 0;
- AllocVec vec(MyAlloc{CountingAllocator<StdVector>{&allocated}});
- EXPECT_EQ(allocated, 0);
+ int64_t total_allocated_byte_count = 0;
- // This default constructs a vector<int>, but the allocator should pass itself
- // into the vector<int>, so check allocation compared to that.
- // The absl::InlinedVector does not allocate any memory.
- // The vector<int> may allocate any memory.
- auto expected = default_std_vec_allocated;
- vec.resize(1);
- EXPECT_EQ(allocated, expected);
-
- // We make vector<int> allocate memory.
- // It must go through the allocator even though we didn't construct the
- // vector directly. This assumes that vec[0] doesn't need to grow its
- // allocation.
- expected += sizeof(int);
- vec[0].push_back(1);
- EXPECT_EQ(allocated, expected);
-
- // Another allocating vector.
- expected += one_element_std_vec_copy_allocated;
- vec.push_back(vec[0]);
- EXPECT_EQ(allocated, expected);
-
- // Overflow the inlined memory.
- // The absl::InlinedVector will now allocate.
- expected += sizeof(StdVector) * 8 + default_std_vec_allocated * 3;
- vec.resize(5);
- EXPECT_EQ(allocated, expected);
-
- // Adding one more in external mode should also work.
- expected += one_element_std_vec_copy_allocated;
- vec.push_back(vec[0]);
- EXPECT_EQ(allocated, expected);
-
- // And extending these should still work. This assumes that vec[0] does not
- // need to grow its allocation.
- expected += sizeof(int);
- vec[0].push_back(1);
- EXPECT_EQ(allocated, expected);
-
- vec.clear();
- EXPECT_EQ(allocated, 0);
+ AllocVec inlined_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
+
+ // Called only once to remain inlined
+ inlined_case.emplace_back();
+
+ int64_t absl_responsible_for_count = total_allocated_byte_count;
+
+ // MSVC's allocator preemptively allocates in debug mode
+#if !defined(_MSC_VER)
+ EXPECT_EQ(absl_responsible_for_count, 0);
+#endif // !defined(_MSC_VER)
+
+ inlined_case[0].emplace_back();
+ EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
+
+ inlined_case.clear();
+ inlined_case.shrink_to_fit();
+ EXPECT_EQ(total_allocated_byte_count, 0);
+}
+
+TEST(AllocatorSupportTest, ScopedAllocatorWorksAllocated) {
+ using StdVector = std::vector<int, CountingAllocator<int>>;
+ using Alloc = CountingAllocator<StdVector>;
+ using ScopedAlloc = std::scoped_allocator_adaptor<Alloc>;
+ using AllocVec = absl::InlinedVector<StdVector, 1, ScopedAlloc>;
+
+ int64_t total_allocated_byte_count = 0;
+
+ AllocVec allocated_case(ScopedAlloc(Alloc(+&total_allocated_byte_count)));
+
+ // Called twice to force into being allocated
+ allocated_case.emplace_back();
+ allocated_case.emplace_back();
+
+ int64_t absl_responsible_for_count = total_allocated_byte_count;
+ EXPECT_GT(absl_responsible_for_count, 0);
+
+ allocated_case[1].emplace_back();
+ EXPECT_GT(total_allocated_byte_count, absl_responsible_for_count);
+
+ allocated_case.clear();
+ allocated_case.shrink_to_fit();
+ EXPECT_EQ(total_allocated_byte_count, 0);
}
TEST(AllocatorSupportTest, SizeAllocConstructor) {
@@ -1811,4 +1769,47 @@ TEST(AllocatorSupportTest, SizeAllocConstructor) {
}
}
+TEST(InlinedVectorTest, MinimumAllocatorCompilesUsingTraits) {
+ using T = int;
+ using A = std::allocator<T>;
+ using ATraits = absl::allocator_traits<A>;
+
+ struct MinimumAllocator {
+ using value_type = T;
+
+ value_type* allocate(size_t n) {
+ A a;
+ return ATraits::allocate(a, n);
+ }
+
+ void deallocate(value_type* p, size_t n) {
+ A a;
+ ATraits::deallocate(a, p, n);
+ }
+ };
+
+ absl::InlinedVector<T, 1, MinimumAllocator> vec;
+ vec.emplace_back();
+ vec.resize(0);
+}
+
+TEST(InlinedVectorTest, AbslHashValueWorks) {
+ using V = absl::InlinedVector<int, 4>;
+ std::vector<V> cases;
+
+ // Generate a variety of vectors some of these are small enough for the inline
+ // space but are stored out of line.
+ for (int i = 0; i < 10; ++i) {
+ V v;
+ for (int j = 0; j < i; ++j) {
+ v.push_back(j);
+ }
+ cases.push_back(v);
+ v.resize(i % 4);
+ cases.push_back(v);
+ }
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(cases));
+}
+
} // anonymous namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree.h
new file mode 100644
index 00000000000..0bb38366d0f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree.h
@@ -0,0 +1,2620 @@
+// 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 <new>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/macros.h"
+#include "absl/container/internal/common.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"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// 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<absl::result_of_t<Compare(const T &, const T &)>,
+ absl::weak_ordering>;
+
+struct StringBtreeDefaultLess {
+ using is_transparent = void;
+
+ StringBtreeDefaultLess() = default;
+
+ // Compatibility constructor.
+ StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT
+ StringBtreeDefaultLess(std::less<string_view>) {} // NOLINT
+
+ 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<string_view>) {} // NOLINT
+
+ 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));
+ }
+};
+
+// A helper class to convert a boolean comparison into a three-way "compare-to"
+// 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>.
+//
+// key_compare_to_adapter is provided so that btree users
+// automatically get the more efficient compare-to code when using common
+// Abseil string types with common comparison functors.
+// These string-like specializations also turn on heterogeneous lookup by
+// default.
+template <typename Compare>
+struct key_compare_to_adapter {
+ using type = Compare;
+};
+
+template <>
+struct key_compare_to_adapter<std::less<std::string>> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_to_adapter<std::greater<std::string>> {
+ using type = StringBtreeDefaultGreater;
+};
+
+template <>
+struct key_compare_to_adapter<std::less<absl::string_view>> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_to_adapter<std::greater<absl::string_view>> {
+ using type = StringBtreeDefaultGreater;
+};
+
+template <>
+struct key_compare_to_adapter<std::less<absl::Cord>> {
+ using type = StringBtreeDefaultLess;
+};
+
+template <>
+struct key_compare_to_adapter<std::greater<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 Key, typename Compare, typename Alloc, int TargetNodeSize,
+ bool Multi, typename SlotPolicy>
+struct common_params {
+ // 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.
+ using key_compare = typename key_compare_to_adapter<Compare>::type;
+ // 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 = std::make_signed<size_t>::type;
+ 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 &;
+
+ // 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 Multi ||
+ (IsTransparent<key_compare>::value &&
+ !std::is_same<LookupKey, Key>::value &&
+ !std::is_same<key_compare, StringBtreeDefaultLess>::value &&
+ !std::is_same<key_compare, StringBtreeDefaultGreater>::value);
+ }
+
+ enum {
+ kTargetNodeSize = TargetNodeSize,
+
+ // Upper bound for the available space for values. This is largest for leaf
+ // nodes, which have overhead of at least a pointer + 4 bytes (for storing
+ // 3 field_types and an enum).
+ kNodeValueSpace =
+ TargetNodeSize - /*minimum overhead=*/(sizeof(void *) + 4),
+ };
+
+ // This is an integral type large enough to hold as many
+ // ValueSize-values as will fit a node of TargetNodeSize bytes.
+ using node_count_type =
+ absl::conditional_t<(kNodeValueSpace / sizeof(value_type) >
+ (std::numeric_limits<uint8_t>::max)()),
+ uint16_t, uint8_t>; // NOLINT
+
+ // The following methods are necessary for passing this struct as PolicyTraits
+ // for node_handle and/or are used within btree.
+ static value_type &element(slot_type *slot) {
+ return slot_policy::element(slot);
+ }
+ static const value_type &element(const slot_type *slot) {
+ return slot_policy::element(slot);
+ }
+ template <class... Args>
+ static void construct(Alloc *alloc, slot_type *slot, Args &&... args) {
+ slot_policy::construct(alloc, slot, std::forward<Args>(args)...);
+ }
+ static void construct(Alloc *alloc, slot_type *slot, slot_type *other) {
+ slot_policy::construct(alloc, slot, other);
+ }
+ static void destroy(Alloc *alloc, slot_type *slot) {
+ slot_policy::destroy(alloc, slot);
+ }
+ static void transfer(Alloc *alloc, slot_type *new_slot, slot_type *old_slot) {
+ construct(alloc, new_slot, old_slot);
+ destroy(alloc, old_slot);
+ }
+ static void swap(Alloc *alloc, slot_type *a, slot_type *b) {
+ slot_policy::swap(alloc, a, b);
+ }
+ static void move(Alloc *alloc, slot_type *src, slot_type *dest) {
+ slot_policy::move(alloc, src, dest);
+ }
+};
+
+// 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 Multi>
+struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
+ 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;
+
+ using key_compare = typename super_type::key_compare;
+ // Inherit from key_compare for empty base class optimization.
+ struct value_compare : private key_compare {
+ value_compare() = default;
+ explicit value_compare(const key_compare &cmp) : key_compare(cmp) {}
+
+ template <typename T, typename U>
+ auto operator()(const T &left, const U &right) const
+ -> decltype(std::declval<key_compare>()(left.first, right.first)) {
+ return key_compare::operator()(left.first, right.first);
+ }
+ };
+ using is_map_container = std::true_type;
+
+ template <typename V>
+ static auto key(const V &value) -> 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; }
+};
+
+// This type implements the necessary functions from the
+// absl::container_internal::slot_type interface.
+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 destroy(Alloc *alloc, slot_type *slot) {
+ absl::allocator_traits<Alloc>::destroy(*alloc, slot);
+ }
+
+ template <typename Alloc>
+ static void swap(Alloc * /*alloc*/, slot_type *a, slot_type *b) {
+ using std::swap;
+ swap(*a, *b);
+ }
+
+ template <typename Alloc>
+ static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) {
+ *dest = std::move(*src);
+ }
+};
+
+// 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 Multi>
+struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
+ set_slot_policy<Key>> {
+ using value_type = Key;
+ using slot_type = typename set_params::common_params::slot_type;
+ using value_compare = typename set_params::common_params::key_compare;
+ using is_map_container = std::false_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; }
+};
+
+// 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() {}
+ explicit SearchResult(V value) : value(value) {}
+ SearchResult(V value, MatchKind /*match*/) : value(value) {}
+
+ 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;
+
+ 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<key_compare>::value
+ ? prefers_linear_node_search<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>, key_compare>::value ||
+ std::is_same<std::greater<key_type>,
+ key_compare>::value)>;
+
+ // This class is organized by gtl::Layout as if it had the following
+ // structure:
+ // // A pointer to the node's parent.
+ // btree_node *parent;
+ //
+ // // 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;
+
+ // Public for EmptyNodeType.
+ constexpr static size_type Alignment() {
+ static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
+ "Alignment of all nodes must be equal.");
+ return InternalLayout().Alignment();
+ }
+
+ protected:
+ btree_node() = default;
+
+ private:
+ using layout_type = absl::container_internal::Layout<btree_node *, field_type,
+ slot_type, btree_node *>;
+ constexpr static size_type SizeWithNSlots(size_type n) {
+ return layout_type(/*parent*/ 1,
+ /*position, start, finish, max_count*/ 4,
+ /*slots*/ n,
+ /*children*/ 0)
+ .AllocSize();
+ }
+ // A lower bound for the overhead of fields other than values in a leaf node.
+ constexpr static size_type MinimumOverhead() {
+ return SizeWithNSlots(1) - sizeof(value_type);
+ }
+
+ // Compute how many values we can fit onto a leaf node taking into account
+ // padding.
+ constexpr static size_type NodeTargetSlots(const int begin, const int end) {
+ return begin == end ? begin
+ : SizeWithNSlots((begin + end) / 2 + 1) >
+ params_type::kTargetNodeSize
+ ? NodeTargetSlots(begin, (begin + end) / 2)
+ : NodeTargetSlots((begin + end) / 2 + 1, end);
+ }
+
+ enum {
+ kTargetNodeSize = params_type::kTargetNodeSize,
+ kNodeTargetSlots = NodeTargetSlots(0, params_type::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).
+ kMinNodeSlots = 4,
+
+ kNodeSlots =
+ kNodeTargetSlots >= kMinNodeSlots ? kNodeTargetSlots : kMinNodeSlots,
+
+ // The node is internal (i.e. is not a leaf node) if and only if `max_count`
+ // has this value.
+ kInternalNodeMaxCount = 0,
+ };
+
+ // Leaves can have less than kNodeSlots values.
+ constexpr static layout_type LeafLayout(const int slot_count = kNodeSlots) {
+ return layout_type(/*parent*/ 1,
+ /*position, start, finish, max_count*/ 4,
+ /*slots*/ slot_count,
+ /*children*/ 0);
+ }
+ constexpr static layout_type InternalLayout() {
+ return layout_type(/*parent*/ 1,
+ /*position, start, finish, max_count*/ 4,
+ /*slots*/ kNodeSlots,
+ /*children*/ kNodeSlots + 1);
+ }
+ constexpr static size_type LeafSize(const int slot_count = kNodeSlots) {
+ return LeafLayout(slot_count).AllocSize();
+ }
+ constexpr static size_type InternalSize() {
+ return InternalLayout().AllocSize();
+ }
+
+ // 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 < 3 || !leaf());
+ 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 < 3 || !leaf());
+ 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<1>()[2]; }
+ slot_type *slot(int i) { return &GetField<2>()[i]; }
+ slot_type *start_slot() { return slot(start()); }
+ slot_type *finish_slot() { return slot(finish()); }
+ const slot_type *slot(int i) const { return &GetField<2>()[i]; }
+ void set_position(field_type v) { GetField<1>()[0] = v; }
+ void set_start(field_type v) { GetField<1>()[1] = v; }
+ void set_finish(field_type v) { GetField<1>()[2] = v; }
+ // This method is only called by the node init methods.
+ void set_max_count(field_type v) { GetField<1>()[3] = v; }
+
+ public:
+ // Whether this is a leaf node or not. This value doesn't change after the
+ // node is created.
+ bool leaf() const { return GetField<1>()[3] != kInternalNodeMaxCount; }
+
+ // Getter for the position of this node in its parent.
+ field_type position() const { return GetField<1>()[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<1>()[1];
+ assert(GetField<1>()[1] == 0);
+ return 0;
+ }
+
+ // Getter for the offset after the last value in the `values` array.
+ field_type finish() const { return GetField<1>()[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<1>()[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()->leaf(); }
+ void make_root() {
+ assert(parent()->is_root());
+ set_parent(parent()->parent());
+ }
+
+ // Getters for the key/value at position i in the node.
+ const key_type &key(int i) const { return params_type::key(slot(i)); }
+ reference value(int i) { return params_type::element(slot(i)); }
+ const_reference value(int i) const { return params_type::element(slot(i)); }
+
+ // Getters/setter for the child at position i in the node.
+ btree_node *child(int i) const { return GetField<3>()[i]; }
+ btree_node *start_child() const { return child(start()); }
+ btree_node *&mutable_child(int i) { return GetField<3>()[i]; }
+ void clear_child(int i) {
+ absl::container_internal::SanitizerPoisonObject(&mutable_child(i));
+ }
+ void set_child(int i, btree_node *c) {
+ absl::container_internal::SanitizerUnpoisonObject(&mutable_child(i));
+ mutable_child(i) = c;
+ c->set_position(i);
+ }
+ void init_child(int 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<int, 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>
+ int 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<int, 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<int, 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<int, false> linear_search_impl(
+ const K &k, int s, const int e, const Compare &comp,
+ std::false_type /* IsCompareTo */) const {
+ while (s < e) {
+ if (!comp(key(s), k)) {
+ break;
+ }
+ ++s;
+ }
+ return SearchResult<int, 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<int, true> linear_search_impl(
+ const K &k, int s, const int 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<int, false> binary_search_impl(
+ const K &k, int s, int e, const Compare &comp,
+ std::false_type /* IsCompareTo */) const {
+ while (s != e) {
+ const int mid = (s + e) >> 1;
+ if (comp(key(mid), k)) {
+ s = mid + 1;
+ } else {
+ e = mid;
+ }
+ }
+ return SearchResult<int, 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<int, true> binary_search_impl(
+ const K &k, int s, int 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 int 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 int 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};
+ }
+ }
+
+ // 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(size_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(int to_move, btree_node *right,
+ allocator_type *alloc);
+ void rebalance_left_to_right(int 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(btree_node *parent, int max_count) {
+ set_parent(parent);
+ set_position(0);
+ 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(btree_node *parent) {
+ init_leaf(parent, kNodeSlots);
+ // 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::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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ for (slot_type *src = src_node->slot(src_i + n - 1), *end = src - n,
+ *dest = slot(dest_i + n - 1);
+ src != end; --src, --dest) {
+ transfer(dest, src, alloc);
+ }
+ }
+
+ template <typename P>
+ friend class btree;
+ template <typename N, typename R, typename P>
+ friend struct btree_iterator;
+ friend class BtreeNodePeer;
+};
+
+template <typename Node, typename Reference, typename Pointer>
+struct btree_iterator {
+ private:
+ 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;
+
+ using iterator =
+ btree_iterator<normal_node, normal_reference, normal_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() : node(nullptr), position(-1) {}
+ explicit btree_iterator(Node *n) : node(n), position(n->start()) {}
+ btree_iterator(Node *n, int p) : 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
+ : node(other.node), position(other.position) {}
+
+ private:
+ // 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)
+ : node(const_cast<node_type *>(other.node)), position(other.position) {}
+
+ // Increment/decrement the iterator.
+ void increment() {
+ if (node->leaf() && ++position < node->finish()) {
+ return;
+ }
+ increment_slow();
+ }
+ void increment_slow();
+
+ void decrement() {
+ if (node->leaf() && --position >= node->start()) {
+ return;
+ }
+ decrement_slow();
+ }
+ void decrement_slow();
+
+ public:
+ bool operator==(const iterator &other) const {
+ return node == other.node && position == other.position;
+ }
+ bool operator==(const const_iterator &other) const {
+ return node == other.node && position == other.position;
+ }
+ bool operator!=(const iterator &other) const {
+ return node != other.node || position != other.position;
+ }
+ bool operator!=(const const_iterator &other) const {
+ return node != other.node || position != other.position;
+ }
+
+ // Accessors for the key/value the iterator is pointing at.
+ reference operator*() const {
+ ABSL_HARDENING_ASSERT(node != nullptr);
+ ABSL_HARDENING_ASSERT(node->start() <= position);
+ ABSL_HARDENING_ASSERT(node->finish() > position);
+ return node->value(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;
+
+ const key_type &key() const { return node->key(position); }
+ slot_type *slot() { return node->slot(position); }
+
+ // 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 init_type = typename Params::init_type;
+ 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 alignas(node_type::Alignment()) EmptyNodeType : node_type {
+ using field_type = typename node_type::field_type;
+ node_type *parent;
+ 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;
+
+#ifdef _MSC_VER
+ // MSVC has constexpr code generations bugs here.
+ EmptyNodeType() : parent(this) {}
+#else
+ constexpr EmptyNodeType(node_type *p) : parent(p) {}
+#endif
+ };
+
+ static node_type *EmptyNode() {
+#ifdef _MSC_VER
+ static EmptyNodeType *empty_node = new EmptyNodeType;
+ // This assert fails on some other construction methods.
+ assert(empty_node->parent == empty_node);
+ return empty_node;
+#else
+ static constexpr EmptyNodeType empty_node(
+ const_cast<EmptyNodeType *>(&empty_node));
+ return const_cast<EmptyNodeType *>(&empty_node);
+#endif
+ }
+
+ 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 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:
+ // For use in copy_or_move_values_in_order.
+ const value_type &maybe_move_from_iterator(const_iterator it) { return *it; }
+ value_type &&maybe_move_from_iterator(iterator it) {
+ // This is a destructive operation on the other container so it's safe for
+ // us to const_cast and move from the keys here even if it's a set.
+ return std::move(const_cast<value_type &>(*it));
+ }
+
+ // 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_(comp, alloc, EmptyNode()), rightmost_(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::move(other.root_)),
+ rightmost_(absl::exchange(other.rightmost_, EmptyNode())),
+ size_(absl::exchange(other.size_, 0)) {
+ other.mutable_root() = 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 root_.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(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.
+ 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:
+ // Internal accessor routines.
+ node_type *root() { return root_.template get<2>(); }
+ const node_type *root() const { return root_.template get<2>(); }
+ node_type *&mutable_root() noexcept { return root_.template get<2>(); }
+ key_compare *mutable_key_comp() noexcept { return &root_.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 &root_.template get<1>();
+ }
+ const allocator_type &allocator() const noexcept {
+ return root_.template get<1>();
+ }
+
+ // Allocates a correctly aligned node of at least size bytes using the
+ // allocator.
+ node_type *allocate(const 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(node_type *parent) {
+ node_type *n = allocate(node_type::InternalSize());
+ n->init_internal(parent);
+ return n;
+ }
+ node_type *new_leaf_node(node_type *parent) {
+ node_type *n = allocate(node_type::LeafSize());
+ n->init_leaf(parent, kNodeSlots);
+ return n;
+ }
+ node_type *new_leaf_root_node(const int max_count) {
+ node_type *n = allocate(node_type::LeafSize(max_count));
+ n->init_leaf(/*parent=*/n, max_count);
+ 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.
+ int 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->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;
+ }
+
+ // 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 *>
+ root_;
+
+ // A pointer to the rightmost node. Note that the leftmost node is stored as
+ // the root's parent.
+ 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 size_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(i, alloc, std::forward<Args>(args)...);
+ set_finish(finish() + 1);
+
+ if (!leaf() && finish() > i + 1) {
+ for (int 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 (!leaf()) {
+ // Delete all children between begin and end.
+ for (int j = 0; j < to_erase; ++j) {
+ clear_and_delete(child(i + j + 1), alloc);
+ }
+ // Rotate children after end into new positions.
+ for (int 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(const int 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 (!leaf()) {
+ // Move the child pointers from the right to the left node.
+ for (int i = 0; i < to_move; ++i) {
+ init_child(finish() + i + 1, right->child(i));
+ }
+ for (int 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(const int 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 (!leaf()) {
+ // Move the child pointers from the left to the right node.
+ for (int i = right->finish(); i >= right->start(); --i) {
+ right->init_child(i + to_move, right->child(i));
+ right->clear_child(i);
+ }
+ for (int 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);
+
+ // 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()->init_child(position() + 1, dest);
+
+ if (!leaf()) {
+ for (int 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 (!leaf()) {
+ // Move the child pointers from the right to the left node.
+ for (int 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->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->leaf()) node = node->start_child();
+ // Use `int` because `pos` needs to be able to hold `kNodeSlots+1`, which
+ // isn't guaranteed to be a valid `field_type`.
+ int 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(pos);
+ if (!node->leaf()) {
+ // Navigate to the leftmost leaf under node.
+ while (!node->leaf()) node = node->start_child();
+ pos = node->position();
+ parent = node->parent();
+ }
+ node->value_destroy_n(node->start(), node->count(), alloc);
+ 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) return;
+ ++pos;
+ } while (pos > parent->finish());
+ }
+}
+
+////
+// btree_iterator methods
+template <typename N, typename R, typename P>
+void btree_iterator<N, R, P>::increment_slow() {
+ if (node->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(position + 1);
+ while (!node->leaf()) {
+ node = node->start_child();
+ }
+ position = node->start();
+ }
+}
+
+template <typename N, typename R, typename P>
+void btree_iterator<N, R, P>::decrement_slow() {
+ if (node->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(position);
+ while (!node->leaf()) {
+ 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(maybe_move_from_iterator(iter));
+ ++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(), maybe_move_from_iterator(iter));
+ }
+}
+
+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(type_traits_internal::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.
+ using compare_result_type =
+ absl::result_of_t<key_compare(key_type, key_type)>;
+ static_assert(
+ std::is_same<compare_result_type, bool>::value ||
+ std::is_convertible<compare_result_type, absl::weak_ordering>::value,
+ "key comparison function must return absl::{weak,strong}_ordering or "
+ "bool.");
+
+ // Test the assumption made in setting kNodeValueSpace.
+ 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() = 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) {
+ init_type value(*b);
+ insert_hint_unique(end(), params_type::key(value), std::move(value));
+ }
+}
+
+template <typename P>
+template <typename ValueType>
+auto btree<P>::insert_multi(const key_type &key, ValueType &&v) -> iterator {
+ if (empty()) {
+ mutable_root() = 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_copy_assignment::value) {
+ // Note: `root_` also contains the allocator and the key comparator.
+ swap(root_, other.root_);
+ 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(rightmost_, other.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 {
+ bool internal_delete = false;
+ if (!iter.node->leaf()) {
+ // Deletion of a value on an internal node. First, move the largest value
+ // from our left child here, then delete that position (in remove_values()
+ // below). We can get to the largest value from our left child by
+ // decrementing iter.
+ iterator internal_iter(iter);
+ --iter;
+ assert(iter.node->leaf());
+ params_type::move(mutable_allocator(), iter.node->slot(iter.position),
+ internal_iter.node->slot(internal_iter.position));
+ internal_delete = true;
+ }
+
+ // Delete the key from the leaf.
+ iter.node->remove_values(iter.position, /*to_erase=*/1, mutable_allocator());
+ --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();
+ }
+
+ // 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;
+}
+
+template <typename P>
+auto btree<P>::erase_range(iterator begin, iterator end)
+ -> std::pair<size_type, iterator> {
+ difference_type count = std::distance(begin, end);
+ assert(count >= 0);
+
+ if (count == 0) {
+ return {0, begin};
+ }
+
+ if (count == size_) {
+ clear();
+ return {count, this->end()};
+ }
+
+ if (begin.node == end.node) {
+ assert(end.position > begin.position);
+ begin.node->remove_values(begin.position, 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->leaf()) {
+ const size_type remaining_to_erase = size_ - target_size;
+ const size_type remaining_in_node = begin.node->finish() - begin.position;
+ const size_type to_erase =
+ (std::min)(remaining_to_erase, remaining_in_node);
+ begin.node->remove_values(begin.position, to_erase, mutable_allocator());
+ size_ -= to_erase;
+ begin = rebalance_after_delete(begin);
+ } else {
+ begin = erase(begin);
+ }
+ }
+ return {count, begin};
+}
+
+template <typename P>
+void btree<P>::clear() {
+ if (!empty()) {
+ node_type::clear_and_delete(root(), mutable_allocator());
+ }
+ mutable_root() = EmptyNode();
+ 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: `root_` also contains the allocator and the key comparator.
+ swap(root_, other.root_);
+ } else {
+ // It's undefined behavior if the allocators are unequal here.
+ assert(allocator() == other.allocator());
+ swap(mutable_root(), other.mutable_root());
+ swap(*mutable_key_comp(), *other.mutable_key_comp());
+ }
+ swap(rightmost_, other.rightmost_);
+ 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()->leaf());
+ assert(rightmost_->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.
+ int to_move = (kNodeSlots - left->count()) /
+ (1 + (insert_position < static_cast<int>(kNodeSlots)));
+ to_move = (std::max)(1, to_move);
+
+ if (insert_position - to_move >= node->start() ||
+ left->count() + to_move < static_cast<int>(kNodeSlots)) {
+ left->rebalance_right_to_left(to_move, node, mutable_allocator());
+
+ assert(node->max_count() - node->count() == to_move);
+ insert_position = 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.
+ int to_move = (static_cast<int>(kNodeSlots) - right->count()) /
+ (1 + (insert_position > node->start()));
+ to_move = (std::max)(1, to_move);
+
+ if (insert_position <= node->finish() - to_move ||
+ right->count() + to_move < static_cast<int>(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(node->parent(), node->position());
+ rebalance_or_split(&parent_iter);
+ }
+ } 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(parent);
+ parent->init_child(parent->start(), root());
+ mutable_root() = parent;
+ // If the former root was a leaf node, then it's now the rightmost node.
+ assert(!parent->start_child()->leaf() ||
+ parent->start_child() == rightmost_);
+ }
+
+ // Split the node.
+ node_type *split_node;
+ if (node->leaf()) {
+ split_node = new_leaf_node(parent);
+ node->split(insert_position, split_node, mutable_allocator());
+ if (rightmost_ == node) rightmost_ = split_node;
+ } else {
+ split_node = new_internal_node(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) 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())) {
+ int to_move = (right->count() - iter->node->count()) / 2;
+ to_move = (std::min)(to_move, 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())) {
+ int to_move = (left->count() - iter->node->count()) / 2;
+ to_move = (std::min)(to_move, 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->leaf()) {
+ assert(size() == 0);
+ mutable_root() = 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->leaf()) {
+ iter.node = nullptr;
+ break;
+ }
+ }
+ return iter;
+}
+
+template <typename P>
+template <typename... Args>
+inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
+ -> iterator {
+ if (!iter.node->leaf()) {
+ // 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();
+ 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.
+ assert(iter.node == root());
+ iter.node =
+ new_leaf_root_node((std::min<int>)(kNodeSlots, 2 * max_count));
+ // Transfer the values from the old root to the new root.
+ node_type *old_root = root();
+ node_type *new_root = iter.node;
+ new_root->transfer_n(old_root->count(), new_root->start(),
+ old_root->start(), old_root, alloc);
+ new_root->set_finish(old_root->finish());
+ old_root->set_finish(old_root->start());
+ node_type::clear_and_delete(old_root, alloc);
+ mutable_root() = rightmost_ = new_root;
+ } else {
+ rebalance_or_split(&iter);
+ }
+ }
+ iter.node->emplace_value(iter.position, alloc, std::forward<Args>(args)...);
+ ++size_;
+ 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<int, is_key_compare_to::value> res =
+ iter.node->lower_bound(key, key_comp());
+ iter.position = 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->leaf()) {
+ break;
+ }
+ iter.node = iter.node->child(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<int, is_key_compare_to::value> res;
+ bool seen_eq = false;
+ for (;;) {
+ res = iter.node->lower_bound(key, key_comp());
+ iter.position = res.value;
+ if (iter.node->leaf()) {
+ break;
+ }
+ seen_eq = seen_eq || res.IsEq();
+ iter.node = iter.node->child(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 = iter.node->upper_bound(key, key_comp());
+ if (iter.node->leaf()) {
+ break;
+ }
+ iter.node = iter.node->child(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>
+int 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)));
+ }
+ int count = node->count();
+ if (!node->leaf()) {
+ for (int 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;
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_BTREE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree_container.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree_container.h
new file mode 100644
index 00000000000..03be708e4fd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/btree_container.h
@@ -0,0 +1,682 @@
+// 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/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<IsTransparent<typename Tree::key_compare>::value>::
+ 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::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;
+
+ // 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() { return tree_.begin(); }
+ const_iterator begin() const { return tree_.begin(); }
+ const_iterator cbegin() const { return tree_.begin(); }
+ iterator end() { return tree_.end(); }
+ const_iterator end() const { return tree_.end(); }
+ const_iterator cend() const { return tree_.end(); }
+ reverse_iterator rbegin() { return tree_.rbegin(); }
+ const_reverse_iterator rbegin() const { return tree_.rbegin(); }
+ const_reverse_iterator crbegin() const { return tree_.rbegin(); }
+ reverse_iterator rend() { return tree_.rend(); }
+ const_reverse_iterator rend() const { return tree_.rend(); }
+ const_reverse_iterator crend() const { 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 std::distance(equal_range.first, equal_range.second);
+ }
+ template <typename K = key_type>
+ iterator find(const key_arg<K> &key) {
+ return tree_.find(key);
+ }
+ template <typename K = key_type>
+ const_iterator find(const key_arg<K> &key) const {
+ 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) {
+ return tree_.lower_bound(key);
+ }
+ template <typename K = key_type>
+ const_iterator lower_bound(const key_arg<K> &key) const {
+ return tree_.lower_bound(key);
+ }
+ template <typename K = key_type>
+ iterator upper_bound(const key_arg<K> &key) {
+ return tree_.upper_bound(key);
+ }
+ template <typename K = key_type>
+ const_iterator upper_bound(const key_arg<K> &key) const {
+ return tree_.upper_bound(key);
+ }
+ template <typename K = key_type>
+ std::pair<iterator, iterator> equal_range(const key_arg<K> &key) {
+ return tree_.equal_range(key);
+ }
+ template <typename K = key_type>
+ std::pair<const_iterator, const_iterator> equal_range(
+ const key_arg<K> &key) const {
+ 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) { return tree_.erase(iterator(iter)); }
+ iterator erase(iterator iter) { return tree_.erase(iter); }
+ iterator erase(const_iterator first, const_iterator last) {
+ 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.
+ node_type extract(iterator position) {
+ // Use Move instead of Transfer, because the rebalancing code expects to
+ // have a valid object to scribble metadata bits on top of.
+ auto node = CommonAccess::Move<node_type>(get_allocator(), position.slot());
+ erase(position);
+ return node;
+ }
+ node_type extract(const_iterator position) {
+ return extract(iterator(position));
+ }
+
+ // Utility routines.
+ 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 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:
+ 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::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) {
+ return this->tree_.insert_unique(params_type::key(v), v);
+ }
+ std::pair<iterator, bool> insert(value_type &&v) {
+ return this->tree_.insert_unique(params_type::key(v), std::move(v));
+ }
+ template <typename... Args>
+ std::pair<iterator, bool> emplace(Args &&... args) {
+ init_type v(std::forward<Args>(args)...);
+ return this->tree_.insert_unique(params_type::key(v), std::move(v));
+ }
+ iterator insert(const_iterator hint, const value_type &v) {
+ return this->tree_
+ .insert_hint_unique(iterator(hint), params_type::key(v), v)
+ .first;
+ }
+ iterator insert(const_iterator hint, value_type &&v) {
+ 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) {
+ init_type v(std::forward<Args>(args)...);
+ return this->tree_
+ .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
+ .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) {
+ 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) {
+ 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::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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ return try_emplace(k).first->second;
+ }
+ template <typename K = key_type>
+ mapped_type &operator[](key_arg<K> &&k) {
+ return try_emplace(std::forward<K>(k)).first->second;
+ }
+
+ template <typename K = key_type>
+ mapped_type &at(const key_arg<K> &key) {
+ 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 {
+ 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;
+
+ 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::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) { return this->tree_.insert_multi(v); }
+ iterator insert(value_type &&v) {
+ return this->tree_.insert_multi(std::move(v));
+ }
+ iterator insert(const_iterator hint, const value_type &v) {
+ return this->tree_.insert_hint_multi(iterator(hint), v);
+ }
+ iterator insert(const_iterator hint, value_type &&v) {
+ 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) {
+ return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
+ }
+ template <typename... Args>
+ iterator emplace_hint(const_iterator hint, Args &&... args) {
+ return this->tree_.insert_hint_multi(
+ iterator(hint), init_type(std::forward<Args>(args)...));
+ }
+ iterator insert(node_type &&node) {
+ 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) {
+ 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;
+
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/common.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/common.h
new file mode 100644
index 00000000000..030e9d4ab07
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/common.h
@@ -0,0 +1,206 @@
+// 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_CONTAINER_H_
+#define ABSL_CONTAINER_INTERNAL_CONTAINER_H_
+
+#include <cassert>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+template <class, class = void>
+struct IsTransparent : std::false_type {};
+template <class T>
+struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
+ : std::true_type {};
+
+template <bool is_transparent>
+struct KeyArg {
+ // Transparent. Forward `K`.
+ template <typename K, typename key_type>
+ using type = K;
+};
+
+template <>
+struct KeyArg<false> {
+ // Not transparent. Always use `key_type`.
+ template <typename K, typename key_type>
+ using type = key_type;
+};
+
+// The node_handle concept from C++17.
+// We specialize node_handle for sets and maps. node_handle_base holds the
+// common API of both.
+template <typename PolicyTraits, typename Alloc>
+class node_handle_base {
+ protected:
+ using slot_type = typename PolicyTraits::slot_type;
+
+ public:
+ using allocator_type = Alloc;
+
+ constexpr node_handle_base() = default;
+ node_handle_base(node_handle_base&& other) noexcept {
+ *this = std::move(other);
+ }
+ ~node_handle_base() { destroy(); }
+ node_handle_base& operator=(node_handle_base&& other) noexcept {
+ destroy();
+ if (!other.empty()) {
+ alloc_ = other.alloc_;
+ PolicyTraits::transfer(alloc(), slot(), other.slot());
+ other.reset();
+ }
+ return *this;
+ }
+
+ bool empty() const noexcept { return !alloc_; }
+ explicit operator bool() const noexcept { return !empty(); }
+ allocator_type get_allocator() const { return *alloc_; }
+
+ protected:
+ friend struct CommonAccess;
+
+ struct transfer_tag_t {};
+ node_handle_base(transfer_tag_t, const allocator_type& a, slot_type* s)
+ : alloc_(a) {
+ PolicyTraits::transfer(alloc(), slot(), s);
+ }
+
+ struct move_tag_t {};
+ node_handle_base(move_tag_t, const allocator_type& a, slot_type* s)
+ : alloc_(a) {
+ PolicyTraits::construct(alloc(), slot(), s);
+ }
+
+ void destroy() {
+ if (!empty()) {
+ PolicyTraits::destroy(alloc(), slot());
+ reset();
+ }
+ }
+
+ void reset() {
+ assert(alloc_.has_value());
+ alloc_ = absl::nullopt;
+ }
+
+ slot_type* slot() const {
+ assert(!empty());
+ return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
+ }
+ allocator_type* alloc() { return std::addressof(*alloc_); }
+
+ private:
+ absl::optional<allocator_type> alloc_ = {};
+ alignas(slot_type) mutable unsigned char slot_space_[sizeof(slot_type)] = {};
+};
+
+// For sets.
+template <typename Policy, typename PolicyTraits, typename Alloc,
+ typename = void>
+class node_handle : public node_handle_base<PolicyTraits, Alloc> {
+ using Base = node_handle_base<PolicyTraits, Alloc>;
+
+ public:
+ using value_type = typename PolicyTraits::value_type;
+
+ constexpr node_handle() {}
+
+ value_type& value() const { return PolicyTraits::element(this->slot()); }
+
+ private:
+ friend struct CommonAccess;
+
+ using Base::Base;
+};
+
+// For maps.
+template <typename Policy, typename PolicyTraits, typename Alloc>
+class node_handle<Policy, PolicyTraits, Alloc,
+ absl::void_t<typename Policy::mapped_type>>
+ : public node_handle_base<PolicyTraits, Alloc> {
+ using Base = node_handle_base<PolicyTraits, Alloc>;
+ using slot_type = typename PolicyTraits::slot_type;
+
+ public:
+ using key_type = typename Policy::key_type;
+ using mapped_type = typename Policy::mapped_type;
+
+ constexpr node_handle() {}
+
+ // When C++17 is available, we can use std::launder to provide mutable
+ // access to the key. Otherwise, we provide const access.
+ auto key() const
+ -> decltype(PolicyTraits::mutable_key(std::declval<slot_type*>())) {
+ return PolicyTraits::mutable_key(this->slot());
+ }
+
+ mapped_type& mapped() const {
+ return PolicyTraits::value(&PolicyTraits::element(this->slot()));
+ }
+
+ private:
+ friend struct CommonAccess;
+
+ using Base::Base;
+};
+
+// Provide access to non-public node-handle functions.
+struct CommonAccess {
+ template <typename Node>
+ static auto GetSlot(const Node& node) -> decltype(node.slot()) {
+ return node.slot();
+ }
+
+ template <typename Node>
+ static void Destroy(Node* node) {
+ node->destroy();
+ }
+
+ template <typename Node>
+ static void Reset(Node* node) {
+ node->reset();
+ }
+
+ template <typename T, typename... Args>
+ static T Transfer(Args&&... args) {
+ return T(typename T::transfer_tag_t{}, std::forward<Args>(args)...);
+ }
+
+ template <typename T, typename... Args>
+ static T Move(Args&&... args) {
+ return T(typename T::move_tag_t{}, std::forward<Args>(args)...);
+ }
+};
+
+// Implement the insert_return_type<> concept of C++17.
+template <class Iterator, class NodeType>
+struct InsertReturnType {
+ Iterator position;
+ bool inserted;
+ NodeType node;
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple.h
index b883ae2657e..5ebe1649424 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,26 +27,28 @@
// const T2& t2 = value.get<2>();
// ...
//
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
#ifndef ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
#define ABSL_CONTAINER_INTERNAL_COMPRESSED_TUPLE_H_
+#include <initializer_list>
#include <tuple>
#include <type_traits>
#include <utility>
#include "absl/utility/utility.h"
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && !defined(__NVCC__)
// We need to mark these classes with this declspec to ensure that
// CompressedTuple happens.
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC __declspec(empty_bases)
-#else // _MSC_VER
+#else
#define ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
-#endif // _MSC_VER
+#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <typename... Ts>
@@ -75,61 +77,134 @@ constexpr bool IsFinal() {
#endif
}
+// We can't use EBCO on other CompressedTuples because that would mean that we
+// derive from multiple Storage<> instantiations with the same I parameter,
+// and potentially from multiple identical Storage<> instantiations. So anytime
+// we use type inheritance rather than encapsulation, we mark
+// CompressedTupleImpl, to make this easy to detect.
+struct uses_inheritance {};
+
template <typename T>
constexpr bool ShouldUseBase() {
- return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>();
+ return std::is_class<T>::value && std::is_empty<T>::value && !IsFinal<T>() &&
+ !std::is_base_of<uses_inheritance, T>::value;
}
// The storage class provides two specializations:
// - For empty classes, it stores T as a base class.
// - For everything else, it stores T as a member.
-template <typename D, size_t I, bool = ShouldUseBase<ElemT<D, I>>()>
+template <typename T, size_t I,
+#if defined(_MSC_VER)
+ bool UseBase =
+ ShouldUseBase<typename std::enable_if<true, T>::type>()>
+#else
+ bool UseBase = ShouldUseBase<T>()>
+#endif
struct Storage {
- using T = ElemT<D, I>;
T value;
constexpr Storage() = default;
- explicit constexpr Storage(T&& v) : value(absl::forward<T>(v)) {}
+ template <typename V>
+ explicit constexpr Storage(absl::in_place_t, V&& v)
+ : value(absl::forward<V>(v)) {}
constexpr const T& get() const& { return value; }
T& get() & { return value; }
constexpr const T&& get() const&& { return absl::move(*this).value; }
T&& get() && { return std::move(*this).value; }
};
-template <typename D, size_t I>
-struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<D, I, true>
- : ElemT<D, I> {
- using T = internal_compressed_tuple::ElemT<D, I>;
+template <typename T, size_t I>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC Storage<T, I, true> : T {
constexpr Storage() = default;
- explicit constexpr Storage(T&& v) : T(absl::forward<T>(v)) {}
+
+ template <typename V>
+ explicit constexpr Storage(absl::in_place_t, V&& v)
+ : T(absl::forward<V>(v)) {}
+
constexpr const T& get() const& { return *this; }
T& get() & { return *this; }
constexpr const T&& get() const&& { return absl::move(*this); }
T&& get() && { return std::move(*this); }
};
-template <typename D, typename I>
+template <typename D, typename I, bool ShouldAnyUseBase>
struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl;
-template <typename... Ts, size_t... I>
-struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
- CompressedTupleImpl<CompressedTuple<Ts...>, absl::index_sequence<I...>>
+template <typename... Ts, size_t... I, bool ShouldAnyUseBase>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
+ CompressedTuple<Ts...>, absl::index_sequence<I...>, ShouldAnyUseBase>
// We use the dummy identity function through std::integral_constant to
// convince MSVC of accepting and expanding I in that context. Without it
// you would get:
// error C3548: 'I': parameter pack cannot be used in this context
- : Storage<CompressedTuple<Ts...>,
- std::integral_constant<size_t, I>::value>... {
+ : uses_inheritance,
+ Storage<Ts, std::integral_constant<size_t, I>::value>... {
constexpr CompressedTupleImpl() = default;
- explicit constexpr CompressedTupleImpl(Ts&&... args)
- : Storage<CompressedTuple<Ts...>, I>(absl::forward<Ts>(args))... {}
+ template <typename... Vs>
+ explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
+ : Storage<Ts, I>(absl::in_place, absl::forward<Vs>(args))... {}
+ friend CompressedTuple<Ts...>;
};
+template <typename... Ts, size_t... I>
+struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTupleImpl<
+ CompressedTuple<Ts...>, absl::index_sequence<I...>, false>
+ // We use the dummy identity function as above...
+ : Storage<Ts, std::integral_constant<size_t, I>::value, false>... {
+ constexpr CompressedTupleImpl() = default;
+ template <typename... Vs>
+ explicit constexpr CompressedTupleImpl(absl::in_place_t, Vs&&... args)
+ : Storage<Ts, I, false>(absl::in_place, absl::forward<Vs>(args))... {}
+ friend CompressedTuple<Ts...>;
+};
+
+std::false_type Or(std::initializer_list<std::false_type>);
+std::true_type Or(std::initializer_list<bool>);
+
+// MSVC requires this to be done separately rather than within the declaration
+// of CompressedTuple below.
+template <typename... Ts>
+constexpr bool ShouldAnyUseBase() {
+ return decltype(
+ Or({std::integral_constant<bool, ShouldUseBase<Ts>()>()...})){};
+}
+
+template <typename T, typename V>
+using TupleElementMoveConstructible =
+ typename std::conditional<std::is_reference<T>::value,
+ std::is_convertible<V, T>,
+ std::is_constructible<T, V&&>>::type;
+
+template <bool SizeMatches, class T, class... Vs>
+struct TupleMoveConstructible : std::false_type {};
+
+template <class... Ts, class... Vs>
+struct TupleMoveConstructible<true, CompressedTuple<Ts...>, Vs...>
+ : std::integral_constant<
+ bool, absl::conjunction<
+ TupleElementMoveConstructible<Ts, Vs&&>...>::value> {};
+
+template <typename T>
+struct compressed_tuple_size;
+
+template <typename... Es>
+struct compressed_tuple_size<CompressedTuple<Es...>>
+ : public std::integral_constant<std::size_t, sizeof...(Es)> {};
+
+template <class T, class... Vs>
+struct TupleItemsMoveConstructible
+ : std::integral_constant<
+ bool, TupleMoveConstructible<compressed_tuple_size<T>::value ==
+ sizeof...(Vs),
+ T, Vs...>::value> {};
+
} // namespace internal_compressed_tuple
// Helper class to perform the Empty Base Class Optimization.
// Ts can contain classes and non-classes, empty or not. For the ones that
// are empty classes, we perform the CompressedTuple. If all types in Ts are
-// empty classes, then CompressedTuple<Ts...> is itself an empty class.
+// empty classes, then CompressedTuple<Ts...> is itself an empty class. (This
+// does not apply when one or more of those empty classes is itself an empty
+// CompressedTuple.)
//
// To access the members, use member .get<N>() function.
//
@@ -141,40 +216,63 @@ struct ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
// const T2& t2 = value.get<2>();
// ...
//
-// http://en.cppreference.com/w/cpp/language/ebo
+// https://en.cppreference.com/w/cpp/language/ebo
template <typename... Ts>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
: private internal_compressed_tuple::CompressedTupleImpl<
- CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>> {
+ CompressedTuple<Ts...>, absl::index_sequence_for<Ts...>,
+ internal_compressed_tuple::ShouldAnyUseBase<Ts...>()> {
private:
template <int I>
using ElemT = internal_compressed_tuple::ElemT<CompressedTuple, I>;
+ template <int I>
+ using StorageT = internal_compressed_tuple::Storage<ElemT<I>, I>;
+
public:
+ // There seems to be a bug in MSVC dealing in which using '=default' here will
+ // cause the compiler to ignore the body of other constructors. The work-
+ // around is to explicitly implement the default constructor.
+#if defined(_MSC_VER)
+ constexpr CompressedTuple() : CompressedTuple::CompressedTupleImpl() {}
+#else
constexpr CompressedTuple() = default;
- explicit constexpr CompressedTuple(Ts... base)
- : CompressedTuple::CompressedTupleImpl(absl::forward<Ts>(base)...) {}
+#endif
+ explicit constexpr CompressedTuple(const Ts&... base)
+ : CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
+
+ template <typename First, typename... Vs,
+ absl::enable_if_t<
+ absl::conjunction<
+ // Ensure we are not hiding default copy/move constructors.
+ absl::negation<std::is_same<void(CompressedTuple),
+ void(absl::decay_t<First>)>>,
+ internal_compressed_tuple::TupleItemsMoveConstructible<
+ CompressedTuple<Ts...>, First, Vs...>>::value,
+ bool> = true>
+ explicit constexpr CompressedTuple(First&& first, Vs&&... base)
+ : CompressedTuple::CompressedTupleImpl(absl::in_place,
+ absl::forward<First>(first),
+ absl::forward<Vs>(base)...) {}
template <int I>
ElemT<I>& get() & {
- return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
+ return StorageT<I>::get();
}
template <int I>
constexpr const ElemT<I>& get() const& {
- return internal_compressed_tuple::Storage<CompressedTuple, I>::get();
+ return StorageT<I>::get();
}
template <int I>
ElemT<I>&& get() && {
- return std::move(*this)
- .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+ return std::move(*this).StorageT<I>::get();
}
template <int I>
constexpr const ElemT<I>&& get() const&& {
- return absl::move(*this)
- .internal_compressed_tuple::template Storage<CompressedTuple, I>::get();
+ return absl::move(*this).StorageT<I>::get();
}
};
@@ -184,6 +282,7 @@ template <>
class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple<> {};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
index 04ead100aa1..62a7483ee31 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,13 +19,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/container/internal/test_instance_tracker.h"
#include "absl/memory/memory.h"
+#include "absl/types/any.h"
+#include "absl/types/optional.h"
#include "absl/utility/utility.h"
-namespace absl {
-namespace container_internal {
-namespace {
-
+// These are declared at global scope purely so that error messages
+// are smaller and easier to understand.
enum class CallType { kConstRef, kConstMove };
template <int>
@@ -45,6 +46,15 @@ struct TwoValues {
U value2;
};
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+using absl::test_internal::CopyableMovableInstance;
+using absl::test_internal::InstanceTracker;
+
TEST(CompressedTupleTest, Sizeof) {
EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>));
EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>));
@@ -60,6 +70,141 @@ TEST(CompressedTupleTest, Sizeof) {
sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>));
}
+TEST(CompressedTupleTest, OneMoveOnRValueConstructionTemp) {
+ InstanceTracker tracker;
+ CompressedTuple<CopyableMovableInstance> x1(CopyableMovableInstance(1));
+ EXPECT_EQ(tracker.instances(), 1);
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_LE(tracker.moves(), 1);
+ EXPECT_EQ(x1.get<0>().value(), 1);
+}
+
+TEST(CompressedTupleTest, OneMoveOnRValueConstructionMove) {
+ InstanceTracker tracker;
+
+ CopyableMovableInstance i1(1);
+ CompressedTuple<CopyableMovableInstance> x1(std::move(i1));
+ EXPECT_EQ(tracker.instances(), 2);
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_LE(tracker.moves(), 1);
+ EXPECT_EQ(x1.get<0>().value(), 1);
+}
+
+TEST(CompressedTupleTest, OneMoveOnRValueConstructionMixedTypes) {
+ InstanceTracker tracker;
+ CopyableMovableInstance i1(1);
+ CopyableMovableInstance i2(2);
+ Empty<0> empty;
+ CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>>
+ x1(std::move(i1), i2, empty);
+ EXPECT_EQ(x1.get<0>().value(), 1);
+ EXPECT_EQ(x1.get<1>().value(), 2);
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+}
+
+struct IncompleteType;
+CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>>
+MakeWithIncomplete(CopyableMovableInstance i1,
+ IncompleteType& t, // NOLINT
+ Empty<0> empty) {
+ return CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>>{
+ std::move(i1), t, empty};
+}
+
+struct IncompleteType {};
+TEST(CompressedTupleTest, OneMoveOnRValueConstructionWithIncompleteType) {
+ InstanceTracker tracker;
+ CopyableMovableInstance i1(1);
+ Empty<0> empty;
+ struct DerivedType : IncompleteType {int value = 0;};
+ DerivedType fd;
+ fd.value = 7;
+
+ CompressedTuple<CopyableMovableInstance, IncompleteType&, Empty<0>> x1 =
+ MakeWithIncomplete(std::move(i1), fd, empty);
+
+ EXPECT_EQ(x1.get<0>().value(), 1);
+ EXPECT_EQ(static_cast<DerivedType&>(x1.get<1>()).value, 7);
+
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 2);
+}
+
+TEST(CompressedTupleTest,
+ OneMoveOnRValueConstructionMixedTypes_BraceInitPoisonPillExpected) {
+ InstanceTracker tracker;
+ CopyableMovableInstance i1(1);
+ CopyableMovableInstance i2(2);
+ CompressedTuple<CopyableMovableInstance, CopyableMovableInstance&, Empty<0>>
+ x1(std::move(i1), i2, {}); // NOLINT
+ EXPECT_EQ(x1.get<0>().value(), 1);
+ EXPECT_EQ(x1.get<1>().value(), 2);
+ EXPECT_EQ(tracker.instances(), 3);
+ // We are forced into the `const Ts&...` constructor (invoking copies)
+ // because we need it to deduce the type of `{}`.
+ // std::tuple also has this behavior.
+ // Note, this test is proof that this is expected behavior, but it is not
+ // _desired_ behavior.
+ EXPECT_EQ(tracker.copies(), 1);
+ EXPECT_EQ(tracker.moves(), 0);
+}
+
+TEST(CompressedTupleTest, OneCopyOnLValueConstruction) {
+ InstanceTracker tracker;
+ CopyableMovableInstance i1(1);
+
+ CompressedTuple<CopyableMovableInstance> x1(i1);
+ EXPECT_EQ(tracker.copies(), 1);
+ EXPECT_EQ(tracker.moves(), 0);
+
+ tracker.ResetCopiesMovesSwaps();
+
+ CopyableMovableInstance i2(2);
+ const CopyableMovableInstance& i2_ref = i2;
+ CompressedTuple<CopyableMovableInstance> x2(i2_ref);
+ EXPECT_EQ(tracker.copies(), 1);
+ EXPECT_EQ(tracker.moves(), 0);
+}
+
+TEST(CompressedTupleTest, OneMoveOnRValueAccess) {
+ InstanceTracker tracker;
+ CopyableMovableInstance i1(1);
+ CompressedTuple<CopyableMovableInstance> x(std::move(i1));
+ tracker.ResetCopiesMovesSwaps();
+
+ CopyableMovableInstance i2 = std::move(x).get<0>();
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(CompressedTupleTest, OneCopyOnLValueAccess) {
+ InstanceTracker tracker;
+
+ CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0));
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+
+ CopyableMovableInstance t = x.get<0>();
+ EXPECT_EQ(tracker.copies(), 1);
+ EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(CompressedTupleTest, ZeroCopyOnRefAccess) {
+ InstanceTracker tracker;
+
+ CompressedTuple<CopyableMovableInstance> x(CopyableMovableInstance(0));
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+
+ CopyableMovableInstance& t1 = x.get<0>();
+ const CopyableMovableInstance& t2 = x.get<0>();
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+ EXPECT_EQ(t1.value(), 0);
+ EXPECT_EQ(t2.value(), 0);
+}
+
TEST(CompressedTupleTest, Access) {
struct S {
std::string x;
@@ -120,18 +265,23 @@ TEST(CompressedTupleTest, Nested) {
EXPECT_EQ(4 * sizeof(char),
sizeof(CompressedTuple<CompressedTuple<char, char>,
CompressedTuple<char, char>>));
- EXPECT_TRUE(
- (std::is_empty<CompressedTuple<CompressedTuple<Empty<0>>,
- CompressedTuple<Empty<1>>>>::value));
+ EXPECT_TRUE((std::is_empty<CompressedTuple<Empty<0>, Empty<1>>>::value));
+
+ // Make sure everything still works when things are nested.
+ struct CT_Empty : CompressedTuple<Empty<0>> {};
+ CompressedTuple<Empty<0>, CT_Empty> nested_empty;
+ auto contained = nested_empty.get<0>();
+ auto nested = nested_empty.get<1>().get<0>();
+ EXPECT_TRUE((std::is_same<decltype(contained), decltype(nested)>::value));
}
TEST(CompressedTupleTest, Reference) {
int i = 7;
- std::string s = "Very long std::string that goes in the heap";
+ std::string s = "Very long string that goes in the heap";
CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);
// Sanity check. We should have not moved from `s`
- EXPECT_EQ(s, "Very long std::string that goes in the heap");
+ EXPECT_EQ(s, "Very long string that goes in the heap");
EXPECT_EQ(x.get<0>(), x.get<1>());
EXPECT_NE(&x.get<0>(), &x.get<1>());
@@ -166,7 +316,36 @@ TEST(CompressedTupleTest, MoveOnlyElements) {
EXPECT_EQ(*x1, 5);
}
+TEST(CompressedTupleTest, MoveConstructionMoveOnlyElements) {
+ CompressedTuple<std::unique_ptr<std::string>> base(
+ absl::make_unique<std::string>("str"));
+ EXPECT_EQ(*base.get<0>(), "str");
+
+ CompressedTuple<std::unique_ptr<std::string>> copy(std::move(base));
+ EXPECT_EQ(*copy.get<0>(), "str");
+}
+
+TEST(CompressedTupleTest, AnyElements) {
+ any a(std::string("str"));
+ CompressedTuple<any, any&> x(any(5), a);
+ EXPECT_EQ(absl::any_cast<int>(x.get<0>()), 5);
+ EXPECT_EQ(absl::any_cast<std::string>(x.get<1>()), "str");
+
+ a = 0.5f;
+ EXPECT_EQ(absl::any_cast<float>(x.get<1>()), 0.5);
+}
+
TEST(CompressedTupleTest, Constexpr) {
+ struct NonTrivialStruct {
+ constexpr NonTrivialStruct() = default;
+ constexpr int value() const { return v; }
+ int v = 5;
+ };
+ struct TrivialStruct {
+ TrivialStruct() = default;
+ constexpr int value() const { return v; }
+ int v;
+ };
constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x(
7, 1.25, CompressedTuple<int>(5), {});
constexpr int x0 = x.get<0>();
@@ -179,6 +358,32 @@ TEST(CompressedTupleTest, Constexpr) {
EXPECT_EQ(x2, 5);
EXPECT_EQ(x3, CallType::kConstRef);
+#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
+ constexpr CompressedTuple<Empty<0>, TrivialStruct, int> trivial = {};
+ constexpr CallType trivial0 = trivial.get<0>().value();
+ constexpr int trivial1 = trivial.get<1>().value();
+ constexpr int trivial2 = trivial.get<2>();
+
+ EXPECT_EQ(trivial0, CallType::kConstRef);
+ EXPECT_EQ(trivial1, 0);
+ EXPECT_EQ(trivial2, 0);
+#endif
+
+ constexpr CompressedTuple<Empty<0>, NonTrivialStruct, absl::optional<int>>
+ non_trivial = {};
+ constexpr CallType non_trivial0 = non_trivial.get<0>().value();
+ constexpr int non_trivial1 = non_trivial.get<1>().value();
+ constexpr absl::optional<int> non_trivial2 = non_trivial.get<2>();
+
+ EXPECT_EQ(non_trivial0, CallType::kConstRef);
+ EXPECT_EQ(non_trivial1, 5);
+ EXPECT_EQ(non_trivial2, absl::nullopt);
+
+ static constexpr char data[] = "DEF";
+ constexpr CompressedTuple<const char*> z(data);
+ constexpr const char* z1 = z.get<0>();
+ EXPECT_EQ(std::string(z1), std::string(data));
+
#if defined(__clang__)
// An apparent bug in earlier versions of gcc claims these are ambiguous.
constexpr int x2m = absl::move(x.get<2>()).get<0>();
@@ -200,4 +405,5 @@ TEST(CompressedTupleTest, EmptyFinalClass) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory.h
index 56c5d2df673..e67529ecb6e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,27 +15,34 @@
#ifndef ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
#define ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
-#ifdef ADDRESS_SANITIZER
-#include <sanitizer/asan_interface.h>
-#endif
-
-#ifdef MEMORY_SANITIZER
-#include <sanitizer/msan_interface.h>
-#endif
-
#include <cassert>
#include <cstddef>
#include <memory>
+#include <new>
#include <tuple>
#include <type_traits>
#include <utility>
+#include "absl/base/config.h"
#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
#include "absl/utility/utility.h"
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#include <sanitizer/msan_interface.h>
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
+template <size_t Alignment>
+struct alignas(Alignment) AlignedType {};
+
// Allocates at least n bytes aligned to the specified alignment.
// Alignment must be a power of 2. It must be positive.
//
@@ -47,11 +54,14 @@ template <size_t Alignment, class Alloc>
void* Allocate(Alloc* alloc, size_t n) {
static_assert(Alignment > 0, "");
assert(n && "n must be positive");
- struct alignas(Alignment) M {};
+ using M = AlignedType<Alignment>;
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
- A mem_alloc(*alloc);
- void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
+ // On macOS, "mem_alloc" is a #define with one argument defined in
+ // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+ // with the "foo(bar)" syntax.
+ A my_mem_alloc(*alloc);
+ void* p = AT::allocate(my_mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
"allocator does not respect alignment");
return p;
@@ -63,11 +73,14 @@ template <size_t Alignment, class Alloc>
void Deallocate(Alloc* alloc, void* p, size_t n) {
static_assert(Alignment > 0, "");
assert(n && "n must be positive");
- struct alignas(Alignment) M {};
+ using M = AlignedType<Alignment>;
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<M>;
- A mem_alloc(*alloc);
- AT::deallocate(mem_alloc, static_cast<M*>(p),
+ // On macOS, "mem_alloc" is a #define with one argument defined in
+ // rpc/types.h, so we can't name the variable "mem_alloc" and initialize it
+ // with the "foo(bar)" syntax.
+ A my_mem_alloc(*alloc);
+ AT::deallocate(my_mem_alloc, static_cast<M*>(p),
(n + sizeof(M) - 1) / sizeof(M));
}
@@ -204,10 +217,10 @@ DecomposeValue(F&& f, Arg&& arg) {
// Helper functions for asan and msan.
inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
ASAN_POISON_MEMORY_REGION(m, s);
#endif
-#ifdef MEMORY_SANITIZER
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
__msan_poison(m, s);
#endif
(void)m;
@@ -215,10 +228,10 @@ inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
}
inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(m, s);
#endif
-#ifdef MEMORY_SANITIZER
+#ifdef ABSL_HAVE_MEMORY_SANITIZER
__msan_unpoison(m, s);
#endif
(void)m;
@@ -245,8 +258,8 @@ namespace memory_internal {
// type, which is non-portable.
template <class Pair, class = std::true_type>
struct OffsetOf {
- static constexpr size_t kFirst = -1;
- static constexpr size_t kSecond = -1;
+ static constexpr size_t kFirst = static_cast<size_t>(-1);
+ static constexpr size_t kSecond = static_cast<size_t>(-1);
};
template <class Pair>
@@ -286,13 +299,49 @@ struct IsLayoutCompatible {
} // namespace memory_internal
-// If kMutableKeys is false, only the value member is accessed.
+// The internal storage type for key-value containers like flat_hash_map.
+//
+// It is convenient for the value_type of a flat_hash_map<K, V> to be
+// pair<const K, V>; the "const K" prevents accidental modification of the key
+// when dealing with the reference returned from find() and similar methods.
+// However, this creates other problems; we want to be able to emplace(K, V)
+// efficiently with move operations, and similarly be able to move a
+// pair<K, V> in insert().
+//
+// The solution is this union, which aliases the const and non-const versions
+// of the pair. This also allows flat_hash_map<const K, V> to work, even though
+// that has the same efficiency issues with move in emplace() and insert() -
+// but people do it anyway.
//
-// If kMutableKeys is true, key is accessed through all slots while value and
-// mutable_value are accessed only via INITIALIZED slots. Slots are created and
-// destroyed via mutable_value so that the key can be moved later.
+// If kMutableKeys is false, only the value member can be accessed.
+//
+// If kMutableKeys is true, key can be accessed through all slots while value
+// and mutable_value must be accessed only via INITIALIZED slots. Slots are
+// created and destroyed via mutable_value so that the key can be moved later.
+//
+// Accessing one of the union fields while the other is active is safe as
+// long as they are layout-compatible, which is guaranteed by the definition of
+// kMutableKeys. For C++11, the relevant section of the standard is
+// https://timsong-cpp.github.io/cppwp/n3337/class.mem#19 (9.2.19)
template <class K, class V>
-union slot_type {
+union map_slot_type {
+ map_slot_type() {}
+ ~map_slot_type() = delete;
+ using value_type = std::pair<const K, V>;
+ using mutable_value_type =
+ std::pair<absl::remove_const_t<K>, absl::remove_const_t<V>>;
+
+ value_type value;
+ mutable_value_type mutable_value;
+ absl::remove_const_t<K> key;
+};
+
+template <class K, class V>
+struct map_slot_policy {
+ using slot_type = map_slot_type<K, V>;
+ using value_type = std::pair<const K, V>;
+ using mutable_value_type = std::pair<K, V>;
+
private:
static void emplace(slot_type* slot) {
// The construction of union doesn't do anything at runtime but it allows us
@@ -302,19 +351,31 @@ union slot_type {
// If pair<const K, V> and pair<K, V> are layout-compatible, we can accept one
// or the other via slot_type. We are also free to access the key via
// slot_type::key in this case.
- using kMutableKeys =
- std::integral_constant<bool,
- memory_internal::IsLayoutCompatible<K, V>::value>;
+ using kMutableKeys = memory_internal::IsLayoutCompatible<K, V>;
public:
- slot_type() {}
- ~slot_type() = delete;
- using value_type = std::pair<const K, V>;
- using mutable_value_type = std::pair<K, V>;
+ static value_type& element(slot_type* slot) { return slot->value; }
+ static const value_type& element(const slot_type* slot) {
+ return slot->value;
+ }
- value_type value;
- mutable_value_type mutable_value;
- K key;
+ // When C++17 is available, we can use std::launder to provide mutable
+ // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ static K& mutable_key(slot_type* slot) {
+ // Still check for kMutableKeys so that we can avoid calling std::launder
+ // unless necessary because it can interfere with optimizations.
+ return kMutableKeys::value ? slot->key
+ : *std::launder(const_cast<K*>(
+ std::addressof(slot->value.first)));
+ }
+#else // !(defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606)
+ static const K& mutable_key(slot_type* slot) { return key(slot); }
+#endif
+
+ static const K& key(const slot_type* slot) {
+ return kMutableKeys::value ? slot->key : slot->value.first;
+ }
template <class Allocator, class... Args>
static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
@@ -390,16 +451,10 @@ union slot_type {
std::move(src->value));
}
}
-
- template <class Allocator>
- static void move(Allocator* alloc, slot_type* first, slot_type* last,
- slot_type* result) {
- for (slot_type *src = first, *dest = result; src != last; ++src, ++dest)
- move(alloc, src, dest);
- }
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_CONTAINER_MEMORY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory_test.cc
index f1c4058298c..fb9c4ddedec 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/container_memory_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,16 +16,25 @@
#include <cstdint>
#include <tuple>
+#include <typeindex>
+#include <typeinfo>
#include <utility>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/container/internal/test_instance_tracker.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
+using ::absl::test_internal::CopyableMovableInstance;
+using ::absl::test_internal::InstanceTracker;
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Gt;
using ::testing::Pair;
TEST(Memory, AlignmentLargerThanBase) {
@@ -44,6 +53,39 @@ TEST(Memory, AlignmentSmallerThanBase) {
Deallocate<2>(&alloc, mem, 3);
}
+std::map<std::type_index, int>& AllocationMap() {
+ static auto* map = new std::map<std::type_index, int>;
+ return *map;
+}
+
+template <typename T>
+struct TypeCountingAllocator {
+ TypeCountingAllocator() = default;
+ template <typename U>
+ TypeCountingAllocator(const TypeCountingAllocator<U>&) {} // NOLINT
+
+ using value_type = T;
+
+ T* allocate(size_t n, const void* = nullptr) {
+ AllocationMap()[typeid(T)] += n;
+ return std::allocator<T>().allocate(n);
+ }
+ void deallocate(T* p, std::size_t n) {
+ AllocationMap()[typeid(T)] -= n;
+ return std::allocator<T>().deallocate(p, n);
+ }
+};
+
+TEST(Memory, AllocateDeallocateMatchType) {
+ TypeCountingAllocator<int> alloc;
+ void* mem = Allocate<1>(&alloc, 1);
+ // Verify that it was allocated
+ EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, Gt(0))));
+ Deallocate<1>(&alloc, mem, 1);
+ // Verify that the deallocation matched.
+ EXPECT_THAT(AllocationMap(), ElementsAre(Pair(_, 0)));
+}
+
class Fixture : public ::testing::Test {
using Alloc = std::allocator<std::string>;
@@ -124,7 +166,7 @@ TryDecomposeValue(F&& f, Arg&& arg) {
}
TEST(DecomposeValue, Decomposable) {
- auto f = [](const int& x, int&& y) {
+ auto f = [](const int& x, int&& y) { // NOLINT
EXPECT_EQ(&x, &y);
EXPECT_EQ(42, x);
return 'A';
@@ -158,7 +200,8 @@ TryDecomposePair(F&& f, Args&&... args) {
}
TEST(DecomposePair, Decomposable) {
- auto f = [](const int& x, std::piecewise_construct_t, std::tuple<int&&> k,
+ auto f = [](const int& x, // NOLINT
+ std::piecewise_construct_t, std::tuple<int&&> k,
std::tuple<double>&& v) {
EXPECT_EQ(&x, &std::get<0>(k));
EXPECT_EQ(42, x);
@@ -183,6 +226,32 @@ TEST(DecomposePair, NotDecomposable) {
std::make_tuple(0.5)));
}
+TEST(MapSlotPolicy, ConstKeyAndValue) {
+ using slot_policy = map_slot_policy<const CopyableMovableInstance,
+ const CopyableMovableInstance>;
+ using slot_type = typename slot_policy::slot_type;
+
+ union Slots {
+ Slots() {}
+ ~Slots() {}
+ slot_type slots[100];
+ } slots;
+
+ std::allocator<
+ std::pair<const CopyableMovableInstance, const CopyableMovableInstance>>
+ alloc;
+ InstanceTracker tracker;
+ slot_policy::construct(&alloc, &slots.slots[0], CopyableMovableInstance(1),
+ CopyableMovableInstance(1));
+ for (int i = 0; i < 99; ++i) {
+ slot_policy::transfer(&alloc, &slots.slots[i + 1], &slots.slots[i]);
+ }
+ slot_policy::destroy(&alloc, &slots.slots[99]);
+
+ EXPECT_EQ(tracker.copies(), 0);
+}
+
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/counting_allocator.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/counting_allocator.h
new file mode 100644
index 00000000000..927cf082557
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/counting_allocator.h
@@ -0,0 +1,114 @@
+// 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_COUNTING_ALLOCATOR_H_
+#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+
+#include <cstdint>
+#include <memory>
+
+#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;
+ AllocatorTraits::destroy(allocator, p);
+ 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;
+};
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults.h
index 1f0d794d966..0683422ad89 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -39,8 +39,8 @@
// equal functions are still bound to T. This is important because some type U
// can be hashed by/tested for equality differently depending on T. A notable
// example is `const char*`. `const char*` is treated as a c-style string when
-// the hash function is hash<string> but as a pointer when the hash function is
-// hash<void*>.
+// the hash function is hash<std::string> but as a pointer when the hash
+// function is hash<void*>.
//
#ifndef ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
#define ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
@@ -53,9 +53,11 @@
#include "absl/base/config.h"
#include "absl/hash/hash.h"
+#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
// The hash of an object of type T is computed by using absl::Hash.
@@ -71,6 +73,9 @@ struct StringHash {
size_t operator()(absl::string_view v) const {
return absl::Hash<absl::string_view>{}(v);
}
+ size_t operator()(const absl::Cord& v) const {
+ return absl::Hash<absl::Cord>{}(v);
+ }
};
// Supports heterogeneous lookup for string-like elements.
@@ -81,12 +86,24 @@ struct StringHashEq {
bool operator()(absl::string_view lhs, absl::string_view rhs) const {
return lhs == rhs;
}
+ bool operator()(const absl::Cord& lhs, const absl::Cord& rhs) const {
+ return lhs == rhs;
+ }
+ bool operator()(const absl::Cord& lhs, absl::string_view rhs) const {
+ return lhs == rhs;
+ }
+ bool operator()(absl::string_view lhs, const absl::Cord& rhs) const {
+ return lhs == rhs;
+ }
};
};
+
template <>
struct HashEq<std::string> : StringHashEq {};
template <>
struct HashEq<absl::string_view> : StringHashEq {};
+template <>
+struct HashEq<absl::Cord> : StringHashEq {};
// Supports heterogeneous lookup for pointers and smart pointers.
template <class T>
@@ -138,6 +155,7 @@ template <class T>
using hash_default_eq = typename container_internal::HashEq<T>::Eq;
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_HASH_FUNCTION_DEFAULTS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
index 464baae02cd..59576b8edeb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,9 +19,13 @@
#include <utility>
#include "gtest/gtest.h"
+#include "absl/random/random.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/cord_test_helpers.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -77,14 +81,14 @@ struct EqString : ::testing::Test {
hash_default_eq<T> key_eq;
};
-TYPED_TEST_CASE(EqString, StringTypes);
+TYPED_TEST_SUITE(EqString, StringTypes);
template <class T>
struct HashString : ::testing::Test {
hash_default_hash<T> hasher;
};
-TYPED_TEST_CASE(HashString, StringTypes);
+TYPED_TEST_SUITE(HashString, StringTypes);
TYPED_TEST(EqString, Works) {
auto eq = this->key_eq;
@@ -121,14 +125,14 @@ struct EqPointer : ::testing::Test {
hash_default_eq<T> key_eq;
};
-TYPED_TEST_CASE(EqPointer, PointerTypes);
+TYPED_TEST_SUITE(EqPointer, PointerTypes);
template <class T>
struct HashPointer : ::testing::Test {
hash_default_hash<T> hasher;
};
-TYPED_TEST_CASE(HashPointer, PointerTypes);
+TYPED_TEST_SUITE(HashPointer, PointerTypes);
TYPED_TEST(EqPointer, Works) {
int dummy;
@@ -202,14 +206,91 @@ TYPED_TEST(HashPointer, Works) {
EXPECT_NE(hash(&dummy), hash(cuptr));
}
-// Cartesian product of (string, std::string, absl::string_view)
-// with (string, std::string, absl::string_view, const char*).
+TEST(EqCord, Works) {
+ hash_default_eq<absl::Cord> eq;
+ const absl::string_view a_string_view = "a";
+ const absl::Cord a_cord(a_string_view);
+ const absl::string_view b_string_view = "b";
+ const absl::Cord b_cord(b_string_view);
+
+ EXPECT_TRUE(eq(a_cord, a_cord));
+ EXPECT_TRUE(eq(a_cord, a_string_view));
+ EXPECT_TRUE(eq(a_string_view, a_cord));
+ EXPECT_FALSE(eq(a_cord, b_cord));
+ EXPECT_FALSE(eq(a_cord, b_string_view));
+ EXPECT_FALSE(eq(b_string_view, a_cord));
+}
+
+TEST(HashCord, Works) {
+ hash_default_hash<absl::Cord> hash;
+ const absl::string_view a_string_view = "a";
+ const absl::Cord a_cord(a_string_view);
+ const absl::string_view b_string_view = "b";
+ const absl::Cord b_cord(b_string_view);
+
+ EXPECT_EQ(hash(a_cord), hash(a_cord));
+ EXPECT_EQ(hash(b_cord), hash(b_cord));
+ EXPECT_EQ(hash(a_string_view), hash(a_cord));
+ EXPECT_EQ(hash(b_string_view), hash(b_cord));
+ EXPECT_EQ(hash(absl::Cord("")), hash(""));
+ EXPECT_EQ(hash(absl::Cord()), hash(absl::string_view()));
+
+ EXPECT_NE(hash(a_cord), hash(b_cord));
+ EXPECT_NE(hash(a_cord), hash(b_string_view));
+ EXPECT_NE(hash(a_string_view), hash(b_cord));
+ EXPECT_NE(hash(a_string_view), hash(b_string_view));
+}
+
+void NoOpReleaser(absl::string_view data, void* arg) {}
+
+TEST(HashCord, FragmentedCordWorks) {
+ hash_default_hash<absl::Cord> hash;
+ absl::Cord c = absl::MakeFragmentedCord({"a", "b", "c"});
+ EXPECT_FALSE(c.TryFlat().has_value());
+ EXPECT_EQ(hash(c), hash("abc"));
+}
+
+TEST(HashCord, FragmentedLongCordWorks) {
+ hash_default_hash<absl::Cord> hash;
+ // Crete some large strings which do not fit on the stack.
+ std::string a(65536, 'a');
+ std::string b(65536, 'b');
+ absl::Cord c = absl::MakeFragmentedCord({a, b});
+ EXPECT_FALSE(c.TryFlat().has_value());
+ EXPECT_EQ(hash(c), hash(a + b));
+}
+
+TEST(HashCord, RandomCord) {
+ hash_default_hash<absl::Cord> hash;
+ auto bitgen = absl::BitGen();
+ for (int i = 0; i < 1000; ++i) {
+ const int number_of_segments = absl::Uniform(bitgen, 0, 10);
+ std::vector<std::string> pieces;
+ for (size_t s = 0; s < number_of_segments; ++s) {
+ std::string str;
+ str.resize(absl::Uniform(bitgen, 0, 4096));
+ // MSVC needed the explicit return type in the lambda.
+ std::generate(str.begin(), str.end(), [&]() -> char {
+ return static_cast<char>(absl::Uniform<unsigned char>(bitgen));
+ });
+ pieces.push_back(str);
+ }
+ absl::Cord c = absl::MakeFragmentedCord(pieces);
+ EXPECT_EQ(hash(c), hash(std::string(c)));
+ }
+}
+
+// Cartesian product of (std::string, absl::string_view)
+// with (std::string, absl::string_view, const char*, absl::Cord).
using StringTypesCartesianProduct = Types<
// clang-format off
+ std::pair<absl::Cord, std::string>,
+ std::pair<absl::Cord, absl::string_view>,
+ std::pair<absl::Cord, absl::Cord>,
+ std::pair<absl::Cord, const char*>,
- std::pair<std::string, std::string>,
- std::pair<std::string, absl::string_view>,
- std::pair<std::string, const char*>,
+ std::pair<std::string, absl::Cord>,
+ std::pair<absl::string_view, absl::Cord>,
std::pair<absl::string_view, std::string>,
std::pair<absl::string_view, absl::string_view>,
@@ -248,18 +329,19 @@ TYPED_TEST_P(StringLikeTest, HashEq) {
EXPECT_NE(this->hash(this->a1), this->hash(this->b2));
}
-TYPED_TEST_CASE(StringLikeTest, StringTypesCartesianProduct);
+TYPED_TEST_SUITE(StringLikeTest, StringTypesCartesianProduct);
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
enum Hash : size_t {
- kStd = 0x2, // std::hash
+ kStd = 0x1, // std::hash
#ifdef _MSC_VER
kExtension = kStd, // In MSVC, std::hash == ::hash
#else // _MSC_VER
- kExtension = 0x4, // ::hash (GCC extension)
+ kExtension = 0x2, // ::hash (GCC extension)
#endif // _MSC_VER
};
@@ -282,6 +364,7 @@ struct hash<Hashable<H>> {
} // namespace std
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -296,4 +379,5 @@ TEST(Delegate, HashDispatch) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.cc
index e0fefbffdfa..59cc5aac7ab 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include <deque>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace hash_internal {
namespace {
@@ -40,8 +41,10 @@ class RandomDeviceSeedSeq {
} // namespace
std::mt19937_64* GetSharedRng() {
- RandomDeviceSeedSeq seed_seq;
- static auto* rng = new std::mt19937_64(seed_seq);
+ static auto* rng = [] {
+ RandomDeviceSeedSeq seed_seq;
+ return new std::mt19937_64(seed_seq);
+ }();
return rng;
}
@@ -69,4 +72,5 @@ absl::string_view Generator<absl::string_view>::operator()() const {
} // namespace hash_internal
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.h
index 6521efe8733..6869fe45e8c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_generator_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,6 +19,7 @@
#define ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
#include <stdint.h>
+
#include <algorithm>
#include <iosfwd>
#include <random>
@@ -27,10 +28,12 @@
#include <utility>
#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 {
@@ -129,6 +132,13 @@ struct Generator<std::tuple<Ts...>> {
}
};
+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())>>
@@ -145,6 +155,7 @@ using GeneratedType = decltype(
} // namespace hash_internal
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_HASH_GENERATOR_TESTING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing.h
index 7fb819a74d2..01c40d2e5cf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,6 +30,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace hash_testing_internal {
@@ -162,6 +163,7 @@ auto keys(const Set& s)
}
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
// ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS is false for glibcxx versions
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing_test.cc
index c215c4237ae..f0b20fe345e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_testing_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -40,4 +41,5 @@ TEST(_, Hash) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits.h
index ace50a6ca42..46c97b18a22 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,26 +17,47 @@
#include <cstddef>
#include <memory>
+#include <new>
#include <type_traits>
#include <utility>
#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
// Defines how slots are initialized/destroyed/moved.
template <class Policy, class = void>
struct hash_policy_traits {
+ // The type of the keys stored in the hashtable.
+ using key_type = typename Policy::key_type;
+
private:
struct ReturnKey {
- // We return `Key` here.
+ // When C++17 is available, we can use std::launder to provide mutable
+ // access to the key for use in node handle.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+ template <class Key,
+ absl::enable_if_t<std::is_lvalue_reference<Key>::value, int> = 0>
+ static key_type& Impl(Key&& k, int) {
+ return *std::launder(
+ const_cast<key_type*>(std::addressof(std::forward<Key>(k))));
+ }
+#endif
+
+ template <class Key>
+ static Key Impl(Key&& k, char) {
+ return std::forward<Key>(k);
+ }
+
// When Key=T&, we forward the lvalue reference.
// When Key=T, we return by value to avoid a dangling reference.
// eg, for string_hash_map.
template <class Key, class... Args>
- Key operator()(Key&& k, const Args&...) const {
- return std::forward<Key>(k);
+ auto operator()(Key&& k, const Args&...) const
+ -> decltype(Impl(std::forward<Key>(k), 0)) {
+ return Impl(std::forward<Key>(k), 0);
}
};
@@ -51,9 +72,6 @@ struct hash_policy_traits {
// The actual object stored in the hash table.
using slot_type = typename Policy::slot_type;
- // The type of the keys stored in the hashtable.
- using key_type = typename Policy::key_type;
-
// The argument type for insertions into the hashtable. This is different
// from value_type for increased performance. See initializer_list constructor
// and insert() member functions for more details.
@@ -155,7 +173,7 @@ struct hash_policy_traits {
// Returns the "key" portion of the slot.
// Used for node handle manipulation.
template <class P = Policy>
- static auto key(slot_type* slot)
+ static auto mutable_key(slot_type* slot)
-> decltype(P::apply(ReturnKey(), element(slot))) {
return P::apply(ReturnKey(), element(slot));
}
@@ -184,6 +202,7 @@ struct hash_policy_traits {
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_HASH_POLICY_TRAITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc
index 423f1548e7c..6ef8b9e05fb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hash_policy_traits_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -139,4 +140,5 @@ TEST_F(Test, with_transfer) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug.h
index 38050c69f61..19d52121d68 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -38,6 +38,7 @@
#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
@@ -103,6 +104,7 @@ size_t LowerBoundAllocatedByteSize(size_t num_elements) {
}
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h
index 8f219726bee..3e9ea5954e0 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtable_debug_hooks.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,7 +23,10 @@
#include <type_traits>
#include <vector>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace hashtable_debug_internal {
@@ -76,6 +79,7 @@ struct HashtableDebugAccess {
} // namespace hashtable_debug_internal
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_HASHTABLE_DEBUG_HOOKS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
new file mode 100644
index 00000000000..5a29bed7922
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
@@ -0,0 +1,274 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include <atomic>
+#include <cassert>
+#include <cmath>
+#include <functional>
+#include <limits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/exponential_biased.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/memory/memory.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+constexpr int HashtablezInfo::kMaxStackDepth;
+
+namespace {
+ABSL_CONST_INIT std::atomic<bool> g_hashtablez_enabled{
+ false
+};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_sample_parameter{1 << 10};
+ABSL_CONST_INIT std::atomic<int32_t> g_hashtablez_max_samples{1 << 20};
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased
+ g_exponential_biased_generator;
+#endif
+
+} // namespace
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+HashtablezSampler& HashtablezSampler::Global() {
+ static auto* sampler = new HashtablezSampler();
+ return *sampler;
+}
+
+HashtablezSampler::DisposeCallback HashtablezSampler::SetDisposeCallback(
+ DisposeCallback f) {
+ return dispose_.exchange(f, std::memory_order_relaxed);
+}
+
+HashtablezInfo::HashtablezInfo() { PrepareForSampling(); }
+HashtablezInfo::~HashtablezInfo() = default;
+
+void HashtablezInfo::PrepareForSampling() {
+ capacity.store(0, std::memory_order_relaxed);
+ size.store(0, std::memory_order_relaxed);
+ num_erases.store(0, std::memory_order_relaxed);
+ num_rehashes.store(0, std::memory_order_relaxed);
+ max_probe_length.store(0, std::memory_order_relaxed);
+ total_probe_length.store(0, std::memory_order_relaxed);
+ hashes_bitwise_or.store(0, std::memory_order_relaxed);
+ hashes_bitwise_and.store(~size_t{}, std::memory_order_relaxed);
+ hashes_bitwise_xor.store(0, std::memory_order_relaxed);
+
+ create_time = absl::Now();
+ // The inliner makes hardcoded skip_count difficult (especially when combined
+ // with LTO). We use the ability to exclude stacks by regex when encoding
+ // instead.
+ depth = absl::GetStackTrace(stack, HashtablezInfo::kMaxStackDepth,
+ /* skip_count= */ 0);
+ dead = nullptr;
+}
+
+HashtablezSampler::HashtablezSampler()
+ : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) {
+ absl::MutexLock l(&graveyard_.init_mu);
+ graveyard_.dead = &graveyard_;
+}
+
+HashtablezSampler::~HashtablezSampler() {
+ HashtablezInfo* s = all_.load(std::memory_order_acquire);
+ while (s != nullptr) {
+ HashtablezInfo* next = s->next;
+ delete s;
+ s = next;
+ }
+}
+
+void HashtablezSampler::PushNew(HashtablezInfo* sample) {
+ sample->next = all_.load(std::memory_order_relaxed);
+ while (!all_.compare_exchange_weak(sample->next, sample,
+ std::memory_order_release,
+ std::memory_order_relaxed)) {
+ }
+}
+
+void HashtablezSampler::PushDead(HashtablezInfo* sample) {
+ if (auto* dispose = dispose_.load(std::memory_order_relaxed)) {
+ dispose(*sample);
+ }
+
+ absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+ absl::MutexLock sample_lock(&sample->init_mu);
+ sample->dead = graveyard_.dead;
+ graveyard_.dead = sample;
+}
+
+HashtablezInfo* HashtablezSampler::PopDead() {
+ absl::MutexLock graveyard_lock(&graveyard_.init_mu);
+
+ // The list is circular, so eventually it collapses down to
+ // graveyard_.dead == &graveyard_
+ // when it is empty.
+ HashtablezInfo* sample = graveyard_.dead;
+ if (sample == &graveyard_) return nullptr;
+
+ absl::MutexLock sample_lock(&sample->init_mu);
+ graveyard_.dead = sample->dead;
+ sample->PrepareForSampling();
+ return sample;
+}
+
+HashtablezInfo* HashtablezSampler::Register() {
+ int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
+ if (size > g_hashtablez_max_samples.load(std::memory_order_relaxed)) {
+ size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+ dropped_samples_.fetch_add(1, std::memory_order_relaxed);
+ return nullptr;
+ }
+
+ HashtablezInfo* sample = PopDead();
+ if (sample == nullptr) {
+ // Resurrection failed. Hire a new warlock.
+ sample = new HashtablezInfo();
+ PushNew(sample);
+ }
+
+ return sample;
+}
+
+void HashtablezSampler::Unregister(HashtablezInfo* sample) {
+ PushDead(sample);
+ size_estimate_.fetch_sub(1, std::memory_order_relaxed);
+}
+
+int64_t HashtablezSampler::Iterate(
+ const std::function<void(const HashtablezInfo& stack)>& f) {
+ HashtablezInfo* s = all_.load(std::memory_order_acquire);
+ while (s != nullptr) {
+ absl::MutexLock l(&s->init_mu);
+ if (s->dead == nullptr) {
+ f(*s);
+ }
+ s = s->next;
+ }
+
+ return dropped_samples_.load(std::memory_order_relaxed);
+}
+
+static bool ShouldForceSampling() {
+ enum ForceState {
+ kDontForce,
+ kForce,
+ kUninitialized
+ };
+ ABSL_CONST_INIT static std::atomic<ForceState> global_state{
+ kUninitialized};
+ ForceState state = global_state.load(std::memory_order_relaxed);
+ if (ABSL_PREDICT_TRUE(state == kDontForce)) return false;
+
+ if (state == kUninitialized) {
+ state = ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)()
+ ? kForce
+ : kDontForce;
+ global_state.store(state, std::memory_order_relaxed);
+ }
+ return state == kForce;
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample) {
+ if (ABSL_PREDICT_FALSE(ShouldForceSampling())) {
+ *next_sample = 1;
+ return HashtablezSampler::Global().Register();
+ }
+
+#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ *next_sample = std::numeric_limits<int64_t>::max();
+ return nullptr;
+#else
+ bool first = *next_sample < 0;
+ *next_sample = g_exponential_biased_generator.GetStride(
+ g_hashtablez_sample_parameter.load(std::memory_order_relaxed));
+ // Small values of interval are equivalent to just sampling next time.
+ ABSL_ASSERT(*next_sample >= 1);
+
+ // g_hashtablez_enabled can be dynamically flipped, we need to set a threshold
+ // low enough that we will start sampling in a reasonable time, so we just use
+ // the default sampling rate.
+ if (!g_hashtablez_enabled.load(std::memory_order_relaxed)) return nullptr;
+
+ // We will only be negative on our first count, so we should just retry in
+ // that case.
+ if (first) {
+ if (ABSL_PREDICT_TRUE(--*next_sample > 0)) return nullptr;
+ return SampleSlow(next_sample);
+ }
+
+ return HashtablezSampler::Global().Register();
+#endif
+}
+
+void UnsampleSlow(HashtablezInfo* info) {
+ HashtablezSampler::Global().Unregister(info);
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+ size_t distance_from_desired) {
+ // SwissTables probe in groups of 16, so scale this to count items probes and
+ // not offset from desired.
+ size_t probe_length = distance_from_desired;
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+ probe_length /= 16;
+#else
+ probe_length /= 8;
+#endif
+
+ info->hashes_bitwise_and.fetch_and(hash, std::memory_order_relaxed);
+ info->hashes_bitwise_or.fetch_or(hash, std::memory_order_relaxed);
+ info->hashes_bitwise_xor.fetch_xor(hash, std::memory_order_relaxed);
+ info->max_probe_length.store(
+ std::max(info->max_probe_length.load(std::memory_order_relaxed),
+ probe_length),
+ std::memory_order_relaxed);
+ info->total_probe_length.fetch_add(probe_length, std::memory_order_relaxed);
+ info->size.fetch_add(1, std::memory_order_relaxed);
+}
+
+void SetHashtablezEnabled(bool enabled) {
+ g_hashtablez_enabled.store(enabled, std::memory_order_release);
+}
+
+void SetHashtablezSampleParameter(int32_t rate) {
+ if (rate > 0) {
+ g_hashtablez_sample_parameter.store(rate, std::memory_order_release);
+ } else {
+ ABSL_RAW_LOG(ERROR, "Invalid hashtablez sample rate: %lld",
+ static_cast<long long>(rate)); // NOLINT(runtime/int)
+ }
+}
+
+void SetHashtablezMaxSamples(int32_t max) {
+ if (max > 0) {
+ g_hashtablez_max_samples.store(max, std::memory_order_release);
+ } else {
+ ABSL_RAW_LOG(ERROR, "Invalid hashtablez max samples: %lld",
+ static_cast<long long>(max)); // NOLINT(runtime/int)
+ }
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.h
new file mode 100644
index 00000000000..85685f72914
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler.h
@@ -0,0 +1,322 @@
+// 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: hashtablez_sampler.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for a low level library to sample hashtables
+// and collect runtime statistics about them.
+//
+// `HashtablezSampler` controls the lifecycle of `HashtablezInfo` objects which
+// store information about a single sample.
+//
+// `Record*` methods store information into samples.
+// `Sample()` and `Unsample()` make use of a single global sampler with
+// properties controlled by the flags hashtablez_enabled,
+// hashtablez_sample_rate, and hashtablez_max_samples.
+//
+// WARNING
+//
+// Using this sampling API may cause sampled Swiss tables to use the global
+// allocator (operator `new`) in addition to any custom allocator. If you
+// are using a table in an unusual circumstance where allocation or calling a
+// linux syscall is unacceptable, this could interfere.
+//
+// This utility is internal-only. Use at your own risk.
+
+#ifndef ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+#define ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
+
+#include <atomic>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/optimization.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// Stores information about a sampled hashtable. All mutations to this *must*
+// be made through `Record*` functions below. All reads from this *must* only
+// occur in the callback to `HashtablezSampler::Iterate`.
+struct HashtablezInfo {
+ // Constructs the object but does not fill in any fields.
+ HashtablezInfo();
+ ~HashtablezInfo();
+ HashtablezInfo(const HashtablezInfo&) = delete;
+ HashtablezInfo& operator=(const HashtablezInfo&) = delete;
+
+ // Puts the object into a clean state, fills in the logically `const` members,
+ // blocking for any readers that are currently sampling the object.
+ void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
+
+ // These fields are mutated by the various Record* APIs and need to be
+ // thread-safe.
+ std::atomic<size_t> capacity;
+ std::atomic<size_t> size;
+ std::atomic<size_t> num_erases;
+ std::atomic<size_t> num_rehashes;
+ std::atomic<size_t> max_probe_length;
+ std::atomic<size_t> total_probe_length;
+ std::atomic<size_t> hashes_bitwise_or;
+ std::atomic<size_t> hashes_bitwise_and;
+ std::atomic<size_t> hashes_bitwise_xor;
+
+ // `HashtablezSampler` maintains intrusive linked lists for all samples. See
+ // comments on `HashtablezSampler::all_` for details on these. `init_mu`
+ // guards the ability to restore the sample to a pristine state. This
+ // prevents races with sampling and resurrecting an object.
+ absl::Mutex init_mu;
+ HashtablezInfo* next;
+ HashtablezInfo* dead ABSL_GUARDED_BY(init_mu);
+
+ // All of the fields below are set by `PrepareForSampling`, they must not be
+ // mutated in `Record*` functions. They are logically `const` in that sense.
+ // These are guarded by init_mu, but that is not externalized to clients, who
+ // can only read them during `HashtablezSampler::Iterate` which will hold the
+ // lock.
+ static constexpr int kMaxStackDepth = 64;
+ absl::Time create_time;
+ int32_t depth;
+ void* stack[kMaxStackDepth];
+};
+
+inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+ total_probe_length /= 16;
+#else
+ total_probe_length /= 8;
+#endif
+ info->total_probe_length.store(total_probe_length, std::memory_order_relaxed);
+ info->num_erases.store(0, std::memory_order_relaxed);
+ // There is only one concurrent writer, so `load` then `store` is sufficient
+ // instead of using `fetch_add`.
+ info->num_rehashes.store(
+ 1 + info->num_rehashes.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+}
+
+inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
+ size_t capacity) {
+ info->size.store(size, std::memory_order_relaxed);
+ info->capacity.store(capacity, std::memory_order_relaxed);
+ if (size == 0) {
+ // This is a clear, reset the total/num_erases too.
+ info->total_probe_length.store(0, std::memory_order_relaxed);
+ info->num_erases.store(0, std::memory_order_relaxed);
+ }
+}
+
+void RecordInsertSlow(HashtablezInfo* info, size_t hash,
+ size_t distance_from_desired);
+
+inline void RecordEraseSlow(HashtablezInfo* info) {
+ info->size.fetch_sub(1, std::memory_order_relaxed);
+ // There is only one concurrent writer, so `load` then `store` is sufficient
+ // instead of using `fetch_add`.
+ info->num_erases.store(
+ 1 + info->num_erases.load(std::memory_order_relaxed),
+ std::memory_order_relaxed);
+}
+
+HashtablezInfo* SampleSlow(int64_t* next_sample);
+void UnsampleSlow(HashtablezInfo* info);
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+class HashtablezInfoHandle {
+ public:
+ explicit HashtablezInfoHandle() : info_(nullptr) {}
+ explicit HashtablezInfoHandle(HashtablezInfo* info) : info_(info) {}
+ ~HashtablezInfoHandle() {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ UnsampleSlow(info_);
+ }
+
+ HashtablezInfoHandle(const HashtablezInfoHandle&) = delete;
+ HashtablezInfoHandle& operator=(const HashtablezInfoHandle&) = delete;
+
+ HashtablezInfoHandle(HashtablezInfoHandle&& o) noexcept
+ : info_(absl::exchange(o.info_, nullptr)) {}
+ HashtablezInfoHandle& operator=(HashtablezInfoHandle&& o) noexcept {
+ if (ABSL_PREDICT_FALSE(info_ != nullptr)) {
+ UnsampleSlow(info_);
+ }
+ info_ = absl::exchange(o.info_, nullptr);
+ return *this;
+ }
+
+ inline void RecordStorageChanged(size_t size, size_t capacity) {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordStorageChangedSlow(info_, size, capacity);
+ }
+
+ inline void RecordRehash(size_t total_probe_length) {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordRehashSlow(info_, total_probe_length);
+ }
+
+ inline void RecordInsert(size_t hash, size_t distance_from_desired) {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordInsertSlow(info_, hash, distance_from_desired);
+ }
+
+ inline void RecordErase() {
+ if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
+ RecordEraseSlow(info_);
+ }
+
+ friend inline void swap(HashtablezInfoHandle& lhs,
+ HashtablezInfoHandle& rhs) {
+ std::swap(lhs.info_, rhs.info_);
+ }
+
+ private:
+ friend class HashtablezInfoHandlePeer;
+ HashtablezInfo* info_;
+};
+#else
+// Ensure that when Hashtablez is turned off at compile time, HashtablezInfo can
+// be removed by the linker, in order to reduce the binary size.
+class HashtablezInfoHandle {
+ public:
+ explicit HashtablezInfoHandle() = default;
+ explicit HashtablezInfoHandle(std::nullptr_t) {}
+
+ inline void RecordStorageChanged(size_t /*size*/, size_t /*capacity*/) {}
+ inline void RecordRehash(size_t /*total_probe_length*/) {}
+ inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
+ inline void RecordErase() {}
+
+ friend inline void swap(HashtablezInfoHandle& /*lhs*/,
+ HashtablezInfoHandle& /*rhs*/) {}
+};
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+// Returns an RAII sampling handle that manages registration and unregistation
+// with the global sampler.
+inline HashtablezInfoHandle Sample() {
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+ if (ABSL_PREDICT_TRUE(--global_next_sample > 0)) {
+ return HashtablezInfoHandle(nullptr);
+ }
+ return HashtablezInfoHandle(SampleSlow(&global_next_sample));
+#else
+ return HashtablezInfoHandle(nullptr);
+#endif // !ABSL_PER_THREAD_TLS
+}
+
+// Holds samples and their associated stack traces with a soft limit of
+// `SetHashtablezMaxSamples()`.
+//
+// Thread safe.
+class HashtablezSampler {
+ public:
+ // Returns a global Sampler.
+ static HashtablezSampler& Global();
+
+ HashtablezSampler();
+ ~HashtablezSampler();
+
+ // Registers for sampling. Returns an opaque registration info.
+ HashtablezInfo* Register();
+
+ // Unregisters the sample.
+ void Unregister(HashtablezInfo* sample);
+
+ // The dispose callback will be called on all samples the moment they are
+ // being unregistered. Only affects samples that are unregistered after the
+ // callback has been set.
+ // Returns the previous callback.
+ using DisposeCallback = void (*)(const HashtablezInfo&);
+ DisposeCallback SetDisposeCallback(DisposeCallback f);
+
+ // Iterates over all the registered `StackInfo`s. Returning the number of
+ // samples that have been dropped.
+ int64_t Iterate(const std::function<void(const HashtablezInfo& stack)>& f);
+
+ private:
+ void PushNew(HashtablezInfo* sample);
+ void PushDead(HashtablezInfo* sample);
+ HashtablezInfo* PopDead();
+
+ std::atomic<size_t> dropped_samples_;
+ std::atomic<size_t> size_estimate_;
+
+ // Intrusive lock free linked lists for tracking samples.
+ //
+ // `all_` records all samples (they are never removed from this list) and is
+ // terminated with a `nullptr`.
+ //
+ // `graveyard_.dead` is a circular linked list. When it is empty,
+ // `graveyard_.dead == &graveyard`. The list is circular so that
+ // every item on it (even the last) has a non-null dead pointer. This allows
+ // `Iterate` to determine if a given sample is live or dead using only
+ // information on the sample itself.
+ //
+ // For example, nodes [A, B, C, D, E] with [A, C, E] alive and [B, D] dead
+ // looks like this (G is the Graveyard):
+ //
+ // +---+ +---+ +---+ +---+ +---+
+ // all -->| A |--->| B |--->| C |--->| D |--->| E |
+ // | | | | | | | | | |
+ // +---+ | | +->| |-+ | | +->| |-+ | |
+ // | G | +---+ | +---+ | +---+ | +---+ | +---+
+ // | | | | | |
+ // | | --------+ +--------+ |
+ // +---+ |
+ // ^ |
+ // +--------------------------------------+
+ //
+ std::atomic<HashtablezInfo*> all_;
+ HashtablezInfo graveyard_;
+
+ std::atomic<DisposeCallback> dispose_;
+};
+
+// Enables or disables sampling for Swiss tables.
+void SetHashtablezEnabled(bool enabled);
+
+// Sets the rate at which Swiss tables will be sampled.
+void SetHashtablezSampleParameter(int32_t rate);
+
+// Sets a soft max for the number of samples that will be kept.
+void SetHashtablezMaxSamples(int32_t max);
+
+// Configuration override.
+// This allows process-wide sampling without depending on order of
+// initialization of static storage duration objects.
+// The definition of this constant is weak, which allows us to inject a
+// different value for it at link time.
+extern "C" bool ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)();
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_HASHTABLEZ_SAMPLER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
new file mode 100644
index 00000000000..ed35a7eec3d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
@@ -0,0 +1,31 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include "absl/base/attributes.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+// See hashtablez_sampler.h for details.
+extern "C" ABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(
+ AbslContainerInternalSampleEverything)() {
+ return false;
+}
+
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
new file mode 100644
index 00000000000..5f4c83b74ad
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
@@ -0,0 +1,377 @@
+// 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.
+
+#include "absl/container/internal/hashtablez_sampler.h"
+
+#include <atomic>
+#include <limits>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/container/internal/have_sse.h"
+#include "absl/synchronization/blocking_counter.h"
+#include "absl/synchronization/internal/thread_pool.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/synchronization/notification.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+constexpr int kProbeLength = 16;
+#else
+constexpr int kProbeLength = 8;
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+class HashtablezInfoHandlePeer {
+ public:
+ static bool IsSampled(const HashtablezInfoHandle& h) {
+ return h.info_ != nullptr;
+ }
+
+ static HashtablezInfo* GetInfo(HashtablezInfoHandle* h) { return h->info_; }
+};
+#else
+class HashtablezInfoHandlePeer {
+ public:
+ static bool IsSampled(const HashtablezInfoHandle&) { return false; }
+ static HashtablezInfo* GetInfo(HashtablezInfoHandle*) { return nullptr; }
+};
+#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+
+namespace {
+using ::absl::synchronization_internal::ThreadPool;
+using ::testing::IsEmpty;
+using ::testing::UnorderedElementsAre;
+
+std::vector<size_t> GetSizes(HashtablezSampler* s) {
+ std::vector<size_t> res;
+ s->Iterate([&](const HashtablezInfo& info) {
+ res.push_back(info.size.load(std::memory_order_acquire));
+ });
+ return res;
+}
+
+HashtablezInfo* Register(HashtablezSampler* s, size_t size) {
+ auto* info = s->Register();
+ assert(info != nullptr);
+ info->size.store(size);
+ return info;
+}
+
+TEST(HashtablezInfoTest, PrepareForSampling) {
+ absl::Time test_start = absl::Now();
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+
+ EXPECT_EQ(info.capacity.load(), 0);
+ EXPECT_EQ(info.size.load(), 0);
+ EXPECT_EQ(info.num_erases.load(), 0);
+ EXPECT_EQ(info.num_rehashes.load(), 0);
+ EXPECT_EQ(info.max_probe_length.load(), 0);
+ EXPECT_EQ(info.total_probe_length.load(), 0);
+ EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
+ EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+ EXPECT_EQ(info.hashes_bitwise_xor.load(), 0);
+ EXPECT_GE(info.create_time, test_start);
+
+ info.capacity.store(1, std::memory_order_relaxed);
+ info.size.store(1, std::memory_order_relaxed);
+ info.num_erases.store(1, std::memory_order_relaxed);
+ info.max_probe_length.store(1, std::memory_order_relaxed);
+ info.total_probe_length.store(1, std::memory_order_relaxed);
+ info.hashes_bitwise_or.store(1, std::memory_order_relaxed);
+ info.hashes_bitwise_and.store(1, std::memory_order_relaxed);
+ info.hashes_bitwise_xor.store(1, std::memory_order_relaxed);
+ info.create_time = test_start - absl::Hours(20);
+
+ info.PrepareForSampling();
+ EXPECT_EQ(info.capacity.load(), 0);
+ EXPECT_EQ(info.size.load(), 0);
+ EXPECT_EQ(info.num_erases.load(), 0);
+ EXPECT_EQ(info.num_rehashes.load(), 0);
+ EXPECT_EQ(info.max_probe_length.load(), 0);
+ EXPECT_EQ(info.total_probe_length.load(), 0);
+ EXPECT_EQ(info.hashes_bitwise_or.load(), 0);
+ EXPECT_EQ(info.hashes_bitwise_and.load(), ~size_t{});
+ EXPECT_EQ(info.hashes_bitwise_xor.load(), 0);
+ EXPECT_GE(info.create_time, test_start);
+}
+
+TEST(HashtablezInfoTest, RecordStorageChanged) {
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+ RecordStorageChangedSlow(&info, 17, 47);
+ EXPECT_EQ(info.size.load(), 17);
+ EXPECT_EQ(info.capacity.load(), 47);
+ RecordStorageChangedSlow(&info, 20, 20);
+ EXPECT_EQ(info.size.load(), 20);
+ EXPECT_EQ(info.capacity.load(), 20);
+}
+
+TEST(HashtablezInfoTest, RecordInsert) {
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+ EXPECT_EQ(info.max_probe_length.load(), 0);
+ RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+ EXPECT_EQ(info.max_probe_length.load(), 6);
+ EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000FF00);
+ EXPECT_EQ(info.hashes_bitwise_or.load(), 0x0000FF00);
+ EXPECT_EQ(info.hashes_bitwise_xor.load(), 0x0000FF00);
+ RecordInsertSlow(&info, 0x000FF000, 4 * kProbeLength);
+ EXPECT_EQ(info.max_probe_length.load(), 6);
+ EXPECT_EQ(info.hashes_bitwise_and.load(), 0x0000F000);
+ EXPECT_EQ(info.hashes_bitwise_or.load(), 0x000FFF00);
+ EXPECT_EQ(info.hashes_bitwise_xor.load(), 0x000F0F00);
+ RecordInsertSlow(&info, 0x00FF0000, 12 * kProbeLength);
+ EXPECT_EQ(info.max_probe_length.load(), 12);
+ EXPECT_EQ(info.hashes_bitwise_and.load(), 0x00000000);
+ EXPECT_EQ(info.hashes_bitwise_or.load(), 0x00FFFF00);
+ EXPECT_EQ(info.hashes_bitwise_xor.load(), 0x00F00F00);
+}
+
+TEST(HashtablezInfoTest, RecordErase) {
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+ EXPECT_EQ(info.num_erases.load(), 0);
+ EXPECT_EQ(info.size.load(), 0);
+ RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
+ EXPECT_EQ(info.size.load(), 1);
+ RecordEraseSlow(&info);
+ EXPECT_EQ(info.size.load(), 0);
+ EXPECT_EQ(info.num_erases.load(), 1);
+}
+
+TEST(HashtablezInfoTest, RecordRehash) {
+ HashtablezInfo info;
+ absl::MutexLock l(&info.init_mu);
+ info.PrepareForSampling();
+ RecordInsertSlow(&info, 0x1, 0);
+ RecordInsertSlow(&info, 0x2, kProbeLength);
+ RecordInsertSlow(&info, 0x4, kProbeLength);
+ RecordInsertSlow(&info, 0x8, 2 * kProbeLength);
+ EXPECT_EQ(info.size.load(), 4);
+ EXPECT_EQ(info.total_probe_length.load(), 4);
+
+ RecordEraseSlow(&info);
+ RecordEraseSlow(&info);
+ EXPECT_EQ(info.size.load(), 2);
+ EXPECT_EQ(info.total_probe_length.load(), 4);
+ EXPECT_EQ(info.num_erases.load(), 2);
+
+ RecordRehashSlow(&info, 3 * kProbeLength);
+ EXPECT_EQ(info.size.load(), 2);
+ EXPECT_EQ(info.total_probe_length.load(), 3);
+ EXPECT_EQ(info.num_erases.load(), 0);
+ EXPECT_EQ(info.num_rehashes.load(), 1);
+}
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+TEST(HashtablezSamplerTest, SmallSampleParameter) {
+ SetHashtablezEnabled(true);
+ SetHashtablezSampleParameter(100);
+
+ for (int i = 0; i < 1000; ++i) {
+ int64_t next_sample = 0;
+ HashtablezInfo* sample = SampleSlow(&next_sample);
+ EXPECT_GT(next_sample, 0);
+ EXPECT_NE(sample, nullptr);
+ UnsampleSlow(sample);
+ }
+}
+
+TEST(HashtablezSamplerTest, LargeSampleParameter) {
+ SetHashtablezEnabled(true);
+ SetHashtablezSampleParameter(std::numeric_limits<int32_t>::max());
+
+ for (int i = 0; i < 1000; ++i) {
+ int64_t next_sample = 0;
+ HashtablezInfo* sample = SampleSlow(&next_sample);
+ EXPECT_GT(next_sample, 0);
+ EXPECT_NE(sample, nullptr);
+ UnsampleSlow(sample);
+ }
+}
+
+TEST(HashtablezSamplerTest, Sample) {
+ SetHashtablezEnabled(true);
+ SetHashtablezSampleParameter(100);
+ int64_t num_sampled = 0;
+ int64_t total = 0;
+ double sample_rate = 0.0;
+ for (int i = 0; i < 1000000; ++i) {
+ HashtablezInfoHandle h = Sample();
+ ++total;
+ if (HashtablezInfoHandlePeer::IsSampled(h)) {
+ ++num_sampled;
+ }
+ sample_rate = static_cast<double>(num_sampled) / total;
+ if (0.005 < sample_rate && sample_rate < 0.015) break;
+ }
+ EXPECT_NEAR(sample_rate, 0.01, 0.005);
+}
+
+TEST(HashtablezSamplerTest, Handle) {
+ auto& sampler = HashtablezSampler::Global();
+ HashtablezInfoHandle h(sampler.Register());
+ auto* info = HashtablezInfoHandlePeer::GetInfo(&h);
+ info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);
+
+ bool found = false;
+ sampler.Iterate([&](const HashtablezInfo& h) {
+ if (&h == info) {
+ EXPECT_EQ(h.hashes_bitwise_and.load(), 0x12345678);
+ found = true;
+ }
+ });
+ EXPECT_TRUE(found);
+
+ h = HashtablezInfoHandle();
+ found = false;
+ sampler.Iterate([&](const HashtablezInfo& h) {
+ if (&h == info) {
+ // this will only happen if some other thread has resurrected the info
+ // the old handle was using.
+ if (h.hashes_bitwise_and.load() == 0x12345678) {
+ found = true;
+ }
+ }
+ });
+ EXPECT_FALSE(found);
+}
+#endif
+
+
+TEST(HashtablezSamplerTest, Registration) {
+ HashtablezSampler sampler;
+ auto* info1 = Register(&sampler, 1);
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1));
+
+ auto* info2 = Register(&sampler, 2);
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(1, 2));
+ info1->size.store(3);
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(3, 2));
+
+ sampler.Unregister(info1);
+ sampler.Unregister(info2);
+}
+
+TEST(HashtablezSamplerTest, Unregistration) {
+ HashtablezSampler sampler;
+ std::vector<HashtablezInfo*> infos;
+ for (size_t i = 0; i < 3; ++i) {
+ infos.push_back(Register(&sampler, i));
+ }
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 1, 2));
+
+ sampler.Unregister(infos[1]);
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2));
+
+ infos.push_back(Register(&sampler, 3));
+ infos.push_back(Register(&sampler, 4));
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 3, 4));
+ sampler.Unregister(infos[3]);
+ EXPECT_THAT(GetSizes(&sampler), UnorderedElementsAre(0, 2, 4));
+
+ sampler.Unregister(infos[0]);
+ sampler.Unregister(infos[2]);
+ sampler.Unregister(infos[4]);
+ EXPECT_THAT(GetSizes(&sampler), IsEmpty());
+}
+
+TEST(HashtablezSamplerTest, MultiThreaded) {
+ HashtablezSampler sampler;
+ Notification stop;
+ ThreadPool pool(10);
+
+ for (int i = 0; i < 10; ++i) {
+ pool.Schedule([&sampler, &stop]() {
+ std::random_device rd;
+ std::mt19937 gen(rd());
+
+ std::vector<HashtablezInfo*> infoz;
+ while (!stop.HasBeenNotified()) {
+ if (infoz.empty()) {
+ infoz.push_back(sampler.Register());
+ }
+ switch (std::uniform_int_distribution<>(0, 2)(gen)) {
+ case 0: {
+ infoz.push_back(sampler.Register());
+ break;
+ }
+ case 1: {
+ size_t p =
+ std::uniform_int_distribution<>(0, infoz.size() - 1)(gen);
+ HashtablezInfo* info = infoz[p];
+ infoz[p] = infoz.back();
+ infoz.pop_back();
+ sampler.Unregister(info);
+ break;
+ }
+ case 2: {
+ absl::Duration oldest = absl::ZeroDuration();
+ sampler.Iterate([&](const HashtablezInfo& info) {
+ oldest = std::max(oldest, absl::Now() - info.create_time);
+ });
+ ASSERT_GE(oldest, absl::ZeroDuration());
+ break;
+ }
+ }
+ }
+ });
+ }
+ // The threads will hammer away. Give it a little bit of time for tsan to
+ // spot errors.
+ absl::SleepFor(absl::Seconds(3));
+ stop.Notify();
+}
+
+TEST(HashtablezSamplerTest, Callback) {
+ HashtablezSampler sampler;
+
+ auto* info1 = Register(&sampler, 1);
+ auto* info2 = Register(&sampler, 2);
+
+ static const HashtablezInfo* expected;
+
+ auto callback = [](const HashtablezInfo& info) {
+ // We can't use `info` outside of this callback because the object will be
+ // disposed as soon as we return from here.
+ EXPECT_EQ(&info, expected);
+ };
+
+ // Set the callback.
+ EXPECT_EQ(sampler.SetDisposeCallback(callback), nullptr);
+ expected = info1;
+ sampler.Unregister(info1);
+
+ // Unset the callback.
+ EXPECT_EQ(callback, sampler.SetDisposeCallback(nullptr));
+ expected = nullptr; // no more calls.
+ sampler.Unregister(info2);
+}
+
+} // namespace
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/have_sse.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/have_sse.h
index 293478895b6..e75e1a16d32 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/have_sse.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/have_sse.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,33 +16,34 @@
#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
-#ifndef SWISSTABLE_HAVE_SSE2
+#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#if defined(__SSE2__) || \
(defined(_MSC_VER) && \
(defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
-#define SWISSTABLE_HAVE_SSE2 1
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 1
#else
-#define SWISSTABLE_HAVE_SSE2 0
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 0
#endif
#endif
-#ifndef SWISSTABLE_HAVE_SSSE3
+#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#ifdef __SSSE3__
-#define SWISSTABLE_HAVE_SSSE3 1
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 1
#else
-#define SWISSTABLE_HAVE_SSSE3 0
+#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 0
#endif
#endif
-#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 && \
+ !ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#error "Bad configuration!"
#endif
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
#include <emmintrin.h>
#endif
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
#include <tmmintrin.h>
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/inlined_vector.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/inlined_vector.h
new file mode 100644
index 00000000000..b8aec45b79b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/inlined_vector.h
@@ -0,0 +1,967 @@
+// 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_INLINED_VECTOR_INTERNAL_H_
+#define ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "absl/base/macros.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace inlined_vector_internal {
+
+// GCC does not deal very well with the below code
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+template <typename Iterator>
+using IsAtLeastForwardIterator = std::is_convertible<
+ typename std::iterator_traits<Iterator>::iterator_category,
+ std::forward_iterator_tag>;
+
+template <typename AllocatorType,
+ typename ValueType =
+ typename absl::allocator_traits<AllocatorType>::value_type>
+using IsMemcpyOk =
+ absl::conjunction<std::is_same<AllocatorType, std::allocator<ValueType>>,
+ absl::is_trivially_copy_constructible<ValueType>,
+ absl::is_trivially_copy_assignable<ValueType>,
+ absl::is_trivially_destructible<ValueType>>;
+
+template <typename AllocatorType, typename Pointer, typename SizeType>
+void DestroyElements(AllocatorType* alloc_ptr, Pointer destroy_first,
+ SizeType destroy_size) {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+
+ if (destroy_first != nullptr) {
+ for (auto i = destroy_size; i != 0;) {
+ --i;
+ AllocatorTraits::destroy(*alloc_ptr, destroy_first + i);
+ }
+
+#if !defined(NDEBUG)
+ {
+ using ValueType = typename AllocatorTraits::value_type;
+
+ // Overwrite unused memory with `0xab` so we can catch uninitialized
+ // usage.
+ //
+ // Cast to `void*` to tell the compiler that we don't care that we might
+ // be scribbling on a vtable pointer.
+ void* memory_ptr = destroy_first;
+ auto memory_size = destroy_size * sizeof(ValueType);
+ std::memset(memory_ptr, 0xab, memory_size);
+ }
+#endif // !defined(NDEBUG)
+ }
+}
+
+// If kUseMemcpy is true, memcpy(dst, src, n); else do nothing.
+// Useful to avoid compiler warnings when memcpy() is used for T values
+// that are not trivially copyable in non-reachable code.
+template <bool kUseMemcpy>
+inline void MemcpyIfAllowed(void* dst, const void* src, size_t n);
+
+// memcpy when allowed.
+template <>
+inline void MemcpyIfAllowed<true>(void* dst, const void* src, size_t n) {
+ memcpy(dst, src, n);
+}
+
+// Do nothing for types that are not memcpy-able. This function is only
+// called from non-reachable branches.
+template <>
+inline void MemcpyIfAllowed<false>(void*, const void*, size_t) {}
+
+template <typename AllocatorType, typename Pointer, typename ValueAdapter,
+ typename SizeType>
+void ConstructElements(AllocatorType* alloc_ptr, Pointer construct_first,
+ ValueAdapter* values_ptr, SizeType construct_size) {
+ for (SizeType i = 0; i < construct_size; ++i) {
+ ABSL_INTERNAL_TRY {
+ values_ptr->ConstructNext(alloc_ptr, construct_first + i);
+ }
+ ABSL_INTERNAL_CATCH_ANY {
+ inlined_vector_internal::DestroyElements(alloc_ptr, construct_first, i);
+ ABSL_INTERNAL_RETHROW;
+ }
+ }
+}
+
+template <typename Pointer, typename ValueAdapter, typename SizeType>
+void AssignElements(Pointer assign_first, ValueAdapter* values_ptr,
+ SizeType assign_size) {
+ for (SizeType i = 0; i < assign_size; ++i) {
+ values_ptr->AssignNext(assign_first + i);
+ }
+}
+
+template <typename AllocatorType>
+struct StorageView {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using Pointer = typename AllocatorTraits::pointer;
+ using SizeType = typename AllocatorTraits::size_type;
+
+ Pointer data;
+ SizeType size;
+ SizeType capacity;
+};
+
+template <typename AllocatorType, typename Iterator>
+class IteratorValueAdapter {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using Pointer = typename AllocatorTraits::pointer;
+
+ public:
+ explicit IteratorValueAdapter(const Iterator& it) : it_(it) {}
+
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at, *it_);
+ ++it_;
+ }
+
+ void AssignNext(Pointer assign_at) {
+ *assign_at = *it_;
+ ++it_;
+ }
+
+ private:
+ Iterator it_;
+};
+
+template <typename AllocatorType>
+class CopyValueAdapter {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using ValueType = typename AllocatorTraits::value_type;
+ using Pointer = typename AllocatorTraits::pointer;
+ using ConstPointer = typename AllocatorTraits::const_pointer;
+
+ public:
+ explicit CopyValueAdapter(const ValueType& v) : ptr_(std::addressof(v)) {}
+
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at, *ptr_);
+ }
+
+ void AssignNext(Pointer assign_at) { *assign_at = *ptr_; }
+
+ private:
+ ConstPointer ptr_;
+};
+
+template <typename AllocatorType>
+class DefaultValueAdapter {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using ValueType = typename AllocatorTraits::value_type;
+ using Pointer = typename AllocatorTraits::pointer;
+
+ public:
+ explicit DefaultValueAdapter() {}
+
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at);
+ }
+
+ void AssignNext(Pointer assign_at) { *assign_at = ValueType(); }
+};
+
+template <typename AllocatorType>
+class AllocationTransaction {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using Pointer = typename AllocatorTraits::pointer;
+ using SizeType = typename AllocatorTraits::size_type;
+
+ public:
+ explicit AllocationTransaction(AllocatorType* alloc_ptr)
+ : alloc_data_(*alloc_ptr, nullptr) {}
+
+ ~AllocationTransaction() {
+ if (DidAllocate()) {
+ AllocatorTraits::deallocate(GetAllocator(), GetData(), GetCapacity());
+ }
+ }
+
+ AllocationTransaction(const AllocationTransaction&) = delete;
+ void operator=(const AllocationTransaction&) = delete;
+
+ AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); }
+ Pointer& GetData() { return alloc_data_.template get<1>(); }
+ SizeType& GetCapacity() { return capacity_; }
+
+ bool DidAllocate() { return GetData() != nullptr; }
+ Pointer Allocate(SizeType capacity) {
+ GetData() = AllocatorTraits::allocate(GetAllocator(), capacity);
+ GetCapacity() = capacity;
+ return GetData();
+ }
+
+ void Reset() {
+ GetData() = nullptr;
+ GetCapacity() = 0;
+ }
+
+ private:
+ container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+ SizeType capacity_ = 0;
+};
+
+template <typename AllocatorType>
+class ConstructionTransaction {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
+ using Pointer = typename AllocatorTraits::pointer;
+ using SizeType = typename AllocatorTraits::size_type;
+
+ public:
+ explicit ConstructionTransaction(AllocatorType* alloc_ptr)
+ : alloc_data_(*alloc_ptr, nullptr) {}
+
+ ~ConstructionTransaction() {
+ if (DidConstruct()) {
+ inlined_vector_internal::DestroyElements(std::addressof(GetAllocator()),
+ GetData(), GetSize());
+ }
+ }
+
+ ConstructionTransaction(const ConstructionTransaction&) = delete;
+ void operator=(const ConstructionTransaction&) = delete;
+
+ AllocatorType& GetAllocator() { return alloc_data_.template get<0>(); }
+ Pointer& GetData() { return alloc_data_.template get<1>(); }
+ SizeType& GetSize() { return size_; }
+
+ bool DidConstruct() { return GetData() != nullptr; }
+ template <typename ValueAdapter>
+ void Construct(Pointer data, ValueAdapter* values_ptr, SizeType size) {
+ inlined_vector_internal::ConstructElements(std::addressof(GetAllocator()),
+ data, values_ptr, size);
+ GetData() = data;
+ GetSize() = size;
+ }
+ void Commit() {
+ GetData() = nullptr;
+ GetSize() = 0;
+ }
+
+ private:
+ container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+ SizeType size_ = 0;
+};
+
+template <typename T, size_t N, typename A>
+class Storage {
+ public:
+ using AllocatorTraits = absl::allocator_traits<A>;
+ using allocator_type = typename AllocatorTraits::allocator_type;
+ 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;
+
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using RValueReference = value_type&&;
+ using iterator = pointer;
+ using const_iterator = const_pointer;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using MoveIterator = std::move_iterator<iterator>;
+ using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<allocator_type>;
+
+ using StorageView = inlined_vector_internal::StorageView<allocator_type>;
+
+ template <typename Iterator>
+ using IteratorValueAdapter =
+ inlined_vector_internal::IteratorValueAdapter<allocator_type, Iterator>;
+ using CopyValueAdapter =
+ inlined_vector_internal::CopyValueAdapter<allocator_type>;
+ using DefaultValueAdapter =
+ inlined_vector_internal::DefaultValueAdapter<allocator_type>;
+
+ using AllocationTransaction =
+ inlined_vector_internal::AllocationTransaction<allocator_type>;
+ using ConstructionTransaction =
+ inlined_vector_internal::ConstructionTransaction<allocator_type>;
+
+ static size_type NextCapacity(size_type current_capacity) {
+ return current_capacity * 2;
+ }
+
+ static size_type ComputeCapacity(size_type current_capacity,
+ size_type requested_capacity) {
+ return (std::max)(NextCapacity(current_capacity), requested_capacity);
+ }
+
+ // ---------------------------------------------------------------------------
+ // Storage Constructors and Destructor
+ // ---------------------------------------------------------------------------
+
+ Storage() : metadata_(allocator_type(), /* size and is_allocated */ 0) {}
+
+ explicit Storage(const allocator_type& alloc)
+ : metadata_(alloc, /* size and is_allocated */ 0) {}
+
+ ~Storage() {
+ if (GetSizeAndIsAllocated() == 0) {
+ // Empty and not allocated; nothing to do.
+ } else if (IsMemcpyOk::value) {
+ // No destructors need to be run; just deallocate if necessary.
+ DeallocateIfAllocated();
+ } else {
+ DestroyContents();
+ }
+ }
+
+ // ---------------------------------------------------------------------------
+ // Storage Member Accessors
+ // ---------------------------------------------------------------------------
+
+ size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
+
+ const size_type& GetSizeAndIsAllocated() const {
+ return metadata_.template get<1>();
+ }
+
+ size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; }
+
+ bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
+
+ pointer GetAllocatedData() { return data_.allocated.allocated_data; }
+
+ const_pointer GetAllocatedData() const {
+ return data_.allocated.allocated_data;
+ }
+
+ pointer GetInlinedData() {
+ return reinterpret_cast<pointer>(
+ std::addressof(data_.inlined.inlined_data[0]));
+ }
+
+ const_pointer GetInlinedData() const {
+ return reinterpret_cast<const_pointer>(
+ std::addressof(data_.inlined.inlined_data[0]));
+ }
+
+ size_type GetAllocatedCapacity() const {
+ return data_.allocated.allocated_capacity;
+ }
+
+ size_type GetInlinedCapacity() const { return static_cast<size_type>(N); }
+
+ StorageView MakeStorageView() {
+ return GetIsAllocated()
+ ? StorageView{GetAllocatedData(), GetSize(),
+ GetAllocatedCapacity()}
+ : StorageView{GetInlinedData(), GetSize(), GetInlinedCapacity()};
+ }
+
+ allocator_type* GetAllocPtr() {
+ return std::addressof(metadata_.template get<0>());
+ }
+
+ const allocator_type* GetAllocPtr() const {
+ return std::addressof(metadata_.template get<0>());
+ }
+
+ // ---------------------------------------------------------------------------
+ // Storage Member Mutators
+ // ---------------------------------------------------------------------------
+
+ ABSL_ATTRIBUTE_NOINLINE void InitFrom(const Storage& other);
+
+ template <typename ValueAdapter>
+ void Initialize(ValueAdapter values, size_type new_size);
+
+ template <typename ValueAdapter>
+ void Assign(ValueAdapter values, size_type new_size);
+
+ template <typename ValueAdapter>
+ void Resize(ValueAdapter values, size_type new_size);
+
+ template <typename ValueAdapter>
+ iterator Insert(const_iterator pos, ValueAdapter values,
+ size_type insert_count);
+
+ template <typename... Args>
+ reference EmplaceBack(Args&&... args);
+
+ iterator Erase(const_iterator from, const_iterator to);
+
+ void Reserve(size_type requested_capacity);
+
+ void ShrinkToFit();
+
+ void Swap(Storage* other_storage_ptr);
+
+ void SetIsAllocated() {
+ GetSizeAndIsAllocated() |= static_cast<size_type>(1);
+ }
+
+ void UnsetIsAllocated() {
+ GetSizeAndIsAllocated() &= ((std::numeric_limits<size_type>::max)() - 1);
+ }
+
+ void SetSize(size_type size) {
+ GetSizeAndIsAllocated() =
+ (size << 1) | static_cast<size_type>(GetIsAllocated());
+ }
+
+ void SetAllocatedSize(size_type size) {
+ GetSizeAndIsAllocated() = (size << 1) | static_cast<size_type>(1);
+ }
+
+ void SetInlinedSize(size_type size) {
+ GetSizeAndIsAllocated() = size << static_cast<size_type>(1);
+ }
+
+ void AddSize(size_type count) {
+ GetSizeAndIsAllocated() += count << static_cast<size_type>(1);
+ }
+
+ void SubtractSize(size_type count) {
+ assert(count <= GetSize());
+
+ GetSizeAndIsAllocated() -= count << static_cast<size_type>(1);
+ }
+
+ void SetAllocatedData(pointer data, size_type capacity) {
+ data_.allocated.allocated_data = data;
+ data_.allocated.allocated_capacity = capacity;
+ }
+
+ void AcquireAllocatedData(AllocationTransaction* allocation_tx_ptr) {
+ SetAllocatedData(allocation_tx_ptr->GetData(),
+ allocation_tx_ptr->GetCapacity());
+
+ allocation_tx_ptr->Reset();
+ }
+
+ void MemcpyFrom(const Storage& other_storage) {
+ assert(IsMemcpyOk::value || other_storage.GetIsAllocated());
+
+ GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated();
+ data_ = other_storage.data_;
+ }
+
+ void DeallocateIfAllocated() {
+ if (GetIsAllocated()) {
+ AllocatorTraits::deallocate(*GetAllocPtr(), GetAllocatedData(),
+ GetAllocatedCapacity());
+ }
+ }
+
+ private:
+ ABSL_ATTRIBUTE_NOINLINE void DestroyContents();
+
+ using Metadata =
+ container_internal::CompressedTuple<allocator_type, size_type>;
+
+ struct Allocated {
+ pointer allocated_data;
+ size_type allocated_capacity;
+ };
+
+ struct Inlined {
+ alignas(value_type) char inlined_data[sizeof(value_type[N])];
+ };
+
+ union Data {
+ Allocated allocated;
+ Inlined inlined;
+ };
+
+ template <typename... Args>
+ ABSL_ATTRIBUTE_NOINLINE reference EmplaceBackSlow(Args&&... args);
+
+ Metadata metadata_;
+ Data data_;
+};
+
+template <typename T, size_t N, typename A>
+void Storage<T, N, A>::DestroyContents() {
+ pointer data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), data, GetSize());
+ DeallocateIfAllocated();
+}
+
+template <typename T, size_t N, typename A>
+void Storage<T, N, A>::InitFrom(const Storage& other) {
+ const auto n = other.GetSize();
+ assert(n > 0); // Empty sources handled handled in caller.
+ const_pointer src;
+ pointer dst;
+ if (!other.GetIsAllocated()) {
+ dst = GetInlinedData();
+ src = other.GetInlinedData();
+ } else {
+ // Because this is only called from the `InlinedVector` constructors, it's
+ // safe to take on the allocation with size `0`. If `ConstructElements(...)`
+ // throws, deallocation will be automatically handled by `~Storage()`.
+ size_type new_capacity = ComputeCapacity(GetInlinedCapacity(), n);
+ dst = AllocatorTraits::allocate(*GetAllocPtr(), new_capacity);
+ SetAllocatedData(dst, new_capacity);
+ src = other.GetAllocatedData();
+ }
+ if (IsMemcpyOk::value) {
+ MemcpyIfAllowed<IsMemcpyOk::value>(dst, src, sizeof(dst[0]) * n);
+ } else {
+ auto values = IteratorValueAdapter<const_pointer>(src);
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), dst, &values, n);
+ }
+ GetSizeAndIsAllocated() = other.GetSizeAndIsAllocated();
+}
+
+template <typename T, size_t N, typename A>
+template <typename ValueAdapter>
+auto Storage<T, N, A>::Initialize(ValueAdapter values, size_type new_size)
+ -> void {
+ // Only callable from constructors!
+ assert(!GetIsAllocated());
+ assert(GetSize() == 0);
+
+ pointer construct_data;
+ if (new_size > GetInlinedCapacity()) {
+ // Because this is only called from the `InlinedVector` constructors, it's
+ // safe to take on the allocation with size `0`. If `ConstructElements(...)`
+ // throws, deallocation will be automatically handled by `~Storage()`.
+ size_type new_capacity = ComputeCapacity(GetInlinedCapacity(), new_size);
+ construct_data = AllocatorTraits::allocate(*GetAllocPtr(), new_capacity);
+ SetAllocatedData(construct_data, new_capacity);
+ SetIsAllocated();
+ } else {
+ construct_data = GetInlinedData();
+ }
+
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), construct_data,
+ &values, new_size);
+
+ // Since the initial size was guaranteed to be `0` and the allocated bit is
+ // already correct for either case, *adding* `new_size` gives us the correct
+ // result faster than setting it directly.
+ AddSize(new_size);
+}
+
+template <typename T, size_t N, typename A>
+template <typename ValueAdapter>
+auto Storage<T, N, A>::Assign(ValueAdapter values, size_type new_size) -> void {
+ StorageView storage_view = MakeStorageView();
+
+ AllocationTransaction allocation_tx(GetAllocPtr());
+
+ absl::Span<value_type> assign_loop;
+ absl::Span<value_type> construct_loop;
+ absl::Span<value_type> destroy_loop;
+
+ if (new_size > storage_view.capacity) {
+ size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
+ construct_loop = {allocation_tx.Allocate(new_capacity), new_size};
+ destroy_loop = {storage_view.data, storage_view.size};
+ } else if (new_size > storage_view.size) {
+ assign_loop = {storage_view.data, storage_view.size};
+ construct_loop = {storage_view.data + storage_view.size,
+ new_size - storage_view.size};
+ } else {
+ assign_loop = {storage_view.data, new_size};
+ destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};
+ }
+
+ inlined_vector_internal::AssignElements(assign_loop.data(), &values,
+ assign_loop.size());
+
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), construct_loop.data(), &values, construct_loop.size());
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), destroy_loop.data(),
+ destroy_loop.size());
+
+ if (allocation_tx.DidAllocate()) {
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+ SetIsAllocated();
+ }
+
+ SetSize(new_size);
+}
+
+template <typename T, size_t N, typename A>
+template <typename ValueAdapter>
+auto Storage<T, N, A>::Resize(ValueAdapter values, size_type new_size) -> void {
+ StorageView storage_view = MakeStorageView();
+ auto* const base = storage_view.data;
+ const size_type size = storage_view.size;
+ auto* alloc = GetAllocPtr();
+ if (new_size <= size) {
+ // Destroy extra old elements.
+ inlined_vector_internal::DestroyElements(alloc, base + new_size,
+ size - new_size);
+ } else if (new_size <= storage_view.capacity) {
+ // Construct new elements in place.
+ inlined_vector_internal::ConstructElements(alloc, base + size, &values,
+ new_size - size);
+ } else {
+ // Steps:
+ // a. Allocate new backing store.
+ // b. Construct new elements in new backing store.
+ // c. Move existing elements from old backing store to now.
+ // d. Destroy all elements in old backing store.
+ // Use transactional wrappers for the first two steps so we can roll
+ // back if necessary due to exceptions.
+ AllocationTransaction allocation_tx(alloc);
+ size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
+ pointer new_data = allocation_tx.Allocate(new_capacity);
+
+ ConstructionTransaction construction_tx(alloc);
+ construction_tx.Construct(new_data + size, &values, new_size - size);
+
+ IteratorValueAdapter<MoveIterator> move_values((MoveIterator(base)));
+ inlined_vector_internal::ConstructElements(alloc, new_data, &move_values,
+ size);
+
+ inlined_vector_internal::DestroyElements(alloc, base, size);
+ construction_tx.Commit();
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+ SetIsAllocated();
+ }
+ SetSize(new_size);
+}
+
+template <typename T, size_t N, typename A>
+template <typename ValueAdapter>
+auto Storage<T, N, A>::Insert(const_iterator pos, ValueAdapter values,
+ size_type insert_count) -> iterator {
+ StorageView storage_view = MakeStorageView();
+
+ size_type insert_index =
+ std::distance(const_iterator(storage_view.data), pos);
+ size_type insert_end_index = insert_index + insert_count;
+ size_type new_size = storage_view.size + insert_count;
+
+ if (new_size > storage_view.capacity) {
+ AllocationTransaction allocation_tx(GetAllocPtr());
+ ConstructionTransaction construction_tx(GetAllocPtr());
+ ConstructionTransaction move_construciton_tx(GetAllocPtr());
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+
+ size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
+ pointer new_data = allocation_tx.Allocate(new_capacity);
+
+ construction_tx.Construct(new_data + insert_index, &values, insert_count);
+
+ move_construciton_tx.Construct(new_data, &move_values, insert_index);
+
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), new_data + insert_end_index, &move_values,
+ storage_view.size - insert_index);
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
+
+ construction_tx.Commit();
+ move_construciton_tx.Commit();
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+
+ SetAllocatedSize(new_size);
+ return iterator(new_data + insert_index);
+ } else {
+ size_type move_construction_destination_index =
+ (std::max)(insert_end_index, storage_view.size);
+
+ ConstructionTransaction move_construction_tx(GetAllocPtr());
+
+ IteratorValueAdapter<MoveIterator> move_construction_values(
+ MoveIterator(storage_view.data +
+ (move_construction_destination_index - insert_count)));
+ absl::Span<value_type> move_construction = {
+ storage_view.data + move_construction_destination_index,
+ new_size - move_construction_destination_index};
+
+ pointer move_assignment_values = storage_view.data + insert_index;
+ absl::Span<value_type> move_assignment = {
+ storage_view.data + insert_end_index,
+ move_construction_destination_index - insert_end_index};
+
+ absl::Span<value_type> insert_assignment = {move_assignment_values,
+ move_construction.size()};
+
+ absl::Span<value_type> insert_construction = {
+ insert_assignment.data() + insert_assignment.size(),
+ insert_count - insert_assignment.size()};
+
+ move_construction_tx.Construct(move_construction.data(),
+ &move_construction_values,
+ move_construction.size());
+
+ for (pointer destination = move_assignment.data() + move_assignment.size(),
+ last_destination = move_assignment.data(),
+ source = move_assignment_values + move_assignment.size();
+ ;) {
+ --destination;
+ --source;
+ if (destination < last_destination) break;
+ *destination = std::move(*source);
+ }
+
+ inlined_vector_internal::AssignElements(insert_assignment.data(), &values,
+ insert_assignment.size());
+
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), insert_construction.data(), &values,
+ insert_construction.size());
+
+ move_construction_tx.Commit();
+
+ AddSize(insert_count);
+ return iterator(storage_view.data + insert_index);
+ }
+}
+
+template <typename T, size_t N, typename A>
+template <typename... Args>
+auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> reference {
+ StorageView storage_view = MakeStorageView();
+ const auto n = storage_view.size;
+ if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) {
+ // Fast path; new element fits.
+ pointer last_ptr = storage_view.data + n;
+ AllocatorTraits::construct(*GetAllocPtr(), last_ptr,
+ std::forward<Args>(args)...);
+ AddSize(1);
+ return *last_ptr;
+ }
+ // TODO(b/173712035): Annotate with musttail attribute to prevent regression.
+ return EmplaceBackSlow(std::forward<Args>(args)...);
+}
+
+template <typename T, size_t N, typename A>
+template <typename... Args>
+auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> reference {
+ StorageView storage_view = MakeStorageView();
+ AllocationTransaction allocation_tx(GetAllocPtr());
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+ size_type new_capacity = NextCapacity(storage_view.capacity);
+ pointer construct_data = allocation_tx.Allocate(new_capacity);
+ pointer last_ptr = construct_data + storage_view.size;
+
+ // Construct new element.
+ AllocatorTraits::construct(*GetAllocPtr(), last_ptr,
+ std::forward<Args>(args)...);
+ // Move elements from old backing store to new backing store.
+ ABSL_INTERNAL_TRY {
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), allocation_tx.GetData(), &move_values,
+ storage_view.size);
+ }
+ ABSL_INTERNAL_CATCH_ANY {
+ AllocatorTraits::destroy(*GetAllocPtr(), last_ptr);
+ ABSL_INTERNAL_RETHROW;
+ }
+ // Destroy elements in old backing store.
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
+
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+ SetIsAllocated();
+ AddSize(1);
+ return *last_ptr;
+}
+
+template <typename T, size_t N, typename A>
+auto Storage<T, N, A>::Erase(const_iterator from, const_iterator to)
+ -> iterator {
+ StorageView storage_view = MakeStorageView();
+
+ size_type erase_size = std::distance(from, to);
+ size_type erase_index =
+ std::distance(const_iterator(storage_view.data), from);
+ size_type erase_end_index = erase_index + erase_size;
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data + erase_end_index));
+
+ inlined_vector_internal::AssignElements(storage_view.data + erase_index,
+ &move_values,
+ storage_view.size - erase_end_index);
+
+ inlined_vector_internal::DestroyElements(
+ GetAllocPtr(), storage_view.data + (storage_view.size - erase_size),
+ erase_size);
+
+ SubtractSize(erase_size);
+ return iterator(storage_view.data + erase_index);
+}
+
+template <typename T, size_t N, typename A>
+auto Storage<T, N, A>::Reserve(size_type requested_capacity) -> void {
+ StorageView storage_view = MakeStorageView();
+
+ if (ABSL_PREDICT_FALSE(requested_capacity <= storage_view.capacity)) return;
+
+ AllocationTransaction allocation_tx(GetAllocPtr());
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+
+ size_type new_capacity =
+ ComputeCapacity(storage_view.capacity, requested_capacity);
+ pointer new_data = allocation_tx.Allocate(new_capacity);
+
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), new_data,
+ &move_values, storage_view.size);
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
+
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+ SetIsAllocated();
+}
+
+template <typename T, size_t N, typename A>
+auto Storage<T, N, A>::ShrinkToFit() -> void {
+ // May only be called on allocated instances!
+ assert(GetIsAllocated());
+
+ StorageView storage_view{GetAllocatedData(), GetSize(),
+ GetAllocatedCapacity()};
+
+ if (ABSL_PREDICT_FALSE(storage_view.size == storage_view.capacity)) return;
+
+ AllocationTransaction allocation_tx(GetAllocPtr());
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+
+ pointer construct_data;
+ if (storage_view.size > GetInlinedCapacity()) {
+ size_type new_capacity = storage_view.size;
+ construct_data = allocation_tx.Allocate(new_capacity);
+ } else {
+ construct_data = GetInlinedData();
+ }
+
+ ABSL_INTERNAL_TRY {
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), construct_data,
+ &move_values, storage_view.size);
+ }
+ ABSL_INTERNAL_CATCH_ANY {
+ SetAllocatedData(storage_view.data, storage_view.capacity);
+ ABSL_INTERNAL_RETHROW;
+ }
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
+
+ AllocatorTraits::deallocate(*GetAllocPtr(), storage_view.data,
+ storage_view.capacity);
+
+ if (allocation_tx.DidAllocate()) {
+ AcquireAllocatedData(&allocation_tx);
+ } else {
+ UnsetIsAllocated();
+ }
+}
+
+template <typename T, size_t N, typename A>
+auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
+ using std::swap;
+ assert(this != other_storage_ptr);
+
+ if (GetIsAllocated() && other_storage_ptr->GetIsAllocated()) {
+ swap(data_.allocated, other_storage_ptr->data_.allocated);
+ } else if (!GetIsAllocated() && !other_storage_ptr->GetIsAllocated()) {
+ Storage* small_ptr = this;
+ Storage* large_ptr = other_storage_ptr;
+ if (small_ptr->GetSize() > large_ptr->GetSize()) swap(small_ptr, large_ptr);
+
+ for (size_type i = 0; i < small_ptr->GetSize(); ++i) {
+ swap(small_ptr->GetInlinedData()[i], large_ptr->GetInlinedData()[i]);
+ }
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(large_ptr->GetInlinedData() + small_ptr->GetSize()));
+
+ inlined_vector_internal::ConstructElements(
+ large_ptr->GetAllocPtr(),
+ small_ptr->GetInlinedData() + small_ptr->GetSize(), &move_values,
+ large_ptr->GetSize() - small_ptr->GetSize());
+
+ inlined_vector_internal::DestroyElements(
+ large_ptr->GetAllocPtr(),
+ large_ptr->GetInlinedData() + small_ptr->GetSize(),
+ large_ptr->GetSize() - small_ptr->GetSize());
+ } else {
+ Storage* allocated_ptr = this;
+ Storage* inlined_ptr = other_storage_ptr;
+ if (!allocated_ptr->GetIsAllocated()) swap(allocated_ptr, inlined_ptr);
+
+ StorageView allocated_storage_view{allocated_ptr->GetAllocatedData(),
+ allocated_ptr->GetSize(),
+ allocated_ptr->GetAllocatedCapacity()};
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(inlined_ptr->GetInlinedData()));
+
+ ABSL_INTERNAL_TRY {
+ inlined_vector_internal::ConstructElements(
+ inlined_ptr->GetAllocPtr(), allocated_ptr->GetInlinedData(),
+ &move_values, inlined_ptr->GetSize());
+ }
+ ABSL_INTERNAL_CATCH_ANY {
+ allocated_ptr->SetAllocatedData(allocated_storage_view.data,
+ allocated_storage_view.capacity);
+ ABSL_INTERNAL_RETHROW;
+ }
+
+ inlined_vector_internal::DestroyElements(inlined_ptr->GetAllocPtr(),
+ inlined_ptr->GetInlinedData(),
+ inlined_ptr->GetSize());
+
+ inlined_ptr->SetAllocatedData(allocated_storage_view.data,
+ allocated_storage_view.capacity);
+ }
+
+ swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated());
+ swap(*GetAllocPtr(), *other_storage_ptr->GetAllocPtr());
+}
+
+// End ignore "maybe-uninitialized"
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
+
+} // namespace inlined_vector_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_CONTAINER_INTERNAL_INLINED_VECTOR_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout.h
index 3d21ac963b4..a59a2430591 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -163,6 +163,7 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
+
#include <ostream>
#include <string>
#include <tuple>
@@ -170,15 +171,16 @@
#include <typeinfo>
#include <utility>
-#ifdef ADDRESS_SANITIZER
-#include <sanitizer/asan_interface.h>
-#endif
-
+#include "absl/base/config.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
+
#if defined(__GXX_RTTI)
#define ABSL_INTERNAL_HAS_CXA_DEMANGLE
#endif
@@ -188,6 +190,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
// A type wrapper that instructs `Layout` to use the specific alignment for the
@@ -401,7 +404,7 @@ class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>,
constexpr size_t Offset() const {
static_assert(N < NumOffsets, "Index out of bounds");
return adl_barrier::Align(
- Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1],
ElementAlignment<N>::value);
}
@@ -594,7 +597,7 @@ class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>,
constexpr size_t AllocSize() const {
static_assert(NumTypes == NumSizes, "You must specify sizes of all fields");
return Offset<NumTypes - 1>() +
- SizeOf<ElementType<NumTypes - 1>>() * size_[NumTypes - 1];
+ SizeOf<ElementType<NumTypes - 1>>::value * size_[NumTypes - 1];
}
// If built with --config=asan, poisons padding bytes (if any) in the
@@ -613,12 +616,12 @@ class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>,
void PoisonPadding(const Char* p) const {
static_assert(N < NumOffsets, "Index out of bounds");
(void)p;
-#ifdef ADDRESS_SANITIZER
+#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>>() * size_[N - 1];
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1];
ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
}
#endif
@@ -642,8 +645,9 @@ class LayoutImpl<std::tuple<Elements...>, absl::index_sequence<SizeSeq...>,
// produce "unsigned*" where another produces "unsigned int *".
std::string DebugString() const {
const auto offsets = Offsets();
- const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>()...};
- const std::string types[] = {adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
+ 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, "[", size_[i], "]; @", offsets[i + 1], types[i + 1],
@@ -733,6 +737,7 @@ class Layout : public internal_layout::LayoutType<sizeof...(Ts), Ts...> {
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_LAYOUT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_benchmark.cc
new file mode 100644
index 00000000000..d8636e8d5a4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_benchmark.cc
@@ -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.
+//
+// Every benchmark should have the same performance as the corresponding
+// headroom benchmark.
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/internal/layout.h"
+#include "benchmark/benchmark.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+namespace {
+
+using ::benchmark::DoNotOptimize;
+
+using Int128 = int64_t[2];
+
+// This benchmark provides the upper bound on performance for BM_OffsetConstant.
+template <size_t Offset, class... Ts>
+void BM_OffsetConstantHeadroom(benchmark::State& state) {
+ for (auto _ : state) {
+ DoNotOptimize(Offset);
+ }
+}
+
+template <size_t Offset, class... Ts>
+void BM_OffsetConstant(benchmark::State& state) {
+ using L = Layout<Ts...>;
+ ABSL_RAW_CHECK(L::Partial(3, 5, 7).template Offset<3>() == Offset,
+ "Invalid offset");
+ for (auto _ : state) {
+ DoNotOptimize(L::Partial(3, 5, 7).template Offset<3>());
+ }
+}
+
+template <class... Ts>
+size_t VariableOffset(size_t n, size_t m, size_t k);
+
+template <>
+size_t VariableOffset<int8_t, int16_t, int32_t, Int128>(size_t n, size_t m,
+ size_t k) {
+ auto Align = [](size_t n, size_t m) { return (n + m - 1) & ~(m - 1); };
+ return Align(Align(Align(n * 1, 2) + m * 2, 4) + k * 4, 8);
+}
+
+template <>
+size_t VariableOffset<Int128, int32_t, int16_t, int8_t>(size_t n, size_t m,
+ size_t k) {
+ // No alignment is necessary.
+ return n * 16 + m * 4 + k * 2;
+}
+
+// This benchmark provides the upper bound on performance for BM_OffsetVariable.
+template <size_t Offset, class... Ts>
+void BM_OffsetVariableHeadroom(benchmark::State& state) {
+ size_t n = 3;
+ size_t m = 5;
+ size_t k = 7;
+ ABSL_RAW_CHECK(VariableOffset<Ts...>(n, m, k) == Offset, "Invalid offset");
+ for (auto _ : state) {
+ DoNotOptimize(n);
+ DoNotOptimize(m);
+ DoNotOptimize(k);
+ DoNotOptimize(VariableOffset<Ts...>(n, m, k));
+ }
+}
+
+template <size_t Offset, class... Ts>
+void BM_OffsetVariable(benchmark::State& state) {
+ using L = Layout<Ts...>;
+ size_t n = 3;
+ size_t m = 5;
+ size_t k = 7;
+ ABSL_RAW_CHECK(L::Partial(n, m, k).template Offset<3>() == Offset,
+ "Inavlid offset");
+ for (auto _ : state) {
+ DoNotOptimize(n);
+ DoNotOptimize(m);
+ DoNotOptimize(k);
+ DoNotOptimize(L::Partial(n, m, k).template Offset<3>());
+ }
+}
+
+// Run all benchmarks in two modes:
+//
+// Layout with padding: int8_t[3], int16_t[5], int32_t[7], Int128[?].
+// Layout without padding: Int128[3], int32_t[5], int16_t[7], int8_t[?].
+
+#define OFFSET_BENCHMARK(NAME, OFFSET, T1, T2, T3, T4) \
+ auto& NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4 = \
+ NAME<OFFSET, T1, T2, T3, T4>; \
+ BENCHMARK(NAME##_##OFFSET##_##T1##_##T2##_##T3##_##T4)
+
+OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 48, int8_t, int16_t, int32_t,
+ Int128);
+OFFSET_BENCHMARK(BM_OffsetConstant, 48, int8_t, int16_t, int32_t, Int128);
+OFFSET_BENCHMARK(BM_OffsetConstantHeadroom, 82, Int128, int32_t, int16_t,
+ int8_t);
+OFFSET_BENCHMARK(BM_OffsetConstant, 82, Int128, int32_t, int16_t, int8_t);
+OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 48, int8_t, int16_t, int32_t,
+ Int128);
+OFFSET_BENCHMARK(BM_OffsetVariable, 48, int8_t, int16_t, int32_t, Int128);
+OFFSET_BENCHMARK(BM_OffsetVariableHeadroom, 82, Int128, int32_t, int16_t,
+ int8_t);
+OFFSET_BENCHMARK(BM_OffsetVariable, 82, Int128, int32_t, int16_t, int8_t);
+} // namespace
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_test.cc
index 301e9f7808f..1d7158ffc0b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/layout_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
// We need ::max_align_t because some libstdc++ versions don't provide
// std::max_align_t
#include <stddef.h>
+
#include <cstdint>
#include <memory>
#include <sstream>
@@ -24,10 +25,12 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/types/span.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -125,8 +128,10 @@ TEST(Layout, ElementTypes) {
{
using L = Layout<int32_t, int32_t>;
SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
- SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
- SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
+ SameType<std::tuple<int32_t, int32_t>,
+ decltype(L::Partial())::ElementTypes>();
+ SameType<std::tuple<int32_t, int32_t>,
+ decltype(L::Partial(0))::ElementTypes>();
}
{
using L = Layout<int8_t, int32_t, Int128>;
@@ -365,18 +370,21 @@ TEST(Layout, PointerByIndex) {
{
using L = Layout<int32_t>;
EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
}
{
using L = Layout<int32_t, int32_t>;
EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
- EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+ Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
EXPECT_EQ(12,
- Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
+ Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
+ EXPECT_EQ(
+ 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
}
@@ -384,39 +392,44 @@ TEST(Layout, PointerByIndex) {
using L = Layout<int8_t, int32_t, Int128>;
EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
- EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
+ EXPECT_EQ(4,
+ Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
+ EXPECT_EQ(8,
+ Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
EXPECT_EQ(0,
Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
EXPECT_EQ(0,
Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
EXPECT_EQ(0,
Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
+ EXPECT_EQ(
+ 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
EXPECT_EQ(8,
Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
EXPECT_EQ(0,
Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
+ EXPECT_EQ(
+ 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
EXPECT_EQ(24,
Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
EXPECT_EQ(
0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+ 0,
+ Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
EXPECT_EQ(
0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
EXPECT_EQ(
0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
EXPECT_EQ(
- 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+ 4,
+ Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
EXPECT_EQ(
8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
EXPECT_EQ(
@@ -425,7 +438,8 @@ TEST(Layout, PointerByIndex) {
24,
Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
EXPECT_EQ(
- 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+ 8,
+ Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -436,75 +450,78 @@ TEST(Layout, PointerByType) {
alignas(max_align_t) const unsigned char p[100] = {};
{
using L = Layout<int32_t>;
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 0,
+ Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
}
{
using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
EXPECT_EQ(
0,
- Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+ Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
EXPECT_EQ(
- 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
EXPECT_EQ(
- 8,
- Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
+ 4,
+ Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
EXPECT_EQ(
- 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+ 8,
+ Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
EXPECT_EQ(
- 24,
- Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
+ 0,
+ Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+ L::Partial(0, 0).Pointer<int32_t>(p))));
EXPECT_EQ(
0,
- Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+ Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
EXPECT_EQ(
0,
- Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<const Int128*>(
- L::Partial(0, 0, 0).Pointer<Int128>(p))));
+ Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+ L::Partial(1, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 8,
+ Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
EXPECT_EQ(
0,
- Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+ Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+ EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+ L::Partial(5, 3).Pointer<int32_t>(p))));
EXPECT_EQ(
- 4,
- Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+ 24,
+ Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+ L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
+ L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const Int128*>(
+ L::Partial(0, 0, 0).Pointer<Int128>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+ L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(4, Distance(p, Type<const int32_t*>(
+ L::Partial(1, 0, 0).Pointer<int32_t>(p))));
EXPECT_EQ(8, Distance(p, Type<const Int128*>(
L::Partial(1, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(
- 0,
- Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+ EXPECT_EQ(0, Distance(p, Type<const int8_t*>(
+ L::Partial(5, 3, 1).Pointer<int8_t>(p))));
EXPECT_EQ(24, Distance(p, Type<const Int128*>(
L::Partial(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(
- 8,
- Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+ EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
+ L::Partial(5, 3, 1).Pointer<int32_t>(p))));
EXPECT_EQ(24,
Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
}
}
@@ -545,15 +562,18 @@ TEST(Layout, MutablePointerByIndex) {
EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
- EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
+ EXPECT_EQ(4,
+ Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
EXPECT_EQ(24,
Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
+ EXPECT_EQ(8,
+ Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
@@ -565,48 +585,61 @@ TEST(Layout, MutablePointerByType) {
{
using L = Layout<int32_t>;
EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
}
{
using L = Layout<int8_t, int32_t, Int128>;
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
- EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+ EXPECT_EQ(4,
+ Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(8,
+ Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
EXPECT_EQ(0,
Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
EXPECT_EQ(8,
Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
- EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
+ EXPECT_EQ(0,
+ Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
EXPECT_EQ(24,
Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 0,
+ Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
EXPECT_EQ(
0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
- EXPECT_EQ(4,
- Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 4,
+ Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
EXPECT_EQ(
8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
- EXPECT_EQ(0,
- Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
+ EXPECT_EQ(
+ 0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
EXPECT_EQ(
24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
- EXPECT_EQ(8,
- Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
+ EXPECT_EQ(
+ 8,
+ Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
@@ -787,67 +820,72 @@ TEST(Layout, SliceByIndexData) {
{
using L = Layout<int32_t>;
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+ EXPECT_EQ(0,
+ Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
}
{
using L = Layout<int32_t, int32_t>;
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
EXPECT_EQ(
0,
- Distance(p,
- Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+ Distance(
+ p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
EXPECT_EQ(
12,
- Distance(p,
- Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
- EXPECT_EQ(12,
- Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
+ Distance(
+ p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
}
{
using L = Layout<int8_t, int32_t, Int128>;
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
EXPECT_EQ(
0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+ p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
EXPECT_EQ(
0,
- Distance(p,
- Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+ Distance(
+ p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+ 0,
+ Distance(
+ p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+ EXPECT_EQ(
+ 0,
+ Distance(
+ p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
EXPECT_EQ(
4,
- Distance(p,
- Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+ Distance(
+ p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+ 0,
+ Distance(
+ p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
EXPECT_EQ(
8,
- Distance(p,
- Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+ Distance(
+ p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+ p,
+ Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
0,
Distance(
@@ -861,7 +899,8 @@ TEST(Layout, SliceByIndexData) {
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+ p,
+ Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
4,
Distance(
@@ -875,7 +914,8 @@ TEST(Layout, SliceByIndexData) {
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+ p,
+ Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
EXPECT_EQ(
24,
Distance(
@@ -887,12 +927,14 @@ TEST(Layout, SliceByIndexData) {
p,
Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+ 0,
+ Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
EXPECT_EQ(
24,
Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
EXPECT_EQ(
- 8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+ 8,
+ Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
}
}
@@ -903,98 +945,94 @@ TEST(Layout, SliceByTypeData) {
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+ p,
+ Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+ p,
+ Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
+ 0,
+ Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
}
{
using L = Layout<int8_t, int32_t, Int128>;
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0, Distance(
- p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 0,
- Distance(
- p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
0,
Distance(
p,
- Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+ Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(
p,
- Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+ Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
- p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 8,
- Distance(
p,
- Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+ Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+ Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p))
+ .data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(0, 0).Slice<int32_t>(p))
+ .data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
+ Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p))
.data()));
- EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
- L::Partial(0, 0, 0).Slice<Int128>(p))
+ EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(1, 0).Slice<int32_t>(p))
.data()));
EXPECT_EQ(
0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
- EXPECT_EQ(
- 4,
- Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
+ Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
.data()));
+ EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(5, 3).Slice<int32_t>(p))
+ .data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+ L::Partial(0, 0, 0).Slice<int8_t>(p))
+ .data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(0, 0, 0).Slice<int32_t>(p))
+ .data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
+ L::Partial(0, 0, 0).Slice<Int128>(p))
+ .data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+ L::Partial(1, 0, 0).Slice<int8_t>(p))
+ .data()));
+ EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(1, 0, 0).Slice<int32_t>(p))
+ .data()));
EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
L::Partial(1, 0, 0).Slice<Int128>(p))
.data()));
- EXPECT_EQ(
- 0,
- Distance(
- p,
- Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+ EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>(
+ L::Partial(5, 3, 1).Slice<int8_t>(p))
+ .data()));
EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
L::Partial(5, 3, 1).Slice<Int128>(p))
.data()));
- EXPECT_EQ(
- 8,
- Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
- .data()));
+ EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>(
+ L::Partial(5, 3, 1).Slice<int32_t>(p))
+ .data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+ Distance(p,
+ Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
EXPECT_EQ(
24,
Distance(p,
Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
EXPECT_EQ(
- 8, Distance(
- p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+ 8,
+ Distance(
+ p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
}
}
@@ -1002,18 +1040,19 @@ TEST(Layout, MutableSliceByIndexData) {
alignas(max_align_t) unsigned char p[100];
{
using L = Layout<int32_t>;
- EXPECT_EQ(0,
- Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
}
{
using L = Layout<int32_t, int32_t>;
- EXPECT_EQ(0,
- Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
+ 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 0,
+ Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
EXPECT_EQ(
12,
Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
@@ -1022,55 +1061,63 @@ TEST(Layout, MutableSliceByIndexData) {
}
{
using L = Layout<int8_t, int32_t, Int128>;
- EXPECT_EQ(0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
- EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
+ 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+ 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
EXPECT_EQ(
- 4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+ 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+ 0,
+ Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+ 0,
+ Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+ Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 4,
+ Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
+ Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 8,
+ Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(
+ p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(
+ p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
EXPECT_EQ(
0, Distance(
p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 4,
- Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
+ 4, Distance(
+ p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
EXPECT_EQ(
8, Distance(
p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
+ 0, Distance(
+ p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
EXPECT_EQ(
24, Distance(
p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
EXPECT_EQ(
- 8,
- Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
- EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
+ 8, Distance(
+ p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
+ EXPECT_EQ(0,
+ Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
EXPECT_EQ(24,
Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
- EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
+ EXPECT_EQ(8,
+ Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
}
}
@@ -1079,66 +1126,84 @@ TEST(Layout, MutableSliceByTypeData) {
{
using L = Layout<int32_t>;
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
+ 0, Distance(
+ p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
- EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
+ 0, Distance(
+ p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
+ EXPECT_EQ(0,
+ Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
}
{
using L = Layout<int8_t, int32_t, Int128>;
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
+ Distance(p,
+ Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
+ 0,
+ Distance(
+ p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
+ Distance(p,
+ Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
- 4, Distance(
- p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
+ 4,
+ Distance(
+ p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
0,
- Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
+ Distance(p,
+ Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
EXPECT_EQ(
- 8, Distance(
- p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
+ 8,
+ Distance(
+ p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(
+ p,
+ Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
- p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
+ p,
+ Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
p,
Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(
+ p,
+ Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
4,
Distance(
- p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
+ p,
+ Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
EXPECT_EQ(
8,
Distance(
p,
Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
EXPECT_EQ(
- 0, Distance(
- p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
+ 0,
+ Distance(
+ p,
+ Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
EXPECT_EQ(
24,
Distance(
@@ -1147,14 +1212,16 @@ TEST(Layout, MutableSliceByTypeData) {
EXPECT_EQ(
8,
Distance(
- p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
- EXPECT_EQ(0,
- Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
+ p,
+ Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
+ EXPECT_EQ(
+ 0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
EXPECT_EQ(
24,
Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
EXPECT_EQ(
- 8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
+ 8,
+ Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
}
}
@@ -1253,17 +1320,17 @@ TEST(Layout, MutableSlices) {
}
{
const auto x = L::Partial(1, 2, 3);
- EXPECT_THAT(
- (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
+ EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+ x.Slices(p))),
+ Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+ IsSameSlice(x.Slice<2>(p))));
}
{
const L x(1, 2, 3);
- EXPECT_THAT(
- (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
- Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
- IsSameSlice(x.Slice<2>(p))));
+ EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(
+ x.Slices(p))),
+ Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
+ IsSameSlice(x.Slice<2>(p))));
}
}
@@ -1313,7 +1380,7 @@ struct Region {
};
void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
-#ifdef ADDRESS_SANITIZER
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
for (size_t i = 0; i != n; ++i) {
EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
}
@@ -1395,7 +1462,8 @@ TEST(Layout, DebugString) {
x.DebugString());
}
{
- constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
+ constexpr auto x =
+ Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
EXPECT_EQ(
"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
"@16" +
@@ -1403,7 +1471,8 @@ TEST(Layout, DebugString) {
x.DebugString());
}
{
- constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
+ constexpr auto x =
+ Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
EXPECT_EQ(
"@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
"@16" +
@@ -1562,4 +1631,5 @@ TEST(CompactString, Works) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy.h
index 065e7009e7e..4617162f0b3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -39,7 +39,10 @@
#include <type_traits>
#include <utility>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class Reference, class Policy>
@@ -83,6 +86,7 @@ struct node_hash_policy {
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_NODE_HASH_POLICY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy_test.cc
index 43d287e3c4a..84aabba9683 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/node_hash_policy_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,6 +21,7 @@
#include "absl/container/internal/hash_policy_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -64,4 +65,5 @@ TEST_F(NodeTest, transfer) {
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_map.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_map.h
index 5a818d8151a..0a02757ddfb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_map.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_map.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +24,7 @@
#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class Policy, class Hash, class Eq, class Alloc>
@@ -40,8 +41,8 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
using MappedConstReference = decltype(P::value(
std::addressof(std::declval<typename raw_hash_map::const_reference>())));
- using KeyArgImpl = container_internal::KeyArg<IsTransparent<Eq>::value &&
- IsTransparent<Hash>::value>;
+ using KeyArgImpl =
+ KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
public:
using key_type = typename Policy::key_type;
@@ -109,6 +110,9 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
return insert_or_assign(k, v).first;
}
+ // 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.
template <class K = key_type, class... Args,
typename std::enable_if<
!std::is_convertible<K, const_iterator>::value, int>::type = 0,
@@ -187,6 +191,7 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_MAP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.cc
index 180d3fe5a91..bfef071f29e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,13 +20,14 @@
#include "absl/base/config.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
constexpr size_t Group::kWidth;
// Returns "random" seed.
inline size_t RandomSeed() {
-#if ABSL_HAVE_THREAD_LOCAL
+#ifdef ABSL_HAVE_THREAD_LOCAL
static thread_local size_t counter = 0;
size_t value = ++counter;
#else // ABSL_HAVE_THREAD_LOCAL
@@ -42,5 +43,19 @@ bool ShouldInsertBackwards(size_t hash, ctrl_t* ctrl) {
return (H1(hash, ctrl) ^ RandomSeed()) % 13 > 6;
}
+void ConvertDeletedToEmptyAndFullToDeleted(
+ ctrl_t* ctrl, size_t capacity) {
+ assert(ctrl[capacity] == kSentinel);
+ assert(IsValidCapacity(capacity));
+ for (ctrl_t* pos = ctrl; pos != ctrl + capacity + 1; pos += Group::kWidth) {
+ Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
+ }
+ // Copy the cloned ctrl bytes.
+ std::memcpy(ctrl + capacity + 1, ctrl, Group::kWidth);
+ ctrl[capacity] = kSentinel;
+}
+
+
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h
index b7b5ef8c7b4..8615de8bdfa 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -102,23 +102,36 @@
#include <type_traits>
#include <utility>
-#include "absl/base/internal/bits.h"
#include "absl/base/internal/endian.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
+#include "absl/container/internal/common.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_policy_traits.h"
#include "absl/container/internal/hashtable_debug_hooks.h"
+#include "absl/container/internal/hashtablez_sampler.h"
#include "absl/container/internal/have_sse.h"
#include "absl/container/internal/layout.h"
#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
-#include "absl/types/optional.h"
+#include "absl/numeric/bits.h"
#include "absl/utility/utility.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
+template <typename AllocType>
+void SwapAlloc(AllocType& lhs, AllocType& rhs,
+ std::true_type /* propagate_on_container_swap */) {
+ using std::swap;
+ swap(lhs, rhs);
+}
+template <typename AllocType>
+void SwapAlloc(AllocType& /*lhs*/, AllocType& /*rhs*/,
+ std::false_type /* propagate_on_container_swap */) {}
+
template <size_t Width>
class probe_seq {
public:
@@ -164,32 +177,21 @@ struct IsDecomposable<
std::declval<Ts>()...))>,
Policy, Hash, Eq, Ts...> : std::true_type {};
-template <class, class = void>
-struct IsTransparent : std::false_type {};
-template <class T>
-struct IsTransparent<T, absl::void_t<typename T::is_transparent>>
- : std::true_type {};
-
// TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
template <class T>
-constexpr bool IsNoThrowSwappable() {
+constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
using std::swap;
return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
}
-
-template <typename T>
-int TrailingZeros(T x) {
- return sizeof(T) == 8 ? base_internal::CountTrailingZerosNonZero64(
- static_cast<uint64_t>(x))
- : base_internal::CountTrailingZerosNonZero32(
- static_cast<uint32_t>(x));
+template <class T>
+constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
+ return false;
}
template <typename T>
-int LeadingZeros(T x) {
- return sizeof(T) == 8
- ? base_internal::CountLeadingZeros64(static_cast<uint64_t>(x))
- : base_internal::CountLeadingZeros32(static_cast<uint32_t>(x));
+uint32_t TrailingZeros(T x) {
+ ABSL_INTERNAL_ASSUME(x != 0);
+ return countr_zero(x);
}
// An abstraction over a bitmask. It provides an easy way to iterate through the
@@ -219,26 +221,24 @@ class BitMask {
}
explicit operator bool() const { return mask_ != 0; }
int operator*() const { return LowestBitSet(); }
- int LowestBitSet() const {
+ uint32_t LowestBitSet() const {
return container_internal::TrailingZeros(mask_) >> Shift;
}
- int HighestBitSet() const {
- return (sizeof(T) * CHAR_BIT - container_internal::LeadingZeros(mask_) -
- 1) >>
- Shift;
+ uint32_t HighestBitSet() const {
+ return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
}
BitMask begin() const { return *this; }
BitMask end() const { return BitMask(0); }
- int TrailingZeros() const {
+ uint32_t TrailingZeros() const {
return container_internal::TrailingZeros(mask_) >> Shift;
}
- int LeadingZeros() const {
+ uint32_t LeadingZeros() const {
constexpr int total_significant_bits = SignificantBits << Shift;
constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
- return container_internal::LeadingZeros(mask_ << extra_bits) >> Shift;
+ return countl_zero(mask_ << extra_bits) >> Shift;
}
private:
@@ -316,7 +316,7 @@ inline bool IsFull(ctrl_t c) { return c >= 0; }
inline bool IsDeleted(ctrl_t c) { return c == kDeleted; }
inline bool IsEmptyOrDeleted(ctrl_t c) { return c < kSentinel; }
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
// https://github.com/abseil/abseil-cpp/issues/209
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
@@ -350,12 +350,12 @@ struct GroupSse2Impl {
// Returns a bitmask representing the positions of empty slots.
BitMask<uint32_t, kWidth> MatchEmpty() const {
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
// This only works because kEmpty is -128.
return BitMask<uint32_t, kWidth>(
_mm_movemask_epi8(_mm_sign_epi8(ctrl, ctrl)));
#else
- return Match(kEmpty);
+ return Match(static_cast<h2_t>(kEmpty));
#endif
}
@@ -369,14 +369,14 @@ struct GroupSse2Impl {
// Returns the number of trailing empty or deleted elements in the group.
uint32_t CountLeadingEmptyOrDeleted() const {
auto special = _mm_set1_epi8(kSentinel);
- return TrailingZeros(
- _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1);
+ return TrailingZeros(static_cast<uint32_t>(
+ _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
}
void ConvertSpecialToEmptyAndFullToDeleted(ctrl_t* dst) const {
auto msbs = _mm_set1_epi8(static_cast<char>(-128));
auto x126 = _mm_set1_epi8(126);
-#if SWISSTABLE_HAVE_SSSE3
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
#else
auto zero = _mm_setzero_si128();
@@ -388,7 +388,7 @@ struct GroupSse2Impl {
__m128i ctrl;
};
-#endif // SWISSTABLE_HAVE_SSE2
+#endif // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
struct GroupPortableImpl {
static constexpr size_t kWidth = 8;
@@ -442,7 +442,7 @@ struct GroupPortableImpl {
uint64_t ctrl;
};
-#if SWISSTABLE_HAVE_SSE2
+#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
using Group = GroupSse2Impl;
#else
using Group = GroupPortableImpl;
@@ -451,9 +451,7 @@ using Group = GroupPortableImpl;
template <class Policy, class Hash, class Eq, class Alloc>
class raw_hash_set;
-inline bool IsValidCapacity(size_t n) {
- return ((n + 1) & n) == 0 && n >= Group::kWidth - 1;
-}
+inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
// PRECONDITION:
// IsValidCapacity(capacity)
@@ -463,164 +461,112 @@ inline bool IsValidCapacity(size_t n) {
// DELETED -> EMPTY
// EMPTY -> EMPTY
// FULL -> DELETED
-inline void ConvertDeletedToEmptyAndFullToDeleted(
- ctrl_t* ctrl, size_t capacity) {
- assert(ctrl[capacity] == kSentinel);
- assert(IsValidCapacity(capacity));
- for (ctrl_t* pos = ctrl; pos != ctrl + capacity + 1; pos += Group::kWidth) {
- Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
- }
- // Copy the cloned ctrl bytes.
- std::memcpy(ctrl + capacity + 1, ctrl, Group::kWidth);
- ctrl[capacity] = kSentinel;
-}
+void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
-// Rounds up the capacity to the next power of 2 minus 1 and ensures it is
-// greater or equal to Group::kWidth - 1.
+// Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
inline size_t NormalizeCapacity(size_t n) {
- constexpr size_t kMinCapacity = Group::kWidth - 1;
- return n <= kMinCapacity
- ? kMinCapacity
- : (std::numeric_limits<size_t>::max)() >> LeadingZeros(n);
+ return n ? ~size_t{} >> countl_zero(n) : 1;
}
-// The node_handle concept from C++17.
-// We specialize node_handle for sets and maps. node_handle_base holds the
-// common API of both.
-template <typename Policy, typename Alloc>
-class node_handle_base {
- protected:
- using PolicyTraits = hash_policy_traits<Policy>;
- using slot_type = typename PolicyTraits::slot_type;
-
- public:
- using allocator_type = Alloc;
-
- constexpr node_handle_base() {}
- node_handle_base(node_handle_base&& other) noexcept {
- *this = std::move(other);
- }
- ~node_handle_base() { destroy(); }
- node_handle_base& operator=(node_handle_base&& other) {
- destroy();
- if (!other.empty()) {
- alloc_ = other.alloc_;
- PolicyTraits::transfer(alloc(), slot(), other.slot());
- other.reset();
- }
- return *this;
- }
-
- bool empty() const noexcept { return !alloc_; }
- explicit operator bool() const noexcept { return !empty(); }
- allocator_type get_allocator() const { return *alloc_; }
-
- protected:
- template <typename, typename, typename, typename>
- friend class raw_hash_set;
-
- node_handle_base(const allocator_type& a, slot_type* s) : alloc_(a) {
- PolicyTraits::transfer(alloc(), slot(), s);
- }
-
- void destroy() {
- if (!empty()) {
- PolicyTraits::destroy(alloc(), slot());
- reset();
- }
- }
-
- void reset() {
- assert(alloc_.has_value());
- alloc_ = absl::nullopt;
- }
-
- slot_type* slot() const {
- assert(!empty());
- return reinterpret_cast<slot_type*>(std::addressof(slot_space_));
+// General notes on capacity/growth methods below:
+// - We use 7/8th as maximum load factor. For 16-wide groups, that gives an
+// average of two empty slots per group.
+// - For (capacity+1) >= Group::kWidth, growth is 7/8*capacity.
+// - For (capacity+1) < Group::kWidth, growth == capacity. In this case, we
+// never need to probe (the whole table fits in one group) so we don't need a
+// load factor less than 1.
+
+// Given `capacity` of the table, returns the size (i.e. number of full slots)
+// at which we should grow the capacity.
+inline size_t CapacityToGrowth(size_t capacity) {
+ assert(IsValidCapacity(capacity));
+ // `capacity*7/8`
+ if (Group::kWidth == 8 && capacity == 7) {
+ // x-x/8 does not work when x==7.
+ return 6;
}
- allocator_type* alloc() { return std::addressof(*alloc_); }
-
- private:
- absl::optional<allocator_type> alloc_;
- mutable absl::aligned_storage_t<sizeof(slot_type), alignof(slot_type)>
- slot_space_;
-};
-
-// For sets.
-template <typename Policy, typename Alloc, typename = void>
-class node_handle : public node_handle_base<Policy, Alloc> {
- using Base = typename node_handle::node_handle_base;
-
- public:
- using value_type = typename Base::PolicyTraits::value_type;
-
- constexpr node_handle() {}
+ return capacity - capacity / 8;
+}
+// From desired "growth" to a lowerbound of the necessary capacity.
+// Might not be a valid one and requires NormalizeCapacity().
+inline size_t GrowthToLowerboundCapacity(size_t growth) {
+ // `growth*8/7`
+ if (Group::kWidth == 8 && growth == 7) {
+ // x+(x-1)/7 does not work when x==7.
+ return 8;
+ }
+ return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
+}
- value_type& value() const {
- return Base::PolicyTraits::element(this->slot());
- }
+inline void AssertIsFull(ctrl_t* ctrl) {
+ ABSL_HARDENING_ASSERT((ctrl != nullptr && IsFull(*ctrl)) &&
+ "Invalid operation on iterator. The element might have "
+ "been erased, or the table might have rehashed.");
+}
- private:
- template <typename, typename, typename, typename>
- friend class raw_hash_set;
+inline void AssertIsValid(ctrl_t* ctrl) {
+ ABSL_HARDENING_ASSERT((ctrl == nullptr || IsFull(*ctrl)) &&
+ "Invalid operation on iterator. The element might have "
+ "been erased, or the table might have rehashed.");
+}
- node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
+struct FindInfo {
+ size_t offset;
+ size_t probe_length;
};
-// For maps.
-template <typename Policy, typename Alloc>
-class node_handle<Policy, Alloc, absl::void_t<typename Policy::mapped_type>>
- : public node_handle_base<Policy, Alloc> {
- using Base = typename node_handle::node_handle_base;
-
- public:
- using key_type = typename Policy::key_type;
- using mapped_type = typename Policy::mapped_type;
-
- constexpr node_handle() {}
-
- auto key() const -> decltype(Base::PolicyTraits::key(this->slot())) {
- return Base::PolicyTraits::key(this->slot());
- }
+// The representation of the object has two modes:
+// - small: For capacities < kWidth-1
+// - large: For the rest.
+//
+// Differences:
+// - In small mode we are able to use the whole capacity. The extra control
+// bytes give us at least one "empty" control byte to stop the iteration.
+// This is important to make 1 a valid capacity.
+//
+// - In small mode only the first `capacity()` control bytes after the
+// sentinel are valid. The rest contain dummy kEmpty values that do not
+// represent a real slot. This is important to take into account on
+// find_first_non_full(), where we never try ShouldInsertBackwards() for
+// small tables.
+inline bool is_small(size_t capacity) { return capacity < Group::kWidth - 1; }
+
+inline probe_seq<Group::kWidth> probe(ctrl_t* ctrl, size_t hash,
+ size_t capacity) {
+ return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
+}
- mapped_type& mapped() const {
- return Base::PolicyTraits::value(
- &Base::PolicyTraits::element(this->slot()));
+// Probes the raw_hash_set with the probe sequence for hash and returns the
+// pointer to the first empty or deleted slot.
+// NOTE: this function must work with tables having both kEmpty and kDelete
+// in one group. Such tables appears during drop_deletes_without_resize.
+//
+// This function is very useful when insertions happen and:
+// - the input is already a set
+// - there are enough slots
+// - the element with the hash is not in the table
+inline FindInfo find_first_non_full(ctrl_t* ctrl, size_t hash,
+ size_t capacity) {
+ auto seq = probe(ctrl, hash, capacity);
+ while (true) {
+ Group g{ctrl + seq.offset()};
+ auto mask = g.MatchEmptyOrDeleted();
+ if (mask) {
+#if !defined(NDEBUG)
+ // We want to add entropy even when ASLR is not enabled.
+ // In debug build we will randomly insert in either the front or back of
+ // the group.
+ // TODO(kfm,sbenza): revisit after we do unconditional mixing
+ if (!is_small(capacity) && ShouldInsertBackwards(hash, ctrl)) {
+ return {seq.offset(mask.HighestBitSet()), seq.index()};
+ }
+#endif
+ return {seq.offset(mask.LowestBitSet()), seq.index()};
+ }
+ seq.next();
+ assert(seq.index() < capacity && "full table!");
}
-
- private:
- template <typename, typename, typename, typename>
- friend class raw_hash_set;
-
- node_handle(const Alloc& a, typename Base::slot_type* s) : Base(a, s) {}
-};
-
-// Implement the insert_return_type<> concept of C++17.
-template <class Iterator, class NodeType>
-struct insert_return_type {
- Iterator position;
- bool inserted;
- NodeType node;
-};
-
-// Helper trait to allow or disallow arbitrary keys when the hash and
-// eq functions are transparent.
-// It is very important that the inner template is an alias and that the type it
-// produces is not a dependent type. Otherwise, type deduction would fail.
-template <bool is_transparent>
-struct KeyArg {
- // Transparent. Forward `K`.
- template <typename K, typename key_type>
- using type = K;
-};
-
-template <>
-struct KeyArg<false> {
- // Not transparent. Always use `key_type`.
- template <typename K, typename key_type>
- using type = key_type;
-};
+}
// Policy: a policy defines how to perform different operations on
// the slots of the hashtable (see hash_policy_traits.h for the full interface
@@ -636,14 +582,15 @@ struct KeyArg<false> {
// if they are equal, false if they are not. If two keys compare equal, then
// their hash values as defined by Hash MUST be equal.
//
-// Allocator: an Allocator [http://devdocs.io/cpp/concept/allocator] with which
+// Allocator: an Allocator
+// [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
// the storage of the hashtable will be allocated and the elements will be
// constructed and destroyed.
template <class Policy, class Hash, class Eq, class Alloc>
class raw_hash_set {
using PolicyTraits = hash_policy_traits<Policy>;
- using KeyArgImpl = container_internal::KeyArg<IsTransparent<Eq>::value &&
- IsTransparent<Hash>::value>;
+ using KeyArgImpl =
+ KeyArg<IsTransparent<Eq>::value && IsTransparent<Hash>::value>;
public:
using init_type = typename PolicyTraits::init_type;
@@ -741,13 +688,17 @@ class raw_hash_set {
iterator() {}
// PRECONDITION: not an end() iterator.
- reference operator*() const { return PolicyTraits::element(slot_); }
+ reference operator*() const {
+ AssertIsFull(ctrl_);
+ return PolicyTraits::element(slot_);
+ }
// PRECONDITION: not an end() iterator.
pointer operator->() const { return &operator*(); }
// PRECONDITION: not an end() iterator.
iterator& operator++() {
+ AssertIsFull(ctrl_);
++ctrl_;
++slot_;
skip_empty_or_deleted();
@@ -761,6 +712,8 @@ class raw_hash_set {
}
friend bool operator==(const iterator& a, const iterator& b) {
+ AssertIsValid(a.ctrl_);
+ AssertIsValid(b.ctrl_);
return a.ctrl_ == b.ctrl_;
}
friend bool operator!=(const iterator& a, const iterator& b) {
@@ -768,23 +721,27 @@ class raw_hash_set {
}
private:
- iterator(ctrl_t* ctrl) : ctrl_(ctrl) {} // for end()
- iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {}
+ iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {
+ // This assumption helps the compiler know that any non-end iterator is
+ // not equal to any end iterator.
+ ABSL_INTERNAL_ASSUME(ctrl != nullptr);
+ }
void skip_empty_or_deleted() {
while (IsEmptyOrDeleted(*ctrl_)) {
- // ctrl is not necessarily aligned to Group::kWidth. It is also likely
- // to read past the space for ctrl bytes and into slots. This is ok
- // because ctrl has sizeof() == 1 and slot has sizeof() >= 1 so there
- // is no way to read outside the combined slot array.
uint32_t shift = Group{ctrl_}.CountLeadingEmptyOrDeleted();
ctrl_ += shift;
slot_ += shift;
}
+ if (ABSL_PREDICT_FALSE(*ctrl_ == kSentinel)) ctrl_ = nullptr;
}
ctrl_t* ctrl_ = nullptr;
- slot_type* slot_;
+ // To avoid uninitialized member warnings, put slot_ in an anonymous union.
+ // The member is not initialized on singleton and end iterators.
+ union {
+ slot_type* slot_;
+ };
};
class const_iterator {
@@ -824,7 +781,8 @@ class raw_hash_set {
iterator inner_;
};
- using node_type = container_internal::node_handle<Policy, Alloc>;
+ using node_type = node_handle<Policy, hash_policy_traits<Policy>, Alloc>;
+ using insert_return_type = InsertReturnType<iterator, node_type>;
raw_hash_set() noexcept(
std::is_nothrow_default_constructible<hasher>::value&&
@@ -834,10 +792,10 @@ class raw_hash_set {
explicit raw_hash_set(size_t bucket_count, const hasher& hash = hasher(),
const key_equal& eq = key_equal(),
const allocator_type& alloc = allocator_type())
- : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
+ : ctrl_(EmptyGroup()),
+ settings_(0, HashtablezInfoHandle(), hash, eq, alloc) {
if (bucket_count) {
capacity_ = NormalizeCapacity(bucket_count);
- growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
initialize_slots();
}
}
@@ -879,8 +837,8 @@ class raw_hash_set {
// that accept std::initializer_list<T> and std::initializer_list<init_type>.
// This is advantageous for performance.
//
- // // Turns {"abc", "def"} into std::initializer_list<std::string>, then copies
- // // the strings into the set.
+ // // Turns {"abc", "def"} into std::initializer_list<std::string>, then
+ // // copies the strings into the set.
// std::unordered_set<std::string> s = {"abc", "def"};
//
// // Turns {"abc", "def"} into std::initializer_list<const char*>, then
@@ -943,9 +901,10 @@ class raw_hash_set {
// than a full `insert`.
for (const auto& v : that) {
const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
- const size_t i = find_first_non_full(hash);
- set_ctrl(i, H2(hash));
- emplace_at(i, v);
+ auto target = find_first_non_full(ctrl_, hash, capacity_);
+ set_ctrl(target.offset, H2(hash));
+ emplace_at(target.offset, v);
+ infoz().RecordInsert(hash, target.probe_length);
}
size_ = that.size();
growth_left() -= that.size();
@@ -962,23 +921,24 @@ class raw_hash_set {
// Hash, equality and allocator are copied instead of moved because
// `that` must be left valid. If Hash is std::function<Key>, moving it
// would create a nullptr functor that cannot be called.
- settings_(that.settings_) {
- // growth_left was copied above, reset the one from `that`.
- that.growth_left() = 0;
- }
+ settings_(absl::exchange(that.growth_left(), 0),
+ absl::exchange(that.infoz(), HashtablezInfoHandle()),
+ that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
raw_hash_set(raw_hash_set&& that, const allocator_type& a)
: ctrl_(EmptyGroup()),
slots_(nullptr),
size_(0),
capacity_(0),
- settings_(0, that.hash_ref(), that.eq_ref(), a) {
+ settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(),
+ a) {
if (a == that.alloc_ref()) {
std::swap(ctrl_, that.ctrl_);
std::swap(slots_, that.slots_);
std::swap(size_, that.size_);
std::swap(capacity_, that.capacity_);
std::swap(growth_left(), that.growth_left());
+ std::swap(infoz(), that.infoz());
} else {
reserve(that.size());
// Note: this will copy elements of dense_set and unordered_set instead of
@@ -1014,12 +974,12 @@ class raw_hash_set {
it.skip_empty_or_deleted();
return it;
}
- iterator end() { return {ctrl_ + capacity_}; }
+ iterator end() { return {}; }
const_iterator begin() const {
return const_cast<raw_hash_set*>(this)->begin();
}
- const_iterator end() const { return const_cast<raw_hash_set*>(this)->end(); }
+ const_iterator end() const { return {}; }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
@@ -1028,7 +988,7 @@ class raw_hash_set {
size_t capacity() const { return capacity_; }
size_t max_size() const { return (std::numeric_limits<size_t>::max)(); }
- void clear() {
+ ABSL_ATTRIBUTE_REINITIALIZES void clear() {
// Iterating over this container is O(bucket_count()). When bucket_count()
// is much greater than size(), iteration becomes prohibitively expensive.
// For clear() it is more important to reuse the allocated array when the
@@ -1046,9 +1006,10 @@ class raw_hash_set {
}
size_ = 0;
reset_ctrl();
- growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor);
+ reset_growth_left();
}
assert(empty());
+ infoz().RecordStorageChanged(0, capacity_);
}
// This overload kicks in when the argument is an rvalue of insertable and
@@ -1056,8 +1017,11 @@ class raw_hash_set {
//
// flat_hash_map<std::string, int> m;
// m.insert(std::make_pair("abc", 42));
+ // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
+ // bug.
template <class T, RequiresInsertable<T> = 0,
- typename std::enable_if<IsDecomposable<T>::value, int>::type = 0,
+ class T2 = T,
+ typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
T* = nullptr>
std::pair<iterator, bool> insert(T&& value) {
return emplace(std::forward<T>(value));
@@ -1087,14 +1051,16 @@ class raw_hash_set {
// This overload kicks in when the argument is an rvalue of init_type. Its
// purpose is to handle brace-init-list arguments.
//
- // flat_hash_set<std::string, int> s;
+ // flat_hash_map<std::string, int> s;
// s.insert({"abc", 42});
std::pair<iterator, bool> insert(init_type&& value) {
return emplace(std::move(value));
}
- template <class T, RequiresInsertable<T> = 0,
- typename std::enable_if<IsDecomposable<T>::value, int>::type = 0,
+ // TODO(cheshire): A type alias T2 is introduced as a workaround for the nvcc
+ // bug.
+ template <class T, RequiresInsertable<T> = 0, class T2 = T,
+ typename std::enable_if<IsDecomposable<T2>::value, int>::type = 0,
T* = nullptr>
iterator insert(const_iterator, T&& value) {
return insert(std::forward<T>(value)).first;
@@ -1116,7 +1082,7 @@ class raw_hash_set {
template <class InputIt>
void insert(InputIt first, InputIt last) {
- for (; first != last; ++first) insert(*first);
+ for (; first != last; ++first) emplace(*first);
}
template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
@@ -1128,13 +1094,14 @@ class raw_hash_set {
insert(ilist.begin(), ilist.end());
}
- insert_return_type<iterator, node_type> insert(node_type&& node) {
+ insert_return_type insert(node_type&& node) {
if (!node) return {end(), false, node_type()};
- const auto& elem = PolicyTraits::element(node.slot());
+ const auto& elem = PolicyTraits::element(CommonAccess::GetSlot(node));
auto res = PolicyTraits::apply(
- InsertSlot<false>{*this, std::move(*node.slot())}, elem);
+ InsertSlot<false>{*this, std::move(*CommonAccess::GetSlot(node))},
+ elem);
if (res.second) {
- node.reset();
+ CommonAccess::Reset(&node);
return {res.first, true, node_type()};
} else {
return {res.first, false, std::move(node)};
@@ -1142,7 +1109,9 @@ class raw_hash_set {
}
iterator insert(const_iterator, node_type&& node) {
- return insert(std::move(node)).first;
+ auto res = insert(std::move(node));
+ node = std::move(res.node);
+ return res.position;
}
// This overload kicks in if we can deduce the key from args. This enables us
@@ -1167,8 +1136,7 @@ class raw_hash_set {
template <class... Args, typename std::enable_if<
!IsDecomposable<Args...>::value, int>::type = 0>
std::pair<iterator, bool> emplace(Args&&... args) {
- typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
- raw;
+ alignas(slot_type) unsigned char raw[sizeof(slot_type)];
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
PolicyTraits::construct(&alloc_ref(), slot, std::forward<Args>(args)...);
@@ -1184,10 +1152,15 @@ class raw_hash_set {
// Extension API: support for lazy emplace.
//
// Looks up key in the table. If found, returns the iterator to the element.
- // Otherwise calls f with one argument of type raw_hash_set::constructor. f
- // MUST call raw_hash_set::constructor with arguments as if a
- // raw_hash_set::value_type is constructed, otherwise the behavior is
- // undefined.
+ // Otherwise calls `f` with one argument of type `raw_hash_set::constructor`.
+ //
+ // `f` must abide by several restrictions:
+ // - it MUST call `raw_hash_set::constructor` with arguments as if a
+ // `raw_hash_set::value_type` is constructed,
+ // - it MUST NOT access the container before the call to
+ // `raw_hash_set::constructor`, and
+ // - it MUST NOT erase the lazily emplaced element.
+ // Doing any of these is undefined behavior.
//
// For example:
//
@@ -1250,15 +1223,16 @@ class raw_hash_set {
}
// Erases the element pointed to by `it`. Unlike `std::unordered_set::erase`,
- // this method returns void to reduce algorithmic complexity to O(1). In
- // order to erase while iterating across a map, use the following idiom (which
- // also works for standard containers):
+ // this method returns void to reduce algorithmic complexity to O(1). The
+ // iterator is invalidated, so any increment should be done before calling
+ // erase. In order to erase while iterating across a map, use the following
+ // idiom (which also works for standard containers):
//
// for (auto it = m.begin(), end = m.end(); it != end;) {
+ // // `erase()` will invalidate `it`, so advance `it` first.
+ // auto copy_it = it++;
// if (<pred>) {
- // m.erase(it++);
- // } else {
- // ++it;
+ // m.erase(copy_it);
// }
// }
void erase(const_iterator cit) { erase(cit.inner_); }
@@ -1266,7 +1240,7 @@ class raw_hash_set {
// This overload is necessary because otherwise erase<K>(const K&) would be
// a better match if non-const iterator is passed as an argument.
void erase(iterator it) {
- assert(it != end());
+ AssertIsFull(it.ctrl_);
PolicyTraits::destroy(&alloc_ref(), it.slot_);
erase_meta_only(it);
}
@@ -1283,12 +1257,14 @@ class raw_hash_set {
template <typename H, typename E>
void merge(raw_hash_set<Policy, H, E, Alloc>& src) { // NOLINT
assert(this != &src);
- for (auto it = src.begin(), e = src.end(); it != e; ++it) {
+ for (auto it = src.begin(), e = src.end(); it != e;) {
+ auto next = std::next(it);
if (PolicyTraits::apply(InsertSlot<false>{*this, std::move(*it.slot_)},
PolicyTraits::element(it.slot_))
.second) {
src.erase_meta_only(it);
}
+ it = next;
}
}
@@ -1298,7 +1274,9 @@ class raw_hash_set {
}
node_type extract(const_iterator position) {
- node_type node(alloc_ref(), position.inner_.slot_);
+ AssertIsFull(position.inner_.ctrl_);
+ auto node =
+ CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
erase_meta_only(position);
return node;
}
@@ -1313,8 +1291,8 @@ class raw_hash_set {
void swap(raw_hash_set& that) noexcept(
IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
- (!AllocTraits::propagate_on_container_swap::value ||
- IsNoThrowSwappable<allocator_type>())) {
+ IsNoThrowSwappable<allocator_type>(
+ typename AllocTraits::propagate_on_container_swap{})) {
using std::swap;
swap(ctrl_, that.ctrl_);
swap(slots_, that.slots_);
@@ -1323,18 +1301,21 @@ class raw_hash_set {
swap(growth_left(), that.growth_left());
swap(hash_ref(), that.hash_ref());
swap(eq_ref(), that.eq_ref());
- if (AllocTraits::propagate_on_container_swap::value) {
- swap(alloc_ref(), that.alloc_ref());
- } else {
- // If the allocators do not compare equal it is officially undefined
- // behavior. We choose to do nothing.
- }
+ swap(infoz(), that.infoz());
+ SwapAlloc(alloc_ref(), that.alloc_ref(),
+ typename AllocTraits::propagate_on_container_swap{});
}
void rehash(size_t n) {
if (n == 0 && capacity_ == 0) return;
- if (n == 0 && size_ == 0) return destroy_slots();
- auto m = NormalizeCapacity((std::max)(n, NumSlotsFast(size())));
+ if (n == 0 && size_ == 0) {
+ destroy_slots();
+ infoz().RecordStorageChanged(0, 0);
+ return;
+ }
+ // bitor is a faster way of doing `max` here. We will round up to the next
+ // power-of-2-minus-1, so bitor is good enough.
+ auto m = NormalizeCapacity(n | GrowthToLowerboundCapacity(size()));
// n == 0 unconditionally rehashes as per the standard.
if (n == 0 || m > capacity_) {
resize(m);
@@ -1342,7 +1323,10 @@ class raw_hash_set {
}
void reserve(size_t n) {
- rehash(NumSlotsFast(n));
+ size_t m = GrowthToLowerboundCapacity(n);
+ if (m > capacity_) {
+ resize(NormalizeCapacity(m));
+ }
}
// Extension API: support for heterogeneous keys.
@@ -1368,7 +1352,7 @@ class raw_hash_set {
void prefetch(const key_arg<K>& key) const {
(void)key;
#if defined(__GNUC__)
- auto seq = probe(hash_ref()(key));
+ auto seq = probe(ctrl_, hash_ref()(key), capacity_);
__builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset()));
__builtin_prefetch(static_cast<const void*>(slots_ + seq.offset()));
#endif // __GNUC__
@@ -1383,7 +1367,7 @@ class raw_hash_set {
// called heterogeneous key support.
template <class K = key_type>
iterator find(const key_arg<K>& key, size_t hash) {
- auto seq = probe(hash);
+ auto seq = probe(ctrl_, hash, capacity_);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1394,6 +1378,7 @@ class raw_hash_set {
}
if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return end();
seq.next();
+ assert(seq.index() < capacity_ && "full table!");
}
}
template <class K = key_type>
@@ -1521,13 +1506,6 @@ class raw_hash_set {
slot_type&& slot;
};
- // Computes std::ceil(n / kMaxLoadFactor). Faster than calling std::ceil.
- static inline size_t NumSlotsFast(size_t n) {
- return static_cast<size_t>(
- (n * kMaxLoadFactorDenominator + (kMaxLoadFactorNumerator - 1)) /
- kMaxLoadFactorNumerator);
- }
-
// "erases" the object from the container, except that it doesn't actually
// destroy the object. It only updates all the metadata of the class.
// This can be used in conjunction with Policy::transfer to move the object to
@@ -1550,17 +1528,34 @@ class raw_hash_set {
set_ctrl(index, was_never_full ? kEmpty : kDeleted);
growth_left() += was_never_full;
+ infoz().RecordErase();
}
void initialize_slots() {
assert(capacity_);
+ // Folks with custom allocators often make unwarranted assumptions about the
+ // behavior of their classes vis-a-vis trivial destructability and what
+ // calls they will or wont make. Avoid sampling for people with custom
+ // allocators to get us out of this mess. This is not a hard guarantee but
+ // a workaround while we plan the exact guarantee we want to provide.
+ //
+ // People are often sloppy with the exact type of their allocator (sometimes
+ // it has an extra const or is missing the pair, but rebinds made it work
+ // anyway). To avoid the ambiguity, we work off SlotAlloc which we have
+ // bound more carefully.
+ if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value &&
+ slots_ == nullptr) {
+ infoz() = Sample();
+ }
+
auto layout = MakeLayout(capacity_);
char* mem = static_cast<char*>(
Allocate<Layout::Alignment()>(&alloc_ref(), layout.AllocSize()));
ctrl_ = reinterpret_cast<ctrl_t*>(layout.template Pointer<0>(mem));
slots_ = layout.template Pointer<1>(mem);
reset_ctrl();
- growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+ reset_growth_left();
+ infoz().RecordStorageChanged(size_, capacity_);
}
void destroy_slots() {
@@ -1589,11 +1584,14 @@ class raw_hash_set {
capacity_ = new_capacity;
initialize_slots();
+ size_t total_probe_length = 0;
for (size_t i = 0; i != old_capacity; ++i) {
if (IsFull(old_ctrl[i])) {
size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
PolicyTraits::element(old_slots + i));
- size_t new_i = find_first_non_full(hash);
+ auto target = find_first_non_full(ctrl_, hash, capacity_);
+ size_t new_i = target.offset;
+ total_probe_length += target.probe_length;
set_ctrl(new_i, H2(hash));
PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
}
@@ -1605,10 +1603,12 @@ class raw_hash_set {
Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
layout.AllocSize());
}
+ infoz().RecordRehash(total_probe_length);
}
void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
assert(IsValidCapacity(capacity_));
+ assert(!is_small(capacity_));
// Algorithm:
// - mark all DELETED slots as EMPTY
// - mark all FULL slots as DELETED
@@ -1626,20 +1626,23 @@ class raw_hash_set {
// mark target as FULL
// repeat procedure for current slot with moved from element (target)
ConvertDeletedToEmptyAndFullToDeleted(ctrl_, capacity_);
- typename std::aligned_storage<sizeof(slot_type), alignof(slot_type)>::type
- raw;
+ alignas(slot_type) unsigned char raw[sizeof(slot_type)];
+ size_t total_probe_length = 0;
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
for (size_t i = 0; i != capacity_; ++i) {
if (!IsDeleted(ctrl_[i])) continue;
size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
PolicyTraits::element(slots_ + i));
- size_t new_i = find_first_non_full(hash);
+ auto target = find_first_non_full(ctrl_, hash, capacity_);
+ size_t new_i = target.offset;
+ total_probe_length += target.probe_length;
// Verify if the old and new i fall within the same group wrt the hash.
// If they do, we don't need to move the object as it falls already in the
// best probe we can.
const auto probe_index = [&](size_t pos) {
- return ((pos - probe(hash).offset()) & capacity_) / Group::kWidth;
+ return ((pos - probe(ctrl_, hash, capacity_).offset()) & capacity_) /
+ Group::kWidth;
};
// Element doesn't move.
@@ -1665,13 +1668,14 @@ class raw_hash_set {
--i; // repeat
}
}
- growth_left() = static_cast<size_t>(capacity_ * kMaxLoadFactor) - size_;
+ reset_growth_left();
+ infoz().RecordRehash(total_probe_length);
}
void rehash_and_grow_if_necessary() {
if (capacity_ == 0) {
- resize(Group::kWidth - 1);
- } else if (size() <= kMaxLoadFactor / 2 * capacity_) {
+ resize(1);
+ } else if (size() <= CapacityToGrowth(capacity()) / 2) {
// Squash DELETED without growing if there is enough capacity.
drop_deletes_without_resize();
} else {
@@ -1682,7 +1686,7 @@ class raw_hash_set {
bool has_element(const value_type& elem) const {
size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, elem);
- auto seq = probe(hash);
+ auto seq = probe(ctrl_, hash, capacity_);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1697,39 +1701,6 @@ class raw_hash_set {
return false;
}
- // Probes the raw_hash_set with the probe sequence for hash and returns the
- // pointer to the first empty or deleted slot.
- // NOTE: this function must work with tables having both kEmpty and kDelete
- // in one group. Such tables appears during drop_deletes_without_resize.
- //
- // This function is very useful when insertions happen and:
- // - the input is already a set
- // - there are enough slots
- // - the element with the hash is not in the table
- size_t find_first_non_full(size_t hash) {
- auto seq = probe(hash);
- while (true) {
- Group g{ctrl_ + seq.offset()};
- auto mask = g.MatchEmptyOrDeleted();
- if (mask) {
-#if !defined(NDEBUG)
- // We want to force small tables to have random entries too, so
- // in debug build we will randomly insert in either the front or back of
- // the group.
- // TODO(kfm,sbenza): revisit after we do unconditional mixing
- if (ShouldInsertBackwards(hash, ctrl_))
- return seq.offset(mask.HighestBitSet());
- else
- return seq.offset(mask.LowestBitSet());
-#else
- return seq.offset(mask.LowestBitSet());
-#endif
- }
- assert(seq.index() < capacity_ && "full table!");
- seq.next();
- }
- }
-
// TODO(alkis): Optimize this assuming *this and that don't overlap.
raw_hash_set& move_assign(raw_hash_set&& that, std::true_type) {
raw_hash_set tmp(std::move(that));
@@ -1746,7 +1717,7 @@ class raw_hash_set {
template <class K>
std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
auto hash = hash_ref()(key);
- auto seq = probe(hash);
+ auto seq = probe(ctrl_, hash, capacity_);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1757,20 +1728,23 @@ class raw_hash_set {
}
if (ABSL_PREDICT_TRUE(g.MatchEmpty())) break;
seq.next();
+ assert(seq.index() < capacity_ && "full table!");
}
return {prepare_insert(hash), true};
}
size_t prepare_insert(size_t hash) ABSL_ATTRIBUTE_NOINLINE {
- size_t target = find_first_non_full(hash);
- if (ABSL_PREDICT_FALSE(growth_left() == 0 && !IsDeleted(ctrl_[target]))) {
+ auto target = find_first_non_full(ctrl_, hash, capacity_);
+ if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
+ !IsDeleted(ctrl_[target.offset]))) {
rehash_and_grow_if_necessary();
- target = find_first_non_full(hash);
+ target = find_first_non_full(ctrl_, hash, capacity_);
}
++size_;
- growth_left() -= IsEmpty(ctrl_[target]);
- set_ctrl(target, H2(hash));
- return target;
+ growth_left() -= IsEmpty(ctrl_[target.offset]);
+ set_ctrl(target.offset, H2(hash));
+ infoz().RecordInsert(hash, target.probe_length);
+ return target.offset;
}
// Constructs the value in the space pointed by the iterator. This only works
@@ -1797,10 +1771,6 @@ class raw_hash_set {
private:
friend struct RawHashSetTestOnlyAccess;
- probe_seq<Group::kWidth> probe(size_t hash) const {
- return probe_seq<Group::kWidth>(H1(hash, ctrl_), capacity_);
- }
-
// Reset all ctrl bytes back to kEmpty, except the sentinel.
void reset_ctrl() {
std::memset(ctrl_, kEmpty, capacity_ + Group::kWidth);
@@ -1808,6 +1778,10 @@ class raw_hash_set {
SanitizerPoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
}
+ void reset_growth_left() {
+ growth_left() = CapacityToGrowth(capacity()) - size_;
+ }
+
// Sets the control byte, and if `i < Group::kWidth`, set the cloned byte at
// the end too.
void set_ctrl(size_t i, ctrl_t h) {
@@ -1820,26 +1794,23 @@ class raw_hash_set {
}
ctrl_[i] = h;
- ctrl_[((i - Group::kWidth) & capacity_) + Group::kWidth] = h;
+ ctrl_[((i - Group::kWidth) & capacity_) + 1 +
+ ((Group::kWidth - 1) & capacity_)] = h;
}
size_t& growth_left() { return settings_.template get<0>(); }
- hasher& hash_ref() { return settings_.template get<1>(); }
- const hasher& hash_ref() const { return settings_.template get<1>(); }
- key_equal& eq_ref() { return settings_.template get<2>(); }
- const key_equal& eq_ref() const { return settings_.template get<2>(); }
- allocator_type& alloc_ref() { return settings_.template get<3>(); }
+ HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
+
+ hasher& hash_ref() { return settings_.template get<2>(); }
+ const hasher& hash_ref() const { return settings_.template get<2>(); }
+ key_equal& eq_ref() { return settings_.template get<3>(); }
+ const key_equal& eq_ref() const { return settings_.template get<3>(); }
+ allocator_type& alloc_ref() { return settings_.template get<4>(); }
const allocator_type& alloc_ref() const {
- return settings_.template get<3>();
+ return settings_.template get<4>();
}
- // On average each group has 2 empty slot (for the vectorized case).
- static constexpr int64_t kMaxLoadFactorNumerator = 14;
- static constexpr int64_t kMaxLoadFactorDenominator = 16;
- static constexpr float kMaxLoadFactor =
- 1.0 * kMaxLoadFactorNumerator / kMaxLoadFactorDenominator;
-
// TODO(alkis): Investigate removing some of these fields:
// - ctrl/slots can be derived from each other
// - size can be moved into the slot array
@@ -1847,11 +1818,24 @@ class raw_hash_set {
slot_type* slots_ = nullptr; // [capacity * slot_type]
size_t size_ = 0; // number of full slots
size_t capacity_ = 0; // total number of slots
- absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher,
+ absl::container_internal::CompressedTuple<size_t /* growth_left */,
+ HashtablezInfoHandle, hasher,
key_equal, allocator_type>
- settings_{0, hasher{}, key_equal{}, allocator_type{}};
+ settings_{0, HashtablezInfoHandle{}, hasher{}, key_equal{},
+ allocator_type{}};
};
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename P, typename H, typename E, typename A, typename Predicate>
+void EraseIf(Predicate pred, raw_hash_set<P, H, E, A>* c) {
+ for (auto it = c->begin(), last = c->end(); it != last;) {
+ auto copy_it = it++;
+ if (pred(*copy_it)) {
+ c->erase(copy_it);
+ }
+ }
+}
+
namespace hashtable_debug_internal {
template <typename Set>
struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
@@ -1862,7 +1846,7 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
const typename Set::key_type& key) {
size_t num_probes = 0;
size_t hash = set.hash_ref()(key);
- auto seq = set.probe(hash);
+ auto seq = probe(set.ctrl_, hash, set.capacity_);
while (true) {
container_internal::Group g{set.ctrl_ + seq.offset()};
for (int i : g.Match(container_internal::H2(hash))) {
@@ -1899,10 +1883,9 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
}
static size_t LowerBoundAllocatedByteSize(size_t size) {
- size_t capacity = container_internal::NormalizeCapacity(
- std::ceil(size / Set::kMaxLoadFactor));
+ size_t capacity = GrowthToLowerboundCapacity(size);
if (capacity == 0) return 0;
- auto layout = Set::MakeLayout(capacity);
+ auto layout = Set::MakeLayout(NormalizeCapacity(capacity));
size_t m = layout.AllocSize();
size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
if (per_slot != ~size_t{}) {
@@ -1914,6 +1897,7 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
} // namespace hashtable_debug_internal
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
index 891fa450fe0..e73f53fd637 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,7 @@
#include "absl/container/internal/tracked.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -423,6 +424,82 @@ TEST_F(PropagateOnAll, Swap) {
EXPECT_EQ(0, it->num_copies());
}
+// This allocator is similar to std::pmr::polymorphic_allocator.
+// Note the disabled assignment.
+template <class T>
+class PAlloc {
+ template <class>
+ friend class PAlloc;
+
+ public:
+ // types
+ using value_type = T;
+
+ // traits
+ using propagate_on_container_swap = std::false_type;
+
+ PAlloc() noexcept = default;
+ explicit PAlloc(size_t id) noexcept : id_(id) {}
+ PAlloc(const PAlloc&) noexcept = default;
+ PAlloc& operator=(const PAlloc&) noexcept = delete;
+
+ template <class U>
+ PAlloc(const PAlloc<U>& that) noexcept : id_(that.id_) {} // NOLINT
+
+ template <class U>
+ struct rebind {
+ using other = PAlloc<U>;
+ };
+
+ constexpr PAlloc select_on_container_copy_construction() const { return {}; }
+
+ // public member functions
+ T* allocate(size_t) { return new T; }
+ void deallocate(T* p, size_t) { delete p; }
+
+ friend bool operator==(const PAlloc& a, const PAlloc& b) {
+ return a.id_ == b.id_;
+ }
+ friend bool operator!=(const PAlloc& a, const PAlloc& b) { return !(a == b); }
+
+ private:
+ size_t id_ = std::numeric_limits<size_t>::max();
+};
+
+// This doesn't compile with GCC 5.4 and 5.5 due to a bug in noexcept handing.
+#if !defined(__GNUC__) || __GNUC__ != 5 || (__GNUC_MINOR__ != 4 && \
+ __GNUC_MINOR__ != 5)
+TEST(NoPropagateOn, Swap) {
+ using PA = PAlloc<char>;
+ using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+ Table t1(PA{1}), t2(PA{2});
+ swap(t1, t2);
+ EXPECT_EQ(t1.get_allocator(), PA(1));
+ EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+#endif
+
+TEST(NoPropagateOn, CopyConstruct) {
+ using PA = PAlloc<char>;
+ using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+ Table t1(PA{1}), t2(t1);
+ EXPECT_EQ(t1.get_allocator(), PA(1));
+ EXPECT_EQ(t2.get_allocator(), PA());
+}
+
+TEST(NoPropagateOn, Assignment) {
+ using PA = PAlloc<char>;
+ using Table = raw_hash_set<Policy, Identity, std::equal_to<int32_t>, PA>;
+
+ Table t1(PA{1}), t2(PA{2});
+ t1 = t2;
+ EXPECT_EQ(t1.get_allocator(), PA(1));
+ EXPECT_EQ(t2.get_allocator(), PA(2));
+}
+
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc
new file mode 100644
index 00000000000..f9be2c5ac7c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc
@@ -0,0 +1,396 @@
+// 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.
+
+#include "absl/container/internal/raw_hash_set.h"
+
+#include <numeric>
+#include <random>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/container/internal/hash_function_defaults.h"
+#include "absl/strings/str_format.h"
+#include "benchmark/benchmark.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace container_internal {
+
+struct RawHashSetTestOnlyAccess {
+ template <typename C>
+ static auto GetSlots(const C& c) -> decltype(c.slots_) {
+ return c.slots_;
+ }
+};
+
+namespace {
+
+struct IntPolicy {
+ using slot_type = int64_t;
+ using key_type = int64_t;
+ using init_type = int64_t;
+
+ static void construct(void*, int64_t* slot, int64_t v) { *slot = v; }
+ static void destroy(void*, int64_t*) {}
+ static void transfer(void*, int64_t* new_slot, int64_t* old_slot) {
+ *new_slot = *old_slot;
+ }
+
+ static int64_t& element(slot_type* slot) { return *slot; }
+
+ template <class F>
+ static auto apply(F&& f, int64_t x) -> decltype(std::forward<F>(f)(x, x)) {
+ return std::forward<F>(f)(x, x);
+ }
+};
+
+class StringPolicy {
+ template <class F, class K, class V,
+ class = typename std::enable_if<
+ std::is_convertible<const K&, absl::string_view>::value>::type>
+ decltype(std::declval<F>()(
+ std::declval<const absl::string_view&>(), std::piecewise_construct,
+ std::declval<std::tuple<K>>(),
+ std::declval<V>())) static apply_impl(F&& f,
+ std::pair<std::tuple<K>, V> p) {
+ const absl::string_view& key = std::get<0>(p.first);
+ return std::forward<F>(f)(key, std::piecewise_construct, std::move(p.first),
+ std::move(p.second));
+ }
+
+ public:
+ struct slot_type {
+ struct ctor {};
+
+ template <class... Ts>
+ slot_type(ctor, Ts&&... ts) : pair(std::forward<Ts>(ts)...) {}
+
+ std::pair<std::string, std::string> pair;
+ };
+
+ using key_type = std::string;
+ using init_type = std::pair<std::string, std::string>;
+
+ template <class allocator_type, class... Args>
+ static void construct(allocator_type* alloc, slot_type* slot, Args... args) {
+ std::allocator_traits<allocator_type>::construct(
+ *alloc, slot, typename slot_type::ctor(), std::forward<Args>(args)...);
+ }
+
+ template <class allocator_type>
+ static void destroy(allocator_type* alloc, slot_type* slot) {
+ std::allocator_traits<allocator_type>::destroy(*alloc, slot);
+ }
+
+ template <class allocator_type>
+ static void transfer(allocator_type* alloc, slot_type* new_slot,
+ slot_type* old_slot) {
+ construct(alloc, new_slot, std::move(old_slot->pair));
+ destroy(alloc, old_slot);
+ }
+
+ static std::pair<std::string, std::string>& element(slot_type* slot) {
+ return slot->pair;
+ }
+
+ template <class F, class... Args>
+ static auto apply(F&& f, Args&&... args)
+ -> decltype(apply_impl(std::forward<F>(f),
+ PairArgs(std::forward<Args>(args)...))) {
+ return apply_impl(std::forward<F>(f),
+ PairArgs(std::forward<Args>(args)...));
+ }
+};
+
+struct StringHash : container_internal::hash_default_hash<absl::string_view> {
+ using is_transparent = void;
+};
+struct StringEq : std::equal_to<absl::string_view> {
+ using is_transparent = void;
+};
+
+struct StringTable
+ : raw_hash_set<StringPolicy, StringHash, StringEq, std::allocator<int>> {
+ using Base = typename StringTable::raw_hash_set;
+ StringTable() {}
+ using Base::Base;
+};
+
+struct IntTable
+ : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>,
+ std::equal_to<int64_t>, std::allocator<int64_t>> {
+ using Base = typename IntTable::raw_hash_set;
+ IntTable() {}
+ using Base::Base;
+};
+
+struct string_generator {
+ template <class RNG>
+ std::string operator()(RNG& rng) const {
+ std::string res;
+ res.resize(12);
+ std::uniform_int_distribution<uint32_t> printable_ascii(0x20, 0x7E);
+ std::generate(res.begin(), res.end(), [&] { return printable_ascii(rng); });
+ return res;
+ }
+
+ size_t size;
+};
+
+// Model a cache in steady state.
+//
+// On a table of size N, keep deleting the LRU entry and add a random one.
+void BM_CacheInSteadyState(benchmark::State& state) {
+ std::random_device rd;
+ std::mt19937 rng(rd());
+ string_generator gen{12};
+ StringTable t;
+ std::deque<std::string> keys;
+ while (t.size() < state.range(0)) {
+ auto x = t.emplace(gen(rng), gen(rng));
+ if (x.second) keys.push_back(x.first->first);
+ }
+ ABSL_RAW_CHECK(state.range(0) >= 10, "");
+ while (state.KeepRunning()) {
+ // Some cache hits.
+ std::deque<std::string>::const_iterator it;
+ for (int i = 0; i != 90; ++i) {
+ if (i % 10 == 0) it = keys.end();
+ ::benchmark::DoNotOptimize(t.find(*--it));
+ }
+ // Some cache misses.
+ for (int i = 0; i != 10; ++i) ::benchmark::DoNotOptimize(t.find(gen(rng)));
+ ABSL_RAW_CHECK(t.erase(keys.front()), keys.front().c_str());
+ keys.pop_front();
+ while (true) {
+ auto x = t.emplace(gen(rng), gen(rng));
+ if (x.second) {
+ keys.push_back(x.first->first);
+ break;
+ }
+ }
+ }
+ state.SetItemsProcessed(state.iterations());
+ state.SetLabel(absl::StrFormat("load_factor=%.2f", t.load_factor()));
+}
+
+template <typename Benchmark>
+void CacheInSteadyStateArgs(Benchmark* bm) {
+ // The default.
+ const float max_load_factor = 0.875;
+ // When the cache is at the steady state, the probe sequence will equal
+ // capacity if there is no reclamation of deleted slots. Pick a number large
+ // enough to make the benchmark slow for that case.
+ const size_t capacity = 1 << 10;
+
+ // Check N data points to cover load factors in [0.4, 0.8).
+ const size_t kNumPoints = 10;
+ for (size_t i = 0; i != kNumPoints; ++i)
+ bm->Arg(std::ceil(
+ capacity * (max_load_factor + i * max_load_factor / kNumPoints) / 2));
+}
+BENCHMARK(BM_CacheInSteadyState)->Apply(CacheInSteadyStateArgs);
+
+void BM_EndComparison(benchmark::State& state) {
+ std::random_device rd;
+ std::mt19937 rng(rd());
+ string_generator gen{12};
+ StringTable t;
+ while (t.size() < state.range(0)) {
+ t.emplace(gen(rng), gen(rng));
+ }
+
+ for (auto _ : state) {
+ for (auto it = t.begin(); it != t.end(); ++it) {
+ benchmark::DoNotOptimize(it);
+ benchmark::DoNotOptimize(t);
+ benchmark::DoNotOptimize(it != t.end());
+ }
+ }
+}
+BENCHMARK(BM_EndComparison)->Arg(400);
+
+void BM_CopyCtor(benchmark::State& state) {
+ std::random_device rd;
+ std::mt19937 rng(rd());
+ IntTable t;
+ std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
+
+ while (t.size() < state.range(0)) {
+ t.emplace(dist(rng));
+ }
+
+ for (auto _ : state) {
+ IntTable t2 = t;
+ benchmark::DoNotOptimize(t2);
+ }
+}
+BENCHMARK(BM_CopyCtor)->Range(128, 4096);
+
+void BM_CopyAssign(benchmark::State& state) {
+ std::random_device rd;
+ std::mt19937 rng(rd());
+ IntTable t;
+ std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
+ while (t.size() < state.range(0)) {
+ t.emplace(dist(rng));
+ }
+
+ IntTable t2;
+ for (auto _ : state) {
+ t2 = t;
+ benchmark::DoNotOptimize(t2);
+ }
+}
+BENCHMARK(BM_CopyAssign)->Range(128, 4096);
+
+void BM_NoOpReserveIntTable(benchmark::State& state) {
+ IntTable t;
+ t.reserve(100000);
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(t);
+ t.reserve(100000);
+ }
+}
+BENCHMARK(BM_NoOpReserveIntTable);
+
+void BM_NoOpReserveStringTable(benchmark::State& state) {
+ StringTable t;
+ t.reserve(100000);
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(t);
+ t.reserve(100000);
+ }
+}
+BENCHMARK(BM_NoOpReserveStringTable);
+
+void BM_ReserveIntTable(benchmark::State& state) {
+ int reserve_size = state.range(0);
+ for (auto _ : state) {
+ state.PauseTiming();
+ IntTable t;
+ state.ResumeTiming();
+ benchmark::DoNotOptimize(t);
+ t.reserve(reserve_size);
+ }
+}
+BENCHMARK(BM_ReserveIntTable)->Range(128, 4096);
+
+void BM_ReserveStringTable(benchmark::State& state) {
+ int reserve_size = state.range(0);
+ for (auto _ : state) {
+ state.PauseTiming();
+ StringTable t;
+ state.ResumeTiming();
+ benchmark::DoNotOptimize(t);
+ t.reserve(reserve_size);
+ }
+}
+BENCHMARK(BM_ReserveStringTable)->Range(128, 4096);
+
+void BM_Group_Match(benchmark::State& state) {
+ std::array<ctrl_t, Group::kWidth> group;
+ std::iota(group.begin(), group.end(), -4);
+ Group g{group.data()};
+ h2_t h = 1;
+ for (auto _ : state) {
+ ::benchmark::DoNotOptimize(h);
+ ::benchmark::DoNotOptimize(g.Match(h));
+ }
+}
+BENCHMARK(BM_Group_Match);
+
+void BM_Group_MatchEmpty(benchmark::State& state) {
+ std::array<ctrl_t, Group::kWidth> group;
+ std::iota(group.begin(), group.end(), -4);
+ Group g{group.data()};
+ for (auto _ : state) ::benchmark::DoNotOptimize(g.MatchEmpty());
+}
+BENCHMARK(BM_Group_MatchEmpty);
+
+void BM_Group_MatchEmptyOrDeleted(benchmark::State& state) {
+ std::array<ctrl_t, Group::kWidth> group;
+ std::iota(group.begin(), group.end(), -4);
+ Group g{group.data()};
+ for (auto _ : state) ::benchmark::DoNotOptimize(g.MatchEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_MatchEmptyOrDeleted);
+
+void BM_Group_CountLeadingEmptyOrDeleted(benchmark::State& state) {
+ std::array<ctrl_t, Group::kWidth> group;
+ std::iota(group.begin(), group.end(), -2);
+ Group g{group.data()};
+ for (auto _ : state)
+ ::benchmark::DoNotOptimize(g.CountLeadingEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_CountLeadingEmptyOrDeleted);
+
+void BM_Group_MatchFirstEmptyOrDeleted(benchmark::State& state) {
+ std::array<ctrl_t, Group::kWidth> group;
+ std::iota(group.begin(), group.end(), -2);
+ Group g{group.data()};
+ for (auto _ : state) ::benchmark::DoNotOptimize(*g.MatchEmptyOrDeleted());
+}
+BENCHMARK(BM_Group_MatchFirstEmptyOrDeleted);
+
+void BM_DropDeletes(benchmark::State& state) {
+ constexpr size_t capacity = (1 << 20) - 1;
+ std::vector<ctrl_t> ctrl(capacity + 1 + Group::kWidth);
+ ctrl[capacity] = kSentinel;
+ std::vector<ctrl_t> pattern = {kEmpty, 2, kDeleted, 2, kEmpty, 1, kDeleted};
+ for (size_t i = 0; i != capacity; ++i) {
+ ctrl[i] = pattern[i % pattern.size()];
+ }
+ while (state.KeepRunning()) {
+ state.PauseTiming();
+ std::vector<ctrl_t> ctrl_copy = ctrl;
+ state.ResumeTiming();
+ ConvertDeletedToEmptyAndFullToDeleted(ctrl_copy.data(), capacity);
+ ::benchmark::DoNotOptimize(ctrl_copy[capacity]);
+ }
+}
+BENCHMARK(BM_DropDeletes);
+
+} // namespace
+} // namespace container_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// These methods are here to make it easy to examine the assembly for targeted
+// parts of the API.
+auto CodegenAbslRawHashSetInt64Find(absl::container_internal::IntTable* table,
+ int64_t key) -> decltype(table->find(key)) {
+ return table->find(key);
+}
+
+bool CodegenAbslRawHashSetInt64FindNeEnd(
+ absl::container_internal::IntTable* table, int64_t key) {
+ return table->find(key) != table->end();
+}
+
+bool CodegenAbslRawHashSetInt64Contains(
+ absl::container_internal::IntTable* table, int64_t key) {
+ return table->contains(key);
+}
+
+void CodegenAbslRawHashSetInt64Iterate(
+ absl::container_internal::IntTable* table) {
+ for (auto x : *table) benchmark::DoNotOptimize(x);
+}
+
+int odr =
+ (::benchmark::DoNotOptimize(std::make_tuple(
+ &CodegenAbslRawHashSetInt64Find, &CodegenAbslRawHashSetInt64FindNeEnd,
+ &CodegenAbslRawHashSetInt64Contains,
+ &CodegenAbslRawHashSetInt64Iterate)),
+ 1);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc
new file mode 100644
index 00000000000..7169a2e2064
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc
@@ -0,0 +1,590 @@
+// 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 probe length statistics for many combinations of key types and key
+// distributions, all using the default hash function for swisstable.
+
+#include <memory>
+#include <regex> // NOLINT
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/internal/hash_function_defaults.h"
+#include "absl/container/internal/hashtable_debug.h"
+#include "absl/container/internal/raw_hash_set.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+enum class OutputStyle { kRegular, kBenchmark };
+
+// The --benchmark command line flag.
+// This is populated from main().
+// When run in "benchmark" mode, we have different output. This allows
+// A/B comparisons with tools like `benchy`.
+absl::string_view benchmarks;
+
+OutputStyle output() {
+ return !benchmarks.empty() ? OutputStyle::kBenchmark : OutputStyle::kRegular;
+}
+
+template <class T>
+struct Policy {
+ using slot_type = T;
+ using key_type = T;
+ using init_type = T;
+
+ template <class allocator_type, class Arg>
+ static void construct(allocator_type* alloc, slot_type* slot,
+ const Arg& arg) {
+ std::allocator_traits<allocator_type>::construct(*alloc, slot, arg);
+ }
+
+ template <class allocator_type>
+ static void destroy(allocator_type* alloc, slot_type* slot) {
+ std::allocator_traits<allocator_type>::destroy(*alloc, slot);
+ }
+
+ static slot_type& element(slot_type* slot) { return *slot; }
+
+ template <class F, class... Args>
+ static auto apply(F&& f, const slot_type& arg)
+ -> decltype(std::forward<F>(f)(arg, arg)) {
+ return std::forward<F>(f)(arg, arg);
+ }
+};
+
+absl::BitGen& GlobalBitGen() {
+ static auto* value = new absl::BitGen;
+ return *value;
+}
+
+// Keeps a pool of allocations and randomly gives one out.
+// This introduces more randomization to the addresses given to swisstable and
+// should help smooth out this factor from probe length calculation.
+template <class T>
+class RandomizedAllocator {
+ public:
+ using value_type = T;
+
+ RandomizedAllocator() = default;
+ template <typename U>
+ RandomizedAllocator(RandomizedAllocator<U>) {} // NOLINT
+
+ static T* allocate(size_t n) {
+ auto& pointers = GetPointers(n);
+ // Fill the pool
+ while (pointers.size() < kRandomPool) {
+ pointers.push_back(std::allocator<T>{}.allocate(n));
+ }
+
+ // Choose a random one.
+ size_t i = absl::Uniform<size_t>(GlobalBitGen(), 0, pointers.size());
+ T* result = pointers[i];
+ pointers[i] = pointers.back();
+ pointers.pop_back();
+ return result;
+ }
+
+ static void deallocate(T* p, size_t n) {
+ // Just put it back on the pool. No need to release the memory.
+ GetPointers(n).push_back(p);
+ }
+
+ private:
+ // We keep at least kRandomPool allocations for each size.
+ static constexpr size_t kRandomPool = 20;
+
+ static std::vector<T*>& GetPointers(size_t n) {
+ static auto* m = new absl::flat_hash_map<size_t, std::vector<T*>>();
+ return (*m)[n];
+ }
+};
+
+template <class T>
+struct DefaultHash {
+ using type = absl::container_internal::hash_default_hash<T>;
+};
+
+template <class T>
+using DefaultHashT = typename DefaultHash<T>::type;
+
+template <class T>
+struct Table : absl::container_internal::raw_hash_set<
+ Policy<T>, DefaultHashT<T>,
+ absl::container_internal::hash_default_eq<T>,
+ RandomizedAllocator<T>> {};
+
+struct LoadSizes {
+ size_t min_load;
+ size_t max_load;
+};
+
+LoadSizes GetMinMaxLoadSizes() {
+ static const auto sizes = [] {
+ Table<int> t;
+
+ // First, fill enough to have a good distribution.
+ constexpr size_t kMinSize = 10000;
+ while (t.size() < kMinSize) t.insert(t.size());
+
+ const auto reach_min_load_factor = [&] {
+ const double lf = t.load_factor();
+ while (lf <= t.load_factor()) t.insert(t.size());
+ };
+
+ // Then, insert until we reach min load factor.
+ reach_min_load_factor();
+ const size_t min_load_size = t.size();
+
+ // Keep going until we hit min load factor again, then go back one.
+ t.insert(t.size());
+ reach_min_load_factor();
+
+ return LoadSizes{min_load_size, t.size() - 1};
+ }();
+ return sizes;
+}
+
+struct Ratios {
+ double min_load;
+ double avg_load;
+ double max_load;
+};
+
+// See absl/container/internal/hashtable_debug.h for details on
+// probe length calculation.
+template <class ElemFn>
+Ratios CollectMeanProbeLengths() {
+ const auto min_max_sizes = GetMinMaxLoadSizes();
+
+ ElemFn elem;
+ using Key = decltype(elem());
+ Table<Key> t;
+
+ Ratios result;
+ while (t.size() < min_max_sizes.min_load) t.insert(elem());
+ result.min_load =
+ absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+ while (t.size() < (min_max_sizes.min_load + min_max_sizes.max_load) / 2)
+ t.insert(elem());
+ result.avg_load =
+ absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+ while (t.size() < min_max_sizes.max_load) t.insert(elem());
+ result.max_load =
+ absl::container_internal::GetHashtableDebugProbeSummary(t).mean;
+
+ return result;
+}
+
+template <int Align>
+uintptr_t PointerForAlignment() {
+ alignas(Align) static constexpr uintptr_t kInitPointer = 0;
+ return reinterpret_cast<uintptr_t>(&kInitPointer);
+}
+
+// This incomplete type is used for testing hash of pointers of different
+// alignments.
+// NOTE: We are generating invalid pointer values on the fly with
+// reinterpret_cast. There are not "safely derived" pointers so using them is
+// technically UB. It is unlikely to be a problem, though.
+template <int Align>
+struct Ptr;
+
+template <int Align>
+Ptr<Align>* MakePtr(uintptr_t v) {
+ if (sizeof(v) == 8) {
+ constexpr int kCopyBits = 16;
+ // Ensure high bits are all the same.
+ v = static_cast<uintptr_t>(static_cast<intptr_t>(v << kCopyBits) >>
+ kCopyBits);
+ }
+ return reinterpret_cast<Ptr<Align>*>(v);
+}
+
+struct IntIdentity {
+ uint64_t i;
+ friend bool operator==(IntIdentity a, IntIdentity b) { return a.i == b.i; }
+ IntIdentity operator++(int) { return IntIdentity{i++}; }
+};
+
+template <int Align>
+struct PtrIdentity {
+ explicit PtrIdentity(uintptr_t val = PointerForAlignment<Align>()) : i(val) {}
+ uintptr_t i;
+ friend bool operator==(PtrIdentity a, PtrIdentity b) { return a.i == b.i; }
+ PtrIdentity operator++(int) {
+ PtrIdentity p(i);
+ i += Align;
+ return p;
+ }
+};
+
+constexpr char kStringFormat[] = "/path/to/file/name-%07d-of-9999999.txt";
+
+template <bool small>
+struct String {
+ std::string value;
+ static std::string Make(uint32_t v) {
+ return {small ? absl::StrCat(v) : absl::StrFormat(kStringFormat, v)};
+ }
+};
+
+template <>
+struct DefaultHash<IntIdentity> {
+ struct type {
+ size_t operator()(IntIdentity t) const { return t.i; }
+ };
+};
+
+template <int Align>
+struct DefaultHash<PtrIdentity<Align>> {
+ struct type {
+ size_t operator()(PtrIdentity<Align> t) const { return t.i; }
+ };
+};
+
+template <class T>
+struct Sequential {
+ T operator()() const { return current++; }
+ mutable T current{};
+};
+
+template <int Align>
+struct Sequential<Ptr<Align>*> {
+ Ptr<Align>* operator()() const {
+ auto* result = MakePtr<Align>(current);
+ current += Align;
+ return result;
+ }
+ mutable uintptr_t current = PointerForAlignment<Align>();
+};
+
+
+template <bool small>
+struct Sequential<String<small>> {
+ std::string operator()() const { return String<small>::Make(current++); }
+ mutable uint32_t current = 0;
+};
+
+template <class T, class U>
+struct Sequential<std::pair<T, U>> {
+ mutable Sequential<T> tseq;
+ mutable Sequential<U> useq;
+
+ using RealT = decltype(tseq());
+ using RealU = decltype(useq());
+
+ mutable std::vector<RealT> ts;
+ mutable std::vector<RealU> us;
+ mutable size_t ti = 0, ui = 0;
+
+ std::pair<RealT, RealU> operator()() const {
+ std::pair<RealT, RealU> value{get_t(), get_u()};
+ if (ti == 0) {
+ ti = ui + 1;
+ ui = 0;
+ } else {
+ --ti;
+ ++ui;
+ }
+ return value;
+ }
+
+ RealT get_t() const {
+ while (ti >= ts.size()) ts.push_back(tseq());
+ return ts[ti];
+ }
+
+ RealU get_u() const {
+ while (ui >= us.size()) us.push_back(useq());
+ return us[ui];
+ }
+};
+
+template <class T, int percent_skip>
+struct AlmostSequential {
+ mutable Sequential<T> current;
+
+ auto operator()() const -> decltype(current()) {
+ while (absl::Uniform(GlobalBitGen(), 0.0, 1.0) <= percent_skip / 100.)
+ current();
+ return current();
+ }
+};
+
+struct Uniform {
+ template <typename T>
+ T operator()(T) const {
+ return absl::Uniform<T>(absl::IntervalClosed, GlobalBitGen(), T{0}, ~T{0});
+ }
+};
+
+struct Gaussian {
+ template <typename T>
+ T operator()(T) const {
+ double d;
+ do {
+ d = absl::Gaussian<double>(GlobalBitGen(), 1e6, 1e4);
+ } while (d <= 0 || d > std::numeric_limits<T>::max() / 2);
+ return static_cast<T>(d);
+ }
+};
+
+struct Zipf {
+ template <typename T>
+ T operator()(T) const {
+ return absl::Zipf<T>(GlobalBitGen(), std::numeric_limits<T>::max(), 1.6);
+ }
+};
+
+template <class T, class Dist>
+struct Random {
+ T operator()() const { return Dist{}(T{}); }
+};
+
+template <class Dist, int Align>
+struct Random<Ptr<Align>*, Dist> {
+ Ptr<Align>* operator()() const {
+ return MakePtr<Align>(Random<uintptr_t, Dist>{}() * Align);
+ }
+};
+
+template <class Dist>
+struct Random<IntIdentity, Dist> {
+ IntIdentity operator()() const {
+ return IntIdentity{Random<uint64_t, Dist>{}()};
+ }
+};
+
+template <class Dist, int Align>
+struct Random<PtrIdentity<Align>, Dist> {
+ PtrIdentity<Align> operator()() const {
+ return PtrIdentity<Align>{Random<uintptr_t, Dist>{}() * Align};
+ }
+};
+
+template <class Dist, bool small>
+struct Random<String<small>, Dist> {
+ std::string operator()() const {
+ return String<small>::Make(Random<uint32_t, Dist>{}());
+ }
+};
+
+template <class T, class U, class Dist>
+struct Random<std::pair<T, U>, Dist> {
+ auto operator()() const
+ -> decltype(std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}())) {
+ return std::make_pair(Random<T, Dist>{}(), Random<U, Dist>{}());
+ }
+};
+
+template <typename>
+std::string Name();
+
+std::string Name(uint32_t*) { return "u32"; }
+std::string Name(uint64_t*) { return "u64"; }
+std::string Name(IntIdentity*) { return "IntIdentity"; }
+
+template <int Align>
+std::string Name(Ptr<Align>**) {
+ return absl::StrCat("Ptr", Align);
+}
+
+template <int Align>
+std::string Name(PtrIdentity<Align>*) {
+ return absl::StrCat("PtrIdentity", Align);
+}
+
+template <bool small>
+std::string Name(String<small>*) {
+ return small ? "StrS" : "StrL";
+}
+
+template <class T, class U>
+std::string Name(std::pair<T, U>*) {
+ if (output() == OutputStyle::kBenchmark)
+ return absl::StrCat("P_", Name<T>(), "_", Name<U>());
+ return absl::StrCat("P<", Name<T>(), ",", Name<U>(), ">");
+}
+
+template <class T>
+std::string Name(Sequential<T>*) {
+ return "Sequential";
+}
+
+template <class T, int P>
+std::string Name(AlmostSequential<T, P>*) {
+ return absl::StrCat("AlmostSeq_", P);
+}
+
+template <class T>
+std::string Name(Random<T, Uniform>*) {
+ return "UnifRand";
+}
+
+template <class T>
+std::string Name(Random<T, Gaussian>*) {
+ return "GausRand";
+}
+
+template <class T>
+std::string Name(Random<T, Zipf>*) {
+ return "ZipfRand";
+}
+
+template <typename T>
+std::string Name() {
+ return Name(static_cast<T*>(nullptr));
+}
+
+constexpr int kNameWidth = 15;
+constexpr int kDistWidth = 16;
+
+bool CanRunBenchmark(absl::string_view name) {
+ static std::regex* const filter = []() -> std::regex* {
+ return benchmarks.empty() || benchmarks == "all"
+ ? nullptr
+ : new std::regex(std::string(benchmarks));
+ }();
+ return filter == nullptr || std::regex_search(std::string(name), *filter);
+}
+
+struct Result {
+ std::string name;
+ std::string dist_name;
+ Ratios ratios;
+};
+
+template <typename T, typename Dist>
+void RunForTypeAndDistribution(std::vector<Result>& results) {
+ std::string name = absl::StrCat(Name<T>(), "/", Name<Dist>());
+ // We have to check against all three names (min/avg/max) before we run it.
+ // If any of them is enabled, we run it.
+ if (!CanRunBenchmark(absl::StrCat(name, "/min")) &&
+ !CanRunBenchmark(absl::StrCat(name, "/avg")) &&
+ !CanRunBenchmark(absl::StrCat(name, "/max"))) {
+ return;
+ }
+ results.push_back({Name<T>(), Name<Dist>(), CollectMeanProbeLengths<Dist>()});
+}
+
+template <class T>
+void RunForType(std::vector<Result>& results) {
+ RunForTypeAndDistribution<T, Sequential<T>>(results);
+ RunForTypeAndDistribution<T, AlmostSequential<T, 20>>(results);
+ RunForTypeAndDistribution<T, AlmostSequential<T, 50>>(results);
+ RunForTypeAndDistribution<T, Random<T, Uniform>>(results);
+#ifdef NDEBUG
+ // Disable these in non-opt mode because they take too long.
+ RunForTypeAndDistribution<T, Random<T, Gaussian>>(results);
+ RunForTypeAndDistribution<T, Random<T, Zipf>>(results);
+#endif // NDEBUG
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ // Parse the benchmark flags. Ignore all of them except the regex pattern.
+ for (int i = 1; i < argc; ++i) {
+ absl::string_view arg = argv[i];
+ const auto next = [&] { return argv[std::min(i + 1, argc - 1)]; };
+
+ if (absl::ConsumePrefix(&arg, "--benchmark_filter")) {
+ if (arg == "") {
+ // --benchmark_filter X
+ benchmarks = next();
+ } else if (absl::ConsumePrefix(&arg, "=")) {
+ // --benchmark_filter=X
+ benchmarks = arg;
+ }
+ }
+
+ // Any --benchmark flag turns on the mode.
+ if (absl::ConsumePrefix(&arg, "--benchmark")) {
+ if (benchmarks.empty()) benchmarks="all";
+ }
+ }
+
+ std::vector<Result> results;
+ RunForType<uint64_t>(results);
+ RunForType<IntIdentity>(results);
+ RunForType<Ptr<8>*>(results);
+ RunForType<Ptr<16>*>(results);
+ RunForType<Ptr<32>*>(results);
+ RunForType<Ptr<64>*>(results);
+ RunForType<PtrIdentity<8>>(results);
+ RunForType<PtrIdentity<16>>(results);
+ RunForType<PtrIdentity<32>>(results);
+ RunForType<PtrIdentity<64>>(results);
+ RunForType<std::pair<uint32_t, uint32_t>>(results);
+ RunForType<String<true>>(results);
+ RunForType<String<false>>(results);
+ RunForType<std::pair<uint64_t, String<true>>>(results);
+ RunForType<std::pair<String<true>, uint64_t>>(results);
+ RunForType<std::pair<uint64_t, String<false>>>(results);
+ RunForType<std::pair<String<false>, uint64_t>>(results);
+
+ switch (output()) {
+ case OutputStyle::kRegular:
+ absl::PrintF("%-*s%-*s Min Avg Max\n%s\n", kNameWidth,
+ "Type", kDistWidth, "Distribution",
+ std::string(kNameWidth + kDistWidth + 10 * 3, '-'));
+ for (const auto& result : results) {
+ absl::PrintF("%-*s%-*s %8.4f %8.4f %8.4f\n", kNameWidth, result.name,
+ kDistWidth, result.dist_name, result.ratios.min_load,
+ result.ratios.avg_load, result.ratios.max_load);
+ }
+ break;
+ case OutputStyle::kBenchmark: {
+ absl::PrintF("{\n");
+ absl::PrintF(" \"benchmarks\": [\n");
+ absl::string_view comma;
+ for (const auto& result : results) {
+ auto print = [&](absl::string_view stat, double Ratios::*val) {
+ std::string name =
+ absl::StrCat(result.name, "/", result.dist_name, "/", stat);
+ // Check the regex again. We might had have enabled only one of the
+ // stats for the benchmark.
+ if (!CanRunBenchmark(name)) return;
+ absl::PrintF(" %s{\n", comma);
+ absl::PrintF(" \"cpu_time\": %f,\n", 1e9 * result.ratios.*val);
+ absl::PrintF(" \"real_time\": %f,\n", 1e9 * result.ratios.*val);
+ absl::PrintF(" \"iterations\": 1,\n");
+ absl::PrintF(" \"name\": \"%s\",\n", name);
+ absl::PrintF(" \"time_unit\": \"ns\"\n");
+ absl::PrintF(" }\n");
+ comma = ",";
+ };
+ print("min", &Ratios::min_load);
+ print("avg", &Ratios::avg_load);
+ print("max", &Ratios::max_load);
+ }
+ absl::PrintF(" ],\n");
+ absl::PrintF(" \"context\": {\n");
+ absl::PrintF(" }\n");
+ absl::PrintF("}\n");
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
index 5ad4904f971..7dac65a03be 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,7 @@
#include "absl/container/internal/raw_hash_set.h"
+#include <atomic>
#include <cmath>
#include <cstdint>
#include <deque>
@@ -22,10 +23,13 @@
#include <numeric>
#include <random>
#include <string>
+#include <unordered_map>
+#include <unordered_set>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/cycleclock.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/container/internal/container_memory.h"
@@ -35,6 +39,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
struct RawHashSetTestOnlyAccess {
@@ -46,20 +51,54 @@ struct RawHashSetTestOnlyAccess {
namespace {
-using ::testing::DoubleNear;
using ::testing::ElementsAre;
-using ::testing::Optional;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::Lt;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
TEST(Util, NormalizeCapacity) {
- constexpr size_t kMinCapacity = Group::kWidth - 1;
- EXPECT_EQ(kMinCapacity, NormalizeCapacity(0));
- EXPECT_EQ(kMinCapacity, NormalizeCapacity(1));
- EXPECT_EQ(kMinCapacity, NormalizeCapacity(2));
- EXPECT_EQ(kMinCapacity, NormalizeCapacity(kMinCapacity));
- EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 1));
- EXPECT_EQ(kMinCapacity * 2 + 1, NormalizeCapacity(kMinCapacity + 2));
+ EXPECT_EQ(1, NormalizeCapacity(0));
+ EXPECT_EQ(1, NormalizeCapacity(1));
+ EXPECT_EQ(3, NormalizeCapacity(2));
+ EXPECT_EQ(3, NormalizeCapacity(3));
+ EXPECT_EQ(7, NormalizeCapacity(4));
+ EXPECT_EQ(7, NormalizeCapacity(7));
+ EXPECT_EQ(15, NormalizeCapacity(8));
+ EXPECT_EQ(15, NormalizeCapacity(15));
+ EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 1));
+ EXPECT_EQ(15 * 2 + 1, NormalizeCapacity(15 + 2));
+}
+
+TEST(Util, GrowthAndCapacity) {
+ // Verify that GrowthToCapacity gives the minimum capacity that has enough
+ // growth.
+ for (size_t growth = 0; growth < 10000; ++growth) {
+ SCOPED_TRACE(growth);
+ size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
+ // The capacity is large enough for `growth`.
+ EXPECT_THAT(CapacityToGrowth(capacity), Ge(growth));
+ // For (capacity+1) < kWidth, growth should equal capacity.
+ if (capacity + 1 < Group::kWidth) {
+ EXPECT_THAT(CapacityToGrowth(capacity), Eq(capacity));
+ } else {
+ EXPECT_THAT(CapacityToGrowth(capacity), Lt(capacity));
+ }
+ if (growth != 0 && capacity > 1) {
+ // There is no smaller capacity that works.
+ EXPECT_THAT(CapacityToGrowth(capacity / 2), Lt(growth));
+ }
+ }
+
+ for (size_t capacity = Group::kWidth - 1; capacity < 10000;
+ capacity = 2 * capacity + 1) {
+ SCOPED_TRACE(capacity);
+ size_t growth = CapacityToGrowth(capacity);
+ EXPECT_THAT(growth, Lt(capacity));
+ EXPECT_LE(GrowthToLowerboundCapacity(growth), capacity);
+ EXPECT_EQ(NormalizeCapacity(GrowthToLowerboundCapacity(growth)), capacity);
+ }
}
TEST(Util, probe_seq) {
@@ -106,14 +145,14 @@ TEST(BitMask, WithShift) {
}
TEST(BitMask, LeadingTrailing) {
- EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).LeadingZeros()), 3);
- EXPECT_EQ((BitMask<uint32_t, 16>(0b0001101001000000).TrailingZeros()), 6);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).LeadingZeros()), 3);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00001a40).TrailingZeros()), 6);
- EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).LeadingZeros()), 15);
- EXPECT_EQ((BitMask<uint32_t, 16>(0b0000000000000001).TrailingZeros()), 0);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).LeadingZeros()), 15);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00000001).TrailingZeros()), 0);
- EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).LeadingZeros()), 0);
- EXPECT_EQ((BitMask<uint32_t, 16>(0b1000000000000000).TrailingZeros()), 15);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).LeadingZeros()), 0);
+ EXPECT_EQ((BitMask<uint32_t, 16>(0x00008000).TrailingZeros()), 15);
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).LeadingZeros()), 3);
EXPECT_EQ((BitMask<uint64_t, 8, 3>(0x0000008080808000).TrailingZeros()), 1);
@@ -219,25 +258,43 @@ TEST(Group, CountLeadingEmptyOrDeleted) {
}
}
-struct IntPolicy {
- using slot_type = int64_t;
- using key_type = int64_t;
- using init_type = int64_t;
+template <class T>
+struct ValuePolicy {
+ using slot_type = T;
+ using key_type = T;
+ using init_type = T;
- static void construct(void*, int64_t* slot, int64_t v) { *slot = v; }
- static void destroy(void*, int64_t*) {}
- static void transfer(void*, int64_t* new_slot, int64_t* old_slot) {
- *new_slot = *old_slot;
+ template <class Allocator, class... Args>
+ static void construct(Allocator* alloc, slot_type* slot, Args&&... args) {
+ absl::allocator_traits<Allocator>::construct(*alloc, slot,
+ std::forward<Args>(args)...);
}
- static int64_t& element(slot_type* slot) { return *slot; }
+ template <class Allocator>
+ static void destroy(Allocator* alloc, slot_type* slot) {
+ absl::allocator_traits<Allocator>::destroy(*alloc, slot);
+ }
- template <class F>
- static auto apply(F&& f, int64_t x) -> decltype(std::forward<F>(f)(x, x)) {
- return std::forward<F>(f)(x, x);
+ template <class Allocator>
+ static void transfer(Allocator* alloc, slot_type* new_slot,
+ slot_type* old_slot) {
+ construct(alloc, new_slot, std::move(*old_slot));
+ destroy(alloc, old_slot);
+ }
+
+ static T& element(slot_type* slot) { return *slot; }
+
+ template <class F, class... Args>
+ 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)...);
}
};
+using IntPolicy = ValuePolicy<int64_t>;
+
class StringPolicy {
template <class F, class K, class V,
class = typename std::enable_if<
@@ -314,7 +371,25 @@ struct IntTable
: raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>,
std::equal_to<int64_t>, std::allocator<int64_t>> {
using Base = typename IntTable::raw_hash_set;
- IntTable() {}
+ using Base::Base;
+};
+
+template <typename T>
+struct CustomAlloc : std::allocator<T> {
+ CustomAlloc() {}
+
+ template <typename U>
+ CustomAlloc(const CustomAlloc<U>& other) {}
+
+ template<class U> struct rebind {
+ using other = CustomAlloc<U>;
+ };
+};
+
+struct CustomAllocIntTable
+ : raw_hash_set<IntPolicy, container_internal::hash_default_hash<int64_t>,
+ std::equal_to<int64_t>, CustomAlloc<int64_t>> {
+ using Base = typename CustomAllocIntTable::raw_hash_set;
using Base::Base;
};
@@ -342,6 +417,14 @@ TEST(Table, EmptyFunctorOptimization) {
size_t size;
size_t capacity;
size_t growth_left;
+ void* infoz;
+ };
+ struct MockTableInfozDisabled {
+ void* ctrl;
+ void* slots;
+ size_t size;
+ size_t capacity;
+ size_t growth_left;
};
struct StatelessHash {
size_t operator()(absl::string_view) const { return 0; }
@@ -350,17 +433,27 @@ TEST(Table, EmptyFunctorOptimization) {
size_t dummy;
};
- EXPECT_EQ(
- sizeof(MockTable),
- sizeof(
- raw_hash_set<StringPolicy, StatelessHash,
- std::equal_to<absl::string_view>, std::allocator<int>>));
+ if (std::is_empty<HashtablezInfoHandle>::value) {
+ EXPECT_EQ(sizeof(MockTableInfozDisabled),
+ sizeof(raw_hash_set<StringPolicy, StatelessHash,
+ std::equal_to<absl::string_view>,
+ std::allocator<int>>));
- EXPECT_EQ(
- sizeof(MockTable) + sizeof(StatefulHash),
- sizeof(
- raw_hash_set<StringPolicy, StatefulHash,
- std::equal_to<absl::string_view>, std::allocator<int>>));
+ EXPECT_EQ(sizeof(MockTableInfozDisabled) + sizeof(StatefulHash),
+ sizeof(raw_hash_set<StringPolicy, StatefulHash,
+ std::equal_to<absl::string_view>,
+ std::allocator<int>>));
+ } else {
+ EXPECT_EQ(sizeof(MockTable),
+ sizeof(raw_hash_set<StringPolicy, StatelessHash,
+ std::equal_to<absl::string_view>,
+ std::allocator<int>>));
+
+ EXPECT_EQ(sizeof(MockTable) + sizeof(StatefulHash),
+ sizeof(raw_hash_set<StringPolicy, StatefulHash,
+ std::equal_to<absl::string_view>,
+ std::allocator<int>>));
+ }
}
TEST(Table, Empty) {
@@ -369,52 +462,6 @@ TEST(Table, Empty) {
EXPECT_TRUE(t.empty());
}
-#ifdef __GNUC__
-template <class T>
-ABSL_ATTRIBUTE_ALWAYS_INLINE inline void DoNotOptimize(const T& v) {
- asm volatile("" : : "r,m"(v) : "memory");
-}
-#endif
-
-TEST(Table, Prefetch) {
- IntTable t;
- t.emplace(1);
- // Works for both present and absent keys.
- t.prefetch(1);
- t.prefetch(2);
-
- // Do not run in debug mode, when prefetch is not implemented, or when
- // sanitizers are enabled.
-#if defined(NDEBUG) && defined(__GNUC__) && !defined(ADDRESS_SANITIZER) && \
- !defined(MEMORY_SANITIZER) && !defined(THREAD_SANITIZER) && \
- !defined(UNDEFINED_BEHAVIOR_SANITIZER)
- const auto now = [] { return absl::base_internal::CycleClock::Now(); };
-
- // Make size enough to not fit in L2 cache (16.7 Mb)
- static constexpr int size = 1 << 22;
- for (int i = 0; i < size; ++i) t.insert(i);
-
- int64_t no_prefetch = 0, prefetch = 0;
- for (int iter = 0; iter < 10; ++iter) {
- int64_t time = now();
- for (int i = 0; i < size; ++i) {
- DoNotOptimize(t.find(i));
- }
- no_prefetch += now() - time;
-
- time = now();
- for (int i = 0; i < size; ++i) {
- t.prefetch(i + 20);
- DoNotOptimize(t.find(i));
- }
- prefetch += now() - time;
- }
-
- // no_prefetch is at least 30% slower.
- EXPECT_GE(1.0 * no_prefetch / prefetch, 1.3);
-#endif
-}
-
TEST(Table, LookupEmpty) {
IntTable t;
auto it = t.find(0);
@@ -784,7 +831,7 @@ TEST(Table, EnsureNonQuadraticAsInRust) {
TEST(Table, ClearBug) {
IntTable t;
constexpr size_t capacity = container_internal::Group::kWidth - 1;
- constexpr size_t max_size = capacity / 2;
+ constexpr size_t max_size = capacity / 2 + 1;
for (size_t i = 0; i < max_size; ++i) {
t.insert(i);
}
@@ -815,6 +862,25 @@ TEST(Table, Erase) {
EXPECT_TRUE(t.find(0) == t.end());
}
+TEST(Table, EraseMaintainsValidIterator) {
+ IntTable t;
+ const int kNumElements = 100;
+ for (int i = 0; i < kNumElements; i ++) {
+ EXPECT_TRUE(t.emplace(i).second);
+ }
+ EXPECT_EQ(t.size(), kNumElements);
+
+ int num_erase_calls = 0;
+ auto it = t.begin();
+ while (it != t.end()) {
+ t.erase(it++);
+ num_erase_calls++;
+ }
+
+ EXPECT_TRUE(t.empty());
+ EXPECT_EQ(num_erase_calls, kNumElements);
+}
+
// Collect N bad keys by following algorithm:
// 1. Create an empty table and reserve it to 2 * N.
// 2. Insert N random elements.
@@ -824,7 +890,8 @@ TEST(Table, Erase) {
std::vector<int64_t> CollectBadMergeKeys(size_t N) {
static constexpr int kGroupSize = Group::kWidth - 1;
- auto topk_range = [](size_t b, size_t e, IntTable* t) -> std::vector<int64_t> {
+ auto topk_range = [](size_t b, size_t e,
+ IntTable* t) -> std::vector<int64_t> {
for (size_t i = b; i != e; ++i) {
t->emplace(i);
}
@@ -978,8 +1045,8 @@ using ProbeStatsPerSize = std::map<size_t, ProbeStats>;
// 1. Create new table and reserve it to keys.size() * 2
// 2. Insert all keys xored with seed
// 3. Collect ProbeStats from final table.
-ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector<int64_t>& keys,
- size_t num_iters) {
+ProbeStats CollectProbeStatsOnKeysXoredWithSeed(
+ const std::vector<int64_t>& keys, size_t num_iters) {
const size_t reserve_size = keys.size() * 2;
ProbeStats stats;
@@ -1013,7 +1080,7 @@ ProbeStats CollectProbeStatsOnKeysXoredWithSeed(const std::vector<int64_t>& keys
ExpectedStats XorSeedExpectedStats() {
constexpr bool kRandomizesInserts =
-#if NDEBUG
+#ifdef NDEBUG
false;
#else // NDEBUG
true;
@@ -1050,6 +1117,7 @@ ExpectedStats XorSeedExpectedStats() {
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
+
TEST(Table, DISABLED_EnsureNonQuadraticTopNXorSeedByProbeSeqLength) {
ProbeStatsPerSize stats;
std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1106,7 +1174,7 @@ ProbeStats CollectProbeStatsOnLinearlyTransformedKeys(
ExpectedStats LinearTransformExpectedStats() {
constexpr bool kRandomizesInserts =
-#if NDEBUG
+#ifdef NDEBUG
false;
#else // NDEBUG
true;
@@ -1143,6 +1211,7 @@ ExpectedStats LinearTransformExpectedStats() {
ABSL_RAW_LOG(FATAL, "%s", "Unknown Group width");
return {};
}
+
TEST(Table, DISABLED_EnsureNonQuadraticTopNLinearTransformByProbeSeqLength) {
ProbeStatsPerSize stats;
std::vector<size_t> sizes = {Group::kWidth << 5, Group::kWidth << 10};
@@ -1295,37 +1364,31 @@ TEST(Table, ConstructFromInitList) {
TEST(Table, CopyConstruct) {
IntTable t;
- t.max_load_factor(.321f);
t.emplace(0);
EXPECT_EQ(1, t.size());
{
IntTable u(t);
EXPECT_EQ(1, u.size());
- EXPECT_EQ(t.max_load_factor(), u.max_load_factor());
EXPECT_THAT(*u.find(0), 0);
}
{
IntTable u{t};
EXPECT_EQ(1, u.size());
- EXPECT_EQ(t.max_load_factor(), u.max_load_factor());
EXPECT_THAT(*u.find(0), 0);
}
{
IntTable u = t;
EXPECT_EQ(1, u.size());
- EXPECT_EQ(t.max_load_factor(), u.max_load_factor());
EXPECT_THAT(*u.find(0), 0);
}
}
TEST(Table, CopyConstructWithAlloc) {
StringTable t;
- t.max_load_factor(.321f);
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u(t, Alloc<std::pair<std::string, std::string>>());
EXPECT_EQ(1, u.size());
- EXPECT_EQ(t.max_load_factor(), u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
@@ -1343,94 +1406,75 @@ TEST(Table, AllocWithExplicitCtor) {
TEST(Table, MoveConstruct) {
{
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u(std::move(t));
EXPECT_EQ(1, u.size());
- EXPECT_EQ(lf, u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
{
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u{std::move(t)};
EXPECT_EQ(1, u.size());
- EXPECT_EQ(lf, u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
{
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u = std::move(t);
EXPECT_EQ(1, u.size());
- EXPECT_EQ(lf, u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
}
TEST(Table, MoveConstructWithAlloc) {
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u(std::move(t), Alloc<std::pair<std::string, std::string>>());
EXPECT_EQ(1, u.size());
- EXPECT_EQ(lf, u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
TEST(Table, CopyAssign) {
StringTable t;
- t.max_load_factor(.321f);
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u;
u = t;
EXPECT_EQ(1, u.size());
- EXPECT_EQ(t.max_load_factor(), u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
TEST(Table, CopySelfAssign) {
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
t = *&t;
EXPECT_EQ(1, t.size());
- EXPECT_EQ(lf, t.max_load_factor());
EXPECT_THAT(*t.find("a"), Pair("a", "b"));
}
TEST(Table, MoveAssign) {
StringTable t;
- t.max_load_factor(.321f);
- const float lf = t.max_load_factor();
t.emplace("a", "b");
EXPECT_EQ(1, t.size());
StringTable u;
u = std::move(t);
EXPECT_EQ(1, u.size());
- EXPECT_EQ(lf, u.max_load_factor());
EXPECT_THAT(*u.find("a"), Pair("a", "b"));
}
TEST(Table, Equality) {
StringTable t;
- std::vector<std::pair<std::string, std::string>> v = {{"a", "b"}, {"aa", "bb"}};
+ std::vector<std::pair<std::string, std::string>> v = {{"a", "b"},
+ {"aa", "bb"}};
t.insert(std::begin(v), std::end(v));
StringTable u = t;
EXPECT_EQ(u, t);
@@ -1438,20 +1482,24 @@ TEST(Table, Equality) {
TEST(Table, Equality2) {
StringTable t;
- std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"}, {"aa", "bb"}};
+ std::vector<std::pair<std::string, std::string>> v1 = {{"a", "b"},
+ {"aa", "bb"}};
t.insert(std::begin(v1), std::end(v1));
StringTable u;
- std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+ std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+ {"aa", "aa"}};
u.insert(std::begin(v2), std::end(v2));
EXPECT_NE(u, t);
}
TEST(Table, Equality3) {
StringTable t;
- std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"}, {"bb", "bb"}};
+ std::vector<std::pair<std::string, std::string>> v1 = {{"b", "b"},
+ {"bb", "bb"}};
t.insert(std::begin(v1), std::end(v1));
StringTable u;
- std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"}, {"aa", "aa"}};
+ std::vector<std::pair<std::string, std::string>> v2 = {{"a", "a"},
+ {"aa", "aa"}};
u.insert(std::begin(v2), std::end(v2));
EXPECT_NE(u, t);
}
@@ -1652,6 +1700,38 @@ TEST(Table, Merge) {
EXPECT_THAT(t2, UnorderedElementsAre(Pair("0", "~0")));
}
+TEST(Table, IteratorEmplaceConstructibleRequirement) {
+ struct Value {
+ explicit Value(absl::string_view view) : value(view) {}
+ std::string value;
+
+ bool operator==(const Value& other) const { return value == other.value; }
+ };
+ struct H {
+ size_t operator()(const Value& v) const {
+ return absl::Hash<std::string>{}(v.value);
+ }
+ };
+
+ struct Table : raw_hash_set<ValuePolicy<Value>, H, std::equal_to<Value>,
+ std::allocator<Value>> {
+ using Base = typename Table::raw_hash_set;
+ using Base::Base;
+ };
+
+ std::string input[3]{"A", "B", "C"};
+
+ Table t(std::begin(input), std::end(input));
+ EXPECT_THAT(t, UnorderedElementsAre(Value{"A"}, Value{"B"}, Value{"C"}));
+
+ input[0] = "D";
+ input[1] = "E";
+ input[2] = "F";
+ t.insert(std::begin(input), std::end(input));
+ EXPECT_THAT(t, UnorderedElementsAre(Value{"A"}, Value{"B"}, Value{"C"},
+ Value{"D"}, Value{"E"}, Value{"F"}));
+}
+
TEST(Nodes, EmptyNodeType) {
using node_type = StringTable::node_type;
node_type n;
@@ -1663,9 +1743,9 @@ TEST(Nodes, EmptyNodeType) {
}
TEST(Nodes, ExtractInsert) {
- constexpr char k0[] = "Very long std::string zero.";
- constexpr char k1[] = "Very long std::string one.";
- constexpr char k2[] = "Very long std::string two.";
+ constexpr char k0[] = "Very long string zero.";
+ constexpr char k1[] = "Very long string one.";
+ constexpr char k2[] = "Very long string two.";
StringTable t = {{k0, ""}, {k1, ""}, {k2, ""}};
EXPECT_THAT(t,
UnorderedElementsAre(Pair(k0, ""), Pair(k1, ""), Pair(k2, "")));
@@ -1676,7 +1756,7 @@ TEST(Nodes, ExtractInsert) {
EXPECT_FALSE(node.empty());
StringTable t2;
- auto res = t2.insert(std::move(node));
+ StringTable::insert_return_type res = t2.insert(std::move(node));
EXPECT_TRUE(res.inserted);
EXPECT_THAT(*res.position, Pair(k0, ""));
EXPECT_FALSE(res.node);
@@ -1706,80 +1786,94 @@ TEST(Nodes, ExtractInsert) {
EXPECT_FALSE(node);
}
-StringTable MakeSimpleTable(size_t size) {
- StringTable t;
- for (size_t i = 0; i < size; ++i) t.emplace(std::string(1, 'A' + i), "");
+TEST(Nodes, HintInsert) {
+ IntTable t = {1, 2, 3};
+ auto node = t.extract(1);
+ EXPECT_THAT(t, UnorderedElementsAre(2, 3));
+ auto it = t.insert(t.begin(), std::move(node));
+ EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+ EXPECT_EQ(*it, 1);
+ EXPECT_FALSE(node);
+
+ node = t.extract(2);
+ EXPECT_THAT(t, UnorderedElementsAre(1, 3));
+ // reinsert 2 to make the next insert fail.
+ t.insert(2);
+ EXPECT_THAT(t, UnorderedElementsAre(1, 2, 3));
+ it = t.insert(t.begin(), std::move(node));
+ EXPECT_EQ(*it, 2);
+ // The node was not emptied by the insert call.
+ EXPECT_TRUE(node);
+}
+
+IntTable MakeSimpleTable(size_t size) {
+ IntTable t;
+ while (t.size() < size) t.insert(t.size());
return t;
}
-std::string OrderOfIteration(const StringTable& t) {
- std::string order;
- for (auto& p : t) order += p.first;
- return order;
+std::vector<int> OrderOfIteration(const IntTable& t) {
+ return {t.begin(), t.end()};
}
+// These IterationOrderChanges tests depend on non-deterministic behavior.
+// We are injecting non-determinism from the pointer of the table, but do so in
+// a way that only the page matters. We have to retry enough times to make sure
+// we are touching different memory pages to cause the ordering to change.
+// We also need to keep the old tables around to avoid getting the same memory
+// blocks over and over.
TEST(Table, IterationOrderChangesByInstance) {
- // Needs to be more than kWidth elements to be able to affect order.
- const StringTable reference = MakeSimpleTable(20);
-
- // Since order is non-deterministic we can't just try once and verify.
- // We'll try until we find that order changed. It should not take many tries
- // for that.
- // Important: we have to keep the old tables around. Otherwise tcmalloc will
- // just give us the same blocks and we would be doing the same order again.
- std::vector<StringTable> garbage;
- for (int i = 0; i < 10; ++i) {
- auto trial = MakeSimpleTable(20);
- if (OrderOfIteration(trial) != OrderOfIteration(reference)) {
- // We are done.
- return;
+ for (size_t size : {2, 6, 12, 20}) {
+ const auto reference_table = MakeSimpleTable(size);
+ const auto reference = OrderOfIteration(reference_table);
+
+ std::vector<IntTable> tables;
+ bool found_difference = false;
+ for (int i = 0; !found_difference && i < 5000; ++i) {
+ tables.push_back(MakeSimpleTable(size));
+ found_difference = OrderOfIteration(tables.back()) != reference;
+ }
+ if (!found_difference) {
+ FAIL()
+ << "Iteration order remained the same across many attempts with size "
+ << size;
}
- garbage.push_back(std::move(trial));
}
- FAIL();
}
TEST(Table, IterationOrderChangesOnRehash) {
- // Since order is non-deterministic we can't just try once and verify.
- // We'll try until we find that order changed. It should not take many tries
- // for that.
- // Important: we have to keep the old tables around. Otherwise tcmalloc will
- // just give us the same blocks and we would be doing the same order again.
- std::vector<StringTable> garbage;
- for (int i = 0; i < 10; ++i) {
- // Needs to be more than kWidth elements to be able to affect order.
- StringTable t = MakeSimpleTable(20);
- const std::string reference = OrderOfIteration(t);
+ std::vector<IntTable> garbage;
+ for (int i = 0; i < 5000; ++i) {
+ auto t = MakeSimpleTable(20);
+ const auto reference = OrderOfIteration(t);
// Force rehash to the same size.
t.rehash(0);
- std::string trial = OrderOfIteration(t);
+ auto trial = OrderOfIteration(t);
if (trial != reference) {
// We are done.
return;
}
garbage.push_back(std::move(t));
}
- FAIL();
+ FAIL() << "Iteration order remained the same across many attempts.";
}
-TEST(Table, IterationOrderChangesForSmallTables) {
- // Since order is non-deterministic we can't just try once and verify.
- // We'll try until we find that order changed.
- // Important: we have to keep the old tables around. Otherwise tcmalloc will
- // just give us the same blocks and we would be doing the same order again.
- StringTable reference_table = MakeSimpleTable(5);
- const std::string reference = OrderOfIteration(reference_table);
- std::vector<StringTable> garbage;
- for (int i = 0; i < 50; ++i) {
- StringTable t = MakeSimpleTable(5);
- std::string trial = OrderOfIteration(t);
- if (trial != reference) {
- // We are done.
- return;
- }
- garbage.push_back(std::move(t));
- }
- FAIL() << "Iteration order remained the same across many attempts.";
+// Verify that pointers are invalidated as soon as a second element is inserted.
+// This prevents dependency on pointer stability on small tables.
+TEST(Table, UnstablePointers) {
+ IntTable table;
+
+ const auto addr = [&](int i) {
+ return reinterpret_cast<uintptr_t>(&*table.find(i));
+ };
+
+ table.insert(0);
+ const uintptr_t old_ptr = addr(0);
+
+ // This causes a rehash.
+ table.insert(1);
+
+ EXPECT_NE(old_ptr, addr(0));
}
// Confirm that we assert if we try to erase() end().
@@ -1794,13 +1888,74 @@ TEST(TableDeathTest, EraseOfEndAsserts) {
IntTable t;
// Extra simple "regexp" as regexp support is highly varied across platforms.
- constexpr char kDeathMsg[] = "it != end";
+ constexpr char kDeathMsg[] = "Invalid operation on iterator";
EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
}
-#ifdef ADDRESS_SANITIZER
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+TEST(RawHashSamplerTest, Sample) {
+ // Enable the feature even if the prod default is off.
+ SetHashtablezEnabled(true);
+ SetHashtablezSampleParameter(100);
+
+ auto& sampler = HashtablezSampler::Global();
+ size_t start_size = 0;
+ std::unordered_set<const HashtablezInfo*> preexisting_info;
+ start_size += sampler.Iterate([&](const HashtablezInfo& info) {
+ preexisting_info.insert(&info);
+ ++start_size;
+ });
+
+ std::vector<IntTable> tables;
+ for (int i = 0; i < 1000000; ++i) {
+ tables.emplace_back();
+ tables.back().insert(1);
+ tables.back().insert(i % 5);
+ }
+ size_t end_size = 0;
+ std::unordered_map<size_t, int> observed_checksums;
+ end_size += sampler.Iterate([&](const HashtablezInfo& info) {
+ if (preexisting_info.count(&info) == 0) {
+ observed_checksums[info.hashes_bitwise_xor.load(
+ std::memory_order_relaxed)]++;
+ }
+ ++end_size;
+ });
+
+ EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
+ 0.01, 0.005);
+ EXPECT_EQ(observed_checksums.size(), 5);
+ for (const auto& [_, count] : observed_checksums) {
+ EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.2, 0.05);
+ }
+}
+#endif // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+
+TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
+ // Enable the feature even if the prod default is off.
+ SetHashtablezEnabled(true);
+ SetHashtablezSampleParameter(100);
+
+ auto& sampler = HashtablezSampler::Global();
+ size_t start_size = 0;
+ start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
+
+ std::vector<CustomAllocIntTable> tables;
+ for (int i = 0; i < 1000000; ++i) {
+ tables.emplace_back();
+ tables.back().insert(1);
+ }
+ size_t end_size = 0;
+ end_size += sampler.Iterate([&](const HashtablezInfo&) { ++end_size; });
+
+ EXPECT_NEAR((end_size - start_size) / static_cast<double>(tables.size()),
+ 0.00, 0.001);
+}
+
+#ifdef ABSL_HAVE_ADDRESS_SANITIZER
TEST(Sanitizer, PoisoningUnused) {
IntTable t;
+ t.reserve(5);
// Insert something to force an allocation.
int64_t& v1 = *t.insert(0).first;
@@ -1821,8 +1976,9 @@ TEST(Sanitizer, PoisoningOnErase) {
t.erase(0);
EXPECT_TRUE(__asan_address_is_poisoned(&v));
}
-#endif // ADDRESS_SANITIZER
+#endif // ABSL_HAVE_ADDRESS_SANITIZER
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.cc
index b18e0bb7a1e..f9947f0475d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/container/internal/test_instance_tracker.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace test_internal {
int BaseCountedInstance::num_instances_ = 0;
int BaseCountedInstance::num_live_instances_ = 0;
@@ -24,4 +25,5 @@ int BaseCountedInstance::num_swaps_ = 0;
int BaseCountedInstance::num_comparisons_ = 0;
} // namespace test_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.h
index ec45f574037..5ff6fd714e2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,10 +18,13 @@
#include <cstdlib>
#include <ostream>
+#include "absl/types/compare.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace test_internal {
-// A type that counts number of occurences of the type, the live occurrences of
+// 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
@@ -96,6 +99,14 @@ class BaseCountedInstance {
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_;
@@ -257,6 +268,7 @@ class MovableOnlyInstance : public BaseCountedInstance {
};
} // namespace test_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_TEST_INSTANCE_TRACKER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker_test.cc
index 0ae57636df2..1c6a4fa7150 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/test_instance_tracker_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -174,6 +174,8 @@ TEST(TestInstanceTracker, Comparisons) {
EXPECT_EQ(5, tracker.comparisons());
EXPECT_FALSE(one >= two);
EXPECT_EQ(6, tracker.comparisons());
+ EXPECT_TRUE(one.compare(two) < 0); // NOLINT
+ EXPECT_EQ(7, tracker.comparisons());
tracker.ResetCopiesMovesSwaps();
EXPECT_EQ(0, tracker.comparisons());
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/tracked.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/tracked.h
index 7d14af03138..29f5829f719 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/tracked.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/tracked.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,10 +16,14 @@
#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.
@@ -73,6 +77,7 @@ class Tracked {
};
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_TRACKED_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
index 87d6c3c33ff..3f90ad7ca88 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,6 +16,7 @@
#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
#include <algorithm>
+#include <unordered_map>
#include <vector>
#include "gmock/gmock.h"
@@ -24,12 +25,13 @@
#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_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
TYPED_TEST_P(ConstructorTest, NoArgs) {
TypeParam m;
@@ -83,8 +85,28 @@ TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {
EXPECT_GE(m.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+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);
@@ -92,11 +114,17 @@ TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
EXPECT_TRUE(m.empty());
EXPECT_THAT(m, ::testing::UnorderedElementsAre());
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+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;
@@ -107,18 +135,38 @@ TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
EXPECT_TRUE(m.empty());
EXPECT_THAT(m, ::testing::UnorderedElementsAre());
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+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());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+ AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -140,8 +188,11 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
EXPECT_GE(m.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+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);
@@ -152,11 +203,17 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+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;
@@ -170,7 +227,10 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+ InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
}
TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -190,8 +250,11 @@ TYPED_TEST_P(ConstructorTest, CopyConstructor) {
EXPECT_EQ(m, n);
}
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+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;
@@ -206,7 +269,10 @@ TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
EXPECT_EQ(m.key_eq(), n.key_eq());
EXPECT_NE(m.get_allocator(), n.get_allocator());
EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+ CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
// TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -229,8 +295,11 @@ TYPED_TEST_P(ConstructorTest, MoveConstructor) {
EXPECT_EQ(m, n);
}
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+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;
@@ -246,7 +315,10 @@ TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
EXPECT_EQ(m.key_eq(), n.key_eq());
EXPECT_NE(m.get_allocator(), n.get_allocator());
EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+ MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
// TODO(alkis): Test non-propagating allocators on move constructors.
@@ -269,8 +341,11 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {
EXPECT_GE(m.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+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;
@@ -280,11 +355,17 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_MAP_CXX14) || defined(UNORDERED_MAP_CXX17)
+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;
@@ -297,7 +378,10 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
+ InitializerListBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
}
TYPED_TEST_P(ConstructorTest, Assignment) {
@@ -390,16 +474,17 @@ TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {
REGISTER_TYPED_TEST_CASE_P(
ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
- BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
- BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+ BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+ InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
- MoveAssignment, AssignmentFromInitializerList,
- AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h
index a3d2159587a..e76421e508f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_lookup_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,12 +21,13 @@
#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_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
TYPED_TEST_P(LookupTest, At) {
using T = hash_internal::GeneratedType<TypeParam>;
@@ -110,6 +111,7 @@ REGISTER_TYPED_TEST_CASE_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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_members_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_members_test.h
new file mode 100644
index 00000000000..7d48cdb890b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
index 61ae7d630b5..8c9ca779a42 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,18 +15,21 @@
#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_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
TYPED_TEST_P(ModifiersTest, Clear) {
using T = hash_internal::GeneratedType<TypeParam>;
@@ -267,7 +270,49 @@ REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_test.cc
index 40e799cda89..9cbf512f32b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_map_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,13 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include <memory>
#include <unordered_map>
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
@@ -29,10 +32,19 @@ using MapTypes = ::testing::Types<
StatefulTestingEqual,
Alloc<std::pair<const std::string, std::string>>>>;
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, ModifiersTest, MapTypes);
+
+using UniquePtrMapTypes = ::testing::Types<std::unordered_map<
+ int, std::unique_ptr<int>, StatefulTestingHash, StatefulTestingEqual,
+ Alloc<std::pair<const int, std::unique_ptr<int>>>>>;
+
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedMap, UniquePtrModifiersTest,
+ UniquePtrMapTypes);
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h
index 9516e5ba580..41165b05e97 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_constructor_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,20 +16,23 @@
#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_CASE_P(ConstructorTest);
+TYPED_TEST_SUITE_P(ConstructorTest);
TYPED_TEST_P(ConstructorTest, NoArgs) {
TypeParam m;
@@ -91,8 +94,28 @@ TYPED_TEST_P(ConstructorTest, BucketCountHashEqualAlloc) {
EXPECT_GE(cm.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
+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);
@@ -100,11 +123,17 @@ TYPED_TEST_P(ConstructorTest, BucketCountAlloc) {
EXPECT_TRUE(m.empty());
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+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;
@@ -115,18 +144,38 @@ TYPED_TEST_P(ConstructorTest, BucketCountHashAlloc) {
EXPECT_TRUE(m.empty());
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAre());
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, BucketAlloc) {
+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());
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, Alloc) {
+ AllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
@@ -148,8 +197,11 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
EXPECT_GE(m.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+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);
@@ -160,11 +212,17 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+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;
@@ -178,7 +236,10 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashAlloc) {
+ InputIteratorBucketHashAllocTest<TypeParam>(expect_cxx14_apis<TypeParam>());
}
TYPED_TEST_P(ConstructorTest, CopyConstructor) {
@@ -196,10 +257,14 @@ TYPED_TEST_P(ConstructorTest, CopyConstructor) {
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);
}
-TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+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;
@@ -214,7 +279,10 @@ TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
EXPECT_EQ(m.key_eq(), n.key_eq());
EXPECT_NE(m.get_allocator(), n.get_allocator());
EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, CopyConstructorAlloc) {
+ CopyConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
// TODO(alkis): Test non-propagating allocators on copy constructors.
@@ -237,8 +305,11 @@ TYPED_TEST_P(ConstructorTest, MoveConstructor) {
EXPECT_EQ(m, n);
}
-TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
-#if ABSL_UNORDERED_SUPPORTS_ALLOC_CTORS
+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;
@@ -254,7 +325,10 @@ TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
EXPECT_EQ(m.key_eq(), n.key_eq());
EXPECT_NE(m.get_allocator(), n.get_allocator());
EXPECT_EQ(m, n);
-#endif
+}
+
+TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
+ MoveConstructorAllocTest<TypeParam>(expect_alloc_constructors<TypeParam>());
}
// TODO(alkis): Test non-propagating allocators on move constructors.
@@ -277,8 +351,11 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {
EXPECT_GE(m.bucket_count(), 123);
}
-TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+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;
@@ -288,11 +365,17 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
-#if defined(UNORDERED_SET_CXX14) || defined(UNORDERED_SET_CXX17)
+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;
@@ -305,10 +388,13 @@ TYPED_TEST_P(ConstructorTest, InitializerListBucketHashAlloc) {
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
EXPECT_GE(m.bucket_count(), 123);
-#endif
}
-TYPED_TEST_P(ConstructorTest, Assignment) {
+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;
@@ -394,16 +480,17 @@ TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {
REGISTER_TYPED_TEST_CASE_P(
ConstructorTest, NoArgs, BucketCount, BucketCountHash, BucketCountHashEqual,
- BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc,
- BucketAlloc, InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
+ BucketCountHashEqualAlloc, BucketCountAlloc, BucketCountHashAlloc, Alloc,
+ InputIteratorBucketHashEqualAlloc, InputIteratorBucketAlloc,
InputIteratorBucketHashAlloc, CopyConstructor, CopyConstructorAlloc,
MoveConstructor, MoveConstructorAlloc, InitializerListBucketHashEqualAlloc,
- InitializerListBucketAlloc, InitializerListBucketHashAlloc, Assignment,
- MoveAssignment, AssignmentFromInitializerList,
- AssignmentOverwritesExisting, MoveAssignmentOverwritesExisting,
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h
index 1421e7b6ffb..8f2f4b207ef 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_lookup_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,12 +21,13 @@
#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_CASE_P(LookupTest);
+TYPED_TEST_SUITE_P(LookupTest);
TYPED_TEST_P(LookupTest, Count) {
using T = hash_internal::GeneratedType<TypeParam>;
@@ -84,6 +85,7 @@ TYPED_TEST_P(LookupTest, EqualRange) {
REGISTER_TYPED_TEST_CASE_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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_members_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_members_test.h
new file mode 100644
index 00000000000..4c5e104af29
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
index 445dcec48fa..26be58d99f2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,12 +21,13 @@
#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_CASE_P(ModifiersTest);
+TYPED_TEST_SUITE_P(ModifiersTest);
TYPED_TEST_P(ModifiersTest, Clear) {
using T = hash_internal::GeneratedType<TypeParam>;
@@ -183,6 +184,7 @@ REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
EraseKey, Swap);
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_INTERNAL_UNORDERED_SET_MODIFIERS_TEST_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_test.cc
index 1281ce53d5e..a134b53984b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/internal/unordered_set_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,22 +16,26 @@
#include "absl/container/internal/unordered_set_constructor_test.h"
#include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
#include "absl/container/internal/unordered_set_modifiers_test.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
-using SetTypes =
- ::testing::Types<std::unordered_set<int, StatefulTestingHash,
- StatefulTestingEqual, Alloc<int>>,
- std::unordered_set<std::string, StatefulTestingHash,
- StatefulTestingEqual, Alloc<std::string>>>;
+using SetTypes = ::testing::Types<
+ std::unordered_set<int, StatefulTestingHash, StatefulTestingEqual,
+ Alloc<int>>,
+ std::unordered_set<std::string, StatefulTestingHash, StatefulTestingEqual,
+ Alloc<std::string>>>;
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(UnorderedSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(UnorderedSet, ModifiersTest, SetTypes);
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map.h
index bd53c590419..7a39f6284cf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -48,6 +48,7 @@
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <class Key, class Value>
class NodeHashMapPolicy;
@@ -224,7 +225,8 @@ class node_hash_map
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists.
+ // 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()
@@ -351,6 +353,10 @@ class node_hash_map
// 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()
@@ -369,6 +375,11 @@ class node_hash_map
// 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()
@@ -509,14 +520,17 @@ class node_hash_map
//
// Returns the function used for comparing keys equality.
using Base::key_eq;
-
- ABSL_DEPRECATED("Call `hash_function()` instead.")
- typename Base::hasher hash_funct() { return this->hash_function(); }
-
- ABSL_DEPRECATED("Call `rehash()` instead.")
- void resize(typename Base::size_type hint) { this->rehash(hint); }
};
+// erase_if(node_hash_map<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename K, typename V, typename H, typename E, typename A,
+ typename Predicate>
+void erase_if(node_hash_map<K, V, H, E, A>& c, Predicate pred) {
+ container_internal::EraseIf(pred, &c);
+}
+
namespace container_internal {
template <class Key, class Value>
@@ -577,6 +591,7 @@ struct IsUnorderedContainer<
} // namespace container_algorithm_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_CONTAINER_NODE_HASH_MAP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map_test.cc
index bd789644c24..8f59a1e4a21 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_map_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,13 +17,16 @@
#include "absl/container/internal/tracked.h"
#include "absl/container/internal/unordered_map_constructor_test.h"
#include "absl/container/internal/unordered_map_lookup_test.h"
+#include "absl/container/internal/unordered_map_members_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
using ::testing::Field;
+using ::testing::IsEmpty;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
@@ -34,9 +37,10 @@ using MapTypes = ::testing::Types<
StatefulTestingEqual,
Alloc<std::pair<const std::string, std::string>>>>;
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ConstructorTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, LookupTest, MapTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashMap, ModifiersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ConstructorTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, LookupTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, MembersTest, MapTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashMap, ModifiersTest, MapTypes);
using M = absl::node_hash_map<std::string, Tracked<int>>;
@@ -213,6 +217,59 @@ TEST(NodeHashMap, MergeExtractInsert) {
EXPECT_THAT(set2, UnorderedElementsAre(Elem(7, -70), Elem(17, 23)));
}
+bool FirstIsEven(std::pair<const int, int> p) { return p.first % 2 == 0; }
+
+TEST(NodeHashMap, EraseIf) {
+ // Erase all elements.
+ {
+ node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, [](std::pair<const int, int>) { return true; });
+ EXPECT_THAT(s, IsEmpty());
+ }
+ // Erase no elements.
+ {
+ node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, [](std::pair<const int, int>) { return false; });
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
+ Pair(4, 4), Pair(5, 5)));
+ }
+ // Erase specific elements.
+ {
+ node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s,
+ [](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; });
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
+ }
+ // Predicate is function reference.
+ {
+ node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, FirstIsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+ }
+ // Predicate is function pointer.
+ {
+ node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
+ erase_if(s, &FirstIsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
+ }
+}
+
+// This test requires std::launder for mutable key access in node handles.
+#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606
+TEST(NodeHashMap, NodeHandleMutableKeyAccess) {
+ node_hash_map<std::string, std::string> map;
+
+ map["key1"] = "mapped";
+
+ auto nh = map.extract(map.begin());
+ nh.key().resize(3);
+ map.insert(std::move(nh));
+
+ EXPECT_THAT(map, testing::ElementsAre(Pair("key", "mapped")));
+}
+#endif
+
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set.h
index 843b11aa58a..93b15f4681a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,7 +18,7 @@
//
// 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 map elements can be done
+// `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
@@ -44,6 +44,7 @@
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
template <typename T>
struct NodeHashSetPolicy;
@@ -59,7 +60,7 @@ struct NodeHashSetPolicy;
// following notable differences:
//
// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
-// `insert()`, provided that the map is provided a compatible heterogeneous
+// `insert()`, provided that the set is provided a compatible heterogeneous
// hashing function and equality operator.
// * Contains a `capacity()` member function indicating the number of element
// slots (open, deleted, and empty) within the hash set.
@@ -75,13 +76,13 @@ struct NodeHashSetPolicy;
// Example:
//
// // Create a node hash set of three strings
-// absl::node_hash_map<std::string, std::string> ducks =
-// {"huey", "dewey"}, "louie"};
+// absl::node_hash_set<std::string> ducks =
+// {"huey", "dewey", "louie"};
//
-// // Insert a new element into the node hash map
-// ducks.insert("donald"};
+// // Insert a new element into the node hash set
+// ducks.insert("donald");
//
-// // Force a rehash of the node hash map
+// // Force a rehash of the node hash set
// ducks.rehash(0);
//
// // See if "dewey" is present
@@ -99,7 +100,7 @@ class node_hash_set
public:
// Constructors and Assignment Operators
//
- // A node_hash_set supports the same overload set as `std::unordered_map`
+ // A node_hash_set supports the same overload set as `std::unordered_set`
// for construction and assignment:
//
// * Default constructor
@@ -110,7 +111,7 @@ class node_hash_set
// * Initializer List constructor
//
// absl::node_hash_set<std::string> set2 =
- // {{"huey"}, {"dewey"}, {"louie"},};
+ // {{"huey"}, {"dewey"}, {"louie"}};
//
// * Copy constructor
//
@@ -166,7 +167,7 @@ class node_hash_set
// 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_map` API.
+ // not provided in the `std::unordered_set` API.
using Base::capacity;
// node_hash_set::empty()
@@ -207,7 +208,7 @@ class node_hash_set
// `void`.
//
// NOTE: this return behavior is different than that of STL containers in
- // general and `std::unordered_map` in particular.
+ // general and `std::unordered_set` in particular.
//
// iterator erase(const_iterator first, const_iterator last):
//
@@ -216,7 +217,8 @@ class node_hash_set
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists.
+ // 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()
@@ -312,7 +314,7 @@ class node_hash_set
// node_hash_set::merge()
//
- // Extracts elements from a given `source` flat hash map into this
+ // 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;
@@ -320,15 +322,15 @@ class node_hash_set
// node_hash_set::swap(node_hash_set& other)
//
// Exchanges the contents of this `node_hash_set` with those of the `other`
- // flat hash map, avoiding invocation of any move, copy, or swap operations on
+ // 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 flat hash set's hashing and key equivalence
+ // `swap()` requires that the node hash set's hashing and key equivalence
// functions be Swappable, and are exchaged using unqualified calls to
- // non-member `swap()`. If the map's allocator has
+ // 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.
@@ -383,14 +385,14 @@ class node_hash_set
// node_hash_set::bucket_count()
//
// Returns the number of "buckets" within the `node_hash_set`. Note that
- // because a flat hash map contains all elements within its internal storage,
+ // 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 map).
+ // of slots occupied with a value within the hash set).
using Base::load_factor;
// node_hash_set::max_load_factor()
@@ -426,14 +428,16 @@ class node_hash_set
//
// Returns the function used for comparing keys equality.
using Base::key_eq;
-
- ABSL_DEPRECATED("Call `hash_function()` instead.")
- typename Base::hasher hash_funct() { return this->hash_function(); }
-
- ABSL_DEPRECATED("Call `rehash()` instead.")
- void resize(typename Base::size_type hint) { this->rehash(hint); }
};
+// erase_if(node_hash_set<>, Pred)
+//
+// Erases all elements that satisfy the predicate `pred` from the container `c`.
+template <typename T, typename H, typename E, typename A, typename Predicate>
+void erase_if(node_hash_set<T, H, E, A>& c, Predicate pred) {
+ container_internal::EraseIf(pred, &c);
+}
+
namespace container_internal {
template <class T>
@@ -483,6 +487,7 @@ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set_test.cc
index 7e498f0f779..7ddad2021d2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/container/node_hash_set_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,27 +16,31 @@
#include "absl/container/internal/unordered_set_constructor_test.h"
#include "absl/container/internal/unordered_set_lookup_test.h"
+#include "absl/container/internal/unordered_set_members_test.h"
#include "absl/container/internal/unordered_set_modifiers_test.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace container_internal {
namespace {
using ::absl::container_internal::hash_internal::Enum;
using ::absl::container_internal::hash_internal::EnumClass;
+using ::testing::IsEmpty;
using ::testing::Pointee;
using ::testing::UnorderedElementsAre;
using SetTypes = ::testing::Types<
node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>,
node_hash_set<std::string, StatefulTestingHash, StatefulTestingEqual,
- Alloc<int>>,
+ Alloc<std::string>>,
node_hash_set<Enum, StatefulTestingHash, StatefulTestingEqual, Alloc<Enum>>,
node_hash_set<EnumClass, StatefulTestingHash, StatefulTestingEqual,
Alloc<EnumClass>>>;
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ConstructorTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, LookupTest, SetTypes);
-INSTANTIATE_TYPED_TEST_CASE_P(NodeHashSet, ModifiersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ConstructorTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, LookupTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, MembersTest, SetTypes);
+INSTANTIATE_TYPED_TEST_SUITE_P(NodeHashSet, ModifiersTest, SetTypes);
TEST(NodeHashSet, MoveableNotCopyableCompiles) {
node_hash_set<std::unique_ptr<void*>> t;
@@ -98,6 +102,42 @@ TEST(NodeHashSet, MergeExtractInsert) {
EXPECT_THAT(set2, UnorderedElementsAre(Pointee(7), Pointee(23)));
}
+bool IsEven(int k) { return k % 2 == 0; }
+
+TEST(NodeHashSet, EraseIf) {
+ // Erase all elements.
+ {
+ node_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int) { return true; });
+ EXPECT_THAT(s, IsEmpty());
+ }
+ // Erase no elements.
+ {
+ node_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int) { return false; });
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+ }
+ // Erase specific elements.
+ {
+ node_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, [](int k) { return k % 2 == 1; });
+ EXPECT_THAT(s, UnorderedElementsAre(2, 4));
+ }
+ // Predicate is function reference.
+ {
+ node_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, IsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+ }
+ // Predicate is function pointer.
+ {
+ node_hash_set<int> s = {1, 2, 3, 4, 5};
+ erase_if(s, &IsEven);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
+ }
+}
+
} // namespace
} // namespace container_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
index 6fde7754d10..942ce90a4d6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
@@ -1,34 +1,65 @@
# See absl/copts/copts.py and absl/copts/generate_copts.py
include(GENERATED_AbseilCopts)
-if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- set(ABSL_DEFAULT_COPTS "${GCC_FLAGS}")
- set(ABSL_TEST_COPTS "${GCC_FLAGS};${GCC_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "${GCC_EXCEPTIONS_FLAGS}")
-elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
- # MATCHES so we get both Clang and AppleClang
- set(ABSL_DEFAULT_COPTS "${LLVM_FLAGS}")
- set(ABSL_TEST_COPTS "${LLVM_FLAGS};${LLVM_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "${LLVM_EXCEPTIONS_FLAGS}")
-elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- set(ABSL_DEFAULT_COPTS "${MSVC_FLAGS}")
- set(ABSL_TEST_COPTS "${MSVC_FLAGS};${MSVC_TEST_FLAGS}")
- set(ABSL_EXCEPTIONS_FLAG "${MSVC_EXCEPTIONS_FLAGS}")
+set(ABSL_LSAN_LINKOPTS "")
+set(ABSL_HAVE_LSAN OFF)
+set(ABSL_DEFAULT_LINKOPTS "")
+
+if (BUILD_SHARED_LIBS AND MSVC)
+ set(ABSL_BUILD_DLL TRUE)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+else()
+ set(ABSL_BUILD_DLL FALSE)
+endif()
+
+if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
+ if (MSVC)
+ set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_MSVC_X64_FLAGS}")
+ else()
+ set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}")
+ endif()
+elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm.*|aarch64")
+ if (CMAKE_SIZEOF_VOID_P STREQUAL "8")
+ set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM64_FLAGS}")
+ elseif(CMAKE_SIZEOF_VOID_P STREQUAL "4")
+ set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM32_FLAGS}")
+ else()
+ message(WARNING "Value of CMAKE_SIZEOF_VOID_P (${CMAKE_SIZEOF_VOID_P}) is not supported.")
+ endif()
+else()
+ message(WARNING "Value of CMAKE_SYSTEM_PROCESSOR (${CMAKE_SYSTEM_PROCESSOR}) is unknown and cannot be used to set ABSL_RANDOM_RANDEN_COPTS")
+ set(ABSL_RANDOM_RANDEN_COPTS "")
+endif()
+
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ set(ABSL_DEFAULT_COPTS "${ABSL_GCC_FLAGS}")
+ set(ABSL_TEST_COPTS "${ABSL_GCC_FLAGS};${ABSL_GCC_TEST_FLAGS}")
+elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # MATCHES so we get both Clang and AppleClang
+ if(MSVC)
+ # clang-cl is half MSVC, half LLVM
+ set(ABSL_DEFAULT_COPTS "${ABSL_CLANG_CL_FLAGS}")
+ set(ABSL_TEST_COPTS "${ABSL_CLANG_CL_FLAGS};${ABSL_CLANG_CL_TEST_FLAGS}")
+ else()
+ set(ABSL_DEFAULT_COPTS "${ABSL_LLVM_FLAGS}")
+ set(ABSL_TEST_COPTS "${ABSL_LLVM_FLAGS};${ABSL_LLVM_TEST_FLAGS}")
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+ # AppleClang doesn't have lsan
+ # https://developer.apple.com/documentation/code_diagnostics
+ if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.5)
+ set(ABSL_LSAN_LINKOPTS "-fsanitize=leak")
+ set(ABSL_HAVE_LSAN ON)
+ endif()
+ endif()
+ endif()
+elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+ set(ABSL_DEFAULT_COPTS "${ABSL_MSVC_FLAGS}")
+ set(ABSL_TEST_COPTS "${ABSL_MSVC_FLAGS};${ABSL_MSVC_TEST_FLAGS}")
+ set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}")
else()
message(WARNING "Unknown compiler: ${CMAKE_CXX_COMPILER}. Building with no default flags")
set(ABSL_DEFAULT_COPTS "")
set(ABSL_TEST_COPTS "")
- set(ABSL_EXCEPTIONS_FLAG "")
endif()
-# This flag is used internally for Bazel builds and is kept here for consistency
-set(ABSL_EXCEPTIONS_FLAG_LINKOPTS "")
-
-if("${CMAKE_CXX_STANDARD}" EQUAL 98)
- message(FATAL_ERROR "Abseil requires at least C++11")
-elseif(NOT "${CMAKE_CXX_STANDARD}")
- message(STATUS "No CMAKE_CXX_STANDARD set, assuming 11")
- set(ABSL_CXX_STANDARD 11)
-else()
- set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
-endif() \ No newline at end of file
+set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
index 80c98193076..51742c9b6b3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
@@ -3,28 +3,56 @@
# (1) Edit absl/copts/copts.py.
# (2) Run `python <path_to_absl>/copts/generate_copts.py`.
-list(APPEND GCC_EXCEPTIONS_FLAGS
- "-fexceptions"
+list(APPEND ABSL_CLANG_CL_FLAGS
+ "/W3"
+ "/DNOMINMAX"
+ "/DWIN32_LEAN_AND_MEAN"
+ "/D_CRT_SECURE_NO_WARNINGS"
+ "/D_SCL_SECURE_NO_WARNINGS"
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+)
+
+list(APPEND ABSL_CLANG_CL_TEST_FLAGS
+ "-Wno-c99-extensions"
+ "-Wno-deprecated-declarations"
+ "-Wno-missing-noreturn"
+ "-Wno-missing-prototypes"
+ "-Wno-missing-variable-declarations"
+ "-Wno-null-conversion"
+ "-Wno-shadow"
+ "-Wno-shift-sign-overflow"
+ "-Wno-sign-compare"
+ "-Wno-unused-function"
+ "-Wno-unused-member-function"
+ "-Wno-unused-parameter"
+ "-Wno-unused-private-field"
+ "-Wno-unused-template"
+ "-Wno-used-but-marked-unused"
+ "-Wno-zero-as-null-pointer-constant"
+ "-Wno-gnu-zero-variadic-macro-arguments"
)
-list(APPEND GCC_FLAGS
+list(APPEND ABSL_GCC_FLAGS
"-Wall"
"-Wextra"
"-Wcast-qual"
"-Wconversion-null"
+ "-Wformat-security"
"-Wmissing-declarations"
"-Woverlength-strings"
"-Wpointer-arith"
+ "-Wundef"
"-Wunused-local-typedefs"
"-Wunused-result"
"-Wvarargs"
"-Wvla"
"-Wwrite-strings"
- "-Wno-sign-compare"
+ "-DNOMINMAX"
)
-list(APPEND GCC_TEST_FLAGS
+list(APPEND ABSL_GCC_TEST_FLAGS
"-Wno-conversion-null"
+ "-Wno-deprecated-declarations"
"-Wno-missing-declarations"
"-Wno-sign-compare"
"-Wno-unused-function"
@@ -32,60 +60,45 @@ list(APPEND GCC_TEST_FLAGS
"-Wno-unused-private-field"
)
-list(APPEND LLVM_EXCEPTIONS_FLAGS
- "-fexceptions"
-)
-
-list(APPEND LLVM_FLAGS
+list(APPEND ABSL_LLVM_FLAGS
"-Wall"
"-Wextra"
- "-Weverything"
- "-Wno-c++98-compat-pedantic"
- "-Wno-conversion"
- "-Wno-covered-switch-default"
- "-Wno-deprecated"
- "-Wno-disabled-macro-expansion"
- "-Wno-double-promotion"
- "-Wno-comma"
- "-Wno-extra-semi"
- "-Wno-extra-semi-stmt"
- "-Wno-packed"
- "-Wno-padded"
- "-Wno-sign-compare"
+ "-Wcast-qual"
+ "-Wconversion"
+ "-Wfloat-overflow-conversion"
+ "-Wfloat-zero-conversion"
+ "-Wfor-loop-analysis"
+ "-Wformat-security"
+ "-Wgnu-redeclared-enum"
+ "-Winfinite-recursion"
+ "-Wliteral-conversion"
+ "-Wmissing-declarations"
+ "-Woverlength-strings"
+ "-Wpointer-arith"
+ "-Wself-assign"
+ "-Wshadow"
+ "-Wstring-conversion"
+ "-Wtautological-overlap-compare"
+ "-Wundef"
+ "-Wuninitialized"
+ "-Wunreachable-code"
+ "-Wunused-comparison"
+ "-Wunused-local-typedefs"
+ "-Wunused-result"
+ "-Wvla"
+ "-Wwrite-strings"
"-Wno-float-conversion"
- "-Wno-float-equal"
- "-Wno-format-nonliteral"
- "-Wno-gcc-compat"
- "-Wno-global-constructors"
- "-Wno-exit-time-destructors"
- "-Wno-nested-anon-types"
- "-Wno-non-modular-include-in-module"
- "-Wno-old-style-cast"
- "-Wno-range-loop-analysis"
- "-Wno-reserved-id-macro"
+ "-Wno-implicit-float-conversion"
+ "-Wno-implicit-int-float-conversion"
+ "-Wno-implicit-int-conversion"
"-Wno-shorten-64-to-32"
- "-Wno-switch-enum"
- "-Wno-thread-safety-negative"
- "-Wno-undef"
- "-Wno-unknown-warning-option"
- "-Wno-unreachable-code"
- "-Wno-unused-macros"
- "-Wno-weak-vtables"
- "-Wbitfield-enum-conversion"
- "-Wbool-conversion"
- "-Wconstant-conversion"
- "-Wenum-conversion"
- "-Wint-conversion"
- "-Wliteral-conversion"
- "-Wnon-literal-null-conversion"
- "-Wnull-conversion"
- "-Wobjc-literal-conversion"
"-Wno-sign-conversion"
- "-Wstring-conversion"
+ "-DNOMINMAX"
)
-list(APPEND LLVM_TEST_FLAGS
+list(APPEND ABSL_LLVM_TEST_FLAGS
"-Wno-c99-extensions"
+ "-Wno-deprecated-declarations"
"-Wno-missing-noreturn"
"-Wno-missing-prototypes"
"-Wno-missing-variable-declarations"
@@ -103,29 +116,47 @@ list(APPEND LLVM_TEST_FLAGS
"-Wno-gnu-zero-variadic-macro-arguments"
)
-list(APPEND MSVC_EXCEPTIONS_FLAGS
- "/U_HAS_EXCEPTIONS"
- "/D_HAS_EXCEPTIONS=1"
- "/EHsc"
-)
-
-list(APPEND MSVC_FLAGS
+list(APPEND ABSL_MSVC_FLAGS
"/W3"
+ "/DNOMINMAX"
+ "/DWIN32_LEAN_AND_MEAN"
+ "/D_CRT_SECURE_NO_WARNINGS"
+ "/D_SCL_SECURE_NO_WARNINGS"
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
+ "/bigobj"
"/wd4005"
"/wd4068"
"/wd4180"
"/wd4244"
"/wd4267"
+ "/wd4503"
"/wd4800"
- "/DNOMINMAX"
- "/DWIN32_LEAN_AND_MEAN"
- "/D_CRT_SECURE_NO_WARNINGS"
- "/D_SCL_SECURE_NO_WARNINGS"
- "/D_ENABLE_EXTENDED_ALIGNED_STORAGE"
)
-list(APPEND MSVC_TEST_FLAGS
+list(APPEND ABSL_MSVC_LINKOPTS
+ "-ignore:4221"
+)
+
+list(APPEND ABSL_MSVC_TEST_FLAGS
"/wd4018"
"/wd4101"
"/wd4503"
+ "/wd4996"
+ "/DNOMINMAX"
+)
+
+list(APPEND ABSL_RANDOM_HWAES_ARM32_FLAGS
+ "-mfpu=neon"
+)
+
+list(APPEND ABSL_RANDOM_HWAES_ARM64_FLAGS
+ "-march=armv8-a+crypto"
+)
+
+list(APPEND ABSL_RANDOM_HWAES_MSVC_X64_FLAGS
+)
+
+list(APPEND ABSL_RANDOM_HWAES_X64_FLAGS
+ "-maes"
+ "-msse4.1"
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_copts.bzl b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_copts.bzl
index a001347d490..6707488f23d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_copts.bzl
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/GENERATED_copts.bzl
@@ -4,28 +4,56 @@
(2) Run `python <path_to_absl>/copts/generate_copts.py`.
"""
-GCC_EXCEPTIONS_FLAGS = [
- "-fexceptions",
+ABSL_CLANG_CL_FLAGS = [
+ "/W3",
+ "/DNOMINMAX",
+ "/DWIN32_LEAN_AND_MEAN",
+ "/D_CRT_SECURE_NO_WARNINGS",
+ "/D_SCL_SECURE_NO_WARNINGS",
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
+ABSL_CLANG_CL_TEST_FLAGS = [
+ "-Wno-c99-extensions",
+ "-Wno-deprecated-declarations",
+ "-Wno-missing-noreturn",
+ "-Wno-missing-prototypes",
+ "-Wno-missing-variable-declarations",
+ "-Wno-null-conversion",
+ "-Wno-shadow",
+ "-Wno-shift-sign-overflow",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-member-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-template",
+ "-Wno-used-but-marked-unused",
+ "-Wno-zero-as-null-pointer-constant",
+ "-Wno-gnu-zero-variadic-macro-arguments",
]
-GCC_FLAGS = [
+ABSL_GCC_FLAGS = [
"-Wall",
"-Wextra",
"-Wcast-qual",
"-Wconversion-null",
+ "-Wformat-security",
"-Wmissing-declarations",
"-Woverlength-strings",
"-Wpointer-arith",
+ "-Wundef",
"-Wunused-local-typedefs",
"-Wunused-result",
"-Wvarargs",
"-Wvla",
"-Wwrite-strings",
- "-Wno-sign-compare",
+ "-DNOMINMAX",
]
-GCC_TEST_FLAGS = [
+ABSL_GCC_TEST_FLAGS = [
"-Wno-conversion-null",
+ "-Wno-deprecated-declarations",
"-Wno-missing-declarations",
"-Wno-sign-compare",
"-Wno-unused-function",
@@ -33,60 +61,45 @@ GCC_TEST_FLAGS = [
"-Wno-unused-private-field",
]
-LLVM_EXCEPTIONS_FLAGS = [
- "-fexceptions",
-]
-
-LLVM_FLAGS = [
+ABSL_LLVM_FLAGS = [
"-Wall",
"-Wextra",
- "-Weverything",
- "-Wno-c++98-compat-pedantic",
- "-Wno-conversion",
- "-Wno-covered-switch-default",
- "-Wno-deprecated",
- "-Wno-disabled-macro-expansion",
- "-Wno-double-promotion",
- "-Wno-comma",
- "-Wno-extra-semi",
- "-Wno-extra-semi-stmt",
- "-Wno-packed",
- "-Wno-padded",
- "-Wno-sign-compare",
+ "-Wcast-qual",
+ "-Wconversion",
+ "-Wfloat-overflow-conversion",
+ "-Wfloat-zero-conversion",
+ "-Wfor-loop-analysis",
+ "-Wformat-security",
+ "-Wgnu-redeclared-enum",
+ "-Winfinite-recursion",
+ "-Wliteral-conversion",
+ "-Wmissing-declarations",
+ "-Woverlength-strings",
+ "-Wpointer-arith",
+ "-Wself-assign",
+ "-Wshadow",
+ "-Wstring-conversion",
+ "-Wtautological-overlap-compare",
+ "-Wundef",
+ "-Wuninitialized",
+ "-Wunreachable-code",
+ "-Wunused-comparison",
+ "-Wunused-local-typedefs",
+ "-Wunused-result",
+ "-Wvla",
+ "-Wwrite-strings",
"-Wno-float-conversion",
- "-Wno-float-equal",
- "-Wno-format-nonliteral",
- "-Wno-gcc-compat",
- "-Wno-global-constructors",
- "-Wno-exit-time-destructors",
- "-Wno-nested-anon-types",
- "-Wno-non-modular-include-in-module",
- "-Wno-old-style-cast",
- "-Wno-range-loop-analysis",
- "-Wno-reserved-id-macro",
+ "-Wno-implicit-float-conversion",
+ "-Wno-implicit-int-float-conversion",
+ "-Wno-implicit-int-conversion",
"-Wno-shorten-64-to-32",
- "-Wno-switch-enum",
- "-Wno-thread-safety-negative",
- "-Wno-undef",
- "-Wno-unknown-warning-option",
- "-Wno-unreachable-code",
- "-Wno-unused-macros",
- "-Wno-weak-vtables",
- "-Wbitfield-enum-conversion",
- "-Wbool-conversion",
- "-Wconstant-conversion",
- "-Wenum-conversion",
- "-Wint-conversion",
- "-Wliteral-conversion",
- "-Wnon-literal-null-conversion",
- "-Wnull-conversion",
- "-Wobjc-literal-conversion",
"-Wno-sign-conversion",
- "-Wstring-conversion",
+ "-DNOMINMAX",
]
-LLVM_TEST_FLAGS = [
+ABSL_LLVM_TEST_FLAGS = [
"-Wno-c99-extensions",
+ "-Wno-deprecated-declarations",
"-Wno-missing-noreturn",
"-Wno-missing-prototypes",
"-Wno-missing-variable-declarations",
@@ -104,29 +117,47 @@ LLVM_TEST_FLAGS = [
"-Wno-gnu-zero-variadic-macro-arguments",
]
-MSVC_EXCEPTIONS_FLAGS = [
- "/U_HAS_EXCEPTIONS",
- "/D_HAS_EXCEPTIONS=1",
- "/EHsc",
-]
-
-MSVC_FLAGS = [
+ABSL_MSVC_FLAGS = [
"/W3",
+ "/DNOMINMAX",
+ "/DWIN32_LEAN_AND_MEAN",
+ "/D_CRT_SECURE_NO_WARNINGS",
+ "/D_SCL_SECURE_NO_WARNINGS",
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+ "/bigobj",
"/wd4005",
"/wd4068",
"/wd4180",
"/wd4244",
"/wd4267",
+ "/wd4503",
"/wd4800",
- "/DNOMINMAX",
- "/DWIN32_LEAN_AND_MEAN",
- "/D_CRT_SECURE_NO_WARNINGS",
- "/D_SCL_SECURE_NO_WARNINGS",
- "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
]
-MSVC_TEST_FLAGS = [
+ABSL_MSVC_LINKOPTS = [
+ "-ignore:4221",
+]
+
+ABSL_MSVC_TEST_FLAGS = [
"/wd4018",
"/wd4101",
"/wd4503",
+ "/wd4996",
+ "/DNOMINMAX",
+]
+
+ABSL_RANDOM_HWAES_ARM32_FLAGS = [
+ "-mfpu=neon",
+]
+
+ABSL_RANDOM_HWAES_ARM64_FLAGS = [
+ "-march=armv8-a+crypto",
+]
+
+ABSL_RANDOM_HWAES_MSVC_X64_FLAGS = [
+]
+
+ABSL_RANDOM_HWAES_X64_FLAGS = [
+ "-maes",
+ "-msse4.1",
]
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/configure_copts.bzl b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/configure_copts.bzl
index 57cd3f62998..669a9060bc8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/configure_copts.bzl
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/configure_copts.bzl
@@ -6,37 +6,73 @@ change Abseil copts, edit absl/copts/copts.py
load(
"//absl:copts/GENERATED_copts.bzl",
- "GCC_EXCEPTIONS_FLAGS",
- "GCC_FLAGS",
- "GCC_TEST_FLAGS",
- "LLVM_EXCEPTIONS_FLAGS",
- "LLVM_FLAGS",
- "LLVM_TEST_FLAGS",
- "MSVC_EXCEPTIONS_FLAGS",
- "MSVC_FLAGS",
- "MSVC_TEST_FLAGS",
+ "ABSL_CLANG_CL_FLAGS",
+ "ABSL_CLANG_CL_TEST_FLAGS",
+ "ABSL_GCC_FLAGS",
+ "ABSL_GCC_TEST_FLAGS",
+ "ABSL_LLVM_FLAGS",
+ "ABSL_LLVM_TEST_FLAGS",
+ "ABSL_MSVC_FLAGS",
+ "ABSL_MSVC_LINKOPTS",
+ "ABSL_MSVC_TEST_FLAGS",
+ "ABSL_RANDOM_HWAES_ARM32_FLAGS",
+ "ABSL_RANDOM_HWAES_ARM64_FLAGS",
+ "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS",
+ "ABSL_RANDOM_HWAES_X64_FLAGS",
)
ABSL_DEFAULT_COPTS = select({
- "//absl:windows": MSVC_FLAGS,
- "//absl:llvm_compiler": LLVM_FLAGS,
- "//conditions:default": GCC_FLAGS,
+ "//absl:msvc_compiler": ABSL_MSVC_FLAGS,
+ "//absl:clang-cl_compiler": ABSL_CLANG_CL_FLAGS,
+ "//absl:clang_compiler": ABSL_LLVM_FLAGS,
+ "//conditions:default": ABSL_GCC_FLAGS,
})
-# in absence of modules (--compiler=gcc or -c opt), cc_tests leak their copts
-# to their (included header) dependencies and fail to build outside absl
ABSL_TEST_COPTS = ABSL_DEFAULT_COPTS + select({
- "//absl:windows": MSVC_TEST_FLAGS,
- "//absl:llvm_compiler": LLVM_TEST_FLAGS,
- "//conditions:default": GCC_TEST_FLAGS,
+ "//absl:msvc_compiler": ABSL_MSVC_TEST_FLAGS,
+ "//absl:clang-cl_compiler": ABSL_CLANG_CL_TEST_FLAGS,
+ "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
+ "//conditions:default": ABSL_GCC_TEST_FLAGS,
})
-ABSL_EXCEPTIONS_FLAG = select({
- "//absl:windows": MSVC_EXCEPTIONS_FLAGS,
- "//absl:llvm_compiler": LLVM_EXCEPTIONS_FLAGS,
- "//conditions:default": GCC_EXCEPTIONS_FLAGS,
+ABSL_DEFAULT_LINKOPTS = select({
+ "//absl:msvc_compiler": ABSL_MSVC_LINKOPTS,
+ "//conditions:default": [],
})
-ABSL_EXCEPTIONS_FLAG_LINKOPTS = select({
+# ABSL_RANDOM_RANDEN_COPTS blaze copts flags which are required by each
+# environment to build an accelerated RandenHwAes library.
+ABSL_RANDOM_RANDEN_COPTS = select({
+ # APPLE
+ ":cpu_darwin_x86_64": ABSL_RANDOM_HWAES_X64_FLAGS,
+ ":cpu_darwin": ABSL_RANDOM_HWAES_X64_FLAGS,
+ ":cpu_x64_windows_msvc": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
+ ":cpu_x64_windows": ABSL_RANDOM_HWAES_MSVC_X64_FLAGS,
+ ":cpu_k8": ABSL_RANDOM_HWAES_X64_FLAGS,
+ ":cpu_ppc": ["-mcrypto"],
+
+ # Supported by default or unsupported.
"//conditions:default": [],
})
+
+# absl_random_randen_copts_init:
+# Initialize the config targets based on cpu, os, etc. used to select
+# the required values for ABSL_RANDOM_RANDEN_COPTS
+def absl_random_randen_copts_init():
+ """Initialize the config_settings used by ABSL_RANDOM_RANDEN_COPTS."""
+
+ # CPU configs.
+ # These configs have consistent flags to enable HWAES intsructions.
+ cpu_configs = [
+ "ppc",
+ "k8",
+ "darwin_x86_64",
+ "darwin",
+ "x64_windows_msvc",
+ "x64_windows",
+ ]
+ for cpu in cpu_configs:
+ native.config_setting(
+ name = "cpu_%s" % cpu,
+ values = {"cpu": cpu},
+ )
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/copts.py b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/copts.py
index 40a8062f33b..cf52981c58c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/copts.py
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/copts.py
@@ -11,147 +11,152 @@ The generated copts are consumed by configure_copts.bzl and
AbseilConfigureCopts.cmake.
"""
-import collections # absl:google-only(used for internal flags)
+# /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
+MSVC_BIG_WARNING_FLAGS = [
+ "/W3",
+]
+
+LLVM_TEST_DISABLE_WARNINGS_FLAGS = [
+ "-Wno-c99-extensions",
+ "-Wno-deprecated-declarations",
+ "-Wno-missing-noreturn",
+ "-Wno-missing-prototypes",
+ "-Wno-missing-variable-declarations",
+ "-Wno-null-conversion",
+ "-Wno-shadow",
+ "-Wno-shift-sign-overflow",
+ "-Wno-sign-compare",
+ "-Wno-unused-function",
+ "-Wno-unused-member-function",
+ "-Wno-unused-parameter",
+ "-Wno-unused-private-field",
+ "-Wno-unused-template",
+ "-Wno-used-but-marked-unused",
+ "-Wno-zero-as-null-pointer-constant",
+ # gtest depends on this GNU extension being offered.
+ "-Wno-gnu-zero-variadic-macro-arguments",
+]
+
+MSVC_DEFINES = [
+ "/DNOMINMAX", # Don't define min and max macros (windows.h)
+ # Don't bloat namespace with incompatible winsock versions.
+ "/DWIN32_LEAN_AND_MEAN",
+ # Don't warn about usage of insecure C functions.
+ "/D_CRT_SECURE_NO_WARNINGS",
+ "/D_SCL_SECURE_NO_WARNINGS",
+ # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
+ "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
+]
+
COPT_VARS = {
- "GCC_FLAGS": [
+ "ABSL_GCC_FLAGS": [
"-Wall",
"-Wextra",
"-Wcast-qual",
"-Wconversion-null",
+ "-Wformat-security",
"-Wmissing-declarations",
"-Woverlength-strings",
"-Wpointer-arith",
+ "-Wundef",
"-Wunused-local-typedefs",
"-Wunused-result",
"-Wvarargs",
"-Wvla", # variable-length array
"-Wwrite-strings",
- # Google style does not use unsigned integers, though STL containers
- # have unsigned types.
- "-Wno-sign-compare",
+ # Don't define min and max macros (Build on Windows using gcc)
+ "-DNOMINMAX",
],
- "GCC_TEST_FLAGS": [
+ "ABSL_GCC_TEST_FLAGS": [
"-Wno-conversion-null",
+ "-Wno-deprecated-declarations",
"-Wno-missing-declarations",
"-Wno-sign-compare",
"-Wno-unused-function",
"-Wno-unused-parameter",
"-Wno-unused-private-field",
],
- "GCC_EXCEPTIONS_FLAGS": ["-fexceptions"],
-
- # Docs on single flags is preceded by a comment.
- # Docs on groups of flags is preceded by ###.
- "LLVM_FLAGS": [
+ "ABSL_LLVM_FLAGS": [
"-Wall",
"-Wextra",
- "-Weverything",
- # Abseil does not support C++98
- "-Wno-c++98-compat-pedantic",
- # Turns off all implicit conversion warnings. Most are re-enabled below.
- "-Wno-conversion",
- "-Wno-covered-switch-default",
- "-Wno-deprecated",
- "-Wno-disabled-macro-expansion",
- "-Wno-double-promotion",
- ###
- # Turned off as they include valid C++ code.
- "-Wno-comma",
- "-Wno-extra-semi",
- "-Wno-extra-semi-stmt",
- "-Wno-packed",
- "-Wno-padded",
- ###
- # Google style does not use unsigned integers, though STL containers
- # have unsigned types.
- "-Wno-sign-compare",
- ###
+ "-Wcast-qual",
+ "-Wconversion",
+ "-Wfloat-overflow-conversion",
+ "-Wfloat-zero-conversion",
+ "-Wfor-loop-analysis",
+ "-Wformat-security",
+ "-Wgnu-redeclared-enum",
+ "-Winfinite-recursion",
+ "-Wliteral-conversion",
+ "-Wmissing-declarations",
+ "-Woverlength-strings",
+ "-Wpointer-arith",
+ "-Wself-assign",
+ "-Wshadow",
+ "-Wstring-conversion",
+ "-Wtautological-overlap-compare",
+ "-Wundef",
+ "-Wuninitialized",
+ "-Wunreachable-code",
+ "-Wunused-comparison",
+ "-Wunused-local-typedefs",
+ "-Wunused-result",
+ "-Wvla",
+ "-Wwrite-strings",
+ # Warnings that are enabled by group warning flags like -Wall that we
+ # explicitly disable.
"-Wno-float-conversion",
- "-Wno-float-equal",
- "-Wno-format-nonliteral",
- # Too aggressive: warns on Clang extensions enclosed in Clang-only
- # compilation paths.
- "-Wno-gcc-compat",
- ###
- # Some internal globals are necessary. Don't do this at home.
- "-Wno-global-constructors",
- "-Wno-exit-time-destructors",
- ###
- "-Wno-nested-anon-types",
- "-Wno-non-modular-include-in-module",
- "-Wno-old-style-cast",
- # Warns on preferred usage of non-POD types such as string_view
- "-Wno-range-loop-analysis",
- "-Wno-reserved-id-macro",
+ "-Wno-implicit-float-conversion",
+ "-Wno-implicit-int-float-conversion",
+ "-Wno-implicit-int-conversion",
"-Wno-shorten-64-to-32",
- "-Wno-switch-enum",
- "-Wno-thread-safety-negative",
- "-Wno-undef",
- "-Wno-unknown-warning-option",
- "-Wno-unreachable-code",
- # Causes warnings on include guards
- "-Wno-unused-macros",
- "-Wno-weak-vtables",
- ###
- # Implicit conversion warnings turned off by -Wno-conversion
- # which are re-enabled below.
- "-Wbitfield-enum-conversion",
- "-Wbool-conversion",
- "-Wconstant-conversion",
- "-Wenum-conversion",
- "-Wint-conversion",
- "-Wliteral-conversion",
- "-Wnon-literal-null-conversion",
- "-Wnull-conversion",
- "-Wobjc-literal-conversion",
"-Wno-sign-conversion",
- "-Wstring-conversion",
- ],
- "LLVM_TEST_FLAGS": [
- "-Wno-c99-extensions",
- "-Wno-missing-noreturn",
- "-Wno-missing-prototypes",
- "-Wno-missing-variable-declarations",
- "-Wno-null-conversion",
- "-Wno-shadow",
- "-Wno-shift-sign-overflow",
- "-Wno-sign-compare",
- "-Wno-unused-function",
- "-Wno-unused-member-function",
- "-Wno-unused-parameter",
- "-Wno-unused-private-field",
- "-Wno-unused-template",
- "-Wno-used-but-marked-unused",
- "-Wno-zero-as-null-pointer-constant",
- # gtest depends on this GNU extension being offered.
- "-Wno-gnu-zero-variadic-macro-arguments",
+ # Don't define min and max macros (Build on Windows using clang)
+ "-DNOMINMAX",
],
- "LLVM_EXCEPTIONS_FLAGS": ["-fexceptions"],
- # /Wall with msvc includes unhelpful warnings such as C4711, C4710, ...
- "MSVC_FLAGS": [
- "/W3",
- "/wd4005", # macro-redefinition
- "/wd4068", # unknown pragma
- "/wd4180", # qualifier applied to function type has no meaning; ignored
- "/wd4244", # conversion from 'type1' to 'type2', possible loss of data
- "/wd4267", # conversion from 'size_t' to 'type', possible loss of data
- # forcing value to bool 'true' or 'false' (performance warning)
- "/wd4800",
- "/DNOMINMAX", # Don't define min and max macros (windows.h)
- # Don't bloat namespace with incompatible winsock versions.
- "/DWIN32_LEAN_AND_MEAN",
- # Don't warn about usage of insecure C functions.
- "/D_CRT_SECURE_NO_WARNINGS",
- "/D_SCL_SECURE_NO_WARNINGS",
- # Introduced in VS 2017 15.8, allow overaligned types in aligned_storage
- "/D_ENABLE_EXTENDED_ALIGNED_STORAGE",
- ],
- "MSVC_TEST_FLAGS": [
+ "ABSL_LLVM_TEST_FLAGS":
+ LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+ "ABSL_CLANG_CL_FLAGS":
+ (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES),
+ "ABSL_CLANG_CL_TEST_FLAGS":
+ LLVM_TEST_DISABLE_WARNINGS_FLAGS,
+ "ABSL_MSVC_FLAGS":
+ MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES + [
+ # Increase the number of sections available in object files
+ "/bigobj",
+ "/wd4005", # macro-redefinition
+ "/wd4068", # unknown pragma
+ # qualifier applied to function type has no meaning; ignored
+ "/wd4180",
+ # conversion from 'type1' to 'type2', possible loss of data
+ "/wd4244",
+ # conversion from 'size_t' to 'type', possible loss of data
+ "/wd4267",
+ # The decorated name was longer than the compiler limit
+ "/wd4503",
+ # forcing value to bool 'true' or 'false' (performance warning)
+ "/wd4800",
+ ],
+ "ABSL_MSVC_TEST_FLAGS": [
"/wd4018", # signed/unsigned mismatch
"/wd4101", # unreferenced local variable
"/wd4503", # decorated name length exceeded, name was truncated
+ "/wd4996", # use of deprecated symbol
+ "/DNOMINMAX", # disable the min() and max() macros from <windows.h>
+ ],
+ "ABSL_MSVC_LINKOPTS": [
+ # Object file doesn't export any previously undefined symbols
+ "-ignore:4221",
+ ],
+ # "HWAES" is an abbreviation for "hardware AES" (AES - Advanced Encryption
+ # Standard). These flags are used for detecting whether or not the target
+ # architecture has hardware support for AES instructions which can be used
+ # to improve performance of some random bit generators.
+ "ABSL_RANDOM_HWAES_ARM64_FLAGS": ["-march=armv8-a+crypto"],
+ "ABSL_RANDOM_HWAES_ARM32_FLAGS": ["-mfpu=neon"],
+ "ABSL_RANDOM_HWAES_X64_FLAGS": [
+ "-maes",
+ "-msse4.1",
],
- "MSVC_EXCEPTIONS_FLAGS": [
- "/U_HAS_EXCEPTIONS", "/D_HAS_EXCEPTIONS=1", "/EHsc"
- ]
+ "ABSL_RANDOM_HWAES_MSVC_X64_FLAGS": [],
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/generate_copts.py b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/generate_copts.py
index 28b677e0cd3..0e5dc9fad29 100755
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/generate_copts.py
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/copts/generate_copts.py
@@ -70,8 +70,9 @@ class StarlarkStyle(object):
return "GENERATED_copts.bzl"
-# Copt file generation
def copt_list(name, arg_list, style):
+ """Copt file generation."""
+
make_line = lambda s: " \"" + s + "\"" + style.separator()
external_str_list = [make_line(s) for s in arg_list]
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/BUILD.bazel
index 84b994da31e..5385bcb6509 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,9 +14,11 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
@@ -24,18 +26,27 @@ package(
default_visibility = ["//visibility:public"],
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "stacktrace",
srcs = [
+ "internal/stacktrace_aarch64-inl.inc",
+ "internal/stacktrace_arm-inl.inc",
+ "internal/stacktrace_config.h",
+ "internal/stacktrace_generic-inl.inc",
+ "internal/stacktrace_powerpc-inl.inc",
+ "internal/stacktrace_unimplemented-inl.inc",
+ "internal/stacktrace_win32-inl.inc",
+ "internal/stacktrace_x86-inl.inc",
"stacktrace.cc",
],
hdrs = ["stacktrace.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":debugging_internal",
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
],
)
@@ -44,6 +55,7 @@ cc_library(
name = "symbolize",
srcs = [
"symbolize.cc",
+ "symbolize_darwin.inc",
"symbolize_elf.inc",
"symbolize_unimplemented.inc",
"symbolize_win32.inc",
@@ -53,25 +65,46 @@ cc_library(
"symbolize.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS + select({
+ "//absl:msvc_compiler": ["-DEFAULTLIB:dbghelp.lib"],
+ "//absl:clang-cl_compiler": ["-DEFAULTLIB:dbghelp.lib"],
+ "//conditions:default": [],
+ }),
deps = [
":debugging_internal",
":demangle_internal",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:dynamic_annotations",
"//absl/base:malloc_internal",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
],
)
cc_test(
name = "symbolize_test",
srcs = ["symbolize_test.cc"],
- copts = ABSL_TEST_COPTS,
+ copts = ABSL_TEST_COPTS + select({
+ "//absl:msvc_compiler": ["/Z7"],
+ "//absl:clang-cl_compiler": ["/Z7"],
+ "//conditions:default": [],
+ }),
+ linkopts = ABSL_DEFAULT_LINKOPTS + select({
+ "//absl:msvc_compiler": ["/DEBUG"],
+ "//absl:clang-cl_compiler": ["/DEBUG"],
+ "//conditions:default": [],
+ }),
deps = [
":stack_consumption",
":symbolize",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/memory",
+ "//absl/strings",
"@com_google_googletest//:gtest",
],
)
@@ -85,12 +118,14 @@ cc_library(
"internal/examine_stack.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
":stacktrace",
":symbolize",
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
],
)
@@ -99,12 +134,15 @@ cc_library(
srcs = ["failure_signal_handler.cc"],
hdrs = ["failure_signal_handler.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":examine_stack",
":stacktrace",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:errno_saver",
+ "//absl/base:raw_logging_internal",
],
)
@@ -113,14 +151,16 @@ cc_test(
srcs = ["failure_signal_handler_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = select({
- "//absl:windows": [],
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
+ "//absl:wasm": [],
"//conditions:default": ["-pthread"],
- }),
+ }) + ABSL_DEFAULT_LINKOPTS,
deps = [
":failure_signal_handler",
":stacktrace",
":symbolize",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
"//absl/strings",
"@com_google_googletest//:gtest",
],
@@ -136,21 +176,16 @@ cc_library(
hdrs = [
"internal/address_is_readable.h",
"internal/elf_mem_image.h",
- "internal/stacktrace_aarch64-inl.inc",
- "internal/stacktrace_arm-inl.inc",
- "internal/stacktrace_config.h",
- "internal/stacktrace_generic-inl.inc",
- "internal/stacktrace_powerpc-inl.inc",
- "internal/stacktrace_unimplemented-inl.inc",
- "internal/stacktrace_win32-inl.inc",
- "internal/stacktrace_x86-inl.inc",
"internal/vdso_support.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
+ "//absl/base:errno_saver",
+ "//absl/base:raw_logging_internal",
],
)
@@ -161,6 +196,7 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
deps = [
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
],
)
@@ -169,11 +205,13 @@ cc_test(
name = "demangle_test",
srcs = ["internal/demangle_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":demangle_internal",
":stack_consumption",
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/memory",
"@com_google_googletest//:gtest_main",
],
@@ -183,7 +221,11 @@ cc_library(
name = "leak_check",
srcs = ["leak_check.cc"],
hdrs = ["leak_check.h"],
- deps = ["//absl/base:core_headers"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
)
# Adding a dependency to leak_check_disable will disable
@@ -192,14 +234,16 @@ cc_library(
cc_library(
name = "leak_check_disable",
srcs = ["leak_check_disable.cc"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
linkstatic = 1,
+ deps = ["//absl/base:config"],
alwayslink = 1,
)
# These targets exists for use in tests only, explicitly configuring the
# LEAK_SANITIZER macro. It must be linked with -fsanitize=leak for lsan.
ABSL_LSAN_LINKOPTS = select({
- "//absl:llvm_compiler": ["-fsanitize=leak"],
+ "//absl:clang_compiler": ["-fsanitize=leak"],
"//conditions:default": [],
})
@@ -209,10 +253,15 @@ cc_library(
srcs = ["leak_check.cc"],
hdrs = ["leak_check.h"],
copts = select({
- "//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
+ "//absl:clang_compiler": ["-DLEAK_SANITIZER"],
"//conditions:default": [],
}),
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
)
cc_library(
@@ -221,17 +270,23 @@ cc_library(
srcs = ["leak_check.cc"],
hdrs = ["leak_check.h"],
copts = ["-ULEAK_SANITIZER"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
)
cc_test(
name = "leak_check_test",
srcs = ["leak_check_test.cc"],
copts = select({
- "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
+ "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
"//conditions:default": [],
}),
- linkopts = ABSL_LSAN_LINKOPTS,
+ linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
+ tags = ["notsan"],
deps = [
":leak_check_api_enabled_for_testing",
"//absl/base",
@@ -243,6 +298,8 @@ cc_test(
name = "leak_check_no_lsan_test",
srcs = ["leak_check_test.cc"],
copts = ["-UABSL_EXPECT_LEAK_SANITIZER"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["noasan"],
deps = [
":leak_check_api_disabled_for_testing",
"//absl/base", # for raw_logging
@@ -257,7 +314,8 @@ cc_test(
cc_test(
name = "disabled_leak_check_test",
srcs = ["leak_check_fail_test.cc"],
- linkopts = ABSL_LSAN_LINKOPTS,
+ linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
+ tags = ["notsan"],
deps = [
":leak_check_api_enabled_for_testing",
":leak_check_disable",
@@ -272,10 +330,12 @@ cc_library(
srcs = ["internal/stack_consumption.cc"],
hdrs = ["internal/stack_consumption.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
- "//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
],
)
@@ -283,10 +343,11 @@ cc_test(
name = "stack_consumption_test",
srcs = ["internal/stack_consumption_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":stack_consumption",
- "//absl/base",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"@com_google_googletest//:gtest_main",
],
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.cc
index c2e56f9d819..a9ed6ef9648 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,9 +21,14 @@
#ifdef _WIN32
#include <windows.h>
#else
+#include <sched.h>
#include <unistd.h>
#endif
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
#ifdef ABSL_HAVE_MMAP
#include <sys/mman.h>
#endif
@@ -37,6 +42,7 @@
#include <ctime>
#include "absl/base/attributes.h"
+#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/debugging/internal/examine_stack.h"
@@ -44,9 +50,15 @@
#ifndef _WIN32
#define ABSL_HAVE_SIGACTION
+// Apple WatchOS and TVOS don't allow sigaltstack
+#if !(defined(TARGET_OS_WATCH) && TARGET_OS_WATCH) && \
+ !(defined(TARGET_OS_TV) && TARGET_OS_TV)
+#define ABSL_HAVE_SIGALTSTACK
+#endif
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
ABSL_CONST_INIT static FailureSignalHandlerOptions fsh_options;
@@ -116,7 +128,7 @@ const char* FailureSignalToString(int signo) {
} // namespace debugging_internal
-#ifndef _WIN32
+#ifdef ABSL_HAVE_SIGALTSTACK
static bool SetupAlternateStackOnce() {
#if defined(__wasm__) || defined (__asjms__)
@@ -125,8 +137,8 @@ static bool SetupAlternateStackOnce() {
const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
#endif
size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_size *= 5;
#endif
@@ -168,7 +180,7 @@ static bool SetupAlternateStackOnce() {
// Returns the appropriate flag for sig_action.sa_flags
// if the system supports using an alternate stack.
static int MaybeSetupAlternateStack() {
-#ifndef _WIN32
+#ifdef ABSL_HAVE_SIGALTSTACK
ABSL_ATTRIBUTE_UNUSED static const bool kOnce = SetupAlternateStackOnce();
return SA_ONSTACK;
#else
@@ -204,22 +216,28 @@ static void InstallOneFailureHandler(FailureSignalData* data,
#endif
static void WriteToStderr(const char* data) {
- int old_errno = errno;
+ absl::base_internal::ErrnoSaver errno_saver;
absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
- errno = old_errno;
}
-static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {
- char buf[64];
+static void WriteSignalMessage(int signo, int cpu,
+ void (*writerfn)(const char*)) {
+ char buf[96];
+ char on_cpu[32] = {0};
+ if (cpu != -1) {
+ snprintf(on_cpu, sizeof(on_cpu), " on cpu %d", cpu);
+ }
const char* const signal_string =
debugging_internal::FailureSignalToString(signo);
if (signal_string != nullptr && signal_string[0] != '\0') {
- snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n",
+ snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
signal_string,
- static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
+ static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
+ on_cpu);
} else {
- snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n",
- signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
+ snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
+ signo, static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
+ on_cpu);
}
writerfn(buf);
}
@@ -259,10 +277,10 @@ ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace(
// Called by AbslFailureSignalHandler() to write the failure info. It is
// called once with writerfn set to WriteToStderr() and then possibly
// with writerfn set to the user provided function.
-static void WriteFailureInfo(int signo, void* ucontext,
+static void WriteFailureInfo(int signo, void* ucontext, int cpu,
void (*writerfn)(const char*)) {
WriterFnStruct writerfn_struct{writerfn};
- WriteSignalMessage(signo, writerfn);
+ WriteSignalMessage(signo, cpu, writerfn);
WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
&writerfn_struct);
}
@@ -324,6 +342,14 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
}
}
+ // Increase the chance that the CPU we report was the same CPU on which the
+ // signal was received by doing this as early as possible, i.e. after
+ // verifying that this is not a recursive signal handler invocation.
+ int my_cpu = -1;
+#ifdef ABSL_HAVE_SCHED_GETCPU
+ my_cpu = sched_getcpu();
+#endif
+
#ifdef ABSL_HAVE_ALARM
// Set an alarm to abort the program in case this code hangs or deadlocks.
if (fsh_options.alarm_on_failure_secs > 0) {
@@ -334,12 +360,12 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
#endif
// First write to stderr.
- WriteFailureInfo(signo, ucontext, WriteToStderr);
+ WriteFailureInfo(signo, ucontext, my_cpu, WriteToStderr);
// Riskier code (because it is less likely to be async-signal-safe)
// goes after this point.
if (fsh_options.writerfn != nullptr) {
- WriteFailureInfo(signo, ucontext, fsh_options.writerfn);
+ WriteFailureInfo(signo, ucontext, my_cpu, fsh_options.writerfn);
}
if (fsh_options.call_previous_handler) {
@@ -356,4 +382,5 @@ void InstallFailureSignalHandler(const FailureSignalHandlerOptions& options) {
}
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.h
index c57954e5875..0c0f585d0fb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -44,7 +44,10 @@
#ifndef ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
#define ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
// FailureSignalHandlerOptions
//
@@ -85,7 +88,7 @@ struct FailureSignalHandlerOptions {
bool call_previous_handler = false;
// If non-null, indicates a pointer to a callback function that will be called
- // upon failure, with a std::string argument containing failure data. This function
+ // upon failure, with a string argument containing failure data. This function
// may be used as a hook to write failure data to a secondary location, such
// as a log file. This function may also be called with null data, as a hint
// to flush any buffered data before the program may be terminated. Consider
@@ -112,6 +115,7 @@ namespace debugging_internal {
const char* FailureSignalToString(int signo);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_FAILURE_SIGNAL_HANDLER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
index ba520910f47..6a62428b338 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,6 +23,7 @@
#include <fstream>
#include "gtest/gtest.h"
+#include "gmock/gmock.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
@@ -31,6 +32,8 @@
namespace {
+using testing::StartsWith;
+
#if GTEST_HAS_DEATH_TEST
// For the parameterized death tests. GetParam() returns the signal number.
@@ -52,7 +55,7 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
exit_regex);
#else
// Windows doesn't have testing::KilledBySignal().
- EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
+ EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex);
#endif
}
@@ -104,8 +107,8 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
testing::KilledBySignal(signo), exit_regex);
#else
// Windows doesn't have testing::KilledBySignal().
- EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
- exit_regex);
+ EXPECT_DEATH_IF_SUPPORTED(
+ InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex);
#endif
// Open the file in this process and check its contents.
@@ -113,15 +116,21 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
ASSERT_TRUE(error_output.is_open()) << file;
std::string error_line;
std::getline(error_output, error_line);
- EXPECT_TRUE(absl::StartsWith(
+ EXPECT_THAT(
error_line,
- absl::StrCat("*** ",
- absl::debugging_internal::FailureSignalToString(signo),
- " received at ")));
+ StartsWith(absl::StrCat(
+ "*** ", absl::debugging_internal::FailureSignalToString(signo),
+ " received at ")));
+
+ // On platforms where it is possible to get the current CPU, the
+ // CPU number is also logged. Check that it is present in output.
+#if defined(__linux__)
+ EXPECT_THAT(error_line, testing::HasSubstr(" on cpu "));
+#endif
if (absl::debugging_internal::StackTraceWorksForTest()) {
std::getline(error_output, error_line);
- EXPECT_TRUE(absl::StartsWith(error_line, "PC: "));
+ EXPECT_THAT(error_line, StartsWith("PC: "));
}
}
@@ -133,16 +142,17 @@ constexpr int kFailureSignals[] = {
};
std::string SignalParamToString(const ::testing::TestParamInfo<int>& info) {
- std::string result = absl::debugging_internal::FailureSignalToString(info.param);
+ std::string result =
+ absl::debugging_internal::FailureSignalToString(info.param);
if (result.empty()) {
result = absl::StrCat(info.param);
}
return result;
}
-INSTANTIATE_TEST_CASE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
- ::testing::ValuesIn(kFailureSignals),
- SignalParamToString);
+INSTANTIATE_TEST_SUITE_P(AbslDeathTest, FailureSignalHandlerDeathTest,
+ ::testing::ValuesIn(kFailureSignals),
+ SignalParamToString);
#endif // GTEST_HAS_DEATH_TEST
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.cc
index 7455aa0b416..329c285f3b5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,12 +20,14 @@
#if !defined(__linux__) || defined(__ANDROID__)
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// On platforms other than Linux, just return true.
bool AddressIsReadable(const void* /* addr */) { return true; }
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#else
@@ -33,13 +35,16 @@ bool AddressIsReadable(const void* /* addr */) { return true; }
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
+
#include <atomic>
#include <cerrno>
#include <cstdint>
+#include "absl/base/internal/errno_saver.h"
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Pack a pid and two file descriptors into a 64-bit word,
@@ -63,8 +68,9 @@ static void Unpack(uint64_t x, int *pid, int *read_fd, int *write_fd) {
// unimplemented.
// This is a namespace-scoped variable for correct zero-initialization.
static std::atomic<uint64_t> pid_and_fds; // initially 0, an invalid pid.
+
bool AddressIsReadable(const void *addr) {
- int save_errno = errno;
+ absl::base_internal::ErrnoSaver errno_saver;
// We test whether a byte is readable by using write(). Normally, this would
// be done via a cached file descriptor to /dev/null, but linux fails to
// check whether the byte is readable when the destination is /dev/null, so
@@ -81,7 +87,7 @@ bool AddressIsReadable(const void *addr) {
int pid;
int read_fd;
int write_fd;
- uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+ uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
while (current_pid != pid) {
int p[2];
@@ -93,13 +99,13 @@ bool AddressIsReadable(const void *addr) {
fcntl(p[1], F_SETFD, FD_CLOEXEC);
uint64_t new_pid_and_fds = Pack(current_pid, p[0], p[1]);
if (pid_and_fds.compare_exchange_strong(
- local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
+ local_pid_and_fds, new_pid_and_fds, std::memory_order_release,
std::memory_order_relaxed)) {
local_pid_and_fds = new_pid_and_fds; // fds exposed to other threads
} else { // fds not exposed to other threads; we can close them.
close(p[0]);
close(p[1]);
- local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
+ local_pid_and_fds = pid_and_fds.load(std::memory_order_acquire);
}
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
}
@@ -119,15 +125,15 @@ bool AddressIsReadable(const void *addr) {
// If pid_and_fds contains the problematic file descriptors we just used,
// this call will forget them, and the loop will try again.
pid_and_fds.compare_exchange_strong(local_pid_and_fds, 0,
- std::memory_order_relaxed,
+ std::memory_order_release,
std::memory_order_relaxed);
}
} while (errno == EBADF);
- errno = save_errno;
return bytes_written == 1;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.h
index 9d48030065c..4bbaf4d69bd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/address_is_readable.h
@@ -4,19 +4,21 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
#define ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Return whether the byte at *addr is readable, without faulting.
@@ -24,6 +26,7 @@ namespace debugging_internal {
bool AddressIsReadable(const void *addr);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_ADDRESS_IS_READABLE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.cc
index 3ee3df51438..5cd563208ea 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +24,7 @@
#include <limits>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
typedef struct {
@@ -93,6 +94,8 @@ static const AbbrevPair kOperatorList[] = {
};
// List of builtin types from Itanium C++ ABI.
+//
+// Invariant: only one- or two-character type abbreviations here.
static const AbbrevPair kBuiltinTypeList[] = {
{"v", "void", 0},
{"w", "wchar_t", 0},
@@ -115,6 +118,17 @@ static const AbbrevPair kBuiltinTypeList[] = {
{"e", "long double", 0},
{"g", "__float128", 0},
{"z", "ellipsis", 0},
+
+ {"De", "decimal128", 0}, // IEEE 754r decimal floating point (128 bits)
+ {"Dd", "decimal64", 0}, // IEEE 754r decimal floating point (64 bits)
+ {"Dc", "decltype(auto)", 0},
+ {"Da", "auto", 0},
+ {"Dn", "std::nullptr_t", 0}, // i.e., decltype(nullptr)
+ {"Df", "decimal32", 0}, // IEEE 754r decimal floating point (32 bits)
+ {"Di", "char32_t", 0},
+ {"Du", "char8_t", 0},
+ {"Ds", "char16_t", 0},
+ {"Dh", "float16", 0}, // IEEE 754r half-precision float (16 bits)
{nullptr, nullptr, 0},
};
@@ -138,7 +152,7 @@ static const AbbrevPair kSubstitutionList[] = {
// frame, so every byte counts.
typedef struct {
int mangled_idx; // Cursor of mangled name.
- int out_cur_idx; // Cursor of output std::string.
+ int out_cur_idx; // Cursor of output string.
int prev_name_idx; // For constructors/destructors.
signed int prev_name_length : 16; // For constructors/destructors.
signed int nest_level : 15; // For nested names.
@@ -159,8 +173,8 @@ static_assert(sizeof(ParseState) == 4 * sizeof(int),
// Only one copy of this exists for each call to Demangle, so the size of this
// struct is nearly inconsequential.
typedef struct {
- const char *mangled_begin; // Beginning of input std::string.
- char *out; // Beginning of output std::string.
+ const char *mangled_begin; // Beginning of input string.
+ char *out; // Beginning of output string.
int out_end_idx; // One past last allowed output character.
int recursion_depth; // For stack exhaustion prevention.
int steps; // Cap how much work we'll do, regardless of depth.
@@ -372,30 +386,35 @@ static bool IsDigit(char c) { return c >= '0' && c <= '9'; }
// by GCC 4.5.x and later versions (and our locally-modified version of GCC
// 4.4.x) to indicate functions which have been cloned during optimization.
// We treat any sequence (.<alpha>+.<digit>+)+ as a function clone suffix.
+// Additionally, '_' is allowed along with the alphanumeric sequence.
static bool IsFunctionCloneSuffix(const char *str) {
size_t i = 0;
while (str[i] != '\0') {
- // Consume a single .<alpha>+.<digit>+ sequence.
- if (str[i] != '.' || !IsAlpha(str[i + 1])) {
- return false;
+ bool parsed = false;
+ // Consume a single [.<alpha> | _]*[.<digit>]* sequence.
+ if (str[i] == '.' && (IsAlpha(str[i + 1]) || str[i + 1] == '_')) {
+ parsed = true;
+ i += 2;
+ while (IsAlpha(str[i]) || str[i] == '_') {
+ ++i;
+ }
}
- i += 2;
- while (IsAlpha(str[i])) {
- ++i;
+ if (str[i] == '.' && IsDigit(str[i + 1])) {
+ parsed = true;
+ i += 2;
+ while (IsDigit(str[i])) {
+ ++i;
+ }
}
- if (str[i] != '.' || !IsDigit(str[i + 1])) {
+ if (!parsed)
return false;
- }
- i += 2;
- while (IsDigit(str[i])) {
- ++i;
- }
}
return true; // Consumed everything in "str".
}
static bool EndsWith(State *state, const char chr) {
return state->parse_state.out_cur_idx > 0 &&
+ state->parse_state.out_cur_idx < state->out_end_idx &&
chr == state->out[state->parse_state.out_cur_idx - 1];
}
@@ -408,8 +427,10 @@ static void MaybeAppendWithLength(State *state, const char *const str,
if (str[0] == '<' && EndsWith(state, '<')) {
Append(state, " ", 1);
}
- // Remember the last identifier name for ctors/dtors.
- if (IsAlpha(str[0]) || str[0] == '_') {
+ // Remember the last identifier name for ctors/dtors,
+ // but only if we haven't yet overflown the buffer.
+ if (state->parse_state.out_cur_idx < state->out_end_idx &&
+ (IsAlpha(str[0]) || str[0] == '_')) {
state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;
state->parse_state.prev_name_length = length;
}
@@ -749,8 +770,8 @@ static bool ParseSourceName(State *state) {
// <local-source-name> ::= L <source-name> [<discriminator>]
//
// References:
-// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
-// http://gcc.gnu.org/viewcvs?view=rev&revision=124467
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=31775
+// https://gcc.gnu.org/viewcvs?view=rev&revision=124467
static bool ParseLocalSourceName(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
@@ -949,6 +970,7 @@ static bool ParseOperatorName(State *state, int *arity) {
// ::= TT <type>
// ::= TI <type>
// ::= TS <type>
+// ::= TH <type> # thread-local
// ::= Tc <call-offset> <call-offset> <(base) encoding>
// ::= GV <(object) name>
// ::= T <call-offset> <(base) encoding>
@@ -967,7 +989,7 @@ static bool ParseSpecialName(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
- if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
+ if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTISH") &&
ParseType(state)) {
return true;
}
@@ -1064,20 +1086,28 @@ static bool ParseVOffset(State *state) {
return false;
}
-// <ctor-dtor-name> ::= C1 | C2 | C3
+// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
+// <base-class-type>
// ::= D0 | D1 | D2
// # GCC extensions: "unified" constructor/destructor. See
-// # https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
+// #
+// https://github.com/gcc-mirror/gcc/blob/7ad17b583c3643bd4557f29b8391ca7ef08391f5/gcc/cp/mangle.c#L1847
// ::= C4 | D4
static bool ParseCtorDtorName(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
- if (ParseOneCharToken(state, 'C') && ParseCharClass(state, "1234")) {
- const char *const prev_name = state->out + state->parse_state.prev_name_idx;
- MaybeAppendWithLength(state, prev_name,
- state->parse_state.prev_name_length);
- return true;
+ if (ParseOneCharToken(state, 'C')) {
+ if (ParseCharClass(state, "1234")) {
+ const char *const prev_name =
+ state->out + state->parse_state.prev_name_idx;
+ MaybeAppendWithLength(state, prev_name,
+ state->parse_state.prev_name_length);
+ return true;
+ } else if (ParseOneCharToken(state, 'I') && ParseCharClass(state, "12") &&
+ ParseClassEnumType(state)) {
+ return true;
+ }
}
state->parse_state = copy;
@@ -1126,6 +1156,7 @@ static bool ParseDecltype(State *state) {
// ::= <decltype>
// ::= <substitution>
// ::= Dp <type> # pack expansion of (C++0x)
+// ::= Dv <num-elems> _ # GNU vector extension
//
static bool ParseType(State *state) {
ComplexityGuard guard(state);
@@ -1192,6 +1223,12 @@ static bool ParseType(State *state) {
return true;
}
+ if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) &&
+ ParseOneCharToken(state, '_')) {
+ return true;
+ }
+ state->parse_state = copy;
+
return false;
}
@@ -1208,16 +1245,26 @@ static bool ParseCVQualifiers(State *state) {
return num_cv_qualifiers > 0;
}
-// <builtin-type> ::= v, etc.
+// <builtin-type> ::= v, etc. # single-character builtin types
// ::= u <source-name>
+// ::= Dd, etc. # two-character builtin types
+//
+// Not supported:
+// ::= DF <number> _ # _FloatN (N bits)
+//
static bool ParseBuiltinType(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
const AbbrevPair *p;
for (p = kBuiltinTypeList; p->abbrev != nullptr; ++p) {
- if (RemainingInput(state)[0] == p->abbrev[0]) {
+ // Guaranteed only 1- or 2-character strings in kBuiltinTypeList.
+ if (p->abbrev[1] == '\0') {
+ if (ParseOneCharToken(state, p->abbrev[0])) {
+ MaybeAppend(state, p->real_name);
+ return true;
+ }
+ } else if (p->abbrev[2] == '\0' && ParseTwoCharToken(state, p->abbrev)) {
MaybeAppend(state, p->real_name);
- ++state->parse_state.mangled_idx;
return true;
}
}
@@ -1230,13 +1277,42 @@ static bool ParseBuiltinType(State *state) {
return false;
}
-// <function-type> ::= F [Y] <bare-function-type> E
+// <exception-spec> ::= Do # non-throwing
+// exception-specification (e.g.,
+// noexcept, throw())
+// ::= DO <expression> E # computed (instantiation-dependent)
+// noexcept
+// ::= Dw <type>+ E # dynamic exception specification
+// with instantiation-dependent types
+static bool ParseExceptionSpec(State *state) {
+ ComplexityGuard guard(state);
+ if (guard.IsTooComplex()) return false;
+
+ if (ParseTwoCharToken(state, "Do")) return true;
+
+ ParseState copy = state->parse_state;
+ if (ParseTwoCharToken(state, "DO") && ParseExpression(state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ state->parse_state = copy;
+ if (ParseTwoCharToken(state, "Dw") && OneOrMore(ParseType, state) &&
+ ParseOneCharToken(state, 'E')) {
+ return true;
+ }
+ state->parse_state = copy;
+
+ return false;
+}
+
+// <function-type> ::= [exception-spec] F [Y] <bare-function-type> [O] E
static bool ParseFunctionType(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
- if (ParseOneCharToken(state, 'F') &&
+ if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
+ Optional(ParseOneCharToken(state, 'O')) &&
ParseOneCharToken(state, 'E')) {
return true;
}
@@ -1864,8 +1940,10 @@ static bool Overflowed(const State *state) {
bool Demangle(const char *mangled, char *out, int out_size) {
State state;
InitState(&state, mangled, out, out_size);
- return ParseTopLevelMangledName(&state) && !Overflowed(&state);
+ return ParseTopLevelMangledName(&state) && !Overflowed(&state) &&
+ state.parse_state.out_cur_idx > 0;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.h
index 2e75564ed35..c314d9bc237 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -53,7 +53,10 @@
#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Demangle `mangled`. On success, return true and write the
@@ -62,6 +65,7 @@ namespace debugging_internal {
bool Demangle(const char *mangled, char *out, int out_size);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_DEMANGLE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle_test.cc
index b9d9008f007..6b142902ca8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/demangle_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,11 +18,13 @@
#include <string>
#include "gtest/gtest.h"
+#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/debugging/internal/stack_consumption.h"
#include "absl/memory/memory.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
namespace {
@@ -68,12 +70,34 @@ TEST(Demangle, Clones) {
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", tmp);
- // Invalid (truncated), should not demangle.
- EXPECT_FALSE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
+ // Demangle suffixes produced by -funique-internal-linkage-names.
+ EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ EXPECT_TRUE(Demangle("_ZL3Foov.__uniq.12345.isra.2.constprop.18", tmp,
+ sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Suffixes without the number should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clo", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Suffixes with just the number should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.123", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (.clone. followed by non-number), should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (.clone. followed by multiple numbers), should also demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.clone.123.456", tmp, sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // (a long valid suffix), should demangle.
+ EXPECT_TRUE(Demangle("_ZL3Foov.part.9.165493.constprop.775.31805", tmp,
+ sizeof(tmp)));
+ EXPECT_STREQ("Foo()", tmp);
+ // Invalid (. without anything else), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.", tmp, sizeof(tmp)));
+ // Invalid (. with mix of alpha and digits), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.abc123", tmp, sizeof(tmp)));
// Invalid (.clone. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.clone.", tmp, sizeof(tmp)));
- // Invalid (.clone. followed by non-number), should not demangle.
- EXPECT_FALSE(Demangle("_ZL3Foov.clone.foo", tmp, sizeof(tmp)));
// Invalid (.constprop. not followed by number), should not demangle.
EXPECT_FALSE(Demangle("_ZL3Foov.isra.2.constprop.", tmp, sizeof(tmp)));
}
@@ -82,7 +106,9 @@ TEST(Demangle, Clones) {
// They are not to be run under sanitizers as the sanitizers increase
// stack consumption by about 4x.
#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
- !ADDRESS_SANITIZER && !MEMORY_SANITIZER && !THREAD_SANITIZER
+ !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
+ !defined(ABSL_HAVE_MEMORY_SANITIZER) && \
+ !defined(ABSL_HAVE_THREAD_SANITIZER)
static const char *g_mangled;
static char g_demangle_buffer[4096];
@@ -176,6 +202,7 @@ static void TestOnInput(const char* input) {
TEST(DemangleRegression, NegativeLength) {
TestOnInput("_ZZn4");
}
+
TEST(DemangleRegression, DeeplyNestedArrayType) {
const int depth = 100000;
std::string data = "_ZStI";
@@ -188,4 +215,5 @@ TEST(DemangleRegression, DeeplyNestedArrayType) {
} // namespace
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
index 3f747e7f958..24cc01302dc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -38,6 +38,7 @@
#define VERSYM_VERSION 0x7fff
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
namespace {
@@ -375,6 +376,7 @@ void ElfMemImage::SymbolIterator::Update(int increment) {
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.h
index 3b577268954..46bfade3503 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/elf_mem_image.h
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -23,6 +23,8 @@
// used.
#include <climits>
+#include "absl/base/config.h"
+
// Maybe one day we can rewrite this file not to require the elf
// symbol extensions in glibc, but for right now we need them.
#ifdef ABSL_HAVE_ELF_MEM_IMAGE
@@ -34,11 +36,12 @@
#define ABSL_HAVE_ELF_MEM_IMAGE 1
#endif
-#if ABSL_HAVE_ELF_MEM_IMAGE
+#ifdef ABSL_HAVE_ELF_MEM_IMAGE
#include <link.h> // for ElfW
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// An in-memory ELF image (may not exist on disk).
@@ -123,6 +126,7 @@ class ElfMemImage {
};
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.cc
index faf88836735..589a3ef367d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,10 @@
#include <unistd.h>
#endif
+#ifdef __APPLE__
+#include <sys/ucontext.h>
+#endif
+
#include <csignal>
#include <cstdio>
@@ -30,6 +34,7 @@
#include "absl/debugging/symbolize.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Returns the program counter from signal context, nullptr if
@@ -41,28 +46,72 @@ void* GetProgramCounter(void* vuc) {
ucontext_t* context = reinterpret_cast<ucontext_t*>(vuc);
#if defined(__aarch64__)
return reinterpret_cast<void*>(context->uc_mcontext.pc);
+#elif defined(__alpha__)
+ return reinterpret_cast<void*>(context->uc_mcontext.sc_pc);
#elif defined(__arm__)
return reinterpret_cast<void*>(context->uc_mcontext.arm_pc);
+#elif defined(__hppa__)
+ return reinterpret_cast<void*>(context->uc_mcontext.sc_iaoq[0]);
#elif defined(__i386__)
if (14 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))
return reinterpret_cast<void*>(context->uc_mcontext.gregs[14]);
+#elif defined(__ia64__)
+ return reinterpret_cast<void*>(context->uc_mcontext.sc_ip);
+#elif defined(__m68k__)
+ return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);
#elif defined(__mips__)
return reinterpret_cast<void*>(context->uc_mcontext.pc);
#elif defined(__powerpc64__)
return reinterpret_cast<void*>(context->uc_mcontext.gp_regs[32]);
#elif defined(__powerpc__)
- return reinterpret_cast<void*>(context->uc_mcontext.regs->nip);
+ return reinterpret_cast<void*>(context->uc_mcontext.uc_regs->gregs[32]);
+#elif defined(__riscv)
+ return reinterpret_cast<void*>(context->uc_mcontext.__gregs[REG_PC]);
#elif defined(__s390__) && !defined(__s390x__)
return reinterpret_cast<void*>(context->uc_mcontext.psw.addr & 0x7fffffff);
#elif defined(__s390__) && defined(__s390x__)
return reinterpret_cast<void*>(context->uc_mcontext.psw.addr);
+#elif defined(__sh__)
+ return reinterpret_cast<void*>(context->uc_mcontext.pc);
+#elif defined(__sparc__) && !defined(__arch64__)
+ return reinterpret_cast<void*>(context->uc_mcontext.gregs[19]);
+#elif defined(__sparc__) && defined(__arch64__)
+ return reinterpret_cast<void*>(context->uc_mcontext.mc_gregs[19]);
#elif defined(__x86_64__)
if (16 < ABSL_ARRAYSIZE(context->uc_mcontext.gregs))
return reinterpret_cast<void*>(context->uc_mcontext.gregs[16]);
+#elif defined(__e2k__)
+ return reinterpret_cast<void*>(context->uc_mcontext.cr0_hi);
#else
#error "Undefined Architecture."
#endif
}
+#elif defined(__APPLE__)
+ if (vuc != nullptr) {
+ ucontext_t* signal_ucontext = reinterpret_cast<ucontext_t*>(vuc);
+#if defined(__aarch64__)
+ return reinterpret_cast<void*>(
+ __darwin_arm_thread_state64_get_pc(signal_ucontext->uc_mcontext->__ss));
+#elif defined(__arm__)
+#if __DARWIN_UNIX03
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__pc);
+#else
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.pc);
+#endif
+#elif defined(__i386__)
+#if __DARWIN_UNIX03
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__eip);
+#else
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.eip);
+#endif
+#elif defined(__x86_64__)
+#if __DARWIN_UNIX03
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->__ss.__rip);
+#else
+ return reinterpret_cast<void*>(signal_ucontext->uc_mcontext->ss.rip);
+#endif
+#endif
+ }
#elif defined(__akaros__)
auto* ctx = reinterpret_cast<struct user_context*>(vuc);
return reinterpret_cast<void*>(get_user_ctx_pc(ctx));
@@ -150,4 +199,5 @@ void DumpPCAndFrameSizesAndStackTrace(
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.h
index a16c03b2748..393369131f1 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/examine_stack.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,7 +17,10 @@
#ifndef ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
#define ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Returns the program counter from signal context, or nullptr if
@@ -33,6 +36,7 @@ void DumpPCAndFrameSizesAndStackTrace(
void (*writerfn)(const char*, void*), void* writerfn_arg);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_EXAMINE_STACK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.cc
index 2b3b972ea53..e3dd51c355a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,6 +27,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
namespace {
@@ -41,7 +42,8 @@ namespace {
// one of them is null, the results of p<q, p>q, p<=q, and p>=q are
// unspecified. Therefore, instead we hardcode the direction of the
// stack on platforms we know about.
-#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
+ defined(__aarch64__)
constexpr bool kStackGrowsDown = true;
#else
#error Need to define kStackGrowsDown
@@ -115,10 +117,11 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) {
// Set up the alt-signal-stack (and save the older one).
stack_t sigstk;
memset(&sigstk, 0, sizeof(sigstk));
- stack_t old_sigstk;
sigstk.ss_sp = altstack;
sigstk.ss_size = kAlternateStackSize;
sigstk.ss_flags = 0;
+ stack_t old_sigstk;
+ memset(&old_sigstk, 0, sizeof(old_sigstk));
ABSL_RAW_CHECK(sigaltstack(&sigstk, &old_sigstk) == 0,
"sigaltstack() failed");
@@ -152,6 +155,15 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) {
int signal_handler_stack_consumption = GetStackConsumption(altstack);
// Now restore the old alt-signal-stack and signal handlers.
+ if (old_sigstk.ss_sp == nullptr && old_sigstk.ss_size == 0 &&
+ (old_sigstk.ss_flags & SS_DISABLE)) {
+ // https://git.musl-libc.org/cgit/musl/commit/src/signal/sigaltstack.c?id=7829f42a2c8944555439380498ab8b924d0f2070
+ // The original stack has ss_size==0 and ss_flags==SS_DISABLE, but some
+ // versions of musl have a bug that rejects ss_size==0. Work around this by
+ // setting ss_size to MINSIGSTKSZ, which should be ignored by the kernel
+ // when SS_DISABLE is set.
+ old_sigstk.ss_size = MINSIGSTKSZ;
+ }
ABSL_RAW_CHECK(sigaltstack(&old_sigstk, nullptr) == 0,
"sigaltstack() failed");
ABSL_RAW_CHECK(sigaction(SIGUSR1, &old_sa1, nullptr) == 0,
@@ -167,6 +179,7 @@ int GetSignalHandlerStackConsumption(void (*signal_handler)(int)) {
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.h
index 4c5fa0f0d82..2b5e7151667 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,15 +18,19 @@
#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__))
+#elif !defined(__APPLE__) && !defined(_WIN32) && \
+ (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
+ defined(__aarch64__))
#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
@@ -38,6 +42,7 @@ namespace debugging_internal {
int GetSignalHandlerStackConsumption(void (*signal_handler)(int));
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption_test.cc
index 5ce3846ec44..80445bf43aa 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stack_consumption_test.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,6 +23,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
namespace {
@@ -43,6 +44,7 @@ TEST(SignalHandlerStackConsumptionTest, MeasuresStackConsumption) {
} // namespace
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
index 7ed6b3eb82d..f4859d7c210 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -37,8 +37,11 @@ static const unsigned char* GetKernelRtSigreturnAddress() {
absl::debugging_internal::VDSOSupport vdso;
if (vdso.IsPresent()) {
absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;
- if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", STT_FUNC,
- &symbol_info) ||
+ auto lookup = [&](int type) {
+ return vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", type,
+ &symbol_info);
+ };
+ if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||
symbol_info.address == nullptr) {
// Unexpected: VDSO is present, yet the expected symbol is missing
// or null.
@@ -74,6 +77,8 @@ static inline uintptr_t ComputeStackFrameSize(const T* low,
// checks (the strictness of which is controlled by the boolean parameter
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING, bool WITH_CONTEXT>
+ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer);
bool check_frame_size = true;
@@ -123,6 +128,8 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
}
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
+ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack.
+ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
const void *ucp, int *min_dropped_frames) {
#ifdef __GNUC__
@@ -180,11 +187,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return true;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_AARCH64_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
index c84083379bb..2a1bf2e8869 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
@@ -1,9 +1,18 @@
-// Copyright 2011 and onwards Google Inc.
-// All rights reserved.
+// Copyright 2017 The Abseil Authors.
//
-// Author: Doug Kwan
-// This is inspired by Craig Silverstein's PowerPC stacktrace code.
+// 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 is inspired by Craig Silverstein's PowerPC stacktrace code.
#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
@@ -113,11 +122,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return false;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_ARM_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_config.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_config.h
index 578e4968b00..cca410d4c75 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_config.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_config.h
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -21,6 +21,8 @@
#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
+#include "absl/base/config.h"
+
#if defined(ABSL_STACKTRACE_INL_HEADER)
#error ABSL_STACKTRACE_INL_HEADER cannot be directly set
@@ -28,43 +30,51 @@
#define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_win32-inl.inc"
+#elif defined(__APPLE__)
+#ifdef ABSL_HAVE_THREAD_LOCAL
+// Thread local support required for UnwindImpl.
+#define ABSL_STACKTRACE_INL_HEADER \
+ "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+
#elif defined(__linux__) && !defined(__ANDROID__)
-#if !defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__)
-#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_x86-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
+#if defined(NO_FRAME_POINTER) && \
+ (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
+// Note: The libunwind-based implementation is not available to open-source
+// users.
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-# elif defined(__aarch64__)
-#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-# elif defined(__arm__)
+ "absl/debugging/internal/stacktrace_libunwind-inl.inc"
+#define STACKTRACE_USES_LIBUNWIND 1
+#elif defined(NO_FRAME_POINTER) && defined(__has_include)
+#if __has_include(<execinfo.h>)
// Note: When using glibc this may require -funwind-tables to function properly.
#define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+#endif
+#elif defined(__i386__) || defined(__x86_64__)
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#else // defined(NO_FRAME_POINTER)
-# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
+ "absl/debugging/internal/stacktrace_x86-inl.inc"
+#elif defined(__ppc__) || defined(__PPC__)
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_generic-inl.inc"
-# elif defined(__ppc__) || defined(__PPC__)
+ "absl/debugging/internal/stacktrace_powerpc-inl.inc"
+#elif defined(__aarch64__)
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_generic-inl.inc"
-# else
+ "absl/debugging/internal/stacktrace_aarch64-inl.inc"
+#elif defined(__has_include)
+#if __has_include(<execinfo.h>)
+// Note: When using glibc this may require -funwind-tables to function properly.
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-# endif
-#endif // NO_FRAME_POINTER
+ "absl/debugging/internal/stacktrace_generic-inl.inc"
+#endif
+#endif
-#else
+#endif
+
+// Fallback to the empty implementation.
+#if !defined(ABSL_STACKTRACE_INL_HEADER)
#define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
-
#endif
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
index 08b87bd6ae3..b2792a1f3ad 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -1,7 +1,16 @@
-// Copyright 2000 - 2007 Google Inc.
-// All rights reserved.
+// Copyright 2017 The Abseil Authors.
//
-// Author: Sanjay Ghemawat
+// 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.
//
// Portable implementation - just use glibc
//
@@ -12,13 +21,48 @@
#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
#include <execinfo.h>
+#include <atomic>
#include <cstring>
#include "absl/debugging/stacktrace.h"
+#include "absl/base/attributes.h"
+
+// Sometimes, we can try to get a stack trace from within a stack
+// trace, because we don't block signals inside this code (which would be too
+// expensive: the two extra system calls per stack trace do matter here).
+// That can cause a self-deadlock.
+// Protect against such reentrant call by failing to get a stack trace.
+//
+// We use __thread here because the code here is extremely low level -- it is
+// called while collecting stack traces from within malloc and mmap, and thus
+// can not call anything which might call malloc or mmap itself.
+static __thread int recursive = 0;
+
+// The stack trace function might be invoked very early in the program's
+// execution (e.g. from the very first malloc if using tcmalloc). Also, the
+// glibc implementation itself will trigger malloc the first time it is called.
+// As such, we suppress usage of backtrace during this early stage of execution.
+static std::atomic<bool> disable_stacktraces(true); // Disabled until healthy.
+// Waiting until static initializers run seems to be late enough.
+// This file is included into stacktrace.cc so this will only run once.
+ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
+ void* unused_stack[1];
+ // Force the first backtrace to happen early to get the one-time shared lib
+ // loading (allocation) out of the way. After the first call it is much safer
+ // to use backtrace from a signal handler if we crash somewhere later.
+ backtrace(unused_stack, 1);
+ disable_stacktraces.store(false, std::memory_order_relaxed);
+ return 0;
+}();
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
const void *ucp, int *min_dropped_frames) {
+ if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
+ return 0;
+ }
+ ++recursive;
+
static_cast<void>(ucp); // Unused.
static const int kStackLength = 64;
void * stack[kStackLength];
@@ -46,15 +90,19 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
}
}
+ --recursive;
+
return result_count;
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return true;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
index 860ac2b3e58..cf8c05160c5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,8 +14,8 @@
//
// Produce stack trace. I'm guessing (hoping!) the code is much like
// for x86. For apple machines, at least, it seems to be; see
-// http://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
-// http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
+// https://developer.apple.com/documentation/mac/runtimehtml/RTArch-59.html
+// https://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK
// Linux has similar code: http://patchwork.ozlabs.org/linuxppc/patch?id=8882
#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
@@ -131,7 +131,12 @@ static void **NextStackFrame(void **old_sp, const void *uc) {
const ucontext_t* signal_context =
reinterpret_cast<const ucontext_t*>(uc);
void **const sp_before_signal =
- reinterpret_cast<void**>(signal_context->uc_mcontext.gp_regs[PT_R1]);
+#if defined(__PPC64__)
+ reinterpret_cast<void **>(signal_context->uc_mcontext.gp_regs[PT_R1]);
+#else
+ reinterpret_cast<void **>(
+ signal_context->uc_mcontext.uc_regs->gregs[PT_R1]);
+#endif
// Check that alleged sp before signal is nonnull and is reasonably
// aligned.
if (sp_before_signal != nullptr &&
@@ -162,7 +167,7 @@ ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
const void *ucp, int *min_dropped_frames) {
void **sp;
- // Apple OS X uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
+ // Apple macOS uses an old version of gnu as -- both Darwin 7.9.0 (Panther)
// and Darwin 8.8.1 (Tiger) use as 1.38. This means we have to use a
// different asm syntax. I don't know quite the best way to discriminate
// systems using the old as from the new one; I've gone with __APPLE__.
@@ -236,11 +241,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return true;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_POWERPC_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc
index e256fdd4ae7..5b8fb191b65 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_unimplemented-inl.inc
@@ -12,11 +12,13 @@ static int UnwindImpl(void** /* result */, int* /* sizes */,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return false;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_UNIMPLEMENTED_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
index a8f8a56afb3..1c666c8b561 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -32,7 +32,7 @@
// server.
//
// This code is inspired by a patch from David Vitek:
-// http://code.google.com/p/google-perftools/issues/detail?id=83
+// https://code.google.com/p/google-perftools/issues/detail?id=83
#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
@@ -46,15 +46,23 @@ typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
OUT PVOID *backtrace,
OUT PULONG backtrace_hash);
+// It is not possible to load RtlCaptureStackBackTrace at static init time in
+// UWP. CaptureStackBackTrace is the public version of RtlCaptureStackBackTrace
+#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && \
+ !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
+ &::CaptureStackBackTrace;
+#else
// Load the function we need at static init time, where we don't have
// to worry about someone else holding the loader's lock.
static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
- (RtlCaptureStackBackTrace_Function*)
- GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+ (RtlCaptureStackBackTrace_Function*)GetProcAddress(
+ GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
- const void *ucp, int *min_dropped_frames) {
+ const void*, int* min_dropped_frames) {
int n = 0;
if (!RtlCaptureStackBackTrace_fn) {
// can't find a stacktrace with no function to call
@@ -73,11 +81,13 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return false;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_WIN32_INL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
index ac85b920332..bc320ff75bc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -33,8 +33,11 @@
#include "absl/debugging/internal/address_is_readable.h"
#include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems
#include "absl/debugging/stacktrace.h"
+
#include "absl/base/internal/raw_logging.h"
+using absl::debugging_internal::AddressIsReadable;
+
#if defined(__linux__) && defined(__i386__)
// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
// preceeding "syscall" or "sysenter".
@@ -80,7 +83,7 @@ static int CountPushInstructions(const unsigned char *const addr) {
// "mov reg,reg"
if (addr[i + 1] == 0xE5) {
// Found "mov %esp,%ebp".
- return 0;
+ return 0;
}
++i; // Skip register encoding byte.
} else if (addr[i] == 0x0F &&
@@ -170,6 +173,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
static const unsigned char *kernel_rt_sigreturn_address = nullptr;
static const unsigned char *kernel_vsyscall_address = nullptr;
if (num_push_instructions == -1) {
+#ifdef ABSL_HAVE_VDSO_SUPPORT
absl::debugging_internal::VDSOSupport vdso;
if (vdso.IsPresent()) {
absl::debugging_internal::VDSOSupport::SymbolInfo
@@ -198,6 +202,9 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
} else {
num_push_instructions = 0;
}
+#else // ABSL_HAVE_VDSO_SUPPORT
+ num_push_instructions = 0;
+#endif // ABSL_HAVE_VDSO_SUPPORT
}
if (num_push_instructions != 0 && kernel_rt_sigreturn_address != nullptr &&
old_fp[1] == kernel_rt_sigreturn_address) {
@@ -221,7 +228,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
// "double fault" in case we hit the first fault due to e.g. stack
// corruption.
void *const reg_esp2 = reg_esp[num_push_instructions - 1];
- if (absl::debugging_internal::AddressIsReadable(reg_esp2)) {
+ if (AddressIsReadable(reg_esp2)) {
// Alleged %esp is readable, use it for further unwinding.
new_fp = reinterpret_cast<void **>(reg_esp2);
}
@@ -273,7 +280,7 @@ static void **NextStackFrame(void **old_fp, const void *uc) {
// Note: NextStackFrame<false>() is only called while the program
// is already on its last leg, so it's ok to be slow here.
- if (!absl::debugging_internal::AddressIsReadable(new_fp)) {
+ if (!AddressIsReadable(new_fp)) {
return nullptr;
}
}
@@ -327,11 +334,13 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
}
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
bool StackTraceWorksForTest() {
return true;
}
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_X86_INL_INC_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/symbolize.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/symbolize.h
index 8d926fec48a..4f26130fbb7 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/symbolize.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/symbolize.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,9 +18,13 @@
#ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
#define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
+#ifdef __cplusplus
+
#include <cstddef>
#include <cstdint>
-#include "absl/base/port.h" // Needed for string vs std::string
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
#error ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE cannot be directly set
@@ -34,6 +38,7 @@
#include <string>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// Iterates over all sections, invoking callback on each with the section name
@@ -42,9 +47,9 @@ namespace debugging_internal {
// Returns true on success; otherwise returns false in case of errors.
//
// This is not async-signal-safe.
-bool ForEachSection(
- int fd, const std::function<bool(const std::string& name, const ElfW(Shdr) &)>&
- callback);
+bool ForEachSection(int fd,
+ const std::function<bool(absl::string_view name,
+ const ElfW(Shdr) &)>& callback);
// Gets the section header for the given name, if it exists. Returns true on
// success. Otherwise, returns false.
@@ -52,11 +57,19 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
ElfW(Shdr) *out);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#ifdef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
+#error ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE cannot be directly set
+#elif defined(__APPLE__)
+#define ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE 1
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
struct SymbolDecoratorArgs {
@@ -105,19 +118,30 @@ bool RemoveAllSymbolDecorators(void);
// filename != nullptr
//
// Returns true if the file was successfully registered.
-bool RegisterFileMappingHint(
- const void* start, const void* end, uint64_t offset, const char* filename);
+bool RegisterFileMappingHint(const void* start, const void* end,
+ uint64_t offset, const char* filename);
// Looks up the file mapping registered by RegisterFileMappingHint for an
// address range. If there is one, the file name is stored in *filename and
// *start and *end are modified to reflect the registered mapping. Returns
// whether any hint was found.
-bool GetFileMappingHint(const void** start,
- const void** end,
- uint64_t * offset,
+bool GetFileMappingHint(const void** start, const void** end, uint64_t* offset,
const char** filename);
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
+#endif // __cplusplus
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C"
+#endif // __cplusplus
+
+ bool
+ AbslInternalGetFileMappingHint(const void** start, const void** end,
+ uint64_t* offset, const char** filename);
+
#endif // ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.cc
index 44ec7c02f51..6be16d90727 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -38,6 +38,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
ABSL_CONST_INIT
@@ -75,15 +76,6 @@ const void *VDSOSupport::Init() {
}
#endif // __GLIBC_PREREQ(2, 16)
if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
- // Valgrind zaps AT_SYSINFO_EHDR and friends from the auxv[]
- // on stack, and so glibc works as if VDSO was not present.
- // But going directly to kernel via /proc/self/auxv below bypasses
- // Valgrind zapping. So we check for Valgrind separately.
- if (RunningOnValgrind()) {
- vdso_base_.store(nullptr, std::memory_order_relaxed);
- getcpu_fn_.store(&GetCPUViaSyscall, std::memory_order_relaxed);
- return nullptr;
- }
int fd = open("/proc/self/auxv", O_RDONLY);
if (fd == -1) {
// Kernel too old to have a VDSO.
@@ -174,19 +166,8 @@ int GetCPU() {
return ret_code == 0 ? cpu : ret_code;
}
-// We need to make sure VDSOSupport::Init() is called before
-// InitGoogle() does any setuid or chroot calls. If VDSOSupport
-// is used in any global constructor, this will happen, since
-// VDSOSupport's constructor calls Init. But if not, we need to
-// ensure it here, with a global constructor of our own. This
-// is an allowed exception to the normal rule against non-trivial
-// global constructors.
-static class VDSOInitHelper {
- public:
- VDSOInitHelper() { VDSOSupport::Init(); }
-} vdso_init_helper;
-
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HAVE_VDSO_SUPPORT
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.h
index 8002c7405fa..6562c6c2350 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/internal/vdso_support.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -53,6 +53,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
// NOTE: this class may be used from within tcmalloc, and can not
@@ -149,6 +150,7 @@ class VDSOSupport {
int GetCPU();
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HAVE_ELF_MEM_IMAGE
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.cc
index e01e5f8c937..764ca0ad008 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.cc
@@ -4,36 +4,56 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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.
+
// Wrappers around lsan_interface functions.
// When lsan is not linked in, these functions are not available,
// therefore Abseil code which depends on these functions is conditioned on the
// definition of LEAK_SANITIZER.
+#include "absl/base/attributes.h"
#include "absl/debugging/leak_check.h"
#ifndef LEAK_SANITIZER
namespace absl {
+ABSL_NAMESPACE_BEGIN
bool HaveLeakSanitizer() { return false; }
+bool LeakCheckerIsActive() { return false; }
void DoIgnoreLeak(const void*) { }
void RegisterLivePointers(const void*, size_t) { }
void UnRegisterLivePointers(const void*, size_t) { }
LeakCheckDisabler::LeakCheckDisabler() { }
LeakCheckDisabler::~LeakCheckDisabler() { }
+ABSL_NAMESPACE_END
} // namespace absl
#else
#include <sanitizer/lsan_interface.h>
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+extern "C" ABSL_ATTRIBUTE_WEAK int __lsan_is_turned_off();
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
bool HaveLeakSanitizer() { return true; }
+
+#if ABSL_HAVE_ATTRIBUTE_WEAK
+bool LeakCheckerIsActive() {
+ return !(&__lsan_is_turned_off && __lsan_is_turned_off());
+}
+#else
+bool LeakCheckerIsActive() { return true; }
+#endif
+
+bool FindAndReportLeaks() { return __lsan_do_recoverable_leak_check(); }
void DoIgnoreLeak(const void* ptr) { __lsan_ignore_object(ptr); }
void RegisterLivePointers(const void* ptr, size_t size) {
__lsan_register_root_region(ptr, size);
@@ -43,6 +63,7 @@ void UnRegisterLivePointers(const void* ptr, size_t size) {
}
LeakCheckDisabler::LeakCheckDisabler() { __lsan_disable(); }
LeakCheckDisabler::~LeakCheckDisabler() { __lsan_enable(); }
+ABSL_NAMESPACE_END
} // namespace absl
#endif // LEAK_SANITIZER
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.h
index c930684e959..5fc2b052e41 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -32,7 +32,10 @@
#include <cstddef>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
// HaveLeakSanitizer()
//
@@ -40,6 +43,12 @@ namespace absl {
// currently built into this target.
bool HaveLeakSanitizer();
+// LeakCheckerIsActive()
+//
+// Returns true if a leak-checking sanitizer (either ASan or standalone LSan) is
+// currently built into this target and is turned on.
+bool LeakCheckerIsActive();
+
// DoIgnoreLeak()
//
// Implements `IgnoreLeak()` below. This function should usually
@@ -59,7 +68,8 @@ void DoIgnoreLeak(const void* ptr);
//
// If the passed `ptr` does not point to an actively allocated object at the
// time `IgnoreLeak()` is called, the call is a no-op; if it is actively
-// allocated, the object must not get deallocated later.
+// allocated, leak sanitizer will assume this object is referenced even if
+// there is no actual reference in user memory.
//
template <typename T>
T* IgnoreLeak(T* ptr) {
@@ -67,6 +77,19 @@ T* IgnoreLeak(T* ptr) {
return ptr;
}
+// FindAndReportLeaks()
+//
+// If any leaks are detected, prints a leak report and returns true. This
+// function may be called repeatedly, and does not affect end-of-process leak
+// checking.
+//
+// Example:
+// if (FindAndReportLeaks()) {
+// ... diagnostic already printed. Exit with failure code.
+// exit(1)
+// }
+bool FindAndReportLeaks();
+
// LeakCheckDisabler
//
// This helper class indicates that any heap allocations done in the code block
@@ -104,6 +127,7 @@ void RegisterLivePointers(const void* ptr, size_t size);
// `RegisterLivePointers()`, enabling leak checking of those pointers.
void UnRegisterLivePointers(const void* ptr, size_t size);
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_LEAK_CHECK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_disable.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_disable.cc
index df22c1cae91..924d6e3d543 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_disable.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_disable.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_fail_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_fail_test.cc
index bf541fe8415..c49b81a9d9e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_fail_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_fail_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,7 +25,7 @@ TEST(LeakCheckTest, LeakMemory) {
// failed exit code.
char* foo = strdup("lsan should complain about this leaked string");
- ABSL_RAW_LOG(INFO, "Should detect leaked std::string %s", foo);
+ ABSL_RAW_LOG(INFO, "Should detect leaked string %s", foo);
}
TEST(LeakCheckTest, LeakMemoryAfterDisablerScope) {
@@ -34,7 +34,7 @@ TEST(LeakCheckTest, LeakMemoryAfterDisablerScope) {
// failed exit code.
{ absl::LeakCheckDisabler disabler; }
char* foo = strdup("lsan should also complain about this leaked string");
- ABSL_RAW_LOG(INFO, "Re-enabled leak detection.Should detect leaked std::string %s",
+ ABSL_RAW_LOG(INFO, "Re-enabled leak detection.Should detect leaked string %s",
foo);
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_test.cc
index febd1ee4f92..9fcfc8e50b4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/leak_check_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,20 +23,22 @@ namespace {
TEST(LeakCheckTest, DetectLeakSanitizer) {
#ifdef ABSL_EXPECT_LEAK_SANITIZER
EXPECT_TRUE(absl::HaveLeakSanitizer());
+ EXPECT_TRUE(absl::LeakCheckerIsActive());
#else
EXPECT_FALSE(absl::HaveLeakSanitizer());
+ EXPECT_FALSE(absl::LeakCheckerIsActive());
#endif
}
TEST(LeakCheckTest, IgnoreLeakSuppressesLeakedMemoryErrors) {
auto foo = absl::IgnoreLeak(new std::string("some ignored leaked string"));
- ABSL_RAW_LOG(INFO, "Ignoring leaked std::string %s", foo->c_str());
+ ABSL_RAW_LOG(INFO, "Ignoring leaked string %s", foo->c_str());
}
TEST(LeakCheckTest, LeakCheckDisablerIgnoresLeak) {
absl::LeakCheckDisabler disabler;
- auto foo = new std::string("some std::string leaked while checks are disabled");
- ABSL_RAW_LOG(INFO, "Ignoring leaked std::string %s", foo->c_str());
+ auto foo = new std::string("some string leaked while checks are disabled");
+ ABSL_RAW_LOG(INFO, "Ignoring leaked string %s", foo->c_str());
}
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.cc
index 7bbd65ac90e..1f7c7d82b2d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -46,6 +46,7 @@
#include ABSL_STACKTRACE_INL_HEADER
#else
# error Cannot calculate stack trace: will need to write for your environment
+
# include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
# include "absl/debugging/internal/stacktrace_arm-inl.inc"
# include "absl/debugging/internal/stacktrace_generic-inl.inc"
@@ -56,6 +57,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
typedef int (*Unwinder)(void**, int*, int, int, const void*, int*);
@@ -134,4 +136,5 @@ int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip,
return n;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.h
index 8b831e26815..0ec0ffdabd4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/stacktrace.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -31,15 +31,18 @@
#ifndef ABSL_DEBUGGING_STACKTRACE_H_
#define ABSL_DEBUGGING_STACKTRACE_H_
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
// GetStackFrames()
//
// Records program counter values for up to `max_depth` frames, skipping the
-// most recent `skip_count` stack frames, and stores their corresponding values
-// and sizes in `results` and `sizes` buffers. (Note that the frame generated
-// for the `absl::GetStackFrames()` routine itself is also skipped.)
-// routine itself.
+// most recent `skip_count` stack frames, stores their corresponding values
+// and sizes in `results` and `sizes` buffers, and returns the number of frames
+// stored. (Note that the frame generated for the `absl::GetStackFrames()`
+// routine itself is also skipped.)
//
// Example:
//
@@ -54,8 +57,8 @@ namespace absl {
// The current stack frame would consist of three function calls: `bar()`,
// `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets
// `skip_count` to `1`, it will skip the frame for `bar()`, the most recently
-// invoked function call. It will therefore return two program counters and will
-// produce values that map to the following function calls:
+// invoked function call. It will therefore return 2 and fill `result` with
+// program counters within the following functions:
//
// result[0] foo()
// result[1] main()
@@ -82,9 +85,10 @@ extern int GetStackFrames(void** result, int* sizes, int max_depth,
//
// Records program counter values obtained from a signal handler. Records
// program counter values for up to `max_depth` frames, skipping the most recent
-// `skip_count` stack frames, and stores their corresponding values and sizes in
-// `results` and `sizes` buffers. (Note that the frame generated for the
-// `absl::GetStackFramesWithContext()` routine itself is also skipped.)
+// `skip_count` stack frames, stores their corresponding values and sizes in
+// `results` and `sizes` buffers, and returns the number of frames stored. (Note
+// that the frame generated for the `absl::GetStackFramesWithContext()` routine
+// itself is also skipped.)
//
// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
// passed to a signal handler registered via the `sa_sigaction` field of a
@@ -105,8 +109,9 @@ extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
// GetStackTrace()
//
// Records program counter values for up to `max_depth` frames, skipping the
-// most recent `skip_count` stack frames, and stores their corresponding values
-// in `results`. Note that this function is similar to `absl::GetStackFrames()`
+// most recent `skip_count` stack frames, stores their corresponding values
+// in `results`, and returns the number of frames
+// stored. Note that this function is similar to `absl::GetStackFrames()`
// except that it returns the stack trace only, and not stack frame sizes.
//
// Example:
@@ -131,9 +136,9 @@ extern int GetStackTrace(void** result, int max_depth, int skip_count);
//
// Records program counter values obtained from a signal handler. Records
// program counter values for up to `max_depth` frames, skipping the most recent
-// `skip_count` stack frames, and stores their corresponding values in
-// `results`. (Note that the frame generated for the
-// `absl::GetStackFramesWithContext()` routine itself is also skipped.)
+// `skip_count` stack frames, stores their corresponding values in `results`,
+// and returns the number of frames stored. (Note that the frame generated for
+// the `absl::GetStackFramesWithContext()` routine itself is also skipped.)
//
// The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
// passed to a signal handler registered via the `sa_sigaction` field of a
@@ -220,6 +225,7 @@ namespace debugging_internal {
// working.
extern bool StackTraceWorksForTest();
} // namespace debugging_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_STACKTRACE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.cc
index a35e24cc29a..5e4a25d69dc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,15 +14,23 @@
#include "absl/debugging/symbolize.h"
+#ifdef _WIN32
+#include <winapifamily.h>
+#if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \
+ WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+// UWP doesn't have access to win32 APIs.
+#define ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32
+#endif
+#endif
+
#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE)
#include "absl/debugging/symbolize_elf.inc"
-#elif defined(_WIN32) && defined(_DEBUG)
-// The Windows Symbolizer only works in debug mode. Note that _DEBUG
-// is the macro that defines whether or not MS C-Runtime debug info is
-// available. Note that the PDB files containing the debug info must
-// also be available to the program at runtime for the symbolizer to
-// work.
+#elif defined(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
+// The Windows Symbolizer only works if PDB files containing the debug info
+// are available to the program at runtime.
#include "absl/debugging/symbolize_win32.inc"
+#elif defined(__APPLE__)
+#include "absl/debugging/symbolize_darwin.inc"
#else
#include "absl/debugging/symbolize_unimplemented.inc"
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.h
index 24e6e6471c6..43d93a86822 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -55,6 +55,7 @@
#include "absl/debugging/internal/symbolize.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// InitializeSymbolizer()
//
@@ -70,7 +71,7 @@ namespace absl {
// // Now you can use the symbolizer
// }
void InitializeSymbolizer(const char* argv0);
-
+//
// Symbolize()
//
// Symbolizes a program counter (instruction pointer value) `pc` and, on
@@ -88,10 +89,11 @@ void InitializeSymbolizer(const char* argv0);
// if (absl::Symbolize(pc, tmp, sizeof(tmp))) {
// symbol = tmp;
// }
-// absl::PrintF("%*p %s\n", pc, symbol);
+// absl::PrintF("%p %s\n", pc, symbol);
// }
bool Symbolize(const void *pc, char *out, int out_size);
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_DEBUGGING_SYMBOLIZE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_darwin.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_darwin.inc
new file mode 100644
index 00000000000..443ce9efc4c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_darwin.inc
@@ -0,0 +1,101 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cxxabi.h>
+#include <execinfo.h>
+
+#include <algorithm>
+#include <cstring>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/internal/demangle.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+void InitializeSymbolizer(const char*) {}
+
+namespace debugging_internal {
+namespace {
+
+static std::string GetSymbolString(absl::string_view backtrace_line) {
+ // Example Backtrace lines:
+ // 0 libimaging_shared.dylib 0x018c152a
+ // _ZNSt11_Deque_baseIN3nik7mediadb4PageESaIS2_EE17_M_initialize_mapEm + 3478
+ //
+ // or
+ // 0 libimaging_shared.dylib 0x0000000001895c39
+ // _ZN3nik4util19register_shared_ptrINS_3gpu7TextureEEEvPKvS5_ + 39
+ //
+ // or
+ // 0 mysterious_app 0x0124000120120009 main + 17
+ auto address_pos = backtrace_line.find(" 0x");
+ if (address_pos == absl::string_view::npos) return std::string();
+ absl::string_view symbol_view = backtrace_line.substr(address_pos + 1);
+
+ auto space_pos = symbol_view.find(" ");
+ if (space_pos == absl::string_view::npos) return std::string();
+ symbol_view = symbol_view.substr(space_pos + 1); // to mangled symbol
+
+ auto plus_pos = symbol_view.find(" + ");
+ if (plus_pos == absl::string_view::npos) return std::string();
+ symbol_view = symbol_view.substr(0, plus_pos); // strip remainng
+
+ return std::string(symbol_view);
+}
+
+} // namespace
+} // namespace debugging_internal
+
+bool Symbolize(const void* pc, char* out, int out_size) {
+ if (out_size <= 0 || pc == nullptr) {
+ out = nullptr;
+ return false;
+ }
+
+ // This allocates a char* array.
+ char** frame_strings = backtrace_symbols(const_cast<void**>(&pc), 1);
+
+ if (frame_strings == nullptr) return false;
+
+ std::string symbol = debugging_internal::GetSymbolString(frame_strings[0]);
+ free(frame_strings);
+
+ char tmp_buf[1024];
+ if (debugging_internal::Demangle(symbol.c_str(), tmp_buf, sizeof(tmp_buf))) {
+ size_t len = strlen(tmp_buf);
+ if (len + 1 <= static_cast<size_t>(out_size)) { // +1 for '\0'
+ assert(len < sizeof(tmp_buf));
+ memmove(out, tmp_buf, len + 1);
+ }
+ } else {
+ strncpy(out, symbol.c_str(), out_size);
+ }
+
+ if (out[out_size - 1] != '\0') {
+ // strncpy() does not '\0' terminate when it truncates.
+ static constexpr char kEllipsis[] = "...";
+ int ellipsis_size = std::min<int>(sizeof(kEllipsis) - 1, out_size - 1);
+ memcpy(out + out_size - ellipsis_size - 1, kEllipsis, ellipsis_size);
+ out[out_size - 1] = '\0';
+ }
+
+ return true;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_elf.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_elf.inc
index 97d767abf11..f4d5727bdeb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_elf.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_elf.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -57,6 +57,7 @@
#include <unistd.h>
#include <algorithm>
+#include <array>
#include <atomic>
#include <cerrno>
#include <cinttypes>
@@ -74,13 +75,21 @@
#include "absl/base/port.h"
#include "absl/debugging/internal/demangle.h"
#include "absl/debugging/internal/vdso_support.h"
+#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Value of argv[0]. Used by MaybeInitializeObjFile().
static char *argv0_value = nullptr;
void InitializeSymbolizer(const char *argv0) {
+#ifdef ABSL_HAVE_VDSO_SUPPORT
+ // We need to make sure VDSOSupport::Init() is called before any setuid or
+ // chroot calls, so InitializeSymbolizer() should be called very early in the
+ // life of a program.
+ absl::debugging_internal::VDSOSupport::Init();
+#endif
if (argv0_value != nullptr) {
free(argv0_value);
argv0_value = nullptr;
@@ -148,13 +157,15 @@ struct FileMappingHint {
// Moreover, we are using only TryLock(), if the decorator list
// is being modified (is busy), we skip all decorators, and possibly
// loose some info. Sorry, that's the best we could do.
-base_internal::SpinLock g_decorators_mu(base_internal::kLinkerInitialized);
+ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu(
+ absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
const int kMaxFileMappingHints = 8;
int g_num_file_mapping_hints;
FileMappingHint g_file_mapping_hints[kMaxFileMappingHints];
// Protects g_file_mapping_hints.
-base_internal::SpinLock g_file_mapping_mu(base_internal::kLinkerInitialized);
+ABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu(
+ absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
// Async-signal-safe function to zero a buffer.
// memset() is not guaranteed to be async-signal-safe.
@@ -174,6 +185,7 @@ struct ObjFile {
fd(-1),
elf_type(-1) {
SafeMemZero(&elf_header, sizeof(elf_header));
+ SafeMemZero(&phdr[0], sizeof(phdr));
}
char *filename;
@@ -186,6 +198,10 @@ struct ObjFile {
int fd;
int elf_type;
ElfW(Ehdr) elf_header;
+
+ // PT_LOAD program header describing executable code.
+ // Normally we expect just one, but SWIFT binaries have two.
+ std::array<ElfW(Phdr), 2> phdr;
};
// Build 4-way associative cache for symbols. Within each cache line, symbols
@@ -305,7 +321,7 @@ class Symbolizer {
char *tmp_buf, int tmp_buf_size);
enum {
- SYMBOL_BUF_SIZE = 2048,
+ SYMBOL_BUF_SIZE = 3072,
TMP_BUF_SIZE = 1024,
SYMBOL_CACHE_LINES = 128,
};
@@ -495,7 +511,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(
const int kMaxSectionNameLen = 64;
bool ForEachSection(int fd,
- const std::function<bool(const std::string &name,
+ const std::function<bool(absl::string_view name,
const ElfW(Shdr) &)> &callback) {
ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@@ -517,7 +533,7 @@ bool ForEachSection(int fd,
return false;
}
off_t name_offset = shstrtab.sh_offset + out.sh_name;
- char header_name[kMaxSectionNameLen + 1];
+ char header_name[kMaxSectionNameLen];
ssize_t n_read =
ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset);
if (n_read == -1) {
@@ -526,9 +542,8 @@ bool ForEachSection(int fd,
// Long read?
return false;
}
- header_name[n_read] = '\0';
- std::string name(header_name);
+ absl::string_view name(header_name, strnlen(header_name, n_read));
if (!callback(name, out)) {
break;
}
@@ -624,6 +639,13 @@ static bool InSection(const void *address, const ElfW(Shdr) * section) {
return start <= address && address < (start + size);
}
+static const char *ComputeOffset(const char *base, ptrdiff_t offset) {
+ // Note: cast to uintptr_t to avoid undefined behavior when base evaluates to
+ // zero and offset is non-zero.
+ return reinterpret_cast<const char *>(
+ reinterpret_cast<uintptr_t>(base) + offset);
+}
+
// Read a symbol table and look for the symbol containing the
// pc. Iterate over symbols in a symbol table and look for the symbol
// containing "pc". If the symbol is found, and its name fits in
@@ -676,7 +698,8 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// We keep the original address for opd redirection below.
const char *const original_start_address =
reinterpret_cast<const char *>(symbol.st_value);
- const char *start_address = original_start_address + relocation;
+ const char *start_address =
+ ComputeOffset(original_start_address, relocation);
if (deref_function_descriptor_pointer &&
InSection(original_start_address, opd)) {
@@ -688,8 +711,7 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// If pc is inside the .opd section, it points to a function descriptor.
const size_t size = pc_in_opd ? kFunctionDescriptorSize : symbol.st_size;
- const void *const end_address =
- reinterpret_cast<const char *>(start_address) + size;
+ const void *const end_address = ComputeOffset(start_address, size);
if (symbol.st_value != 0 && // Skip null value symbols.
symbol.st_shndx != 0 && // Skip undefined symbols.
#ifdef STT_TLS
@@ -762,37 +784,27 @@ FindSymbolResult Symbolizer::GetSymbolFromObjectFile(
}
}
- // Consult a regular symbol table first.
- if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum,
- obj.elf_header.e_shoff, SHT_SYMTAB, &symtab,
- tmp_buf, tmp_buf_size)) {
- return SYMBOL_NOT_FOUND;
- }
- if (!ReadFromOffsetExact(
- obj.fd, &strtab, sizeof(strtab),
- obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
- return SYMBOL_NOT_FOUND;
- }
- const FindSymbolResult rc =
- FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab,
- opd_ptr, tmp_buf, tmp_buf_size);
- if (rc != SYMBOL_NOT_FOUND) {
- return rc; // Found the symbol in a regular symbol table.
+ // Consult a regular symbol table, then fall back to the dynamic symbol table.
+ for (const auto symbol_table_type : {SHT_SYMTAB, SHT_DYNSYM}) {
+ if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum,
+ obj.elf_header.e_shoff, symbol_table_type,
+ &symtab, tmp_buf, tmp_buf_size)) {
+ continue;
+ }
+ if (!ReadFromOffsetExact(
+ obj.fd, &strtab, sizeof(strtab),
+ obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
+ continue;
+ }
+ const FindSymbolResult rc =
+ FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab,
+ opd_ptr, tmp_buf, tmp_buf_size);
+ if (rc != SYMBOL_NOT_FOUND) {
+ return rc;
+ }
}
- // If the symbol is not found, then consult a dynamic symbol table.
- if (!GetSectionHeaderByType(obj.fd, obj.elf_header.e_shnum,
- obj.elf_header.e_shoff, SHT_DYNSYM, &symtab,
- tmp_buf, tmp_buf_size)) {
- return SYMBOL_NOT_FOUND;
- }
- if (!ReadFromOffsetExact(
- obj.fd, &strtab, sizeof(strtab),
- obj.elf_header.e_shoff + symtab.sh_link * sizeof(symtab))) {
- return SYMBOL_NOT_FOUND;
- }
- return FindSymbol(pc, obj.fd, out, out_size, relocation, &strtab, &symtab,
- opd_ptr, tmp_buf, tmp_buf_size);
+ return SYMBOL_NOT_FOUND;
}
namespace {
@@ -925,6 +937,14 @@ static const char *GetHex(const char *start, const char *end,
return p;
}
+// Normally we are only interested in "r?x" maps.
+// On the PowerPC, function pointers point to descriptors in the .opd
+// section. The descriptors themselves are not executable code, so
+// we need to relax the check below to "r??".
+static bool ShouldUseMapping(const char *const flags) {
+ return flags[0] == 'r' && (kPlatformUsesOPDSections || flags[2] == 'x');
+}
+
// Read /proc/self/maps and run "callback" for each mmapped file found. If
// "callback" returns false, stop scanning and return true. Else continue
// scanning /proc/self/maps. Return true if no parse error is found.
@@ -994,12 +1014,8 @@ static ABSL_ATTRIBUTE_NOINLINE bool ReadAddrMap(
return false;
}
- // Check flags. Normally we are only interested in "r-x" maps. On
- // the PowerPC, function pointers point to descriptors in the .opd
- // section. The descriptors themselves are not executable code. So
- // we need to relax the check below to "r**".
- if (memcmp(flags_start, "r-x", 3) != 0 && // Not a "r-x" map.
- !(kPlatformUsesOPDSections && flags_start[0] == 'r')) {
+ // Check flags.
+ if (!ShouldUseMapping(flags_start)) {
continue; // We skip this map.
}
++cursor; // Skip ' '.
@@ -1262,6 +1278,36 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
ABSL_RAW_LOG(WARNING, "%s: failed to read elf header", obj->filename);
return false;
}
+ const int phnum = obj->elf_header.e_phnum;
+ const int phentsize = obj->elf_header.e_phentsize;
+ size_t phoff = obj->elf_header.e_phoff;
+ size_t num_executable_load_segments = 0;
+ for (int j = 0; j < phnum; j++) {
+ ElfW(Phdr) phdr;
+ if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
+ ABSL_RAW_LOG(WARNING, "%s: failed to read program header %d",
+ obj->filename, j);
+ return false;
+ }
+ phoff += phentsize;
+ constexpr int rx = PF_X | PF_R;
+ if (phdr.p_type != PT_LOAD || (phdr.p_flags & rx) != rx) {
+ // Not a LOAD segment, or not executable code.
+ continue;
+ }
+ if (num_executable_load_segments < obj->phdr.size()) {
+ memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
+ } else {
+ ABSL_RAW_LOG(WARNING, "%s: too many executable LOAD segments",
+ obj->filename);
+ break;
+ }
+ }
+ if (num_executable_load_segments == 0) {
+ // This object has no "r-x" LOAD segments. That's unexpected.
+ ABSL_RAW_LOG(WARNING, "%s: no executable LOAD segments", obj->filename);
+ return false;
+ }
}
return true;
}
@@ -1285,23 +1331,52 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
int fd = -1;
if (obj != nullptr) {
if (MaybeInitializeObjFile(obj)) {
- if (obj->elf_type == ET_DYN &&
- reinterpret_cast<uint64_t>(obj->start_addr) >= obj->offset) {
+ const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
+ if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
// This object was relocated.
//
// For obj->offset > 0, adjust the relocation since a mapping at offset
// X in the file will have a start address of [true relocation]+X.
- relocation = reinterpret_cast<ptrdiff_t>(obj->start_addr) - obj->offset;
+ relocation = start_addr - obj->offset;
+
+ // Note: some binaries have multiple "rx" LOAD segments. We must
+ // find the right one.
+ ElfW(Phdr) *phdr = nullptr;
+ for (size_t j = 0; j < obj->phdr.size(); j++) {
+ ElfW(Phdr) &p = obj->phdr[j];
+ if (p.p_type != PT_LOAD) {
+ // We only expect PT_LOADs. This must be PT_NULL that we didn't
+ // write over (i.e. we exhausted all interesting PT_LOADs).
+ ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
+ break;
+ }
+ if (pc < reinterpret_cast<void *>(start_addr + p.p_memsz)) {
+ phdr = &p;
+ break;
+ }
+ }
+ if (phdr == nullptr) {
+ // That's unexpected. Hope for the best.
+ ABSL_RAW_LOG(
+ WARNING,
+ "%s: unable to find LOAD segment for pc: %p, start_addr: %zx",
+ obj->filename, pc, start_addr);
+ } else {
+ // Adjust relocation in case phdr.p_vaddr != 0.
+ // This happens for binaries linked with `lld --rosegment`, and for
+ // binaries linked with BFD `ld -z separate-code`.
+ relocation -= phdr->p_vaddr - phdr->p_offset;
+ }
}
fd = obj->fd;
- }
- if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
- sizeof(symbol_buf_), tmp_buf_,
- sizeof(tmp_buf_)) == SYMBOL_FOUND) {
- // Only try to demangle the symbol name if it fit into symbol_buf_.
- DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
- sizeof(tmp_buf_));
+ if (GetSymbolFromObjectFile(*obj, pc, relocation, symbol_buf_,
+ sizeof(symbol_buf_), tmp_buf_,
+ sizeof(tmp_buf_)) == SYMBOL_FOUND) {
+ // Only try to demangle the symbol name if it fit into symbol_buf_.
+ DemangleInplace(symbol_buf_, sizeof(symbol_buf_), tmp_buf_,
+ sizeof(tmp_buf_));
+ }
}
} else {
#if ABSL_HAVE_VDSO_SUPPORT
@@ -1372,7 +1447,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
if (!g_decorators_mu.TryLock()) {
// Someone else is using decorators. Get out.
- return false;
+ return -2;
}
int ret = ticket;
if (g_num_decorators >= kMaxDecorators) {
@@ -1400,7 +1475,7 @@ bool RegisterFileMappingHint(const void *start, const void *end, uint64_t offset
if (g_num_file_mapping_hints >= kMaxFileMappingHints) {
ret = false;
} else {
- // TODO(ckennelly): Move this into a std::string copy routine.
+ // TODO(ckennelly): Move this into a string copy routine.
int len = strlen(filename);
char *dst = static_cast<char *>(
base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
@@ -1451,7 +1526,7 @@ bool GetFileMappingHint(const void **start, const void **end, uint64_t *offset,
bool Symbolize(const void *pc, char *out, int out_size) {
// Symbolization is very slow under tsan.
- ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
SAFE_ASSERT(out_size >= 0);
debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
const char *name = s->GetSymbol(pc);
@@ -1470,8 +1545,16 @@ bool Symbolize(const void *pc, char *out, int out_size) {
}
}
debugging_internal::FreeSymbolizer(s);
- ANNOTATE_IGNORE_READS_AND_WRITES_END();
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
return ok;
}
+ABSL_NAMESPACE_END
} // namespace absl
+
+extern "C" bool AbslInternalGetFileMappingHint(const void **start,
+ const void **end, uint64_t *offset,
+ const char **filename) {
+ return absl::debugging_internal::GetFileMappingHint(start, end, offset,
+ filename);
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_test.cc
index 8029fbe9d2e..a2dd4956c49 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,18 +27,39 @@
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/base/casts.h"
+#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/optimization.h"
#include "absl/debugging/internal/stack_consumption.h"
#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
using testing::Contains;
+#ifdef _WIN32
+#define ABSL_SYMBOLIZE_TEST_NOINLINE __declspec(noinline)
+#else
+#define ABSL_SYMBOLIZE_TEST_NOINLINE ABSL_ATTRIBUTE_NOINLINE
+#endif
+
// Functions to symbolize. Use C linkage to avoid mangled names.
extern "C" {
-void nonstatic_func() { ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); }
-static void static_func() { ABSL_BLOCK_TAIL_CALL_OPTIMIZATION(); }
+ABSL_SYMBOLIZE_TEST_NOINLINE void nonstatic_func() {
+ // The next line makes this a unique function to prevent the compiler from
+ // folding identical functions together.
+ volatile int x = __LINE__;
+ static_cast<void>(x);
+ ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+}
+
+ABSL_SYMBOLIZE_TEST_NOINLINE static void static_func() {
+ // The next line makes this a unique function to prevent the compiler from
+ // folding identical functions together.
+ volatile int x = __LINE__;
+ static_cast<void>(x);
+ ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
+}
} // extern "C"
struct Foo {
@@ -46,7 +67,11 @@ struct Foo {
};
// A C++ method that should have a mangled name.
-void ABSL_ATTRIBUTE_NOINLINE Foo::func(int) {
+ABSL_SYMBOLIZE_TEST_NOINLINE void Foo::func(int) {
+ // The next line makes this a unique function to prevent the compiler from
+ // folding identical functions together.
+ volatile int x = __LINE__;
+ static_cast<void>(x);
ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
}
@@ -80,6 +105,7 @@ static ABSL_PER_THREAD_TLS_KEYWORD char
symbolize_test_thread_big[2 * 1024 * 1024];
#endif
+#if !defined(__EMSCRIPTEN__)
// Used below to hopefully inhibit some compiler/linker optimizations
// that may remove kHpageTextPadding, kPadding0, and kPadding1 from
// the binary.
@@ -89,6 +115,7 @@ static volatile bool volatile_bool = false;
static constexpr size_t kHpageSize = 1 << 21;
const char kHpageTextPadding[kHpageSize * 4] ABSL_ATTRIBUTE_SECTION_VARIABLE(
.text) = "";
+#endif // !defined(__EMSCRIPTEN__)
static char try_symbolize_buffer[4096];
@@ -107,7 +134,8 @@ static const char *TrySymbolizeWithLimit(void *pc, int limit) {
ABSL_RAW_CHECK(strnlen(heap_buffer.get(), limit) < limit,
"absl::Symbolize() did not properly terminate the string");
strncpy(try_symbolize_buffer, heap_buffer.get(),
- sizeof(try_symbolize_buffer));
+ sizeof(try_symbolize_buffer) - 1);
+ try_symbolize_buffer[sizeof(try_symbolize_buffer) - 1] = '\0';
}
return found ? try_symbolize_buffer : nullptr;
@@ -118,7 +146,8 @@ static const char *TrySymbolize(void *pc) {
return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));
}
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+ defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
TEST(Symbolize, Cached) {
// Compilers should give us pointers to them.
@@ -192,8 +221,8 @@ static const char *SymbolizeStackConsumption(void *pc, int *stack_consumed) {
static int GetStackConsumptionUpperLimit() {
// Symbolize stack consumption should be within 2kB.
int stack_consumption_upper_limit = 2048;
-#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
- defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
+ defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_consumption_upper_limit *= 5;
#endif
@@ -232,6 +261,7 @@ TEST(Symbolize, SymbolizeWithDemanglingStackConsumption) {
#endif // ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
+#ifndef ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
// Use a 64K page size for PPC.
const size_t kPageSize = 64 << 10;
// We place a read-only symbols into the .text section and verify that we can
@@ -373,8 +403,8 @@ TEST(Symbolize, ForEachSection) {
std::vector<std::string> sections;
ASSERT_TRUE(absl::debugging_internal::ForEachSection(
- fd, [&sections](const std::string &name, const ElfW(Shdr) &) {
- sections.push_back(name);
+ fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {
+ sections.emplace_back(name);
return true;
}));
@@ -387,21 +417,26 @@ TEST(Symbolize, ForEachSection) {
close(fd);
}
+#endif // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
// x86 specific tests. Uses some inline assembler.
extern "C" {
inline void *ABSL_ATTRIBUTE_ALWAYS_INLINE inline_func() {
void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
- __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+ __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+ __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
#endif
return pc;
}
void *ABSL_ATTRIBUTE_NOINLINE non_inline_func() {
void *pc = nullptr;
-#if defined(__i386__) || defined(__x86_64__)
- __asm__ __volatile__("call 1f; 1: pop %0" : "=r"(pc));
+#if defined(__i386__)
+ __asm__ __volatile__("call 1f;\n 1: pop %[PC]" : [ PC ] "=r"(pc));
+#elif defined(__x86_64__)
+ __asm__ __volatile__("leaq 0(%%rip),%[PC];\n" : [ PC ] "=r"(pc));
#endif
return pc;
}
@@ -442,14 +477,15 @@ void ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {
#endif
}
-#elif defined(_WIN32) && defined(_DEBUG)
+#elif defined(_WIN32)
+#if !defined(ABSL_CONSUME_DLL)
TEST(Symbolize, Basics) {
EXPECT_STREQ("nonstatic_func", TrySymbolize((void *)(&nonstatic_func)));
// The name of an internal linkage symbol is not specified; allow either a
// mangled or an unmangled name here.
- const char* static_func_symbol = TrySymbolize((void *)(&static_func));
+ const char *static_func_symbol = TrySymbolize((void *)(&static_func));
ASSERT_TRUE(static_func_symbol != nullptr);
EXPECT_TRUE(strstr(static_func_symbol, "static_func") != nullptr);
@@ -476,11 +512,12 @@ TEST(Symbolize, Truncation) {
}
TEST(Symbolize, SymbolizeWithDemangling) {
- const char* result = TrySymbolize((void *)(&Foo::func));
+ const char *result = TrySymbolize((void *)(&Foo::func));
ASSERT_TRUE(result != nullptr);
EXPECT_TRUE(strstr(result, "Foo::func") != nullptr) << result;
}
+#endif // !defined(ABSL_CONSUME_DLL)
#else // Symbolizer unimplemented
TEST(Symbolize, Unimplemented) {
@@ -493,10 +530,12 @@ TEST(Symbolize, Unimplemented) {
#endif
int main(int argc, char **argv) {
+#if !defined(__EMSCRIPTEN__)
// Make sure kHpageTextPadding is linked into the binary.
if (volatile_bool) {
ABSL_RAW_LOG(INFO, "%s", kHpageTextPadding);
}
+#endif // !defined(__EMSCRIPTEN__)
#if ABSL_PER_THREAD_TLS
// Touch the per-thread variables.
@@ -507,7 +546,8 @@ int main(int argc, char **argv) {
absl::InitializeSymbolizer(argv[0]);
testing::InitGoogleTest(&argc, argv);
-#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
+#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
+ defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
TestWithPCInsideInlineFunction();
TestWithPCInsideNonInlineFunction();
TestWithReturnAddress();
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_unimplemented.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_unimplemented.inc
index 2a3f4acb0e1..db24456b0af 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_unimplemented.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_unimplemented.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
@@ -26,10 +27,14 @@ bool RemoveAllSymbolDecorators(void) { return false; }
bool RegisterFileMappingHint(const void *, const void *, uint64_t, const char *) {
return false;
}
+bool GetFileMappingHint(const void **, const void **, uint64_t *, const char **) {
+ return false;
+}
} // namespace debugging_internal
void InitializeSymbolizer(const char*) {}
bool Symbolize(const void *, char *, int) { return false; }
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_win32.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_win32.inc
index e3fff74d493..c3df46f606c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_win32.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/debugging/symbolize_win32.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,8 +16,14 @@
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms680578(v=vs.85).aspx
#include <windows.h>
-#include <DbgHelp.h>
-#pragma comment(lib, "DbgHelp")
+
+// MSVC header dbghelp.h has a warning for an ignored typedef.
+#pragma warning(push)
+#pragma warning(disable:4091)
+#include <dbghelp.h>
+#pragma warning(pop)
+
+#pragma comment(lib, "dbghelp.lib")
#include <algorithm>
#include <cstring>
@@ -25,10 +31,11 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
static HANDLE process = NULL;
-void InitializeSymbolizer(const char *argv0) {
+void InitializeSymbolizer(const char*) {
if (process != nullptr) {
return;
}
@@ -47,13 +54,12 @@ void InitializeSymbolizer(const char *argv0) {
}
}
-bool Symbolize(const void *pc, char *out, int out_size) {
+bool Symbolize(const void* pc, char* out, int out_size) {
if (out_size <= 0) {
return false;
}
- std::aligned_storage<sizeof(SYMBOL_INFO) + MAX_SYM_NAME,
- alignof(SYMBOL_INFO)>::type buf;
- SYMBOL_INFO *symbol = reinterpret_cast<SYMBOL_INFO *>(&buf);
+ alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME];
+ SYMBOL_INFO* symbol = reinterpret_cast<SYMBOL_INFO*>(buf);
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = MAX_SYM_NAME;
if (!SymFromAddr(process, reinterpret_cast<DWORD64>(pc), nullptr, symbol)) {
@@ -71,4 +77,5 @@ bool Symbolize(const void *pc, char *out, int out_size) {
return true;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/BUILD.bazel
new file mode 100644
index 00000000000..147249ed1bb
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/BUILD.bazel
@@ -0,0 +1,538 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "path_util",
+ hdrs = [
+ "internal/path_util.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/flags:__pkg__",
+ ],
+ deps = [
+ "//absl/base:config",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "program_name",
+ srcs = [
+ "internal/program_name.cc",
+ ],
+ hdrs = [
+ "internal/program_name.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/flags:__pkg__",
+ ],
+ deps = [
+ ":path_util",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ "//absl/synchronization",
+ ],
+)
+
+cc_library(
+ name = "config",
+ srcs = [
+ "usage_config.cc",
+ ],
+ hdrs = [
+ "config.h",
+ "usage_config.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":path_util",
+ ":program_name",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ "//absl/synchronization",
+ ],
+)
+
+cc_library(
+ name = "marshalling",
+ srcs = [
+ "marshalling.cc",
+ ],
+ hdrs = [
+ "marshalling.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:log_severity",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ ],
+)
+
+cc_library(
+ name = "commandlineflag_internal",
+ srcs = [
+ "internal/commandlineflag.cc",
+ ],
+ hdrs = [
+ "internal/commandlineflag.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:fast_type_id",
+ ],
+)
+
+cc_library(
+ name = "commandlineflag",
+ srcs = [
+ "commandlineflag.cc",
+ ],
+ hdrs = [
+ "commandlineflag.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":commandlineflag_internal",
+ "//absl/base:config",
+ "//absl/base:fast_type_id",
+ "//absl/strings",
+ "//absl/types:optional",
+ ],
+)
+
+cc_library(
+ name = "private_handle_accessor",
+ srcs = [
+ "internal/private_handle_accessor.cc",
+ ],
+ hdrs = [
+ "internal/private_handle_accessor.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/flags:__pkg__",
+ ],
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ "//absl/base:config",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "reflection",
+ srcs = [
+ "reflection.cc",
+ ],
+ hdrs = [
+ "internal/registry.h",
+ "reflection.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ ":config",
+ ":private_handle_accessor",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/container:flat_hash_map",
+ "//absl/strings",
+ "//absl/synchronization",
+ ],
+)
+
+cc_library(
+ name = "flag_internal",
+ srcs = [
+ "internal/flag.cc",
+ ],
+ hdrs = [
+ "internal/flag.h",
+ "internal/sequence_lock.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//absl/base:__subpackages__"],
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ ":config",
+ ":marshalling",
+ ":reflection",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/memory",
+ "//absl/meta:type_traits",
+ "//absl/strings",
+ "//absl/synchronization",
+ "//absl/utility",
+ ],
+)
+
+cc_library(
+ name = "flag",
+ srcs = [
+ "flag.cc",
+ ],
+ hdrs = [
+ "declare.h",
+ "flag.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":flag_internal",
+ ":reflection",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "usage_internal",
+ srcs = [
+ "internal/usage.cc",
+ ],
+ hdrs = [
+ "internal/usage.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/flags:__pkg__",
+ ],
+ deps = [
+ ":commandlineflag",
+ ":config",
+ ":flag",
+ ":flag_internal",
+ ":path_util",
+ ":private_handle_accessor",
+ ":program_name",
+ ":reflection",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "usage",
+ srcs = [
+ "usage.cc",
+ ],
+ hdrs = [
+ "usage.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":usage_internal",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ "//absl/synchronization",
+ ],
+)
+
+cc_library(
+ name = "parse",
+ srcs = ["parse.cc"],
+ hdrs = [
+ "internal/parse.h",
+ "parse.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ ":config",
+ ":flag",
+ ":flag_internal",
+ ":private_handle_accessor",
+ ":program_name",
+ ":reflection",
+ ":usage",
+ ":usage_internal",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/strings",
+ "//absl/synchronization",
+ ],
+)
+
+############################################################################
+# Unit tests in alphabetical order.
+
+cc_test(
+ name = "commandlineflag_test",
+ size = "small",
+ srcs = [
+ "commandlineflag_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":commandlineflag",
+ ":commandlineflag_internal",
+ ":config",
+ ":flag",
+ ":private_handle_accessor",
+ ":reflection",
+ "//absl/memory",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "config_test",
+ size = "small",
+ srcs = [
+ "config_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "flag_test",
+ size = "small",
+ srcs = [
+ "flag_test.cc",
+ "flag_test_defs.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":flag",
+ ":flag_internal",
+ ":marshalling",
+ ":reflection",
+ "//absl/base:core_headers",
+ "//absl/base:malloc_internal",
+ "//absl/strings",
+ "//absl/time",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_binary(
+ name = "flag_benchmark",
+ testonly = 1,
+ srcs = [
+ "flag_benchmark.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = select({
+ "//conditions:default": [],
+ }) + ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ "flag_benchmark.lds",
+ ":flag",
+ ":marshalling",
+ ":parse",
+ ":reflection",
+ "//absl/strings",
+ "//absl/time",
+ "//absl/types:optional",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
+cc_test(
+ name = "marshalling_test",
+ size = "small",
+ srcs = [
+ "marshalling_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":marshalling",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "parse_test",
+ size = "small",
+ srcs = [
+ "parse_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":flag",
+ ":parse",
+ ":reflection",
+ ":usage_internal",
+ "//absl/base:raw_logging_internal",
+ "//absl/base:scoped_set_env",
+ "//absl/strings",
+ "//absl/types:span",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "path_util_test",
+ size = "small",
+ srcs = [
+ "internal/path_util_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":path_util",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "program_name_test",
+ size = "small",
+ srcs = [
+ "internal/program_name_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":program_name",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "reflection_test",
+ size = "small",
+ srcs = [
+ "reflection_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":commandlineflag_internal",
+ ":flag",
+ ":marshalling",
+ ":reflection",
+ ":usage_internal",
+ "//absl/memory",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "sequence_lock_test",
+ size = "small",
+ timeout = "moderate",
+ srcs = [
+ "internal/sequence_lock_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ shard_count = 31,
+ deps = [
+ ":flag_internal",
+ "//absl/base",
+ "//absl/container:fixed_array",
+ "//absl/time",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "usage_config_test",
+ size = "small",
+ srcs = [
+ "usage_config_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":path_util",
+ ":program_name",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "usage_test",
+ size = "small",
+ srcs = [
+ "internal/usage_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":config",
+ ":flag",
+ ":parse",
+ ":path_util",
+ ":program_name",
+ ":reflection",
+ ":usage",
+ ":usage_internal",
+ "//absl/strings",
+ "@com_google_googletest//:gtest",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.cc
new file mode 100644
index 00000000000..9f3b4a5a28e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.cc
@@ -0,0 +1,34 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/commandlineflag.h"
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+bool CommandLineFlag::IsRetired() const { return false; }
+bool CommandLineFlag::ParseFrom(absl::string_view value, std::string* error) {
+ return ParseFrom(value, flags_internal::SET_FLAGS_VALUE,
+ flags_internal::kProgrammaticChange, *error);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.h
new file mode 100644
index 00000000000..f2fa08977fd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag.h
@@ -0,0 +1,200 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: commandlineflag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `CommandLineFlag`, which acts as a type-erased
+// handle for accessing metadata about the Abseil Flag in question.
+//
+// Because an actual Abseil flag is of an unspecified type, you should not
+// manipulate or interact directly with objects of that type. Instead, use the
+// CommandLineFlag type as an intermediary.
+#ifndef ABSL_FLAGS_COMMANDLINEFLAG_H_
+#define ABSL_FLAGS_COMMANDLINEFLAG_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class PrivateHandleAccessor;
+} // namespace flags_internal
+
+// CommandLineFlag
+//
+// This type acts as a type-erased handle for an instance of an Abseil Flag and
+// holds reflection information pertaining to that flag. Use CommandLineFlag to
+// access a flag's name, location, help string etc.
+//
+// To obtain an absl::CommandLineFlag, invoke `absl::FindCommandLineFlag()`
+// passing it the flag name string.
+//
+// Example:
+//
+// // Obtain reflection handle for a flag named "flagname".
+// const absl::CommandLineFlag* my_flag_data =
+// absl::FindCommandLineFlag("flagname");
+//
+// // Now you can get flag info from that reflection handle.
+// std::string flag_location = my_flag_data->Filename();
+// ...
+class CommandLineFlag {
+ public:
+ constexpr CommandLineFlag() = default;
+
+ // Not copyable/assignable.
+ CommandLineFlag(const CommandLineFlag&) = delete;
+ CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+ // absl::CommandLineFlag::IsOfType()
+ //
+ // Return true iff flag has type T.
+ template <typename T>
+ inline bool IsOfType() const {
+ return TypeId() == base_internal::FastTypeId<T>();
+ }
+
+ // absl::CommandLineFlag::TryGet()
+ //
+ // Attempts to retrieve the flag value. Returns value on success,
+ // absl::nullopt otherwise.
+ template <typename T>
+ absl::optional<T> TryGet() const {
+ if (IsRetired() || !IsOfType<T>()) {
+ return absl::nullopt;
+ }
+
+ // Implementation notes:
+ //
+ // We are wrapping a union around the value of `T` to serve three purposes:
+ //
+ // 1. `U.value` has correct size and alignment for a value of type `T`
+ // 2. The `U.value` constructor is not invoked since U's constructor does
+ // not do it explicitly.
+ // 3. The `U.value` destructor is invoked since U's destructor does it
+ // explicitly. This makes `U` a kind of RAII wrapper around non default
+ // constructible value of T, which is destructed when we leave the
+ // scope. We do need to destroy U.value, which is constructed by
+ // CommandLineFlag::Read even though we left it in a moved-from state
+ // after std::move.
+ //
+ // All of this serves to avoid requiring `T` being default constructible.
+ union U {
+ T value;
+ U() {}
+ ~U() { value.~T(); }
+ };
+ U u;
+
+ Read(&u.value);
+ // allow retired flags to be "read", so we can report invalid access.
+ if (IsRetired()) {
+ return absl::nullopt;
+ }
+ return std::move(u.value);
+ }
+
+ // absl::CommandLineFlag::Name()
+ //
+ // Returns name of this flag.
+ virtual absl::string_view Name() const = 0;
+
+ // absl::CommandLineFlag::Filename()
+ //
+ // Returns name of the file where this flag is defined.
+ virtual std::string Filename() const = 0;
+
+ // absl::CommandLineFlag::Help()
+ //
+ // Returns help message associated with this flag.
+ virtual std::string Help() const = 0;
+
+ // absl::CommandLineFlag::IsRetired()
+ //
+ // Returns true iff this object corresponds to retired flag.
+ virtual bool IsRetired() const;
+
+ // absl::CommandLineFlag::DefaultValue()
+ //
+ // Returns the default value for this flag.
+ virtual std::string DefaultValue() const = 0;
+
+ // absl::CommandLineFlag::CurrentValue()
+ //
+ // Returns the current value for this flag.
+ virtual std::string CurrentValue() const = 0;
+
+ // absl::CommandLineFlag::ParseFrom()
+ //
+ // Sets the value of the flag based on specified string `value`. If the flag
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
+ // to indicate the error, leaves the flag unchanged, and returns false.
+ bool ParseFrom(absl::string_view value, std::string* error);
+
+ protected:
+ ~CommandLineFlag() = default;
+
+ private:
+ friend class flags_internal::PrivateHandleAccessor;
+
+ // Sets the value of the flag based on specified string `value`. If the flag
+ // was successfully set to new value, it returns true. Otherwise, sets `error`
+ // to indicate the error, leaves the flag unchanged, and returns false. There
+ // are three ways to set the flag's value:
+ // * Update the current flag value
+ // * Update the flag's default value
+ // * Update the current flag value if it was never set before
+ // The mode is selected based on `set_mode` parameter.
+ virtual bool ParseFrom(absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source,
+ std::string& error) = 0;
+
+ // Returns id of the flag's value type.
+ virtual flags_internal::FlagFastTypeId TypeId() const = 0;
+
+ // Interface to save flag to some persistent state. Returns current flag state
+ // or nullptr if flag does not support saving and restoring a state.
+ virtual std::unique_ptr<flags_internal::FlagStateInterface> SaveState() = 0;
+
+ // Copy-construct a new value of the flag's type in a memory referenced by
+ // the dst based on the current flag's value.
+ virtual void Read(void* dst) const = 0;
+
+ // To be deleted. Used to return true if flag's current value originated from
+ // command line.
+ virtual bool IsSpecifiedOnCommandLine() const = 0;
+
+ // Validates supplied value usign validator or parseflag routine
+ virtual bool ValidateInputValue(absl::string_view value) const = 0;
+
+ // Checks that flags default value can be converted to string and back to the
+ // flag's value type.
+ virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_COMMANDLINEFLAG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag_test.cc
new file mode 100644
index 00000000000..585db4ba78a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/commandlineflag_test.cc
@@ -0,0 +1,231 @@
+//
+// 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.
+
+#include "absl/flags/commandlineflag.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/reflection.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+ABSL_FLAG(int, int_flag, 201, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt",
+ absl::StrCat("string_flag", " help"));
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+// These are only used to test default values.
+ABSL_FLAG(int, int_flag2, 201, "");
+ABSL_FLAG(std::string, string_flag2, "dflt", "");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class CommandLineFlagTest : public testing::Test {
+ protected:
+ static void SetUpTestSuite() {
+ // Install a function to normalize filenames before this test is run.
+ absl::FlagsUsageConfig default_config;
+ default_config.normalize_filename = &CommandLineFlagTest::NormalizeFileName;
+ absl::SetFlagsUsageConfig(default_config);
+ }
+
+ void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
+ void TearDown() override { flag_saver_.reset(); }
+
+ private:
+ static std::string NormalizeFileName(absl::string_view fname) {
+#ifdef _WIN32
+ std::string normalized(fname);
+ std::replace(normalized.begin(), normalized.end(), '\\', '/');
+ fname = normalized;
+#endif
+ return std::string(fname);
+ }
+
+ std::unique_ptr<absl::FlagSaver> flag_saver_;
+};
+
+TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+ ASSERT_TRUE(flag_01);
+ EXPECT_EQ(flag_01->Name(), "int_flag");
+ EXPECT_EQ(flag_01->Help(), "int_flag help");
+ EXPECT_TRUE(!flag_01->IsRetired());
+ EXPECT_TRUE(flag_01->IsOfType<int>());
+ EXPECT_TRUE(!flag_01->IsOfType<bool>());
+ EXPECT_TRUE(!flag_01->IsOfType<std::string>());
+ EXPECT_TRUE(absl::EndsWith(flag_01->Filename(),
+ "absl/flags/commandlineflag_test.cc"))
+ << flag_01->Filename();
+
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+
+ ASSERT_TRUE(flag_02);
+ EXPECT_EQ(flag_02->Name(), "string_flag");
+ EXPECT_EQ(flag_02->Help(), "string_flag help");
+ EXPECT_TRUE(!flag_02->IsRetired());
+ EXPECT_TRUE(flag_02->IsOfType<std::string>());
+ EXPECT_TRUE(!flag_02->IsOfType<bool>());
+ EXPECT_TRUE(!flag_02->IsOfType<int>());
+ EXPECT_TRUE(absl::EndsWith(flag_02->Filename(),
+ "absl/flags/commandlineflag_test.cc"))
+ << flag_02->Filename();
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
+ absl::SetFlag(&FLAGS_int_flag2, 301);
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag2");
+
+ ASSERT_TRUE(flag_01);
+ EXPECT_EQ(flag_01->CurrentValue(), "301");
+ EXPECT_EQ(flag_01->DefaultValue(), "201");
+
+ absl::SetFlag(&FLAGS_string_flag2, "new_str_value");
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag2");
+
+ ASSERT_TRUE(flag_02);
+ EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
+ EXPECT_EQ(flag_02->DefaultValue(), "dflt");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromCurrentValue) {
+ std::string err;
+
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "11", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "-123", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+ EXPECT_EQ(err, "Illegal value 'xyz' specified for flag 'int_flag'");
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "A1", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+ EXPECT_EQ(err, "Illegal value 'A1' specified for flag 'int_flag'");
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "0x10", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
+ EXPECT_FALSE(
+ flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "011", flags::SET_FLAGS_VALUE, flags::kCommandLine, err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+ EXPECT_TRUE(flags::PrivateHandleAccessor::IsSpecifiedOnCommandLine(*flag_01));
+
+ EXPECT_TRUE(!flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+ EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
+
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_02, "xyz", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_02, "", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange, err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromDefaultValue) {
+ std::string err;
+
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "111", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(flag_01->DefaultValue(), "111");
+
+ auto* flag_02 = absl::FindCommandLineFlag("string_flag");
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_02, "abc", flags::SET_FLAGS_DEFAULT, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(flag_02->DefaultValue(), "abc");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestParseFromIfDefault) {
+ std::string err;
+
+ auto* flag_01 = absl::FindCommandLineFlag("int_flag");
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "22", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err))
+ << err;
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+ // EXPECT_EQ(err, "ERROR: int_flag is already set to 22");
+
+ // Reset back to default value
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "201", flags::SET_FLAGS_VALUE, flags::kProgrammaticChange,
+ err));
+
+ EXPECT_TRUE(flags::PrivateHandleAccessor::ParseFrom(
+ *flag_01, "33", flags::SET_FLAG_IF_DEFAULT, flags::kProgrammaticChange,
+ err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 201);
+ // EXPECT_EQ(err, "ERROR: int_flag is already set to 201");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config.h
new file mode 100644
index 00000000000..5ab1f311dc9
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config.h
@@ -0,0 +1,76 @@
+//
+// 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_FLAGS_CONFIG_H_
+#define ABSL_FLAGS_CONFIG_H_
+
+// Determine if we should strip string literals from the Flag objects.
+// By default we strip string literals on mobile platforms.
+#if !defined(ABSL_FLAGS_STRIP_NAMES)
+
+#if defined(__ANDROID__)
+#define ABSL_FLAGS_STRIP_NAMES 1
+
+#elif defined(__APPLE__)
+#include <TargetConditionals.h>
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+#define ABSL_FLAGS_STRIP_NAMES 1
+#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED
+#define ABSL_FLAGS_STRIP_NAMES 1
+#endif // TARGET_OS_*
+#endif
+
+#endif // !defined(ABSL_FLAGS_STRIP_NAMES)
+
+#if !defined(ABSL_FLAGS_STRIP_NAMES)
+// If ABSL_FLAGS_STRIP_NAMES wasn't set on the command line or above,
+// the default is not to strip.
+#define ABSL_FLAGS_STRIP_NAMES 0
+#endif
+
+#if !defined(ABSL_FLAGS_STRIP_HELP)
+// By default, if we strip names, we also strip help.
+#define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES
+#endif
+
+// ABSL_FLAGS_INTERNAL_HAS_RTTI macro is used for selecting if we can use RTTI
+// for flag type identification.
+#ifdef ABSL_FLAGS_INTERNAL_HAS_RTTI
+#error ABSL_FLAGS_INTERNAL_HAS_RTTI cannot be directly set
+#elif !defined(__GNUC__) || defined(__GXX_RTTI)
+#define ABSL_FLAGS_INTERNAL_HAS_RTTI 1
+#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
+
+// These macros represent the "source of truth" for the list of supported
+// built-in types.
+#define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
+ A(bool, bool) \
+ A(short, short) \
+ A(unsigned short, unsigned_short) \
+ A(int, int) \
+ A(unsigned int, unsigned_int) \
+ A(long, long) \
+ A(unsigned long, unsigned_long) \
+ A(long long, long_long) \
+ A(unsigned long long, unsigned_long_long) \
+ A(double, double) \
+ A(float, float)
+
+#define ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(A) \
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
+ A(std::string, std_string) \
+ A(std::vector<std::string>, std_vector_of_string)
+
+#endif // ABSL_FLAGS_CONFIG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config_test.cc
new file mode 100644
index 00000000000..638998667e7
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/config_test.cc
@@ -0,0 +1,61 @@
+// 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.
+
+#include "absl/flags/config.h"
+
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
+#include "gtest/gtest.h"
+
+#ifndef ABSL_FLAGS_STRIP_NAMES
+#error ABSL_FLAGS_STRIP_NAMES is not defined
+#endif
+
+#ifndef ABSL_FLAGS_STRIP_HELP
+#error ABSL_FLAGS_STRIP_HELP is not defined
+#endif
+
+namespace {
+
+// Test that ABSL_FLAGS_STRIP_NAMES and ABSL_FLAGS_STRIP_HELP are configured how
+// we expect them to be configured by default. If you override this
+// configuration, this test will fail, but the code should still be safe to use.
+TEST(FlagsConfigTest, Test) {
+#if defined(__ANDROID__)
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
+#elif defined(__myriad2__)
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
+#elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
+#elif defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 1);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 1);
+#elif defined(__APPLE__)
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
+#elif defined(_WIN32)
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
+#elif defined(__linux__)
+ EXPECT_EQ(ABSL_FLAGS_STRIP_NAMES, 0);
+ EXPECT_EQ(ABSL_FLAGS_STRIP_HELP, 0);
+#endif
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/declare.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/declare.h
new file mode 100644
index 00000000000..b9794d8b85a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/declare.h
@@ -0,0 +1,65 @@
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: declare.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the ABSL_DECLARE_FLAG macro, allowing you to declare an
+// `absl::Flag` for use within a translation unit. You should place this
+// declaration within the header file associated with the .cc file that defines
+// and owns the `Flag`.
+
+#ifndef ABSL_FLAGS_DECLARE_H_
+#define ABSL_FLAGS_DECLARE_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// absl::Flag<T> represents a flag of type 'T' created by ABSL_FLAG.
+template <typename T>
+class Flag;
+
+} // namespace flags_internal
+
+// Flag
+//
+// Forward declaration of the `absl::Flag` type for use in defining the macro.
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// ABSL_DECLARE_FLAG()
+//
+// This macro is a convenience for declaring use of an `absl::Flag` within a
+// translation unit. This macro should be used within a header file to
+// declare usage of the flag within any .cc file including that header file.
+//
+// The ABSL_DECLARE_FLAG(type, name) macro expands to:
+//
+// extern absl::Flag<type> FLAGS_name;
+#define ABSL_DECLARE_FLAG(type, name) extern ::absl::Flag<type> FLAGS_##name
+
+#endif // ABSL_FLAGS_DECLARE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.cc
new file mode 100644
index 00000000000..531df1287a1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.cc
@@ -0,0 +1,38 @@
+//
+// 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.
+
+#include "absl/flags/flag.h"
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// This global mutex protects on-demand construction of flag objects in MSVC
+// builds.
+#if defined(_MSC_VER) && !defined(__clang__)
+
+namespace flags_internal {
+
+ABSL_CONST_INIT static absl::Mutex construction_guard(absl::kConstInit);
+
+absl::Mutex* GetGlobalConstructionGuard() { return &construction_guard; }
+
+} // namespace flags_internal
+
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.h
new file mode 100644
index 00000000000..f09580b06a7
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag.h
@@ -0,0 +1,398 @@
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: flag.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::Flag<T>` type for holding command-line
+// flag data, and abstractions to create, get and set such flag data.
+//
+// It is important to note that this type is **unspecified** (an implementation
+// detail) and you do not construct or manipulate actual `absl::Flag<T>`
+// instances. Instead, you define and declare flags using the
+// `ABSL_FLAG()` and `ABSL_DECLARE_FLAG()` macros, and get and set flag values
+// using the `absl::GetFlag()` and `absl::SetFlag()` functions.
+
+#ifndef ABSL_FLAGS_FLAG_H_
+#define ABSL_FLAGS_FLAG_H_
+
+#include <string>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Flag
+//
+// An `absl::Flag` holds a command-line flag value, providing a runtime
+// parameter to a binary. Such flags should be defined in the global namespace
+// and (preferably) in the module containing the binary's `main()` function.
+//
+// You should not construct and cannot use the `absl::Flag` type directly;
+// instead, you should declare flags using the `ABSL_DECLARE_FLAG()` macro
+// within a header file, and define your flag using `ABSL_FLAG()` within your
+// header's associated `.cc` file. Such flags will be named `FLAGS_name`.
+//
+// Example:
+//
+// .h file
+//
+// // Declares usage of a flag named "FLAGS_count"
+// ABSL_DECLARE_FLAG(int, count);
+//
+// .cc file
+//
+// // Defines a flag named "FLAGS_count" with a default `int` value of 0.
+// ABSL_FLAG(int, count, 0, "Count of items to process");
+//
+// No public methods of `absl::Flag<T>` are part of the Abseil Flags API.
+#if !defined(_MSC_VER) || defined(__clang__)
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#else
+// MSVC debug builds do not implement initialization with constexpr constructors
+// correctly. To work around this we add a level of indirection, so that the
+// class `absl::Flag` contains an `internal::Flag*` (instead of being an alias
+// to that class) and dynamically allocates an instance when necessary. We also
+// forward all calls to internal::Flag methods via trampoline methods. In this
+// setup the `absl::Flag` class does not have constructor and virtual methods,
+// all the data members are public and thus MSVC is able to initialize it at
+// link time. To deal with multiple threads accessing the flag for the first
+// time concurrently we use an atomic boolean indicating if flag object is
+// initialized. We also employ the double-checked locking pattern where the
+// second level of protection is a global Mutex, so if two threads attempt to
+// construct the flag concurrently only one wins.
+// This solution is based on a recomendation here:
+// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html?childToView=648454#comment-648454
+
+namespace flags_internal {
+absl::Mutex* GetGlobalConstructionGuard();
+} // namespace flags_internal
+
+template <typename T>
+class Flag {
+ public:
+ // No constructor and destructor to ensure this is an aggregate type.
+ // Visual Studio 2015 still requires the constructor for class to be
+ // constexpr initializable.
+#if _MSC_VER <= 1900
+ constexpr Flag(const char* name, const char* filename,
+ const flags_internal::HelpGenFunc help_gen,
+ const flags_internal::FlagDfltGenFunc default_value_gen)
+ : name_(name),
+ filename_(filename),
+ help_gen_(help_gen),
+ default_value_gen_(default_value_gen),
+ inited_(false),
+ impl_(nullptr) {}
+#endif
+
+ flags_internal::Flag<T>& GetImpl() const {
+ if (!inited_.load(std::memory_order_acquire)) {
+ absl::MutexLock l(flags_internal::GetGlobalConstructionGuard());
+
+ if (inited_.load(std::memory_order_acquire)) {
+ return *impl_;
+ }
+
+ impl_ = new flags_internal::Flag<T>(
+ name_, filename_,
+ {flags_internal::FlagHelpMsg(help_gen_),
+ flags_internal::FlagHelpKind::kGenFunc},
+ {flags_internal::FlagDefaultSrc(default_value_gen_),
+ flags_internal::FlagDefaultKind::kGenFunc});
+ inited_.store(true, std::memory_order_release);
+ }
+
+ return *impl_;
+ }
+
+ // Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
+ // See https://abseil.io/docs/cpp/guides/flags
+ bool IsRetired() const { return GetImpl().IsRetired(); }
+ absl::string_view Name() const { return GetImpl().Name(); }
+ std::string Help() const { return GetImpl().Help(); }
+ bool IsModified() const { return GetImpl().IsModified(); }
+ bool IsSpecifiedOnCommandLine() const {
+ return GetImpl().IsSpecifiedOnCommandLine();
+ }
+ std::string Filename() const { return GetImpl().Filename(); }
+ std::string DefaultValue() const { return GetImpl().DefaultValue(); }
+ std::string CurrentValue() const { return GetImpl().CurrentValue(); }
+ template <typename U>
+ inline bool IsOfType() const {
+ return GetImpl().template IsOfType<U>();
+ }
+ T Get() const {
+ return flags_internal::FlagImplPeer::InvokeGet<T>(GetImpl());
+ }
+ void Set(const T& v) {
+ flags_internal::FlagImplPeer::InvokeSet(GetImpl(), v);
+ }
+ void InvokeCallback() { GetImpl().InvokeCallback(); }
+
+ const CommandLineFlag& Reflect() const {
+ return flags_internal::FlagImplPeer::InvokeReflect(GetImpl());
+ }
+
+ // The data members are logically private, but they need to be public for
+ // this to be an aggregate type.
+ const char* name_;
+ const char* filename_;
+ const flags_internal::HelpGenFunc help_gen_;
+ const flags_internal::FlagDfltGenFunc default_value_gen_;
+
+ mutable std::atomic<bool> inited_;
+ mutable flags_internal::Flag<T>* impl_;
+};
+#endif
+
+// GetFlag()
+//
+// Returns the value (of type `T`) of an `absl::Flag<T>` instance, by value. Do
+// not construct an `absl::Flag<T>` directly and call `absl::GetFlag()`;
+// instead, refer to flag's constructed variable name (e.g. `FLAGS_name`).
+// Because this function returns by value and not by reference, it is
+// thread-safe, but note that the operation may be expensive; as a result, avoid
+// `absl::GetFlag()` within any tight loops.
+//
+// Example:
+//
+// // FLAGS_count is a Flag of type `int`
+// int my_count = absl::GetFlag(FLAGS_count);
+//
+// // FLAGS_firstname is a Flag of type `std::string`
+// std::string first_name = absl::GetFlag(FLAGS_firstname);
+template <typename T>
+ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
+ return flags_internal::FlagImplPeer::InvokeGet<T>(flag);
+}
+
+// SetFlag()
+//
+// Sets the value of an `absl::Flag` to the value `v`. Do not construct an
+// `absl::Flag<T>` directly and call `absl::SetFlag()`; instead, use the
+// flag's variable name (e.g. `FLAGS_name`). This function is
+// thread-safe, but is potentially expensive. Avoid setting flags in general,
+// but especially within performance-critical code.
+template <typename T>
+void SetFlag(absl::Flag<T>* flag, const T& v) {
+ flags_internal::FlagImplPeer::InvokeSet(*flag, v);
+}
+
+// Overload of `SetFlag()` to allow callers to pass in a value that is
+// convertible to `T`. E.g., use this overload to pass a "const char*" when `T`
+// is `std::string`.
+template <typename T, typename V>
+void SetFlag(absl::Flag<T>* flag, const V& v) {
+ T value(v);
+ flags_internal::FlagImplPeer::InvokeSet(*flag, value);
+}
+
+// GetFlagReflectionHandle()
+//
+// Returns the reflection handle corresponding to specified Abseil Flag
+// instance. Use this handle to access flag's reflection information, like name,
+// location, default value etc.
+//
+// Example:
+//
+// std::string = absl::GetFlagReflectionHandle(FLAGS_count).DefaultValue();
+
+template <typename T>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<T>& f) {
+ return flags_internal::FlagImplPeer::InvokeReflect(f);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+
+// ABSL_FLAG()
+//
+// This macro defines an `absl::Flag<T>` instance of a specified type `T`:
+//
+// ABSL_FLAG(T, name, default_value, help);
+//
+// where:
+//
+// * `T` is a supported flag type (see the list of types in `marshalling.h`),
+// * `name` designates the name of the flag (as a global variable
+// `FLAGS_name`),
+// * `default_value` is an expression holding the default value for this flag
+// (which must be implicitly convertible to `T`),
+// * `help` is the help text, which can also be an expression.
+//
+// This macro expands to a flag named 'FLAGS_name' of type 'T':
+//
+// absl::Flag<T> FLAGS_name = ...;
+//
+// Note that all such instances are created as global variables.
+//
+// For `ABSL_FLAG()` values that you wish to expose to other translation units,
+// it is recommended to define those flags within the `.cc` file associated with
+// the header where the flag is declared.
+//
+// Note: do not construct objects of type `absl::Flag<T>` directly. Only use the
+// `ABSL_FLAG()` macro for such construction.
+#define ABSL_FLAG(Type, name, default_value, help) \
+ ABSL_FLAG_IMPL(Type, name, default_value, help)
+
+// ABSL_FLAG().OnUpdate()
+//
+// Defines a flag of type `T` with a callback attached:
+//
+// ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
+//
+// After any setting of the flag value, the callback will be called at least
+// once. A rapid sequence of changes may be merged together into the same
+// callback. No concurrent calls to the callback will be made for the same
+// flag. Callbacks are allowed to read the current value of the flag but must
+// not mutate that flag.
+//
+// The update mechanism guarantees "eventual consistency"; if the callback
+// derives an auxiliary data structure from the flag value, it is guaranteed
+// that eventually the flag value and the derived data structure will be
+// consistent.
+//
+// Note: ABSL_FLAG.OnUpdate() does not have a public definition. Hence, this
+// comment serves as its API documentation.
+
+
+// -----------------------------------------------------------------------------
+// Implementation details below this section
+// -----------------------------------------------------------------------------
+
+// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_NAMES
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag
+#define ABSL_FLAG_IMPL_HELP_ARG(name) \
+ absl::flags_internal::HelpArg<AbslFlagHelpGenFor##name>( \
+ FLAGS_help_storage_##name)
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) \
+ absl::flags_internal::DefaultArg<Type, AbslFlagDefaultGenFor##name>(0)
+#else
+#define ABSL_FLAG_IMPL_FLAG_PTR(flag) flag.GetImpl()
+#define ABSL_FLAG_IMPL_HELP_ARG(name) &AbslFlagHelpGenFor##name::NonConst
+#define ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name) &AbslFlagDefaultGenFor##name::Gen
+#endif
+
+#if ABSL_FLAGS_STRIP_NAMES
+#define ABSL_FLAG_IMPL_FLAGNAME(txt) ""
+#define ABSL_FLAG_IMPL_FILENAME() ""
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
+ nullptr)
+#else
+#define ABSL_FLAG_IMPL_FLAGNAME(txt) txt
+#define ABSL_FLAG_IMPL_FILENAME() __FILE__
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, true>(ABSL_FLAG_IMPL_FLAG_PTR(flag), \
+ __FILE__)
+#endif
+
+// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
+
+#if ABSL_FLAGS_STRIP_HELP
+#define ABSL_FLAG_IMPL_FLAGHELP(txt) absl::flags_internal::kStrippedFlagHelp
+#else
+#define ABSL_FLAG_IMPL_FLAGHELP(txt) txt
+#endif
+
+// AbslFlagHelpGenFor##name is used to encapsulate both immediate (method Const)
+// and lazy (method NonConst) evaluation of help message expression. We choose
+// between the two via the call to HelpArg in absl::Flag instantiation below.
+// If help message expression is constexpr evaluable compiler will optimize
+// away this whole struct.
+// TODO(rogeeff): place these generated structs into local namespace and apply
+// ABSL_INTERNAL_UNIQUE_SHORT_NAME.
+// TODO(rogeeff): Apply __attribute__((nodebug)) to FLAGS_help_storage_##name
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
+ struct AbslFlagHelpGenFor##name { \
+ /* The expression is run in the caller as part of the */ \
+ /* default value argument. That keeps temporaries alive */ \
+ /* long enough for NonConst to work correctly. */ \
+ static constexpr absl::string_view Value( \
+ absl::string_view v = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
+ return v; \
+ } \
+ static std::string NonConst() { return std::string(Value()); } \
+ }; \
+ constexpr auto FLAGS_help_storage_##name ABSL_INTERNAL_UNIQUE_SMALL_NAME() \
+ ABSL_ATTRIBUTE_SECTION_VARIABLE(flags_help_cold) = \
+ absl::flags_internal::HelpStringAsArray<AbslFlagHelpGenFor##name>( \
+ 0);
+
+#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+ struct AbslFlagDefaultGenFor##name { \
+ Type value = absl::flags_internal::InitDefaultValue<Type>(default_value); \
+ static void Gen(void* p) { \
+ new (p) Type(AbslFlagDefaultGenFor##name{}.value); \
+ } \
+ };
+
+// ABSL_FLAG_IMPL
+//
+// Note: Name of registrar object is not arbitrary. It is used to "grab"
+// global name for FLAGS_no<flag_name> symbol, thus preventing the possibility
+// of defining two flags with names foo and nofoo.
+#define ABSL_FLAG_IMPL(Type, name, default_value, help) \
+ namespace absl /* block flags in namespaces */ {} \
+ ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+ ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, help) \
+ ABSL_CONST_INIT absl::Flag<Type> FLAGS_##name{ \
+ ABSL_FLAG_IMPL_FLAGNAME(#name), ABSL_FLAG_IMPL_FILENAME(), \
+ ABSL_FLAG_IMPL_HELP_ARG(name), ABSL_FLAG_IMPL_DEFAULT_ARG(Type, name)}; \
+ extern absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name; \
+ absl::flags_internal::FlagRegistrarEmpty FLAGS_no##name = \
+ ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+
+// ABSL_RETIRED_FLAG
+//
+// Designates the flag (which is usually pre-existing) as "retired." A retired
+// flag is a flag that is now unused by the program, but may still be passed on
+// the command line, usually by production scripts. A retired flag is ignored
+// and code can't access it at runtime.
+//
+// This macro registers a retired flag with given name and type, with a name
+// identical to the name of the original flag you are retiring. The retired
+// flag's type can change over time, so that you can retire code to support a
+// custom flag type.
+//
+// This macro has the same signature as `ABSL_FLAG`. To retire a flag, simply
+// replace an `ABSL_FLAG` definition with `ABSL_RETIRED_FLAG`, leaving the
+// arguments unchanged (unless of course you actually want to retire the flag
+// type at this time as well).
+//
+// `default_value` is only used as a double check on the type. `explanation` is
+// unused.
+// TODO(rogeeff): replace RETIRED_FLAGS with FLAGS once forward declarations of
+// retired flags are cleaned up.
+#define ABSL_RETIRED_FLAG(type, name, default_value, explanation) \
+ static absl::flags_internal::RetiredFlag<type> RETIRED_FLAGS_##name; \
+ ABSL_ATTRIBUTE_UNUSED static const auto RETIRED_FLAGS_REG_##name = \
+ (RETIRED_FLAGS_##name.Retire(#name), \
+ ::absl::flags_internal::FlagRegistrarEmpty{})
+
+#endif // ABSL_FLAGS_FLAG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.cc
new file mode 100644
index 00000000000..57584f85d35
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.cc
@@ -0,0 +1,168 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "absl/flags/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/flags/parse.h"
+#include "absl/flags/reflection.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "absl/types/optional.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+using String = std::string;
+using VectorOfStrings = std::vector<std::string>;
+using AbslDuration = absl::Duration;
+
+// We do not want to take over marshalling for the types absl::optional<int>,
+// absl::optional<std::string> which we do not own. Instead we introduce unique
+// "aliases" to these types, which we do.
+using AbslOptionalInt = absl::optional<int>;
+struct OptionalInt : AbslOptionalInt {
+ using AbslOptionalInt::AbslOptionalInt;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalInt.
+bool AbslParseFlag(absl::string_view src, OptionalInt* flag,
+ std::string* error) {
+ int val;
+ if (src.empty())
+ flag->reset();
+ else if (!absl::ParseFlag(src, &val, error))
+ return false;
+ *flag = val;
+ return true;
+}
+std::string AbslUnparseFlag(const OptionalInt& flag) {
+ return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+using AbslOptionalString = absl::optional<std::string>;
+struct OptionalString : AbslOptionalString {
+ using AbslOptionalString::AbslOptionalString;
+};
+// Next two functions represent Abseil Flags marshalling for OptionalString.
+bool AbslParseFlag(absl::string_view src, OptionalString* flag,
+ std::string* error) {
+ std::string val;
+ if (src.empty())
+ flag->reset();
+ else if (!absl::ParseFlag(src, &val, error))
+ return false;
+ *flag = val;
+ return true;
+}
+std::string AbslUnparseFlag(const OptionalString& flag) {
+ return !flag ? "" : absl::UnparseFlag(*flag);
+}
+
+struct UDT {
+ UDT() = default;
+ UDT(const UDT&) {}
+ UDT& operator=(const UDT&) { return *this; }
+};
+// Next two functions represent Abseil Flags marshalling for UDT.
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return ""; }
+
+} // namespace
+
+#define BENCHMARKED_TYPES(A) \
+ A(bool) \
+ A(int16_t) \
+ A(uint16_t) \
+ A(int32_t) \
+ A(uint32_t) \
+ A(int64_t) \
+ A(uint64_t) \
+ A(double) \
+ A(float) \
+ A(String) \
+ A(VectorOfStrings) \
+ A(OptionalInt) \
+ A(OptionalString) \
+ A(AbslDuration) \
+ A(UDT)
+
+#define FLAG_DEF(T) ABSL_FLAG(T, T##_flag, {}, "");
+
+#if defined(__clang__) && defined(__linux__)
+// Force the flags used for benchmarks into a separate ELF section.
+// This ensures that, even when other parts of the code might change size,
+// the layout of the flags across cachelines is kept constant. This makes
+// benchmark results more reproducible across unrelated code changes.
+#pragma clang section data = ".benchmark_flags"
+#endif
+BENCHMARKED_TYPES(FLAG_DEF)
+#if defined(__clang__) && defined(__linux__)
+#pragma clang section data = ""
+#endif
+// Register thousands of flags to bloat up the size of the registry.
+// This mimics real life production binaries.
+#define DEFINE_FLAG_0(name) ABSL_FLAG(int, name, 0, "");
+#define DEFINE_FLAG_1(name) DEFINE_FLAG_0(name##0) DEFINE_FLAG_0(name##1)
+#define DEFINE_FLAG_2(name) DEFINE_FLAG_1(name##0) DEFINE_FLAG_1(name##1)
+#define DEFINE_FLAG_3(name) DEFINE_FLAG_2(name##0) DEFINE_FLAG_2(name##1)
+#define DEFINE_FLAG_4(name) DEFINE_FLAG_3(name##0) DEFINE_FLAG_3(name##1)
+#define DEFINE_FLAG_5(name) DEFINE_FLAG_4(name##0) DEFINE_FLAG_4(name##1)
+#define DEFINE_FLAG_6(name) DEFINE_FLAG_5(name##0) DEFINE_FLAG_5(name##1)
+#define DEFINE_FLAG_7(name) DEFINE_FLAG_6(name##0) DEFINE_FLAG_6(name##1)
+#define DEFINE_FLAG_8(name) DEFINE_FLAG_7(name##0) DEFINE_FLAG_7(name##1)
+#define DEFINE_FLAG_9(name) DEFINE_FLAG_8(name##0) DEFINE_FLAG_8(name##1)
+#define DEFINE_FLAG_10(name) DEFINE_FLAG_9(name##0) DEFINE_FLAG_9(name##1)
+#define DEFINE_FLAG_11(name) DEFINE_FLAG_10(name##0) DEFINE_FLAG_10(name##1)
+#define DEFINE_FLAG_12(name) DEFINE_FLAG_11(name##0) DEFINE_FLAG_11(name##1)
+DEFINE_FLAG_12(bloat_flag_);
+
+namespace {
+
+#define BM_GetFlag(T) \
+ void BM_GetFlag_##T(benchmark::State& state) { \
+ for (auto _ : state) { \
+ benchmark::DoNotOptimize(absl::GetFlag(FLAGS_##T##_flag)); \
+ } \
+ } \
+ BENCHMARK(BM_GetFlag_##T)->ThreadRange(1, 16);
+
+BENCHMARKED_TYPES(BM_GetFlag)
+
+void BM_ThreadedFindCommandLineFlag(benchmark::State& state) {
+ char dummy[] = "dummy";
+ char* argv[] = {dummy};
+ // We need to ensure that flags have been parsed. That is where the registry
+ // is finalized.
+ absl::ParseCommandLine(1, argv);
+
+ for (auto s : state) {
+ benchmark::DoNotOptimize(
+ absl::FindCommandLineFlag("bloat_flag_010101010101"));
+ }
+}
+BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+
+} // namespace
+
+#define InvokeGetFlag(T) \
+ T AbslInvokeGetFlag##T() { return absl::GetFlag(FLAGS_##T##_flag); } \
+ int odr##T = (benchmark::DoNotOptimize(AbslInvokeGetFlag##T), 1);
+
+BENCHMARKED_TYPES(InvokeGetFlag)
+
+// To veiw disassembly use: gdb ${BINARY} -batch -ex "disassemble /s $FUNC"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.lds b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.lds
new file mode 100644
index 00000000000..af115dfc009
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_benchmark.lds
@@ -0,0 +1,13 @@
+/* This linker script forces the flags used by flags_benchmark
+ * into a separate page-aligned section. This isn't necessary for
+ * correctness but ensures that the benchmark results are more
+ * reproducible across unrelated code changes.
+ */
+SECTIONS {
+ .benchmark_flags : {
+ . = ALIGN(0x1000);
+ * (.benchmark_flags);
+ }
+}
+
+INSERT AFTER .data
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test.cc
new file mode 100644
index 00000000000..6912b5461f1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test.cc
@@ -0,0 +1,945 @@
+//
+// 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.
+
+#include "absl/flags/flag.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cmath>
+#include <new>
+#include <string>
+#include <thread> // NOLINT
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/attributes.h"
+#include "absl/base/macros.h"
+#include "absl/flags/config.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/flags/reflection.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/match.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+
+ABSL_DECLARE_FLAG(int64_t, mistyped_int_flag);
+ABSL_DECLARE_FLAG(std::vector<std::string>, mistyped_string_flag);
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+std::string TestHelpMsg() { return "dynamic help"; }
+#if defined(_MSC_VER) && !defined(__clang__)
+std::string TestLiteralHelpMsg() { return "literal help"; }
+#endif
+template <typename T>
+void TestMakeDflt(void* dst) {
+ new (dst) T{};
+}
+void TestCallback() {}
+
+struct UDT {
+ UDT() = default;
+ UDT(const UDT&) = default;
+};
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return ""; }
+
+class FlagTest : public testing::Test {
+ protected:
+ static void SetUpTestSuite() {
+ // Install a function to normalize filenames before this test is run.
+ absl::FlagsUsageConfig default_config;
+ default_config.normalize_filename = &FlagTest::NormalizeFileName;
+ absl::SetFlagsUsageConfig(default_config);
+ }
+
+ private:
+ static std::string NormalizeFileName(absl::string_view fname) {
+#ifdef _WIN32
+ std::string normalized(fname);
+ std::replace(normalized.begin(), normalized.end(), '\\', '/');
+ fname = normalized;
+#endif
+ return std::string(fname);
+ }
+ absl::FlagSaver flag_saver_;
+};
+
+struct S1 {
+ S1() = default;
+ S1(const S1&) = default;
+ int32_t f1;
+ int64_t f2;
+};
+
+struct S2 {
+ S2() = default;
+ S2(const S2&) = default;
+ int64_t f1;
+ double f2;
+};
+
+TEST_F(FlagTest, Traits) {
+ EXPECT_EQ(flags::StorageKind<int>(),
+ flags::FlagValueStorageKind::kOneWordAtomic);
+ EXPECT_EQ(flags::StorageKind<bool>(),
+ flags::FlagValueStorageKind::kOneWordAtomic);
+ EXPECT_EQ(flags::StorageKind<double>(),
+ flags::FlagValueStorageKind::kOneWordAtomic);
+ EXPECT_EQ(flags::StorageKind<int64_t>(),
+ flags::FlagValueStorageKind::kOneWordAtomic);
+
+ EXPECT_EQ(flags::StorageKind<S1>(),
+ flags::FlagValueStorageKind::kSequenceLocked);
+ EXPECT_EQ(flags::StorageKind<S2>(),
+ flags::FlagValueStorageKind::kSequenceLocked);
+// Make sure absl::Duration uses the sequence-locked code path. MSVC 2015
+// doesn't consider absl::Duration to be trivially-copyable so we just
+// restrict this to clang as it seems to be a well-behaved compiler.
+#ifdef __clang__
+ EXPECT_EQ(flags::StorageKind<absl::Duration>(),
+ flags::FlagValueStorageKind::kSequenceLocked);
+#endif
+
+ EXPECT_EQ(flags::StorageKind<std::string>(),
+ flags::FlagValueStorageKind::kAlignedBuffer);
+ EXPECT_EQ(flags::StorageKind<std::vector<std::string>>(),
+ flags::FlagValueStorageKind::kAlignedBuffer);
+}
+
+// --------------------------------------------------------------------
+
+constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
+ flags::FlagHelpKind::kLiteral};
+
+using String = std::string;
+
+#if !defined(_MSC_VER) || defined(__clang__)
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
+ constexpr flags::FlagDefaultArg f1default##T{ \
+ flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+ constexpr absl::Flag<T> f1##T{"f1", "file", help_arg, f1default##T}; \
+ ABSL_CONST_INIT absl::Flag<T> f2##T { \
+ "f2", "file", \
+ {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc}, \
+ flags::FlagDefaultArg { \
+ flags::FlagDefaultSrc(&TestMakeDflt<T>), \
+ flags::FlagDefaultKind::kGenFunc \
+ } \
+ }
+#else
+#define DEFINE_CONSTRUCTED_FLAG(T, dflt, dflt_kind) \
+ constexpr flags::FlagDefaultArg f1default##T{ \
+ flags::FlagDefaultSrc{dflt}, flags::FlagDefaultKind::dflt_kind}; \
+ constexpr absl::Flag<T> f1##T{"f1", "file", &TestLiteralHelpMsg, \
+ &TestMakeDflt<T>}; \
+ ABSL_CONST_INIT absl::Flag<T> f2##T { \
+ "f2", "file", &TestHelpMsg, &TestMakeDflt<T> \
+ }
+#endif
+
+DEFINE_CONSTRUCTED_FLAG(bool, true, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int16_t, 1, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint16_t, 2, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int32_t, 3, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint32_t, 4, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(int64_t, 5, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(uint64_t, 6, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(float, 7.8, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(double, 9.10, kOneWord);
+DEFINE_CONSTRUCTED_FLAG(String, &TestMakeDflt<String>, kGenFunc);
+DEFINE_CONSTRUCTED_FLAG(UDT, &TestMakeDflt<UDT>, kGenFunc);
+
+template <typename T>
+bool TestConstructionFor(const absl::Flag<T>& f1, absl::Flag<T>& f2) {
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Name(), "f1");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Help(), "literal help");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f1).Filename(), "file");
+
+ flags::FlagRegistrar<T, false>(ABSL_FLAG_IMPL_FLAG_PTR(f2), nullptr)
+ .OnUpdate(TestCallback);
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Name(), "f2");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Help(), "dynamic help");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(f2).Filename(), "file");
+
+ return true;
+}
+
+#define TEST_CONSTRUCTED_FLAG(T) TestConstructionFor(f1##T, f2##T);
+
+TEST_F(FlagTest, TestConstruction) {
+ TEST_CONSTRUCTED_FLAG(bool);
+ TEST_CONSTRUCTED_FLAG(int16_t);
+ TEST_CONSTRUCTED_FLAG(uint16_t);
+ TEST_CONSTRUCTED_FLAG(int32_t);
+ TEST_CONSTRUCTED_FLAG(uint32_t);
+ TEST_CONSTRUCTED_FLAG(int64_t);
+ TEST_CONSTRUCTED_FLAG(uint64_t);
+ TEST_CONSTRUCTED_FLAG(float);
+ TEST_CONSTRUCTED_FLAG(double);
+ TEST_CONSTRUCTED_FLAG(String);
+ TEST_CONSTRUCTED_FLAG(UDT);
+}
+
+// --------------------------------------------------------------------
+
+} // namespace
+
+ABSL_DECLARE_FLAG(bool, test_flag_01);
+ABSL_DECLARE_FLAG(int, test_flag_02);
+ABSL_DECLARE_FLAG(int16_t, test_flag_03);
+ABSL_DECLARE_FLAG(uint16_t, test_flag_04);
+ABSL_DECLARE_FLAG(int32_t, test_flag_05);
+ABSL_DECLARE_FLAG(uint32_t, test_flag_06);
+ABSL_DECLARE_FLAG(int64_t, test_flag_07);
+ABSL_DECLARE_FLAG(uint64_t, test_flag_08);
+ABSL_DECLARE_FLAG(double, test_flag_09);
+ABSL_DECLARE_FLAG(float, test_flag_10);
+ABSL_DECLARE_FLAG(std::string, test_flag_11);
+ABSL_DECLARE_FLAG(absl::Duration, test_flag_12);
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_NAMES
+
+TEST_F(FlagTest, TestFlagDeclaration) {
+ // test that we can access flag objects.
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+ "test_flag_01");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+ "test_flag_02");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+ "test_flag_03");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+ "test_flag_04");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+ "test_flag_05");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+ "test_flag_06");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+ "test_flag_07");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+ "test_flag_08");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+ "test_flag_09");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+ "test_flag_10");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+ "test_flag_11");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+ "test_flag_12");
+}
+#endif // !ABSL_FLAGS_STRIP_NAMES
+
+// --------------------------------------------------------------------
+
+} // namespace
+
+ABSL_FLAG(bool, test_flag_01, true, "test flag 01");
+ABSL_FLAG(int, test_flag_02, 1234, "test flag 02");
+ABSL_FLAG(int16_t, test_flag_03, -34, "test flag 03");
+ABSL_FLAG(uint16_t, test_flag_04, 189, "test flag 04");
+ABSL_FLAG(int32_t, test_flag_05, 10765, "test flag 05");
+ABSL_FLAG(uint32_t, test_flag_06, 40000, "test flag 06");
+ABSL_FLAG(int64_t, test_flag_07, -1234567, "test flag 07");
+ABSL_FLAG(uint64_t, test_flag_08, 9876543, "test flag 08");
+ABSL_FLAG(double, test_flag_09, -9.876e-50, "test flag 09");
+ABSL_FLAG(float, test_flag_10, 1.234e12f, "test flag 10");
+ABSL_FLAG(std::string, test_flag_11, "", "test flag 11");
+ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "test flag 12");
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_NAMES
+TEST_F(FlagTest, TestFlagDefinition) {
+ absl::string_view expected_file_name = "absl/flags/flag_test.cc";
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Name(),
+ "test_flag_01");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Help(),
+ "test flag 01");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_01).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Name(),
+ "test_flag_02");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Help(),
+ "test flag 02");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_02).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Name(),
+ "test_flag_03");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Help(),
+ "test flag 03");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_03).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Name(),
+ "test_flag_04");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Help(),
+ "test flag 04");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_04).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Name(),
+ "test_flag_05");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Help(),
+ "test flag 05");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_05).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Name(),
+ "test_flag_06");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Help(),
+ "test flag 06");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_06).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Name(),
+ "test_flag_07");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Help(),
+ "test flag 07");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_07).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Name(),
+ "test_flag_08");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Help(),
+ "test flag 08");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_08).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Name(),
+ "test_flag_09");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Help(),
+ "test flag 09");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_09).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Name(),
+ "test_flag_10");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Help(),
+ "test flag 10");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_10).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Name(),
+ "test_flag_11");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Help(),
+ "test flag 11");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_11).Filename();
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Name(),
+ "test_flag_12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Help(),
+ "test flag 12");
+ EXPECT_TRUE(absl::EndsWith(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename(),
+ expected_file_name))
+ << absl::GetFlagReflectionHandle(FLAGS_test_flag_12).Filename();
+}
+#endif // !ABSL_FLAGS_STRIP_NAMES
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, TestDefault) {
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).DefaultValue(),
+ "true");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).DefaultValue(),
+ "1234");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).DefaultValue(),
+ "-34");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).DefaultValue(),
+ "189");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).DefaultValue(),
+ "10765");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).DefaultValue(),
+ "40000");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).DefaultValue(),
+ "-1234567");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).DefaultValue(),
+ "9876543");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).DefaultValue(),
+ "-9.876e-50");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).DefaultValue(),
+ "1.234e+12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).DefaultValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).DefaultValue(),
+ "10m");
+
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_01).CurrentValue(),
+ "true");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_02).CurrentValue(),
+ "1234");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_03).CurrentValue(),
+ "-34");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_04).CurrentValue(),
+ "189");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_05).CurrentValue(),
+ "10765");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_06).CurrentValue(),
+ "40000");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_07).CurrentValue(),
+ "-1234567");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_08).CurrentValue(),
+ "9876543");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_09).CurrentValue(),
+ "-9.876e-50");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_10).CurrentValue(),
+ "1.234e+12");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_11).CurrentValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_12).CurrentValue(),
+ "10m");
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+}
+
+// --------------------------------------------------------------------
+
+struct NonTriviallyCopyableAggregate {
+ NonTriviallyCopyableAggregate() = default;
+ NonTriviallyCopyableAggregate(const NonTriviallyCopyableAggregate& rhs)
+ : value(rhs.value) {}
+ NonTriviallyCopyableAggregate& operator=(
+ const NonTriviallyCopyableAggregate& rhs) {
+ value = rhs.value;
+ return *this;
+ }
+
+ int value;
+};
+bool AbslParseFlag(absl::string_view src, NonTriviallyCopyableAggregate* f,
+ std::string* e) {
+ return absl::ParseFlag(src, &f->value, e);
+}
+std::string AbslUnparseFlag(const NonTriviallyCopyableAggregate& ntc) {
+ return absl::StrCat(ntc.value);
+}
+
+bool operator==(const NonTriviallyCopyableAggregate& ntc1,
+ const NonTriviallyCopyableAggregate& ntc2) {
+ return ntc1.value == ntc2.value;
+}
+
+} // namespace
+
+ABSL_FLAG(bool, test_flag_eb_01, {}, "");
+ABSL_FLAG(int32_t, test_flag_eb_02, {}, "");
+ABSL_FLAG(int64_t, test_flag_eb_03, {}, "");
+ABSL_FLAG(double, test_flag_eb_04, {}, "");
+ABSL_FLAG(std::string, test_flag_eb_05, {}, "");
+ABSL_FLAG(NonTriviallyCopyableAggregate, test_flag_eb_06, {}, "");
+
+namespace {
+
+TEST_F(FlagTest, TestEmptyBracesDefault) {
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_01).DefaultValue(),
+ "false");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_02).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_03).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_04).DefaultValue(),
+ "0");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_05).DefaultValue(),
+ "");
+ EXPECT_EQ(absl::GetFlagReflectionHandle(FLAGS_test_flag_eb_06).DefaultValue(),
+ "0");
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_01), false);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_02), 0);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_03), 0);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_04), 0.0);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_05), "");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_eb_06),
+ NonTriviallyCopyableAggregate{});
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, TestGetSet) {
+ absl::SetFlag(&FLAGS_test_flag_01, false);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), false);
+
+ absl::SetFlag(&FLAGS_test_flag_02, 321);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 321);
+
+ absl::SetFlag(&FLAGS_test_flag_03, 67);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), 67);
+
+ absl::SetFlag(&FLAGS_test_flag_04, 1);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 1);
+
+ absl::SetFlag(&FLAGS_test_flag_05, -908);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), -908);
+
+ absl::SetFlag(&FLAGS_test_flag_06, 4001);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 4001);
+
+ absl::SetFlag(&FLAGS_test_flag_07, -23456);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -23456);
+
+ absl::SetFlag(&FLAGS_test_flag_08, 975310);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 975310);
+
+ absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), 1.00001, 1e-10);
+
+ absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), -3.54f, 1e-6f);
+
+ absl::SetFlag(&FLAGS_test_flag_11, "asdf");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "asdf");
+
+ absl::SetFlag(&FLAGS_test_flag_12, absl::Seconds(110));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Seconds(110));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, TestGetViaReflection) {
+ auto* handle = absl::FindCommandLineFlag("test_flag_01");
+ EXPECT_EQ(*handle->TryGet<bool>(), true);
+ handle = absl::FindCommandLineFlag("test_flag_02");
+ EXPECT_EQ(*handle->TryGet<int>(), 1234);
+ handle = absl::FindCommandLineFlag("test_flag_03");
+ EXPECT_EQ(*handle->TryGet<int16_t>(), -34);
+ handle = absl::FindCommandLineFlag("test_flag_04");
+ EXPECT_EQ(*handle->TryGet<uint16_t>(), 189);
+ handle = absl::FindCommandLineFlag("test_flag_05");
+ EXPECT_EQ(*handle->TryGet<int32_t>(), 10765);
+ handle = absl::FindCommandLineFlag("test_flag_06");
+ EXPECT_EQ(*handle->TryGet<uint32_t>(), 40000);
+ handle = absl::FindCommandLineFlag("test_flag_07");
+ EXPECT_EQ(*handle->TryGet<int64_t>(), -1234567);
+ handle = absl::FindCommandLineFlag("test_flag_08");
+ EXPECT_EQ(*handle->TryGet<uint64_t>(), 9876543);
+ handle = absl::FindCommandLineFlag("test_flag_09");
+ EXPECT_NEAR(*handle->TryGet<double>(), -9.876e-50, 1e-55);
+ handle = absl::FindCommandLineFlag("test_flag_10");
+ EXPECT_NEAR(*handle->TryGet<float>(), 1.234e12f, 1e5f);
+ handle = absl::FindCommandLineFlag("test_flag_11");
+ EXPECT_EQ(*handle->TryGet<std::string>(), "");
+ handle = absl::FindCommandLineFlag("test_flag_12");
+ EXPECT_EQ(*handle->TryGet<absl::Duration>(), absl::Minutes(10));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagTest, ConcurrentSetAndGet) {
+ static constexpr int kNumThreads = 8;
+ // Two arbitrary durations. One thread will concurrently flip the flag
+ // between these two values, while the other threads read it and verify
+ // that no other value is seen.
+ static const absl::Duration kValidDurations[] = {
+ absl::Seconds(int64_t{0x6cebf47a9b68c802}) + absl::Nanoseconds(229702057),
+ absl::Seconds(int64_t{0x23fec0307e4e9d3}) + absl::Nanoseconds(44555374)};
+ absl::SetFlag(&FLAGS_test_flag_12, kValidDurations[0]);
+
+ std::atomic<bool> stop{false};
+ std::vector<std::thread> threads;
+ auto* handle = absl::FindCommandLineFlag("test_flag_12");
+ for (int i = 0; i < kNumThreads; i++) {
+ threads.emplace_back([&]() {
+ while (!stop.load(std::memory_order_relaxed)) {
+ // Try loading the flag both directly and via a reflection
+ // handle.
+ absl::Duration v = absl::GetFlag(FLAGS_test_flag_12);
+ EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
+ v = *handle->TryGet<absl::Duration>();
+ EXPECT_TRUE(v == kValidDurations[0] || v == kValidDurations[1]);
+ }
+ });
+ }
+ absl::Time end_time = absl::Now() + absl::Seconds(1);
+ int i = 0;
+ while (absl::Now() < end_time) {
+ absl::SetFlag(&FLAGS_test_flag_12,
+ kValidDurations[i++ % ABSL_ARRAYSIZE(kValidDurations)]);
+ }
+ stop.store(true, std::memory_order_relaxed);
+ for (auto& t : threads) t.join();
+}
+
+// --------------------------------------------------------------------
+
+int GetDflt1() { return 1; }
+
+} // namespace
+
+ABSL_FLAG(int, test_int_flag_with_non_const_default, GetDflt1(),
+ "test int flag non const default");
+ABSL_FLAG(std::string, test_string_flag_with_non_const_default,
+ absl::StrCat("AAA", "BBB"), "test string flag non const default");
+
+namespace {
+
+TEST_F(FlagTest, TestNonConstexprDefault) {
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_int_flag_with_non_const_default), 1);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_string_flag_with_non_const_default),
+ "AAABBB");
+}
+
+// --------------------------------------------------------------------
+
+} // namespace
+
+ABSL_FLAG(bool, test_flag_with_non_const_help, true,
+ absl::StrCat("test ", "flag ", "non const help"));
+
+namespace {
+
+#if !ABSL_FLAGS_STRIP_HELP
+TEST_F(FlagTest, TestNonConstexprHelp) {
+ EXPECT_EQ(
+ absl::GetFlagReflectionHandle(FLAGS_test_flag_with_non_const_help).Help(),
+ "test flag non const help");
+}
+#endif //! ABSL_FLAGS_STRIP_HELP
+
+// --------------------------------------------------------------------
+
+int cb_test_value = -1;
+void TestFlagCB();
+
+} // namespace
+
+ABSL_FLAG(int, test_flag_with_cb, 100, "").OnUpdate(TestFlagCB);
+
+ABSL_FLAG(int, test_flag_with_lambda_cb, 200, "").OnUpdate([]() {
+ cb_test_value = absl::GetFlag(FLAGS_test_flag_with_lambda_cb) +
+ absl::GetFlag(FLAGS_test_flag_with_cb);
+});
+
+namespace {
+
+void TestFlagCB() { cb_test_value = absl::GetFlag(FLAGS_test_flag_with_cb); }
+
+// Tests side-effects of callback invocation.
+TEST_F(FlagTest, CallbackInvocation) {
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_cb), 100);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_with_lambda_cb), 200);
+ EXPECT_EQ(cb_test_value, 300);
+
+ absl::SetFlag(&FLAGS_test_flag_with_cb, 1);
+ EXPECT_EQ(cb_test_value, 1);
+
+ absl::SetFlag(&FLAGS_test_flag_with_lambda_cb, 3);
+ EXPECT_EQ(cb_test_value, 4);
+}
+
+// --------------------------------------------------------------------
+
+struct CustomUDT {
+ CustomUDT() : a(1), b(1) {}
+ CustomUDT(int a_, int b_) : a(a_), b(b_) {}
+
+ friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
+ return f1.a == f2.a && f1.b == f2.b;
+ }
+
+ int a;
+ int b;
+};
+bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
+ std::vector<absl::string_view> parts =
+ absl::StrSplit(in, ':', absl::SkipWhitespace());
+
+ if (parts.size() != 2) return false;
+
+ if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
+
+ if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
+
+ return true;
+}
+std::string AbslUnparseFlag(const CustomUDT& f) {
+ return absl::StrCat(f.a, ":", f.b);
+}
+
+} // namespace
+
+ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
+
+namespace {
+
+TEST_F(FlagTest, TestCustomUDT) {
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(1, 1));
+ absl::SetFlag(&FLAGS_test_flag_custom_udt, CustomUDT(2, 3));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_custom_udt), CustomUDT(2, 3));
+}
+
+// MSVC produces link error on the type mismatch.
+// Linux does not have build errors and validations work as expected.
+#if !defined(_WIN32) && GTEST_HAS_DEATH_TEST
+
+using FlagDeathTest = FlagTest;
+
+TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
+#if !defined(NDEBUG)
+ EXPECT_DEATH_IF_SUPPORTED(
+ static_cast<void>(absl::GetFlag(FLAGS_mistyped_int_flag)),
+ "Flag 'mistyped_int_flag' is defined as one type and declared "
+ "as another");
+ EXPECT_DEATH_IF_SUPPORTED(
+ static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
+ "Flag 'mistyped_string_flag' is defined as one type and "
+ "declared as another");
+#endif
+
+ EXPECT_DEATH_IF_SUPPORTED(
+ absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
+ "Flag 'mistyped_int_flag' is defined as one type and declared "
+ "as another");
+ EXPECT_DEATH_IF_SUPPORTED(
+ absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
+ "Flag 'mistyped_string_flag' is defined as one type and declared as "
+ "another");
+}
+
+#endif
+
+// --------------------------------------------------------------------
+
+// A contrived type that offers implicit and explicit conversion from specific
+// source types.
+struct ConversionTestVal {
+ ConversionTestVal() = default;
+ explicit ConversionTestVal(int a_in) : a(a_in) {}
+
+ enum class ViaImplicitConv { kTen = 10, kEleven };
+ // NOLINTNEXTLINE
+ ConversionTestVal(ViaImplicitConv from) : a(static_cast<int>(from)) {}
+
+ int a;
+};
+
+bool AbslParseFlag(absl::string_view in, ConversionTestVal* val_out,
+ std::string*) {
+ if (!absl::SimpleAtoi(in, &val_out->a)) {
+ return false;
+ }
+ return true;
+}
+std::string AbslUnparseFlag(const ConversionTestVal& val) {
+ return absl::StrCat(val.a);
+}
+
+} // namespace
+
+// Flag default values can be specified with a value that converts to the flag
+// value type implicitly.
+ABSL_FLAG(ConversionTestVal, test_flag_implicit_conv,
+ ConversionTestVal::ViaImplicitConv::kTen,
+ "test flag init via implicit conversion");
+
+namespace {
+
+TEST_F(FlagTest, CanSetViaImplicitConversion) {
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
+ absl::SetFlag(&FLAGS_test_flag_implicit_conv,
+ ConversionTestVal::ViaImplicitConv::kEleven);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
+}
+
+// --------------------------------------------------------------------
+
+struct NonDfltConstructible {
+ public:
+ // This constructor tests that we can initialize the flag with int value
+ NonDfltConstructible(int i) : value(i) {} // NOLINT
+
+ // This constructor tests that we can't initialize the flag with char value
+ // but can with explicitly constructed NonDfltConstructible.
+ explicit NonDfltConstructible(char c) : value(100 + static_cast<int>(c)) {}
+
+ int value;
+};
+
+bool AbslParseFlag(absl::string_view in, NonDfltConstructible* ndc_out,
+ std::string*) {
+ return absl::SimpleAtoi(in, &ndc_out->value);
+}
+std::string AbslUnparseFlag(const NonDfltConstructible& ndc) {
+ return absl::StrCat(ndc.value);
+}
+
+} // namespace
+
+ABSL_FLAG(NonDfltConstructible, ndc_flag1, NonDfltConstructible('1'),
+ "Flag with non default constructible type");
+ABSL_FLAG(NonDfltConstructible, ndc_flag2, 0,
+ "Flag with non default constructible type");
+
+namespace {
+
+TEST_F(FlagTest, TestNonDefaultConstructibleType) {
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, '1' + 100);
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 0);
+
+ absl::SetFlag(&FLAGS_ndc_flag1, NonDfltConstructible('A'));
+ absl::SetFlag(&FLAGS_ndc_flag2, 25);
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag1).value, 'A' + 100);
+ EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+
+ABSL_RETIRED_FLAG(bool, old_bool_flag, true, "old descr");
+ABSL_RETIRED_FLAG(int, old_int_flag, (int)std::sqrt(10), "old descr");
+ABSL_RETIRED_FLAG(std::string, old_str_flag, "", absl::StrCat("old ", "descr"));
+
+bool initializaion_order_fiasco_test = [] {
+ // Iterate over all the flags during static initialization.
+ // This should not trigger ASan's initialization-order-fiasco.
+ auto* handle1 = absl::FindCommandLineFlag("flag_on_separate_file");
+ auto* handle2 = absl::FindCommandLineFlag("retired_flag_on_separate_file");
+ if (handle1 != nullptr && handle2 != nullptr) {
+ return handle1->Name() == handle2->Name();
+ }
+ return true;
+}();
+
+namespace {
+
+TEST_F(FlagTest, TestRetiredFlagRegistration) {
+ auto* handle = absl::FindCommandLineFlag("old_bool_flag");
+ EXPECT_TRUE(handle->IsOfType<bool>());
+ EXPECT_TRUE(handle->IsRetired());
+ handle = absl::FindCommandLineFlag("old_int_flag");
+ EXPECT_TRUE(handle->IsOfType<int>());
+ EXPECT_TRUE(handle->IsRetired());
+ handle = absl::FindCommandLineFlag("old_str_flag");
+ EXPECT_TRUE(handle->IsOfType<std::string>());
+ EXPECT_TRUE(handle->IsRetired());
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+
+namespace {
+
+// User-defined type with small alignment, but size exceeding 16.
+struct SmallAlignUDT {
+ SmallAlignUDT() : c('A'), s(12) {}
+ char c;
+ int16_t s;
+ char bytes[14];
+};
+
+bool AbslParseFlag(absl::string_view, SmallAlignUDT*, std::string*) {
+ return true;
+}
+std::string AbslUnparseFlag(const SmallAlignUDT&) { return ""; }
+
+// User-defined type with small size, but not trivially copyable.
+struct NonTriviallyCopyableUDT {
+ NonTriviallyCopyableUDT() : c('A') {}
+ NonTriviallyCopyableUDT(const NonTriviallyCopyableUDT& rhs) : c(rhs.c) {}
+ NonTriviallyCopyableUDT& operator=(const NonTriviallyCopyableUDT& rhs) {
+ c = rhs.c;
+ return *this;
+ }
+
+ char c;
+};
+
+bool AbslParseFlag(absl::string_view, NonTriviallyCopyableUDT*, std::string*) {
+ return true;
+}
+std::string AbslUnparseFlag(const NonTriviallyCopyableUDT&) { return ""; }
+
+} // namespace
+
+ABSL_FLAG(SmallAlignUDT, test_flag_sa_udt, {}, "help");
+ABSL_FLAG(NonTriviallyCopyableUDT, test_flag_ntc_udt, {}, "help");
+
+namespace {
+
+TEST_F(FlagTest, TestSmallAlignUDT) {
+ SmallAlignUDT value = absl::GetFlag(FLAGS_test_flag_sa_udt);
+ EXPECT_EQ(value.c, 'A');
+ EXPECT_EQ(value.s, 12);
+
+ value.c = 'B';
+ value.s = 45;
+ absl::SetFlag(&FLAGS_test_flag_sa_udt, value);
+ value = absl::GetFlag(FLAGS_test_flag_sa_udt);
+ EXPECT_EQ(value.c, 'B');
+ EXPECT_EQ(value.s, 45);
+}
+
+TEST_F(FlagTest, TestNonTriviallyCopyableUDT) {
+ NonTriviallyCopyableUDT value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
+ EXPECT_EQ(value.c, 'A');
+
+ value.c = 'B';
+ absl::SetFlag(&FLAGS_test_flag_ntc_udt, value);
+ value = absl::GetFlag(FLAGS_test_flag_ntc_udt);
+ EXPECT_EQ(value.c, 'B');
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test_defs.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test_defs.cc
new file mode 100644
index 00000000000..4e1693cdb9c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/flag_test_defs.cc
@@ -0,0 +1,24 @@
+//
+// 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.
+
+// This file is used to test the mismatch of the flag type between definition
+// and declaration. These are definitions. flag_test.cc contains declarations.
+#include <string>
+#include "absl/flags/flag.h"
+
+ABSL_FLAG(int, mistyped_int_flag, 0, "");
+ABSL_FLAG(std::string, mistyped_string_flag, "", "");
+ABSL_FLAG(bool, flag_on_separate_file, false, "");
+ABSL_RETIRED_FLAG(bool, retired_flag_on_separate_file, false, "");
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/commandlineflag.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/commandlineflag.h
new file mode 100644
index 00000000000..ebfe81ba1e3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/commandlineflag.h
@@ -0,0 +1,68 @@
+//
+// 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_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+
+#include "absl/base/config.h"
+#include "absl/base/internal/fast_type_id.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// An alias for flag fast type id. This value identifies the flag value type
+// similarly to typeid(T), without relying on RTTI being available. In most
+// cases this id is enough to uniquely identify the flag's value type. In a few
+// cases we'll have to resort to using actual RTTI implementation if it is
+// available.
+using FlagFastTypeId = absl::base_internal::FastTypeIdType;
+
+// Options that control SetCommandLineOptionWithMode.
+enum FlagSettingMode {
+ // update the flag's value unconditionally (can call this multiple times).
+ SET_FLAGS_VALUE,
+ // update the flag's value, but *only if* it has not yet been updated
+ // with SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef".
+ SET_FLAG_IF_DEFAULT,
+ // set the flag's default value to this. If the flag has not been updated
+ // yet (via SET_FLAGS_VALUE, SET_FLAG_IF_DEFAULT, or "FLAGS_xxx = nondef")
+ // change the flag's current value to the new default value as well.
+ SET_FLAGS_DEFAULT
+};
+
+// Options that control ParseFrom: Source of a value.
+enum ValueSource {
+ // Flag is being set by value specified on a command line.
+ kCommandLine,
+ // Flag is being set by value specified in the code.
+ kProgrammaticChange,
+};
+
+// Handle to FlagState objects. Specific flag state objects will restore state
+// of a flag produced this flag state from method CommandLineFlag::SaveState().
+class FlagStateInterface {
+ public:
+ virtual ~FlagStateInterface();
+
+ // Restores the flag originated this object to the saved state.
+ virtual void Restore() const = 0;
+};
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.cc
new file mode 100644
index 00000000000..f83c1fe723f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.cc
@@ -0,0 +1,581 @@
+//
+// 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.
+
+#include "absl/flags/internal/flag.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+#include <new>
+#include <string>
+#include <typeinfo>
+
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// The help message indicating that the commandline flag has been
+// 'stripped'. It will not show up when doing "-help" and its
+// variants. The flag is stripped if ABSL_FLAGS_STRIP_HELP is set to 1
+// before including absl/flags/flag.h
+const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
+
+namespace {
+
+// Currently we only validate flag values for user-defined flag types.
+bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
+#define DONT_VALIDATE(T, _) \
+ if (flag_type_id == base_internal::FastTypeId<T>()) return false;
+ ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(DONT_VALIDATE)
+#undef DONT_VALIDATE
+
+ return true;
+}
+
+// RAII helper used to temporarily unlock and relock `absl::Mutex`.
+// This is used when we need to ensure that locks are released while
+// invoking user supplied callbacks and then reacquired, since callbacks may
+// need to acquire these locks themselves.
+class MutexRelock {
+ public:
+ explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
+ ~MutexRelock() { mu_.Lock(); }
+
+ MutexRelock(const MutexRelock&) = delete;
+ MutexRelock& operator=(const MutexRelock&) = delete;
+
+ private:
+ absl::Mutex& mu_;
+};
+
+} // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+// Persistent state of the flag data.
+
+class FlagImpl;
+
+class FlagState : public flags_internal::FlagStateInterface {
+ public:
+ template <typename V>
+ FlagState(FlagImpl& flag_impl, const V& v, bool modified,
+ bool on_command_line, int64_t counter)
+ : flag_impl_(flag_impl),
+ value_(v),
+ modified_(modified),
+ on_command_line_(on_command_line),
+ counter_(counter) {}
+
+ ~FlagState() override {
+ if (flag_impl_.ValueStorageKind() != FlagValueStorageKind::kAlignedBuffer &&
+ flag_impl_.ValueStorageKind() != FlagValueStorageKind::kSequenceLocked)
+ return;
+ flags_internal::Delete(flag_impl_.op_, value_.heap_allocated);
+ }
+
+ private:
+ friend class FlagImpl;
+
+ // Restores the flag to the saved state.
+ void Restore() const override {
+ if (!flag_impl_.RestoreState(*this)) return;
+
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("Restore saved value of ", flag_impl_.Name(),
+ " to: ", flag_impl_.CurrentValue()));
+ }
+
+ // Flag and saved flag data.
+ FlagImpl& flag_impl_;
+ union SavedValue {
+ explicit SavedValue(void* v) : heap_allocated(v) {}
+ explicit SavedValue(int64_t v) : one_word(v) {}
+
+ void* heap_allocated;
+ int64_t one_word;
+ } value_;
+ bool modified_;
+ bool on_command_line_;
+ int64_t counter_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+
+DynValueDeleter::DynValueDeleter(FlagOpFn op_arg) : op(op_arg) {}
+
+void DynValueDeleter::operator()(void* ptr) const {
+ if (op == nullptr) return;
+
+ Delete(op, ptr);
+}
+
+void FlagImpl::Init() {
+ new (&data_guard_) absl::Mutex;
+
+ auto def_kind = static_cast<FlagDefaultKind>(def_kind_);
+
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer:
+ // For this storage kind the default_value_ always points to gen_func
+ // during initialization.
+ assert(def_kind == FlagDefaultKind::kGenFunc);
+ (*default_value_.gen_func)(AlignedBufferValue());
+ break;
+ case FlagValueStorageKind::kOneWordAtomic: {
+ alignas(int64_t) std::array<char, sizeof(int64_t)> buf{};
+ if (def_kind == FlagDefaultKind::kGenFunc) {
+ (*default_value_.gen_func)(buf.data());
+ } else {
+ assert(def_kind != FlagDefaultKind::kDynamicValue);
+ std::memcpy(buf.data(), &default_value_, Sizeof(op_));
+ }
+ OneWordValue().store(absl::bit_cast<int64_t>(buf),
+ std::memory_order_release);
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ // For this storage kind the default_value_ always points to gen_func
+ // during initialization.
+ assert(def_kind == FlagDefaultKind::kGenFunc);
+ (*default_value_.gen_func)(AtomicBufferValue());
+ break;
+ }
+ }
+ seq_lock_.MarkInitialized();
+}
+
+absl::Mutex* FlagImpl::DataGuard() const {
+ absl::call_once(const_cast<FlagImpl*>(this)->init_control_, &FlagImpl::Init,
+ const_cast<FlagImpl*>(this));
+
+ // data_guard_ is initialized inside Init.
+ return reinterpret_cast<absl::Mutex*>(&data_guard_);
+}
+
+void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
+ const std::type_info* (*gen_rtti)()) const {
+ FlagFastTypeId lhs_type_id = flags_internal::FastTypeId(op_);
+
+ // `rhs_type_id` is the fast type id corresponding to the declaration
+ // visibile at the call site. `lhs_type_id` is the fast type id
+ // corresponding to the type specified in flag definition. They must match
+ // for this operation to be well-defined.
+ if (ABSL_PREDICT_TRUE(lhs_type_id == rhs_type_id)) return;
+
+ const std::type_info* lhs_runtime_type_id =
+ flags_internal::RuntimeTypeId(op_);
+ const std::type_info* rhs_runtime_type_id = (*gen_rtti)();
+
+ if (lhs_runtime_type_id == rhs_runtime_type_id) return;
+
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+ if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
+#endif
+
+ ABSL_INTERNAL_LOG(
+ FATAL, absl::StrCat("Flag '", Name(),
+ "' is defined as one type and declared as another"));
+}
+
+std::unique_ptr<void, DynValueDeleter> FlagImpl::MakeInitValue() const {
+ void* res = nullptr;
+ switch (DefaultKind()) {
+ case FlagDefaultKind::kDynamicValue:
+ res = flags_internal::Clone(op_, default_value_.dynamic_value);
+ break;
+ case FlagDefaultKind::kGenFunc:
+ res = flags_internal::Alloc(op_);
+ (*default_value_.gen_func)(res);
+ break;
+ default:
+ res = flags_internal::Clone(op_, &default_value_);
+ break;
+ }
+ return {res, DynValueDeleter{op_}};
+}
+
+void FlagImpl::StoreValue(const void* src) {
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer:
+ Copy(op_, src, AlignedBufferValue());
+ seq_lock_.IncrementModificationCount();
+ break;
+ case FlagValueStorageKind::kOneWordAtomic: {
+ int64_t one_word_val = 0;
+ std::memcpy(&one_word_val, src, Sizeof(op_));
+ OneWordValue().store(one_word_val, std::memory_order_release);
+ seq_lock_.IncrementModificationCount();
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ seq_lock_.Write(AtomicBufferValue(), src, Sizeof(op_));
+ break;
+ }
+ }
+ modified_ = true;
+ InvokeCallback();
+}
+
+absl::string_view FlagImpl::Name() const { return name_; }
+
+std::string FlagImpl::Filename() const {
+ return flags_internal::GetUsageConfig().normalize_filename(filename_);
+}
+
+std::string FlagImpl::Help() const {
+ return HelpSourceKind() == FlagHelpKind::kLiteral ? help_.literal
+ : help_.gen_func();
+}
+
+FlagFastTypeId FlagImpl::TypeId() const {
+ return flags_internal::FastTypeId(op_);
+}
+
+int64_t FlagImpl::ModificationCount() const {
+ return seq_lock_.ModificationCount();
+}
+
+bool FlagImpl::IsSpecifiedOnCommandLine() const {
+ absl::MutexLock l(DataGuard());
+ return on_command_line_;
+}
+
+std::string FlagImpl::DefaultValue() const {
+ absl::MutexLock l(DataGuard());
+
+ auto obj = MakeInitValue();
+ return flags_internal::Unparse(op_, obj.get());
+}
+
+std::string FlagImpl::CurrentValue() const {
+ auto* guard = DataGuard(); // Make sure flag initialized
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer: {
+ absl::MutexLock l(guard);
+ return flags_internal::Unparse(op_, AlignedBufferValue());
+ }
+ case FlagValueStorageKind::kOneWordAtomic: {
+ const auto one_word_val =
+ absl::bit_cast<std::array<char, sizeof(int64_t)>>(
+ OneWordValue().load(std::memory_order_acquire));
+ return flags_internal::Unparse(op_, one_word_val.data());
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ std::unique_ptr<void, DynValueDeleter> cloned(flags_internal::Alloc(op_),
+ DynValueDeleter{op_});
+ ReadSequenceLockedData(cloned.get());
+ return flags_internal::Unparse(op_, cloned.get());
+ }
+ }
+
+ return "";
+}
+
+void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
+ absl::MutexLock l(DataGuard());
+
+ if (callback_ == nullptr) {
+ callback_ = new FlagCallback;
+ }
+ callback_->func = mutation_callback;
+
+ InvokeCallback();
+}
+
+void FlagImpl::InvokeCallback() const {
+ if (!callback_) return;
+
+ // Make a copy of the C-style function pointer that we are about to invoke
+ // before we release the lock guarding it.
+ FlagCallbackFunc cb = callback_->func;
+
+ // If the flag has a mutation callback this function invokes it. While the
+ // callback is being invoked the primary flag's mutex is unlocked and it is
+ // re-locked back after call to callback is completed. Callback invocation is
+ // guarded by flag's secondary mutex instead which prevents concurrent
+ // callback invocation. Note that it is possible for other thread to grab the
+ // primary lock and update flag's value at any time during the callback
+ // invocation. This is by design. Callback can get a value of the flag if
+ // necessary, but it might be different from the value initiated the callback
+ // and it also can be different by the time the callback invocation is
+ // completed. Requires that *primary_lock be held in exclusive mode; it may be
+ // released and reacquired by the implementation.
+ MutexRelock relock(*DataGuard());
+ absl::MutexLock lock(&callback_->guard);
+ cb();
+}
+
+std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
+ absl::MutexLock l(DataGuard());
+
+ bool modified = modified_;
+ bool on_command_line = on_command_line_;
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer: {
+ return absl::make_unique<FlagState>(
+ *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
+ on_command_line, ModificationCount());
+ }
+ case FlagValueStorageKind::kOneWordAtomic: {
+ return absl::make_unique<FlagState>(
+ *this, OneWordValue().load(std::memory_order_acquire), modified,
+ on_command_line, ModificationCount());
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ void* cloned = flags_internal::Alloc(op_);
+ // Read is guaranteed to be successful because we hold the lock.
+ bool success =
+ seq_lock_.TryRead(cloned, AtomicBufferValue(), Sizeof(op_));
+ assert(success);
+ static_cast<void>(success);
+ return absl::make_unique<FlagState>(*this, cloned, modified,
+ on_command_line, ModificationCount());
+ }
+ }
+ return nullptr;
+}
+
+bool FlagImpl::RestoreState(const FlagState& flag_state) {
+ absl::MutexLock l(DataGuard());
+ if (flag_state.counter_ == ModificationCount()) {
+ return false;
+ }
+
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer:
+ case FlagValueStorageKind::kSequenceLocked:
+ StoreValue(flag_state.value_.heap_allocated);
+ break;
+ case FlagValueStorageKind::kOneWordAtomic:
+ StoreValue(&flag_state.value_.one_word);
+ break;
+ }
+
+ modified_ = flag_state.modified_;
+ on_command_line_ = flag_state.on_command_line_;
+
+ return true;
+}
+
+template <typename StorageT>
+StorageT* FlagImpl::OffsetValue() const {
+ char* p = reinterpret_cast<char*>(const_cast<FlagImpl*>(this));
+ // The offset is deduced via Flag value type specific op_.
+ size_t offset = flags_internal::ValueOffset(op_);
+
+ return reinterpret_cast<StorageT*>(p + offset);
+}
+
+void* FlagImpl::AlignedBufferValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kAlignedBuffer);
+ return OffsetValue<void>();
+}
+
+std::atomic<uint64_t>* FlagImpl::AtomicBufferValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kSequenceLocked);
+ return OffsetValue<std::atomic<uint64_t>>();
+}
+
+std::atomic<int64_t>& FlagImpl::OneWordValue() const {
+ assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic);
+ return OffsetValue<FlagOneWordValue>()->value;
+}
+
+// Attempts to parse supplied `value` string using parsing routine in the `flag`
+// argument. If parsing successful, this function replaces the dst with newly
+// parsed value. In case if any error is encountered in either step, the error
+// message is stored in 'err'
+std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
+ absl::string_view value, std::string& err) const {
+ std::unique_ptr<void, DynValueDeleter> tentative_value = MakeInitValue();
+
+ std::string parse_err;
+ if (!flags_internal::Parse(op_, value, tentative_value.get(), &parse_err)) {
+ absl::string_view err_sep = parse_err.empty() ? "" : "; ";
+ err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+ Name(), "'", err_sep, parse_err);
+ return nullptr;
+ }
+
+ return tentative_value;
+}
+
+void FlagImpl::Read(void* dst) const {
+ auto* guard = DataGuard(); // Make sure flag initialized
+ switch (ValueStorageKind()) {
+ case FlagValueStorageKind::kAlignedBuffer: {
+ absl::MutexLock l(guard);
+ flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
+ break;
+ }
+ case FlagValueStorageKind::kOneWordAtomic: {
+ const int64_t one_word_val =
+ OneWordValue().load(std::memory_order_acquire);
+ std::memcpy(dst, &one_word_val, Sizeof(op_));
+ break;
+ }
+ case FlagValueStorageKind::kSequenceLocked: {
+ ReadSequenceLockedData(dst);
+ break;
+ }
+ }
+}
+
+void FlagImpl::ReadSequenceLockedData(void* dst) const {
+ int size = Sizeof(op_);
+ // Attempt to read using the sequence lock.
+ if (ABSL_PREDICT_TRUE(seq_lock_.TryRead(dst, AtomicBufferValue(), size))) {
+ return;
+ }
+ // We failed due to contention. Acquire the lock to prevent contention
+ // and try again.
+ absl::ReaderMutexLock l(DataGuard());
+ bool success = seq_lock_.TryRead(dst, AtomicBufferValue(), size);
+ assert(success);
+ static_cast<void>(success);
+}
+
+void FlagImpl::Write(const void* src) {
+ absl::MutexLock l(DataGuard());
+
+ if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
+ std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
+ DynValueDeleter{op_}};
+ std::string ignored_error;
+ std::string src_as_str = flags_internal::Unparse(op_, src);
+ if (!flags_internal::Parse(op_, src_as_str, obj.get(), &ignored_error)) {
+ ABSL_INTERNAL_LOG(ERROR, absl::StrCat("Attempt to set flag '", Name(),
+ "' to invalid value ", src_as_str));
+ }
+ }
+
+ StoreValue(src);
+}
+
+// Sets the value of the flag based on specified string `value`. If the flag
+// was successfully set to new value, it returns true. Otherwise, sets `err`
+// to indicate the error, leaves the flag unchanged, and returns false. There
+// are three ways to set the flag's value:
+// * Update the current flag value
+// * Update the flag's default value
+// * Update the current flag value if it was never set before
+// The mode is selected based on 'set_mode' parameter.
+bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, std::string& err) {
+ absl::MutexLock l(DataGuard());
+
+ switch (set_mode) {
+ case SET_FLAGS_VALUE: {
+ // set or modify the flag's value
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ StoreValue(tentative_value.get());
+
+ if (source == kCommandLine) {
+ on_command_line_ = true;
+ }
+ break;
+ }
+ case SET_FLAG_IF_DEFAULT: {
+ // set the flag's value, but only if it hasn't been set by someone else
+ if (modified_) {
+ // TODO(rogeeff): review and fix this semantic. Currently we do not fail
+ // in this case if flag is modified. This is misleading since the flag's
+ // value is not updated even though we return true.
+ // *err = absl::StrCat(Name(), " is already set to ",
+ // CurrentValue(), "\n");
+ // return false;
+ return true;
+ }
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ StoreValue(tentative_value.get());
+ break;
+ }
+ case SET_FLAGS_DEFAULT: {
+ auto tentative_value = TryParse(value, err);
+ if (!tentative_value) return false;
+
+ if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
+ void* old_value = default_value_.dynamic_value;
+ default_value_.dynamic_value = tentative_value.release();
+ tentative_value.reset(old_value);
+ } else {
+ default_value_.dynamic_value = tentative_value.release();
+ def_kind_ = static_cast<uint8_t>(FlagDefaultKind::kDynamicValue);
+ }
+
+ if (!modified_) {
+ // Need to set both default value *and* current, in this case.
+ StoreValue(default_value_.dynamic_value);
+ modified_ = false;
+ }
+ break;
+ }
+ }
+
+ return true;
+}
+
+void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
+ std::string v = DefaultValue();
+
+ absl::MutexLock lock(DataGuard());
+
+ auto dst = MakeInitValue();
+ std::string error;
+ if (!flags_internal::Parse(op_, v, dst.get(), &error)) {
+ ABSL_INTERNAL_LOG(
+ FATAL,
+ absl::StrCat("Flag ", Name(), " (from ", Filename(),
+ "): string form of default value '", v,
+ "' could not be parsed; error=", error));
+ }
+
+ // We do not compare dst to def since parsing/unparsing may make
+ // small changes, e.g., precision loss for floating point types.
+}
+
+bool FlagImpl::ValidateInputValue(absl::string_view value) const {
+ absl::MutexLock l(DataGuard());
+
+ auto obj = MakeInitValue();
+ std::string ignored_error;
+ return flags_internal::Parse(op_, value, obj.get(), &ignored_error);
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.h
new file mode 100644
index 00000000000..e6bade0a8c5
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/flag.h
@@ -0,0 +1,747 @@
+//
+// 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_FLAGS_INTERNAL_FLAG_H_
+#define ABSL_FLAGS_INTERNAL_FLAG_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cstring>
+#include <memory>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <typeinfo>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/internal/sequence_lock.h"
+#include "absl/flags/marshalling.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+///////////////////////////////////////////////////////////////////////////////
+// Forward declaration of absl::Flag<T> public API.
+namespace flags_internal {
+template <typename T>
+class Flag;
+} // namespace flags_internal
+
+#if defined(_MSC_VER) && !defined(__clang__)
+template <typename T>
+class Flag;
+#else
+template <typename T>
+using Flag = flags_internal::Flag<T>;
+#endif
+
+template <typename T>
+ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag);
+
+template <typename T>
+void SetFlag(absl::Flag<T>* flag, const T& v);
+
+template <typename T, typename V>
+void SetFlag(absl::Flag<T>* flag, const V& v);
+
+template <typename U>
+const CommandLineFlag& GetFlagReflectionHandle(const absl::Flag<U>& f);
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag value type operations, eg., parsing, copying, etc. are provided
+// by function specific to that type with a signature matching FlagOpFn.
+
+namespace flags_internal {
+
+enum class FlagOp {
+ kAlloc,
+ kDelete,
+ kCopy,
+ kCopyConstruct,
+ kSizeof,
+ kFastTypeId,
+ kRuntimeTypeId,
+ kParse,
+ kUnparse,
+ kValueOffset,
+};
+using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
+
+// Forward declaration for Flag value specific operations.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3);
+
+// Allocate aligned memory for a flag value.
+inline void* Alloc(FlagOpFn op) {
+ return op(FlagOp::kAlloc, nullptr, nullptr, nullptr);
+}
+// Deletes memory interpreting obj as flag value type pointer.
+inline void Delete(FlagOpFn op, void* obj) {
+ op(FlagOp::kDelete, nullptr, obj, nullptr);
+}
+// Copies src to dst interpreting as flag value type pointers.
+inline void Copy(FlagOpFn op, const void* src, void* dst) {
+ op(FlagOp::kCopy, src, dst, nullptr);
+}
+// Construct a copy of flag value in a location pointed by dst
+// based on src - pointer to the flag's value.
+inline void CopyConstruct(FlagOpFn op, const void* src, void* dst) {
+ op(FlagOp::kCopyConstruct, src, dst, nullptr);
+}
+// Makes a copy of flag value pointed by obj.
+inline void* Clone(FlagOpFn op, const void* obj) {
+ void* res = flags_internal::Alloc(op);
+ flags_internal::CopyConstruct(op, obj, res);
+ return res;
+}
+// Returns true if parsing of input text is successfull.
+inline bool Parse(FlagOpFn op, absl::string_view text, void* dst,
+ std::string* error) {
+ return op(FlagOp::kParse, &text, dst, error) != nullptr;
+}
+// Returns string representing supplied value.
+inline std::string Unparse(FlagOpFn op, const void* val) {
+ std::string result;
+ op(FlagOp::kUnparse, val, &result, nullptr);
+ return result;
+}
+// Returns size of flag value type.
+inline size_t Sizeof(FlagOpFn op) {
+ // This sequence of casts reverses the sequence from
+ // `flags_internal::FlagOps()`
+ return static_cast<size_t>(reinterpret_cast<intptr_t>(
+ op(FlagOp::kSizeof, nullptr, nullptr, nullptr)));
+}
+// Returns fast type id coresponding to the value type.
+inline FlagFastTypeId FastTypeId(FlagOpFn op) {
+ return reinterpret_cast<FlagFastTypeId>(
+ op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
+}
+// Returns fast type id coresponding to the value type.
+inline const std::type_info* RuntimeTypeId(FlagOpFn op) {
+ return reinterpret_cast<const std::type_info*>(
+ op(FlagOp::kRuntimeTypeId, nullptr, nullptr, nullptr));
+}
+// Returns offset of the field value_ from the field impl_ inside of
+// absl::Flag<T> data. Given FlagImpl pointer p you can get the
+// location of the corresponding value as:
+// reinterpret_cast<char*>(p) + ValueOffset().
+inline ptrdiff_t ValueOffset(FlagOpFn op) {
+ // This sequence of casts reverses the sequence from
+ // `flags_internal::FlagOps()`
+ return static_cast<ptrdiff_t>(reinterpret_cast<intptr_t>(
+ op(FlagOp::kValueOffset, nullptr, nullptr, nullptr)));
+}
+
+// Returns an address of RTTI's typeid(T).
+template <typename T>
+inline const std::type_info* GenRuntimeTypeId() {
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+ return &typeid(T);
+#else
+ return nullptr;
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag help auxiliary structs.
+
+// This is help argument for absl::Flag encapsulating the string literal pointer
+// or pointer to function generating it as well as enum descriminating two
+// cases.
+using HelpGenFunc = std::string (*)();
+
+template <size_t N>
+struct FixedCharArray {
+ char value[N];
+
+ template <size_t... I>
+ static constexpr FixedCharArray<N> FromLiteralString(
+ absl::string_view str, absl::index_sequence<I...>) {
+ return (void)str, FixedCharArray<N>({{str[I]..., '\0'}});
+ }
+};
+
+template <typename Gen, size_t N = Gen::Value().size()>
+constexpr FixedCharArray<N + 1> HelpStringAsArray(int) {
+ return FixedCharArray<N + 1>::FromLiteralString(
+ Gen::Value(), absl::make_index_sequence<N>{});
+}
+
+template <typename Gen>
+constexpr std::false_type HelpStringAsArray(char) {
+ return std::false_type{};
+}
+
+union FlagHelpMsg {
+ constexpr explicit FlagHelpMsg(const char* help_msg) : literal(help_msg) {}
+ constexpr explicit FlagHelpMsg(HelpGenFunc help_gen) : gen_func(help_gen) {}
+
+ const char* literal;
+ HelpGenFunc gen_func;
+};
+
+enum class FlagHelpKind : uint8_t { kLiteral = 0, kGenFunc = 1 };
+
+struct FlagHelpArg {
+ FlagHelpMsg source;
+ FlagHelpKind kind;
+};
+
+extern const char kStrippedFlagHelp[];
+
+// These two HelpArg overloads allows us to select at compile time one of two
+// way to pass Help argument to absl::Flag. We'll be passing
+// AbslFlagHelpGenFor##name as Gen and integer 0 as a single argument to prefer
+// first overload if possible. If help message is evaluatable on constexpr
+// context We'll be able to make FixedCharArray out of it and we'll choose first
+// overload. In this case the help message expression is immediately evaluated
+// and is used to construct the absl::Flag. No additionl code is generated by
+// ABSL_FLAG Otherwise SFINAE kicks in and first overload is dropped from the
+// consideration, in which case the second overload will be used. The second
+// overload does not attempt to evaluate the help message expression
+// immediately and instead delays the evaluation by returing the function
+// pointer (&T::NonConst) genering the help message when necessary. This is
+// evaluatable in constexpr context, but the cost is an extra function being
+// generated in the ABSL_FLAG code.
+template <typename Gen, size_t N>
+constexpr FlagHelpArg HelpArg(const FixedCharArray<N>& value) {
+ return {FlagHelpMsg(value.value), FlagHelpKind::kLiteral};
+}
+
+template <typename Gen>
+constexpr FlagHelpArg HelpArg(std::false_type) {
+ return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag default value auxiliary structs.
+
+// Signature for the function generating the initial flag value (usually
+// based on default value supplied in flag's definition)
+using FlagDfltGenFunc = void (*)(void*);
+
+union FlagDefaultSrc {
+ constexpr explicit FlagDefaultSrc(FlagDfltGenFunc gen_func_arg)
+ : gen_func(gen_func_arg) {}
+
+#define ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE(T, name) \
+ T name##_value; \
+ constexpr explicit FlagDefaultSrc(T value) : name##_value(value) {} // NOLINT
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE)
+#undef ABSL_FLAGS_INTERNAL_DFLT_FOR_TYPE
+
+ void* dynamic_value;
+ FlagDfltGenFunc gen_func;
+};
+
+enum class FlagDefaultKind : uint8_t {
+ kDynamicValue = 0,
+ kGenFunc = 1,
+ kOneWord = 2 // for default values UP to one word in size
+};
+
+struct FlagDefaultArg {
+ FlagDefaultSrc source;
+ FlagDefaultKind kind;
+};
+
+// This struct and corresponding overload to InitDefaultValue are used to
+// facilitate usage of {} as default value in ABSL_FLAG macro.
+// TODO(rogeeff): Fix handling types with explicit constructors.
+struct EmptyBraces {};
+
+template <typename T>
+constexpr T InitDefaultValue(T t) {
+ return t;
+}
+
+template <typename T>
+constexpr T InitDefaultValue(EmptyBraces) {
+ return T{};
+}
+
+template <typename ValueT, typename GenT,
+ typename std::enable_if<std::is_integral<ValueT>::value, int>::type =
+ (GenT{}, 0)>
+constexpr FlagDefaultArg DefaultArg(int) {
+ return {FlagDefaultSrc(GenT{}.value), FlagDefaultKind::kOneWord};
+}
+
+template <typename ValueT, typename GenT>
+constexpr FlagDefaultArg DefaultArg(char) {
+ return {FlagDefaultSrc(&GenT::Gen), FlagDefaultKind::kGenFunc};
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag current value auxiliary structs.
+
+constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; }
+
+template <typename T>
+using FlagUseOneWordStorage = std::integral_constant<
+ bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+ (sizeof(T) <= 8)>;
+
+template <class T>
+using FlagShouldUseSequenceLock = std::integral_constant<
+ bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
+ (sizeof(T) > 8)>;
+
+enum class FlagValueStorageKind : uint8_t {
+ kAlignedBuffer = 0,
+ kOneWordAtomic = 1,
+ kSequenceLocked = 2,
+};
+
+template <typename T>
+static constexpr FlagValueStorageKind StorageKind() {
+ return FlagUseOneWordStorage<T>::value ? FlagValueStorageKind::kOneWordAtomic
+ : FlagShouldUseSequenceLock<T>::value
+ ? FlagValueStorageKind::kSequenceLocked
+ : FlagValueStorageKind::kAlignedBuffer;
+}
+
+struct FlagOneWordValue {
+ constexpr FlagOneWordValue() : value(UninitializedFlagValue()) {}
+
+ std::atomic<int64_t> value;
+};
+
+template <typename T,
+ FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
+struct FlagValue;
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
+ bool Get(const SequenceLock&, T&) const { return false; }
+
+ alignas(T) char value[sizeof(T)];
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
+ bool Get(const SequenceLock&, T& dst) const {
+ int64_t one_word_val = value.load(std::memory_order_acquire);
+ if (ABSL_PREDICT_FALSE(one_word_val == UninitializedFlagValue())) {
+ return false;
+ }
+ std::memcpy(&dst, static_cast<const void*>(&one_word_val), sizeof(T));
+ return true;
+ }
+};
+
+template <typename T>
+struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
+ bool Get(const SequenceLock& lock, T& dst) const {
+ return lock.TryRead(&dst, value_words, sizeof(T));
+ }
+
+ static constexpr int kNumWords =
+ flags_internal::AlignUp(sizeof(T), sizeof(uint64_t)) / sizeof(uint64_t);
+
+ alignas(T) alignas(
+ std::atomic<uint64_t>) std::atomic<uint64_t> value_words[kNumWords];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag callback auxiliary structs.
+
+// Signature for the mutation callback used by watched Flags
+// The callback is noexcept.
+// TODO(rogeeff): add noexcept after C++17 support is added.
+using FlagCallbackFunc = void (*)();
+
+struct FlagCallback {
+ FlagCallbackFunc func;
+ absl::Mutex guard; // Guard for concurrent callback invocations.
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Flag implementation, which does not depend on flag value type.
+// The class encapsulates the Flag's data and access to it.
+
+struct DynValueDeleter {
+ explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
+ void operator()(void* ptr) const;
+
+ FlagOpFn op;
+};
+
+class FlagState;
+
+class FlagImpl final : public CommandLineFlag {
+ public:
+ constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
+ FlagHelpArg help, FlagValueStorageKind value_kind,
+ FlagDefaultArg default_arg)
+ : name_(name),
+ filename_(filename),
+ op_(op),
+ help_(help.source),
+ help_source_kind_(static_cast<uint8_t>(help.kind)),
+ value_storage_kind_(static_cast<uint8_t>(value_kind)),
+ def_kind_(static_cast<uint8_t>(default_arg.kind)),
+ modified_(false),
+ on_command_line_(false),
+ callback_(nullptr),
+ default_value_(default_arg.source),
+ data_guard_{} {}
+
+ // Constant access methods
+ void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Mutating access methods
+ void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Interfaces to operate on callbacks.
+ void SetCallback(const FlagCallbackFunc mutation_callback)
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void InvokeCallback() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Used in read/write operations to validate source/target has correct type.
+ // For example if flag is declared as absl::Flag<int> FLAGS_foo, a call to
+ // absl::GetFlag(FLAGS_foo) validates that the type of FLAGS_foo is indeed
+ // int. To do that we pass the "assumed" type id (which is deduced from type
+ // int) as an argument `type_id`, which is in turn is validated against the
+ // type id stored in flag object by flag definition statement.
+ void AssertValidType(FlagFastTypeId type_id,
+ const std::type_info* (*gen_rtti)()) const;
+
+ private:
+ template <typename T>
+ friend class Flag;
+ friend class FlagState;
+
+ // Ensures that `data_guard_` is initialized and returns it.
+ absl::Mutex* DataGuard() const
+ ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
+ // Returns heap allocated value of type T initialized with default value.
+ std::unique_ptr<void, DynValueDeleter> MakeInitValue() const
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+ // Flag initialization called via absl::call_once.
+ void Init();
+
+ // Offset value access methods. One per storage kind. These methods to not
+ // respect const correctness, so be very carefull using them.
+
+ // This is a shared helper routine which encapsulates most of the magic. Since
+ // it is only used inside the three routines below, which are defined in
+ // flag.cc, we can define it in that file as well.
+ template <typename StorageT>
+ StorageT* OffsetValue() const;
+ // This is an accessor for a value stored in an aligned buffer storage
+ // used for non-trivially-copyable data types.
+ // Returns a mutable pointer to the start of a buffer.
+ void* AlignedBufferValue() const;
+
+ // The same as above, but used for sequencelock-protected storage.
+ std::atomic<uint64_t>* AtomicBufferValue() const;
+
+ // This is an accessor for a value stored as one word atomic. Returns a
+ // mutable reference to an atomic value.
+ std::atomic<int64_t>& OneWordValue() const;
+
+ // Attempts to parse supplied `value` string. If parsing is successful,
+ // returns new value. Otherwise returns nullptr.
+ std::unique_ptr<void, DynValueDeleter> TryParse(absl::string_view value,
+ std::string& err) const
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+ // Stores the flag value based on the pointer to the source.
+ void StoreValue(const void* src) ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Copy the flag data, protected by `seq_lock_` into `dst`.
+ //
+ // REQUIRES: ValueStorageKind() == kSequenceLocked.
+ void ReadSequenceLockedData(void* dst) const
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ FlagHelpKind HelpSourceKind() const {
+ return static_cast<FlagHelpKind>(help_source_kind_);
+ }
+ FlagValueStorageKind ValueStorageKind() const {
+ return static_cast<FlagValueStorageKind>(value_storage_kind_);
+ }
+ FlagDefaultKind DefaultKind() const
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard()) {
+ return static_cast<FlagDefaultKind>(def_kind_);
+ }
+
+ // CommandLineFlag interface implementation
+ absl::string_view Name() const override;
+ std::string Filename() const override;
+ std::string Help() const override;
+ FlagFastTypeId TypeId() const override;
+ bool IsSpecifiedOnCommandLine() const override
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+ std::string DefaultValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+ std::string CurrentValue() const override ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool ValidateInputValue(absl::string_view value) const override
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void CheckDefaultValueParsingRoundtrip() const override
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ int64_t ModificationCount() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(*DataGuard());
+
+ // Interfaces to save and restore flags to/from persistent state.
+ // Returns current flag state or nullptr if flag does not support
+ // saving and restoring a state.
+ std::unique_ptr<FlagStateInterface> SaveState() override
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Restores the flag state to the supplied state object. If there is
+ // nothing to restore returns false. Otherwise returns true.
+ bool RestoreState(const FlagState& flag_state)
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ bool ParseFrom(absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, std::string& error) override
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ // Immutable flag's state.
+
+ // Flags name passed to ABSL_FLAG as second arg.
+ const char* const name_;
+ // The file name where ABSL_FLAG resides.
+ const char* const filename_;
+ // Type-specific operations "vtable".
+ const FlagOpFn op_;
+ // Help message literal or function to generate it.
+ const FlagHelpMsg help_;
+ // Indicates if help message was supplied as literal or generator func.
+ const uint8_t help_source_kind_ : 1;
+ // Kind of storage this flag is using for the flag's value.
+ const uint8_t value_storage_kind_ : 2;
+
+ uint8_t : 0; // The bytes containing the const bitfields must not be
+ // shared with bytes containing the mutable bitfields.
+
+ // Mutable flag's state (guarded by `data_guard_`).
+
+ // def_kind_ is not guard by DataGuard() since it is accessed in Init without
+ // locks.
+ uint8_t def_kind_ : 2;
+ // Has this flag's value been modified?
+ bool modified_ : 1 ABSL_GUARDED_BY(*DataGuard());
+ // Has this flag been specified on command line.
+ bool on_command_line_ : 1 ABSL_GUARDED_BY(*DataGuard());
+
+ // Unique tag for absl::call_once call to initialize this flag.
+ absl::once_flag init_control_;
+
+ // Sequence lock / mutation counter.
+ flags_internal::SequenceLock seq_lock_;
+
+ // Optional flag's callback and absl::Mutex to guard the invocations.
+ FlagCallback* callback_ ABSL_GUARDED_BY(*DataGuard());
+ // Either a pointer to the function generating the default value based on the
+ // value specified in ABSL_FLAG or pointer to the dynamically set default
+ // value via SetCommandLineOptionWithMode. def_kind_ is used to distinguish
+ // these two cases.
+ FlagDefaultSrc default_value_;
+
+ // This is reserved space for an absl::Mutex to guard flag data. It will be
+ // initialized in FlagImpl::Init via placement new.
+ // We can't use "absl::Mutex data_guard_", since this class is not literal.
+ // We do not want to use "absl::Mutex* data_guard_", since this would require
+ // heap allocation during initialization, which is both slows program startup
+ // and can fail. Using reserved space + placement new allows us to avoid both
+ // problems.
+ alignas(absl::Mutex) mutable char data_guard_[sizeof(absl::Mutex)];
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// The Flag object parameterized by the flag's value type. This class implements
+// flag reflection handle interface.
+
+template <typename T>
+class Flag {
+ public:
+ constexpr Flag(const char* name, const char* filename, FlagHelpArg help,
+ const FlagDefaultArg default_arg)
+ : impl_(name, filename, &FlagOps<T>, help,
+ flags_internal::StorageKind<T>(), default_arg),
+ value_() {}
+
+ // CommandLineFlag interface
+ absl::string_view Name() const { return impl_.Name(); }
+ std::string Filename() const { return impl_.Filename(); }
+ std::string Help() const { return impl_.Help(); }
+ // Do not use. To be removed.
+ bool IsSpecifiedOnCommandLine() const {
+ return impl_.IsSpecifiedOnCommandLine();
+ }
+ std::string DefaultValue() const { return impl_.DefaultValue(); }
+ std::string CurrentValue() const { return impl_.CurrentValue(); }
+
+ private:
+ template <typename, bool>
+ friend class FlagRegistrar;
+ friend class FlagImplPeer;
+
+ T Get() const {
+ // See implementation notes in CommandLineFlag::Get().
+ union U {
+ T value;
+ U() {}
+ ~U() { value.~T(); }
+ };
+ U u;
+
+#if !defined(NDEBUG)
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+#endif
+
+ if (ABSL_PREDICT_FALSE(!value_.Get(impl_.seq_lock_, u.value))) {
+ impl_.Read(&u.value);
+ }
+ return std::move(u.value);
+ }
+ void Set(const T& v) {
+ impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
+ impl_.Write(&v);
+ }
+
+ // Access to the reflection.
+ const CommandLineFlag& Reflect() const { return impl_; }
+
+ // Flag's data
+ // The implementation depends on value_ field to be placed exactly after the
+ // impl_ field, so that impl_ can figure out the offset to the value and
+ // access it.
+ FlagImpl impl_;
+ FlagValue<T> value_;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Trampoline for friend access
+
+class FlagImplPeer {
+ public:
+ template <typename T, typename FlagType>
+ static T InvokeGet(const FlagType& flag) {
+ return flag.Get();
+ }
+ template <typename FlagType, typename T>
+ static void InvokeSet(FlagType& flag, const T& v) {
+ flag.Set(v);
+ }
+ template <typename FlagType>
+ static const CommandLineFlag& InvokeReflect(const FlagType& f) {
+ return f.Reflect();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Implementation of Flag value specific operations routine.
+template <typename T>
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
+ switch (op) {
+ case FlagOp::kAlloc: {
+ std::allocator<T> alloc;
+ return std::allocator_traits<std::allocator<T>>::allocate(alloc, 1);
+ }
+ case FlagOp::kDelete: {
+ T* p = static_cast<T*>(v2);
+ p->~T();
+ std::allocator<T> alloc;
+ std::allocator_traits<std::allocator<T>>::deallocate(alloc, p, 1);
+ return nullptr;
+ }
+ case FlagOp::kCopy:
+ *static_cast<T*>(v2) = *static_cast<const T*>(v1);
+ return nullptr;
+ case FlagOp::kCopyConstruct:
+ new (v2) T(*static_cast<const T*>(v1));
+ return nullptr;
+ case FlagOp::kSizeof:
+ return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
+ case FlagOp::kFastTypeId:
+ return const_cast<void*>(base_internal::FastTypeId<T>());
+ case FlagOp::kRuntimeTypeId:
+ return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
+ case FlagOp::kParse: {
+ // Initialize the temporary instance of type T based on current value in
+ // destination (which is going to be flag's default value).
+ T temp(*static_cast<T*>(v2));
+ if (!absl::ParseFlag<T>(*static_cast<const absl::string_view*>(v1), &temp,
+ static_cast<std::string*>(v3))) {
+ return nullptr;
+ }
+ *static_cast<T*>(v2) = std::move(temp);
+ return v2;
+ }
+ case FlagOp::kUnparse:
+ *static_cast<std::string*>(v2) =
+ absl::UnparseFlag<T>(*static_cast<const T*>(v1));
+ return nullptr;
+ case FlagOp::kValueOffset: {
+ // Round sizeof(FlagImp) to a multiple of alignof(FlagValue<T>) to get the
+ // offset of the data.
+ ptrdiff_t round_to = alignof(FlagValue<T>);
+ ptrdiff_t offset =
+ (sizeof(FlagImpl) + round_to - 1) / round_to * round_to;
+ return reinterpret_cast<void*>(offset);
+ }
+ }
+ return nullptr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// This class facilitates Flag object registration and tail expression-based
+// flag definition, for example:
+// ABSL_FLAG(int, foo, 42, "Foo help").OnUpdate(NotifyFooWatcher);
+struct FlagRegistrarEmpty {};
+template <typename T, bool do_register>
+class FlagRegistrar {
+ public:
+ explicit FlagRegistrar(Flag<T>& flag, const char* filename) : flag_(flag) {
+ if (do_register)
+ flags_internal::RegisterCommandLineFlag(flag_.impl_, filename);
+ }
+
+ FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
+ flag_.impl_.SetCallback(cb);
+ return *this;
+ }
+
+ // Make the registrar "die" gracefully as an empty struct on a line where
+ // registration happens. Registrar objects are intended to live only as
+ // temporary.
+ operator FlagRegistrarEmpty() const { return {}; } // NOLINT
+
+ private:
+ Flag<T>& flag_; // Flag being registered (not owned).
+};
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_FLAG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/parse.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/parse.h
new file mode 100644
index 00000000000..de706c89847
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/parse.h
@@ -0,0 +1,59 @@
+//
+// 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_FLAGS_INTERNAL_PARSE_H_
+#define ABSL_FLAGS_INTERNAL_PARSE_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/flags/declare.h"
+#include "absl/strings/string_view.h"
+
+ABSL_DECLARE_FLAG(std::vector<std::string>, flagfile);
+ABSL_DECLARE_FLAG(std::vector<std::string>, fromenv);
+ABSL_DECLARE_FLAG(std::vector<std::string>, tryfromenv);
+ABSL_DECLARE_FLAG(std::vector<std::string>, undefok);
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+enum class ArgvListAction { kRemoveParsedArgs, kKeepParsedArgs };
+enum class UsageFlagsAction { kHandleUsage, kIgnoreUsage };
+enum class OnUndefinedFlag {
+ kIgnoreUndefined,
+ kReportUndefined,
+ kAbortIfUndefined
+};
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+ ArgvListAction arg_list_act,
+ UsageFlagsAction usage_flag_act,
+ OnUndefinedFlag on_undef_flag);
+
+// --------------------------------------------------------------------
+// Inspect original command line
+
+// Returns true if flag with specified name was either present on the original
+// command line or specified in flag file present on the original command line.
+bool WasPresentOnCommandLine(absl::string_view flag_name);
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_PARSE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util.h
new file mode 100644
index 00000000000..a6594d3347e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util.h
@@ -0,0 +1,62 @@
+//
+// 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_FLAGS_INTERNAL_PATH_UTIL_H_
+#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// A portable interface that returns the basename of the filename passed as an
+// argument. It is similar to basename(3)
+// <https://linux.die.net/man/3/basename>.
+// For example:
+// flags_internal::Basename("a/b/prog/file.cc")
+// returns "file.cc"
+// flags_internal::Basename("file.cc")
+// returns "file.cc"
+inline absl::string_view Basename(absl::string_view filename) {
+ auto last_slash_pos = filename.find_last_of("/\\");
+
+ return last_slash_pos == absl::string_view::npos
+ ? filename
+ : filename.substr(last_slash_pos + 1);
+}
+
+// A portable interface that returns the directory name of the filename
+// passed as an argument, including the trailing slash.
+// Returns the empty string if a slash is not found in the input file name.
+// For example:
+// flags_internal::Package("a/b/prog/file.cc")
+// returns "a/b/prog/"
+// flags_internal::Package("file.cc")
+// returns ""
+inline absl::string_view Package(absl::string_view filename) {
+ auto last_slash_pos = filename.find_last_of("/\\");
+
+ return last_slash_pos == absl::string_view::npos
+ ? absl::string_view()
+ : filename.substr(0, last_slash_pos + 1);
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util_test.cc
new file mode 100644
index 00000000000..2091373c88e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/path_util_test.cc
@@ -0,0 +1,46 @@
+//
+// 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.
+
+#include "absl/flags/internal/path_util.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+TEST(FlagsPathUtilTest, TestBasename) {
+ EXPECT_EQ(flags::Basename(""), "");
+ EXPECT_EQ(flags::Basename("a.cc"), "a.cc");
+ EXPECT_EQ(flags::Basename("dir/a.cc"), "a.cc");
+ EXPECT_EQ(flags::Basename("dir1/dir2/a.cc"), "a.cc");
+ EXPECT_EQ(flags::Basename("../dir1/dir2/a.cc"), "a.cc");
+ EXPECT_EQ(flags::Basename("/dir1/dir2/a.cc"), "a.cc");
+ EXPECT_EQ(flags::Basename("/dir1/dir2/../dir3/a.cc"), "a.cc");
+}
+
+// --------------------------------------------------------------------
+
+TEST(FlagsPathUtilTest, TestPackage) {
+ EXPECT_EQ(flags::Package(""), "");
+ EXPECT_EQ(flags::Package("a.cc"), "");
+ EXPECT_EQ(flags::Package("dir/a.cc"), "dir/");
+ EXPECT_EQ(flags::Package("dir1/dir2/a.cc"), "dir1/dir2/");
+ EXPECT_EQ(flags::Package("../dir1/dir2/a.cc"), "../dir1/dir2/");
+ EXPECT_EQ(flags::Package("/dir1/dir2/a.cc"), "/dir1/dir2/");
+ EXPECT_EQ(flags::Package("/dir1/dir2/../dir3/a.cc"), "/dir1/dir2/../dir3/");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.cc
new file mode 100644
index 00000000000..a7eb58b6d45
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.cc
@@ -0,0 +1,65 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/private_handle_accessor.h"
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+FlagFastTypeId PrivateHandleAccessor::TypeId(const CommandLineFlag& flag) {
+ return flag.TypeId();
+}
+
+std::unique_ptr<FlagStateInterface> PrivateHandleAccessor::SaveState(
+ CommandLineFlag& flag) {
+ return flag.SaveState();
+}
+
+bool PrivateHandleAccessor::IsSpecifiedOnCommandLine(
+ const CommandLineFlag& flag) {
+ return flag.IsSpecifiedOnCommandLine();
+}
+
+bool PrivateHandleAccessor::ValidateInputValue(const CommandLineFlag& flag,
+ absl::string_view value) {
+ return flag.ValidateInputValue(value);
+}
+
+void PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+ const CommandLineFlag& flag) {
+ flag.CheckDefaultValueParsingRoundtrip();
+}
+
+bool PrivateHandleAccessor::ParseFrom(CommandLineFlag& flag,
+ absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source,
+ std::string& error) {
+ return flag.ParseFrom(value, set_mode, source, error);
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.h
new file mode 100644
index 00000000000..c64435cd619
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/private_handle_accessor.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+#define ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
+
+#include <memory>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// This class serves as a trampoline to access private methods of
+// CommandLineFlag. This class is intended for use exclusively internally inside
+// of the Abseil Flags implementation.
+class PrivateHandleAccessor {
+ public:
+ // Access to CommandLineFlag::TypeId.
+ static FlagFastTypeId TypeId(const CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::SaveState.
+ static std::unique_ptr<FlagStateInterface> SaveState(CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::IsSpecifiedOnCommandLine.
+ static bool IsSpecifiedOnCommandLine(const CommandLineFlag& flag);
+
+ // Access to CommandLineFlag::ValidateInputValue.
+ static bool ValidateInputValue(const CommandLineFlag& flag,
+ absl::string_view value);
+
+ // Access to CommandLineFlag::CheckDefaultValueParsingRoundtrip.
+ static void CheckDefaultValueParsingRoundtrip(const CommandLineFlag& flag);
+
+ static bool ParseFrom(CommandLineFlag& flag, absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source, std::string& error);
+};
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_PRIVATE_HANDLE_ACCESSOR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.cc
new file mode 100644
index 00000000000..51d698da8b3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.cc
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/internal/program_name.h"
+
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+ABSL_CONST_INIT static absl::Mutex program_name_guard(absl::kConstInit);
+ABSL_CONST_INIT static std::string* program_name
+ ABSL_GUARDED_BY(program_name_guard) = nullptr;
+
+std::string ProgramInvocationName() {
+ absl::MutexLock l(&program_name_guard);
+
+ return program_name ? *program_name : "UNKNOWN";
+}
+
+std::string ShortProgramInvocationName() {
+ absl::MutexLock l(&program_name_guard);
+
+ return program_name ? std::string(flags_internal::Basename(*program_name))
+ : "UNKNOWN";
+}
+
+void SetProgramInvocationName(absl::string_view prog_name_str) {
+ absl::MutexLock l(&program_name_guard);
+
+ if (!program_name)
+ program_name = new std::string(prog_name_str);
+ else
+ program_name->assign(prog_name_str.data(), prog_name_str.size());
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.h
new file mode 100644
index 00000000000..b99b94fe18a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name.h
@@ -0,0 +1,50 @@
+//
+// 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_FLAGS_INTERNAL_PROGRAM_NAME_H_
+#define ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Program name
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Returns program invocation name or "UNKNOWN" if `SetProgramInvocationName()`
+// is never called. At the moment this is always set to argv[0] as part of
+// library initialization.
+std::string ProgramInvocationName();
+
+// Returns base name for program invocation name. For example, if
+// ProgramInvocationName() == "a/b/mybinary"
+// then
+// ShortProgramInvocationName() == "mybinary"
+std::string ShortProgramInvocationName();
+
+// Sets program invocation name to a new value. Should only be called once
+// during program initialization, before any threads are spawned.
+void SetProgramInvocationName(absl::string_view prog_name_str);
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_PROGRAM_NAME_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name_test.cc
new file mode 100644
index 00000000000..aff9f6315e4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/program_name_test.cc
@@ -0,0 +1,61 @@
+//
+// 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.
+
+#include "absl/flags/internal/program_name.h"
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
+ flags::SetProgramInvocationName("absl/flags/program_name_test");
+ std::string program_name = flags::ProgramInvocationName();
+ for (char& c : program_name)
+ if (c == '\\') c = '/';
+
+#if !defined(__wasm__) && !defined(__asmjs__)
+ const std::string expect_name = "absl/flags/program_name_test";
+ const std::string expect_basename = "program_name_test";
+#else
+ // For targets that generate javascript or webassembly the invocation name
+ // has the special value below.
+ const std::string expect_name = "this.program";
+ const std::string expect_basename = "this.program";
+#endif
+
+ EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name;
+ EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename);
+
+ flags::SetProgramInvocationName("a/my_test");
+
+ EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test");
+ EXPECT_EQ(flags::ShortProgramInvocationName(), "my_test");
+
+ absl::string_view not_null_terminated("absl/aaa/bbb");
+ not_null_terminated = not_null_terminated.substr(1, 10);
+
+ flags::SetProgramInvocationName(not_null_terminated);
+
+ EXPECT_EQ(flags::ProgramInvocationName(), "bsl/aaa/bb");
+ EXPECT_EQ(flags::ShortProgramInvocationName(), "bb");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/registry.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/registry.h
new file mode 100644
index 00000000000..4b68c85f5c4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/registry.h
@@ -0,0 +1,97 @@
+//
+// 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_FLAGS_INTERNAL_REGISTRY_H_
+#define ABSL_FLAGS_INTERNAL_REGISTRY_H_
+
+#include <functional>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Global flags registry API.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Executes specified visitor for each non-retired flag in the registry. While
+// callback are executed, the registry is locked and can't be changed.
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+
+//-----------------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag&, const char* filename);
+
+void FinalizeRegistry();
+
+//-----------------------------------------------------------------------------
+// Retired registrations:
+//
+// Retired flag registrations are treated specially. A 'retired' flag is
+// provided only for compatibility with automated invocations that still
+// name it. A 'retired' flag:
+// - is not bound to a C++ FLAGS_ reference.
+// - has a type and a value, but that value is intentionally inaccessible.
+// - does not appear in --help messages.
+// - is fully supported by _all_ flag parsing routines.
+// - consumes args normally, and complains about type mismatches in its
+// argument.
+// - emits a complaint but does not die (e.g. LOG(ERROR)) if it is
+// accessed by name through the flags API for parsing or otherwise.
+//
+// The registrations for a flag happen in an unspecified order as the
+// initializers for the namespace-scope objects of a program are run.
+// Any number of weak registrations for a flag can weakly define the flag.
+// One non-weak registration will upgrade the flag from weak to non-weak.
+// Further weak registrations of a non-weak flag are ignored.
+//
+// This mechanism is designed to support moving dead flags into a
+// 'graveyard' library. An example migration:
+//
+// 0: Remove references to this FLAGS_flagname in the C++ codebase.
+// 1: Register as 'retired' in old_lib.
+// 2: Make old_lib depend on graveyard.
+// 3: Add a redundant 'retired' registration to graveyard.
+// 4: Remove the old_lib 'retired' registration.
+// 5: Eventually delete the graveyard registration entirely.
+//
+
+// Retire flag with name "name" and type indicated by ops.
+void Retire(const char* name, FlagFastTypeId type_id, char* buf);
+
+constexpr size_t kRetiredFlagObjSize = 3 * sizeof(void*);
+constexpr size_t kRetiredFlagObjAlignment = alignof(void*);
+
+// Registered a retired flag with name 'flag_name' and type 'T'.
+template <typename T>
+class RetiredFlag {
+ public:
+ void Retire(const char* flag_name) {
+ flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
+ }
+
+ private:
+ alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
+};
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_REGISTRY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock.h
new file mode 100644
index 00000000000..807b2a73137
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock.h
@@ -0,0 +1,187 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+#define ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <atomic>
+#include <cassert>
+#include <cstring>
+
+#include "absl/base/optimization.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Align 'x' up to the nearest 'align' bytes.
+inline constexpr size_t AlignUp(size_t x, size_t align) {
+ return align * ((x + align - 1) / align);
+}
+
+// A SequenceLock implements lock-free reads. A sequence counter is incremented
+// before and after each write, and readers access the counter before and after
+// accessing the protected data. If the counter is verified to not change during
+// the access, and the sequence counter value was even, then the reader knows
+// that the read was race-free and valid. Otherwise, the reader must fall back
+// to a Mutex-based code path.
+//
+// This particular SequenceLock starts in an "uninitialized" state in which
+// TryRead() returns false. It must be enabled by calling MarkInitialized().
+// This serves as a marker that the associated flag value has not yet been
+// initialized and a slow path needs to be taken.
+//
+// The memory reads and writes protected by this lock must use the provided
+// `TryRead()` and `Write()` functions. These functions behave similarly to
+// `memcpy()`, with one oddity: the protected data must be an array of
+// `std::atomic<int64>`. This is to comply with the C++ standard, which
+// considers data races on non-atomic objects to be undefined behavior. See "Can
+// Seqlocks Get Along With Programming Language Memory Models?"[1] by Hans J.
+// Boehm for more details.
+//
+// [1] https://www.hpl.hp.com/techreports/2012/HPL-2012-68.pdf
+class SequenceLock {
+ public:
+ constexpr SequenceLock() : lock_(kUninitialized) {}
+
+ // Mark that this lock is ready for use.
+ void MarkInitialized() {
+ assert(lock_.load(std::memory_order_relaxed) == kUninitialized);
+ lock_.store(0, std::memory_order_release);
+ }
+
+ // Copy "size" bytes of data from "src" to "dst", protected as a read-side
+ // critical section of the sequence lock.
+ //
+ // Unlike traditional sequence lock implementations which loop until getting a
+ // clean read, this implementation returns false in the case of concurrent
+ // calls to `Write`. In such a case, the caller should fall back to a
+ // locking-based slow path.
+ //
+ // Returns false if the sequence lock was not yet marked as initialized.
+ //
+ // NOTE: If this returns false, "dst" may be overwritten with undefined
+ // (potentially uninitialized) data.
+ bool TryRead(void* dst, const std::atomic<uint64_t>* src, size_t size) const {
+ // Acquire barrier ensures that no loads done by f() are reordered
+ // above the first load of the sequence counter.
+ int64_t seq_before = lock_.load(std::memory_order_acquire);
+ if (ABSL_PREDICT_FALSE(seq_before & 1) == 1) return false;
+ RelaxedCopyFromAtomic(dst, src, size);
+ // Another acquire fence ensures that the load of 'lock_' below is
+ // strictly ordered after the RelaxedCopyToAtomic call above.
+ std::atomic_thread_fence(std::memory_order_acquire);
+ int64_t seq_after = lock_.load(std::memory_order_relaxed);
+ return ABSL_PREDICT_TRUE(seq_before == seq_after);
+ }
+
+ // Copy "size" bytes from "src" to "dst" as a write-side critical section
+ // of the sequence lock. Any concurrent readers will be forced to retry
+ // until they get a read that does not conflict with this write.
+ //
+ // This call must be externally synchronized against other calls to Write,
+ // but may proceed concurrently with reads.
+ void Write(std::atomic<uint64_t>* dst, const void* src, size_t size) {
+ // We can use relaxed instructions to increment the counter since we
+ // are extenally synchronized. The std::atomic_thread_fence below
+ // ensures that the counter updates don't get interleaved with the
+ // copy to the data.
+ int64_t orig_seq = lock_.load(std::memory_order_relaxed);
+ assert((orig_seq & 1) == 0); // Must be initially unlocked.
+ lock_.store(orig_seq + 1, std::memory_order_relaxed);
+
+ // We put a release fence between update to lock_ and writes to shared data.
+ // Thus all stores to shared data are effectively release operations and
+ // update to lock_ above cannot be re-ordered past any of them. Note that
+ // this barrier is not for the fetch_add above. A release barrier for the
+ // fetch_add would be before it, not after.
+ std::atomic_thread_fence(std::memory_order_release);
+ RelaxedCopyToAtomic(dst, src, size);
+ // "Release" semantics ensure that none of the writes done by
+ // RelaxedCopyToAtomic() can be reordered after the following modification.
+ lock_.store(orig_seq + 2, std::memory_order_release);
+ }
+
+ // Return the number of times that Write() has been called.
+ //
+ // REQUIRES: This must be externally synchronized against concurrent calls to
+ // `Write()` or `IncrementModificationCount()`.
+ // REQUIRES: `MarkInitialized()` must have been previously called.
+ int64_t ModificationCount() const {
+ int64_t val = lock_.load(std::memory_order_relaxed);
+ assert(val != kUninitialized && (val & 1) == 0);
+ return val / 2;
+ }
+
+ // REQUIRES: This must be externally synchronized against concurrent calls to
+ // `Write()` or `ModificationCount()`.
+ // REQUIRES: `MarkInitialized()` must have been previously called.
+ void IncrementModificationCount() {
+ int64_t val = lock_.load(std::memory_order_relaxed);
+ assert(val != kUninitialized);
+ lock_.store(val + 2, std::memory_order_relaxed);
+ }
+
+ private:
+ // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+ // atomics.
+ static void RelaxedCopyFromAtomic(void* dst, const std::atomic<uint64_t>* src,
+ size_t size) {
+ char* dst_byte = static_cast<char*>(dst);
+ while (size >= sizeof(uint64_t)) {
+ uint64_t word = src->load(std::memory_order_relaxed);
+ std::memcpy(dst_byte, &word, sizeof(word));
+ dst_byte += sizeof(word);
+ src++;
+ size -= sizeof(word);
+ }
+ if (size > 0) {
+ uint64_t word = src->load(std::memory_order_relaxed);
+ std::memcpy(dst_byte, &word, size);
+ }
+ }
+
+ // Perform the equivalent of "memcpy(dst, src, size)", but using relaxed
+ // atomics.
+ static void RelaxedCopyToAtomic(std::atomic<uint64_t>* dst, const void* src,
+ size_t size) {
+ const char* src_byte = static_cast<const char*>(src);
+ while (size >= sizeof(uint64_t)) {
+ uint64_t word;
+ std::memcpy(&word, src_byte, sizeof(word));
+ dst->store(word, std::memory_order_relaxed);
+ src_byte += sizeof(word);
+ dst++;
+ size -= sizeof(word);
+ }
+ if (size > 0) {
+ uint64_t word = 0;
+ std::memcpy(&word, src_byte, size);
+ dst->store(word, std::memory_order_relaxed);
+ }
+ }
+
+ static constexpr int64_t kUninitialized = -1;
+ std::atomic<int64_t> lock_;
+};
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_SEQUENCE_LOCK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock_test.cc
new file mode 100644
index 00000000000..c3ec372ed8c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/sequence_lock_test.cc
@@ -0,0 +1,169 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/flags/internal/sequence_lock.h"
+
+#include <algorithm>
+#include <atomic>
+#include <thread> // NOLINT(build/c++11)
+#include <tuple>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/container/fixed_array.h"
+#include "absl/time/clock.h"
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+class ConcurrentSequenceLockTest
+ : public testing::TestWithParam<std::tuple<int, int>> {
+ public:
+ ConcurrentSequenceLockTest()
+ : buf_bytes_(std::get<0>(GetParam())),
+ num_threads_(std::get<1>(GetParam())) {}
+
+ protected:
+ const int buf_bytes_;
+ const int num_threads_;
+};
+
+TEST_P(ConcurrentSequenceLockTest, ReadAndWrite) {
+ const int buf_words =
+ flags::AlignUp(buf_bytes_, sizeof(uint64_t)) / sizeof(uint64_t);
+
+ // The buffer that will be protected by the SequenceLock.
+ absl::FixedArray<std::atomic<uint64_t>> protected_buf(buf_words);
+ for (auto& v : protected_buf) v = -1;
+
+ flags::SequenceLock seq_lock;
+ std::atomic<bool> stop{false};
+ std::atomic<int64_t> bad_reads{0};
+ std::atomic<int64_t> good_reads{0};
+ std::atomic<int64_t> unsuccessful_reads{0};
+
+ // Start a bunch of threads which read 'protected_buf' under the sequence
+ // lock. The main thread will concurrently update 'protected_buf'. The updates
+ // always consist of an array of identical integers. The reader ensures that
+ // any data it reads matches that pattern (i.e. the reads are not "torn").
+ std::vector<std::thread> threads;
+ for (int i = 0; i < num_threads_; i++) {
+ threads.emplace_back([&]() {
+ absl::FixedArray<char> local_buf(buf_bytes_);
+ while (!stop.load(std::memory_order_relaxed)) {
+ if (seq_lock.TryRead(local_buf.data(), protected_buf.data(),
+ buf_bytes_)) {
+ bool good = true;
+ for (const auto& v : local_buf) {
+ if (v != local_buf[0]) good = false;
+ }
+ if (good) {
+ good_reads.fetch_add(1, std::memory_order_relaxed);
+ } else {
+ bad_reads.fetch_add(1, std::memory_order_relaxed);
+ }
+ } else {
+ unsuccessful_reads.fetch_add(1, std::memory_order_relaxed);
+ }
+ }
+ });
+ }
+ while (unsuccessful_reads.load(std::memory_order_relaxed) < num_threads_) {
+ absl::SleepFor(absl::Milliseconds(1));
+ }
+ seq_lock.MarkInitialized();
+
+ // Run a maximum of 5 seconds. On Windows, the scheduler behavior seems
+ // somewhat unfair and without an explicit timeout for this loop, the tests
+ // can run a long time.
+ absl::Time deadline = absl::Now() + absl::Seconds(5);
+ for (int i = 0; i < 100 && absl::Now() < deadline; i++) {
+ absl::FixedArray<char> writer_buf(buf_bytes_);
+ for (auto& v : writer_buf) v = i;
+ seq_lock.Write(protected_buf.data(), writer_buf.data(), buf_bytes_);
+ absl::SleepFor(absl::Microseconds(10));
+ }
+ stop.store(true, std::memory_order_relaxed);
+ for (auto& t : threads) t.join();
+ ASSERT_GE(good_reads, 0);
+ ASSERT_EQ(bad_reads, 0);
+}
+
+// Simple helper for generating a range of thread counts.
+// Generates [low, low*scale, low*scale^2, ...high)
+// (even if high is between low*scale^k and low*scale^(k+1)).
+std::vector<int> MultiplicativeRange(int low, int high, int scale) {
+ std::vector<int> result;
+ for (int current = low; current < high; current *= scale) {
+ result.push_back(current);
+ }
+ result.push_back(high);
+ return result;
+}
+
+#ifndef ABSL_HAVE_THREAD_SANITIZER
+const int kMaxThreads = absl::base_internal::NumCPUs();
+#else
+// With TSAN, a lot of threads contending for atomic access on the sequence
+// lock make this test run too slowly.
+const int kMaxThreads = std::min(absl::base_internal::NumCPUs(), 4);
+#endif
+
+// Return all of the interesting buffer sizes worth testing:
+// powers of two and adjacent values.
+std::vector<int> InterestingBufferSizes() {
+ std::vector<int> ret;
+ for (int v : MultiplicativeRange(1, 128, 2)) {
+ ret.push_back(v);
+ if (v > 1) {
+ ret.push_back(v - 1);
+ }
+ ret.push_back(v + 1);
+ }
+ return ret;
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ TestManyByteSizes, ConcurrentSequenceLockTest,
+ testing::Combine(
+ // Buffer size (bytes).
+ testing::ValuesIn(InterestingBufferSizes()),
+ // Number of reader threads.
+ testing::ValuesIn(MultiplicativeRange(1, kMaxThreads, 2))));
+
+// Simple single-threaded test, parameterized by the size of the buffer to be
+// protected.
+class SequenceLockTest : public testing::TestWithParam<int> {};
+
+TEST_P(SequenceLockTest, SingleThreaded) {
+ const int size = GetParam();
+ absl::FixedArray<std::atomic<uint64_t>> protected_buf(
+ flags::AlignUp(size, sizeof(uint64_t)) / sizeof(uint64_t));
+
+ flags::SequenceLock seq_lock;
+ seq_lock.MarkInitialized();
+
+ std::vector<char> src_buf(size, 'x');
+ seq_lock.Write(protected_buf.data(), src_buf.data(), size);
+
+ std::vector<char> dst_buf(size, '0');
+ ASSERT_TRUE(seq_lock.TryRead(dst_buf.data(), protected_buf.data(), size));
+ ASSERT_EQ(src_buf, dst_buf);
+}
+INSTANTIATE_TEST_SUITE_P(TestManyByteSizes, SequenceLockTest,
+ // Buffer size (bytes).
+ testing::Range(1, 128));
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.cc
new file mode 100644
index 00000000000..a588c7f73ac
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.cc
@@ -0,0 +1,518 @@
+//
+// 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.
+
+#include "absl/flags/internal/usage.h"
+
+#include <stdint.h>
+
+#include <functional>
+#include <map>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+
+// Dummy global variables to prevent anyone else defining these.
+bool FLAGS_help = false;
+bool FLAGS_helpfull = false;
+bool FLAGS_helpshort = false;
+bool FLAGS_helppackage = false;
+bool FLAGS_version = false;
+bool FLAGS_only_check_args = false;
+bool FLAGS_helpon = false;
+bool FLAGS_helpmatch = false;
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+
+using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
+
+// Maximum length size in a human readable format.
+constexpr size_t kHrfMaxLineLength = 80;
+
+// This class is used to emit an XML element with `tag` and `text`.
+// It adds opening and closing tags and escapes special characters in the text.
+// For example:
+// std::cout << XMLElement("title", "Milk & Cookies");
+// prints "<title>Milk &amp; Cookies</title>"
+class XMLElement {
+ public:
+ XMLElement(absl::string_view tag, absl::string_view txt)
+ : tag_(tag), txt_(txt) {}
+
+ friend std::ostream& operator<<(std::ostream& out,
+ const XMLElement& xml_elem) {
+ out << "<" << xml_elem.tag_ << ">";
+
+ for (auto c : xml_elem.txt_) {
+ switch (c) {
+ case '"':
+ out << "&quot;";
+ break;
+ case '\'':
+ out << "&apos;";
+ break;
+ case '&':
+ out << "&amp;";
+ break;
+ case '<':
+ out << "&lt;";
+ break;
+ case '>':
+ out << "&gt;";
+ break;
+ default:
+ out << c;
+ break;
+ }
+ }
+
+ return out << "</" << xml_elem.tag_ << ">";
+ }
+
+ private:
+ absl::string_view tag_;
+ absl::string_view txt_;
+};
+
+// --------------------------------------------------------------------
+// Helper class to pretty-print info about a flag.
+
+class FlagHelpPrettyPrinter {
+ public:
+ // Pretty printer holds on to the std::ostream& reference to direct an output
+ // to that stream.
+ FlagHelpPrettyPrinter(size_t max_line_len, size_t min_line_len,
+ size_t wrapped_line_indent, std::ostream& out)
+ : out_(out),
+ max_line_len_(max_line_len),
+ min_line_len_(min_line_len),
+ wrapped_line_indent_(wrapped_line_indent),
+ line_len_(0),
+ first_line_(true) {}
+
+ void Write(absl::string_view str, bool wrap_line = false) {
+ // Empty string - do nothing.
+ if (str.empty()) return;
+
+ std::vector<absl::string_view> tokens;
+ if (wrap_line) {
+ for (auto line : absl::StrSplit(str, absl::ByAnyChar("\n\r"))) {
+ if (!tokens.empty()) {
+ // Keep line separators in the input string.
+ tokens.push_back("\n");
+ }
+ for (auto token :
+ absl::StrSplit(line, absl::ByAnyChar(" \t"), absl::SkipEmpty())) {
+ tokens.push_back(token);
+ }
+ }
+ } else {
+ tokens.push_back(str);
+ }
+
+ for (auto token : tokens) {
+ bool new_line = (line_len_ == 0);
+
+ // Respect line separators in the input string.
+ if (token == "\n") {
+ EndLine();
+ continue;
+ }
+
+ // Write the token, ending the string first if necessary/possible.
+ if (!new_line &&
+ (line_len_ + static_cast<int>(token.size()) >= max_line_len_)) {
+ EndLine();
+ new_line = true;
+ }
+
+ if (new_line) {
+ StartLine();
+ } else {
+ out_ << ' ';
+ ++line_len_;
+ }
+
+ out_ << token;
+ line_len_ += token.size();
+ }
+ }
+
+ void StartLine() {
+ if (first_line_) {
+ line_len_ = min_line_len_;
+ first_line_ = false;
+ } else {
+ line_len_ = min_line_len_ + wrapped_line_indent_;
+ }
+ out_ << std::string(line_len_, ' ');
+ }
+ void EndLine() {
+ out_ << '\n';
+ line_len_ = 0;
+ }
+
+ private:
+ std::ostream& out_;
+ const size_t max_line_len_;
+ const size_t min_line_len_;
+ const size_t wrapped_line_indent_;
+ size_t line_len_;
+ bool first_line_;
+};
+
+void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
+ FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
+
+ // Flag name.
+ printer.Write(absl::StrCat("--", flag.Name()));
+
+ // Flag help.
+ printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
+
+ // The listed default value will be the actual default from the flag
+ // definition in the originating source file, unless the value has
+ // subsequently been modified using SetCommandLineOption() with mode
+ // SET_FLAGS_DEFAULT.
+ std::string dflt_val = flag.DefaultValue();
+ std::string curr_val = flag.CurrentValue();
+ bool is_modified = curr_val != dflt_val;
+
+ if (flag.IsOfType<std::string>()) {
+ dflt_val = absl::StrCat("\"", dflt_val, "\"");
+ }
+ printer.Write(absl::StrCat("default: ", dflt_val, ";"));
+
+ if (is_modified) {
+ if (flag.IsOfType<std::string>()) {
+ curr_val = absl::StrCat("\"", curr_val, "\"");
+ }
+ printer.Write(absl::StrCat("currently: ", curr_val, ";"));
+ }
+
+ printer.EndLine();
+}
+
+// Shows help for every filename which matches any of the filters
+// If filters are empty, shows help for every file.
+// If a flag's help message has been stripped (e.g. by adding '#define
+// STRIP_FLAG_HELP 1' then this flag will not be displayed by '--help'
+// and its variants.
+void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
+ HelpFormat format, absl::string_view program_usage_message) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << flags_internal::ShortProgramInvocationName() << ": "
+ << program_usage_message << "\n\n";
+ } else {
+ // XML schema is not a part of our public API for now.
+ out << "<?xml version=\"1.0\"?>\n"
+ << "<!-- This output should be used with care. We do not report type "
+ "names for flags with user defined types -->\n"
+ << "<!-- Prefer flag only_check_args for validating flag inputs -->\n"
+ // The document.
+ << "<AllFlags>\n"
+ // The program name and usage.
+ << XMLElement("program", flags_internal::ShortProgramInvocationName())
+ << '\n'
+ << XMLElement("usage", program_usage_message) << '\n';
+ }
+
+ // Map of package name to
+ // map of file name to
+ // vector of flags in the file.
+ // This map is used to output matching flags grouped by package and file
+ // name.
+ std::map<std::string,
+ std::map<std::string, std::vector<const absl::CommandLineFlag*>>>
+ matching_flags;
+
+ flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
+ // Ignore retired flags.
+ if (flag.IsRetired()) return;
+
+ // If the flag has been stripped, pretend that it doesn't exist.
+ if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
+
+ // Make sure flag satisfies the filter
+ if (!filter_cb(flag)) return;
+
+ std::string flag_filename = flag.Filename();
+
+ matching_flags[std::string(flags_internal::Package(flag_filename))]
+ [flag_filename]
+ .push_back(&flag);
+ });
+
+ absl::string_view package_separator; // controls blank lines between packages
+ absl::string_view file_separator; // controls blank lines between files
+ for (const auto& package : matching_flags) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << package_separator;
+ package_separator = "\n\n";
+ }
+
+ file_separator = "";
+ for (const auto& flags_in_file : package.second) {
+ if (format == HelpFormat::kHumanReadable) {
+ out << file_separator << " Flags from " << flags_in_file.first
+ << ":\n";
+ file_separator = "\n";
+ }
+
+ for (const auto* flag : flags_in_file.second) {
+ flags_internal::FlagHelp(out, *flag, format);
+ }
+ }
+ }
+
+ if (format == HelpFormat::kHumanReadable) {
+ FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
+
+ if (filter_cb && matching_flags.empty()) {
+ printer.Write("No flags matched.\n", true);
+ }
+ printer.EndLine();
+ printer.Write(
+ "Try --helpfull to get a list of all flags or --help=substring "
+ "shows help for flags which include specified substring in either "
+ "in the name, or description or path.\n",
+ true);
+ } else {
+ // The end of the document.
+ out << "</AllFlags>\n";
+ }
+}
+
+void FlagsHelpImpl(std::ostream& out,
+ flags_internal::FlagKindFilter filename_filter_cb,
+ HelpFormat format, absl::string_view program_usage_message) {
+ FlagsHelpImpl(
+ out,
+ [&](const absl::CommandLineFlag& flag) {
+ return filename_filter_cb && filename_filter_cb(flag.Filename());
+ },
+ format, program_usage_message);
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+// Produces the help message describing specific flag.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
+ HelpFormat format) {
+ if (format == HelpFormat::kHumanReadable)
+ flags_internal::FlagHelpHumanReadable(flag, out);
+}
+
+// --------------------------------------------------------------------
+// Produces the help messages for all flags matching the filename filter.
+// If filter is empty produces help messages for all flags.
+void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
+ absl::string_view program_usage_message) {
+ flags_internal::FlagKindFilter filter_cb = [&](absl::string_view filename) {
+ return filter.empty() || filename.find(filter) != absl::string_view::npos;
+ };
+ flags_internal::FlagsHelpImpl(out, filter_cb, format, program_usage_message);
+}
+
+// --------------------------------------------------------------------
+// Checks all the 'usage' command line flags to see if any have been set.
+// If so, handles them appropriately.
+int HandleUsageFlags(std::ostream& out,
+ absl::string_view program_usage_message) {
+ switch (GetFlagsHelpMode()) {
+ case HelpMode::kNone:
+ break;
+ case HelpMode::kImportant:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_help_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+ return 1;
+
+ case HelpMode::kShort:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+ return 1;
+
+ case HelpMode::kFull:
+ flags_internal::FlagsHelp(out, "", GetFlagsHelpFormat(),
+ program_usage_message);
+ return 1;
+
+ case HelpMode::kPackage:
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+ GetFlagsHelpFormat(), program_usage_message);
+
+ return 1;
+
+ case HelpMode::kMatch: {
+ std::string substr = GetFlagsHelpMatchSubstr();
+ if (substr.empty()) {
+ // show all options
+ flags_internal::FlagsHelp(out, substr, GetFlagsHelpFormat(),
+ program_usage_message);
+ } else {
+ auto filter_cb = [&substr](const absl::CommandLineFlag& flag) {
+ if (absl::StrContains(flag.Name(), substr)) return true;
+ if (absl::StrContains(flag.Filename(), substr)) return true;
+ if (absl::StrContains(flag.Help(), substr)) return true;
+
+ return false;
+ };
+ flags_internal::FlagsHelpImpl(
+ out, filter_cb, HelpFormat::kHumanReadable, program_usage_message);
+ }
+
+ return 1;
+ }
+ case HelpMode::kVersion:
+ if (flags_internal::GetUsageConfig().version_string)
+ out << flags_internal::GetUsageConfig().version_string();
+ // Unlike help, we may be asking for version in a script, so return 0
+ return 0;
+
+ case HelpMode::kOnlyCheckArgs:
+ return 0;
+ }
+
+ return -1;
+}
+
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+namespace {
+
+ABSL_CONST_INIT absl::Mutex help_attributes_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* match_substr
+ ABSL_GUARDED_BY(help_attributes_guard) = nullptr;
+ABSL_CONST_INIT HelpMode help_mode ABSL_GUARDED_BY(help_attributes_guard) =
+ HelpMode::kNone;
+ABSL_CONST_INIT HelpFormat help_format ABSL_GUARDED_BY(help_attributes_guard) =
+ HelpFormat::kHumanReadable;
+
+} // namespace
+
+std::string GetFlagsHelpMatchSubstr() {
+ absl::MutexLock l(&help_attributes_guard);
+ if (match_substr == nullptr) return "";
+ return *match_substr;
+}
+
+void SetFlagsHelpMatchSubstr(absl::string_view substr) {
+ absl::MutexLock l(&help_attributes_guard);
+ if (match_substr == nullptr) match_substr = new std::string;
+ match_substr->assign(substr.data(), substr.size());
+}
+
+HelpMode GetFlagsHelpMode() {
+ absl::MutexLock l(&help_attributes_guard);
+ return help_mode;
+}
+
+void SetFlagsHelpMode(HelpMode mode) {
+ absl::MutexLock l(&help_attributes_guard);
+ help_mode = mode;
+}
+
+HelpFormat GetFlagsHelpFormat() {
+ absl::MutexLock l(&help_attributes_guard);
+ return help_format;
+}
+
+void SetFlagsHelpFormat(HelpFormat format) {
+ absl::MutexLock l(&help_attributes_guard);
+ help_format = format;
+}
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value) {
+ if (absl::ConsumePrefix(&name, "help")) {
+ if (name == "") {
+ if (value.empty()) {
+ SetFlagsHelpMode(HelpMode::kImportant);
+ } else {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(value);
+ }
+ return true;
+ }
+
+ if (name == "match") {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(value);
+ return true;
+ }
+
+ if (name == "on") {
+ SetFlagsHelpMode(HelpMode::kMatch);
+ SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
+ return true;
+ }
+
+ if (name == "full") {
+ SetFlagsHelpMode(HelpMode::kFull);
+ return true;
+ }
+
+ if (name == "short") {
+ SetFlagsHelpMode(HelpMode::kShort);
+ return true;
+ }
+
+ if (name == "package") {
+ SetFlagsHelpMode(HelpMode::kPackage);
+ return true;
+ }
+
+ return false;
+ }
+
+ if (name == "version") {
+ SetFlagsHelpMode(HelpMode::kVersion);
+ return true;
+ }
+
+ if (name == "only_check_args") {
+ SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.h
new file mode 100644
index 00000000000..c0bcac57628
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage.h
@@ -0,0 +1,104 @@
+//
+// 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_FLAGS_INTERNAL_USAGE_H_
+#define ABSL_FLAGS_INTERNAL_USAGE_H_
+
+#include <iosfwd>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/declare.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Usage reporting interfaces
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// The format to report the help messages in.
+enum class HelpFormat {
+ kHumanReadable,
+};
+
+// Streams the help message describing `flag` to `out`.
+// The default value for `flag` is included in the output.
+void FlagHelp(std::ostream& out, const CommandLineFlag& flag,
+ HelpFormat format = HelpFormat::kHumanReadable);
+
+// Produces the help messages for all flags matching the filter. A flag matches
+// the filter if it is defined in a file with a filename which includes
+// filter string as a substring. You can use '/' and '.' to restrict the
+// matching to a specific file names. For example:
+// FlagsHelp(out, "/path/to/file.");
+// restricts help to only flags which resides in files named like:
+// .../path/to/file.<ext>
+// for any extension 'ext'. If the filter is empty this function produces help
+// messages for all flags.
+void FlagsHelp(std::ostream& out, absl::string_view filter,
+ HelpFormat format, absl::string_view program_usage_message);
+
+// --------------------------------------------------------------------
+
+// If any of the 'usage' related command line flags (listed on the bottom of
+// this file) has been set this routine produces corresponding help message in
+// the specified output stream and returns:
+// 0 - if "version" or "only_check_flags" flags were set and handled.
+// 1 - if some other 'usage' related flag was set and handled.
+// -1 - if no usage flags were set on a commmand line.
+// Non negative return values are expected to be used as an exit code for a
+// binary.
+int HandleUsageFlags(std::ostream& out,
+ absl::string_view program_usage_message);
+
+// --------------------------------------------------------------------
+// Globals representing usage reporting flags
+
+enum class HelpMode {
+ kNone,
+ kImportant,
+ kShort,
+ kFull,
+ kPackage,
+ kMatch,
+ kVersion,
+ kOnlyCheckArgs
+};
+
+// Returns substring to filter help output (--help=substr argument)
+std::string GetFlagsHelpMatchSubstr();
+// Returns the requested help mode.
+HelpMode GetFlagsHelpMode();
+// Returns the requested help format.
+HelpFormat GetFlagsHelpFormat();
+
+// These are corresponding setters to the attributes above.
+void SetFlagsHelpMatchSubstr(absl::string_view);
+void SetFlagsHelpMode(HelpMode);
+void SetFlagsHelpFormat(HelpFormat);
+
+// Deduces usage flags from the input argument in a form --name=value or
+// --name. argument is already split into name and value before we call this
+// function.
+bool DeduceUsageFlags(absl::string_view name, absl::string_view value);
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage_test.cc
new file mode 100644
index 00000000000..b5c2487da57
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/internal/usage_test.cc
@@ -0,0 +1,493 @@
+//
+// 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.
+
+#include "absl/flags/internal/usage.h"
+
+#include <stdint.h>
+
+#include <sstream>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/reflection.h"
+#include "absl/flags/usage.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+
+ABSL_FLAG(int, usage_reporting_test_flag_01, 101,
+ "usage_reporting_test_flag_01 help message");
+ABSL_FLAG(bool, usage_reporting_test_flag_02, false,
+ "usage_reporting_test_flag_02 help message");
+ABSL_FLAG(double, usage_reporting_test_flag_03, 1.03,
+ "usage_reporting_test_flag_03 help message");
+ABSL_FLAG(int64_t, usage_reporting_test_flag_04, 1000000000000004L,
+ "usage_reporting_test_flag_04 help message");
+
+static const char kTestUsageMessage[] = "Custom usage message";
+
+struct UDT {
+ UDT() = default;
+ UDT(const UDT&) = default;
+};
+bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
+std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; }
+
+ABSL_FLAG(UDT, usage_reporting_test_flag_05, {},
+ "usage_reporting_test_flag_05 help message");
+
+ABSL_FLAG(
+ std::string, usage_reporting_test_flag_06, {},
+ "usage_reporting_test_flag_06 help message.\n"
+ "\n"
+ "Some more help.\n"
+ "Even more long long long long long long long long long long long long "
+ "help message.");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+
+static std::string NormalizeFileName(absl::string_view fname) {
+#ifdef _WIN32
+ std::string normalized(fname);
+ std::replace(normalized.begin(), normalized.end(), '\\', '/');
+ fname = normalized;
+#endif
+
+ auto absl_pos = fname.rfind("absl/");
+ if (absl_pos != absl::string_view::npos) {
+ fname = fname.substr(absl_pos);
+ }
+ return std::string(fname);
+}
+
+class UsageReportingTest : public testing::Test {
+ protected:
+ UsageReportingTest() {
+ // Install default config for the use on this unit test.
+ // Binary may install a custom config before tests are run.
+ absl::FlagsUsageConfig default_config;
+ default_config.normalize_filename = &NormalizeFileName;
+ absl::SetFlagsUsageConfig(default_config);
+ }
+ ~UsageReportingTest() override {
+ flags::SetFlagsHelpMode(flags::HelpMode::kNone);
+ flags::SetFlagsHelpMatchSubstr("");
+ flags::SetFlagsHelpFormat(flags::HelpFormat::kHumanReadable);
+ }
+
+ private:
+ absl::FlagSaver flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+using UsageReportingDeathTest = UsageReportingTest;
+
+TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
+ EXPECT_EQ(absl::ProgramUsageMessage(), kTestUsageMessage);
+
+#ifndef _WIN32
+ // TODO(rogeeff): figure out why this does not work on Windows.
+ EXPECT_DEATH_IF_SUPPORTED(
+ absl::SetProgramUsageMessage("custom usage message"),
+ ".*SetProgramUsageMessage\\(\\) called twice.*");
+#endif
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_01");
+ std::stringstream test_buf;
+
+ flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+ EXPECT_EQ(
+ test_buf.str(),
+ R"( --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
+ std::stringstream test_buf;
+
+ flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+ EXPECT_EQ(
+ test_buf.str(),
+ R"( --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
+ std::stringstream test_buf;
+
+ flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+ EXPECT_EQ(
+ test_buf.str(),
+ R"( --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
+ std::stringstream test_buf;
+
+ flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+ EXPECT_EQ(
+ test_buf.str(),
+ R"( --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+)");
+}
+
+TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
+ const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
+ std::stringstream test_buf;
+
+ flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
+ EXPECT_EQ(
+ test_buf.str(),
+ R"( --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
+ std::string usage_test_flags_out =
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)";
+
+ std::stringstream test_buf_01;
+ flags::FlagsHelp(test_buf_01, "usage_test.cc",
+ flags::HelpFormat::kHumanReadable, kTestUsageMessage);
+ EXPECT_EQ(test_buf_01.str(), usage_test_flags_out);
+
+ std::stringstream test_buf_02;
+ flags::FlagsHelp(test_buf_02, "flags/internal/usage_test.cc",
+ flags::HelpFormat::kHumanReadable, kTestUsageMessage);
+ EXPECT_EQ(test_buf_02.str(), usage_test_flags_out);
+
+ std::stringstream test_buf_03;
+ flags::FlagsHelp(test_buf_03, "usage_test", flags::HelpFormat::kHumanReadable,
+ kTestUsageMessage);
+ EXPECT_EQ(test_buf_03.str(), usage_test_flags_out);
+
+ std::stringstream test_buf_04;
+ flags::FlagsHelp(test_buf_04, "flags/invalid_file_name.cc",
+ flags::HelpFormat::kHumanReadable, kTestUsageMessage);
+ EXPECT_EQ(test_buf_04.str(),
+ R"(usage_test: Custom usage message
+
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+
+ std::stringstream test_buf_05;
+ flags::FlagsHelp(test_buf_05, "", flags::HelpFormat::kHumanReadable,
+ kTestUsageMessage);
+ std::string test_out = test_buf_05.str();
+ absl::string_view test_out_str(test_out);
+ EXPECT_TRUE(
+ absl::StartsWith(test_out_str, "usage_test: Custom usage message"));
+ EXPECT_TRUE(absl::StrContains(
+ test_out_str, "Flags from absl/flags/internal/usage_test.cc:"));
+ EXPECT_TRUE(
+ absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestNoUsageFlags) {
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), -1);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helpshort) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kShort);
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kImportant);
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_one_flag) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+ flags::SetFlagsHelpMatchSubstr("usage_reporting_test_flag_06");
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+ flags::SetFlagsHelpMatchSubstr("test_flag");
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_version) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+#ifndef NDEBUG
+ EXPECT_EQ(test_buf.str(), "usage_test\nDebug build (NDEBUG not #defined)\n");
+#else
+ EXPECT_EQ(test_buf.str(), "usage_test\n");
+#endif
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
+
+ std::stringstream test_buf;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
+ EXPECT_EQ(test_buf.str(), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
+ flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
+ flags::SetFlagsHelpMatchSubstr("/bla-bla.");
+
+ std::stringstream test_buf_01;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf_01, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf_01.str(),
+ R"(usage_test: Custom usage message
+
+No flags matched.
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+
+ flags::SetFlagsHelpMatchSubstr("/usage_test.");
+
+ std::stringstream test_buf_02;
+ EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
+ EXPECT_EQ(test_buf_02.str(),
+ R"(usage_test: Custom usage message
+
+ Flags from absl/flags/internal/usage_test.cc:
+ --usage_reporting_test_flag_01 (usage_reporting_test_flag_01 help message);
+ default: 101;
+ --usage_reporting_test_flag_02 (usage_reporting_test_flag_02 help message);
+ default: false;
+ --usage_reporting_test_flag_03 (usage_reporting_test_flag_03 help message);
+ default: 1.03;
+ --usage_reporting_test_flag_04 (usage_reporting_test_flag_04 help message);
+ default: 1000000000000004;
+ --usage_reporting_test_flag_05 (usage_reporting_test_flag_05 help message);
+ default: UDT{};
+ --usage_reporting_test_flag_06 (usage_reporting_test_flag_06 help message.
+
+ Some more help.
+ Even more long long long long long long long long long long long long help
+ message.); default: "";
+
+Try --helpfull to get a list of all flags or --help=substring shows help for
+flags which include specified substring in either in the name, or description or
+path.
+)");
+}
+
+// --------------------------------------------------------------------
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ (void)absl::GetFlag(FLAGS_undefok); // Force linking of parse.cc
+ flags::SetProgramInvocationName("usage_test");
+ absl::SetProgramUsageMessage(kTestUsageMessage);
+ ::testing::InitGoogleTest(&argc, argv);
+
+ return RUN_ALL_TESTS();
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.cc
new file mode 100644
index 00000000000..81f9cebd6f4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.cc
@@ -0,0 +1,241 @@
+//
+// 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.
+
+#include "absl/flags/marshalling.h"
+
+#include <stddef.h>
+
+#include <cmath>
+#include <limits>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/log_severity.h"
+#include "absl/base/macros.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/match.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// AbslParseFlag specializations for boolean type.
+
+bool AbslParseFlag(absl::string_view text, bool* dst, std::string*) {
+ const char* kTrue[] = {"1", "t", "true", "y", "yes"};
+ const char* kFalse[] = {"0", "f", "false", "n", "no"};
+ static_assert(sizeof(kTrue) == sizeof(kFalse), "true_false_equal");
+
+ text = absl::StripAsciiWhitespace(text);
+
+ for (size_t i = 0; i < ABSL_ARRAYSIZE(kTrue); ++i) {
+ if (absl::EqualsIgnoreCase(text, kTrue[i])) {
+ *dst = true;
+ return true;
+ } else if (absl::EqualsIgnoreCase(text, kFalse[i])) {
+ *dst = false;
+ return true;
+ }
+ }
+ return false; // didn't match a legal input
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for integral types.
+
+// Return the base to use for parsing text as an integer. Leading 0x
+// puts us in base 16. But leading 0 does not put us in base 8. It
+// caused too many bugs when we had that behavior.
+static int NumericBase(absl::string_view text) {
+ const bool hex = (text.size() >= 2 && text[0] == '0' &&
+ (text[1] == 'x' || text[1] == 'X'));
+ return hex ? 16 : 10;
+}
+
+template <typename IntType>
+inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
+ text = absl::StripAsciiWhitespace(text);
+
+ return absl::numbers_internal::safe_strtoi_base(text, &dst,
+ NumericBase(text));
+}
+
+bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
+ int val;
+ if (!ParseFlagImpl(text, val)) return false;
+ if (static_cast<short>(val) != val) // worked, but number out of range
+ return false;
+ *dst = static_cast<short>(val);
+ return true;
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
+ unsigned int val;
+ if (!ParseFlagImpl(text, val)) return false;
+ if (static_cast<unsigned short>(val) !=
+ val) // worked, but number out of range
+ return false;
+ *dst = static_cast<unsigned short>(val);
+ return true;
+}
+
+bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
+ std::string*) {
+ return ParseFlagImpl(text, *dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for floating point types.
+
+bool AbslParseFlag(absl::string_view text, float* dst, std::string*) {
+ return absl::SimpleAtof(text, dst);
+}
+
+bool AbslParseFlag(absl::string_view text, double* dst, std::string*) {
+ return absl::SimpleAtod(text, dst);
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for strings.
+
+bool AbslParseFlag(absl::string_view text, std::string* dst, std::string*) {
+ dst->assign(text.data(), text.size());
+ return true;
+}
+
+// --------------------------------------------------------------------
+// AbslParseFlag for vector of strings.
+
+bool AbslParseFlag(absl::string_view text, std::vector<std::string>* dst,
+ std::string*) {
+ // An empty flag value corresponds to an empty vector, not a vector
+ // with a single, empty std::string.
+ if (text.empty()) {
+ dst->clear();
+ return true;
+ }
+ *dst = absl::StrSplit(text, ',', absl::AllowEmpty());
+ return true;
+}
+
+// --------------------------------------------------------------------
+// AbslUnparseFlag specializations for various builtin flag types.
+
+std::string Unparse(bool v) { return v ? "true" : "false"; }
+std::string Unparse(short v) { return absl::StrCat(v); }
+std::string Unparse(unsigned short v) { return absl::StrCat(v); }
+std::string Unparse(int v) { return absl::StrCat(v); }
+std::string Unparse(unsigned int v) { return absl::StrCat(v); }
+std::string Unparse(long v) { return absl::StrCat(v); }
+std::string Unparse(unsigned long v) { return absl::StrCat(v); }
+std::string Unparse(long long v) { return absl::StrCat(v); }
+std::string Unparse(unsigned long long v) { return absl::StrCat(v); }
+template <typename T>
+std::string UnparseFloatingPointVal(T v) {
+ // digits10 is guaranteed to roundtrip correctly in string -> value -> string
+ // conversions, but may not be enough to represent all the values correctly.
+ std::string digit10_str =
+ absl::StrFormat("%.*g", std::numeric_limits<T>::digits10, v);
+ if (std::isnan(v) || std::isinf(v)) return digit10_str;
+
+ T roundtrip_val = 0;
+ std::string err;
+ if (absl::ParseFlag(digit10_str, &roundtrip_val, &err) &&
+ roundtrip_val == v) {
+ return digit10_str;
+ }
+
+ // max_digits10 is the number of base-10 digits that are necessary to uniquely
+ // represent all distinct values.
+ return absl::StrFormat("%.*g", std::numeric_limits<T>::max_digits10, v);
+}
+std::string Unparse(float v) { return UnparseFloatingPointVal(v); }
+std::string Unparse(double v) { return UnparseFloatingPointVal(v); }
+std::string AbslUnparseFlag(absl::string_view v) { return std::string(v); }
+std::string AbslUnparseFlag(const std::vector<std::string>& v) {
+ return absl::StrJoin(v, ",");
+}
+
+} // namespace flags_internal
+
+bool AbslParseFlag(absl::string_view text, absl::LogSeverity* dst,
+ std::string* err) {
+ text = absl::StripAsciiWhitespace(text);
+ if (text.empty()) {
+ *err = "no value provided";
+ return false;
+ }
+ if (text.front() == 'k' || text.front() == 'K') text.remove_prefix(1);
+ if (absl::EqualsIgnoreCase(text, "info")) {
+ *dst = absl::LogSeverity::kInfo;
+ return true;
+ }
+ if (absl::EqualsIgnoreCase(text, "warning")) {
+ *dst = absl::LogSeverity::kWarning;
+ return true;
+ }
+ if (absl::EqualsIgnoreCase(text, "error")) {
+ *dst = absl::LogSeverity::kError;
+ return true;
+ }
+ if (absl::EqualsIgnoreCase(text, "fatal")) {
+ *dst = absl::LogSeverity::kFatal;
+ return true;
+ }
+ std::underlying_type<absl::LogSeverity>::type numeric_value;
+ if (absl::ParseFlag(text, &numeric_value, err)) {
+ *dst = static_cast<absl::LogSeverity>(numeric_value);
+ return true;
+ }
+ *err = "only integers and absl::LogSeverity enumerators are accepted";
+ return false;
+}
+
+std::string AbslUnparseFlag(absl::LogSeverity v) {
+ if (v == absl::NormalizeLogSeverity(v)) return absl::LogSeverityName(v);
+ return absl::UnparseFlag(static_cast<int>(v));
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.h
new file mode 100644
index 00000000000..7cbc136d579
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling.h
@@ -0,0 +1,264 @@
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: marshalling.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the API for extending Abseil flag support to
+// custom types, and defines the set of overloads for fundamental types.
+//
+// Out of the box, the Abseil flags library supports the following types:
+//
+// * `bool`
+// * `int16_t`
+// * `uint16_t`
+// * `int32_t`
+// * `uint32_t`
+// * `int64_t`
+// * `uint64_t`
+// * `float`
+// * `double`
+// * `std::string`
+// * `std::vector<std::string>`
+// * `absl::LogSeverity` (provided natively for layering reasons)
+//
+// Note that support for integral types is implemented using overloads for
+// variable-width fundamental types (`short`, `int`, `long`, etc.). However,
+// you should prefer the fixed-width integral types (`int32_t`, `uint64_t`,
+// etc.) we've noted above within flag definitions.
+//
+// In addition, several Abseil libraries provide their own custom support for
+// Abseil flags. Documentation for these formats is provided in the type's
+// `AbslParseFlag()` definition.
+//
+// The Abseil time library provides the following support for civil time values:
+//
+// * `absl::CivilSecond`
+// * `absl::CivilMinute`
+// * `absl::CivilHour`
+// * `absl::CivilDay`
+// * `absl::CivilMonth`
+// * `absl::CivilYear`
+//
+// and also provides support for the following absolute time values:
+//
+// * `absl::Duration`
+// * `absl::Time`
+//
+// Additional support for Abseil types will be noted here as it is added.
+//
+// You can also provide your own custom flags by adding overloads for
+// `AbslParseFlag()` and `AbslUnparseFlag()` to your type definitions. (See
+// below.)
+//
+// -----------------------------------------------------------------------------
+// Adding Type Support for Abseil Flags
+// -----------------------------------------------------------------------------
+//
+// To add support for your user-defined type, add overloads of `AbslParseFlag()`
+// and `AbslUnparseFlag()` as free (non-member) functions to your type. If `T`
+// is a class type, these functions can be friend function definitions. These
+// overloads must be added to the same namespace where the type is defined, so
+// that they can be discovered by Argument-Dependent Lookup (ADL).
+//
+// Example:
+//
+// namespace foo {
+//
+// enum OutputMode { kPlainText, kHtml };
+//
+// // AbslParseFlag converts from a string to OutputMode.
+// // Must be in same namespace as OutputMode.
+//
+// // Parses an OutputMode from the command line flag value `text`. Returns
+// // `true` and sets `*mode` on success; returns `false` and sets `*error`
+// // on failure.
+// bool AbslParseFlag(absl::string_view text,
+// OutputMode* mode,
+// std::string* error) {
+// if (text == "plaintext") {
+// *mode = kPlainText;
+// return true;
+// }
+// if (text == "html") {
+// *mode = kHtml;
+// return true;
+// }
+// *error = "unknown value for enumeration";
+// return false;
+// }
+//
+// // AbslUnparseFlag converts from an OutputMode to a string.
+// // Must be in same namespace as OutputMode.
+//
+// // Returns a textual flag value corresponding to the OutputMode `mode`.
+// std::string AbslUnparseFlag(OutputMode mode) {
+// switch (mode) {
+// case kPlainText: return "plaintext";
+// case kHtml: return "html";
+// }
+// return absl::StrCat(mode);
+// }
+//
+// Notice that neither `AbslParseFlag()` nor `AbslUnparseFlag()` are class
+// members, but free functions. `AbslParseFlag/AbslUnparseFlag()` overloads
+// for a type should only be declared in the same file and namespace as said
+// type. The proper `AbslParseFlag/AbslUnparseFlag()` implementations for a
+// given type will be discovered via Argument-Dependent Lookup (ADL).
+//
+// `AbslParseFlag()` may need, in turn, to parse simpler constituent types
+// using `absl::ParseFlag()`. For example, a custom struct `MyFlagType`
+// consisting of a `std::pair<int, std::string>` would add an `AbslParseFlag()`
+// overload for its `MyFlagType` like so:
+//
+// Example:
+//
+// namespace my_flag_type {
+//
+// struct MyFlagType {
+// std::pair<int, std::string> my_flag_data;
+// };
+//
+// bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
+// std::string* err);
+//
+// std::string AbslUnparseFlag(const MyFlagType&);
+//
+// // Within the implementation, `AbslParseFlag()` will, in turn invoke
+// // `absl::ParseFlag()` on its constituent `int` and `std::string` types
+// // (which have built-in Abseil flag support).
+//
+// bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
+// std::string* err) {
+// std::pair<absl::string_view, absl::string_view> tokens =
+// absl::StrSplit(text, ',');
+// if (!absl::ParseFlag(tokens.first, &flag->my_flag_data.first, err))
+// return false;
+// if (!absl::ParseFlag(tokens.second, &flag->my_flag_data.second, err))
+// return false;
+// return true;
+// }
+//
+// // Similarly, for unparsing, we can simply invoke `absl::UnparseFlag()` on
+// // the constituent types.
+// std::string AbslUnparseFlag(const MyFlagType& flag) {
+// return absl::StrCat(absl::UnparseFlag(flag.my_flag_data.first),
+// ",",
+// absl::UnparseFlag(flag.my_flag_data.second));
+// }
+#ifndef ABSL_FLAGS_MARSHALLING_H_
+#define ABSL_FLAGS_MARSHALLING_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// Overloads of `AbslParseFlag()` and `AbslUnparseFlag()` for fundamental types.
+bool AbslParseFlag(absl::string_view, bool*, std::string*);
+bool AbslParseFlag(absl::string_view, short*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned short*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, int*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned int*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, long*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned long*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, long long*, std::string*); // NOLINT
+bool AbslParseFlag(absl::string_view, unsigned long long*, // NOLINT
+ std::string*);
+bool AbslParseFlag(absl::string_view, float*, std::string*);
+bool AbslParseFlag(absl::string_view, double*, std::string*);
+bool AbslParseFlag(absl::string_view, std::string*, std::string*);
+bool AbslParseFlag(absl::string_view, std::vector<std::string>*, std::string*);
+
+template <typename T>
+bool InvokeParseFlag(absl::string_view input, T* dst, std::string* err) {
+ // Comment on next line provides a good compiler error message if T
+ // does not have AbslParseFlag(absl::string_view, T*, std::string*).
+ return AbslParseFlag(input, dst, err); // Is T missing AbslParseFlag?
+}
+
+// Strings and std:: containers do not have the same overload resolution
+// considerations as fundamental types. Naming these 'AbslUnparseFlag' means we
+// can avoid the need for additional specializations of Unparse (below).
+std::string AbslUnparseFlag(absl::string_view v);
+std::string AbslUnparseFlag(const std::vector<std::string>&);
+
+template <typename T>
+std::string Unparse(const T& v) {
+ // Comment on next line provides a good compiler error message if T does not
+ // have UnparseFlag.
+ return AbslUnparseFlag(v); // Is T missing AbslUnparseFlag?
+}
+
+// Overloads for builtin types.
+std::string Unparse(bool v);
+std::string Unparse(short v); // NOLINT
+std::string Unparse(unsigned short v); // NOLINT
+std::string Unparse(int v); // NOLINT
+std::string Unparse(unsigned int v); // NOLINT
+std::string Unparse(long v); // NOLINT
+std::string Unparse(unsigned long v); // NOLINT
+std::string Unparse(long long v); // NOLINT
+std::string Unparse(unsigned long long v); // NOLINT
+std::string Unparse(float v);
+std::string Unparse(double v);
+
+} // namespace flags_internal
+
+// ParseFlag()
+//
+// Parses a string value into a flag value of type `T`. Do not add overloads of
+// this function for your type directly; instead, add an `AbslParseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslParseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may need to call
+// `absl::ParseFlag()` on those consituent string values. (See above.)
+template <typename T>
+inline bool ParseFlag(absl::string_view input, T* dst, std::string* error) {
+ return flags_internal::InvokeParseFlag(input, dst, error);
+}
+
+// UnparseFlag()
+//
+// Unparses a flag value of type `T` into a string value. Do not add overloads
+// of this function for your type directly; instead, add an `AbslUnparseFlag()`
+// free function as documented above.
+//
+// Some implementations of `AbslUnparseFlag()` for types which consist of other,
+// constituent types which already have Abseil flag support, may want to call
+// `absl::UnparseFlag()` on those constituent types. (See above.)
+template <typename T>
+inline std::string UnparseFlag(const T& v) {
+ return flags_internal::Unparse(v);
+}
+
+// Overloads for `absl::LogSeverity` can't (easily) appear alongside that type's
+// definition because it is layered below flags. See proper documentation in
+// base/log_severity.h.
+enum class LogSeverity : int;
+bool AbslParseFlag(absl::string_view, absl::LogSeverity*, std::string*);
+std::string AbslUnparseFlag(absl::LogSeverity);
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_MARSHALLING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling_test.cc
new file mode 100644
index 00000000000..4a64ce11a16
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/marshalling_test.cc
@@ -0,0 +1,904 @@
+//
+// 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.
+
+#include "absl/flags/marshalling.h"
+
+#include <stdint.h>
+
+#include <cmath>
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(MarshallingTest, TestBoolParsing) {
+ std::string err;
+ bool value;
+
+ // True values.
+ EXPECT_TRUE(absl::ParseFlag("True", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("true", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("TRUE", &value, &err));
+ EXPECT_TRUE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("Yes", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("yes", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("YES", &value, &err));
+ EXPECT_TRUE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("t", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("T", &value, &err));
+ EXPECT_TRUE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("y", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("Y", &value, &err));
+ EXPECT_TRUE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_TRUE(value);
+
+ // False values.
+ EXPECT_TRUE(absl::ParseFlag("False", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("false", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("FALSE", &value, &err));
+ EXPECT_FALSE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("No", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("no", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("NO", &value, &err));
+ EXPECT_FALSE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("f", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("F", &value, &err));
+ EXPECT_FALSE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("n", &value, &err));
+ EXPECT_FALSE(value);
+ EXPECT_TRUE(absl::ParseFlag("N", &value, &err));
+ EXPECT_FALSE(value);
+
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_FALSE(value);
+
+ // Whitespace handling.
+ EXPECT_TRUE(absl::ParseFlag(" true", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag("true ", &value, &err));
+ EXPECT_TRUE(value);
+ EXPECT_TRUE(absl::ParseFlag(" true ", &value, &err));
+ EXPECT_TRUE(value);
+
+ // Invalid input.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("11", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("tt", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt16Parsing) {
+ std::string err;
+ int16_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_EQ(value, -1);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("-18765", &value, &err));
+ EXPECT_EQ(value, -18765);
+ EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+ EXPECT_EQ(value, 3);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("-001", &value, &err));
+ EXPECT_EQ(value, -1);
+ EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+ EXPECT_EQ(value, 100);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+ EXPECT_EQ(value, 564);
+ // TODO(rogeeff): fix below validations
+ EXPECT_FALSE(absl::ParseFlag("-0x7FFD", &value, &err));
+ EXPECT_NE(value, -3);
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+ EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err));
+ EXPECT_EQ(value, 34);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("40000", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint16Parsing) {
+ std::string err;
+ uint16_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+ EXPECT_EQ(value, 3);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+ EXPECT_EQ(value, 100);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+ EXPECT_EQ(value, 564);
+ // TODO(rogeeff): fix below validations
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+ EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err));
+ EXPECT_EQ(value, 34);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("70000", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt32Parsing) {
+ std::string err;
+ int32_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_EQ(value, -1);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err));
+ EXPECT_EQ(value, -98765);
+ EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+ EXPECT_EQ(value, 3);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("-001", &value, &err));
+ EXPECT_EQ(value, -1);
+ EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+ EXPECT_EQ(value, 100);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+ EXPECT_EQ(value, 564);
+ // TODO(rogeeff): fix below validations
+ EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFD", &value, &err));
+ EXPECT_NE(value, -3);
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+ EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err));
+ EXPECT_EQ(value, 34);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("70000000000", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint32Parsing) {
+ std::string err;
+ uint32_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+ EXPECT_EQ(value, 3);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+ EXPECT_EQ(value, 100);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0X234", &value, &err));
+ EXPECT_EQ(value, 564);
+ EXPECT_TRUE(absl::ParseFlag("0xFFFFFFFD", &value, &err));
+ EXPECT_EQ(value, 4294967293);
+ // TODO(rogeeff): fix below validations
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+ EXPECT_TRUE(absl::ParseFlag(" 0x22 ", &value, &err));
+ EXPECT_EQ(value, 34);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("140000000000", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt64Parsing) {
+ std::string err;
+ int64_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_EQ(value, -1);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("-98765", &value, &err));
+ EXPECT_EQ(value, -98765);
+ EXPECT_TRUE(absl::ParseFlag("+3", &value, &err));
+ EXPECT_EQ(value, 3);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0000100", &value, &err));
+ EXPECT_EQ(value, 100);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0XFFFAAABBBCCCDDD", &value, &err));
+ EXPECT_EQ(value, 1152827684197027293);
+ // TODO(rogeeff): fix below validation
+ EXPECT_FALSE(absl::ParseFlag("-0x7FFFFFFFFFFFFFFE", &value, &err));
+ EXPECT_NE(value, -2);
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+ EXPECT_TRUE(absl::ParseFlag(" 0x7F ", &value, &err));
+ EXPECT_EQ(value, 127);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUInt64Parsing) {
+ std::string err;
+ uint64_t value;
+
+ // Decimal values.
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0", &value, &err));
+ EXPECT_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("123", &value, &err));
+ EXPECT_EQ(value, 123);
+ EXPECT_TRUE(absl::ParseFlag("+13", &value, &err));
+ EXPECT_EQ(value, 13);
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("001", &value, &err));
+ EXPECT_EQ(value, 1);
+ EXPECT_TRUE(absl::ParseFlag("0000300", &value, &err));
+ EXPECT_EQ(value, 300);
+
+ // Hex values.
+ EXPECT_TRUE(absl::ParseFlag("0x10", &value, &err));
+ EXPECT_EQ(value, 16);
+ EXPECT_TRUE(absl::ParseFlag("0XFFFF", &value, &err));
+ EXPECT_EQ(value, 65535);
+ // TODO(rogeeff): fix below validation
+ EXPECT_FALSE(absl::ParseFlag("+0x31", &value, &err));
+ EXPECT_NE(value, 49);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10 ", &value, &err));
+ EXPECT_EQ(value, 10);
+ EXPECT_TRUE(absl::ParseFlag(" 11", &value, &err));
+ EXPECT_EQ(value, 11);
+ EXPECT_TRUE(absl::ParseFlag(" 012 ", &value, &err));
+ EXPECT_EQ(value, 12);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("0xFFFFFFFFFFFFFFFFFF", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("-1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2U", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("FFF", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestFloatParsing) {
+ std::string err;
+ float value;
+
+ // Ordinary values.
+ EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err));
+ EXPECT_FLOAT_EQ(value, 1.3f);
+ EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err));
+ EXPECT_DOUBLE_EQ(value, -0.1f);
+ EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.01f);
+
+ // Scientific values.
+ EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 1.2e3f);
+ EXPECT_TRUE(absl::ParseFlag("9.8765402e-37", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 9.8765402e-37f);
+ EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.11e+3f);
+ EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.f);
+ EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err));
+ EXPECT_TRUE(std::isinf(value));
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 1.6f);
+ EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.0001f);
+
+ // Trailing zero values.
+ EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err));
+ EXPECT_DOUBLE_EQ(value, -5.1f);
+
+ // Exceptional values.
+ EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err));
+ EXPECT_TRUE(std::isnan(value));
+ EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err));
+ EXPECT_TRUE(std::isinf(value));
+
+ // Hex values
+ EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 66096.f);
+ EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err));
+ EXPECT_NEAR(value, -60.4092f, 5e-5f);
+ EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err));
+ EXPECT_NEAR(value, 1.01328e-05f, 5e-11f);
+ EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err));
+ EXPECT_NEAR(value, 0.0078125f, 5e-8f);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10.1 ", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 10.1f);
+ EXPECT_TRUE(absl::ParseFlag(" 2.34", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 2.34f);
+ EXPECT_TRUE(absl::ParseFlag(" 5.7 ", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 5.7f);
+ EXPECT_TRUE(absl::ParseFlag(" -0xE0.F3p01 ", &value, &err));
+ EXPECT_NEAR(value, -449.8984375f, 5e-8f);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err));
+ // TODO(rogeeff): below assertion should fail
+ EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestDoubleParsing) {
+ std::string err;
+ double value;
+
+ // Ordinary values.
+ EXPECT_TRUE(absl::ParseFlag("1.3", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 1.3);
+ EXPECT_TRUE(absl::ParseFlag("-0.1", &value, &err));
+ EXPECT_DOUBLE_EQ(value, -0.1);
+ EXPECT_TRUE(absl::ParseFlag("+0.01", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.01);
+
+ // Scientific values.
+ EXPECT_TRUE(absl::ParseFlag("1.2e3", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 1.2e3);
+ EXPECT_TRUE(absl::ParseFlag("9.00000002e-123", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 9.00000002e-123);
+ EXPECT_TRUE(absl::ParseFlag("0.11e+3", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.11e+3);
+ EXPECT_TRUE(absl::ParseFlag("1.e-2300", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0);
+ EXPECT_TRUE(absl::ParseFlag("1.e+2300", &value, &err));
+ EXPECT_TRUE(std::isinf(value));
+
+ // Leading zero values.
+ EXPECT_TRUE(absl::ParseFlag("01.6", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 1.6);
+ EXPECT_TRUE(absl::ParseFlag("000.0001", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 0.0001);
+
+ // Trailing zero values.
+ EXPECT_TRUE(absl::ParseFlag("-5.1000", &value, &err));
+ EXPECT_DOUBLE_EQ(value, -5.1);
+
+ // Exceptional values.
+ EXPECT_TRUE(absl::ParseFlag("NaN", &value, &err));
+ EXPECT_TRUE(std::isnan(value));
+ EXPECT_TRUE(absl::ParseFlag("nan", &value, &err));
+ EXPECT_TRUE(std::isnan(value));
+ EXPECT_TRUE(absl::ParseFlag("Inf", &value, &err));
+ EXPECT_TRUE(std::isinf(value));
+ EXPECT_TRUE(absl::ParseFlag("inf", &value, &err));
+ EXPECT_TRUE(std::isinf(value));
+
+ // Hex values
+ EXPECT_TRUE(absl::ParseFlag("0x10.23p12", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 66096);
+ EXPECT_TRUE(absl::ParseFlag("-0xF1.A3p-2", &value, &err));
+ EXPECT_NEAR(value, -60.4092, 5e-5);
+ EXPECT_TRUE(absl::ParseFlag("+0x0.0AAp-12", &value, &err));
+ EXPECT_NEAR(value, 1.01328e-05, 5e-11);
+ EXPECT_TRUE(absl::ParseFlag("0x.01p1", &value, &err));
+ EXPECT_NEAR(value, 0.0078125, 5e-8);
+
+ // Whitespace handling
+ EXPECT_TRUE(absl::ParseFlag("10.1 ", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 10.1);
+ EXPECT_TRUE(absl::ParseFlag(" 2.34", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 2.34);
+ EXPECT_TRUE(absl::ParseFlag(" 5.7 ", &value, &err));
+ EXPECT_DOUBLE_EQ(value, 5.7);
+ EXPECT_TRUE(absl::ParseFlag(" -0xE0.F3p01 ", &value, &err));
+ EXPECT_NEAR(value, -449.8984375, 5e-8);
+
+ // Invalid values.
+ EXPECT_FALSE(absl::ParseFlag("", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("--1", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("2.3xxx", &value, &err));
+ EXPECT_FALSE(absl::ParseFlag("0x0.1pAA", &value, &err));
+ // TODO(rogeeff): below assertion should fail
+ EXPECT_TRUE(absl::ParseFlag("0x0.1", &value, &err));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestStringParsing) {
+ std::string err;
+ std::string value;
+
+ EXPECT_TRUE(absl::ParseFlag("", &value, &err));
+ EXPECT_EQ(value, "");
+ EXPECT_TRUE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_EQ(value, " ");
+ EXPECT_TRUE(absl::ParseFlag(" ", &value, &err));
+ EXPECT_EQ(value, " ");
+ EXPECT_TRUE(absl::ParseFlag("\n", &value, &err));
+ EXPECT_EQ(value, "\n");
+ EXPECT_TRUE(absl::ParseFlag("\t", &value, &err));
+ EXPECT_EQ(value, "\t");
+ EXPECT_TRUE(absl::ParseFlag("asdfg", &value, &err));
+ EXPECT_EQ(value, "asdfg");
+ EXPECT_TRUE(absl::ParseFlag("asdf ghjk", &value, &err));
+ EXPECT_EQ(value, "asdf ghjk");
+ EXPECT_TRUE(absl::ParseFlag("a\nb\nc", &value, &err));
+ EXPECT_EQ(value, "a\nb\nc");
+ EXPECT_TRUE(absl::ParseFlag("asd\0fgh", &value, &err));
+ EXPECT_EQ(value, "asd");
+ EXPECT_TRUE(absl::ParseFlag("\\\\", &value, &err));
+ EXPECT_EQ(value, "\\\\");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestVectorOfStringParsing) {
+ std::string err;
+ std::vector<std::string> value;
+
+ EXPECT_TRUE(absl::ParseFlag("", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>{});
+ EXPECT_TRUE(absl::ParseFlag("1", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"1"}));
+ EXPECT_TRUE(absl::ParseFlag("a,b", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"a", "b"}));
+ EXPECT_TRUE(absl::ParseFlag("a,b,c,", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"a", "b", "c", ""}));
+ EXPECT_TRUE(absl::ParseFlag("a,,", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"a", "", ""}));
+ EXPECT_TRUE(absl::ParseFlag(",", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"", ""}));
+ EXPECT_TRUE(absl::ParseFlag("a, b,c ", &value, &err));
+ EXPECT_EQ(value, std::vector<std::string>({"a", " b", "c "}));
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestBoolUnparsing) {
+ EXPECT_EQ(absl::UnparseFlag(true), "true");
+ EXPECT_EQ(absl::UnparseFlag(false), "false");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt16Unparsing) {
+ int16_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = -1;
+ EXPECT_EQ(absl::UnparseFlag(value), "-1");
+ value = 9876;
+ EXPECT_EQ(absl::UnparseFlag(value), "9876");
+ value = -987;
+ EXPECT_EQ(absl::UnparseFlag(value), "-987");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint16Unparsing) {
+ uint16_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = 19876;
+ EXPECT_EQ(absl::UnparseFlag(value), "19876");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt32Unparsing) {
+ int32_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = -1;
+ EXPECT_EQ(absl::UnparseFlag(value), "-1");
+ value = 12345;
+ EXPECT_EQ(absl::UnparseFlag(value), "12345");
+ value = -987;
+ EXPECT_EQ(absl::UnparseFlag(value), "-987");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint32Unparsing) {
+ uint32_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = 1234500;
+ EXPECT_EQ(absl::UnparseFlag(value), "1234500");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestInt64Unparsing) {
+ int64_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = -1;
+ EXPECT_EQ(absl::UnparseFlag(value), "-1");
+ value = 123456789L;
+ EXPECT_EQ(absl::UnparseFlag(value), "123456789");
+ value = -987654321L;
+ EXPECT_EQ(absl::UnparseFlag(value), "-987654321");
+ value = 0x7FFFFFFFFFFFFFFF;
+ EXPECT_EQ(absl::UnparseFlag(value), "9223372036854775807");
+ value = 0xFFFFFFFFFFFFFFFF;
+ EXPECT_EQ(absl::UnparseFlag(value), "-1");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestUint64Unparsing) {
+ uint64_t value;
+
+ value = 1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1");
+ value = 0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = 123456789L;
+ EXPECT_EQ(absl::UnparseFlag(value), "123456789");
+ value = 0xFFFFFFFFFFFFFFFF;
+ EXPECT_EQ(absl::UnparseFlag(value), "18446744073709551615");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestFloatUnparsing) {
+ float value;
+
+ value = 1.1f;
+ EXPECT_EQ(absl::UnparseFlag(value), "1.1");
+ value = 0.01f;
+ EXPECT_EQ(absl::UnparseFlag(value), "0.01");
+ value = 1.23e-2f;
+ EXPECT_EQ(absl::UnparseFlag(value), "0.0123");
+ value = -0.71f;
+ EXPECT_EQ(absl::UnparseFlag(value), "-0.71");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestDoubleUnparsing) {
+ double value;
+
+ value = 1.1;
+ EXPECT_EQ(absl::UnparseFlag(value), "1.1");
+ value = 0.01;
+ EXPECT_EQ(absl::UnparseFlag(value), "0.01");
+ value = 1.23e-2;
+ EXPECT_EQ(absl::UnparseFlag(value), "0.0123");
+ value = -0.71;
+ EXPECT_EQ(absl::UnparseFlag(value), "-0.71");
+ value = -0;
+ EXPECT_EQ(absl::UnparseFlag(value), "0");
+ value = std::nan("");
+ EXPECT_EQ(absl::UnparseFlag(value), "nan");
+ value = std::numeric_limits<double>::infinity();
+ EXPECT_EQ(absl::UnparseFlag(value), "inf");
+}
+
+// --------------------------------------------------------------------
+
+TEST(MarshallingTest, TestStringUnparsing) {
+ EXPECT_EQ(absl::UnparseFlag(""), "");
+ EXPECT_EQ(absl::UnparseFlag(" "), " ");
+ EXPECT_EQ(absl::UnparseFlag("qwerty"), "qwerty");
+ EXPECT_EQ(absl::UnparseFlag("ASDFGH"), "ASDFGH");
+ EXPECT_EQ(absl::UnparseFlag("\n\t "), "\n\t ");
+}
+
+// --------------------------------------------------------------------
+
+template <typename T>
+void TestRoundtrip(T v) {
+ T new_v;
+ std::string err;
+ EXPECT_TRUE(absl::ParseFlag(absl::UnparseFlag(v), &new_v, &err));
+ EXPECT_EQ(new_v, v);
+}
+
+TEST(MarshallingTest, TestFloatRoundTrip) {
+ TestRoundtrip(0.1f);
+ TestRoundtrip(0.12f);
+ TestRoundtrip(0.123f);
+ TestRoundtrip(0.1234f);
+ TestRoundtrip(0.12345f);
+ TestRoundtrip(0.123456f);
+ TestRoundtrip(0.1234567f);
+ TestRoundtrip(0.12345678f);
+
+ TestRoundtrip(0.1e20f);
+ TestRoundtrip(0.12e20f);
+ TestRoundtrip(0.123e20f);
+ TestRoundtrip(0.1234e20f);
+ TestRoundtrip(0.12345e20f);
+ TestRoundtrip(0.123456e20f);
+ TestRoundtrip(0.1234567e20f);
+ TestRoundtrip(0.12345678e20f);
+
+ TestRoundtrip(0.1e-20f);
+ TestRoundtrip(0.12e-20f);
+ TestRoundtrip(0.123e-20f);
+ TestRoundtrip(0.1234e-20f);
+ TestRoundtrip(0.12345e-20f);
+ TestRoundtrip(0.123456e-20f);
+ TestRoundtrip(0.1234567e-20f);
+ TestRoundtrip(0.12345678e-20f);
+}
+
+TEST(MarshallingTest, TestDoubleRoundTrip) {
+ TestRoundtrip(0.1);
+ TestRoundtrip(0.12);
+ TestRoundtrip(0.123);
+ TestRoundtrip(0.1234);
+ TestRoundtrip(0.12345);
+ TestRoundtrip(0.123456);
+ TestRoundtrip(0.1234567);
+ TestRoundtrip(0.12345678);
+ TestRoundtrip(0.123456789);
+ TestRoundtrip(0.1234567891);
+ TestRoundtrip(0.12345678912);
+ TestRoundtrip(0.123456789123);
+ TestRoundtrip(0.1234567891234);
+ TestRoundtrip(0.12345678912345);
+ TestRoundtrip(0.123456789123456);
+ TestRoundtrip(0.1234567891234567);
+ TestRoundtrip(0.12345678912345678);
+
+ TestRoundtrip(0.1e50);
+ TestRoundtrip(0.12e50);
+ TestRoundtrip(0.123e50);
+ TestRoundtrip(0.1234e50);
+ TestRoundtrip(0.12345e50);
+ TestRoundtrip(0.123456e50);
+ TestRoundtrip(0.1234567e50);
+ TestRoundtrip(0.12345678e50);
+ TestRoundtrip(0.123456789e50);
+ TestRoundtrip(0.1234567891e50);
+ TestRoundtrip(0.12345678912e50);
+ TestRoundtrip(0.123456789123e50);
+ TestRoundtrip(0.1234567891234e50);
+ TestRoundtrip(0.12345678912345e50);
+ TestRoundtrip(0.123456789123456e50);
+ TestRoundtrip(0.1234567891234567e50);
+ TestRoundtrip(0.12345678912345678e50);
+
+ TestRoundtrip(0.1e-50);
+ TestRoundtrip(0.12e-50);
+ TestRoundtrip(0.123e-50);
+ TestRoundtrip(0.1234e-50);
+ TestRoundtrip(0.12345e-50);
+ TestRoundtrip(0.123456e-50);
+ TestRoundtrip(0.1234567e-50);
+ TestRoundtrip(0.12345678e-50);
+ TestRoundtrip(0.123456789e-50);
+ TestRoundtrip(0.1234567891e-50);
+ TestRoundtrip(0.12345678912e-50);
+ TestRoundtrip(0.123456789123e-50);
+ TestRoundtrip(0.1234567891234e-50);
+ TestRoundtrip(0.12345678912345e-50);
+ TestRoundtrip(0.123456789123456e-50);
+ TestRoundtrip(0.1234567891234567e-50);
+ TestRoundtrip(0.12345678912345678e-50);
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.cc
new file mode 100644
index 00000000000..dd1a6796cab
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.cc
@@ -0,0 +1,823 @@
+//
+// 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.
+
+#include "absl/flags/parse.h"
+
+#include <stdlib.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <iterator>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/config.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/flag.h"
+#include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
+#include "absl/flags/usage.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/synchronization/mutex.h"
+
+// --------------------------------------------------------------------
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+
+ABSL_CONST_INIT absl::Mutex processing_checks_guard(absl::kConstInit);
+
+ABSL_CONST_INIT bool flagfile_needs_processing
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
+ABSL_CONST_INIT bool fromenv_needs_processing
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
+ABSL_CONST_INIT bool tryfromenv_needs_processing
+ ABSL_GUARDED_BY(processing_checks_guard) = false;
+
+ABSL_CONST_INIT absl::Mutex specified_flags_guard(absl::kConstInit);
+ABSL_CONST_INIT std::vector<const CommandLineFlag*>* specified_flags
+ ABSL_GUARDED_BY(specified_flags_guard) = nullptr;
+
+struct SpecifiedFlagsCompare {
+ bool operator()(const CommandLineFlag* a, const CommandLineFlag* b) const {
+ return a->Name() < b->Name();
+ }
+ bool operator()(const CommandLineFlag* a, absl::string_view b) const {
+ return a->Name() < b;
+ }
+ bool operator()(absl::string_view a, const CommandLineFlag* b) const {
+ return a < b->Name();
+ }
+};
+
+} // namespace
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+ABSL_FLAG(std::vector<std::string>, flagfile, {},
+ "comma-separated list of files to load flags from")
+ .OnUpdate([]() {
+ if (absl::GetFlag(FLAGS_flagfile).empty()) return;
+
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (absl::flags_internal::flagfile_needs_processing) {
+ ABSL_INTERNAL_LOG(WARNING, "flagfile set twice before it is handled");
+ }
+
+ absl::flags_internal::flagfile_needs_processing = true;
+ });
+ABSL_FLAG(std::vector<std::string>, fromenv, {},
+ "comma-separated list of flags to set from the environment"
+ " [use 'export FLAGS_flag1=value']")
+ .OnUpdate([]() {
+ if (absl::GetFlag(FLAGS_fromenv).empty()) return;
+
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (absl::flags_internal::fromenv_needs_processing) {
+ ABSL_INTERNAL_LOG(WARNING, "fromenv set twice before it is handled.");
+ }
+
+ absl::flags_internal::fromenv_needs_processing = true;
+ });
+ABSL_FLAG(std::vector<std::string>, tryfromenv, {},
+ "comma-separated list of flags to try to set from the environment if "
+ "present")
+ .OnUpdate([]() {
+ if (absl::GetFlag(FLAGS_tryfromenv).empty()) return;
+
+ absl::MutexLock l(&absl::flags_internal::processing_checks_guard);
+
+ // Setting this flag twice before it is handled most likely an internal
+ // error and should be reviewed by developers.
+ if (absl::flags_internal::tryfromenv_needs_processing) {
+ ABSL_INTERNAL_LOG(WARNING,
+ "tryfromenv set twice before it is handled.");
+ }
+
+ absl::flags_internal::tryfromenv_needs_processing = true;
+ });
+
+ABSL_FLAG(std::vector<std::string>, undefok, {},
+ "comma-separated list of flag names that it is okay to specify "
+ "on the command line even if the program does not define a flag "
+ "with that name");
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+namespace {
+
+class ArgsList {
+ public:
+ ArgsList() : next_arg_(0) {}
+ ArgsList(int argc, char* argv[]) : args_(argv, argv + argc), next_arg_(0) {}
+ explicit ArgsList(const std::vector<std::string>& args)
+ : args_(args), next_arg_(0) {}
+
+ // Returns success status: true if parsing successful, false otherwise.
+ bool ReadFromFlagfile(const std::string& flag_file_name);
+
+ int Size() const { return args_.size() - next_arg_; }
+ int FrontIndex() const { return next_arg_; }
+ absl::string_view Front() const { return args_[next_arg_]; }
+ void PopFront() { next_arg_++; }
+
+ private:
+ std::vector<std::string> args_;
+ int next_arg_;
+};
+
+bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
+ std::ifstream flag_file(flag_file_name);
+
+ if (!flag_file) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Can't open flagfile ", flag_file_name), true);
+
+ return false;
+ }
+
+ // This argument represents fake argv[0], which should be present in all arg
+ // lists.
+ args_.push_back("");
+
+ std::string line;
+ bool success = true;
+
+ while (std::getline(flag_file, line)) {
+ absl::string_view stripped = absl::StripLeadingAsciiWhitespace(line);
+
+ if (stripped.empty() || stripped[0] == '#') {
+ // Comment or empty line; just ignore.
+ continue;
+ }
+
+ if (stripped[0] == '-') {
+ if (stripped == "--") {
+ flags_internal::ReportUsageError(
+ "Flagfile can't contain position arguments or --", true);
+
+ success = false;
+ break;
+ }
+
+ args_.push_back(std::string(stripped));
+ continue;
+ }
+
+ flags_internal::ReportUsageError(
+ absl::StrCat("Unexpected line in the flagfile ", flag_file_name, ": ",
+ line),
+ true);
+
+ success = false;
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+// Reads the environment variable with name `name` and stores results in
+// `value`. If variable is not present in environment returns false, otherwise
+// returns true.
+bool GetEnvVar(const char* var_name, std::string& var_value) {
+#ifdef _WIN32
+ char buf[1024];
+ auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
+ if (get_res >= sizeof(buf)) {
+ return false;
+ }
+
+ if (get_res == 0) {
+ return false;
+ }
+
+ var_value = std::string(buf, get_res);
+#else
+ const char* val = ::getenv(var_name);
+ if (val == nullptr) {
+ return false;
+ }
+
+ var_value = val;
+#endif
+
+ return true;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// Flag name or empty if arg= --
+// Flag value after = in --flag=value (empty if --foo)
+// "Is empty value" status. True if arg= --foo=, false otherwise. This is
+// required to separate --foo from --foo=.
+// For example:
+// arg return values
+// "--foo=bar" -> {"foo", "bar", false}.
+// "--foo" -> {"foo", "", false}.
+// "--foo=" -> {"foo", "", true}.
+std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
+ absl::string_view arg) {
+ // Allow -foo and --foo
+ absl::ConsumePrefix(&arg, "-");
+
+ if (arg.empty()) {
+ return std::make_tuple("", "", false);
+ }
+
+ auto equal_sign_pos = arg.find("=");
+
+ absl::string_view flag_name = arg.substr(0, equal_sign_pos);
+
+ absl::string_view value;
+ bool is_empty_value = false;
+
+ if (equal_sign_pos != absl::string_view::npos) {
+ value = arg.substr(equal_sign_pos + 1);
+ is_empty_value = value.empty();
+ }
+
+ return std::make_tuple(flag_name, value, is_empty_value);
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// found flag or nullptr
+// is negative in case of --nofoo
+std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
+ CommandLineFlag* flag = absl::FindCommandLineFlag(flag_name);
+ bool is_negative = false;
+
+ if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
+ flag = absl::FindCommandLineFlag(flag_name);
+ is_negative = true;
+ }
+
+ return std::make_tuple(flag, is_negative);
+}
+
+// --------------------------------------------------------------------
+
+// Verify that default values of typed flags must be convertible to string and
+// back.
+void CheckDefaultValuesParsingRoundtrip() {
+#ifndef NDEBUG
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (flag.IsRetired()) return;
+
+#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
+ if (flag.IsOfType<T>()) return;
+
+ ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
+#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
+
+ flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
+ flag);
+ });
+#endif
+}
+
+// --------------------------------------------------------------------
+
+// Returns success status, which is true if we successfully read all flag files,
+// in which case new ArgLists are appended to the input_args in a reverse order
+// of file names in the input flagfiles list. This order ensures that flags from
+// the first flagfile in the input list are processed before the second flagfile
+// etc.
+bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
+ std::vector<ArgsList>& input_args) {
+ bool success = true;
+ for (auto it = flagfiles.rbegin(); it != flagfiles.rend(); ++it) {
+ ArgsList al;
+
+ if (al.ReadFromFlagfile(*it)) {
+ input_args.push_back(al);
+ } else {
+ success = false;
+ }
+ }
+
+ return success;
+}
+
+// Returns success status, which is true if were able to locate all environment
+// variables correctly or if fail_on_absent_in_env is false. The environment
+// variable names are expected to be of the form `FLAGS_<flag_name>`, where
+// `flag_name` is a string from the input flag_names list. If successful we
+// append a single ArgList at the end of the input_args.
+bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
+ std::vector<ArgsList>& input_args,
+ bool fail_on_absent_in_env) {
+ bool success = true;
+ std::vector<std::string> args;
+
+ // This argument represents fake argv[0], which should be present in all arg
+ // lists.
+ args.push_back("");
+
+ for (const auto& flag_name : flag_names) {
+ // Avoid infinite recursion.
+ if (flag_name == "fromenv" || flag_name == "tryfromenv") {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Infinite recursion on flag ", flag_name), true);
+
+ success = false;
+ continue;
+ }
+
+ const std::string envname = absl::StrCat("FLAGS_", flag_name);
+ std::string envval;
+ if (!GetEnvVar(envname.c_str(), envval)) {
+ if (fail_on_absent_in_env) {
+ flags_internal::ReportUsageError(
+ absl::StrCat(envname, " not found in environment"), true);
+
+ success = false;
+ }
+
+ continue;
+ }
+
+ args.push_back(absl::StrCat("--", flag_name, "=", envval));
+ }
+
+ if (success) {
+ input_args.emplace_back(args);
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+// Returns success status, which is true if were able to handle all generator
+// flags (flagfile, fromenv, tryfromemv) successfully.
+bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
+ std::vector<std::string>& flagfile_value) {
+ bool success = true;
+
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
+
+ // flagfile could have been set either on a command line or
+ // programmatically before invoking ParseCommandLine. Note that we do not
+ // actually process arguments specified in the flagfile, but instead
+ // create a secondary arguments list to be processed along with the rest
+ // of the comamnd line arguments. Since we always the process most recently
+ // created list of arguments first, this will result in flagfile argument
+ // being processed before any other argument in the command line. If
+ // FLAGS_flagfile contains more than one file name we create multiple new
+ // levels of arguments in a reverse order of file names. Thus we always
+ // process arguments from first file before arguments containing in a
+ // second file, etc. If flagfile contains another
+ // --flagfile inside of it, it will produce new level of arguments and
+ // processed before the rest of the flagfile. We are also collecting all
+ // flagfiles set on original command line. Unlike the rest of the flags,
+ // this flag can be set multiple times and is expected to be handled
+ // multiple times. We are collecting them all into a single list and set
+ // the value of FLAGS_flagfile to that value at the end of the parsing.
+ if (flags_internal::flagfile_needs_processing) {
+ auto flagfiles = absl::GetFlag(FLAGS_flagfile);
+
+ if (input_args.size() == 1) {
+ flagfile_value.insert(flagfile_value.end(), flagfiles.begin(),
+ flagfiles.end());
+ }
+
+ success &= ReadFlagfiles(flagfiles, input_args);
+
+ flags_internal::flagfile_needs_processing = false;
+ }
+
+ // Similar to flagfile fromenv/tryfromemv can be set both
+ // programmatically and at runtime on a command line. Unlike flagfile these
+ // can't be recursive.
+ if (flags_internal::fromenv_needs_processing) {
+ auto flags_list = absl::GetFlag(FLAGS_fromenv);
+
+ success &= ReadFlagsFromEnv(flags_list, input_args, true);
+
+ flags_internal::fromenv_needs_processing = false;
+ }
+
+ if (flags_internal::tryfromenv_needs_processing) {
+ auto flags_list = absl::GetFlag(FLAGS_tryfromenv);
+
+ success &= ReadFlagsFromEnv(flags_list, input_args, false);
+
+ flags_internal::tryfromenv_needs_processing = false;
+ }
+
+ return success;
+}
+
+// --------------------------------------------------------------------
+
+void ResetGeneratorFlags(const std::vector<std::string>& flagfile_value) {
+ // Setting flagfile to the value which collates all the values set on a
+ // command line and programmatically. So if command line looked like
+ // --flagfile=f1 --flagfile=f2 the final value of the FLAGS_flagfile flag is
+ // going to be {"f1", "f2"}
+ if (!flagfile_value.empty()) {
+ absl::SetFlag(&FLAGS_flagfile, flagfile_value);
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
+ flags_internal::flagfile_needs_processing = false;
+ }
+
+ // fromenv/tryfromenv are set to <undefined> value.
+ if (!absl::GetFlag(FLAGS_fromenv).empty()) {
+ absl::SetFlag(&FLAGS_fromenv, {});
+ }
+ if (!absl::GetFlag(FLAGS_tryfromenv).empty()) {
+ absl::SetFlag(&FLAGS_tryfromenv, {});
+ }
+
+ absl::MutexLock l(&flags_internal::processing_checks_guard);
+ flags_internal::fromenv_needs_processing = false;
+ flags_internal::tryfromenv_needs_processing = false;
+}
+
+// --------------------------------------------------------------------
+
+// Returns:
+// success status
+// deduced value
+// We are also mutating curr_list in case if we need to get a hold of next
+// argument in the input.
+std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
+ absl::string_view value,
+ bool is_negative,
+ bool is_empty_value,
+ ArgsList* curr_list) {
+ // Value is either an argument suffix after `=` in "--foo=<value>"
+ // or separate argument in case of "--foo" "<value>".
+
+ // boolean flags have these forms:
+ // --foo
+ // --nofoo
+ // --foo=true
+ // --foo=false
+ // --nofoo=<value> is not supported
+ // --foo <value> is not supported
+
+ // non boolean flags have these forms:
+ // --foo=<value>
+ // --foo <value>
+ // --nofoo is not supported
+
+ if (flag.IsOfType<bool>()) {
+ if (value.empty()) {
+ if (is_empty_value) {
+ // "--bool_flag=" case
+ flags_internal::ReportUsageError(
+ absl::StrCat(
+ "Missing the value after assignment for the boolean flag '",
+ flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+
+ // "--bool_flag" case
+ value = is_negative ? "0" : "1";
+ } else if (is_negative) {
+ // "--nobool_flag=Y" case
+ flags_internal::ReportUsageError(
+ absl::StrCat("Negative form with assignment is not valid for the "
+ "boolean flag '",
+ flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+ } else if (is_negative) {
+ // "--noint_flag=1" case
+ flags_internal::ReportUsageError(
+ absl::StrCat("Negative form is not valid for the flag '", flag.Name(),
+ "'"),
+ true);
+ return std::make_tuple(false, "");
+ } else if (value.empty() && (!is_empty_value)) {
+ if (curr_list->Size() == 1) {
+ // "--int_flag" case
+ flags_internal::ReportUsageError(
+ absl::StrCat("Missing the value for the flag '", flag.Name(), "'"),
+ true);
+ return std::make_tuple(false, "");
+ }
+
+ // "--int_flag" "10" case
+ curr_list->PopFront();
+ value = curr_list->Front();
+
+ // Heuristic to detect the case where someone treats a string arg
+ // like a bool or just forgets to pass a value:
+ // --my_string_var --foo=bar
+ // We look for a flag of string type, whose value begins with a
+ // dash and corresponds to known flag or standalone --.
+ if (!value.empty() && value[0] == '-' && flag.IsOfType<std::string>()) {
+ auto maybe_flag_name = std::get<0>(SplitNameAndValue(value.substr(1)));
+
+ if (maybe_flag_name.empty() ||
+ std::get<0>(LocateFlag(maybe_flag_name)) != nullptr) {
+ // "--string_flag" "--known_flag" case
+ ABSL_INTERNAL_LOG(
+ WARNING,
+ absl::StrCat("Did you really mean to set flag '", flag.Name(),
+ "' to the value '", value, "'?"));
+ }
+ }
+ }
+
+ return std::make_tuple(true, value);
+}
+
+// --------------------------------------------------------------------
+
+bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
+ auto undefok = absl::GetFlag(FLAGS_undefok);
+ if (std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+ return true;
+ }
+
+ if (absl::ConsumePrefix(&flag_name, "no") &&
+ std::find(undefok.begin(), undefok.end(), flag_name) != undefok.end()) {
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+
+bool WasPresentOnCommandLine(absl::string_view flag_name) {
+ absl::MutexLock l(&specified_flags_guard);
+ ABSL_INTERNAL_CHECK(specified_flags != nullptr,
+ "ParseCommandLine is not invoked yet");
+
+ return std::binary_search(specified_flags->begin(), specified_flags->end(),
+ flag_name, SpecifiedFlagsCompare{});
+}
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
+ ArgvListAction arg_list_act,
+ UsageFlagsAction usage_flag_act,
+ OnUndefinedFlag on_undef_flag) {
+ ABSL_INTERNAL_CHECK(argc > 0, "Missing argv[0]");
+
+ // Once parsing has started we will not have more flag registrations.
+ // If we did, they would be missing during parsing, which is a problem on
+ // itself.
+ flags_internal::FinalizeRegistry();
+
+ // This routine does not return anything since we abort on failure.
+ CheckDefaultValuesParsingRoundtrip();
+
+ std::vector<std::string> flagfile_value;
+
+ std::vector<ArgsList> input_args;
+ input_args.push_back(ArgsList(argc, argv));
+
+ std::vector<char*> output_args;
+ std::vector<char*> positional_args;
+ output_args.reserve(argc);
+
+ // This is the list of undefined flags. The element of the list is the pair
+ // consisting of boolean indicating if flag came from command line (vs from
+ // some flag file we've read) and flag name.
+ // TODO(rogeeff): Eliminate the first element in the pair after cleanup.
+ std::vector<std::pair<bool, std::string>> undefined_flag_names;
+
+ // Set program invocation name if it is not set before.
+ if (ProgramInvocationName() == "UNKNOWN") {
+ flags_internal::SetProgramInvocationName(argv[0]);
+ }
+ output_args.push_back(argv[0]);
+
+ absl::MutexLock l(&specified_flags_guard);
+ if (specified_flags == nullptr) {
+ specified_flags = new std::vector<const CommandLineFlag*>;
+ } else {
+ specified_flags->clear();
+ }
+
+ // Iterate through the list of the input arguments. First level are arguments
+ // originated from argc/argv. Following levels are arguments originated from
+ // recursive parsing of flagfile(s).
+ bool success = true;
+ while (!input_args.empty()) {
+ // 10. First we process the built-in generator flags.
+ success &= HandleGeneratorFlags(input_args, flagfile_value);
+
+ // 30. Select top-most (most recent) arguments list. If it is empty drop it
+ // and re-try.
+ ArgsList& curr_list = input_args.back();
+
+ curr_list.PopFront();
+
+ if (curr_list.Size() == 0) {
+ input_args.pop_back();
+ continue;
+ }
+
+ // 40. Pick up the front remaining argument in the current list. If current
+ // stack of argument lists contains only one element - we are processing an
+ // argument from the original argv.
+ absl::string_view arg(curr_list.Front());
+ bool arg_from_argv = input_args.size() == 1;
+
+ // 50. If argument does not start with - or is just "-" - this is
+ // positional argument.
+ if (!absl::ConsumePrefix(&arg, "-") || arg.empty()) {
+ ABSL_INTERNAL_CHECK(arg_from_argv,
+ "Flagfile cannot contain positional argument");
+
+ positional_args.push_back(argv[curr_list.FrontIndex()]);
+ continue;
+ }
+
+ if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs)) {
+ output_args.push_back(argv[curr_list.FrontIndex()]);
+ }
+
+ // 60. Split the current argument on '=' to figure out the argument
+ // name and value. If flag name is empty it means we've got "--". value
+ // can be empty either if there were no '=' in argument string at all or
+ // an argument looked like "--foo=". In a latter case is_empty_value is
+ // true.
+ absl::string_view flag_name;
+ absl::string_view value;
+ bool is_empty_value = false;
+
+ std::tie(flag_name, value, is_empty_value) = SplitNameAndValue(arg);
+
+ // 70. "--" alone means what it does for GNU: stop flags parsing. We do
+ // not support positional arguments in flagfiles, so we just drop them.
+ if (flag_name.empty()) {
+ ABSL_INTERNAL_CHECK(arg_from_argv,
+ "Flagfile cannot contain positional argument");
+
+ curr_list.PopFront();
+ break;
+ }
+
+ // 80. Locate the flag based on flag name. Handle both --foo and --nofoo
+ CommandLineFlag* flag = nullptr;
+ bool is_negative = false;
+ std::tie(flag, is_negative) = LocateFlag(flag_name);
+
+ if (flag == nullptr) {
+ // Usage flags are not modeled as Abseil flags. Locate them separately.
+ if (flags_internal::DeduceUsageFlags(flag_name, value)) {
+ continue;
+ }
+
+ if (on_undef_flag != OnUndefinedFlag::kIgnoreUndefined) {
+ undefined_flag_names.emplace_back(arg_from_argv,
+ std::string(flag_name));
+ }
+ continue;
+ }
+
+ // 90. Deduce flag's value (from this or next argument)
+ auto curr_index = curr_list.FrontIndex();
+ bool value_success = true;
+ std::tie(value_success, value) =
+ DeduceFlagValue(*flag, value, is_negative, is_empty_value, &curr_list);
+ success &= value_success;
+
+ // If above call consumed an argument, it was a standalone value
+ if (arg_from_argv && (arg_list_act == ArgvListAction::kKeepParsedArgs) &&
+ (curr_index != curr_list.FrontIndex())) {
+ output_args.push_back(argv[curr_list.FrontIndex()]);
+ }
+
+ // 100. Set the located flag to a new new value, unless it is retired.
+ // Setting retired flag fails, but we ignoring it here while also reporting
+ // access to retired flag.
+ std::string error;
+ if (!flags_internal::PrivateHandleAccessor::ParseFrom(
+ *flag, value, SET_FLAGS_VALUE, kCommandLine, error)) {
+ if (flag->IsRetired()) continue;
+
+ flags_internal::ReportUsageError(error, true);
+ success = false;
+ } else {
+ specified_flags->push_back(flag);
+ }
+ }
+
+ for (const auto& flag_name : undefined_flag_names) {
+ if (CanIgnoreUndefinedFlag(flag_name.second)) continue;
+
+ flags_internal::ReportUsageError(
+ absl::StrCat("Unknown command line flag '", flag_name.second, "'"),
+ true);
+
+ success = false;
+ }
+
+#if ABSL_FLAGS_STRIP_NAMES
+ if (!success) {
+ flags_internal::ReportUsageError(
+ "NOTE: command line flags are disabled in this build", true);
+ }
+#endif
+
+ if (!success) {
+ flags_internal::HandleUsageFlags(std::cout,
+ ProgramUsageMessage());
+ std::exit(1);
+ }
+
+ if (usage_flag_act == UsageFlagsAction::kHandleUsage) {
+ int exit_code = flags_internal::HandleUsageFlags(
+ std::cout, ProgramUsageMessage());
+
+ if (exit_code != -1) {
+ std::exit(exit_code);
+ }
+ }
+
+ ResetGeneratorFlags(flagfile_value);
+
+ // Reinstate positional args which were intermixed with flags in the arguments
+ // list.
+ for (auto arg : positional_args) {
+ output_args.push_back(arg);
+ }
+
+ // All the remaining arguments are positional.
+ if (!input_args.empty()) {
+ for (int arg_index = input_args.back().FrontIndex(); arg_index < argc;
+ ++arg_index) {
+ output_args.push_back(argv[arg_index]);
+ }
+ }
+
+ // Trim and sort the vector.
+ specified_flags->shrink_to_fit();
+ std::sort(specified_flags->begin(), specified_flags->end(),
+ SpecifiedFlagsCompare{});
+ return output_args;
+}
+
+} // namespace flags_internal
+
+// --------------------------------------------------------------------
+
+std::vector<char*> ParseCommandLine(int argc, char* argv[]) {
+ return flags_internal::ParseCommandLineImpl(
+ argc, argv, flags_internal::ArgvListAction::kRemoveParsedArgs,
+ flags_internal::UsageFlagsAction::kHandleUsage,
+ flags_internal::OnUndefinedFlag::kAbortIfUndefined);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.h
new file mode 100644
index 00000000000..929de2cb40d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: parse.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main parsing function for Abseil flags:
+// `absl::ParseCommandLine()`.
+
+#ifndef ABSL_FLAGS_PARSE_H_
+#define ABSL_FLAGS_PARSE_H_
+
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/flags/internal/parse.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// ParseCommandLine()
+//
+// Parses the set of command-line arguments passed in the `argc` (argument
+// count) and `argv[]` (argument vector) parameters from `main()`, assigning
+// values to any defined Abseil flags. (Any arguments passed after the
+// flag-terminating delimiter (`--`) are treated as positional arguments and
+// ignored.)
+//
+// Any command-line flags (and arguments to those flags) are parsed into Abseil
+// Flag values, if those flags are defined. Any undefined flags will either
+// return an error, or be ignored if that flag is designated using `undefok` to
+// indicate "undefined is OK."
+//
+// Any command-line positional arguments not part of any command-line flag (or
+// arguments to a flag) are returned in a vector, with the program invocation
+// name at position 0 of that vector. (Note that this includes positional
+// arguments after the flag-terminating delimiter `--`.)
+//
+// After all flags and flag arguments are parsed, this function looks for any
+// built-in usage flags (e.g. `--help`), and if any were specified, it reports
+// help messages and then exits the program.
+std::vector<char*> ParseCommandLine(int argc, char* argv[]);
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_PARSE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse_test.cc
new file mode 100644
index 00000000000..41bc0bc6b3a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/parse_test.cc
@@ -0,0 +1,929 @@
+//
+// 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.
+
+#include "absl/flags/parse.h"
+
+#include <stdlib.h>
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/scoped_set_env.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/parse.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/flags/reflection.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "absl/types/span.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+namespace {
+
+using absl::base_internal::ScopedSetEnv;
+
+struct UDT {
+ UDT() = default;
+ UDT(const UDT&) = default;
+ UDT(int v) : value(v) {} // NOLINT
+
+ int value;
+};
+
+bool AbslParseFlag(absl::string_view in, UDT* udt, std::string* err) {
+ if (in == "A") {
+ udt->value = 1;
+ return true;
+ }
+ if (in == "AAA") {
+ udt->value = 10;
+ return true;
+ }
+
+ *err = "Use values A, AAA instead";
+ return false;
+}
+std::string AbslUnparseFlag(const UDT& udt) {
+ return udt.value == 1 ? "A" : "AAA";
+}
+
+std::string GetTestTmpDirEnvVar(const char* const env_var_name) {
+#ifdef _WIN32
+ char buf[MAX_PATH];
+ auto get_res = GetEnvironmentVariableA(env_var_name, buf, sizeof(buf));
+ if (get_res >= sizeof(buf) || get_res == 0) {
+ return "";
+ }
+
+ return std::string(buf, get_res);
+#else
+ const char* val = ::getenv(env_var_name);
+ if (val == nullptr) {
+ return "";
+ }
+
+ return val;
+#endif
+}
+
+const std::string& GetTestTempDir() {
+ static std::string* temp_dir_name = []() -> std::string* {
+ std::string* res = new std::string(GetTestTmpDirEnvVar("TEST_TMPDIR"));
+
+ if (res->empty()) {
+ *res = GetTestTmpDirEnvVar("TMPDIR");
+ }
+
+ if (res->empty()) {
+#ifdef _WIN32
+ char temp_path_buffer[MAX_PATH];
+
+ auto len = GetTempPathA(MAX_PATH, temp_path_buffer);
+ if (len < MAX_PATH && len != 0) {
+ std::string temp_dir_name = temp_path_buffer;
+ if (!absl::EndsWith(temp_dir_name, "\\")) {
+ temp_dir_name.push_back('\\');
+ }
+ absl::StrAppend(&temp_dir_name, "parse_test.", GetCurrentProcessId());
+ if (CreateDirectoryA(temp_dir_name.c_str(), nullptr)) {
+ *res = temp_dir_name;
+ }
+ }
+#else
+ char temp_dir_template[] = "/tmp/parse_test.XXXXXX";
+ if (auto* unique_name = ::mkdtemp(temp_dir_template)) {
+ *res = unique_name;
+ }
+#endif
+ }
+
+ if (res->empty()) {
+ ABSL_INTERNAL_LOG(FATAL,
+ "Failed to make temporary directory for data files");
+ }
+
+#ifdef _WIN32
+ *res += "\\";
+#else
+ *res += "/";
+#endif
+
+ return res;
+ }();
+
+ return *temp_dir_name;
+}
+
+struct FlagfileData {
+ const absl::string_view file_name;
+ const absl::Span<const char* const> file_lines;
+};
+
+// clang-format off
+constexpr const char* const ff1_data[] = {
+ "# comment ",
+ " # comment ",
+ "",
+ " ",
+ "--int_flag=-1",
+ " --string_flag=q2w2 ",
+ " ## ",
+ " --double_flag=0.1",
+ "--bool_flag=Y "
+};
+
+constexpr const char* const ff2_data[] = {
+ "# Setting legacy flag",
+ "--legacy_int=1111",
+ "--legacy_bool",
+ "--nobool_flag",
+ "--legacy_str=aqsw",
+ "--int_flag=100",
+ " ## ============="
+};
+// clang-format on
+
+// Builds flagfile flag in the flagfile_flag buffer and returns it. This
+// function also creates a temporary flagfile based on FlagfileData input.
+// We create a flagfile in a temporary directory with the name specified in
+// FlagfileData and populate it with lines specifed in FlagfileData. If $0 is
+// referenced in any of the lines in FlagfileData they are replaced with
+// temporary directory location. This way we can test inclusion of one flagfile
+// from another flagfile.
+const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
+ std::string& flagfile_flag) {
+ flagfile_flag = "--flagfile=";
+ absl::string_view separator;
+ for (const auto& flagfile_data : ffd) {
+ std::string flagfile_name =
+ absl::StrCat(GetTestTempDir(), flagfile_data.file_name);
+
+ std::ofstream flagfile_out(flagfile_name);
+ for (auto line : flagfile_data.file_lines) {
+ flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
+ }
+
+ absl::StrAppend(&flagfile_flag, separator, flagfile_name);
+ separator = ",";
+ }
+
+ return flagfile_flag.c_str();
+}
+
+} // namespace
+
+ABSL_FLAG(int, int_flag, 1, "");
+ABSL_FLAG(double, double_flag, 1.1, "");
+ABSL_FLAG(std::string, string_flag, "a", "");
+ABSL_FLAG(bool, bool_flag, false, "");
+ABSL_FLAG(UDT, udt_flag, -1, "");
+ABSL_RETIRED_FLAG(int, legacy_int, 1, "");
+ABSL_RETIRED_FLAG(bool, legacy_bool, false, "");
+ABSL_RETIRED_FLAG(std::string, legacy_str, "l", "");
+
+namespace {
+
+namespace flags = absl::flags_internal;
+using testing::ElementsAreArray;
+
+class ParseTest : public testing::Test {
+ public:
+ ~ParseTest() override { flags::SetFlagsHelpMode(flags::HelpMode::kNone); }
+
+ private:
+ absl::FlagSaver flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+template <int N>
+std::vector<char*> InvokeParse(const char* (&in_argv)[N]) {
+ return absl::ParseCommandLine(N, const_cast<char**>(in_argv));
+}
+
+// --------------------------------------------------------------------
+
+template <int N>
+void TestParse(const char* (&in_argv)[N], int int_flag_value,
+ double double_flag_val, absl::string_view string_flag_val,
+ bool bool_flag_val, int exp_position_args = 0) {
+ auto out_args = InvokeParse(in_argv);
+
+ EXPECT_EQ(out_args.size(), 1 + exp_position_args);
+ EXPECT_STREQ(out_args[0], "testbin");
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), int_flag_value);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_double_flag), double_flag_val, 0.0001);
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), string_flag_val);
+ EXPECT_EQ(absl::GetFlag(FLAGS_bool_flag), bool_flag_val);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestEmptyArgv) {
+ const char* in_argv[] = {"testbin"};
+
+ auto out_args = InvokeParse(in_argv);
+
+ EXPECT_EQ(out_args.size(), 1);
+ EXPECT_STREQ(out_args[0], "testbin");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidIntArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--int_flag=10",
+ };
+ TestParse(in_args1, 10, 1.1, "a", false);
+
+ const char* in_args2[] = {
+ "testbin",
+ "-int_flag=020",
+ };
+ TestParse(in_args2, 20, 1.1, "a", false);
+
+ const char* in_args3[] = {
+ "testbin",
+ "--int_flag",
+ "-30",
+ };
+ TestParse(in_args3, -30, 1.1, "a", false);
+
+ const char* in_args4[] = {
+ "testbin",
+ "-int_flag",
+ "0x21",
+ };
+ TestParse(in_args4, 33, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidDoubleArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--double_flag=2.3",
+ };
+ TestParse(in_args1, 1, 2.3, "a", false);
+
+ const char* in_args2[] = {
+ "testbin",
+ "--double_flag=0x1.2",
+ };
+ TestParse(in_args2, 1, 1.125, "a", false);
+
+ const char* in_args3[] = {
+ "testbin",
+ "--double_flag",
+ "99.7",
+ };
+ TestParse(in_args3, 1, 99.7, "a", false);
+
+ const char* in_args4[] = {
+ "testbin",
+ "--double_flag",
+ "0x20.1",
+ };
+ TestParse(in_args4, 1, 32.0625, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidStringArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--string_flag=aqswde",
+ };
+ TestParse(in_args1, 1, 1.1, "aqswde", false);
+
+ const char* in_args2[] = {
+ "testbin",
+ "-string_flag=a=b=c",
+ };
+ TestParse(in_args2, 1, 1.1, "a=b=c", false);
+
+ const char* in_args3[] = {
+ "testbin",
+ "--string_flag",
+ "zaxscd",
+ };
+ TestParse(in_args3, 1, 1.1, "zaxscd", false);
+
+ const char* in_args4[] = {
+ "testbin",
+ "-string_flag",
+ "--int_flag",
+ };
+ TestParse(in_args4, 1, 1.1, "--int_flag", false);
+
+ const char* in_args5[] = {
+ "testbin",
+ "--string_flag",
+ "--no_a_flag=11",
+ };
+ TestParse(in_args5, 1, 1.1, "--no_a_flag=11", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidBoolArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--bool_flag",
+ };
+ TestParse(in_args1, 1, 1.1, "a", true);
+
+ const char* in_args2[] = {
+ "testbin",
+ "--nobool_flag",
+ };
+ TestParse(in_args2, 1, 1.1, "a", false);
+
+ const char* in_args3[] = {
+ "testbin",
+ "--bool_flag=true",
+ };
+ TestParse(in_args3, 1, 1.1, "a", true);
+
+ const char* in_args4[] = {
+ "testbin",
+ "-bool_flag=false",
+ };
+ TestParse(in_args4, 1, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidUDTArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--udt_flag=A",
+ };
+ InvokeParse(in_args1);
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 1);
+
+ const char* in_args2[] = {"testbin", "--udt_flag", "AAA"};
+ InvokeParse(in_args2);
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_udt_flag).value, 10);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidMultipleArg) {
+ const char* in_args1[] = {
+ "testbin", "--bool_flag", "--int_flag=2",
+ "--double_flag=0.1", "--string_flag=asd",
+ };
+ TestParse(in_args1, 2, 0.1, "asd", true);
+
+ const char* in_args2[] = {
+ "testbin", "--string_flag=", "--nobool_flag", "--int_flag",
+ "-011", "--double_flag", "-1e-2",
+ };
+ TestParse(in_args2, -11, -0.01, "", false);
+
+ const char* in_args3[] = {
+ "testbin", "--int_flag", "-0", "--string_flag", "\"\"",
+ "--bool_flag=true", "--double_flag=1e18",
+ };
+ TestParse(in_args3, 0, 1e18, "\"\"", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestPositionalArgs) {
+ const char* in_args1[] = {
+ "testbin",
+ "p1",
+ "p2",
+ };
+ TestParse(in_args1, 1, 1.1, "a", false, 2);
+
+ auto out_args1 = InvokeParse(in_args1);
+
+ EXPECT_STREQ(out_args1[1], "p1");
+ EXPECT_STREQ(out_args1[2], "p2");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--int_flag=2",
+ "p1",
+ };
+ TestParse(in_args2, 2, 1.1, "a", false, 1);
+
+ auto out_args2 = InvokeParse(in_args2);
+
+ EXPECT_STREQ(out_args2[1], "p1");
+
+ const char* in_args3[] = {"testbin", "p1", "--int_flag=3",
+ "p2", "--bool_flag", "true"};
+ TestParse(in_args3, 3, 1.1, "a", true, 3);
+
+ auto out_args3 = InvokeParse(in_args3);
+
+ EXPECT_STREQ(out_args3[1], "p1");
+ EXPECT_STREQ(out_args3[2], "p2");
+ EXPECT_STREQ(out_args3[3], "true");
+
+ const char* in_args4[] = {
+ "testbin",
+ "--",
+ "p1",
+ "p2",
+ };
+ TestParse(in_args4, 3, 1.1, "a", true, 2);
+
+ auto out_args4 = InvokeParse(in_args4);
+
+ EXPECT_STREQ(out_args4[1], "p1");
+ EXPECT_STREQ(out_args4[2], "p2");
+
+ const char* in_args5[] = {
+ "testbin", "p1", "--int_flag=4", "--", "--bool_flag", "false", "p2",
+ };
+ TestParse(in_args5, 4, 1.1, "a", true, 4);
+
+ auto out_args5 = InvokeParse(in_args5);
+
+ EXPECT_STREQ(out_args5[1], "p1");
+ EXPECT_STREQ(out_args5[2], "--bool_flag");
+ EXPECT_STREQ(out_args5[3], "false");
+ EXPECT_STREQ(out_args5[4], "p2");
+}
+
+// --------------------------------------------------------------------
+
+using ParseDeathTest = ParseTest;
+
+TEST_F(ParseDeathTest, TestUndefinedArg) {
+ const char* in_args1[] = {
+ "testbin",
+ "--undefined_flag",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "Unknown command line flag 'undefined_flag'");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--noprefixed_flag",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ "Unknown command line flag 'noprefixed_flag'");
+
+ const char* in_args3[] = {
+ "testbin",
+ "--Int_flag=1",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
+ "Unknown command line flag 'Int_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
+ const char* in_args1[] = {
+ "testbin",
+ "--bool_flag=",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(
+ InvokeParse(in_args1),
+ "Missing the value after assignment for the boolean flag 'bool_flag'");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--nobool_flag=true",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ "Negative form with assignment is not valid for the boolean "
+ "flag 'bool_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
+ const char* in_args1[] = {
+ "testbin",
+ "--nostring_flag",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "Negative form is not valid for the flag 'string_flag'");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--int_flag",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ "Missing the value for the flag 'int_flag'");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
+ const char* in_args1[] = {
+ "testbin",
+ "--udt_flag=1",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "Illegal value '1' specified for flag 'udt_flag'; Use values A, "
+ "AAA instead");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--udt_flag",
+ "AA",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ "Illegal value 'AA' specified for flag 'udt_flag'; Use values "
+ "A, AAA instead");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestLegacyFlags) {
+ const char* in_args1[] = {
+ "testbin",
+ "--legacy_int=11",
+ };
+ TestParse(in_args1, 1, 1.1, "a", false);
+
+ const char* in_args2[] = {
+ "testbin",
+ "--legacy_bool",
+ };
+ TestParse(in_args2, 1, 1.1, "a", false);
+
+ const char* in_args3[] = {
+ "testbin", "--legacy_int", "22", "--int_flag=2",
+ "--legacy_bool", "true", "--legacy_str", "--string_flag=qwe",
+ };
+ TestParse(in_args3, 2, 1.1, "a", false, 1);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestSimpleValidFlagfile) {
+ std::string flagfile_flag;
+
+ const char* in_args1[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+ flagfile_flag),
+ };
+ TestParse(in_args1, -1, 0.1, "q2w2 ", true);
+
+ const char* in_args2[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)}},
+ flagfile_flag),
+ };
+ TestParse(in_args2, 100, 0.1, "q2w2 ", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestValidMultiFlagfile) {
+ std::string flagfile_flag;
+
+ const char* in_args1[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
+ {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+ flagfile_flag),
+ };
+ TestParse(in_args1, -1, 0.1, "q2w2 ", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
+ std::string flagfile_flag;
+
+ const char* in_args1[] = {
+ "testbin", "--int_flag=3",
+ GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+ flagfile_flag),
+ "-double_flag=0.2"};
+ TestParse(in_args1, -1, 0.2, "q2w2 ", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestFlagfileInFlagfile) {
+ std::string flagfile_flag;
+
+ constexpr const char* const ff3_data[] = {
+ "--flagfile=$0/parse_test.ff1",
+ "--flagfile=$0/parse_test.ff2",
+ };
+
+ GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
+ {"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
+ flagfile_flag);
+
+ const char* in_args1[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff3", absl::MakeConstSpan(ff3_data)}},
+ flagfile_flag),
+ };
+ TestParse(in_args1, 100, 0.1, "q2w2 ", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
+ std::string flagfile_flag;
+
+ constexpr const char* const ff4_data[] = {
+ "--unknown_flag=10"
+ };
+
+ const char* in_args1[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff4",
+ absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "Unknown command line flag 'unknown_flag'");
+
+ constexpr const char* const ff5_data[] = {
+ "--int_flag 10",
+ };
+
+ const char* in_args2[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff5",
+ absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ "Unknown command line flag 'int_flag 10'");
+
+ constexpr const char* const ff6_data[] = {
+ "--int_flag=10", "--", "arg1", "arg2", "arg3",
+ };
+
+ const char* in_args3[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
+ flagfile_flag),
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
+ "Flagfile can't contain position arguments or --");
+
+ const char* in_args4[] = {
+ "testbin",
+ "--flagfile=invalid_flag_file",
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args4),
+ "Can't open flagfile invalid_flag_file");
+
+ constexpr const char* const ff7_data[] = {
+ "--int_flag=10",
+ "*bin*",
+ "--str_flag=aqsw",
+ };
+
+ const char* in_args5[] = {
+ "testbin",
+ GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
+ flagfile_flag),
+ };
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
+ "Unexpected line in the flagfile .*: \\*bin\\*");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
+ const char* in_args1[] = {"testbin",
+ "--fromenv=int_flag,bool_flag,string_flag"};
+
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "33");
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "True");
+ ScopedSetEnv set_string_flag("FLAGS_string_flag", "AQ12");
+
+ TestParse(in_args1, 33, 1.1, "AQ12", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
+ const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
+
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "FLAGS_int_flag not found in environment");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
+ const char* in_args1[] = {"testbin", "--fromenv=tryfromenv"};
+
+ ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
+
+ EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ "Infinite recursion on flag tryfromenv");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingOptionalFlagsFromEnv) {
+ const char* in_args1[] = {
+ "testbin", "--tryfromenv=int_flag,bool_flag,string_flag,other_flag"};
+
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "17");
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "Y");
+
+ TestParse(in_args1, 17, 1.1, "a", true);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestReadingFlagsFromEnvMoxedWithRegularFlags) {
+ const char* in_args1[] = {
+ "testbin",
+ "--bool_flag=T",
+ "--tryfromenv=int_flag,bool_flag",
+ "--int_flag=-21",
+ };
+
+ ScopedSetEnv set_int_flag("FLAGS_int_flag", "-15");
+ ScopedSetEnv set_bool_flag("FLAGS_bool_flag", "F");
+
+ TestParse(in_args1, -21, 1.1, "a", false);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestKeepParsedArgs) {
+ const char* in_args1[] = {
+ "testbin", "arg1", "--bool_flag",
+ "--int_flag=211", "arg2", "--double_flag=1.1",
+ "--string_flag", "asd", "--",
+ "arg3", "arg4",
+ };
+
+ auto out_args1 = InvokeParse(in_args1);
+
+ EXPECT_THAT(
+ out_args1,
+ ElementsAreArray({absl::string_view("testbin"), absl::string_view("arg1"),
+ absl::string_view("arg2"), absl::string_view("arg3"),
+ absl::string_view("arg4")}));
+
+ auto out_args2 = flags::ParseCommandLineImpl(
+ 11, const_cast<char**>(in_args1), flags::ArgvListAction::kKeepParsedArgs,
+ flags::UsageFlagsAction::kHandleUsage,
+ flags::OnUndefinedFlag::kAbortIfUndefined);
+
+ EXPECT_THAT(
+ out_args2,
+ ElementsAreArray({absl::string_view("testbin"),
+ absl::string_view("--bool_flag"),
+ absl::string_view("--int_flag=211"),
+ absl::string_view("--double_flag=1.1"),
+ absl::string_view("--string_flag"),
+ absl::string_view("asd"), absl::string_view("--"),
+ absl::string_view("arg1"), absl::string_view("arg2"),
+ absl::string_view("arg3"), absl::string_view("arg4")}));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
+ const char* in_args1[] = {
+ "testbin",
+ "arg1",
+ "--undef_flag=aa",
+ "--int_flag=21",
+ };
+
+ auto out_args1 = flags::ParseCommandLineImpl(
+ 4, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
+ flags::UsageFlagsAction::kHandleUsage,
+ flags::OnUndefinedFlag::kIgnoreUndefined);
+
+ EXPECT_THAT(out_args1, ElementsAreArray({absl::string_view("testbin"),
+ absl::string_view("arg1")}));
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 21);
+
+ const char* in_args2[] = {
+ "testbin",
+ "arg1",
+ "--undef_flag=aa",
+ "--string_flag=AA",
+ };
+
+ auto out_args2 = flags::ParseCommandLineImpl(
+ 4, const_cast<char**>(in_args2), flags::ArgvListAction::kKeepParsedArgs,
+ flags::UsageFlagsAction::kHandleUsage,
+ flags::OnUndefinedFlag::kIgnoreUndefined);
+
+ EXPECT_THAT(
+ out_args2,
+ ElementsAreArray(
+ {absl::string_view("testbin"), absl::string_view("--undef_flag=aa"),
+ absl::string_view("--string_flag=AA"), absl::string_view("arg1")}));
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "AA");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
+ const char* in_args1[] = {
+ "testbin",
+ "--help",
+ };
+
+ EXPECT_EXIT(InvokeParse(in_args1), testing::ExitedWithCode(1), "");
+
+ const char* in_args2[] = {
+ "testbin",
+ "--help",
+ "--int_flag=3",
+ };
+
+ auto out_args2 = flags::ParseCommandLineImpl(
+ 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
+ flags::UsageFlagsAction::kIgnoreUsage,
+ flags::OnUndefinedFlag::kAbortIfUndefined);
+
+ EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 3);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseDeathTest, TestSubstringHelpFlagHandling) {
+ const char* in_args1[] = {
+ "testbin",
+ "--help=abcd",
+ };
+
+ auto out_args1 = flags::ParseCommandLineImpl(
+ 2, const_cast<char**>(in_args1), flags::ArgvListAction::kRemoveParsedArgs,
+ flags::UsageFlagsAction::kIgnoreUsage,
+ flags::OnUndefinedFlag::kAbortIfUndefined);
+
+ EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kMatch);
+ EXPECT_EQ(flags::GetFlagsHelpMatchSubstr(), "abcd");
+
+ const char* in_args2[] = {"testbin", "--help", "some_positional_arg"};
+
+ auto out_args2 = flags::ParseCommandLineImpl(
+ 3, const_cast<char**>(in_args2), flags::ArgvListAction::kRemoveParsedArgs,
+ flags::UsageFlagsAction::kIgnoreUsage,
+ flags::OnUndefinedFlag::kAbortIfUndefined);
+
+ EXPECT_EQ(flags::GetFlagsHelpMode(), flags::HelpMode::kImportant);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ParseTest, WasPresentOnCommandLine) {
+ const char* in_args1[] = {
+ "testbin", "arg1", "--bool_flag",
+ "--int_flag=211", "arg2", "--double_flag=1.1",
+ "--string_flag", "asd", "--",
+ "--some_flag", "arg4",
+ };
+
+ InvokeParse(in_args1);
+
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("bool_flag"));
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("int_flag"));
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("double_flag"));
+ EXPECT_TRUE(flags::WasPresentOnCommandLine("string_flag"));
+ EXPECT_FALSE(flags::WasPresentOnCommandLine("some_flag"));
+ EXPECT_FALSE(flags::WasPresentOnCommandLine("another_flag"));
+}
+
+// --------------------------------------------------------------------
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.cc
new file mode 100644
index 00000000000..0c761101633
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.cc
@@ -0,0 +1,350 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/flags/reflection.h"
+
+#include <assert.h>
+
+#include <atomic>
+#include <map>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/private_handle_accessor.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// --------------------------------------------------------------------
+// FlagRegistry
+// A FlagRegistry singleton object holds all flag objects indexed by their
+// names so that if you know a flag's name, you can access or set it. If the
+// function is named FooLocked(), you must own the registry lock before
+// calling the function; otherwise, you should *not* hold the lock, and the
+// function will acquire it itself if needed.
+// --------------------------------------------------------------------
+
+class FlagRegistry {
+ public:
+ FlagRegistry() = default;
+ ~FlagRegistry() = default;
+
+ // Store a flag in this registry. Takes ownership of *flag.
+ void RegisterFlag(CommandLineFlag& flag, const char* filename);
+
+ void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION(lock_) { lock_.Lock(); }
+ void Unlock() ABSL_UNLOCK_FUNCTION(lock_) { lock_.Unlock(); }
+
+ // Returns the flag object for the specified name, or nullptr if not found.
+ // Will emit a warning if a 'retired' flag is specified.
+ CommandLineFlag* FindFlag(absl::string_view name);
+
+ static FlagRegistry& GlobalRegistry(); // returns a singleton registry
+
+ private:
+ friend class flags_internal::FlagSaverImpl; // reads all the flags in order
+ // to copy them
+ friend void ForEachFlag(std::function<void(CommandLineFlag&)> visitor);
+ friend void FinalizeRegistry();
+
+ // The map from name to flag, for FindFlag().
+ using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
+ using FlagIterator = FlagMap::iterator;
+ using FlagConstIterator = FlagMap::const_iterator;
+ FlagMap flags_;
+ std::vector<CommandLineFlag*> flat_flags_;
+ std::atomic<bool> finalized_flags_{false};
+
+ absl::Mutex lock_;
+
+ // Disallow
+ FlagRegistry(const FlagRegistry&);
+ FlagRegistry& operator=(const FlagRegistry&);
+};
+
+namespace {
+
+class FlagRegistryLock {
+ public:
+ explicit FlagRegistryLock(FlagRegistry& fr) : fr_(fr) { fr_.Lock(); }
+ ~FlagRegistryLock() { fr_.Unlock(); }
+
+ private:
+ FlagRegistry& fr_;
+};
+
+} // namespace
+
+CommandLineFlag* FlagRegistry::FindFlag(absl::string_view name) {
+ if (finalized_flags_.load(std::memory_order_acquire)) {
+ // We could save some gcus here if we make `Name()` be non-virtual.
+ // We could move the `const char*` name to the base class.
+ auto it = std::partition_point(
+ flat_flags_.begin(), flat_flags_.end(),
+ [=](CommandLineFlag* f) { return f->Name() < name; });
+ if (it != flat_flags_.end() && (*it)->Name() == name) return *it;
+ }
+
+ FlagRegistryLock frl(*this);
+ auto it = flags_.find(name);
+ return it != flags_.end() ? it->second : nullptr;
+}
+
+void FlagRegistry::RegisterFlag(CommandLineFlag& flag, const char* filename) {
+ if (filename != nullptr &&
+ flag.Filename() != GetUsageConfig().normalize_filename(filename)) {
+ flags_internal::ReportUsageError(
+ absl::StrCat(
+ "Inconsistency between flag object and registration for flag '",
+ flag.Name(),
+ "', likely due to duplicate flags or an ODR violation. Relevant "
+ "files: ",
+ flag.Filename(), " and ", filename),
+ true);
+ std::exit(1);
+ }
+
+ FlagRegistryLock registry_lock(*this);
+
+ std::pair<FlagIterator, bool> ins =
+ flags_.insert(FlagMap::value_type(flag.Name(), &flag));
+ if (ins.second == false) { // means the name was already in the map
+ CommandLineFlag& old_flag = *ins.first->second;
+ if (flag.IsRetired() != old_flag.IsRetired()) {
+ // All registrations must agree on the 'retired' flag.
+ flags_internal::ReportUsageError(
+ absl::StrCat(
+ "Retired flag '", flag.Name(), "' was defined normally in file '",
+ (flag.IsRetired() ? old_flag.Filename() : flag.Filename()), "'."),
+ true);
+ } else if (flags_internal::PrivateHandleAccessor::TypeId(flag) !=
+ flags_internal::PrivateHandleAccessor::TypeId(old_flag)) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Flag '", flag.Name(),
+ "' was defined more than once but with "
+ "differing types. Defined in files '",
+ old_flag.Filename(), "' and '", flag.Filename(), "'."),
+ true);
+ } else if (old_flag.IsRetired()) {
+ return;
+ } else if (old_flag.Filename() != flag.Filename()) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Flag '", flag.Name(),
+ "' was defined more than once (in files '",
+ old_flag.Filename(), "' and '", flag.Filename(), "')."),
+ true);
+ } else {
+ flags_internal::ReportUsageError(
+ absl::StrCat(
+ "Something is wrong with flag '", flag.Name(), "' in file '",
+ flag.Filename(), "'. One possibility: file '", flag.Filename(),
+ "' is being linked both statically and dynamically into this "
+ "executable. e.g. some files listed as srcs to a test and also "
+ "listed as srcs of some shared lib deps of the same test."),
+ true);
+ }
+ // All cases above are fatal, except for the retired flags.
+ std::exit(1);
+ }
+}
+
+FlagRegistry& FlagRegistry::GlobalRegistry() {
+ static FlagRegistry* global_registry = new FlagRegistry;
+ return *global_registry;
+}
+
+// --------------------------------------------------------------------
+
+void ForEachFlag(std::function<void(CommandLineFlag&)> visitor) {
+ FlagRegistry& registry = FlagRegistry::GlobalRegistry();
+
+ if (registry.finalized_flags_.load(std::memory_order_acquire)) {
+ for (const auto& i : registry.flat_flags_) visitor(*i);
+ }
+
+ FlagRegistryLock frl(registry);
+ for (const auto& i : registry.flags_) visitor(*i.second);
+}
+
+// --------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag& flag, const char* filename) {
+ FlagRegistry::GlobalRegistry().RegisterFlag(flag, filename);
+ return true;
+}
+
+void FinalizeRegistry() {
+ auto& registry = FlagRegistry::GlobalRegistry();
+ FlagRegistryLock frl(registry);
+ if (registry.finalized_flags_.load(std::memory_order_relaxed)) {
+ // Was already finalized. Ignore the second time.
+ return;
+ }
+ registry.flat_flags_.reserve(registry.flags_.size());
+ for (const auto& f : registry.flags_) {
+ registry.flat_flags_.push_back(f.second);
+ }
+ registry.flags_.clear();
+ registry.finalized_flags_.store(true, std::memory_order_release);
+}
+
+// --------------------------------------------------------------------
+
+namespace {
+
+class RetiredFlagObj final : public CommandLineFlag {
+ public:
+ constexpr RetiredFlagObj(const char* name, FlagFastTypeId type_id)
+ : name_(name), type_id_(type_id) {}
+
+ private:
+ absl::string_view Name() const override { return name_; }
+ std::string Filename() const override {
+ OnAccess();
+ return "RETIRED";
+ }
+ FlagFastTypeId TypeId() const override { return type_id_; }
+ std::string Help() const override {
+ OnAccess();
+ return "";
+ }
+ bool IsRetired() const override { return true; }
+ bool IsSpecifiedOnCommandLine() const override {
+ OnAccess();
+ return false;
+ }
+ std::string DefaultValue() const override {
+ OnAccess();
+ return "";
+ }
+ std::string CurrentValue() const override {
+ OnAccess();
+ return "";
+ }
+
+ // Any input is valid
+ bool ValidateInputValue(absl::string_view) const override {
+ OnAccess();
+ return true;
+ }
+
+ std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
+ return nullptr;
+ }
+
+ bool ParseFrom(absl::string_view, flags_internal::FlagSettingMode,
+ flags_internal::ValueSource, std::string&) override {
+ OnAccess();
+ return false;
+ }
+
+ void CheckDefaultValueParsingRoundtrip() const override { OnAccess(); }
+
+ void Read(void*) const override { OnAccess(); }
+
+ void OnAccess() const {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Accessing retired flag '", name_, "'"), false);
+ }
+
+ // Data members
+ const char* const name_;
+ const FlagFastTypeId type_id_;
+};
+
+} // namespace
+
+void Retire(const char* name, FlagFastTypeId type_id, char* buf) {
+ static_assert(sizeof(RetiredFlagObj) == kRetiredFlagObjSize, "");
+ static_assert(alignof(RetiredFlagObj) == kRetiredFlagObjAlignment, "");
+ auto* flag = ::new (static_cast<void*>(buf))
+ flags_internal::RetiredFlagObj(name, type_id);
+ FlagRegistry::GlobalRegistry().RegisterFlag(*flag, nullptr);
+}
+
+// --------------------------------------------------------------------
+
+class FlagSaverImpl {
+ public:
+ FlagSaverImpl() = default;
+ FlagSaverImpl(const FlagSaverImpl&) = delete;
+ void operator=(const FlagSaverImpl&) = delete;
+
+ // Saves the flag states from the flag registry into this object.
+ // It's an error to call this more than once.
+ void SaveFromRegistry() {
+ assert(backup_registry_.empty()); // call only once!
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (auto flag_state =
+ flags_internal::PrivateHandleAccessor::SaveState(flag)) {
+ backup_registry_.emplace_back(std::move(flag_state));
+ }
+ });
+ }
+
+ // Restores the saved flag states into the flag registry.
+ void RestoreToRegistry() {
+ for (const auto& flag_state : backup_registry_) {
+ flag_state->Restore();
+ }
+ }
+
+ private:
+ std::vector<std::unique_ptr<flags_internal::FlagStateInterface>>
+ backup_registry_;
+};
+
+} // namespace flags_internal
+
+FlagSaver::FlagSaver() : impl_(new flags_internal::FlagSaverImpl) {
+ impl_->SaveFromRegistry();
+}
+
+FlagSaver::~FlagSaver() {
+ if (!impl_) return;
+
+ impl_->RestoreToRegistry();
+ delete impl_;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+ if (name.empty()) return nullptr;
+ flags_internal::FlagRegistry& registry =
+ flags_internal::FlagRegistry::GlobalRegistry();
+ return registry.FindFlag(name);
+}
+
+// --------------------------------------------------------------------
+
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags() {
+ absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> res;
+ flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
+ if (!flag.IsRetired()) res.insert({flag.Name(), &flag});
+ });
+ return res;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.h
new file mode 100644
index 00000000000..e6baf5de4b0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection.h
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: reflection.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the routines to access and operate on an Abseil Flag's
+// reflection handle.
+
+#ifndef ABSL_FLAGS_REFLECTION_H_
+#define ABSL_FLAGS_REFLECTION_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/flags/commandlineflag.h"
+#include "absl/flags/internal/commandlineflag.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+class FlagSaverImpl;
+} // namespace flags_internal
+
+// FindCommandLineFlag()
+//
+// Returns the reflection handle of an Abseil flag of the specified name, or
+// `nullptr` if not found. This function will emit a warning if the name of a
+// 'retired' flag is specified.
+absl::CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+
+// Returns current state of the Flags registry in a form of mapping from flag
+// name to a flag reflection handle.
+absl::flat_hash_map<absl::string_view, absl::CommandLineFlag*> GetAllFlags();
+
+//------------------------------------------------------------------------------
+// FlagSaver
+//------------------------------------------------------------------------------
+//
+// A FlagSaver object stores the state of flags in the scope where the FlagSaver
+// is defined, allowing modification of those flags within that scope and
+// automatic restoration of the flags to their previous state upon leaving the
+// scope.
+//
+// A FlagSaver can be used within tests to temporarily change the test
+// environment and restore the test case to its previous state.
+//
+// Example:
+//
+// void MyFunc() {
+// absl::FlagSaver fs;
+// ...
+// absl::SetFlag(&FLAGS_myFlag, otherValue);
+// ...
+// } // scope of FlagSaver left, flags return to previous state
+//
+// This class is thread-safe.
+
+class FlagSaver {
+ public:
+ FlagSaver();
+ ~FlagSaver();
+
+ FlagSaver(const FlagSaver&) = delete;
+ void operator=(const FlagSaver&) = delete;
+
+ private:
+ flags_internal::FlagSaverImpl* impl_;
+};
+
+//-----------------------------------------------------------------------------
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_REFLECTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection_test.cc
new file mode 100644
index 00000000000..79cfa90c3a6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/reflection_test.cc
@@ -0,0 +1,265 @@
+//
+// 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.
+
+#include "absl/flags/reflection.h"
+
+#include <memory>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/marshalling.h"
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+
+ABSL_FLAG(int, int_flag, 1, "int_flag help");
+ABSL_FLAG(std::string, string_flag, "dflt", "string_flag help");
+ABSL_RETIRED_FLAG(bool, bool_retired_flag, false, "bool_retired_flag help");
+
+namespace {
+
+class ReflectionTest : public testing::Test {
+ protected:
+ void SetUp() override { flag_saver_ = absl::make_unique<absl::FlagSaver>(); }
+ void TearDown() override { flag_saver_.reset(); }
+
+ private:
+ std::unique_ptr<absl::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFindCommandLineFlag) {
+ auto* handle = absl::FindCommandLineFlag("some_flag");
+ EXPECT_EQ(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("int_flag");
+ EXPECT_NE(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("string_flag");
+ EXPECT_NE(handle, nullptr);
+
+ handle = absl::FindCommandLineFlag("bool_retired_flag");
+ EXPECT_NE(handle, nullptr);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestGetAllFlags) {
+ auto all_flags = absl::GetAllFlags();
+ EXPECT_NE(all_flags.find("int_flag"), all_flags.end());
+ EXPECT_EQ(all_flags.find("bool_retired_flag"), all_flags.end());
+ EXPECT_EQ(all_flags.find("some_undefined_flag"), all_flags.end());
+
+ std::vector<absl::string_view> flag_names_first_attempt;
+ auto all_flags_1 = absl::GetAllFlags();
+ for (auto f : all_flags_1) {
+ flag_names_first_attempt.push_back(f.first);
+ }
+
+ std::vector<absl::string_view> flag_names_second_attempt;
+ auto all_flags_2 = absl::GetAllFlags();
+ for (auto f : all_flags_2) {
+ flag_names_second_attempt.push_back(f.first);
+ }
+
+ EXPECT_THAT(flag_names_first_attempt,
+ ::testing::UnorderedElementsAreArray(flag_names_second_attempt));
+}
+
+// --------------------------------------------------------------------
+
+struct CustomUDT {
+ CustomUDT() : a(1), b(1) {}
+ CustomUDT(int a_, int b_) : a(a_), b(b_) {}
+
+ friend bool operator==(const CustomUDT& f1, const CustomUDT& f2) {
+ return f1.a == f2.a && f1.b == f2.b;
+ }
+
+ int a;
+ int b;
+};
+bool AbslParseFlag(absl::string_view in, CustomUDT* f, std::string*) {
+ std::vector<absl::string_view> parts =
+ absl::StrSplit(in, ':', absl::SkipWhitespace());
+
+ if (parts.size() != 2) return false;
+
+ if (!absl::SimpleAtoi(parts[0], &f->a)) return false;
+
+ if (!absl::SimpleAtoi(parts[1], &f->b)) return false;
+
+ return true;
+}
+std::string AbslUnparseFlag(const CustomUDT& f) {
+ return absl::StrCat(f.a, ":", f.b);
+}
+
+} // namespace
+
+// --------------------------------------------------------------------
+
+ABSL_FLAG(bool, test_flag_01, true, "");
+ABSL_FLAG(int, test_flag_02, 1234, "");
+ABSL_FLAG(int16_t, test_flag_03, -34, "");
+ABSL_FLAG(uint16_t, test_flag_04, 189, "");
+ABSL_FLAG(int32_t, test_flag_05, 10765, "");
+ABSL_FLAG(uint32_t, test_flag_06, 40000, "");
+ABSL_FLAG(int64_t, test_flag_07, -1234567, "");
+ABSL_FLAG(uint64_t, test_flag_08, 9876543, "");
+ABSL_FLAG(double, test_flag_09, -9.876e-50, "");
+ABSL_FLAG(float, test_flag_10, 1.234e12f, "");
+ABSL_FLAG(std::string, test_flag_11, "", "");
+ABSL_FLAG(absl::Duration, test_flag_12, absl::Minutes(10), "");
+static int counter = 0;
+ABSL_FLAG(int, test_flag_13, 200, "").OnUpdate([]() { counter++; });
+ABSL_FLAG(CustomUDT, test_flag_14, {}, "");
+
+namespace {
+
+TEST_F(ReflectionTest, TestFlagSaverInScope) {
+ {
+ absl::FlagSaver s;
+ counter = 0;
+ absl::SetFlag(&FLAGS_test_flag_01, false);
+ absl::SetFlag(&FLAGS_test_flag_02, -1021);
+ absl::SetFlag(&FLAGS_test_flag_03, 6009);
+ absl::SetFlag(&FLAGS_test_flag_04, 44);
+ absl::SetFlag(&FLAGS_test_flag_05, +800);
+ absl::SetFlag(&FLAGS_test_flag_06, -40978756);
+ absl::SetFlag(&FLAGS_test_flag_07, 23405);
+ absl::SetFlag(&FLAGS_test_flag_08, 975310);
+ absl::SetFlag(&FLAGS_test_flag_09, 1.00001);
+ absl::SetFlag(&FLAGS_test_flag_10, -3.54f);
+ absl::SetFlag(&FLAGS_test_flag_11, "asdf");
+ absl::SetFlag(&FLAGS_test_flag_12, absl::Hours(20));
+ absl::SetFlag(&FLAGS_test_flag_13, 4);
+ absl::SetFlag(&FLAGS_test_flag_14, CustomUDT{-1, -2});
+ }
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+ EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestFlagSaverVsUpdateViaReflection) {
+ {
+ absl::FlagSaver s;
+ counter = 0;
+ std::string error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_01")->ParseFrom("false", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_02")->ParseFrom("-4536", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_03")->ParseFrom("111", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_04")->ParseFrom("909", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_05")->ParseFrom("-2004", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_06")->ParseFrom("1000023", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_07")->ParseFrom("69305", &error))
+ << error;
+ EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_08")
+ ->ParseFrom("1000000001", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_09")->ParseFrom("2.09021", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_10")->ParseFrom("-33.1", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_11")->ParseFrom("ADD_FOO", &error))
+ << error;
+ EXPECT_TRUE(absl::FindCommandLineFlag("test_flag_12")
+ ->ParseFrom("3h11m16s", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_13")->ParseFrom("0", &error))
+ << error;
+ EXPECT_TRUE(
+ absl::FindCommandLineFlag("test_flag_14")->ParseFrom("10:1", &error))
+ << error;
+ }
+
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_01), true);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_02), 1234);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_03), -34);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_04), 189);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_05), 10765);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_06), 40000);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_07), -1234567);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_09), -9.876e-50, 1e-55);
+ EXPECT_NEAR(absl::GetFlag(FLAGS_test_flag_10), 1.234e12f, 1e5f);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_11), "");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), absl::Minutes(10));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), 200);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_14), CustomUDT{});
+ EXPECT_EQ(counter, 2);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(ReflectionTest, TestMultipleFlagSaversInEnclosedScopes) {
+ {
+ absl::FlagSaver s;
+ absl::SetFlag(&FLAGS_test_flag_08, 10);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+ {
+ absl::FlagSaver s;
+ absl::SetFlag(&FLAGS_test_flag_08, 20);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+ {
+ absl::FlagSaver s;
+ absl::SetFlag(&FLAGS_test_flag_08, -200);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), -200);
+ }
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 20);
+ }
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 10);
+ }
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_08), 9876543);
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.cc
new file mode 100644
index 00000000000..452f667512e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.cc
@@ -0,0 +1,65 @@
+//
+// 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.
+#include "absl/flags/usage.h"
+
+#include <stdlib.h>
+
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/internal/usage.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+namespace {
+ABSL_CONST_INIT absl::Mutex usage_message_guard(absl::kConstInit);
+ABSL_CONST_INIT std::string* program_usage_message
+ ABSL_GUARDED_BY(usage_message_guard) = nullptr;
+} // namespace
+} // namespace flags_internal
+
+// --------------------------------------------------------------------
+// Sets the "usage" message to be used by help reporting routines.
+void SetProgramUsageMessage(absl::string_view new_usage_message) {
+ absl::MutexLock l(&flags_internal::usage_message_guard);
+
+ if (flags_internal::program_usage_message != nullptr) {
+ ABSL_INTERNAL_LOG(FATAL, "SetProgramUsageMessage() called twice.");
+ std::exit(1);
+ }
+
+ flags_internal::program_usage_message = new std::string(new_usage_message);
+}
+
+// --------------------------------------------------------------------
+// Returns the usage message set by SetProgramUsageMessage().
+// Note: We able to return string_view here only because calling
+// SetProgramUsageMessage twice is prohibited.
+absl::string_view ProgramUsageMessage() {
+ absl::MutexLock l(&flags_internal::usage_message_guard);
+
+ return flags_internal::program_usage_message != nullptr
+ ? absl::string_view(*flags_internal::program_usage_message)
+ : "Warning: SetProgramUsageMessage() never called";
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.h
new file mode 100644
index 00000000000..ad12ab7ad90
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage.h
@@ -0,0 +1,43 @@
+//
+// 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_FLAGS_USAGE_H_
+#define ABSL_FLAGS_USAGE_H_
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Usage reporting interfaces
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Sets the "usage" message to be used by help reporting routines.
+// For example:
+// absl::SetProgramUsageMessage(
+// absl::StrCat("This program does nothing. Sample usage:\n", argv[0],
+// " <uselessarg1> <uselessarg2>"));
+// Do not include commandline flags in the usage: we do that for you!
+// Note: Calling SetProgramUsageMessage twice will trigger a call to std::exit.
+void SetProgramUsageMessage(absl::string_view new_usage_message);
+
+// Returns the usage message set by SetProgramUsageMessage().
+absl::string_view ProgramUsageMessage();
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_USAGE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.cc
new file mode 100644
index 00000000000..5d7426db31f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.cc
@@ -0,0 +1,165 @@
+//
+// 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.
+
+#include "absl/flags/usage_config.h"
+
+#include <functional>
+#include <iostream>
+#include <string>
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/const_init.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/synchronization/mutex.h"
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(
+ AbslInternalReportFatalUsageError)(absl::string_view) {}
+
+} // extern "C"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+namespace {
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helpshort flag.
+
+bool ContainsHelpshortFlags(absl::string_view filename) {
+ // By default we only want flags in binary's main. We expect the main
+ // routine to reside in <program>.cc or <program>-main.cc or
+ // <program>_main.cc, where the <program> is the name of the binary
+ // (without .exe on Windows).
+ auto suffix = flags_internal::Basename(filename);
+ auto program_name = flags_internal::ShortProgramInvocationName();
+ absl::string_view program_name_ref = program_name;
+#if defined(_WIN32)
+ absl::ConsumeSuffix(&program_name_ref, ".exe");
+#endif
+ if (!absl::ConsumePrefix(&suffix, program_name_ref))
+ return false;
+ return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") ||
+ absl::StartsWith(suffix, "_main.");
+}
+
+// --------------------------------------------------------------------
+// Returns true if flags defined in the filename should be reported with
+// -helppackage flag.
+
+bool ContainsHelppackageFlags(absl::string_view filename) {
+ // TODO(rogeeff): implement properly when registry is available.
+ return ContainsHelpshortFlags(filename);
+}
+
+// --------------------------------------------------------------------
+// Generates program version information into supplied output.
+
+std::string VersionString() {
+ std::string version_str(flags_internal::ShortProgramInvocationName());
+
+ version_str += "\n";
+
+#if !defined(NDEBUG)
+ version_str += "Debug build (NDEBUG not #defined)\n";
+#endif
+
+ return version_str;
+}
+
+// --------------------------------------------------------------------
+// Normalizes the filename specific to the build system/filesystem used.
+
+std::string NormalizeFilename(absl::string_view filename) {
+ // Skip any leading slashes
+ auto pos = filename.find_first_not_of("\\/");
+ if (pos == absl::string_view::npos) return "";
+
+ filename.remove_prefix(pos);
+ return std::string(filename);
+}
+
+// --------------------------------------------------------------------
+
+ABSL_CONST_INIT absl::Mutex custom_usage_config_guard(absl::kConstInit);
+ABSL_CONST_INIT FlagsUsageConfig* custom_usage_config
+ ABSL_GUARDED_BY(custom_usage_config_guard) = nullptr;
+
+} // namespace
+
+FlagsUsageConfig GetUsageConfig() {
+ absl::MutexLock l(&custom_usage_config_guard);
+
+ if (custom_usage_config) return *custom_usage_config;
+
+ FlagsUsageConfig default_config;
+ default_config.contains_helpshort_flags = &ContainsHelpshortFlags;
+ default_config.contains_help_flags = &ContainsHelppackageFlags;
+ default_config.contains_helppackage_flags = &ContainsHelppackageFlags;
+ default_config.version_string = &VersionString;
+ default_config.normalize_filename = &NormalizeFilename;
+
+ return default_config;
+}
+
+void ReportUsageError(absl::string_view msg, bool is_fatal) {
+ std::cerr << "ERROR: " << msg << std::endl;
+
+ if (is_fatal) {
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(msg);
+ }
+}
+
+} // namespace flags_internal
+
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config) {
+ absl::MutexLock l(&flags_internal::custom_usage_config_guard);
+
+ if (!usage_config.contains_helpshort_flags)
+ usage_config.contains_helpshort_flags =
+ flags_internal::ContainsHelpshortFlags;
+
+ if (!usage_config.contains_help_flags)
+ usage_config.contains_help_flags = flags_internal::ContainsHelppackageFlags;
+
+ if (!usage_config.contains_helppackage_flags)
+ usage_config.contains_helppackage_flags =
+ flags_internal::ContainsHelppackageFlags;
+
+ if (!usage_config.version_string)
+ usage_config.version_string = flags_internal::VersionString;
+
+ if (!usage_config.normalize_filename)
+ usage_config.normalize_filename = flags_internal::NormalizeFilename;
+
+ if (flags_internal::custom_usage_config)
+ *flags_internal::custom_usage_config = usage_config;
+ else
+ flags_internal::custom_usage_config = new FlagsUsageConfig(usage_config);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.h
new file mode 100644
index 00000000000..ded70300f09
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config.h
@@ -0,0 +1,135 @@
+//
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: usage_config.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the main usage reporting configuration interfaces and
+// documents Abseil's supported built-in usage flags. If these flags are found
+// when parsing a command-line, Abseil will exit the program and display
+// appropriate help messages.
+#ifndef ABSL_FLAGS_USAGE_CONFIG_H_
+#define ABSL_FLAGS_USAGE_CONFIG_H_
+
+#include <functional>
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
+
+// -----------------------------------------------------------------------------
+// Built-in Usage Flags
+// -----------------------------------------------------------------------------
+//
+// Abseil supports the following built-in usage flags. When passed, these flags
+// exit the program and :
+//
+// * --help
+// Shows help on important flags for this binary
+// * --helpfull
+// Shows help on all flags
+// * --helpshort
+// Shows help on only the main module for this program
+// * --helppackage
+// Shows help on all modules in the main package
+// * --version
+// Shows the version and build info for this binary and exits
+// * --only_check_args
+// Exits after checking all flags
+// * --helpon
+// Shows help on the modules named by this flag value
+// * --helpmatch
+// Shows help on modules whose name contains the specified substring
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace flags_internal {
+using FlagKindFilter = std::function<bool (absl::string_view)>;
+} // namespace flags_internal
+
+// FlagsUsageConfig
+//
+// This structure contains the collection of callbacks for changing the behavior
+// of the usage reporting routines in Abseil Flags.
+struct FlagsUsageConfig {
+ // Returns true if flags defined in the given source code file should be
+ // reported with --helpshort flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_helpshort_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --helpshort will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_helpshort_flags;
+
+ // Returns true if flags defined in the filename should be reported with
+ // --help flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_help_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --help will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_help_flags;
+
+ // Returns true if flags defined in the filename should be reported with
+ // --helppackage flag. For example, if the file
+ // "path/to/my/code.cc" defines the flag "--my_flag", and
+ // contains_helppackage_flags("path/to/my/code.cc") returns true, invoking the
+ // program with --helppackage will include information about --my_flag in the
+ // program output.
+ flags_internal::FlagKindFilter contains_helppackage_flags;
+
+ // Generates string containing program version. This is the string reported
+ // when user specifies --version in a command line.
+ std::function<std::string()> version_string;
+
+ // Normalizes the filename specific to the build system/filesystem used. This
+ // routine is used when we report the information about the flag definition
+ // location. For instance, if your build resides at some location you do not
+ // want to expose in the usage output, you can trim it to show only relevant
+ // part.
+ // For example:
+ // normalize_filename("/my_company/some_long_path/src/project/file.cc")
+ // might produce
+ // "project/file.cc".
+ std::function<std::string(absl::string_view)> normalize_filename;
+};
+
+// SetFlagsUsageConfig()
+//
+// Sets the usage reporting configuration callbacks. If any of the callbacks are
+// not set in usage_config instance, then the default value of the callback is
+// used.
+void SetFlagsUsageConfig(FlagsUsageConfig usage_config);
+
+namespace flags_internal {
+
+FlagsUsageConfig GetUsageConfig();
+
+void ReportUsageError(absl::string_view msg, bool is_fatal);
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+extern "C" {
+
+// Additional report of fatal usage error message before we std::exit. Error is
+// fatal if is_fatal argument to ReportUsageError is true.
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(
+ absl::string_view);
+
+} // extern "C"
+
+#endif // ABSL_FLAGS_USAGE_CONFIG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config_test.cc
new file mode 100644
index 00000000000..e57a8832f64
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/flags/usage_config_test.cc
@@ -0,0 +1,205 @@
+//
+// 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.
+
+#include "absl/flags/usage_config.h"
+
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/internal/path_util.h"
+#include "absl/flags/internal/program_name.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+
+namespace {
+
+class FlagsUsageConfigTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ // Install Default config for the use on this unit test.
+ // Binary may install a custom config before tests are run.
+ absl::FlagsUsageConfig default_config;
+ absl::SetFlagsUsageConfig(default_config);
+ }
+};
+
+namespace flags = absl::flags_internal;
+
+bool TstContainsHelpshortFlags(absl::string_view f) {
+ return absl::StartsWith(flags::Basename(f), "progname.");
+}
+
+bool TstContainsHelppackageFlags(absl::string_view f) {
+ return absl::EndsWith(flags::Package(f), "aaa/");
+}
+
+bool TstContainsHelpFlags(absl::string_view f) {
+ return absl::EndsWith(flags::Package(f), "zzz/");
+}
+
+std::string TstVersionString() { return "program 1.0.0"; }
+
+std::string TstNormalizeFilename(absl::string_view filename) {
+ return std::string(filename.substr(2));
+}
+
+void TstReportUsageMessage(absl::string_view msg) {}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) {
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().version_string);
+ EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
+
+ absl::FlagsUsageConfig empty_config;
+ empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
+ empty_config.contains_help_flags = &TstContainsHelpFlags;
+ empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
+ empty_config.version_string = &TstVersionString;
+ empty_config.normalize_filename = &TstNormalizeFilename;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helpshort_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().contains_helppackage_flags);
+ EXPECT_TRUE(flags::GetUsageConfig().version_string);
+ EXPECT_TRUE(flags::GetUsageConfig().normalize_filename);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelpshortFlags) {
+#if defined(_WIN32)
+ flags::SetProgramInvocationName("usage_config_test.exe");
+#else
+ flags::SetProgramInvocationName("usage_config_test");
+#endif
+
+ auto config = flags::GetUsageConfig();
+ EXPECT_TRUE(config.contains_helpshort_flags("adir/cd/usage_config_test.cc"));
+ EXPECT_TRUE(
+ config.contains_helpshort_flags("aaaa/usage_config_test-main.cc"));
+ EXPECT_TRUE(config.contains_helpshort_flags("abc/usage_config_test_main.cc"));
+ EXPECT_FALSE(config.contains_helpshort_flags("usage_config_main.cc"));
+
+ absl::FlagsUsageConfig empty_config;
+ empty_config.contains_helpshort_flags = &TstContainsHelpshortFlags;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_TRUE(
+ flags::GetUsageConfig().contains_helpshort_flags("aaa/progname.cpp"));
+ EXPECT_FALSE(
+ flags::GetUsageConfig().contains_helpshort_flags("aaa/progmane.cpp"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelpFlags) {
+ flags::SetProgramInvocationName("usage_config_test");
+
+ auto config = flags::GetUsageConfig();
+ EXPECT_TRUE(config.contains_help_flags("zzz/usage_config_test.cc"));
+ EXPECT_TRUE(
+ config.contains_help_flags("bdir/a/zzz/usage_config_test-main.cc"));
+ EXPECT_TRUE(
+ config.contains_help_flags("//aqse/zzz/usage_config_test_main.cc"));
+ EXPECT_FALSE(config.contains_help_flags("zzz/aa/usage_config_main.cc"));
+
+ absl::FlagsUsageConfig empty_config;
+ empty_config.contains_help_flags = &TstContainsHelpFlags;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_TRUE(flags::GetUsageConfig().contains_help_flags("zzz/main-body.c"));
+ EXPECT_FALSE(
+ flags::GetUsageConfig().contains_help_flags("zzz/dir/main-body.c"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestContainsHelppackageFlags) {
+ flags::SetProgramInvocationName("usage_config_test");
+
+ auto config = flags::GetUsageConfig();
+ EXPECT_TRUE(config.contains_helppackage_flags("aaa/usage_config_test.cc"));
+ EXPECT_TRUE(
+ config.contains_helppackage_flags("bbdir/aaa/usage_config_test-main.cc"));
+ EXPECT_TRUE(config.contains_helppackage_flags(
+ "//aqswde/aaa/usage_config_test_main.cc"));
+ EXPECT_FALSE(config.contains_helppackage_flags("aadir/usage_config_main.cc"));
+
+ absl::FlagsUsageConfig empty_config;
+ empty_config.contains_helppackage_flags = &TstContainsHelppackageFlags;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_TRUE(
+ flags::GetUsageConfig().contains_helppackage_flags("aaa/main-body.c"));
+ EXPECT_FALSE(
+ flags::GetUsageConfig().contains_helppackage_flags("aadir/main-body.c"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestVersionString) {
+ flags::SetProgramInvocationName("usage_config_test");
+
+#ifdef NDEBUG
+ std::string expected_output = "usage_config_test\n";
+#else
+ std::string expected_output =
+ "usage_config_test\nDebug build (NDEBUG not #defined)\n";
+#endif
+
+ EXPECT_EQ(flags::GetUsageConfig().version_string(), expected_output);
+
+ absl::FlagsUsageConfig empty_config;
+ empty_config.version_string = &TstVersionString;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_EQ(flags::GetUsageConfig().version_string(), "program 1.0.0");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(FlagsUsageConfigTest, TestNormalizeFilename) {
+ // This tests the default implementation.
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/"), "");
+
+ // This tests that the custom implementation is called.
+ absl::FlagsUsageConfig empty_config;
+ empty_config.normalize_filename = &TstNormalizeFilename;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("aaa/a.cc"), "a/a.cc");
+
+ // This tests that the default implementation is called.
+ empty_config.normalize_filename = nullptr;
+ absl::SetFlagsUsageConfig(empty_config);
+
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("/a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("///a/a.cc"), "a/a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\a\\a.cc"), "a\\a.cc");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("//"), "");
+ EXPECT_EQ(flags::GetUsageConfig().normalize_filename("\\\\"), "");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/BUILD.bazel
new file mode 100644
index 00000000000..ebd9b99b782
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/BUILD.bazel
@@ -0,0 +1,93 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "bind_front",
+ srcs = ["internal/front_binder.h"],
+ hdrs = ["bind_front.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:base_internal",
+ "//absl/container:compressed_tuple",
+ "//absl/meta:type_traits",
+ "//absl/utility",
+ ],
+)
+
+cc_test(
+ name = "bind_front_test",
+ srcs = ["bind_front_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":bind_front",
+ "//absl/memory",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "function_ref",
+ srcs = ["internal/function_ref.h"],
+ hdrs = ["function_ref.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:base_internal",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_test(
+ name = "function_ref_test",
+ size = "small",
+ srcs = ["function_ref_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":function_ref",
+ "//absl/container:test_instance_tracker",
+ "//absl/memory",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "function_ref_benchmark",
+ srcs = [
+ "function_ref_benchmark.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":function_ref",
+ "//absl/base:core_headers",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front.h
new file mode 100644
index 00000000000..5b47970e357
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front.h
@@ -0,0 +1,184 @@
+// 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_
+
+#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.
+//
+// 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");
+//
+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, absl::forward<F>(func),
+ absl::forward<BoundArgs>(args)...);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_BIND_FRONT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front_test.cc
new file mode 100644
index 00000000000..4801a81caf0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/bind_front_test.cc
@@ -0,0 +1,231 @@
+// 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.
+
+#include "absl/functional/bind_front.h"
+
+#include <stddef.h>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/memory/memory.h"
+
+namespace {
+
+char CharAt(const char* s, size_t index) { return s[index]; }
+
+TEST(BindTest, Basics) {
+ EXPECT_EQ('C', absl::bind_front(CharAt)("ABC", 2));
+ EXPECT_EQ('C', absl::bind_front(CharAt, "ABC")(2));
+ EXPECT_EQ('C', absl::bind_front(CharAt, "ABC", 2)());
+}
+
+TEST(BindTest, Lambda) {
+ auto lambda = [](int x, int y, int z) { return x + y + z; };
+ EXPECT_EQ(6, absl::bind_front(lambda)(1, 2, 3));
+ EXPECT_EQ(6, absl::bind_front(lambda, 1)(2, 3));
+ EXPECT_EQ(6, absl::bind_front(lambda, 1, 2)(3));
+ EXPECT_EQ(6, absl::bind_front(lambda, 1, 2, 3)());
+}
+
+struct Functor {
+ std::string operator()() & { return "&"; }
+ std::string operator()() const& { return "const&"; }
+ std::string operator()() && { return "&&"; }
+ std::string operator()() const&& { return "const&&"; }
+};
+
+TEST(BindTest, PerfectForwardingOfBoundArgs) {
+ auto f = absl::bind_front(Functor());
+ const auto& cf = f;
+ EXPECT_EQ("&", f());
+ EXPECT_EQ("const&", cf());
+ EXPECT_EQ("&&", std::move(f)());
+ EXPECT_EQ("const&&", std::move(cf)());
+}
+
+struct ArgDescribe {
+ std::string operator()(int&) const { return "&"; } // NOLINT
+ std::string operator()(const int&) const { return "const&"; } // NOLINT
+ std::string operator()(int&&) const { return "&&"; }
+ std::string operator()(const int&&) const { return "const&&"; }
+};
+
+TEST(BindTest, PerfectForwardingOfFreeArgs) {
+ ArgDescribe f;
+ int i;
+ EXPECT_EQ("&", absl::bind_front(f)(static_cast<int&>(i)));
+ EXPECT_EQ("const&", absl::bind_front(f)(static_cast<const int&>(i)));
+ EXPECT_EQ("&&", absl::bind_front(f)(static_cast<int&&>(i)));
+ EXPECT_EQ("const&&", absl::bind_front(f)(static_cast<const int&&>(i)));
+}
+
+struct NonCopyableFunctor {
+ NonCopyableFunctor() = default;
+ NonCopyableFunctor(const NonCopyableFunctor&) = delete;
+ NonCopyableFunctor& operator=(const NonCopyableFunctor&) = delete;
+ const NonCopyableFunctor* operator()() const { return this; }
+};
+
+TEST(BindTest, RefToFunctor) {
+ // It won't copy/move the functor and use the original object.
+ NonCopyableFunctor ncf;
+ auto bound_ncf = absl::bind_front(std::ref(ncf));
+ auto bound_ncf_copy = bound_ncf;
+ EXPECT_EQ(&ncf, bound_ncf_copy());
+}
+
+struct Struct {
+ std::string value;
+};
+
+TEST(BindTest, StoreByCopy) {
+ Struct s = {"hello"};
+ auto f = absl::bind_front(&Struct::value, s);
+ auto g = f;
+ EXPECT_EQ("hello", f());
+ EXPECT_EQ("hello", g());
+ EXPECT_NE(&s.value, &f());
+ EXPECT_NE(&s.value, &g());
+ EXPECT_NE(&g(), &f());
+}
+
+struct NonCopyable {
+ explicit NonCopyable(const std::string& s) : value(s) {}
+ NonCopyable(const NonCopyable&) = delete;
+ NonCopyable& operator=(const NonCopyable&) = delete;
+
+ std::string value;
+};
+
+const std::string& GetNonCopyableValue(const NonCopyable& n) { return n.value; }
+
+TEST(BindTest, StoreByRef) {
+ NonCopyable s("hello");
+ auto f = absl::bind_front(&GetNonCopyableValue, std::ref(s));
+ EXPECT_EQ("hello", f());
+ EXPECT_EQ(&s.value, &f());
+ auto g = std::move(f); // NOLINT
+ EXPECT_EQ("hello", g());
+ EXPECT_EQ(&s.value, &g());
+ s.value = "goodbye";
+ EXPECT_EQ("goodbye", g());
+}
+
+TEST(BindTest, StoreByCRef) {
+ NonCopyable s("hello");
+ auto f = absl::bind_front(&GetNonCopyableValue, std::cref(s));
+ EXPECT_EQ("hello", f());
+ EXPECT_EQ(&s.value, &f());
+ auto g = std::move(f); // NOLINT
+ EXPECT_EQ("hello", g());
+ EXPECT_EQ(&s.value, &g());
+ s.value = "goodbye";
+ EXPECT_EQ("goodbye", g());
+}
+
+const std::string& GetNonCopyableValueByWrapper(
+ std::reference_wrapper<NonCopyable> n) {
+ return n.get().value;
+}
+
+TEST(BindTest, StoreByRefInvokeByWrapper) {
+ NonCopyable s("hello");
+ auto f = absl::bind_front(GetNonCopyableValueByWrapper, std::ref(s));
+ EXPECT_EQ("hello", f());
+ EXPECT_EQ(&s.value, &f());
+ auto g = std::move(f);
+ EXPECT_EQ("hello", g());
+ EXPECT_EQ(&s.value, &g());
+ s.value = "goodbye";
+ EXPECT_EQ("goodbye", g());
+}
+
+TEST(BindTest, StoreByPointer) {
+ NonCopyable s("hello");
+ auto f = absl::bind_front(&NonCopyable::value, &s);
+ EXPECT_EQ("hello", f());
+ EXPECT_EQ(&s.value, &f());
+ auto g = std::move(f);
+ EXPECT_EQ("hello", g());
+ EXPECT_EQ(&s.value, &g());
+}
+
+int Sink(std::unique_ptr<int> p) {
+ return *p;
+}
+
+std::unique_ptr<int> Factory(int n) { return absl::make_unique<int>(n); }
+
+TEST(BindTest, NonCopyableArg) {
+ EXPECT_EQ(42, absl::bind_front(Sink)(absl::make_unique<int>(42)));
+ EXPECT_EQ(42, absl::bind_front(Sink, absl::make_unique<int>(42))());
+}
+
+TEST(BindTest, NonCopyableResult) {
+ EXPECT_THAT(absl::bind_front(Factory)(42), ::testing::Pointee(42));
+ EXPECT_THAT(absl::bind_front(Factory, 42)(), ::testing::Pointee(42));
+}
+
+// is_copy_constructible<FalseCopyable<unique_ptr<T>> is true but an attempt to
+// instantiate the copy constructor leads to a compile error. This is similar
+// to how standard containers behave.
+template <class T>
+struct FalseCopyable {
+ FalseCopyable() {}
+ FalseCopyable(const FalseCopyable& other) : m(other.m) {}
+ FalseCopyable(FalseCopyable&& other) : m(std::move(other.m)) {}
+ T m;
+};
+
+int GetMember(FalseCopyable<std::unique_ptr<int>> x) { return *x.m; }
+
+TEST(BindTest, WrappedMoveOnly) {
+ FalseCopyable<std::unique_ptr<int>> x;
+ x.m = absl::make_unique<int>(42);
+ auto f = absl::bind_front(&GetMember, std::move(x));
+ EXPECT_EQ(42, std::move(f)());
+}
+
+int Plus(int a, int b) { return a + b; }
+
+TEST(BindTest, ConstExpr) {
+ constexpr auto f = absl::bind_front(CharAt);
+ EXPECT_EQ(f("ABC", 1), 'B');
+ static constexpr int five = 5;
+ constexpr auto plus5 = absl::bind_front(Plus, five);
+ EXPECT_EQ(plus5(1), 6);
+
+ // There seems to be a bug in MSVC dealing constexpr construction of
+ // char[]. Notice 'plus5' above; 'int' works just fine.
+#if !(defined(_MSC_VER) && _MSC_VER < 1910)
+ static constexpr char data[] = "DEF";
+ constexpr auto g = absl::bind_front(CharAt, data);
+ EXPECT_EQ(g(1), 'E');
+#endif
+}
+
+struct ManglingCall {
+ int operator()(int, double, std::string) const { return 0; }
+};
+
+TEST(BindTest, Mangling) {
+ // We just want to generate a particular instantiation to see its mangling.
+ absl::bind_front(ManglingCall{}, 1, 3.3)("A");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref.h
new file mode 100644
index 00000000000..6e03ac2e04e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref.h
@@ -0,0 +1,139 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: function_ref.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::FunctionRef` type for holding a
+// non-owning reference to an object of any invocable type. This function
+// reference is typically most useful as a type-erased argument type for
+// accepting function types that neither take ownership nor copy the type; using
+// the reference type in this case avoids a copy and an allocation. Best
+// practices of other non-owning reference-like objects (such as
+// `absl::string_view`) apply here.
+//
+// An `absl::FunctionRef` is similar in usage to a `std::function` but has the
+// following differences:
+//
+// * It doesn't own the underlying object.
+// * It doesn't have a null or empty state.
+// * It never performs deep copies or allocations.
+// * It's much faster and cheaper to construct.
+// * It's trivially copyable and destructable.
+//
+// Generally, `absl::FunctionRef` should not be used as a return value, data
+// member, or to initialize a `std::function`. Such usages will often lead to
+// problematic lifetime issues. Once you convert something to an
+// `absl::FunctionRef` you cannot make a deep copy later.
+//
+// This class is suitable for use wherever a "const std::function<>&"
+// would be used without making a copy. ForEach functions and other versions of
+// the visitor pattern are a good example of when this class should be used.
+//
+// This class is trivial to copy and should be passed by value.
+#ifndef ABSL_FUNCTIONAL_FUNCTION_REF_H_
+#define ABSL_FUNCTIONAL_FUNCTION_REF_H_
+
+#include <cassert>
+#include <functional>
+#include <type_traits>
+
+#include "absl/functional/internal/function_ref.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// FunctionRef
+//
+// Dummy class declaration to allow the partial specialization based on function
+// types below.
+template <typename T>
+class FunctionRef;
+
+// FunctionRef
+//
+// An `absl::FunctionRef` is a lightweight wrapper to any invokable object with
+// a compatible signature. Generally, an `absl::FunctionRef` should only be used
+// as an argument type and should be preferred as an argument over a const
+// reference to a `std::function`.
+//
+// Example:
+//
+// // The following function takes a function callback by const reference
+// bool Visitor(const std::function<void(my_proto&,
+// absl::string_view)>& callback);
+//
+// // Assuming that the function is not stored or otherwise copied, it can be
+// // replaced by an `absl::FunctionRef`:
+// bool Visitor(absl::FunctionRef<void(my_proto&, absl::string_view)>
+// callback);
+//
+// Note: the assignment operator within an `absl::FunctionRef` is intentionally
+// deleted to prevent misuse; because the `absl::FunctionRef` does not own the
+// underlying type, assignment likely indicates misuse.
+template <typename R, typename... Args>
+class FunctionRef<R(Args...)> {
+ private:
+ // Used to disable constructors for objects that are not compatible with the
+ // signature of this FunctionRef.
+ template <typename F,
+ typename FR = absl::base_internal::invoke_result_t<F, Args&&...>>
+ using EnableIfCompatible =
+ typename std::enable_if<std::is_void<R>::value ||
+ std::is_convertible<FR, R>::value>::type;
+
+ public:
+ // Constructs a FunctionRef from any invokable type.
+ template <typename F, typename = EnableIfCompatible<const F&>>
+ FunctionRef(const F& f) // NOLINT(runtime/explicit)
+ : invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) {
+ absl::functional_internal::AssertNonNull(f);
+ ptr_.obj = &f;
+ }
+
+ // Overload for function pointers. This eliminates a level of indirection that
+ // would happen if the above overload was used (it lets us store the pointer
+ // instead of a pointer to a pointer).
+ //
+ // This overload is also used for references to functions, since references to
+ // functions can decay to function pointers implicitly.
+ template <
+ typename F, typename = EnableIfCompatible<F*>,
+ absl::functional_internal::EnableIf<absl::is_function<F>::value> = 0>
+ FunctionRef(F* f) // NOLINT(runtime/explicit)
+ : invoker_(&absl::functional_internal::InvokeFunction<F*, R, Args...>) {
+ assert(f != nullptr);
+ ptr_.fun = reinterpret_cast<decltype(ptr_.fun)>(f);
+ }
+
+ // To help prevent subtle lifetime bugs, FunctionRef is not assignable.
+ // Typically, it should only be used as an argument type.
+ FunctionRef& operator=(const FunctionRef& rhs) = delete;
+
+ // Call the underlying object.
+ R operator()(Args... args) const {
+ return invoker_(ptr_, std::forward<Args>(args)...);
+ }
+
+ private:
+ absl::functional_internal::VoidPtr ptr_;
+ absl::functional_internal::Invoker<R, Args...> invoker_;
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_FUNCTION_REF_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_benchmark.cc
new file mode 100644
index 00000000000..045305bfef3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_benchmark.cc
@@ -0,0 +1,142 @@
+// 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.
+
+#include "absl/functional/function_ref.h"
+
+#include <memory>
+
+#include "benchmark/benchmark.h"
+#include "absl/base/attributes.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+int dummy = 0;
+
+void FreeFunction() { benchmark::DoNotOptimize(dummy); }
+
+struct TrivialFunctor {
+ void operator()() const { benchmark::DoNotOptimize(dummy); }
+};
+
+struct LargeFunctor {
+ void operator()() const { benchmark::DoNotOptimize(this); }
+ std::string a, b, c;
+};
+
+template <typename Function, typename... Args>
+void ABSL_ATTRIBUTE_NOINLINE CallFunction(Function f, Args&&... args) {
+ f(std::forward<Args>(args)...);
+}
+
+template <typename Function, typename Callable, typename... Args>
+void ConstructAndCallFunctionBenchmark(benchmark::State& state,
+ const Callable& c, Args&&... args) {
+ for (auto _ : state) {
+ CallFunction<Function>(c, std::forward<Args>(args)...);
+ }
+}
+
+void BM_TrivialStdFunction(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
+ TrivialFunctor{});
+}
+BENCHMARK(BM_TrivialStdFunction);
+
+void BM_TrivialFunctionRef(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state,
+ TrivialFunctor{});
+}
+BENCHMARK(BM_TrivialFunctionRef);
+
+void BM_LargeStdFunction(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<std::function<void()>>(state,
+ LargeFunctor{});
+}
+BENCHMARK(BM_LargeStdFunction);
+
+void BM_LargeFunctionRef(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, LargeFunctor{});
+}
+BENCHMARK(BM_LargeFunctionRef);
+
+void BM_FunPtrStdFunction(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<std::function<void()>>(state, FreeFunction);
+}
+BENCHMARK(BM_FunPtrStdFunction);
+
+void BM_FunPtrFunctionRef(benchmark::State& state) {
+ ConstructAndCallFunctionBenchmark<FunctionRef<void()>>(state, FreeFunction);
+}
+BENCHMARK(BM_FunPtrFunctionRef);
+
+// Doesn't include construction or copy overhead in the loop.
+template <typename Function, typename Callable, typename... Args>
+void CallFunctionBenchmark(benchmark::State& state, const Callable& c,
+ Args... args) {
+ Function f = c;
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(&f);
+ f(args...);
+ }
+}
+
+struct FunctorWithTrivialArgs {
+ void operator()(int a, int b, int c) const {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ benchmark::DoNotOptimize(c);
+ }
+};
+
+void BM_TrivialArgsStdFunction(benchmark::State& state) {
+ CallFunctionBenchmark<std::function<void(int, int, int)>>(
+ state, FunctorWithTrivialArgs{}, 1, 2, 3);
+}
+BENCHMARK(BM_TrivialArgsStdFunction);
+
+void BM_TrivialArgsFunctionRef(benchmark::State& state) {
+ CallFunctionBenchmark<FunctionRef<void(int, int, int)>>(
+ state, FunctorWithTrivialArgs{}, 1, 2, 3);
+}
+BENCHMARK(BM_TrivialArgsFunctionRef);
+
+struct FunctorWithNonTrivialArgs {
+ void operator()(std::string a, std::string b, std::string c) const {
+ benchmark::DoNotOptimize(&a);
+ benchmark::DoNotOptimize(&b);
+ benchmark::DoNotOptimize(&c);
+ }
+};
+
+void BM_NonTrivialArgsStdFunction(benchmark::State& state) {
+ std::string a, b, c;
+ CallFunctionBenchmark<
+ std::function<void(std::string, std::string, std::string)>>(
+ state, FunctorWithNonTrivialArgs{}, a, b, c);
+}
+BENCHMARK(BM_NonTrivialArgsStdFunction);
+
+void BM_NonTrivialArgsFunctionRef(benchmark::State& state) {
+ std::string a, b, c;
+ CallFunctionBenchmark<
+ FunctionRef<void(std::string, std::string, std::string)>>(
+ state, FunctorWithNonTrivialArgs{}, a, b, c);
+}
+BENCHMARK(BM_NonTrivialArgsFunctionRef);
+
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_test.cc
new file mode 100644
index 00000000000..3aa59745873
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/function_ref_test.cc
@@ -0,0 +1,257 @@
+// 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.
+
+#include "absl/functional/function_ref.h"
+
+#include <memory>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/container/internal/test_instance_tracker.h"
+#include "absl/memory/memory.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+void RunFun(FunctionRef<void()> f) { f(); }
+
+TEST(FunctionRefTest, Lambda) {
+ bool ran = false;
+ RunFun([&] { ran = true; });
+ EXPECT_TRUE(ran);
+}
+
+int Function() { return 1337; }
+
+TEST(FunctionRefTest, Function1) {
+ FunctionRef<int()> ref(&Function);
+ EXPECT_EQ(1337, ref());
+}
+
+TEST(FunctionRefTest, Function2) {
+ FunctionRef<int()> ref(Function);
+ EXPECT_EQ(1337, ref());
+}
+
+int NoExceptFunction() noexcept { return 1337; }
+
+// TODO(jdennett): Add a test for noexcept member functions.
+TEST(FunctionRefTest, NoExceptFunction) {
+ FunctionRef<int()> ref(NoExceptFunction);
+ EXPECT_EQ(1337, ref());
+}
+
+TEST(FunctionRefTest, ForwardsArgs) {
+ auto l = [](std::unique_ptr<int> i) { return *i; };
+ FunctionRef<int(std::unique_ptr<int>)> ref(l);
+ EXPECT_EQ(42, ref(absl::make_unique<int>(42)));
+}
+
+TEST(FunctionRef, ReturnMoveOnly) {
+ auto l = [] { return absl::make_unique<int>(29); };
+ FunctionRef<std::unique_ptr<int>()> ref(l);
+ EXPECT_EQ(29, *ref());
+}
+
+TEST(FunctionRef, ManyArgs) {
+ auto l = [](int a, int b, int c) { return a + b + c; };
+ FunctionRef<int(int, int, int)> ref(l);
+ EXPECT_EQ(6, ref(1, 2, 3));
+}
+
+TEST(FunctionRef, VoidResultFromNonVoidFunctor) {
+ bool ran = false;
+ auto l = [&]() -> int {
+ ran = true;
+ return 2;
+ };
+ FunctionRef<void()> ref(l);
+ ref();
+ EXPECT_TRUE(ran);
+}
+
+TEST(FunctionRef, CastFromDerived) {
+ struct Base {};
+ struct Derived : public Base {};
+
+ Derived d;
+ auto l1 = [&](Base* b) { EXPECT_EQ(&d, b); };
+ FunctionRef<void(Derived*)> ref1(l1);
+ ref1(&d);
+
+ auto l2 = [&]() -> Derived* { return &d; };
+ FunctionRef<Base*()> ref2(l2);
+ EXPECT_EQ(&d, ref2());
+}
+
+TEST(FunctionRef, VoidResultFromNonVoidFuncton) {
+ FunctionRef<void()> ref(Function);
+ ref();
+}
+
+TEST(FunctionRef, MemberPtr) {
+ struct S {
+ int i;
+ };
+
+ S s{1100111};
+ auto mem_ptr = &S::i;
+ FunctionRef<int(const S& s)> ref(mem_ptr);
+ EXPECT_EQ(1100111, ref(s));
+}
+
+TEST(FunctionRef, MemberFun) {
+ struct S {
+ int i;
+ int get_i() const { return i; }
+ };
+
+ S s{22};
+ auto mem_fun_ptr = &S::get_i;
+ FunctionRef<int(const S& s)> ref(mem_fun_ptr);
+ EXPECT_EQ(22, ref(s));
+}
+
+TEST(FunctionRef, MemberFunRefqualified) {
+ struct S {
+ int i;
+ int get_i() && { return i; }
+ };
+ auto mem_fun_ptr = &S::get_i;
+ S s{22};
+ FunctionRef<int(S && s)> ref(mem_fun_ptr);
+ EXPECT_EQ(22, ref(std::move(s)));
+}
+
+#if !defined(_WIN32) && defined(GTEST_HAS_DEATH_TEST)
+
+TEST(FunctionRef, MemberFunRefqualifiedNull) {
+ struct S {
+ int i;
+ int get_i() && { return i; }
+ };
+ auto mem_fun_ptr = &S::get_i;
+ mem_fun_ptr = nullptr;
+ EXPECT_DEBUG_DEATH({ FunctionRef<int(S && s)> ref(mem_fun_ptr); }, "");
+}
+
+TEST(FunctionRef, NullMemberPtrAssertFails) {
+ struct S {
+ int i;
+ };
+ using MemberPtr = int S::*;
+ MemberPtr mem_ptr = nullptr;
+ EXPECT_DEBUG_DEATH({ FunctionRef<int(const S& s)> ref(mem_ptr); }, "");
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValue) {
+ absl::test_internal::InstanceTracker tracker;
+ absl::test_internal::CopyableMovableInstance instance(0);
+ auto l = [](absl::test_internal::CopyableMovableInstance) {};
+ FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+ ref(instance);
+ EXPECT_EQ(tracker.copies(), 1);
+ EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByRef) {
+ absl::test_internal::InstanceTracker tracker;
+ absl::test_internal::CopyableMovableInstance instance(0);
+ auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
+ FunctionRef<void(const absl::test_internal::CopyableMovableInstance&)> ref(l);
+ ref(instance);
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 0);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValueCallByMove) {
+ absl::test_internal::InstanceTracker tracker;
+ absl::test_internal::CopyableMovableInstance instance(0);
+ auto l = [](absl::test_internal::CopyableMovableInstance) {};
+ FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+ ref(std::move(instance));
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 2);
+}
+
+TEST(FunctionRef, CopiesAndMovesPerPassByValueToRef) {
+ absl::test_internal::InstanceTracker tracker;
+ absl::test_internal::CopyableMovableInstance instance(0);
+ auto l = [](const absl::test_internal::CopyableMovableInstance&) {};
+ FunctionRef<void(absl::test_internal::CopyableMovableInstance)> ref(l);
+ ref(std::move(instance));
+ EXPECT_EQ(tracker.copies(), 0);
+ EXPECT_EQ(tracker.moves(), 1);
+}
+
+TEST(FunctionRef, PassByValueTypes) {
+ using absl::functional_internal::Invoker;
+ using absl::functional_internal::VoidPtr;
+ using absl::test_internal::CopyableMovableInstance;
+ struct Trivial {
+ void* p[2];
+ };
+ struct LargeTrivial {
+ void* p[3];
+ };
+
+ static_assert(std::is_same<Invoker<void, int>, void (*)(VoidPtr, int)>::value,
+ "Scalar types should be passed by value");
+ static_assert(
+ std::is_same<Invoker<void, Trivial>, void (*)(VoidPtr, Trivial)>::value,
+ "Small trivial types should be passed by value");
+ static_assert(std::is_same<Invoker<void, LargeTrivial>,
+ void (*)(VoidPtr, LargeTrivial &&)>::value,
+ "Large trivial types should be passed by rvalue reference");
+ static_assert(
+ std::is_same<Invoker<void, CopyableMovableInstance>,
+ void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
+ "Types with copy/move ctor should be passed by rvalue reference");
+
+ // References are passed as references.
+ static_assert(
+ std::is_same<Invoker<void, int&>, void (*)(VoidPtr, int&)>::value,
+ "Reference types should be preserved");
+ static_assert(
+ std::is_same<Invoker<void, CopyableMovableInstance&>,
+ void (*)(VoidPtr, CopyableMovableInstance&)>::value,
+ "Reference types should be preserved");
+ static_assert(
+ std::is_same<Invoker<void, CopyableMovableInstance&&>,
+ void (*)(VoidPtr, CopyableMovableInstance &&)>::value,
+ "Reference types should be preserved");
+
+ // Make sure the address of an object received by reference is the same as the
+ // addess of the object passed by the caller.
+ {
+ LargeTrivial obj;
+ auto test = [&obj](LargeTrivial& input) { ASSERT_EQ(&input, &obj); };
+ absl::FunctionRef<void(LargeTrivial&)> ref(test);
+ ref(obj);
+ }
+
+ {
+ Trivial obj;
+ auto test = [&obj](Trivial& input) { ASSERT_EQ(&input, &obj); };
+ absl::FunctionRef<void(Trivial&)> ref(test);
+ ref(obj);
+ }
+}
+
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/front_binder.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/front_binder.h
new file mode 100644
index 00000000000..45f52de73d2
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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(
+ absl::forward<Tuple>(bound).template get<Idx>()...,
+ absl::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_(absl::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(),
+ absl::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(),
+ absl::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>(absl::move(bound_args_), Idx(),
+ absl::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>(absl::move(bound_args_), Idx(),
+ absl::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/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/function_ref.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/function_ref.h
new file mode 100644
index 00000000000..b5bb8b430a8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/functional/internal/function_ref.h
@@ -0,0 +1,106 @@
+// 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_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
+#define ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
+
+#include <cassert>
+#include <functional>
+#include <type_traits>
+
+#include "absl/base/internal/invoke.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace functional_internal {
+
+// Like a void* that can handle function pointers as well. The standard does not
+// allow function pointers to round-trip through void*, but void(*)() is fine.
+//
+// Note: It's important that this class remains trivial and is the same size as
+// a pointer, since this allows the compiler to perform tail-call optimizations
+// when the underlying function is a callable object with a matching signature.
+union VoidPtr {
+ const void* obj;
+ void (*fun)();
+};
+
+// Chooses the best type for passing T as an argument.
+// Attempt to be close to SystemV AMD64 ABI. Objects with trivial copy ctor are
+// passed by value.
+template <typename T>
+constexpr bool PassByValue() {
+ return !std::is_lvalue_reference<T>::value &&
+ absl::is_trivially_copy_constructible<T>::value &&
+ absl::is_trivially_copy_assignable<
+ typename std::remove_cv<T>::type>::value &&
+ std::is_trivially_destructible<T>::value &&
+ sizeof(T) <= 2 * sizeof(void*);
+}
+
+template <typename T>
+struct ForwardT : std::conditional<PassByValue<T>(), T, T&&> {};
+
+// An Invoker takes a pointer to the type-erased invokable object, followed by
+// the arguments that the invokable object expects.
+//
+// Note: The order of arguments here is an optimization, since member functions
+// have an implicit "this" pointer as their first argument, putting VoidPtr
+// first allows the compiler to perform tail-call optimization in many cases.
+template <typename R, typename... Args>
+using Invoker = R (*)(VoidPtr, typename ForwardT<Args>::type...);
+
+//
+// InvokeObject and InvokeFunction provide static "Invoke" functions that can be
+// used as Invokers for objects or functions respectively.
+//
+// static_cast<R> handles the case the return type is void.
+template <typename Obj, typename R, typename... Args>
+R InvokeObject(VoidPtr ptr, typename ForwardT<Args>::type... args) {
+ auto o = static_cast<const Obj*>(ptr.obj);
+ return static_cast<R>(
+ absl::base_internal::invoke(*o, std::forward<Args>(args)...));
+}
+
+template <typename Fun, typename R, typename... Args>
+R InvokeFunction(VoidPtr ptr, typename ForwardT<Args>::type... args) {
+ auto f = reinterpret_cast<Fun>(ptr.fun);
+ return static_cast<R>(
+ absl::base_internal::invoke(f, std::forward<Args>(args)...));
+}
+
+template <typename Sig>
+void AssertNonNull(const std::function<Sig>& f) {
+ assert(f != nullptr);
+ (void)f;
+}
+
+template <typename F>
+void AssertNonNull(const F&) {}
+
+template <typename F, typename C>
+void AssertNonNull(F C::*f) {
+ assert(f != nullptr);
+ (void)f;
+}
+
+template <bool C>
+using EnableIf = typename ::std::enable_if<C, int>::type;
+
+} // namespace functional_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FUNCTIONAL_INTERNAL_FUNCTION_REF_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/BUILD.bazel
index 5f24b99977c..4b2c220fc24 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/BUILD.bazel
@@ -1,11 +1,11 @@
#
-# Copyright 2018 The Abseil Authors.
+# 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
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,15 +14,17 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "hash",
@@ -32,8 +34,11 @@ cc_library(
],
hdrs = ["hash.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":city",
+ ":wyhash",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/container:fixed_array",
@@ -50,6 +55,7 @@ cc_library(
name = "hash_testing",
testonly = 1,
hdrs = ["hash_testing.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":spy_hash_state",
"//absl/meta:type_traits",
@@ -63,23 +69,45 @@ cc_test(
name = "hash_test",
srcs = ["hash_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":hash",
":hash_testing",
+ ":spy_hash_state",
"//absl/base:core_headers",
"//absl/container:flat_hash_set",
- "//absl/hash:spy_hash_state",
"//absl/meta:type_traits",
"//absl/numeric:int128",
+ "//absl/strings:cord_test_helpers",
"@com_google_googletest//:gtest_main",
],
)
+cc_binary(
+ name = "hash_benchmark",
+ testonly = 1,
+ srcs = ["hash_benchmark.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ["benchmark"],
+ visibility = ["//visibility:private"],
+ deps = [
+ ":hash",
+ "//absl/base:core_headers",
+ "//absl/random",
+ "//absl/strings",
+ "//absl/strings:cord",
+ "//absl/strings:cord_test_helpers",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
+
cc_library(
name = "spy_hash_state",
testonly = 1,
hdrs = ["internal/spy_hash_state.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
":hash",
@@ -95,6 +123,7 @@ cc_library(
"internal/city.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:config",
"//absl/base:core_headers",
@@ -106,8 +135,36 @@ cc_test(
name = "city_test",
srcs = ["internal/city_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":city",
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "wyhash",
+ srcs = ["internal/wyhash.cc"],
+ hdrs = ["internal/wyhash.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ "//absl/base:config",
+ "//absl/base:endian",
+ "//absl/numeric:int128",
+ ],
+)
+
+cc_test(
+ name = "wyhash_test",
+ srcs = ["internal/wyhash_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":wyhash",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash.h
index 36c7c2b3b6d..5de132cac8a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -36,25 +36,37 @@
// framework by simply combining its state with the state of known, hashable
// types. Hashing of that combined state is separately done by `absl::Hash`.
//
+// One should assume that a hash algorithm is chosen randomly at the start of
+// each process. E.g., `absl::Hash<int>{}(9)` in one process and
+// `absl::Hash<int>{}(9)` in another process are likely to differ.
+//
+// `absl::Hash` is intended to strongly mix input bits with a target of passing
+// an [Avalanche Test](https://en.wikipedia.org/wiki/Avalanche_effect).
+//
// Example:
//
-// // Suppose we have a class `Circle` for which we want to add hashing
+// // Suppose we have a class `Circle` for which we want to add hashing:
// class Circle {
-// public:
-// ...
-// private:
-// std::pair<int, int> center_;
-// int radius_;
-// };
-//
-// // To add hashing support to `Circle`, we simply need to add an ordinary
-// // function `AbslHashValue()`, and return the combined hash state of the
-// // existing hash state and the class state:
+// public:
+// ...
+// private:
+// std::pair<int, int> center_;
+// int radius_;
+// };
//
+// // To add hashing support to `Circle`, we simply need to add a free
+// // (non-member) function `AbslHashValue()`, and return the combined hash
+// // state of the existing hash state and the class state. You can add such a
+// // free function using a friend declaration within the body of the class:
+// class Circle {
+// public:
+// ...
// template <typename H>
// friend H AbslHashValue(H h, const Circle& c) {
// return H::combine(std::move(h), c.center_, c.radius_);
// }
+// ...
+// };
//
// For more information, see Adding Type Support to `absl::Hash` below.
//
@@ -64,6 +76,7 @@
#include "absl/hash/internal/hash.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// `absl::Hash`
@@ -75,7 +88,6 @@ namespace absl {
// * T is an arithmetic or pointer type
// * T defines an overload for `AbslHashValue(H, const T&)` for an arbitrary
// hash state `H`.
-// - T defines a specialization of `HASH_NAMESPACE::hash<T>`
// - T defines a specialization of `std::hash<T>`
//
// `absl::Hash` intrinsically supports the following types:
@@ -88,6 +100,7 @@ namespace absl {
// * std::tuple<Ts...>, if all the Ts... are hashable
// * std::unique_ptr and std::shared_ptr
// * All string-like types including:
+// * absl::Cord
// * std::string
// * std::string_view (as well as any instance of std::basic_string that
// uses char and std::char_traits)
@@ -114,8 +127,6 @@ namespace absl {
// * Natively supported types out of the box (see above)
// * Types for which an `AbslHashValue()` overload is provided (such as
// user-defined types). See "Adding Type Support to `absl::Hash`" below.
-// * Types which define a `HASH_NAMESPACE::hash<T>` specialization (aka
-// `__gnu_cxx::hash<T>` for gcc/Clang or `stdext::hash<T>` for MSVC)
// * Types which define a `std::hash<T>` specialization
//
// The fallback to legacy hash functions exists mainly for backwards
@@ -235,7 +246,7 @@ using Hash = absl::hash_internal::Hash<T>;
// }
// private:
// virtual void HashValue(absl::HashState state) const = 0;
-// };
+// };
//
// class Impl : Interface {
// private:
@@ -243,7 +254,7 @@ using Hash = absl::hash_internal::Hash<T>;
// absl::HashState::combine(std::move(state), v1_, v2_);
// }
// int v1_;
-// string v2_;
+// std::string v2_;
// };
class HashState : public hash_internal::HashStateBase<HashState> {
public:
@@ -308,5 +319,7 @@ class HashState : public hash_internal::HashStateBase<HashState> {
void (*combine_contiguous_)(void*, const unsigned char*, size_t);
};
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_HASH_HASH_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_benchmark.cc
new file mode 100644
index 00000000000..d498ac29c0a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_benchmark.cc
@@ -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.
+
+#include <string>
+#include <type_traits>
+#include <typeindex>
+#include <utility>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/hash/hash.h"
+#include "absl/random/random.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/cord_test_helpers.h"
+#include "absl/strings/string_view.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+using absl::Hash;
+
+template <template <typename> class H, typename T>
+void RunBenchmark(benchmark::State& state, T value) {
+ H<T> h;
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(value);
+ benchmark::DoNotOptimize(h(value));
+ }
+}
+
+} // namespace
+
+template <typename T>
+using AbslHash = absl::Hash<T>;
+
+class TypeErasedInterface {
+ public:
+ virtual ~TypeErasedInterface() = default;
+
+ template <typename H>
+ friend H AbslHashValue(H state, const TypeErasedInterface& wrapper) {
+ state = H::combine(std::move(state), std::type_index(typeid(wrapper)));
+ wrapper.HashValue(absl::HashState::Create(&state));
+ return state;
+ }
+
+ private:
+ virtual void HashValue(absl::HashState state) const = 0;
+};
+
+template <typename T>
+struct TypeErasedAbslHash {
+ class Wrapper : public TypeErasedInterface {
+ public:
+ explicit Wrapper(const T& value) : value_(value) {}
+
+ private:
+ void HashValue(absl::HashState state) const override {
+ absl::HashState::combine(std::move(state), value_);
+ }
+
+ const T& value_;
+ };
+
+ size_t operator()(const T& value) {
+ return absl::Hash<Wrapper>{}(Wrapper(value));
+ }
+};
+
+template <typename FuncType>
+inline FuncType* ODRUseFunction(FuncType* ptr) {
+ volatile FuncType* dummy = ptr;
+ return dummy;
+}
+
+absl::Cord FlatCord(size_t size) {
+ absl::Cord result(std::string(size, 'a'));
+ result.Flatten();
+ return result;
+}
+
+absl::Cord FragmentedCord(size_t size) {
+ const size_t orig_size = size;
+ std::vector<std::string> chunks;
+ size_t chunk_size = std::max<size_t>(1, size / 10);
+ while (size > chunk_size) {
+ chunks.push_back(std::string(chunk_size, 'a'));
+ size -= chunk_size;
+ }
+ if (size > 0) {
+ chunks.push_back(std::string(size, 'a'));
+ }
+ absl::Cord result = absl::MakeFragmentedCord(chunks);
+ (void) orig_size;
+ assert(result.size() == orig_size);
+ return result;
+}
+
+// Generates a benchmark and a codegen method for the provided types. The
+// codegen method provides a well known entrypoint for dumping assembly.
+#define MAKE_BENCHMARK(hash, name, ...) \
+ namespace { \
+ void BM_##hash##_##name(benchmark::State& state) { \
+ RunBenchmark<hash>(state, __VA_ARGS__); \
+ } \
+ BENCHMARK(BM_##hash##_##name); \
+ } \
+ size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg); \
+ size_t Codegen##hash##name(const decltype(__VA_ARGS__)& arg) { \
+ return hash<decltype(__VA_ARGS__)>{}(arg); \
+ } \
+ bool absl_hash_test_odr_use##hash##name = \
+ ODRUseFunction(&Codegen##hash##name);
+
+MAKE_BENCHMARK(AbslHash, Int32, int32_t{});
+MAKE_BENCHMARK(AbslHash, Int64, int64_t{});
+MAKE_BENCHMARK(AbslHash, Double, 1.2);
+MAKE_BENCHMARK(AbslHash, DoubleZero, 0.0);
+MAKE_BENCHMARK(AbslHash, PairInt32Int32, std::pair<int32_t, int32_t>{});
+MAKE_BENCHMARK(AbslHash, PairInt64Int64, std::pair<int64_t, int64_t>{});
+MAKE_BENCHMARK(AbslHash, TupleInt32BoolInt64,
+ std::tuple<int32_t, bool, int64_t>{});
+MAKE_BENCHMARK(AbslHash, String_0, std::string());
+MAKE_BENCHMARK(AbslHash, String_10, std::string(10, 'a'));
+MAKE_BENCHMARK(AbslHash, String_30, std::string(30, 'a'));
+MAKE_BENCHMARK(AbslHash, String_90, std::string(90, 'a'));
+MAKE_BENCHMARK(AbslHash, String_200, std::string(200, 'a'));
+MAKE_BENCHMARK(AbslHash, String_5000, std::string(5000, 'a'));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_0, absl::Cord());
+MAKE_BENCHMARK(AbslHash, Cord_Flat_10, FlatCord(10));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_30, FlatCord(30));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_90, FlatCord(90));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_200, FlatCord(200));
+MAKE_BENCHMARK(AbslHash, Cord_Flat_5000, FlatCord(5000));
+MAKE_BENCHMARK(AbslHash, Cord_Fragmented_200, FragmentedCord(200));
+MAKE_BENCHMARK(AbslHash, Cord_Fragmented_5000, FragmentedCord(5000));
+MAKE_BENCHMARK(AbslHash, VectorInt64_10, std::vector<int64_t>(10));
+MAKE_BENCHMARK(AbslHash, VectorInt64_100, std::vector<int64_t>(100));
+MAKE_BENCHMARK(AbslHash, VectorDouble_10, std::vector<double>(10, 1.1));
+MAKE_BENCHMARK(AbslHash, VectorDouble_100, std::vector<double>(100, 1.1));
+MAKE_BENCHMARK(AbslHash, PairStringString_0,
+ std::make_pair(std::string(), std::string()));
+MAKE_BENCHMARK(AbslHash, PairStringString_10,
+ std::make_pair(std::string(10, 'a'), std::string(10, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_30,
+ std::make_pair(std::string(30, 'a'), std::string(30, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_90,
+ std::make_pair(std::string(90, 'a'), std::string(90, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_200,
+ std::make_pair(std::string(200, 'a'), std::string(200, 'b')));
+MAKE_BENCHMARK(AbslHash, PairStringString_5000,
+ std::make_pair(std::string(5000, 'a'), std::string(5000, 'b')));
+
+MAKE_BENCHMARK(TypeErasedAbslHash, Int32, int32_t{});
+MAKE_BENCHMARK(TypeErasedAbslHash, Int64, int64_t{});
+MAKE_BENCHMARK(TypeErasedAbslHash, PairInt32Int32,
+ std::pair<int32_t, int32_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, PairInt64Int64,
+ std::pair<int64_t, int64_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, TupleInt32BoolInt64,
+ std::tuple<int32_t, bool, int64_t>{});
+MAKE_BENCHMARK(TypeErasedAbslHash, String_0, std::string());
+MAKE_BENCHMARK(TypeErasedAbslHash, String_10, std::string(10, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_30, std::string(30, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_90, std::string(90, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_200, std::string(200, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, String_5000, std::string(5000, 'a'));
+MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_10,
+ std::vector<double>(10, 1.1));
+MAKE_BENCHMARK(TypeErasedAbslHash, VectorDouble_100,
+ std::vector<double>(100, 1.1));
+
+// The latency benchmark attempts to model the speed of the hash function in
+// production. When a hash function is used for hashtable lookups it is rarely
+// used to hash N items in a tight loop nor on constant sized strings. Instead,
+// after hashing there is a potential equality test plus a (usually) large
+// amount of user code. To simulate this effectively we introduce a data
+// dependency between elements we hash by using the hash of the Nth element as
+// the selector of the N+1th element to hash. This isolates the hash function
+// code much like in production. As a bonus we use the hash to generate strings
+// of size [1,N] (instead of fixed N) to disable perfect branch predictions in
+// hash function implementations.
+namespace {
+// 16kb fits in L1 cache of most CPUs we care about. Keeping memory latency low
+// will allow us to attribute most time to CPU which means more accurate
+// measurements.
+static constexpr size_t kEntropySize = 16 << 10;
+static char entropy[kEntropySize + 1024];
+ABSL_ATTRIBUTE_UNUSED static const bool kInitialized = [] {
+ absl::BitGen gen;
+ static_assert(sizeof(entropy) % sizeof(uint64_t) == 0, "");
+ for (int i = 0; i != sizeof(entropy); i += sizeof(uint64_t)) {
+ auto rand = absl::Uniform<uint64_t>(gen);
+ memcpy(&entropy[i], &rand, sizeof(uint64_t));
+ }
+ return true;
+}();
+} // namespace
+
+template <class T>
+struct PodRand {
+ static_assert(std::is_pod<T>::value, "");
+ static_assert(kEntropySize + sizeof(T) < sizeof(entropy), "");
+
+ T Get(size_t i) const {
+ T v;
+ memcpy(&v, &entropy[i % kEntropySize], sizeof(T));
+ return v;
+ }
+};
+
+template <size_t N>
+struct StringRand {
+ static_assert(kEntropySize + N < sizeof(entropy), "");
+
+ absl::string_view Get(size_t i) const {
+ // This has a small bias towards small numbers. Because max N is ~200 this
+ // is very small and prefer to be very fast instead of absolutely accurate.
+ // Also we pass N = 2^K+1 so that mod reduces to a bitand.
+ size_t s = (i % (N - 1)) + 1;
+ return {&entropy[i % kEntropySize], s};
+ }
+};
+
+#define MAKE_LATENCY_BENCHMARK(hash, name, ...) \
+ namespace { \
+ void BM_latency_##hash##_##name(benchmark::State& state) { \
+ __VA_ARGS__ r; \
+ hash<decltype(r.Get(0))> h; \
+ size_t i = 871401241; \
+ for (auto _ : state) { \
+ benchmark::DoNotOptimize(i = h(r.Get(i))); \
+ } \
+ } \
+ BENCHMARK(BM_latency_##hash##_##name); \
+ } // namespace
+
+MAKE_LATENCY_BENCHMARK(AbslHash, Int32, PodRand<int32_t>);
+MAKE_LATENCY_BENCHMARK(AbslHash, Int64, PodRand<int64_t>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String9, StringRand<9>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String33, StringRand<33>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String65, StringRand<65>);
+MAKE_LATENCY_BENCHMARK(AbslHash, String257, StringRand<257>);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_test.cc
index 7b6fb2e7ac1..1d2e6cf0df4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/hash/hash.h"
#include <array>
+#include <bitset>
#include <cstring>
#include <deque>
#include <forward_list>
@@ -41,6 +42,7 @@
#include "absl/hash/internal/spy_hash_state.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
+#include "absl/strings/cord_test_helpers.h"
namespace {
@@ -50,7 +52,7 @@ using absl::hash_internal::SpyHashState;
template <typename T>
class HashValueIntTest : public testing::Test {
};
-TYPED_TEST_CASE_P(HashValueIntTest);
+TYPED_TEST_SUITE_P(HashValueIntTest);
template <typename T>
SpyHashState SpyHash(const T& value) {
@@ -80,15 +82,528 @@ TYPED_TEST_P(HashValueIntTest, FastPath) {
}
REGISTER_TYPED_TEST_CASE_P(HashValueIntTest, BasicUsage, FastPath);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
- uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+ uint32_t, uint64_t, size_t>;
INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueIntTest, IntTypes);
+enum LegacyEnum { kValue1, kValue2, kValue3 };
+
+enum class EnumClass { kValue4, kValue5, kValue6 };
+
+TEST(HashValueTest, EnumAndBool) {
+ EXPECT_TRUE((is_hashable<LegacyEnum>::value));
+ EXPECT_TRUE((is_hashable<EnumClass>::value));
+ EXPECT_TRUE((is_hashable<bool>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ LegacyEnum::kValue1, LegacyEnum::kValue2, LegacyEnum::kValue3)));
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ EnumClass::kValue4, EnumClass::kValue5, EnumClass::kValue6)));
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(true, false)));
+}
+
+TEST(HashValueTest, FloatingPoint) {
+ EXPECT_TRUE((is_hashable<float>::value));
+ EXPECT_TRUE((is_hashable<double>::value));
+ EXPECT_TRUE((is_hashable<long double>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(42.f, 0.f, -0.f, std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity())));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(42., 0., -0., std::numeric_limits<double>::infinity(),
+ -std::numeric_limits<double>::infinity())));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ // Add some values with small exponent to test that NORMAL values also
+ // append their category.
+ .5L, 1.L, 2.L, 4.L, 42.L, 0.L, -0.L,
+ 17 * static_cast<long double>(std::numeric_limits<double>::max()),
+ std::numeric_limits<long double>::infinity(),
+ -std::numeric_limits<long double>::infinity())));
+}
+
+TEST(HashValueTest, Pointer) {
+ EXPECT_TRUE((is_hashable<int*>::value));
+
+ int i;
+ int* ptr = &i;
+ int* n = nullptr;
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(&i, ptr, nullptr, ptr + 1, n)));
+}
+
+TEST(HashValueTest, PointerAlignment) {
+ // We want to make sure that pointer alignment will not cause bits to be
+ // stuck.
+
+ constexpr size_t kTotalSize = 1 << 20;
+ std::unique_ptr<char[]> data(new char[kTotalSize]);
+ constexpr size_t kLog2NumValues = 5;
+ constexpr size_t kNumValues = 1 << kLog2NumValues;
+
+ for (size_t align = 1; align < kTotalSize / kNumValues;
+ align < 8 ? align += 1 : align < 1024 ? align += 8 : align += 32) {
+ SCOPED_TRACE(align);
+ ASSERT_LE(align * kNumValues, kTotalSize);
+
+ size_t bits_or = 0;
+ size_t bits_and = ~size_t{};
+
+ for (size_t i = 0; i < kNumValues; ++i) {
+ size_t hash = absl::Hash<void*>()(data.get() + i * align);
+ bits_or |= hash;
+ bits_and &= hash;
+ }
+
+ // Limit the scope to the bits we would be using for Swisstable.
+ constexpr size_t kMask = (1 << (kLog2NumValues + 7)) - 1;
+ size_t stuck_bits = (~bits_or | bits_and) & kMask;
+ EXPECT_EQ(stuck_bits, 0) << "0x" << std::hex << stuck_bits;
+ }
+}
+
+TEST(HashValueTest, PairAndTuple) {
+ EXPECT_TRUE((is_hashable<std::pair<int, int>>::value));
+ EXPECT_TRUE((is_hashable<std::pair<const int&, const int&>>::value));
+ EXPECT_TRUE((is_hashable<std::tuple<int&, int&>>::value));
+ EXPECT_TRUE((is_hashable<std::tuple<int&&, int&&>>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::make_pair(0, 42), std::make_pair(0, 42), std::make_pair(42, 0),
+ std::make_pair(0, 0), std::make_pair(42, 42), std::make_pair(1, 42))));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(std::make_tuple(0, 0, 0), std::make_tuple(0, 0, 42),
+ std::make_tuple(0, 23, 0), std::make_tuple(17, 0, 0),
+ std::make_tuple(42, 0, 0), std::make_tuple(3, 9, 9),
+ std::make_tuple(0, 0, -42))));
+
+ // Test that tuples of lvalue references work (so we need a few lvalues):
+ int a = 0, b = 1, c = 17, d = 23;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::tie(a, a), std::tie(a, b), std::tie(b, c), std::tie(c, d))));
+
+ // Test that tuples of rvalue references work:
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::forward_as_tuple(0, 0, 0), std::forward_as_tuple(0, 0, 42),
+ std::forward_as_tuple(0, 23, 0), std::forward_as_tuple(17, 0, 0),
+ std::forward_as_tuple(42, 0, 0), std::forward_as_tuple(3, 9, 9),
+ std::forward_as_tuple(0, 0, -42))));
+}
+
+TEST(HashValueTest, CombineContiguousWorks) {
+ std::vector<std::tuple<int>> v1 = {std::make_tuple(1), std::make_tuple(3)};
+ std::vector<std::tuple<int>> v2 = {std::make_tuple(1), std::make_tuple(2)};
+
+ auto vh1 = SpyHash(v1);
+ auto vh2 = SpyHash(v2);
+ EXPECT_NE(vh1, vh2);
+}
+
+struct DummyDeleter {
+ template <typename T>
+ void operator() (T* ptr) {}
+};
+
+struct SmartPointerEq {
+ template <typename T, typename U>
+ bool operator()(const T& t, const U& u) const {
+ return GetPtr(t) == GetPtr(u);
+ }
+
+ template <typename T>
+ static auto GetPtr(const T& t) -> decltype(&*t) {
+ return t ? &*t : nullptr;
+ }
+
+ static std::nullptr_t GetPtr(std::nullptr_t) { return nullptr; }
+};
+
+TEST(HashValueTest, SmartPointers) {
+ EXPECT_TRUE((is_hashable<std::unique_ptr<int>>::value));
+ EXPECT_TRUE((is_hashable<std::unique_ptr<int, DummyDeleter>>::value));
+ EXPECT_TRUE((is_hashable<std::shared_ptr<int>>::value));
+
+ int i, j;
+ std::unique_ptr<int, DummyDeleter> unique1(&i);
+ std::unique_ptr<int, DummyDeleter> unique2(&i);
+ std::unique_ptr<int, DummyDeleter> unique_other(&j);
+ std::unique_ptr<int, DummyDeleter> unique_null;
+
+ std::shared_ptr<int> shared1(&i, DummyDeleter());
+ std::shared_ptr<int> shared2(&i, DummyDeleter());
+ std::shared_ptr<int> shared_other(&j, DummyDeleter());
+ std::shared_ptr<int> shared_null;
+
+ // Sanity check of the Eq function.
+ ASSERT_TRUE(SmartPointerEq{}(unique1, shared1));
+ ASSERT_FALSE(SmartPointerEq{}(unique1, shared_other));
+ ASSERT_TRUE(SmartPointerEq{}(unique_null, nullptr));
+ ASSERT_FALSE(SmartPointerEq{}(shared2, nullptr));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::forward_as_tuple(&i, nullptr, //
+ unique1, unique2, unique_null, //
+ absl::make_unique<int>(), //
+ shared1, shared2, shared_null, //
+ std::make_shared<int>()),
+ SmartPointerEq{}));
+}
+
+TEST(HashValueTest, FunctionPointer) {
+ using Func = int (*)();
+ EXPECT_TRUE(is_hashable<Func>::value);
+
+ Func p1 = [] { return 2; }, p2 = [] { return 1; };
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(p1, p2, nullptr)));
+}
+
+struct WrapInTuple {
+ template <typename T>
+ std::tuple<int, T, size_t> operator()(const T& t) const {
+ return std::make_tuple(7, t, 0xdeadbeef);
+ }
+};
+
+absl::Cord FlatCord(absl::string_view sv) {
+ absl::Cord c(sv);
+ c.Flatten();
+ return c;
+}
+
+absl::Cord FragmentedCord(absl::string_view sv) {
+ if (sv.size() < 2) {
+ return absl::Cord(sv);
+ }
+ size_t halfway = sv.size() / 2;
+ std::vector<absl::string_view> parts = {sv.substr(0, halfway),
+ sv.substr(halfway)};
+ return absl::MakeFragmentedCord(parts);
+}
+
+TEST(HashValueTest, Strings) {
+ EXPECT_TRUE((is_hashable<std::string>::value));
+
+ const std::string small = "foo";
+ const std::string dup = "foofoo";
+ const std::string large = std::string(2048, 'x'); // multiple of chunk size
+ const std::string huge = std::string(5000, 'a'); // not a multiple
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( //
+ std::string(), absl::string_view(), absl::Cord(), //
+ std::string(""), absl::string_view(""), absl::Cord(""), //
+ std::string(small), absl::string_view(small), absl::Cord(small), //
+ std::string(dup), absl::string_view(dup), absl::Cord(dup), //
+ std::string(large), absl::string_view(large), absl::Cord(large), //
+ std::string(huge), absl::string_view(huge), FlatCord(huge), //
+ FragmentedCord(huge))));
+
+ // Also check that nested types maintain the same hash.
+ const WrapInTuple t{};
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple( //
+ t(std::string()), t(absl::string_view()), t(absl::Cord()), //
+ t(std::string("")), t(absl::string_view("")), t(absl::Cord("")), //
+ t(std::string(small)), t(absl::string_view(small)), //
+ t(absl::Cord(small)), //
+ t(std::string(dup)), t(absl::string_view(dup)), t(absl::Cord(dup)), //
+ t(std::string(large)), t(absl::string_view(large)), //
+ t(absl::Cord(large)), //
+ t(std::string(huge)), t(absl::string_view(huge)), //
+ t(FlatCord(huge)), t(FragmentedCord(huge)))));
+
+ // Make sure that hashing a `const char*` does not use its string-value.
+ EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
+ SpyHash(absl::string_view("ABC")));
+}
+
+TEST(HashValueTest, WString) {
+ EXPECT_TRUE((is_hashable<std::wstring>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::wstring(), std::wstring(L"ABC"), std::wstring(L"ABC"),
+ std::wstring(L"Some other different string"),
+ std::wstring(L"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U16String) {
+ EXPECT_TRUE((is_hashable<std::u16string>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::u16string(), std::u16string(u"ABC"), std::u16string(u"ABC"),
+ std::u16string(u"Some other different string"),
+ std::u16string(u"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, U32String) {
+ EXPECT_TRUE((is_hashable<std::u32string>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::u32string(), std::u32string(U"ABC"), std::u32string(U"ABC"),
+ std::u32string(U"Some other different string"),
+ std::u32string(U"Iñtërnâtiônàlizætiøn"))));
+}
+
+TEST(HashValueTest, StdArray) {
+ EXPECT_TRUE((is_hashable<std::array<int, 3>>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(std::array<int, 3>{}, std::array<int, 3>{{0, 23, 42}})));
+}
+
+TEST(HashValueTest, StdBitset) {
+ EXPECT_TRUE((is_hashable<std::bitset<257>>::value));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ {std::bitset<2>("00"), std::bitset<2>("01"), std::bitset<2>("10"),
+ std::bitset<2>("11")}));
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ {std::bitset<5>("10101"), std::bitset<5>("10001"), std::bitset<5>()}));
+
+ constexpr int kNumBits = 256;
+ std::array<std::string, 6> bit_strings;
+ bit_strings.fill(std::string(kNumBits, '1'));
+ bit_strings[1][0] = '0';
+ bit_strings[2][1] = '0';
+ bit_strings[3][kNumBits / 3] = '0';
+ bit_strings[4][kNumBits - 2] = '0';
+ bit_strings[5][kNumBits - 1] = '0';
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ {std::bitset<kNumBits>(bit_strings[0].c_str()),
+ std::bitset<kNumBits>(bit_strings[1].c_str()),
+ std::bitset<kNumBits>(bit_strings[2].c_str()),
+ std::bitset<kNumBits>(bit_strings[3].c_str()),
+ std::bitset<kNumBits>(bit_strings[4].c_str()),
+ std::bitset<kNumBits>(bit_strings[5].c_str())}));
+} // namespace
+
+template <typename T>
+class HashValueSequenceTest : public testing::Test {
+};
+TYPED_TEST_SUITE_P(HashValueSequenceTest);
+
+TYPED_TEST_P(HashValueSequenceTest, BasicUsage) {
+ EXPECT_TRUE((is_hashable<TypeParam>::value));
+
+ using ValueType = typename TypeParam::value_type;
+ auto a = static_cast<ValueType>(0);
+ auto b = static_cast<ValueType>(23);
+ auto c = static_cast<ValueType>(42);
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(TypeParam(), TypeParam{}, TypeParam{a, b, c},
+ TypeParam{a, b}, TypeParam{b, c})));
+}
+
+REGISTER_TYPED_TEST_CASE_P(HashValueSequenceTest, BasicUsage);
+using IntSequenceTypes =
+ testing::Types<std::deque<int>, std::forward_list<int>, std::list<int>,
+ std::vector<int>, std::vector<bool>, std::set<int>,
+ std::multiset<int>>;
+INSTANTIATE_TYPED_TEST_CASE_P(My, HashValueSequenceTest, IntSequenceTypes);
+
+// Private type that only supports AbslHashValue to make sure our chosen hash
+// implementation is recursive within absl::Hash.
+// It uses std::abs() on the value to provide different bitwise representations
+// of the same logical value.
+struct Private {
+ int i;
+ template <typename H>
+ friend H AbslHashValue(H h, Private p) {
+ return H::combine(std::move(h), std::abs(p.i));
+ }
+
+ friend bool operator==(Private a, Private b) {
+ return std::abs(a.i) == std::abs(b.i);
+ }
+
+ friend std::ostream& operator<<(std::ostream& o, Private p) {
+ return o << p.i;
+ }
+};
+
+// Test helper for combine_piecewise_buffer. It holds a string_view to the
+// buffer-to-be-hashed. Its AbslHashValue specialization will split up its
+// contents at the character offsets requested.
+class PiecewiseHashTester {
+ public:
+ // Create a hash view of a buffer to be hashed contiguously.
+ explicit PiecewiseHashTester(absl::string_view buf)
+ : buf_(buf), piecewise_(false), split_locations_() {}
+
+ // Create a hash view of a buffer to be hashed piecewise, with breaks at the
+ // given locations.
+ PiecewiseHashTester(absl::string_view buf, std::set<size_t> split_locations)
+ : buf_(buf),
+ piecewise_(true),
+ split_locations_(std::move(split_locations)) {}
+
+ template <typename H>
+ friend H AbslHashValue(H h, const PiecewiseHashTester& p) {
+ if (!p.piecewise_) {
+ return H::combine_contiguous(std::move(h), p.buf_.data(), p.buf_.size());
+ }
+ absl::hash_internal::PiecewiseCombiner combiner;
+ if (p.split_locations_.empty()) {
+ h = combiner.add_buffer(std::move(h), p.buf_.data(), p.buf_.size());
+ return combiner.finalize(std::move(h));
+ }
+ size_t begin = 0;
+ for (size_t next : p.split_locations_) {
+ absl::string_view chunk = p.buf_.substr(begin, next - begin);
+ h = combiner.add_buffer(std::move(h), chunk.data(), chunk.size());
+ begin = next;
+ }
+ absl::string_view last_chunk = p.buf_.substr(begin);
+ if (!last_chunk.empty()) {
+ h = combiner.add_buffer(std::move(h), last_chunk.data(),
+ last_chunk.size());
+ }
+ return combiner.finalize(std::move(h));
+ }
+
+ private:
+ absl::string_view buf_;
+ bool piecewise_;
+ std::set<size_t> split_locations_;
+};
+
+// Dummy object that hashes as two distinct contiguous buffers, "foo" followed
+// by "bar"
+struct DummyFooBar {
+ template <typename H>
+ friend H AbslHashValue(H h, const DummyFooBar&) {
+ const char* foo = "foo";
+ const char* bar = "bar";
+ h = H::combine_contiguous(std::move(h), foo, 3);
+ h = H::combine_contiguous(std::move(h), bar, 3);
+ return h;
+ }
+};
+
+TEST(HashValueTest, CombinePiecewiseBuffer) {
+ absl::Hash<PiecewiseHashTester> hash;
+
+ // Check that hashing an empty buffer through the piecewise API works.
+ EXPECT_EQ(hash(PiecewiseHashTester("")), hash(PiecewiseHashTester("", {})));
+
+ // Similarly, small buffers should give consistent results
+ EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
+ hash(PiecewiseHashTester("foobar", {})));
+ EXPECT_EQ(hash(PiecewiseHashTester("foobar")),
+ hash(PiecewiseHashTester("foobar", {3})));
+
+ // But hashing "foobar" in pieces gives a different answer than hashing "foo"
+ // contiguously, then "bar" contiguously.
+ EXPECT_NE(hash(PiecewiseHashTester("foobar", {3})),
+ absl::Hash<DummyFooBar>()(DummyFooBar{}));
+
+ // Test hashing a large buffer incrementally, broken up in several different
+ // ways. Arrange for breaks on and near the stride boundaries to look for
+ // off-by-one errors in the implementation.
+ //
+ // This test is run on a buffer that is a multiple of the stride size, and one
+ // that isn't.
+ for (size_t big_buffer_size : {1024 * 2 + 512, 1024 * 3}) {
+ SCOPED_TRACE(big_buffer_size);
+ std::string big_buffer;
+ for (int i = 0; i < big_buffer_size; ++i) {
+ // Arbitrary string
+ big_buffer.push_back(32 + (i * (i / 3)) % 64);
+ }
+ auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
+
+ const int possible_breaks = 9;
+ size_t breaks[possible_breaks] = {1, 512, 1023, 1024, 1025,
+ 1536, 2047, 2048, 2049};
+ for (unsigned test_mask = 0; test_mask < (1u << possible_breaks);
+ ++test_mask) {
+ SCOPED_TRACE(test_mask);
+ std::set<size_t> break_locations;
+ for (int j = 0; j < possible_breaks; ++j) {
+ if (test_mask & (1u << j)) {
+ break_locations.insert(breaks[j]);
+ }
+ }
+ EXPECT_EQ(
+ hash(PiecewiseHashTester(big_buffer, std::move(break_locations))),
+ big_buffer_hash);
+ }
+ }
+}
+
+TEST(HashValueTest, PrivateSanity) {
+ // Sanity check that Private is working as the tests below expect it to work.
+ EXPECT_TRUE(is_hashable<Private>::value);
+ EXPECT_NE(SpyHash(Private{0}), SpyHash(Private{1}));
+ EXPECT_EQ(SpyHash(Private{1}), SpyHash(Private{1}));
+}
+
+TEST(HashValueTest, Optional) {
+ EXPECT_TRUE(is_hashable<absl::optional<Private>>::value);
+
+ using O = absl::optional<Private>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(O{}, O{{1}}, O{{-1}}, O{{10}})));
+}
+
+TEST(HashValueTest, Variant) {
+ using V = absl::variant<Private, std::string>;
+ EXPECT_TRUE(is_hashable<V>::value);
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ V(Private{1}), V(Private{-1}), V(Private{2}), V("ABC"), V("BCD"))));
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+ struct S {};
+ EXPECT_FALSE(is_hashable<absl::variant<S>>::value);
+#endif
+}
+
+TEST(HashValueTest, Maps) {
+ EXPECT_TRUE((is_hashable<std::map<int, std::string>>::value));
+
+ using M = std::map<int, std::string>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ M{}, M{{0, "foo"}}, M{{1, "foo"}}, M{{0, "bar"}}, M{{1, "bar"}},
+ M{{0, "foo"}, {42, "bar"}}, M{{1, "foo"}, {42, "bar"}},
+ M{{1, "foo"}, {43, "bar"}}, M{{1, "foo"}, {43, "baz"}})));
+
+ using MM = std::multimap<int, std::string>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ MM{}, MM{{0, "foo"}}, MM{{1, "foo"}}, MM{{0, "bar"}}, MM{{1, "bar"}},
+ MM{{0, "foo"}, {0, "bar"}}, MM{{0, "bar"}, {0, "foo"}},
+ MM{{0, "foo"}, {42, "bar"}}, MM{{1, "foo"}, {42, "bar"}},
+ MM{{1, "foo"}, {1, "foo"}, {43, "bar"}}, MM{{1, "foo"}, {43, "baz"}})));
+}
+
+TEST(HashValueTest, ReferenceWrapper) {
+ EXPECT_TRUE(is_hashable<std::reference_wrapper<Private>>::value);
+
+ Private p1{1}, p10{10};
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ p1, p10, std::ref(p1), std::ref(p10), std::cref(p1), std::cref(p10))));
+
+ EXPECT_TRUE(is_hashable<std::reference_wrapper<int>>::value);
+ int one = 1, ten = 10;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ one, ten, std::ref(one), std::ref(ten), std::cref(one), std::cref(ten))));
+
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ std::make_tuple(std::tuple<std::reference_wrapper<int>>(std::ref(one)),
+ std::tuple<std::reference_wrapper<int>>(std::ref(ten)),
+ std::tuple<int>(one), std::tuple<int>(ten))));
+}
+
template <typename T, typename = void>
-struct IsHashCallble : std::false_type {};
+struct IsHashCallable : std::false_type {};
template <typename T>
-struct IsHashCallble<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(
+struct IsHashCallable<T, absl::void_t<decltype(std::declval<absl::Hash<T>>()(
std::declval<const T&>()))>> : std::true_type {};
template <typename T, typename = void>
@@ -105,10 +620,11 @@ TEST(IsHashableTest, ValidHash) {
EXPECT_TRUE(std::is_move_constructible<absl::Hash<int>>::value);
EXPECT_TRUE(absl::is_copy_assignable<absl::Hash<int>>::value);
EXPECT_TRUE(absl::is_move_assignable<absl::Hash<int>>::value);
- EXPECT_TRUE(IsHashCallble<int>::value);
+ EXPECT_TRUE(IsHashCallable<int>::value);
EXPECT_TRUE(IsAggregateInitializable<absl::Hash<int>>::value);
}
-#if ABSL_HASH_INTERNAL_CAN_POISON_ && !defined(__APPLE__)
+
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
TEST(IsHashableTest, PoisonHash) {
struct X {};
EXPECT_FALSE((is_hashable<X>::value));
@@ -117,10 +633,13 @@ TEST(IsHashableTest, PoisonHash) {
EXPECT_FALSE(std::is_move_constructible<absl::Hash<X>>::value);
EXPECT_FALSE(absl::is_copy_assignable<absl::Hash<X>>::value);
EXPECT_FALSE(absl::is_move_assignable<absl::Hash<X>>::value);
- EXPECT_FALSE(IsHashCallble<X>::value);
+ EXPECT_FALSE(IsHashCallable<X>::value);
+#if !defined(__GNUC__) || __GNUC__ < 9
+ // This doesn't compile on GCC 9.
EXPECT_FALSE(IsAggregateInitializable<absl::Hash<X>>::value);
+#endif
}
-#endif // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
// Hashable types
//
@@ -129,7 +648,7 @@ TEST(IsHashableTest, PoisonHash) {
struct NoOp {
template <typename HashCode>
friend HashCode AbslHashValue(HashCode h, NoOp n) {
- return std::move(h);
+ return h;
}
};
@@ -159,8 +678,16 @@ struct CombineVariadic {
Int(4));
}
};
+enum class InvokeTag {
+ kUniquelyRepresented,
+ kHashValue,
+#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ kLegacyHash,
+#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ kStdHash,
+ kNone
+};
-using InvokeTag = absl::hash_internal::InvokeHashTag;
template <InvokeTag T>
using InvokeTagConstant = std::integral_constant<InvokeTag, T>;
@@ -175,6 +702,7 @@ struct MinTag<a> : InvokeTagConstant<a> {};
template <InvokeTag... Tags>
struct CustomHashType {
+ explicit CustomHashType(size_t val) : value(val) {}
size_t value;
};
@@ -195,6 +723,7 @@ H AbslHashValue(H state, CustomHashType<Tags...> t) {
} // namespace
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
template <InvokeTag... Tags>
struct is_uniquely_represented<
@@ -202,6 +731,7 @@ struct is_uniquely_represented<
typename EnableIfContained<InvokeTag::kUniquelyRepresented, Tags...>::type>
: std::true_type {};
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
@@ -241,17 +771,17 @@ void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>, T...) {
EXPECT_TRUE(is_hashable<const type&>());
const size_t offset = static_cast<int>(std::min({T::value...}));
- EXPECT_EQ(SpyHash(type{7}), SpyHash(size_t{7 + offset}));
+ EXPECT_EQ(SpyHash(type(7)), SpyHash(size_t{7 + offset}));
}
void TestCustomHashType(InvokeTagConstant<InvokeTag::kNone>) {
-#if ABSL_HASH_INTERNAL_CAN_POISON_
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
// is_hashable is false if we don't support any of the hooks.
using type = CustomHashType<>;
EXPECT_FALSE(is_hashable<type>());
EXPECT_FALSE(is_hashable<const type>());
EXPECT_FALSE(is_hashable<const type&>());
-#endif // ABSL_HASH_INTERNAL_CAN_POISON_
+#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
}
template <InvokeTag Tag, typename... T>
@@ -273,7 +803,7 @@ TEST(HashTest, NoOpsAreEquivalent) {
template <typename T>
class HashIntTest : public testing::Test {
};
-TYPED_TEST_CASE_P(HashIntTest);
+TYPED_TEST_SUITE_P(HashIntTest);
TYPED_TEST_P(HashIntTest, BasicUsage) {
EXPECT_NE(Hash<NoOp>()({}), Hash<TypeParam>()(0));
@@ -289,8 +819,8 @@ TYPED_TEST_P(HashIntTest, BasicUsage) {
}
REGISTER_TYPED_TEST_CASE_P(HashIntTest, BasicUsage);
-using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t, uint32_t,
- uint64_t, size_t>;
+using IntTypes = testing::Types<unsigned char, char, int, int32_t, int64_t,
+ uint32_t, uint64_t, size_t>;
INSTANTIATE_TYPED_TEST_CASE_P(My, HashIntTest, IntTypes);
struct StructWithPadding {
@@ -352,7 +882,8 @@ TEST(HashTest, HashNonUniquelyRepresentedType) {
}
TEST(HashTest, StandardHashContainerUsage) {
- std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"}, { 42, "bar" }};
+ std::unordered_map<int, std::string, Hash<int>> map = {{0, "foo"},
+ {42, "bar"}};
EXPECT_NE(map.find(0), map.end());
EXPECT_EQ(map.find(1), map.end());
@@ -422,4 +953,24 @@ TEST(HashTest, TypeErased) {
SpyHash(std::make_pair(size_t{7}, 17)));
}
+struct ValueWithBoolConversion {
+ operator bool() const { return false; }
+ int i;
+};
+
+} // namespace
+namespace std {
+template <>
+struct hash<ValueWithBoolConversion> {
+ size_t operator()(ValueWithBoolConversion v) { return v.i; }
+};
+} // namespace std
+
+namespace {
+
+TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
+ EXPECT_NE(absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{0}),
+ absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_testing.h
index 52bcb55a20f..1e1c5741491 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_testing.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/hash_testing.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,6 +28,7 @@
#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.
@@ -190,7 +191,9 @@ VerifyTypeImplementsAbslHashCorrectly(const Container& values, Eq equals) {
struct Info {
const V& value;
size_t index;
- std::string ToString() const { return absl::visit(PrintVisitor{index}, value); }
+ std::string ToString() const {
+ return absl::visit(PrintVisitor{index}, value);
+ }
SpyHashState expand() const { return absl::visit(ExpandVisitor{}, value); }
};
@@ -369,6 +372,7 @@ VerifyTypeImplementsAbslHashCorrectly(std::initializer_list<T> values,
equals);
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HASH_HASH_TESTING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.cc
index 122906fab04..5460134e576 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,6 +30,7 @@
#include "absl/base/optimization.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
#ifdef ABSL_IS_BIG_ENDIAN
@@ -199,10 +200,6 @@ static uint64_t Rotate(uint64_t val, int shift) {
static uint64_t ShiftMix(uint64_t val) { return val ^ (val >> 47); }
-static uint64_t HashLen16(uint64_t u, uint64_t v) {
- return Hash128to64(uint128(u, v));
-}
-
static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
// Murmur-inspired hashing.
uint64_t a = (u ^ v) * mul;
@@ -213,6 +210,11 @@ static uint64_t HashLen16(uint64_t u, uint64_t v, uint64_t mul) {
return b;
}
+static uint64_t HashLen16(uint64_t u, uint64_t v) {
+ const uint64_t kMul = 0x9ddfea08eb382d69ULL;
+ return HashLen16(u, v, kMul);
+}
+
static uint64_t HashLen0to16(const char *s, size_t len) {
if (len >= 8) {
uint64_t mul = k2 + len * 2;
@@ -252,9 +254,8 @@ static uint64_t HashLen17to32(const char *s, size_t len) {
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(uint64_t w, uint64_t x,
- uint64_t y, uint64_t z,
- uint64_t a, uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
+ uint64_t w, uint64_t x, uint64_t y, uint64_t z, uint64_t a, uint64_t b) {
a += w;
b = Rotate(b + a + z, 21);
uint64_t c = a;
@@ -265,8 +266,9 @@ static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(uint64_t w, uint64_t
}
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
-static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s, uint64_t a,
- uint64_t b) {
+static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(const char *s,
+ uint64_t a,
+ uint64_t b) {
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16),
Fetch64(s + 24), a, b);
}
@@ -309,8 +311,10 @@ uint64_t CityHash64(const char *s, size_t len) {
uint64_t x = Fetch64(s + len - 40);
uint64_t y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
uint64_t z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
- std::pair<uint64_t, uint64_t> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
- std::pair<uint64_t, uint64_t> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
+ std::pair<uint64_t, uint64_t> v =
+ WeakHashLen32WithSeeds(s + len - 64, len, z);
+ std::pair<uint64_t, uint64_t> w =
+ WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -336,9 +340,10 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed) {
}
uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
- uint64_t seed1) {
+ uint64_t seed1) {
return HashLen16(CityHash64(s, len) - seed0, seed1);
}
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.h
index 16df5563548..393da0b95d9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-// http://code.google.com/p/cityhash/
+// https://code.google.com/p/cityhash/
//
// This file provides a few functions for hashing strings. All of them are
// high-quality functions in the sense that they pass standard tests such
@@ -47,17 +47,15 @@
#include <stdint.h>
#include <stdlib.h> // for size_t.
+
#include <utility>
+#include "absl/base/config.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
-typedef std::pair<uint64_t, uint64_t> uint128;
-
-inline uint64_t Uint128Low64(const uint128 &x) { return x.first; }
-inline uint64_t Uint128High64(const uint128 &x) { return x.second; }
-
// Hash function for a byte array.
uint64_t CityHash64(const char *s, size_t len);
@@ -68,25 +66,13 @@ uint64_t CityHash64WithSeed(const char *s, size_t len, uint64_t seed);
// Hash function for a byte array. For convenience, two seeds are also
// hashed into the result.
uint64_t CityHash64WithSeeds(const char *s, size_t len, uint64_t seed0,
- uint64_t seed1);
+ uint64_t seed1);
// Hash function for a byte array. Most useful in 32-bit binaries.
uint32_t CityHash32(const char *s, size_t len);
-// Hash 128 input bits down to 64 bits of output.
-// This is intended to be a reasonably good hash function.
-inline uint64_t Hash128to64(const uint128 &x) {
- // Murmur-inspired hashing.
- const uint64_t kMul = 0x9ddfea08eb382d69ULL;
- uint64_t a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul;
- a ^= (a >> 47);
- uint64_t b = (Uint128High64(x) ^ a) * kMul;
- b ^= (b >> 47);
- b *= kMul;
- return b;
-}
-
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HASH_INTERNAL_CITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city_test.cc
index 0427cd1afb7..251d381d73e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/city_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,7 @@
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
static const uint64_t k0 = 0xc3a5c85c97cb3127ULL;
@@ -590,4 +591,5 @@ TEST(CityHashTest, Unchanging) {
}
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.cc
index 4bf64096e7e..1433eb9db34 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,9 +15,56 @@
#include "absl/hash/internal/hash.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
-ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed;
+uint64_t HashState::CombineLargeContiguousImpl32(uint64_t state,
+ const unsigned char* first,
+ size_t len) {
+ while (len >= PiecewiseChunkSize()) {
+ state =
+ Mix(state, absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first),
+ PiecewiseChunkSize()));
+ len -= PiecewiseChunkSize();
+ first += PiecewiseChunkSize();
+ }
+ // Handle the remainder.
+ return CombineContiguousImpl(state, first, len,
+ std::integral_constant<int, 4>{});
+}
+
+uint64_t HashState::CombineLargeContiguousImpl64(uint64_t state,
+ const unsigned char* first,
+ size_t len) {
+ while (len >= PiecewiseChunkSize()) {
+ state = Mix(state, Hash64(first, PiecewiseChunkSize()));
+ len -= PiecewiseChunkSize();
+ first += PiecewiseChunkSize();
+ }
+ // Handle the remainder.
+ return CombineContiguousImpl(state, first, len,
+ std::integral_constant<int, 8>{});
+}
+
+ABSL_CONST_INIT const void* const HashState::kSeed = &kSeed;
+
+// The salt array used by Wyhash. This array is NOT the mechanism used to make
+// absl::Hash non-deterministic between program invocations. See `Seed()` for
+// that mechanism.
+//
+// Any random values are fine. These values are just digits from the decimal
+// part of pi.
+// https://en.wikipedia.org/wiki/Nothing-up-my-sleeve_number
+constexpr uint64_t kWyhashSalt[5] = {
+ uint64_t{0x243F6A8885A308D3}, uint64_t{0x13198A2E03707344},
+ uint64_t{0xA4093822299F31D0}, uint64_t{0x082EFA98EC4E6C89},
+ uint64_t{0x452821E638D01377},
+};
+
+uint64_t HashState::WyhashImpl(const unsigned char* data, size_t len) {
+ return Wyhash(data, len, Seed(), kWyhashSalt);
+}
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.h
index 6c00f35413d..7fb0af0b969 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/hash.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -38,9 +38,11 @@
#include <utility>
#include <vector>
-#include "absl/base/internal/endian.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/unaligned_access.h"
#include "absl/base/port.h"
#include "absl/container/fixed_array.h"
+#include "absl/hash/internal/wyhash.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
@@ -50,8 +52,68 @@
#include "absl/hash/internal/city.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
+// Internal detail: Large buffers are hashed in smaller chunks. This function
+// returns the size of these chunks.
+constexpr size_t PiecewiseChunkSize() { return 1024; }
+
+// PiecewiseCombiner
+//
+// PiecewiseCombiner is an internal-only helper class for hashing a piecewise
+// buffer of `char` or `unsigned char` as though it were contiguous. This class
+// provides two methods:
+//
+// H add_buffer(state, data, size)
+// H finalize(state)
+//
+// `add_buffer` can be called zero or more times, followed by a single call to
+// `finalize`. This will produce the same hash expansion as concatenating each
+// buffer piece into a single contiguous buffer, and passing this to
+// `H::combine_contiguous`.
+//
+// Example usage:
+// PiecewiseCombiner combiner;
+// for (const auto& piece : pieces) {
+// state = combiner.add_buffer(std::move(state), piece.data, piece.size);
+// }
+// return combiner.finalize(std::move(state));
+class PiecewiseCombiner {
+ public:
+ PiecewiseCombiner() : position_(0) {}
+ PiecewiseCombiner(const PiecewiseCombiner&) = delete;
+ PiecewiseCombiner& operator=(const PiecewiseCombiner&) = delete;
+
+ // PiecewiseCombiner::add_buffer()
+ //
+ // Appends the given range of bytes to the sequence to be hashed, which may
+ // modify the provided hash state.
+ template <typename H>
+ H add_buffer(H state, const unsigned char* data, size_t size);
+ template <typename H>
+ H add_buffer(H state, const char* data, size_t size) {
+ return add_buffer(std::move(state),
+ reinterpret_cast<const unsigned char*>(data), size);
+ }
+
+ // PiecewiseCombiner::finalize()
+ //
+ // Finishes combining the hash sequence, which may may modify the provided
+ // hash state.
+ //
+ // Once finalize() is called, add_buffer() may no longer be called. The
+ // resulting hash state will be the same as if the pieces passed to
+ // add_buffer() were concatenated into a single flat buffer, and then provided
+ // to H::combine_contiguous().
+ template <typename H>
+ H finalize(H state);
+
+ private:
+ unsigned char buf_[PiecewiseChunkSize()];
+ size_t position_;
+};
+
// HashStateBase
//
// A hash state object represents an intermediate state in the computation
@@ -68,7 +130,7 @@ namespace hash_internal {
//
// `static H combine_contiguous(H state, const unsigned char*, size_t)`.
//
-// `HashStateBase` will provide a complete implementations for a hash state
+// `HashStateBase` will provide a complete implementation for a hash state
// object in terms of this method.
//
// Example:
@@ -117,6 +179,8 @@ class HashStateBase {
// for-loop instead.
template <typename T>
static H combine_contiguous(H state, const T* data, size_t size);
+
+ using AbslInternalPiecewiseCombiner = PiecewiseCombiner;
};
// is_uniquely_represented
@@ -221,7 +285,9 @@ typename std::enable_if<std::is_enum<Enum>::value, H>::type AbslHashValue(
}
// AbslHashValue() for hashing floating-point values
template <typename H, typename Float>
-typename std::enable_if<std::is_floating_point<Float>::value, H>::type
+typename std::enable_if<std::is_same<Float, float>::value ||
+ std::is_same<Float, double>::value,
+ H>::type
AbslHashValue(H hash_state, Float value) {
return hash_internal::hash_bytes(std::move(hash_state),
value == 0 ? 0 : value);
@@ -231,8 +297,9 @@ AbslHashValue(H hash_state, Float value) {
// For example, in x86 sizeof(long double)==16 but it only really uses 80-bits
// of it. This means we can't use hash_bytes on a long double and have to
// convert it to something else first.
-template <typename H>
-H AbslHashValue(H hash_state, long double value) {
+template <typename H, typename LongDouble>
+typename std::enable_if<std::is_same<LongDouble, long double>::value, H>::type
+AbslHashValue(H hash_state, LongDouble value) {
const int category = std::fpclassify(value);
switch (category) {
case FP_INFINITE:
@@ -264,7 +331,12 @@ H AbslHashValue(H hash_state, long double value) {
// AbslHashValue() for hashing pointers
template <typename H, typename T>
H AbslHashValue(H hash_state, T* ptr) {
- return hash_internal::hash_bytes(std::move(hash_state), ptr);
+ auto v = reinterpret_cast<uintptr_t>(ptr);
+ // Due to alignment, pointers tend to have low bits as zero, and the next few
+ // bits follow a pattern since they are also multiples of some base value.
+ // Mixing the pointer twice helps prevent stuck low bits for certain alignment
+ // values.
+ return H::combine(std::move(hash_state), v, v);
}
// AbslHashValue() for hashing nullptr_t
@@ -340,6 +412,7 @@ H AbslHashValue(H hash_state, const std::shared_ptr<T>& ptr) {
// All the string-like types supported here provide the same hash expansion for
// the same character sequence. These types are:
//
+// - `absl::Cord`
// - `std::string` (and std::basic_string<char, std::char_traits<char>, A> for
// any allocator A)
// - `absl::string_view` and `std::string_view`
@@ -355,6 +428,19 @@ H AbslHashValue(H hash_state, absl::string_view str) {
str.size());
}
+// Support std::wstring, std::u16string and std::u32string.
+template <typename Char, typename Alloc, typename H,
+ typename = absl::enable_if_t<std::is_same<Char, wchar_t>::value ||
+ std::is_same<Char, char16_t>::value ||
+ std::is_same<Char, char32_t>::value>>
+H AbslHashValue(
+ H hash_state,
+ const std::basic_string<Char, std::char_traits<Char>, Alloc>& str) {
+ return H::combine(
+ H::combine_contiguous(std::move(hash_state), str.data(), str.size()),
+ str.size());
+}
+
// -----------------------------------------------------------------------------
// AbslHashValue for Sequence Containers
// -----------------------------------------------------------------------------
@@ -467,6 +553,13 @@ typename std::enable_if<is_hashable<Key>::value, H>::type AbslHashValue(
// AbslHashValue for Wrapper Types
// -----------------------------------------------------------------------------
+// AbslHashValue for hashing std::reference_wrapper
+template <typename H, typename T>
+typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
+ H hash_state, std::reference_wrapper<T> opt) {
+ return H::combine(std::move(hash_state), opt.get());
+}
+
// AbslHashValue for hashing absl::optional
template <typename H, typename T>
typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
@@ -527,53 +620,22 @@ hash_range_or_bytes(H hash_state, const T* data, size_t size) {
return hash_state;
}
-// InvokeHashTag
-//
-// InvokeHash(H, const T&) invokes the appropriate hash implementation for a
-// hasher of type `H` and a value of type `T`. If `T` is not hashable, there
-// will be no matching overload of InvokeHash().
-// Note: Some platforms (eg MSVC) do not support the detect idiom on
-// std::hash. In those platforms the last fallback will be std::hash and
-// InvokeHash() will always have a valid overload even if std::hash<T> is not
-// valid.
-//
-// We try the following options in order:
-// * If is_uniquely_represented, hash bytes directly.
-// * ADL AbslHashValue(H, const T&) call.
-// * std::hash<T>
-
-// In MSVC we can't probe std::hash or stdext::hash because it triggers a
-// static_assert instead of failing substitution.
-#if defined(_MSC_VER)
-#define ABSL_HASH_INTERNAL_CAN_POISON_ 0
-#else // _MSC_VER
-#define ABSL_HASH_INTERNAL_CAN_POISON_ 1
-#endif // _MSC_VER
-
#if defined(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE) && \
- ABSL_HASH_INTERNAL_CAN_POISON_
+ ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 1
#else
#define ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_ 0
#endif
-enum class InvokeHashTag {
- kUniquelyRepresented,
- kHashValue,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- kLegacyHash,
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- kStdHash,
- kNone
-};
-
// HashSelect
//
// Type trait to select the appropriate hash implementation to use.
-// HashSelect<T>::value is an instance of InvokeHashTag that indicates the best
-// available hashing mechanism.
-// See `Note` above about MSVC.
-template <typename T>
+// HashSelect::type<T> will give the proper hash implementation, to be invoked
+// as:
+// HashSelect::type<T>::Invoke(state, value)
+// Also, HashSelect::type<T>::value is a boolean equal to `true` if there is a
+// valid `Invoke` function. Types that are not hashable will have a ::value of
+// `false`.
struct HashSelect {
private:
struct State : HashStateBase<State> {
@@ -582,98 +644,78 @@ struct HashSelect {
using State::HashStateBase::combine_contiguous;
};
- // `Probe<V, Tag>::value` evaluates to `V<T>::value` if it is a valid
- // expression, and `false` otherwise.
- // `Probe<V, Tag>::tag` always evaluates to `Tag`.
- template <template <typename> class V, InvokeHashTag Tag>
- struct Probe {
- private:
- template <typename U, typename std::enable_if<V<U>::value, int>::type = 0>
- static std::true_type Test(int);
- template <typename U>
- static std::false_type Test(char);
-
- public:
- static constexpr InvokeHashTag kTag = Tag;
- static constexpr bool value = decltype(
- Test<absl::remove_const_t<absl::remove_reference_t<T>>>(0))::value;
+ struct UniquelyRepresentedProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value)
+ -> absl::enable_if_t<is_uniquely_represented<T>::value, H> {
+ return hash_internal::hash_bytes(std::move(state), value);
+ }
};
- template <typename U>
- using ProbeUniquelyRepresented = is_uniquely_represented<U>;
-
- template <typename U>
- using ProbeHashValue =
- std::is_same<State, decltype(AbslHashValue(std::declval<State>(),
- std::declval<const U&>()))>;
+ struct HashValueProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+ std::is_same<H,
+ decltype(AbslHashValue(std::move(state), value))>::value,
+ H> {
+ return AbslHashValue(std::move(state), value);
+ }
+ };
+ struct LegacyHashProbe {
#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- template <typename U>
- using ProbeLegacyHash =
- std::is_convertible<decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<
- U>()(std::declval<const U&>())),
- size_t>;
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value) -> absl::enable_if_t<
+ std::is_convertible<
+ decltype(ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>()(value)),
+ size_t>::value,
+ H> {
+ return hash_internal::hash_bytes(
+ std::move(state),
+ ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
+ }
#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
+ };
+
+ struct StdHashProbe {
+ template <typename H, typename T>
+ static auto Invoke(H state, const T& value)
+ -> absl::enable_if_t<type_traits_internal::IsHashable<T>::value, H> {
+ return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
+ }
+ };
- template <typename U>
- using ProbeStdHash =
-#if ABSL_HASH_INTERNAL_CAN_POISON_
- std::is_convertible<decltype(std::hash<U>()(std::declval<const U&>())),
- size_t>;
-#else // ABSL_HASH_INTERNAL_CAN_POISON_
- std::true_type;
-#endif // ABSL_HASH_INTERNAL_CAN_POISON_
+ template <typename Hash, typename T>
+ struct Probe : Hash {
+ private:
+ template <typename H, typename = decltype(H::Invoke(
+ std::declval<State>(), std::declval<const T&>()))>
+ static std::true_type Test(int);
+ template <typename U>
+ static std::false_type Test(char);
- template <typename U>
- using ProbeNone = std::true_type;
+ public:
+ static constexpr bool value = decltype(Test<Hash>(0))::value;
+ };
public:
// Probe each implementation in order.
- // disjunction provides short circuting wrt instantiation.
- static constexpr InvokeHashTag value = absl::disjunction<
- Probe<ProbeUniquelyRepresented, InvokeHashTag::kUniquelyRepresented>,
- Probe<ProbeHashValue, InvokeHashTag::kHashValue>,
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- Probe<ProbeLegacyHash, InvokeHashTag::kLegacyHash>,
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
- Probe<ProbeStdHash, InvokeHashTag::kStdHash>,
- Probe<ProbeNone, InvokeHashTag::kNone>>::kTag;
+ // disjunction provides short circuiting wrt instantiation.
+ template <typename T>
+ using Apply = absl::disjunction< //
+ Probe<UniquelyRepresentedProbe, T>, //
+ Probe<HashValueProbe, T>, //
+ Probe<LegacyHashProbe, T>, //
+ Probe<StdHashProbe, T>, //
+ std::false_type>;
};
template <typename T>
-struct is_hashable : std::integral_constant<bool, HashSelect<T>::value !=
- InvokeHashTag::kNone> {};
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kUniquelyRepresented,
- H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(std::move(state), value);
-}
+struct is_hashable
+ : std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kHashValue, H>
-InvokeHash(H state, const T& value) {
- return AbslHashValue(std::move(state), value);
-}
-
-#if ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kLegacyHash, H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(
- std::move(state), ABSL_INTERNAL_LEGACY_HASH_NAMESPACE::hash<T>{}(value));
-}
-#endif // ABSL_HASH_INTERNAL_SUPPORT_LEGACY_HASH_
-
-template <typename H, typename T>
-absl::enable_if_t<HashSelect<T>::value == InvokeHashTag::kStdHash, H>
-InvokeHash(H state, const T& value) {
- return hash_internal::hash_bytes(std::move(state), std::hash<T>{}(value));
-}
-
-// CityHashState
-class CityHashState : public HashStateBase<CityHashState> {
+// HashState
+class ABSL_DLL HashState : public HashStateBase<HashState> {
// absl::uint128 is not an alias or a thin wrapper around the intrinsic.
// We use the intrinsic when available to improve performance.
#ifdef ABSL_HAVE_INTRINSIC_INT128
@@ -683,7 +725,8 @@ class CityHashState : public HashStateBase<CityHashState> {
#endif // ABSL_HAVE_INTRINSIC_INT128
static constexpr uint64_t kMul =
- sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51} : uint64_t{0x9ddfea08eb382d69};
+ sizeof(size_t) == 4 ? uint64_t{0xcc9e2d51}
+ : uint64_t{0x9ddfea08eb382d69};
template <typename T>
using IntegralFastPath =
@@ -691,23 +734,22 @@ class CityHashState : public HashStateBase<CityHashState> {
public:
// Move only
- CityHashState(CityHashState&&) = default;
- CityHashState& operator=(CityHashState&&) = default;
+ HashState(HashState&&) = default;
+ HashState& operator=(HashState&&) = default;
- // CityHashState::combine_contiguous()
+ // HashState::combine_contiguous()
//
// Fundamental base case for hash recursion: mixes the given range of bytes
// into the hash state.
- static CityHashState combine_contiguous(CityHashState hash_state,
- const unsigned char* first,
- size_t size) {
- return CityHashState(
+ static HashState combine_contiguous(HashState hash_state,
+ const unsigned char* first, size_t size) {
+ return HashState(
CombineContiguousImpl(hash_state.state_, first, size,
std::integral_constant<int, sizeof(size_t)>{}));
}
- using CityHashState::HashStateBase::combine_contiguous;
+ using HashState::HashStateBase::combine_contiguous;
- // CityHashState::hash()
+ // HashState::hash()
//
// For performance reasons in non-opt mode, we specialize this for
// integral types.
@@ -719,24 +761,24 @@ class CityHashState : public HashStateBase<CityHashState> {
return static_cast<size_t>(Mix(Seed(), static_cast<uint64_t>(value)));
}
- // Overload of CityHashState::hash()
+ // Overload of HashState::hash()
template <typename T, absl::enable_if_t<!IntegralFastPath<T>::value, int> = 0>
static size_t hash(const T& value) {
- return static_cast<size_t>(combine(CityHashState{}, value).state_);
+ return static_cast<size_t>(combine(HashState{}, value).state_);
}
private:
// Invoked only once for a given argument; that plus the fact that this is
// move-only ensures that there is only one non-moved-from object.
- CityHashState() : state_(Seed()) {}
+ HashState() : state_(Seed()) {}
// Workaround for MSVC bug.
// We make the type copyable to fix the calling convention, even though we
// never actually copy it. Keep it private to not affect the public API of the
// type.
- CityHashState(const CityHashState&) = default;
+ HashState(const HashState&) = default;
- explicit CityHashState(uint64_t state) : state_(state) {}
+ explicit HashState(uint64_t state) : state_(state) {}
// Implementation of the base case for combine_contiguous where we actually
// mix the bytes into the state.
@@ -749,29 +791,68 @@ class CityHashState : public HashStateBase<CityHashState> {
static uint64_t CombineContiguousImpl(uint64_t state,
const unsigned char* first, size_t len,
std::integral_constant<int, 8>
- /* sizeof_size_t*/);
+ /* sizeof_size_t */);
+
+
+ // Slow dispatch path for calls to CombineContiguousImpl with a size argument
+ // larger than PiecewiseChunkSize(). Has the same effect as calling
+ // CombineContiguousImpl() repeatedly with the chunk stride size.
+ static uint64_t CombineLargeContiguousImpl32(uint64_t state,
+ const unsigned char* first,
+ size_t len);
+ static uint64_t CombineLargeContiguousImpl64(uint64_t state,
+ const unsigned char* first,
+ size_t len);
// Reads 9 to 16 bytes from p.
- // The first 8 bytes are in .first, the rest (zero padded) bytes are in
- // .second.
+ // The least significant 8 bytes are in .first, the rest (zero padded) bytes
+ // are in .second.
static std::pair<uint64_t, uint64_t> Read9To16(const unsigned char* p,
size_t len) {
- uint64_t high = little_endian::Load64(p + len - 8);
- return {little_endian::Load64(p), high >> (128 - len * 8)};
+ uint64_t low_mem = absl::base_internal::UnalignedLoad64(p);
+ uint64_t high_mem = absl::base_internal::UnalignedLoad64(p + len - 8);
+#ifdef ABSL_IS_LITTLE_ENDIAN
+ uint64_t most_significant = high_mem;
+ uint64_t least_significant = low_mem;
+#else
+ uint64_t most_significant = low_mem;
+ uint64_t least_significant = high_mem;
+#endif
+ return {least_significant, most_significant >> (128 - len * 8)};
}
// Reads 4 to 8 bytes from p. Zero pads to fill uint64_t.
static uint64_t Read4To8(const unsigned char* p, size_t len) {
- return (static_cast<uint64_t>(little_endian::Load32(p + len - 4))
- << (len - 4) * 8) |
- little_endian::Load32(p);
+ uint32_t low_mem = absl::base_internal::UnalignedLoad32(p);
+ uint32_t high_mem = absl::base_internal::UnalignedLoad32(p + len - 4);
+#ifdef ABSL_IS_LITTLE_ENDIAN
+ uint32_t most_significant = high_mem;
+ uint32_t least_significant = low_mem;
+#else
+ uint32_t most_significant = low_mem;
+ uint32_t least_significant = high_mem;
+#endif
+ return (static_cast<uint64_t>(most_significant) << (len - 4) * 8) |
+ least_significant;
}
// Reads 1 to 3 bytes from p. Zero pads to fill uint32_t.
static uint32_t Read1To3(const unsigned char* p, size_t len) {
- return static_cast<uint32_t>((p[0]) | //
- (p[len / 2] << (len / 2 * 8)) | //
- (p[len - 1] << ((len - 1) * 8)));
+ unsigned char mem0 = p[0];
+ unsigned char mem1 = p[len / 2];
+ unsigned char mem2 = p[len - 1];
+#ifdef ABSL_IS_LITTLE_ENDIAN
+ unsigned char significant2 = mem2;
+ unsigned char significant1 = mem1;
+ unsigned char significant0 = mem0;
+#else
+ unsigned char significant2 = mem0;
+ unsigned char significant1 = mem1;
+ unsigned char significant0 = mem2;
+#endif
+ return static_cast<uint32_t>(significant0 | //
+ (significant1 << (len / 2 * 8)) | //
+ (significant2 << ((len - 1) * 8)));
}
ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) {
@@ -786,6 +867,19 @@ class CityHashState : public HashStateBase<CityHashState> {
return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
}
+ // An extern to avoid bloat on a direct call to Wyhash() with fixed values for
+ // both the seed and salt parameters.
+ static uint64_t WyhashImpl(const unsigned char* data, size_t len);
+
+ ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Hash64(const unsigned char* data,
+ size_t len) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ return WyhashImpl(data, len);
+#else
+ return absl::hash_internal::CityHash64(reinterpret_cast<const char*>(data), len);
+#endif
+ }
+
// Seed()
//
// A non-deterministic seed.
@@ -803,21 +897,31 @@ class CityHashState : public HashStateBase<CityHashState> {
// On other platforms this is still going to be non-deterministic but most
// probably per-build and not per-process.
ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Seed() {
+#if (!defined(__clang__) || __clang_major__ > 11) && \
+ !defined(__apple_build_version__)
+ return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(&kSeed));
+#else
+ // Workaround the absence of
+ // https://github.com/llvm/llvm-project/commit/bc15bf66dcca76cc06fe71fca35b74dc4d521021.
return static_cast<uint64_t>(reinterpret_cast<uintptr_t>(kSeed));
+#endif
}
static const void* const kSeed;
uint64_t state_;
};
-// CityHashState::CombineContiguousImpl()
-inline uint64_t CityHashState::CombineContiguousImpl(
+// HashState::CombineContiguousImpl()
+inline uint64_t HashState::CombineContiguousImpl(
uint64_t state, const unsigned char* first, size_t len,
std::integral_constant<int, 4> /* sizeof_size_t */) {
// For large values we use CityHash, for small ones we just use a
// multiplicative hash.
uint64_t v;
if (len > 8) {
+ if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
+ return CombineLargeContiguousImpl32(state, first, len);
+ }
v = absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
} else if (len >= 4) {
v = Read4To8(first, len);
@@ -830,15 +934,18 @@ inline uint64_t CityHashState::CombineContiguousImpl(
return Mix(state, v);
}
-// Overload of CityHashState::CombineContiguousImpl()
-inline uint64_t CityHashState::CombineContiguousImpl(
+// Overload of HashState::CombineContiguousImpl()
+inline uint64_t HashState::CombineContiguousImpl(
uint64_t state, const unsigned char* first, size_t len,
std::integral_constant<int, 8> /* sizeof_size_t */) {
- // For large values we use CityHash, for small ones we just use a
- // multiplicative hash.
+ // For large values we use Wyhash or CityHash depending on the platform, for
+ // small ones we just use a multiplicative hash.
uint64_t v;
if (len > 16) {
- v = absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first), len);
+ if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
+ return CombineLargeContiguousImpl64(state, first, len);
+ }
+ v = Hash64(first, len);
} else if (len > 8) {
auto p = Read9To16(first, len);
state = Mix(state, p.first);
@@ -854,7 +961,6 @@ inline uint64_t CityHashState::CombineContiguousImpl(
return Mix(state, v);
}
-
struct AggregateBarrier {};
// HashImpl
@@ -870,7 +976,7 @@ struct PoisonedHash : private AggregateBarrier {
template <typename T>
struct HashImpl {
- size_t operator()(const T& value) const { return CityHashState::hash(value); }
+ size_t operator()(const T& value) const { return HashState::hash(value); }
};
template <typename T>
@@ -880,7 +986,8 @@ struct Hash
template <typename H>
template <typename T, typename... Ts>
H HashStateBase<H>::combine(H state, const T& value, const Ts&... values) {
- return H::combine(hash_internal::InvokeHash(std::move(state), value),
+ return H::combine(hash_internal::HashSelect::template Apply<T>::Invoke(
+ std::move(state), value),
values...);
}
@@ -890,7 +997,49 @@ template <typename T>
H HashStateBase<H>::combine_contiguous(H state, const T* data, size_t size) {
return hash_internal::hash_range_or_bytes(std::move(state), data, size);
}
+
+// HashStateBase::PiecewiseCombiner::add_buffer()
+template <typename H>
+H PiecewiseCombiner::add_buffer(H state, const unsigned char* data,
+ size_t size) {
+ if (position_ + size < PiecewiseChunkSize()) {
+ // This partial chunk does not fill our existing buffer
+ memcpy(buf_ + position_, data, size);
+ position_ += size;
+ return state;
+ }
+
+ // If the buffer is partially filled we need to complete the buffer
+ // and hash it.
+ if (position_ != 0) {
+ const size_t bytes_needed = PiecewiseChunkSize() - position_;
+ memcpy(buf_ + position_, data, bytes_needed);
+ state = H::combine_contiguous(std::move(state), buf_, PiecewiseChunkSize());
+ data += bytes_needed;
+ size -= bytes_needed;
+ }
+
+ // Hash whatever chunks we can without copying
+ while (size >= PiecewiseChunkSize()) {
+ state = H::combine_contiguous(std::move(state), data, PiecewiseChunkSize());
+ data += PiecewiseChunkSize();
+ size -= PiecewiseChunkSize();
+ }
+ // Fill the buffer with the remainder
+ memcpy(buf_, data, size);
+ position_ = size;
+ return state;
+}
+
+// HashStateBase::PiecewiseCombiner::finalize()
+template <typename H>
+H PiecewiseCombiner::finalize(H state) {
+ // Hash the remainder left in the buffer, which may be empty
+ return H::combine_contiguous(std::move(state), buf_, position_);
+}
+
} // namespace hash_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_HASH_INTERNAL_HASH_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/print_hash_of.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/print_hash_of.cc
index b6df31cc5e8..c392125a69f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/print_hash_of.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/print_hash_of.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/spy_hash_state.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/spy_hash_state.h
index 03d795b0900..c0831208118 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/spy_hash_state.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/spy_hash_state.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
#include "absl/strings/str_join.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace hash_internal {
// SpyHashState is an implementation of the HashState API that simply
@@ -39,8 +40,7 @@ namespace hash_internal {
template <typename T>
class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
public:
- SpyHashStateImpl()
- : error_(std::make_shared<absl::optional<std::string>>()) {
+ SpyHashStateImpl() : error_(std::make_shared<absl::optional<std::string>>()) {
static_assert(std::is_void<T>::value, "");
}
@@ -147,6 +147,19 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
static SpyHashStateImpl combine_contiguous(SpyHashStateImpl hash_state,
const unsigned char* begin,
size_t size) {
+ const size_t large_chunk_stride = PiecewiseChunkSize();
+ if (size > large_chunk_stride) {
+ // 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;
+ }
+ }
+
hash_state.hash_representation_.emplace_back(
reinterpret_cast<const char*>(begin), size);
return hash_state;
@@ -170,7 +183,6 @@ class SpyHashStateImpl : public HashStateBase<SpyHashStateImpl<T>> {
// 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
@@ -200,7 +212,7 @@ bool RunOnStartup<f>::run = (f(), true);
template <
typename T, typename U,
// Only trigger for when (T != U),
- absl::enable_if_t<!std::is_same<T, U>::value, int> = 0,
+ 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.
@@ -213,6 +225,7 @@ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.cc
new file mode 100644
index 00000000000..642bde43452
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.cc
@@ -0,0 +1,111 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/hash/internal/wyhash.h"
+
+#include "absl/base/internal/unaligned_access.h"
+#include "absl/numeric/int128.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+static uint64_t WyhashMix(uint64_t v0, uint64_t v1) {
+ absl::uint128 p = v0;
+ p *= v1;
+ return absl::Uint128Low64(p) ^ absl::Uint128High64(p);
+}
+
+uint64_t Wyhash(const void* data, size_t len, uint64_t seed,
+ const uint64_t salt[]) {
+ const uint8_t* ptr = static_cast<const uint8_t*>(data);
+ uint64_t starting_length = static_cast<uint64_t>(len);
+ uint64_t current_state = seed ^ salt[0];
+
+ if (len > 64) {
+ // If we have more than 64 bytes, we're going to handle chunks of 64
+ // bytes at a time. We're going to build up two separate hash states
+ // which we will then hash together.
+ uint64_t duplicated_state = current_state;
+
+ do {
+ uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
+ uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
+ uint64_t c = absl::base_internal::UnalignedLoad64(ptr + 16);
+ uint64_t d = absl::base_internal::UnalignedLoad64(ptr + 24);
+ uint64_t e = absl::base_internal::UnalignedLoad64(ptr + 32);
+ uint64_t f = absl::base_internal::UnalignedLoad64(ptr + 40);
+ uint64_t g = absl::base_internal::UnalignedLoad64(ptr + 48);
+ uint64_t h = absl::base_internal::UnalignedLoad64(ptr + 56);
+
+ uint64_t cs0 = WyhashMix(a ^ salt[1], b ^ current_state);
+ uint64_t cs1 = WyhashMix(c ^ salt[2], d ^ current_state);
+ current_state = (cs0 ^ cs1);
+
+ uint64_t ds0 = WyhashMix(e ^ salt[3], f ^ duplicated_state);
+ uint64_t ds1 = WyhashMix(g ^ salt[4], h ^ duplicated_state);
+ duplicated_state = (ds0 ^ ds1);
+
+ ptr += 64;
+ len -= 64;
+ } while (len > 64);
+
+ current_state = current_state ^ duplicated_state;
+ }
+
+ // We now have a data `ptr` with at most 64 bytes and the current state
+ // of the hashing state machine stored in current_state.
+ while (len > 16) {
+ uint64_t a = absl::base_internal::UnalignedLoad64(ptr);
+ uint64_t b = absl::base_internal::UnalignedLoad64(ptr + 8);
+
+ current_state = WyhashMix(a ^ salt[1], b ^ current_state);
+
+ ptr += 16;
+ len -= 16;
+ }
+
+ // We now have a data `ptr` with at most 16 bytes.
+ uint64_t a = 0;
+ uint64_t b = 0;
+ if (len > 8) {
+ // When we have at least 9 and at most 16 bytes, set A to the first 64
+ // bits of the input and B to the last 64 bits of the input. Yes, they will
+ // overlap in the middle if we are working with less than the full 16
+ // bytes.
+ a = absl::base_internal::UnalignedLoad64(ptr);
+ b = absl::base_internal::UnalignedLoad64(ptr + len - 8);
+ } else if (len > 3) {
+ // If we have at least 4 and at most 8 bytes, set A to the first 32
+ // bits and B to the last 32 bits.
+ a = absl::base_internal::UnalignedLoad32(ptr);
+ b = absl::base_internal::UnalignedLoad32(ptr + len - 4);
+ } else if (len > 0) {
+ // If we have at least 1 and at most 3 bytes, read all of the provided
+ // bits into A, with some adjustments.
+ a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]);
+ b = 0;
+ } else {
+ a = 0;
+ b = 0;
+ }
+
+ uint64_t w = WyhashMix(a ^ salt[1], b ^ current_state);
+ uint64_t z = salt[1] ^ starting_length;
+ return WyhashMix(w, z);
+}
+
+} // namespace hash_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.h
new file mode 100644
index 00000000000..4aff4e931a0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash.h
@@ -0,0 +1,48 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// This file provides the Google-internal implementation of the Wyhash
+// algorithm.
+//
+// Wyhash is a fast hash function for hash tables, the fastest we've currently
+// (late 2020) found that passes the SMHasher tests. The algorithm relies on
+// intrinsic 128-bit multiplication for speed. This is not meant to be secure -
+// just fast.
+
+#ifndef ABSL_HASH_INTERNAL_WYHASH_H_
+#define ABSL_HASH_INTERNAL_WYHASH_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace hash_internal {
+
+// Hash function for a byte array. A 64-bit seed and a set of five 64-bit
+// integers are hashed into the result.
+//
+// To allow all hashable types (including string_view and Span) to depend on
+// this algoritm, we keep the API low-level, with as few dependencies as
+// possible.
+uint64_t Wyhash(const void* data, size_t len, uint64_t seed,
+ const uint64_t salt[5]);
+
+} // namespace hash_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_HASH_INTERNAL_WYHASH_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash_test.cc
new file mode 100644
index 00000000000..9fb06d23d76
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/hash/internal/wyhash_test.cc
@@ -0,0 +1,486 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/hash/internal/wyhash.h"
+
+#include "absl/strings/escaping.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+static const uint64_t kCurrentSeed = 0;
+static const uint64_t kSalt[5] = {0xa0761d6478bd642f, 0xe7037ed1a0b428dbl,
+ 0x8ebc6af09c88c6e3, 0x589965cc75374cc3l,
+ 0x1d8e4e27c47d124f};
+
+// Note: We don't account for endianness, so the values here are only correct if
+// you're also running on a little endian platform.
+
+TEST(WyhashTest, EmptyString) {
+ const std::string s = "";
+ EXPECT_EQ(
+ absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+ 4808886099364463827);
+}
+
+TEST(WyhashTest, Spaces) {
+ const std::string s = " ";
+ EXPECT_EQ(
+ absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+ 1686201463024549249);
+}
+
+TEST(WyhashTest, RepeatingString) {
+ const std::string s = "aaaa";
+ EXPECT_EQ(
+ absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+ 6646112255271966632);
+}
+
+TEST(WyhashTest, HexString) {
+ const std::string small = "\x01\x02\x03";
+ const std::string med = "\x01\x02\x03\x04";
+
+ EXPECT_EQ(absl::hash_internal::Wyhash(small.c_str(), small.length(),
+ kCurrentSeed, kSalt),
+ 11989428023081740911ULL);
+ EXPECT_EQ(absl::hash_internal::Wyhash(med.c_str(), med.length(), kCurrentSeed,
+ kSalt),
+ 9765997711188871556ULL);
+}
+
+TEST(WyhashTest, Words) {
+ const std::string s = "third_party|wyhash|64";
+ EXPECT_EQ(
+ absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+ 3702018632387611330);
+}
+
+TEST(WyhashTest, LongString) {
+ const std::string s =
+ "AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz"
+ "0123456789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOp"
+ "QrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789AbCdEf"
+ "GhIjKlMnOpQrStUvWxYz0123456789AbCdEfGhIjKlMnOpQrStUvWxYz012345"
+ "6789AbCdEfGhIjKlMnOpQrStUvWxYz0123456789";
+
+ EXPECT_EQ(
+ absl::hash_internal::Wyhash(s.c_str(), s.length(), kCurrentSeed, kSalt),
+ 9245411362605796064ULL);
+}
+
+TEST(WyhashTest, BigReference) {
+ struct ExpectedResult {
+ absl::string_view base64_data;
+ uint64_t seed;
+ uint64_t hash;
+ } expected_results[] = {
+ {"", uint64_t{0xec42b7ab404b8acb}, uint64_t{0xe5a40d39ab796423}},
+ {"Zw==", uint64_t{0xeeee074043a3ee0f}, uint64_t{0xa6564b468248c683}},
+ {"xmk=", uint64_t{0x857902089c393de}, uint64_t{0xef192f401b116e1c}},
+ {"c1H/", uint64_t{0x993df040024ca3af}, uint64_t{0xbe8dc0c54617639d}},
+ {"SuwpzQ==", uint64_t{0xc4e4c2acea740e96}, uint64_t{0x93d7f665b5521c8e}},
+ {"uqvy++M=", uint64_t{0x6a214b3db872d0cf}, uint64_t{0x646d70bb42445f28}},
+ {"RnzCVPgb", uint64_t{0x44343db6a89dba4d}, uint64_t{0x96a7b1e3cc9bd426}},
+ {"6OeNdlouYw==", uint64_t{0x77b5d6d1ae1dd483},
+ uint64_t{0x76020289ab0790c4}},
+ {"M5/JmmYyDbc=", uint64_t{0x89ab8ecb44d221f1},
+ uint64_t{0x39f842e4133b9b44}},
+ {"MVijWiVdBRdY", uint64_t{0x60244b17577ca81b},
+ uint64_t{0x2b8d7047be4bcaab}},
+ {"6V7Uq7LNxpu0VA==", uint64_t{0x59a08dcee0717067},
+ uint64_t{0x99628abef6716a97}},
+ {"EQ6CdEEhPdyHcOk=", uint64_t{0xf5f20db3ade57396},
+ uint64_t{0x4432e02ba42b2740}},
+ {"PqFB4fxnPgF+l+rc", uint64_t{0xbf8dee0751ad3efb},
+ uint64_t{0x74d810efcad7918a}},
+ {"a5aPOFwq7LA7+zKvPA==", uint64_t{0x6b7a06b268d63e30},
+ uint64_t{0x88c84e986002507f}},
+ {"VOwY21wCGv5D+/qqOvs=", uint64_t{0xb8c37f0ae0f54c82},
+ uint64_t{0x4f99acf193cf39b9}},
+ {"KdHmBTx8lHXYvmGJ+Vy7", uint64_t{0x9fcbed0c38e50eef},
+ uint64_t{0xd90e7a3655891e37}},
+ {"qJkPlbHr8bMF7/cA6aE65Q==", uint64_t{0x2af4bade1d8e3a1d},
+ uint64_t{0x3bb378b1d4df8fcf}},
+ {"ygvL0EhHZL0fIx6oHHtkxRQ=", uint64_t{0x714e3aa912da2f2c},
+ uint64_t{0xf78e94045c052d47}},
+ {"c1rFXkt5YztwZCQRngncqtSs", uint64_t{0xf5ee75e3cbb82c1c},
+ uint64_t{0x26da0b2130da6b40}},
+ {"8hsQrzszzeNQSEcVXLtvIhm6mw==", uint64_t{0x620e7007321b93b9},
+ uint64_t{0x30b4d426af8c6986}},
+ {"ffUL4RocfyP4KfikGxO1yk7omDI=", uint64_t{0xc08528cac2e551fc},
+ uint64_t{0x5413b4aaf3baaeae}},
+ {"OOB5TT00vF9Od/rLbAWshiErqhpV", uint64_t{0x6a1debf9cc3ad39},
+ uint64_t{0x756ab265370a1597}},
+ {"or5wtXM7BFzTNpSzr+Lw5J5PMhVJ/Q==", uint64_t{0x7e0a3c88111fc226},
+ uint64_t{0xdaf5f4b7d09814fb}},
+ {"gk6pCHDUsoopVEiaCrzVDhioRKxb844=", uint64_t{0x1301fef15df39edb},
+ uint64_t{0x8f874ae37742b75e}},
+ {"TNctmwlC5QbEM6/No4R/La3UdkfeMhzs", uint64_t{0x64e181f3d5817ab},
+ uint64_t{0x8fecd03956121ce8}},
+ {"SsQw9iAjhWz7sgcE9OwLuSC6hsM+BfHs2Q==", uint64_t{0xafafc44961078ecb},
+ uint64_t{0x229c292ea7a08285}},
+ {"ZzO3mVCj4xTT2TT3XqDyEKj2BZQBvrS8RHg=", uint64_t{0x4f7bb45549250094},
+ uint64_t{0xbb4bf0692d14bae}},
+ {"+klp5iPQGtppan5MflEls0iEUzqU+zGZkDJX", uint64_t{0xa30061abaa2818c},
+ uint64_t{0x207b24ca3bdac1db}},
+ {"RO6bvOnlJc8I9eniXlNgqtKy0IX6VNg16NRmgg==", uint64_t{0xd902ee3e44a5705f},
+ uint64_t{0x64f6cd6745d3825b}},
+ {"ZJjZqId1ZXBaij9igClE3nyliU5XWdNRrayGlYA=", uint64_t{0x316d36da516f583},
+ uint64_t{0xa2b2e1656b58df1e}},
+ {"7BfkhfGMDGbxfMB8uyL85GbaYQtjr2K8g7RpLzr/", uint64_t{0x402d83f9f834f616},
+ uint64_t{0xd01d30d9ee7a148}},
+ {"rycWk6wHH7htETQtje9PidS2YzXBx+Qkg2fY7ZYS7A==",
+ uint64_t{0x9c604164c016b72c}, uint64_t{0x1cb4cd00ab804e3b}},
+ {"RTkC2OUK+J13CdGllsH0H5WqgspsSa6QzRZouqx6pvI=",
+ uint64_t{0x3f4507e01f9e73ba}, uint64_t{0x4697f2637fd90999}},
+ {"tKjKmbLCNyrLCM9hycOAXm4DKNpM12oZ7dLTmUx5iwAi",
+ uint64_t{0xc3fe0d5be8d2c7c7}, uint64_t{0x8383a756b5688c07}},
+ {"VprUGNH+5NnNRaORxgH/ySrZFQFDL+4VAodhfBNinmn8cg==",
+ uint64_t{0x531858a40bfa7ea1}, uint64_t{0x695c29cb3696a975}},
+ {"gc1xZaY+q0nPcUvOOnWnT3bqfmT/geth/f7Dm2e/DemMfk4=",
+ uint64_t{0x86689478a7a7e8fa}, uint64_t{0xda2e5a5a5e971521}},
+ {"Mr35fIxqx1ukPAL0su1yFuzzAU3wABCLZ8+ZUFsXn47UmAph",
+ uint64_t{0x4ec948b8e7f27288}, uint64_t{0x7935d4befa056b2b}},
+ {"A9G8pw2+m7+rDtWYAdbl8tb2fT7FFo4hLi2vAsa5Y8mKH3CX3g==",
+ uint64_t{0xce46c7213c10032}, uint64_t{0x38dd541ca95420fe}},
+ {"DFaJGishGwEHDdj9ixbCoaTjz9KS0phLNWHVVdFsM93CvPft3hM=",
+ uint64_t{0xf63e96ee6f32a8b6}, uint64_t{0xcc06c7a4963f967f}},
+ {"7+Ugx+Kr3aRNgYgcUxru62YkTDt5Hqis+2po81hGBkcrJg4N0uuy",
+ uint64_t{0x1cfe85e65fc5225}, uint64_t{0xbf0f6f66e232fb20}},
+ {"H2w6O8BUKqu6Tvj2xxaecxEI2wRgIgqnTTG1WwOgDSINR13Nm4d4Vg==",
+ uint64_t{0x45c474f1cee1d2e8}, uint64_t{0xf7efb32d373fe71a}},
+ {"1XBMnIbqD5jy65xTDaf6WtiwtdtQwv1dCVoqpeKj+7cTR1SaMWMyI04=",
+ uint64_t{0x6e024e14015f329c}, uint64_t{0xe2e64634b1c12660}},
+ {"znZbdXG2TSFrKHEuJc83gPncYpzXGbAebUpP0XxzH0rpe8BaMQ17nDbt",
+ uint64_t{0x760c40502103ae1c}, uint64_t{0x285b8fd1638e306d}},
+ {"ylu8Atu13j1StlcC1MRMJJXIl7USgDDS22HgVv0WQ8hx/8pNtaiKB17hCQ==",
+ uint64_t{0x17fd05c3c560c320}, uint64_t{0x658e8a4e3b714d6c}},
+ {"M6ZVVzsd7vAvbiACSYHioH/440dp4xG2mLlBnxgiqEvI/aIEGpD0Sf4VS0g=",
+ uint64_t{0x8b34200a6f8e90d9}, uint64_t{0xf391fb968e0eb398}},
+ {"li3oFSXLXI+ubUVGJ4blP6mNinGKLHWkvGruun85AhVn6iuMtocbZPVhqxzn",
+ uint64_t{0x6be89e50818bdf69}, uint64_t{0x744a9ea0cc144bf2}},
+ {"kFuQHuUCqBF3Tc3hO4dgdIp223ShaCoog48d5Do5zMqUXOh5XpGK1t5XtxnfGA==",
+ uint64_t{0xfb389773315b47d8}, uint64_t{0x12636f2be11012f1}},
+ {"jWmOad0v0QhXVJd1OdGuBZtDYYS8wBVHlvOeTQx9ZZnm8wLEItPMeihj72E0nWY=",
+ uint64_t{0x4f2512a23f61efee}, uint64_t{0x29c57de825948f80}},
+ {"z+DHU52HaOQdW4JrZwDQAebEA6rm13Zg/9lPYA3txt3NjTBqFZlOMvTRnVzRbl23",
+ uint64_t{0x59ccd92fc16c6fda}, uint64_t{0x58c6f99ab0d1c021}},
+ {"MmBiGDfYeTayyJa/tVycg+rN7f9mPDFaDc+23j0TlW9094er0ADigsl4QX7V3gG/qw==",
+ uint64_t{0x25c5a7f5bd330919}, uint64_t{0x13e7b5a7b82fe3bb}},
+ {"774RK+9rOL4iFvs1q2qpo/JVc/I39buvNjqEFDtDvyoB0FXxPI2vXqOrk08VPfIHkmU=",
+ uint64_t{0x51df4174d34c97d7}, uint64_t{0x10fbc87901e02b63}},
+ {"+slatXiQ7/2lK0BkVUI1qzNxOOLP3I1iK6OfHaoxgqT63FpzbElwEXSwdsryq3UlHK0I",
+ uint64_t{0x80ce6d76f89cb57}, uint64_t{0xa24c9184901b748b}},
+ {"64mVTbQ47dHjHlOHGS/hjJwr/"
+ "K2frCNpn87exOqMzNUVYiPKmhCbfS7vBUce5tO6Ec9osQ==",
+ uint64_t{0x20961c911965f684}, uint64_t{0xcac4fd4c5080e581}},
+ {"fIsaG1r530SFrBqaDj1kqE0AJnvvK8MNEZbII2Yw1OK77v0V59xabIh0B5axaz/"
+ "+a2V5WpA=",
+ uint64_t{0x4e5b926ec83868e7}, uint64_t{0xc38bdb7483ba68e1}},
+ {"PGih0zDEOWCYGxuHGDFu9Ivbff/"
+ "iE7BNUq65tycTR2R76TerrXALRosnzaNYO5fjFhTi+CiS",
+ uint64_t{0x3927b30b922eecef}, uint64_t{0xdb2a8069b2ceaffa}},
+ {"RnpA/"
+ "zJnEnnLjmICORByRVb9bCOgxF44p3VMiW10G7PvW7IhwsWajlP9kIwNA9FjAD2GoQHk2Q="
+ "=",
+ uint64_t{0xbd0291284a49b61c}, uint64_t{0xdf9fe91d0d1c7887}},
+ {"qFklMceaTHqJpy2qavJE+EVBiNFOi6OxjOA3LeIcBop1K7w8xQi3TrDk+"
+ "BrWPRIbfprszSaPfrI=",
+ uint64_t{0x73a77c575bcc956}, uint64_t{0xe83f49e96e2e6a08}},
+ {"cLbfUtLl3EcQmITWoTskUR8da/VafRDYF/ylPYwk7/"
+ "zazk6ssyrzxMN3mmSyvrXR2yDGNZ3WDrTT",
+ uint64_t{0x766a0e2ade6d09a6}, uint64_t{0xc69e61b62ca2b62}},
+ {"s/"
+ "Jf1+"
+ "FbsbCpXWPTUSeWyMH6e4CvTFvPE5Fs6Z8hvFITGyr0dtukHzkI84oviVLxhM1xMxrMAy1db"
+ "w==",
+ uint64_t{0x2599f4f905115869}, uint64_t{0xb4a4f3f85f8298fe}},
+ {"FvyQ00+j7nmYZVQ8hI1Edxd0AWplhTfWuFGiu34AK5X8u2hLX1bE97sZM0CmeLe+"
+ "7LgoUT1fJ/axybE=",
+ uint64_t{0xd8256e5444d21e53}, uint64_t{0x167a1b39e1e95f41}},
+ {"L8ncxMaYLBH3g9buPu8hfpWZNlOF7nvWLNv9IozH07uQsIBWSKxoPy8+"
+ "LW4tTuzC6CIWbRGRRD1sQV/4",
+ uint64_t{0xf664a91333fb8dfd}, uint64_t{0xf8a2a5649855ee41}},
+ {"CDK0meI07yrgV2kQlZZ+"
+ "wuVqhc2NmzqeLH7bmcA6kchsRWFPeVF5Wqjjaj556ABeUoUr3yBmfU3kWOakkg==",
+ uint64_t{0x9625b859be372cd1}, uint64_t{0x27992565b595c498}},
+ {"d23/vc5ONh/"
+ "HkMiq+gYk4gaCNYyuFKwUkvn46t+dfVcKfBTYykr4kdvAPNXGYLjM4u1YkAEFpJP+"
+ "nX7eOvs=",
+ uint64_t{0x7b99940782e29898}, uint64_t{0x3e08cca5b71f9346}},
+ {"NUR3SRxBkxTSbtQORJpu/GdR6b/h6sSGfsMj/KFd99ahbh+9r7LSgSGmkGVB/"
+ "mGoT0pnMTQst7Lv2q6QN6Vm",
+ uint64_t{0x4fe12fa5383b51a8}, uint64_t{0xad406b10c770a6d2}},
+ {"2BOFlcI3Z0RYDtS9T9Ie9yJoXlOdigpPeeT+CRujb/"
+ "O39Ih5LPC9hP6RQk1kYESGyaLZZi3jtabHs7DiVx/VDg==",
+ uint64_t{0xe2ccb09ac0f5b4b6}, uint64_t{0xd1713ce6e552bcf2}},
+ {"FF2HQE1FxEvWBpg6Z9zAMH+Zlqx8S1JD/"
+ "wIlViL6ZDZY63alMDrxB0GJQahmAtjlm26RGLnjW7jmgQ4Ie3I+014=",
+ uint64_t{0x7d0a37adbd7b753b}, uint64_t{0x753b287194c73ad3}},
+ {"tHmO7mqVL/PX11nZrz50Hc+M17Poj5lpnqHkEN+4bpMx/"
+ "YGbkrGOaYjoQjgmt1X2QyypK7xClFrjeWrCMdlVYtbW",
+ uint64_t{0xd3ae96ef9f7185f2}, uint64_t{0x5ae41a95f600af1c}},
+ {"/WiHi9IQcxRImsudkA/KOTqGe8/"
+ "gXkhKIHkjddv5S9hi02M049dIK3EUyAEjkjpdGLUs+BN0QzPtZqjIYPOgwsYE9g==",
+ uint64_t{0x4fb88ea63f79a0d8}, uint64_t{0x4a61163b86a8bb4c}},
+ {"qds+1ExSnU11L4fTSDz/QE90g4Jh6ioqSh3KDOTOAo2pQGL1k/"
+ "9CCC7J23YF27dUTzrWsCQA2m4epXoCc3yPHb3xElA=",
+ uint64_t{0xed564e259bb5ebe9}, uint64_t{0x42eeaa79e760c7e4}},
+ {"8FVYHx40lSQPTHheh08Oq0/"
+ "pGm2OlG8BEf8ezvAxHuGGdgCkqpXIueJBF2mQJhTfDy5NncO8ntS7vaKs7sCNdDaNGOEi",
+ uint64_t{0x3e3256b60c428000}, uint64_t{0x698df622ef465b0a}},
+ {"4ZoEIrJtstiCkeew3oRzmyJHVt/pAs2pj0HgHFrBPztbQ10NsQ/"
+ "lM6DM439QVxpznnBSiHMgMQJhER+70l72LqFTO1JiIQ==",
+ uint64_t{0xfb05bad59ec8705}, uint64_t{0x157583111e1a6026}},
+ {"hQPtaYI+wJyxXgwD5n8jGIKFKaFA/"
+ "P83KqCKZfPthnjwdOFysqEOYwAaZuaaiv4cDyi9TyS8hk5cEbNP/jrI7q6pYGBLbsM=",
+ uint64_t{0xafdc251dbf97b5f8}, uint64_t{0xaa1388f078e793e0}},
+ {"S4gpMSKzMD7CWPsSfLeYyhSpfWOntyuVZdX1xSBjiGvsspwOZcxNKCRIOqAA0moUfOh3I5+"
+ "juQV4rsqYElMD/gWfDGpsWZKQ",
+ uint64_t{0x10ec9c92ddb5dcbc}, uint64_t{0xf10d68d0f3309360}},
+ {"oswxop+"
+ "bthuDLT4j0PcoSKby4LhF47ZKg8K17xxHf74UsGCzTBbOz0MM8hQEGlyqDT1iUiAYnaPaUp"
+ "L2mRK0rcIUYA4qLt5uOw==",
+ uint64_t{0x9a767d5822c7dac4}, uint64_t{0x2af056184457a3de}},
+ {"0II/"
+ "697p+"
+ "BtLSjxj5989OXI004TogEb94VUnDzOVSgMXie72cuYRvTFNIBgtXlKfkiUjeqVpd4a+"
+ "n5bxNOD1TGrjQtzKU5r7obo=",
+ uint64_t{0xee46254080d6e2db}, uint64_t{0x6d0058e1590b2489}},
+ {"E84YZW2qipAlMPmctrg7TKlwLZ68l4L+c0xRDUfyyFrA4MAti0q9sHq3TDFviH0Y+"
+ "Kq3tEE5srWFA8LM9oomtmvm5PYxoaarWPLc",
+ uint64_t{0xbbb669588d8bf398}, uint64_t{0x638f287f68817f12}},
+ {"x3pa4HIElyZG0Nj7Vdy9IdJIR4izLmypXw5PCmZB5y68QQ4uRaVVi3UthsoJROvbjDJkP2D"
+ "Q6L/eN8pFeLFzNPKBYzcmuMOb5Ull7w==",
+ uint64_t{0xdc2afaa529beef44}, uint64_t{0xc46b71fecefd5467}},
+ {"jVDKGYIuWOP/"
+ "QKLdd2wi8B2VJA8Wh0c8PwrXJVM8FOGM3voPDVPyDJOU6QsBDPseoR8uuKd19OZ/"
+ "zAvSCB+zlf6upAsBlheUKgCfKww=",
+ uint64_t{0xf1f67391d45013a8}, uint64_t{0x2c8e94679d964e0a}},
+ {"mkquunhmYe1aR2wmUz4vcvLEcKBoe6H+kjUok9VUn2+eTSkWs4oDDtJvNCWtY5efJwg/"
+ "j4PgjRYWtqnrCkhaqJaEvkkOwVfgMIwF3e+d",
+ uint64_t{0x16fce2b8c65a3429}, uint64_t{0x8612b797ce22503a}},
+ {"fRelvKYonTQ+s+rnnvQw+JzGfFoPixtna0vzcSjiDqX5s2Kg2//"
+ "UGrK+AVCyMUhO98WoB1DDbrsOYSw2QzrcPe0+3ck9sePvb+Q/IRaHbw==",
+ uint64_t{0xf4b096699f49fe67}, uint64_t{0x59f929babfba7170}},
+ {"DUwXFJzagljo44QeJ7/"
+ "6ZKw4QXV18lhkYT2jglMr8WB3CHUU4vdsytvw6AKv42ZcG6fRkZkq9fpnmXy6xG0aO3WPT1"
+ "eHuyFirAlkW+zKtwg=",
+ uint64_t{0xca584c4bc8198682}, uint64_t{0x9527556923fb49a0}},
+ {"cYmZCrOOBBongNTr7e4nYn52uQUy2mfe48s50JXx2AZ6cRAt/"
+ "xRHJ5QbEoEJOeOHsJyM4nbzwFm++SlT6gFZZHJpkXJ92JkR86uS/eV1hJUR",
+ uint64_t{0xed269fc3818b6aad}, uint64_t{0x1039ab644f5e150b}},
+ {"EXeHBDfhwzAKFhsMcH9+2RHwV+mJaN01+9oacF6vgm8mCXRd6jeN9U2oAb0of5c5cO4i+"
+ "Vb/LlHZSMI490SnHU0bejhSCC2gsC5d2K30ER3iNA==",
+ uint64_t{0x33f253cbb8fe66a8}, uint64_t{0x7816c83f3aa05e6d}},
+ {"FzkzRYoNjkxFhZDso94IHRZaJUP61nFYrh5MwDwv9FNoJ5jyNCY/"
+ "eazPZk+tbmzDyJIGw2h3GxaWZ9bSlsol/vK98SbkMKCQ/wbfrXRLcDzdd/8=",
+ uint64_t{0xd0b76b2c1523d99c}, uint64_t{0xf51d2f564518c619}},
+ {"Re4aXISCMlYY/XsX7zkIFR04ta03u4zkL9dVbLXMa/q6hlY/CImVIIYRN3VKP4pnd0AUr/"
+ "ugkyt36JcstAInb4h9rpAGQ7GMVOgBniiMBZ/MGU7H",
+ uint64_t{0xfd28f0811a2a237f}, uint64_t{0x67d494cff03ac004}},
+ {"ueLyMcqJXX+MhO4UApylCN9WlTQ+"
+ "ltJmItgG7vFUtqs2qNwBMjmAvr5u0sAKd8jpzV0dDPTwchbIeAW5zbtkA2NABJV6hFM48ib"
+ "4/J3A5mseA3cS8w==",
+ uint64_t{0x6261fb136482e84}, uint64_t{0x2802d636ced1cfbb}},
+ {"6Si7Yi11L+jZMkwaN+GUuzXMrlvEqviEkGOilNq0h8TdQyYKuFXzkYc/"
+ "q74gP3pVCyiwz9KpVGMM9vfnq36riMHRknkmhQutxLZs5fbmOgEO69HglCU=",
+ uint64_t{0x458efc750bca7c3a}, uint64_t{0xf64e20bad771cb12}},
+ {"Q6AbOofGuTJOegPh9Clm/"
+ "9crtUMQqylKrTc1fhfJo1tqvpXxhU4k08kntL1RG7woRnFrVh2UoMrL1kjin+s9CanT+"
+ "y4hHwLqRranl9FjvxfVKm3yvg68",
+ uint64_t{0xa7e69ff84e5e7c27}, uint64_t{0xb9a6cf84a83e15e}},
+ {"ieQEbIPvqY2YfIjHnqfJiO1/MIVRk0RoaG/WWi3kFrfIGiNLCczYoklgaecHMm/"
+ "1sZ96AjO+a5stQfZbJQwS7Sc1ODABEdJKcTsxeW2hbh9A6CFzpowP1A==",
+ uint64_t{0x3c59bfd0c29efe9e}, uint64_t{0x8da6630319609301}},
+ {"zQUv8hFB3zh2GGl3KTvCmnfzE+"
+ "SUgQPVaSVIELFX5H9cE3FuVFGmymkPQZJLAyzC90Cmi8GqYCvPqTuAAB//"
+ "XTJxy4bCcVArgZG9zJXpjowpNBfr3ngWrSE=",
+ uint64_t{0x10befacc6afd298d}, uint64_t{0x40946a86e2a996f3}},
+ {"US4hcC1+op5JKGC7eIs8CUgInjKWKlvKQkapulxW262E/"
+ "B2ye79QxOexf188u2mFwwe3WTISJHRZzS61IwljqAWAWoBAqkUnW8SHmIDwHUP31J0p5sGd"
+ "P47L",
+ uint64_t{0x41d5320b0a38efa7}, uint64_t{0xcab7f5997953fa76}},
+ {"9bHUWFna2LNaGF6fQLlkx1Hkt24nrkLE2CmFdWgTQV3FFbUe747SSqYw6ebpTa07MWSpWRP"
+ "sHesVo2B9tqHbe7eQmqYebPDFnNqrhSdZwFm9arLQVs+7a3Ic6A==",
+ uint64_t{0x58db1c7450fe17f3}, uint64_t{0x39129ca0e04fc465}},
+ {"Kb3DpHRUPhtyqgs3RuXjzA08jGb59hjKTOeFt1qhoINfYyfTt2buKhD6YVffRCPsgK9SeqZ"
+ "qRPJSyaqsa0ovyq1WnWW8jI/NhvAkZTVHUrX2pC+cD3OPYT05Dag=",
+ uint64_t{0x6098c055a335b7a6}, uint64_t{0x5238221fd685e1b8}},
+ {"gzxyMJIPlU+bJBwhFUCHSofZ/"
+ "319LxqMoqnt3+L6h2U2+ZXJCSsYpE80xmR0Ta77Jq54o92SMH87HV8dGOaCTuAYF+"
+ "lDL42SY1P316Cl0sZTS2ow3ZqwGbcPNs/1",
+ uint64_t{0x1bbacec67845a801}, uint64_t{0x175130c407dbcaab}},
+ {"uR7V0TW+FGVMpsifnaBAQ3IGlr1wx5sKd7TChuqRe6OvUXTlD4hKWy8S+"
+ "8yyOw8lQabism19vOQxfmocEOW/"
+ "vzY0pEa87qHrAZy4s9fH2Bltu8vaOIe+agYohhYORQ==",
+ uint64_t{0xc419cfc7442190}, uint64_t{0x2f20e7536c0b0df}},
+ {"1UR5eoo2aCwhacjZHaCh9bkOsITp6QunUxHQ2SfeHv0imHetzt/"
+ "Z70mhyWZBalv6eAx+YfWKCUib2SHDtz/"
+ "A2dc3hqUWX5VfAV7FQsghPUAtu6IiRatq4YSLpDvKZBQ=",
+ uint64_t{0xc95e510d94ba270c}, uint64_t{0x2742cb488a04ad56}},
+ {"opubR7H63BH7OtY+Avd7QyQ25UZ8kLBdFDsBTwZlY6gA/"
+ "u+x+"
+ "czC9AaZMgmQrUy15DH7YMGsvdXnviTtI4eVI4aF1H9Rl3NXMKZgwFOsdTfdcZeeHVRzBBKX"
+ "8jUfh1il",
+ uint64_t{0xff1ae05c98089c3f}, uint64_t{0xd6afb593879ff93b}},
+ {"DC0kXcSXtfQ9FbSRwirIn5tgPri0sbzHSa78aDZVDUKCMaBGyFU6BmrulywYX8yzvwprdLs"
+ "oOwTWN2wMjHlPDqrvVHNEjnmufRDblW+nSS+xtKNs3N5xsxXdv6JXDrAB/Q==",
+ uint64_t{0x90c02b8dceced493}, uint64_t{0xf50ad64caac0ca7f}},
+ {"BXRBk+3wEP3Lpm1y75wjoz+PgB0AMzLe8tQ1AYU2/"
+ "oqrQB2YMC6W+9QDbcOfkGbeH+b7IBkt/"
+ "gwCMw2HaQsRFEsurXtcQ3YwRuPz5XNaw5NAvrNa67Fm7eRzdE1+hWLKtA8=",
+ uint64_t{0x9f8a76697ab1aa36}, uint64_t{0x2ade95c4261364ae}},
+ {"RRBSvEGYnzR9E45Aps/+WSnpCo/X7gJLO4DRnUqFrJCV/kzWlusLE/"
+ "6ZU6RoUf2ROwcgEvUiXTGjLs7ts3t9SXnJHxC1KiOzxHdYLMhVvgNd3hVSAXODpKFSkVXND"
+ "55G2L1W",
+ uint64_t{0x6ba1bf3d811a531d}, uint64_t{0x5c4f3299faacd07a}},
+ {"jeh6Qazxmdi57pa9S3XSnnZFIRrnc6s8QLrah5OX3SB/V2ErSPoEAumavzQPkdKF1/"
+ "SfvmdL+qgF1C+Yawy562QaFqwVGq7+tW0yxP8FStb56ZRgNI4IOmI30s1Ei7iops9Uuw==",
+ uint64_t{0x6a418974109c67b4}, uint64_t{0xfffe3bff0ae5e9bc}},
+ {"6QO5nnDrY2/"
+ "wrUXpltlKy2dSBcmK15fOY092CR7KxAjNfaY+"
+ "aAmtWbbzQk3MjBg03x39afSUN1fkrWACdyQKRaGxgwq6MGNxI6W+8DLWJBHzIXrntrE/"
+ "ml6fnNXEpxplWJ1vEs4=",
+ uint64_t{0x8472f1c2b3d230a3}, uint64_t{0x1db785c0005166e4}},
+ {"0oPxeEHhqhcFuwonNfLd5jF3RNATGZS6NPoS0WklnzyokbTqcl4BeBkMn07+fDQv83j/"
+ "BpGUwcWO05f3+DYzocfnizpFjLJemFGsls3gxcBYxcbqWYev51tG3lN9EvRE+X9+Pwww",
+ uint64_t{0x5e06068f884e73a7}, uint64_t{0xea000d962ad18418}},
+ {"naSBSjtOKgAOg8XVbR5cHAW3Y+QL4Pb/JO9/"
+ "oy6L08wvVRZqo0BrssMwhzBP401Um7A4ppAupbQeJFdMrysY34AuSSNvtNUy5VxjNECwiNt"
+ "gwYHw7yakDUv8WvonctmnoSPKENegQg==",
+ uint64_t{0x55290b1a8f170f59}, uint64_t{0xe42aef38359362d9}},
+ {"vPyl8DxVeRe1OpilKb9KNwpGkQRtA94UpAHetNh+"
+ "95V7nIW38v7PpzhnTWIml5kw3So1Si0TXtIUPIbsu32BNhoH7QwFvLM+"
+ "JACgSpc5e3RjsL6Qwxxi11npwxRmRUqATDeMUfRAjxg=",
+ uint64_t{0x5501cfd83dfe706a}, uint64_t{0xc8e95657348a3891}},
+ {"QC9i2GjdTMuNC1xQJ74ngKfrlA4w3o58FhvNCltdIpuMhHP1YsDA78scQPLbZ3OCUgeQguY"
+ "f/vw6zAaVKSgwtaykqg5ka/4vhz4hYqWU5ficdXqClHl+zkWEY26slCNYOM5nnDlly8Cj",
+ uint64_t{0xe43ed13d13a66990}, uint64_t{0xc162eca864f238c6}},
+ {"7CNIgQhAHX27nxI0HeB5oUTnTdgKpRDYDKwRcXfSFGP1XeT9nQF6WKCMjL1tBV6x7KuJ91G"
+ "Zz11F4c+8s+MfqEAEpd4FHzamrMNjGcjCyrVtU6y+7HscMVzr7Q/"
+ "ODLcPEFztFnwjvCjmHw==",
+ uint64_t{0xdf43bc375cf5283f}, uint64_t{0xbe1fb373e20579ad}},
+ {"Qa/hC2RPXhANSospe+gUaPfjdK/yhQvfm4cCV6/pdvCYWPv8p1kMtKOX3h5/"
+ "8oZ31fsmx4Axphu5qXJokuhZKkBUJueuMpxRyXpwSWz2wELx5glxF7CM0Fn+"
+ "OevnkhUn5jsPlG2r5jYlVn8=",
+ uint64_t{0x8112b806d288d7b5}, uint64_t{0x628a1d4f40aa6ffd}},
+ {"kUw/0z4l3a89jTwN5jpG0SHY5km/"
+ "IVhTjgM5xCiPRLncg40aqWrJ5vcF891AOq5hEpSq0bUCJUMFXgct7kvnys905HjerV7Vs1G"
+ "y84tgVJ70/2+pAZTsB/PzNOE/G6sOj4+GbTzkQu819OLB",
+ uint64_t{0xd52a18abb001cb46}, uint64_t{0xa87bdb7456340f90}},
+ {"VDdfSDbO8Tdj3T5W0XM3EI7iHh5xpIutiM6dvcJ/fhe23V/srFEkDy5iZf/"
+ "VnA9kfi2C79ENnFnbOReeuZW1b3MUXB9lgC6U4pOTuC+"
+ "jHK3Qnpyiqzj7h3ISJSuo2pob7vY6VHZo6Fn7exEqHg==",
+ uint64_t{0xe12b76a2433a1236}, uint64_t{0x5960ef3ba982c801}},
+ {"Ldfvy3ORdquM/R2fIkhH/ONi69mcP1AEJ6n/"
+ "oropwecAsLJzQSgezSY8bEiEs0VnFTBBsW+RtZY6tDj03fnb3amNUOq1b7jbqyQkL9hpl+"
+ "2Z2J8IaVSeownWl+bQcsR5/xRktIMckC5AtF4YHfU=",
+ uint64_t{0x175bf7319cf1fa00}, uint64_t{0x5026586df9a431ec}},
+ {"BrbNpb42+"
+ "VzZAjJw6QLirXzhweCVRfwlczzZ0VX2xluskwBqyfnGovz5EuX79JJ31VNXa5hTkAyQat3l"
+ "YKRADTdAdwE5PqM1N7YaMqqsqoAAAeuYVXuk5eWCykYmClNdSspegwgCuT+403JigBzi",
+ uint64_t{0xd63d57b3f67525ae}, uint64_t{0xfe4b8a20fdf0840b}},
+ {"gB3NGHJJvVcuPyF0ZSvHwnWSIfmaI7La24VMPQVoIIWF7Z74NltPZZpx2f+cocESM+"
+ "ILzQW9p+BC8x5IWz7N4Str2WLGKMdgmaBfNkEhSHQDU0IJEOnpUt0HmjhFaBlx0/"
+ "LTmhua+rQ6Wup8ezLwfg==",
+ uint64_t{0x933faea858832b73}, uint64_t{0xdcb761867da7072f}},
+ {"hTKHlRxx6Pl4gjG+6ksvvj0CWFicUg3WrPdSJypDpq91LUWRni2KF6+"
+ "81ZoHBFhEBrCdogKqeK+hy9bLDnx7g6rAFUjtn1+cWzQ2YjiOpz4+"
+ "ROBB7lnwjyTGWzJD1rXtlso1g2qVH8XJVigC5M9AIxM=",
+ uint64_t{0x53d061e5f8e7c04f}, uint64_t{0xc10d4653667275b7}},
+ {"IWQBelSQnhrr0F3BhUpXUIDauhX6f95Qp+A0diFXiUK7irwPG1oqBiqHyK/SH/"
+ "9S+"
+ "rln9DlFROAmeFdH0OCJi2tFm4afxYzJTFR4HnR4cG4x12JqHaZLQx6iiu6CE3rtWBVz99oA"
+ "wCZUOEXIsLU24o2Y",
+ uint64_t{0xdb4124556dd515e0}, uint64_t{0x727720deec13110b}},
+ {"TKo+l+"
+ "1dOXdLvIrFqeLaHdm0HZnbcdEgOoLVcGRiCbAMR0j5pIFw8D36tefckAS1RCFOH5IgP8yiF"
+ "T0Gd0a2hI3+"
+ "fTKA7iK96NekxWeoeqzJyctc6QsoiyBlkZerRxs5RplrxoeNg29kKDTM0K94mnhD9g==",
+ uint64_t{0x4fb31a0dd681ee71}, uint64_t{0x710b009662858dc9}},
+ {"YU4e7G6EfQYvxCFoCrrT0EFgVLHFfOWRTJQJ5gxM3G2b+"
+ "1kJf9YPrpsxF6Xr6nYtS8reEEbDoZJYqnlk9lXSkVArm88Cqn6d25VCx3+"
+ "49MqC0trIlXtb7SXUUhwpJK16T0hJUfPH7s5cMZXc6YmmbFuBNPE=",
+ uint64_t{0x27cc72eefa138e4c}, uint64_t{0xfbf8f7a3ecac1eb7}},
+ {"/I/"
+ "eImMwPo1U6wekNFD1Jxjk9XQVi1D+"
+ "FPdqcHifYXQuP5aScNQfxMAmaPR2XhuOQhADV5tTVbBKwCDCX4E3jcDNHzCiPvViZF1W27t"
+ "xaf2BbFQdwKrNCmrtzcluBFYu0XZfc7RU1RmxK/RtnF1qHsq/O4pp",
+ uint64_t{0x44bc2dfba4bd3ced}, uint64_t{0xb6fc4fcd0722e3df}},
+ {"CJTT9WGcY2XykTdo8KodRIA29qsqY0iHzWZRjKHb9alwyJ7RZAE3V5Juv4MY3MeYEr1EPCC"
+ "MxO7yFXqT8XA8YTjaMp3bafRt17Pw8JC4iKJ1zN+WWKOESrj+"
+ "3aluGQqn8z1EzqY4PH7rLG575PYeWsP98BugdA==",
+ uint64_t{0x242da1e3a439bed8}, uint64_t{0x7cb86dcc55104aac}},
+ {"ZlhyQwLhXQyIUEnMH/"
+ "AEW27vh9xrbNKJxpWGtrEmKhd+nFqAfbeNBQjW0SfG1YI0xQkQMHXjuTt4P/"
+ "EpZRtA47ibZDVS8TtaxwyBjuIDwqcN09eCtpC+Ls+"
+ "vWDTLmBeDM3u4hmzz4DQAYsLiZYSJcldg9Q3wszw=",
+ uint64_t{0xdc559c746e35c139}, uint64_t{0x19e71e9b45c3a51e}},
+ {"v2KU8y0sCrBghmnm8lzGJlwo6D6ObccAxCf10heoDtYLosk4ztTpLlpSFEyu23MLA1tJkcg"
+ "Rko04h19QMG0mOw/"
+ "wc93EXAweriBqXfvdaP85sZABwiKO+6rtS9pacRVpYYhHJeVTQ5NzrvBvi1huxAr+"
+ "xswhVMfL",
+ uint64_t{0xd0b0350275b9989}, uint64_t{0x51de38573c2bea48}},
+ {"QhKlnIS6BuVCTQsnoE67E/"
+ "yrgogE8EwO7xLaEGei26m0gEU4OksefJgppDh3X0x0Cs78Dr9IHK5b977CmZlrTRmwhlP8p"
+ "M+UzXPNRNIZuN3ntOum/QhUWP8SGpirheXENWsXMQ/"
+ "nxtxakyEtrNkKk471Oov9juP8oQ==",
+ uint64_t{0xb04489e41d17730c}, uint64_t{0xa73ab6996d6df158}},
+ {"/ZRMgnoRt+Uo6fUPr9FqQvKX7syhgVqWu+"
+ "WUSsiQ68UlN0efSP6Eced5gJZL6tg9gcYJIkhjuQNITU0Q3TjVAnAcobgbJikCn6qZ6pRxK"
+ "BY4MTiAlfGD3T7R7hwJwx554MAy++Zb/YUFlnCaCJiwQMnowF7aQzwYFCo=",
+ uint64_t{0x2217285eb4572156}, uint64_t{0x55ef2b8c930817b2}},
+ {"NB7tU5fNE8nI+SXGfipc7sRkhnSkUF1krjeo6k+8FITaAtdyz+"
+ "o7mONgXmGLulBPH9bEwyYhKNVY0L+njNQrZ9YC2aXsFD3PdZsxAFaBT3VXEzh+"
+ "NGBTjDASNL3mXyS8Yv1iThGfHoY7T4aR0NYGJ+k+pR6f+KrPC96M",
+ uint64_t{0x12c2e8e68aede73b}, uint64_t{0xb2850bf5fae87157}},
+ {"8T6wrqCtEO6/rwxF6lvMeyuigVOLwPipX/FULvwyu+1wa5sQGav/"
+ "2FsLHUVn6cGSi0LlFwLewGHPFJDLR0u4t7ZUyM//"
+ "x6da0sWgOa5hzDqjsVGmjxEHXiaXKW3i4iSZNuxoNbMQkIbVML+"
+ "DkYu9ND0O2swg4itGeVSzXA==",
+ uint64_t{0x4d612125bdc4fd00}, uint64_t{0xecf3de1acd04651f}},
+ {"Ntf1bMRdondtMv1CYr3G80iDJ4WSAlKy5H34XdGruQiCrnRGDBa+"
+ "eUi7vKp4gp3BBcVGl8eYSasVQQjn7MLvb3BjtXx6c/"
+ "bCL7JtpzQKaDnPr9GWRxpBXVxKREgMM7d8lm35EODv0w+"
+ "hQLfVSh8OGs7fsBb68nNWPLeeSOo=",
+ uint64_t{0x81826b553954464e}, uint64_t{0xcc0a40552559ff32}},
+ {"VsSAw72Ro6xks02kaiLuiTEIWBC5bgqr4WDnmP8vglXzAhixk7td926rm9jNimL+"
+ "kroPSygZ9gl63aF5DCPOACXmsbmhDrAQuUzoh9ZKhWgElLQsrqo1KIjWoZT5b5QfVUXY9lS"
+ "IBg3U75SqORoTPq7HalxxoIT5diWOcJQi",
+ uint64_t{0xc2e5d345dc0ddd2d}, uint64_t{0xc385c374f20315b1}},
+ {"j+loZ+C87+"
+ "bJxNVebg94gU0mSLeDulcHs84tQT7BZM2rzDSLiCNxUedHr1ZWJ9ejTiBa0dqy2I2ABc++"
+ "xzOLcv+//YfibtjKtYggC6/3rv0XCc7xu6d/"
+ "O6xO+XOBhOWAQ+IHJVHf7wZnDxIXB8AUHsnjEISKj7823biqXjyP3g==",
+ uint64_t{0x3da6830a9e32631e}, uint64_t{0xb90208a4c7234183}},
+ {"f3LlpcPElMkspNtDq5xXyWU62erEaKn7RWKlo540gR6mZsNpK1czV/"
+ "sOmqaq8XAQLEn68LKj6/"
+ "cFkJukxRzCa4OF1a7cCAXYFp9+wZDu0bw4y63qbpjhdCl8GO6Z2lkcXy7KOzbPE01ukg7+"
+ "gN+7uKpoohgAhIwpAKQXmX5xtd0=",
+ uint64_t{0xc9ae5c8759b4877a}, uint64_t{0x58aa1ca7a4c075d9}},
+ };
+
+ for (const auto& expected_result : expected_results) {
+ std::string str;
+ ASSERT_TRUE(absl::Base64Unescape(expected_result.base64_data, &str));
+ EXPECT_EQ(absl::hash_internal::Wyhash(str.data(), str.size(),
+ expected_result.seed, kSalt),
+ expected_result.hash);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/BUILD.bazel
index c0da9ce1d84..d2824a05add 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/BUILD.bazel
@@ -1,11 +1,11 @@
#
-# Copyright 2017 The Abseil Authors.
+# 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
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,22 +14,23 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
- "ABSL_EXCEPTIONS_FLAG",
- "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "memory",
hdrs = ["memory.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:core_headers",
"//absl/meta:type_traits",
@@ -40,9 +41,9 @@ cc_test(
name = "memory_test",
srcs = ["memory_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":memory",
- "//absl/base",
"//absl/base:core_headers",
"@com_google_googletest//:gtest_main",
],
@@ -53,10 +54,11 @@ cc_test(
srcs = [
"memory_exception_safety_test.cc",
],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":memory",
+ "//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory.h
index 8bf4fe82adb..2b5ff623d43 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -34,6 +34,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// Function Template: WrapUnique()
@@ -47,19 +48,14 @@ namespace absl {
// X* NewX(int, int);
// auto x = WrapUnique(NewX(1, 2)); // 'x' is std::unique_ptr<X>.
//
-// The purpose of WrapUnique is to automatically deduce the pointer type. If you
-// wish to make the type explicit, for readability reasons or because you prefer
-// to use a base-class pointer rather than a derived one, just use
+// Do not call WrapUnique with an explicit type, as in
+// `WrapUnique<X>(NewX(1, 2))`. The purpose of WrapUnique is to automatically
+// deduce the pointer type. If you wish to make the type explicit, just use
// `std::unique_ptr` directly.
//
-// Example:
-// X* Factory(int, int);
-// auto x = std::unique_ptr<X>(Factory(1, 2));
+// auto x = std::unique_ptr<X>(NewX(1, 2));
// - or -
-// std::unique_ptr<X> x(Factory(1, 2));
-//
-// This has the added advantage of working whether Factory returns a raw
-// pointer or a `std::unique_ptr`.
+// std::unique_ptr<X> x(NewX(1, 2));
//
// While `absl::WrapUnique` is useful for capturing the output of a raw
// pointer factory, prefer 'absl::make_unique<T>(args...)' over
@@ -97,11 +93,12 @@ struct MakeUniqueResult<T[N]> {
} // namespace memory_internal
-// gcc 4.8 has __cplusplus at 201301 but doesn't define make_unique. Other
-// supported compilers either just define __cplusplus as 201103 but have
-// make_unique (msvc), or have make_unique whenever __cplusplus > 201103 (clang)
+// gcc 4.8 has __cplusplus at 201301 but the libstdc++ shipped with it doesn't
+// define make_unique. Other supported compilers either just define __cplusplus
+// as 201103 but have make_unique (msvc), or have make_unique whenever
+// __cplusplus > 201103 (clang).
#if (__cplusplus > 201103L || defined(_MSC_VER)) && \
- !(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 8)
+ !(defined(__GLIBCXX__) && !defined(__cpp_lib_make_unique))
using std::make_unique;
#else
// -----------------------------------------------------------------------------
@@ -120,7 +117,7 @@ using std::make_unique;
//
// For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic,
// see Herb Sutter's explanation on
-// (Exception-Safe Function Calls)[http://herbsutter.com/gotw/_102/].
+// (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/].
// (In general, reviewers should treat `new T(a,b)` with scrutiny.)
//
// Example usage:
@@ -423,6 +420,9 @@ struct pointer_traits<T*> {
//
// A C++11 compatible implementation of C++17's std::allocator_traits.
//
+#if __cplusplus >= 201703L
+using std::allocator_traits;
+#else // __cplusplus >= 201703L
template <typename Alloc>
struct allocator_traits {
using allocator_type = Alloc;
@@ -612,6 +612,7 @@ struct allocator_traits {
return a;
}
};
+#endif // __cplusplus >= 201703L
namespace memory_internal {
@@ -646,7 +647,7 @@ struct allocator_is_nothrow
: memory_internal::ExtractOrT<memory_internal::GetIsNothrow, Alloc,
std::false_type> {};
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
template <typename T>
struct allocator_is_nothrow<std::allocator<T>> : std::true_type {};
struct default_allocator_is_nothrow : std::true_type {};
@@ -692,6 +693,7 @@ void CopyRange(Allocator& alloc, Iterator destination, InputIterator first,
}
}
} // namespace memory_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_MEMORY_MEMORY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_exception_safety_test.cc
index 00d2b192cfc..1df72614c00 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_exception_safety_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_exception_safety_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,17 +14,19 @@
#include "absl/memory/memory.h"
+#include "absl/base/config.h"
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+
#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
constexpr int kLength = 50;
using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>;
-using ThrowerStorage =
- absl::aligned_storage_t<sizeof(Thrower), alignof(Thrower)>;
-using ThrowerList = std::array<ThrowerStorage, kLength>;
TEST(MakeUnique, CheckForLeaks) {
constexpr int kValue = 321;
@@ -49,4 +51,7 @@ TEST(MakeUnique, CheckForLeaks) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+
+#endif // ABSL_HAVE_EXCEPTIONS
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_test.cc
index 21fe32f9350..1990c7ba472 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/memory/memory_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/memory/memory.h"
#include <sys/types.h>
+
#include <cstddef>
#include <memory>
#include <string>
@@ -36,10 +37,10 @@ using ::testing::Return;
// been called, via the instance_count variable.
class DestructorVerifier {
public:
- DestructorVerifier() { ++instance_count_; }
+ DestructorVerifier() { ++instance_count_; }
DestructorVerifier(const DestructorVerifier&) = delete;
DestructorVerifier& operator=(const DestructorVerifier&) = delete;
- ~DestructorVerifier() { --instance_count_; }
+ ~DestructorVerifier() { --instance_count_; }
// The number of instances of this class currently active.
static int instance_count() { return instance_count_; }
@@ -156,9 +157,7 @@ struct ArrayWatch {
allocs().push_back(n);
return ::operator new[](n);
}
- void operator delete[](void* p) {
- return ::operator delete[](p);
- }
+ void operator delete[](void* p) { return ::operator delete[](p); }
static std::vector<size_t>& allocs() {
static auto& v = *new std::vector<size_t>;
return v;
@@ -171,8 +170,7 @@ TEST(Make_UniqueTest, Array) {
ArrayWatch::allocs().clear();
auto p = absl::make_unique<ArrayWatch[]>(5);
- static_assert(std::is_same<decltype(p),
- std::unique_ptr<ArrayWatch[]>>::value,
+ static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value,
"unexpected return type");
EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch)));
}
@@ -181,7 +179,7 @@ TEST(Make_UniqueTest, NotAmbiguousWithStdMakeUnique) {
// Ensure that absl::make_unique is not ambiguous with std::make_unique.
// In C++14 mode, the below call to make_unique has both types as candidates.
struct TakesStdType {
- explicit TakesStdType(const std::vector<int> &vec) {}
+ explicit TakesStdType(const std::vector<int>& vec) {}
};
using absl::make_unique;
(void)make_unique<TakesStdType>(std::vector<int>());
@@ -541,8 +539,8 @@ struct MinimalMockAllocator {
MinimalMockAllocator(const MinimalMockAllocator& other)
: value(other.value) {}
using value_type = TestValue;
- MOCK_METHOD1(allocate, value_type*(size_t));
- MOCK_METHOD2(deallocate, void(value_type*, size_t));
+ MOCK_METHOD(value_type*, allocate, (size_t));
+ MOCK_METHOD(void, deallocate, (value_type*, size_t));
int value;
};
@@ -557,7 +555,7 @@ TEST(AllocatorTraits, FunctionsMinimal) {
EXPECT_CALL(mock, deallocate(&x, 7));
EXPECT_EQ(&x, Traits::allocate(mock, 7));
- Traits::allocate(mock, 7, static_cast<const void*>(&hint));
+ static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
EXPECT_EQ(&x, Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
Traits::deallocate(mock, &x, 7);
@@ -579,13 +577,14 @@ struct FullMockAllocator {
explicit FullMockAllocator(int value) : value(value) {}
FullMockAllocator(const FullMockAllocator& other) : value(other.value) {}
using value_type = TestValue;
- MOCK_METHOD1(allocate, value_type*(size_t));
- MOCK_METHOD2(allocate, value_type*(size_t, const void*));
- MOCK_METHOD2(construct, void(value_type*, int*));
- MOCK_METHOD1(destroy, void(value_type*));
- MOCK_CONST_METHOD0(max_size, size_t());
- MOCK_CONST_METHOD0(select_on_container_copy_construction,
- FullMockAllocator());
+ MOCK_METHOD(value_type*, allocate, (size_t));
+ MOCK_METHOD(value_type*, allocate, (size_t, const void*));
+ MOCK_METHOD(void, construct, (value_type*, int*));
+ MOCK_METHOD(void, destroy, (value_type*));
+ MOCK_METHOD(size_t, max_size, (),
+ (const));
+ MOCK_METHOD(FullMockAllocator, select_on_container_copy_construction, (),
+ (const));
int value;
};
@@ -620,7 +619,7 @@ TEST(AllocatorTraits, FunctionsFull) {
}
TEST(AllocatorNoThrowTest, DefaultAllocator) {
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
EXPECT_TRUE(absl::default_allocator_is_nothrow::value);
#else
EXPECT_FALSE(absl::default_allocator_is_nothrow::value);
@@ -628,7 +627,7 @@ TEST(AllocatorNoThrowTest, DefaultAllocator) {
}
TEST(AllocatorNoThrowTest, StdAllocator) {
-#if ABSL_ALLOCATOR_NOTHROW
+#if defined(ABSL_ALLOCATOR_NOTHROW) && ABSL_ALLOCATOR_NOTHROW
EXPECT_TRUE(absl::allocator_is_nothrow<std::allocator<int>>::value);
#else
EXPECT_FALSE(absl::allocator_is_nothrow<std::allocator<int>>::value);
@@ -642,8 +641,7 @@ TEST(AllocatorNoThrowTest, CustomAllocator) {
struct CanThrowAllocator {
using is_nothrow = std::false_type;
};
- struct UnspecifiedAllocator {
- };
+ struct UnspecifiedAllocator {};
EXPECT_TRUE(absl::allocator_is_nothrow<NoThrowAllocator>::value);
EXPECT_FALSE(absl::allocator_is_nothrow<CanThrowAllocator>::value);
EXPECT_FALSE(absl::allocator_is_nothrow<UnspecifiedAllocator>::value);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/BUILD.bazel
index 1c39fa98b63..5585fcca794 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/BUILD.bazel
@@ -1,17 +1,36 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "type_traits",
hdrs = ["type_traits.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:config",
],
@@ -21,9 +40,9 @@ cc_test(
name = "type_traits_test",
srcs = ["type_traits_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":type_traits",
- "//absl/base:core_headers",
"@com_google_googletest//:gtest_main",
],
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits.h
index 23ebd6ed099..d5cb5f3be39 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,7 +22,7 @@
// support type inference, classification, and transformation, as well as
// make it easier to write templates based on generic type behavior.
//
-// See http://en.cppreference.com/w/cpp/header/type_traits
+// See https://en.cppreference.com/w/cpp/header/type_traits
//
// WARNING: use of many of the constructs in this header will count as "complex
// template metaprogramming", so before proceeding, please carefully consider
@@ -41,10 +41,66 @@
#include "absl/base/config.h"
+// MSVC constructibility traits do not detect destructor properties and so our
+// implementations should not use them as a source-of-truth.
+#if defined(_MSC_VER) && !defined(__clang__) && !defined(__GNUC__)
+#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Defined and documented later on in this file.
+template <typename T>
+struct is_trivially_destructible;
+
+// Defined and documented later on in this file.
+template <typename T>
+struct is_trivially_move_assignable;
namespace type_traits_internal {
+// Silence MSVC warnings about the destructor being defined as deleted.
+#if defined(_MSC_VER) && !defined(__GNUC__)
+#pragma warning(push)
+#pragma warning(disable : 4624)
+#endif // defined(_MSC_VER) && !defined(__GNUC__)
+
+template <class T>
+union SingleMemberUnion {
+ T t;
+};
+
+// Restore the state of the destructor warning that was silenced above.
+#if defined(_MSC_VER) && !defined(__GNUC__)
+#pragma warning(pop)
+#endif // defined(_MSC_VER) && !defined(__GNUC__)
+
+template <class T>
+struct IsTriviallyMoveConstructibleObject
+ : std::integral_constant<
+ bool, std::is_move_constructible<
+ type_traits_internal::SingleMemberUnion<T>>::value &&
+ absl::is_trivially_destructible<T>::value> {};
+
+template <class T>
+struct IsTriviallyCopyConstructibleObject
+ : std::integral_constant<
+ bool, std::is_copy_constructible<
+ type_traits_internal::SingleMemberUnion<T>>::value &&
+ absl::is_trivially_destructible<T>::value> {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference : std::false_type {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference<T&>
+ : absl::is_trivially_move_assignable<T>::type {};
+
+template <class T>
+struct IsTriviallyMoveAssignableReference<T&&>
+ : absl::is_trivially_move_assignable<T>::type {};
+
template <typename... Ts>
struct VoidTImpl {
using type = void;
@@ -114,6 +170,18 @@ using IsMoveAssignableImpl = decltype(std::declval<T&>() = std::declval<T&&>());
} // namespace type_traits_internal
+// MSVC 19.20 has a regression that causes our workarounds to fail, but their
+// std forms now appear to be compliant.
+#if defined(_MSC_VER) && !defined(__clang__) && (_MSC_VER >= 1920)
+
+template <typename T>
+using is_copy_assignable = std::is_copy_assignable<T>;
+
+template <typename T>
+using is_move_assignable = std::is_move_assignable<T>;
+
+#else
+
template <typename T>
struct is_copy_assignable : type_traits_internal::is_detected<
type_traits_internal::IsCopyAssignableImpl, T> {
@@ -124,6 +192,8 @@ struct is_move_assignable : type_traits_internal::is_detected<
type_traits_internal::IsMoveAssignableImpl, T> {
};
+#endif
+
// void_t()
//
// Ignores the type of any its arguments and returns `void`. In general, this
@@ -149,7 +219,7 @@ using void_t = typename type_traits_internal::VoidTImpl<Ts...>::type;
// This metafunction is designed to be a drop-in replacement for the C++17
// `std::conjunction` metafunction.
template <typename... Ts>
-struct conjunction;
+struct conjunction : std::true_type {};
template <typename T, typename... Ts>
struct conjunction<T, Ts...>
@@ -158,9 +228,6 @@ struct conjunction<T, Ts...>
template <typename T>
struct conjunction<T> : T {};
-template <>
-struct conjunction<> : std::true_type {};
-
// disjunction
//
// Performs a compile-time logical OR operation on the passed types (which
@@ -171,7 +238,7 @@ struct conjunction<> : std::true_type {};
// This metafunction is designed to be a drop-in replacement for the C++17
// `std::disjunction` metafunction.
template <typename... Ts>
-struct disjunction;
+struct disjunction : std::false_type {};
template <typename T, typename... Ts>
struct disjunction<T, Ts...> :
@@ -180,9 +247,6 @@ struct disjunction<T, Ts...> :
template <typename T>
struct disjunction<T> : T {};
-template <>
-struct disjunction<> : std::false_type {};
-
// negation
//
// Performs a compile-time logical NOT operation on the passed type (which
@@ -193,9 +257,26 @@ struct disjunction<> : std::false_type {};
template <typename T>
struct negation : std::integral_constant<bool, !T::value> {};
+// is_function()
+//
+// Determines whether the passed type `T` is a function type.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_function()` metafunction for platforms that have incomplete C++11
+// support (such as libstdc++ 4.x).
+//
+// This metafunction works because appending `const` to a type does nothing to
+// function types and reference types (and forms a const-qualified type
+// otherwise).
+template <typename T>
+struct is_function
+ : std::integral_constant<
+ bool, !(std::is_reference<T>::value ||
+ std::is_const<typename std::add_const<T>::type>::value)> {};
+
// is_trivially_destructible()
//
-// Determines whether the passed type `T` is trivially destructable.
+// Determines whether the passed type `T` is trivially destructible.
//
// This metafunction is designed to be a drop-in replacement for the C++11
// `std::is_trivially_destructible()` metafunction for platforms that have
@@ -246,7 +327,7 @@ struct is_trivially_destructible
// For the purposes of this check, the call to std::declval is considered
// trivial."
//
-// Notes from http://en.cppreference.com/w/cpp/types/is_constructible:
+// Notes from https://en.cppreference.com/w/cpp/types/is_constructible:
// In many implementations, is_nothrow_constructible also checks if the
// destructor throws because it is effectively noexcept(T(arg)). Same
// applies to is_trivially_constructible, which, in these implementations, also
@@ -261,7 +342,9 @@ struct is_trivially_default_constructible
: std::integral_constant<bool, __has_trivial_constructor(T) &&
std::is_default_constructible<T>::value &&
is_trivially_destructible<T>::value> {
-#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+ !defined( \
+ ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_default_constructible<T>::value ==
@@ -275,6 +358,41 @@ struct is_trivially_default_constructible
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
};
+// is_trivially_move_constructible()
+//
+// Determines whether the passed type `T` is trivially move constructible.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_move_constructible()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `T obj(declval<T>());` needs to be well-formed and not call any
+// nontrivial operation. Nontrivially destructible types will cause the
+// expression to be nontrivial.
+template <typename T>
+struct is_trivially_move_constructible
+ : std::conditional<
+ std::is_object<T>::value && !std::is_array<T>::value,
+ type_traits_internal::IsTriviallyMoveConstructibleObject<T>,
+ std::is_reference<T>>::type::type {
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+ !defined( \
+ ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
+ private:
+ static constexpr bool compliant =
+ std::is_trivially_move_constructible<T>::value ==
+ is_trivially_move_constructible::value;
+ static_assert(compliant || std::is_trivially_move_constructible<T>::value,
+ "Not compliant with std::is_trivially_move_constructible; "
+ "Standard: false, Implementation: true");
+ static_assert(compliant || !std::is_trivially_move_constructible<T>::value,
+ "Not compliant with std::is_trivially_move_constructible; "
+ "Standard: true, Implementation: false");
+#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+};
+
// is_trivially_copy_constructible()
//
// Determines whether the passed type `T` is trivially copy constructible.
@@ -290,10 +408,13 @@ struct is_trivially_default_constructible
// expression to be nontrivial.
template <typename T>
struct is_trivially_copy_constructible
- : std::integral_constant<bool, __has_trivial_copy(T) &&
- std::is_copy_constructible<T>::value &&
- is_trivially_destructible<T>::value> {
-#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
+ : std::conditional<
+ std::is_object<T>::value && !std::is_array<T>::value,
+ type_traits_internal::IsTriviallyCopyConstructibleObject<T>,
+ std::is_lvalue_reference<T>>::type::type {
+#if defined(ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE) && \
+ !defined( \
+ ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION)
private:
static constexpr bool compliant =
std::is_trivially_copy_constructible<T>::value ==
@@ -307,6 +428,43 @@ struct is_trivially_copy_constructible
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE
};
+// is_trivially_move_assignable()
+//
+// Determines whether the passed type `T` is trivially move assignable.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_move_assignable()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). On any platforms that do
+// fully support C++11, we check whether this yields the same result as the std
+// implementation.
+//
+// NOTE: `is_assignable<T, U>::value` is `true` if the expression
+// `declval<T>() = declval<U>()` is well-formed when treated as an unevaluated
+// operand. `is_trivially_assignable<T, U>` requires the assignment to call no
+// operation that is not trivial. `is_trivially_copy_assignable<T>` is simply
+// `is_trivially_assignable<T&, T>`.
+template <typename T>
+struct is_trivially_move_assignable
+ : std::conditional<
+ std::is_object<T>::value && !std::is_array<T>::value &&
+ std::is_move_assignable<T>::value,
+ std::is_move_assignable<type_traits_internal::SingleMemberUnion<T>>,
+ type_traits_internal::IsTriviallyMoveAssignableReference<T>>::type::
+ type {
+#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+ private:
+ static constexpr bool compliant =
+ std::is_trivially_move_assignable<T>::value ==
+ is_trivially_move_assignable::value;
+ static_assert(compliant || std::is_trivially_move_assignable<T>::value,
+ "Not compliant with std::is_trivially_move_assignable; "
+ "Standard: false, Implementation: true");
+ static_assert(compliant || !std::is_trivially_move_assignable<T>::value,
+ "Not compliant with std::is_trivially_move_assignable; "
+ "Standard: true, Implementation: false");
+#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
+};
+
// is_trivially_copy_assignable()
//
// Determines whether the passed type `T` is trivially copy assignable.
@@ -341,6 +499,49 @@ struct is_trivially_copy_assignable
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
};
+namespace type_traits_internal {
+// is_trivially_copyable()
+//
+// Determines whether the passed type `T` is trivially copyable.
+//
+// This metafunction is designed to be a drop-in replacement for the C++11
+// `std::is_trivially_copyable()` metafunction for platforms that have
+// incomplete C++11 support (such as libstdc++ 4.x). We use the C++17 definition
+// of TriviallyCopyable.
+//
+// NOTE: `is_trivially_copyable<T>::value` is `true` if all of T's copy/move
+// constructors/assignment operators are trivial or deleted, T has at least
+// one non-deleted copy/move constructor/assignment operator, and T is trivially
+// destructible. Arrays of trivially copyable types are trivially copyable.
+//
+// We expose this metafunction only for internal use within absl.
+template <typename T>
+class is_trivially_copyable_impl {
+ using ExtentsRemoved = typename std::remove_all_extents<T>::type;
+ static constexpr bool kIsCopyOrMoveConstructible =
+ std::is_copy_constructible<ExtentsRemoved>::value ||
+ std::is_move_constructible<ExtentsRemoved>::value;
+ static constexpr bool kIsCopyOrMoveAssignable =
+ absl::is_copy_assignable<ExtentsRemoved>::value ||
+ absl::is_move_assignable<ExtentsRemoved>::value;
+
+ public:
+ static constexpr bool kValue =
+ (__has_trivial_copy(ExtentsRemoved) || !kIsCopyOrMoveConstructible) &&
+ (__has_trivial_assign(ExtentsRemoved) || !kIsCopyOrMoveAssignable) &&
+ (kIsCopyOrMoveConstructible || kIsCopyOrMoveAssignable) &&
+ is_trivially_destructible<ExtentsRemoved>::value &&
+ // We need to check for this explicitly because otherwise we'll say
+ // references are trivial copyable when compiled by MSVC.
+ !std::is_reference<ExtentsRemoved>::value;
+};
+
+template <typename T>
+struct is_trivially_copyable
+ : std::integral_constant<
+ bool, type_traits_internal::is_trivially_copyable_impl<T>::kValue> {};
+} // namespace type_traits_internal
+
// -----------------------------------------------------------------------------
// C++14 "_t" trait aliases
// -----------------------------------------------------------------------------
@@ -409,28 +610,158 @@ using common_type_t = typename std::common_type<T...>::type;
template <typename T>
using underlying_type_t = typename std::underlying_type<T>::type;
-template <typename T>
-using result_of_t = typename std::result_of<T>::type;
namespace type_traits_internal {
+
+#if __cplusplus >= 201703L
+// std::result_of is deprecated (C++17) or removed (C++20)
+template<typename> struct result_of;
+template<typename F, typename... Args>
+struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};
+#else
+template<typename F> using result_of = std::result_of<F>;
+#endif
+
+} // namespace type_traits_internal
+
+template<typename F>
+using result_of_t = typename type_traits_internal::result_of<F>::type;
+
+namespace type_traits_internal {
+// In MSVC we can't probe std::hash or stdext::hash because it triggers a
+// static_assert instead of failing substitution. Libc++ prior to 4.0
+// also used a static_assert.
+//
+#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
+ _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 0
+#else
+#define ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_ 1
+#endif
+
+#if !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
template <typename Key, typename = size_t>
+struct IsHashable : std::true_type {};
+#else // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+template <typename Key, typename = void>
struct IsHashable : std::false_type {};
template <typename Key>
-struct IsHashable<Key,
- decltype(std::declval<std::hash<Key>>()(std::declval<Key>()))>
- : std::true_type {};
+struct IsHashable<
+ Key,
+ absl::enable_if_t<std::is_convertible<
+ decltype(std::declval<std::hash<Key>&>()(std::declval<Key const&>())),
+ std::size_t>::value>> : std::true_type {};
+#endif // !ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+
+struct AssertHashEnabledHelper {
+ private:
+ static void Sink(...) {}
+ struct NAT {};
+
+ template <class Key>
+ static auto GetReturnType(int)
+ -> decltype(std::declval<std::hash<Key>>()(std::declval<Key const&>()));
+ template <class Key>
+ static NAT GetReturnType(...);
+
+ template <class Key>
+ static std::nullptr_t DoIt() {
+ static_assert(IsHashable<Key>::value,
+ "std::hash<Key> does not provide a call operator");
+ static_assert(
+ std::is_default_constructible<std::hash<Key>>::value,
+ "std::hash<Key> must be default constructible when it is enabled");
+ static_assert(
+ std::is_copy_constructible<std::hash<Key>>::value,
+ "std::hash<Key> must be copy constructible when it is enabled");
+ static_assert(absl::is_copy_assignable<std::hash<Key>>::value,
+ "std::hash<Key> must be copy assignable when it is enabled");
+ // is_destructible is unchecked as it's implied by each of the
+ // is_constructible checks.
+ using ReturnType = decltype(GetReturnType<Key>(0));
+ static_assert(std::is_same<ReturnType, NAT>::value ||
+ std::is_same<ReturnType, size_t>::value,
+ "std::hash<Key> must return size_t");
+ return nullptr;
+ }
+
+ template <class... Ts>
+ friend void AssertHashEnabled();
+};
-template <typename Key>
-struct IsHashEnabled
- : absl::conjunction<std::is_default_constructible<std::hash<Key>>,
- std::is_copy_constructible<std::hash<Key>>,
- std::is_destructible<std::hash<Key>>,
- absl::is_copy_assignable<std::hash<Key>>,
- IsHashable<Key>> {};
+template <class... Ts>
+inline void AssertHashEnabled() {
+ using Helper = AssertHashEnabledHelper;
+ Helper::Sink(Helper::DoIt<Ts>()...);
+}
} // namespace type_traits_internal
+// An internal namespace that is required to implement the C++17 swap traits.
+// It is not further nested in type_traits_internal to avoid long symbol names.
+namespace swap_internal {
+
+// Necessary for the traits.
+using std::swap;
+
+// This declaration prevents global `swap` and `absl::swap` overloads from being
+// considered unless ADL picks them up.
+void swap();
+
+template <class T>
+using IsSwappableImpl = decltype(swap(std::declval<T&>(), std::declval<T&>()));
+
+// NOTE: This dance with the default template parameter is for MSVC.
+template <class T,
+ class IsNoexcept = std::integral_constant<
+ bool, noexcept(swap(std::declval<T&>(), std::declval<T&>()))>>
+using IsNothrowSwappableImpl = typename std::enable_if<IsNoexcept::value>::type;
+
+// IsSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T`.
+template <class T>
+struct IsSwappable
+ : absl::type_traits_internal::is_detected<IsSwappableImpl, T> {};
+
+// IsNothrowSwappable
+//
+// Determines whether the standard swap idiom is a valid expression for
+// arguments of type `T` and is noexcept.
+template <class T>
+struct IsNothrowSwappable
+ : absl::type_traits_internal::is_detected<IsNothrowSwappableImpl, T> {};
+
+// Swap()
+//
+// Performs the swap idiom from a namespace where valid candidates may only be
+// found in `std` or via ADL.
+template <class T, absl::enable_if_t<IsSwappable<T>::value, int> = 0>
+void Swap(T& lhs, T& rhs) noexcept(IsNothrowSwappable<T>::value) {
+ swap(lhs, rhs);
+}
+
+// StdSwapIsUnconstrained
+//
+// Some standard library implementations are broken in that they do not
+// constrain `std::swap`. This will effectively tell us if we are dealing with
+// one of those implementations.
+using StdSwapIsUnconstrained = IsSwappable<void()>;
+
+} // namespace swap_internal
+
+namespace type_traits_internal {
+
+// Make the swap-related traits/function accessible from this namespace.
+using swap_internal::IsNothrowSwappable;
+using swap_internal::IsSwappable;
+using swap_internal::Swap;
+using swap_internal::StdSwapIsUnconstrained;
+
+} // namespace type_traits_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_META_TYPE_TRAITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits_test.cc
index f51f5dedee4..1aafd0d49a8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/meta/type_traits_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -214,6 +214,29 @@ class DeletedDefaultCtor {
int n_;
};
+class TrivialMoveCtor {
+ public:
+ explicit TrivialMoveCtor(int n) : n_(n) {}
+ TrivialMoveCtor(TrivialMoveCtor&&) = default;
+ TrivialMoveCtor& operator=(const TrivialMoveCtor& t) {
+ n_ = t.n_;
+ return *this;
+ }
+
+ private:
+ int n_;
+};
+
+class NontrivialMoveCtor {
+ public:
+ explicit NontrivialMoveCtor(int n) : n_(n) {}
+ NontrivialMoveCtor(NontrivialMoveCtor&& t) noexcept : n_(t.n_) {}
+ NontrivialMoveCtor& operator=(const NontrivialMoveCtor&) = default;
+
+ private:
+ int n_;
+};
+
class TrivialCopyCtor {
public:
explicit TrivialCopyCtor(int n) : n_(n) {}
@@ -247,6 +270,29 @@ class DeletedCopyCtor {
int n_;
};
+class TrivialMoveAssign {
+ public:
+ explicit TrivialMoveAssign(int n) : n_(n) {}
+ TrivialMoveAssign(const TrivialMoveAssign& t) : n_(t.n_) {}
+ TrivialMoveAssign& operator=(TrivialMoveAssign&&) = default;
+ ~TrivialMoveAssign() {} // can have nontrivial destructor
+ private:
+ int n_;
+};
+
+class NontrivialMoveAssign {
+ public:
+ explicit NontrivialMoveAssign(int n) : n_(n) {}
+ NontrivialMoveAssign(const NontrivialMoveAssign&) = default;
+ NontrivialMoveAssign& operator=(NontrivialMoveAssign&& t) noexcept {
+ n_ = t.n_;
+ return *this;
+ }
+
+ private:
+ int n_;
+};
+
class TrivialCopyAssign {
public:
explicit TrivialCopyAssign(int n) : n_(n) {}
@@ -280,10 +326,20 @@ class DeletedCopyAssign {
int n_;
};
-struct NonCopyable {
- NonCopyable() = default;
- NonCopyable(const NonCopyable&) = delete;
- NonCopyable& operator=(const NonCopyable&) = delete;
+struct MovableNonCopyable {
+ MovableNonCopyable() = default;
+ MovableNonCopyable(const MovableNonCopyable&) = delete;
+ MovableNonCopyable(MovableNonCopyable&&) = default;
+ MovableNonCopyable& operator=(const MovableNonCopyable&) = delete;
+ MovableNonCopyable& operator=(MovableNonCopyable&&) = default;
+};
+
+struct NonCopyableOrMovable {
+ NonCopyableOrMovable() = default;
+ NonCopyableOrMovable(const NonCopyableOrMovable&) = delete;
+ NonCopyableOrMovable(NonCopyableOrMovable&&) = delete;
+ NonCopyableOrMovable& operator=(const NonCopyableOrMovable&) = delete;
+ NonCopyableOrMovable& operator=(NonCopyableOrMovable&&) = delete;
};
class Base {
@@ -291,21 +347,6 @@ class Base {
virtual ~Base() {}
};
-// In GCC/Clang, std::is_trivially_constructible requires that the destructor is
-// trivial. However, MSVC doesn't require that. This results in different
-// behavior when checking is_trivially_constructible on any type with
-// nontrivial destructor. Since absl::is_trivially_default_constructible and
-// absl::is_trivially_copy_constructible both follows Clang/GCC's interpretation
-// and check is_trivially_destructible, it results in inconsistency with
-// std::is_trivially_xxx_constructible on MSVC. This macro is used to work
-// around this issue in test. In practice, a trivially constructible type
-// should also be trivially destructible.
-// GCC bug 51452: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51452
-// LWG issue 2116: http://cplusplus.github.io/LWG/lwg-active.html#2116
-#ifndef _MSC_VER
-#define ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE 1
-#endif
-
// Old versions of libc++, around Clang 3.5 to 3.6, consider deleted destructors
// as also being trivial. With the resolution of CWG 1928 and CWG 1734, this
// is no longer considered true and has thus been amended.
@@ -329,6 +370,22 @@ class Base {
#define ABSL_GCC_BUG_TRIVIALLY_CONSTRUCTIBLE_ON_ARRAY_OF_NONTRIVIAL 1
#endif
+TEST(TypeTraitsTest, TestIsFunction) {
+ struct Callable {
+ void operator()() {}
+ };
+ EXPECT_TRUE(absl::is_function<void()>::value);
+ EXPECT_TRUE(absl::is_function<void()&>::value);
+ EXPECT_TRUE(absl::is_function<void() const>::value);
+ EXPECT_TRUE(absl::is_function<void() noexcept>::value);
+ EXPECT_TRUE(absl::is_function<void(...) noexcept>::value);
+
+ EXPECT_FALSE(absl::is_function<void(*)()>::value);
+ EXPECT_FALSE(absl::is_function<void(&)()>::value);
+ EXPECT_FALSE(absl::is_function<int>::value);
+ EXPECT_FALSE(absl::is_function<Callable>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialDestructor) {
// Verify that arithmetic types and pointers have trivial destructors.
EXPECT_TRUE(absl::is_trivially_destructible<bool>::value);
@@ -427,11 +484,9 @@ TEST(TypeTraitsTest, TestTrivialDefaultCtor) {
EXPECT_FALSE(
absl::is_trivially_default_constructible<DeletedDefaultCtor>::value);
-#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// types with nontrivial destructor are nontrivial
EXPECT_FALSE(
absl::is_trivially_default_constructible<NontrivialDestructor>::value);
-#endif
// types with vtables
EXPECT_FALSE(absl::is_trivially_default_constructible<Base>::value);
@@ -474,6 +529,99 @@ TEST(TypeTraitsTest, TestTrivialDefaultCtor) {
#endif
}
+// GCC prior to 7.4 had a bug in its trivially-constructible traits
+// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654).
+// This test makes sure that we do not depend on the trait in these cases when
+// implementing absl triviality traits.
+
+template <class T>
+struct BadConstructors {
+ BadConstructors() { static_assert(T::value, ""); }
+
+ BadConstructors(BadConstructors&&) { static_assert(T::value, ""); }
+
+ BadConstructors(const BadConstructors&) { static_assert(T::value, ""); }
+};
+
+TEST(TypeTraitsTest, TestTrivialityBadConstructors) {
+ using BadType = BadConstructors<int>;
+
+ EXPECT_FALSE(absl::is_trivially_default_constructible<BadType>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<BadType>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<BadType>::value);
+}
+
+TEST(TypeTraitsTest, TestTrivialMoveCtor) {
+ // Verify that arithmetic types and pointers have trivial move
+ // constructors.
+ EXPECT_TRUE(absl::is_trivially_move_constructible<bool>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<signed char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<wchar_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<unsigned int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<uint16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<uint64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<float>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<long double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<const std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<const Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<std::string**>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial**>::value);
+
+ // Reference types
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int&>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<int&&>::value);
+
+ // types with compiler generated move ctors
+ EXPECT_TRUE(absl::is_trivially_move_constructible<Trivial>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<TrivialMoveCtor>::value);
+
+ // Verify that types without them (i.e. nontrivial or deleted) are not.
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NontrivialCopyCtor>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<DeletedCopyCtor>::value);
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NonCopyableOrMovable>::value);
+
+ // type with nontrivial destructor are nontrivial move construbtible
+ EXPECT_FALSE(
+ absl::is_trivially_move_constructible<NontrivialDestructor>::value);
+
+ // types with vtables
+ EXPECT_FALSE(absl::is_trivially_move_constructible<Base>::value);
+
+ // Verify that simple_pair of such types is trivially move constructible
+ EXPECT_TRUE(
+ (absl::is_trivially_move_constructible<simple_pair<int, char*>>::value));
+ EXPECT_TRUE((
+ absl::is_trivially_move_constructible<simple_pair<int, Trivial>>::value));
+ EXPECT_TRUE((absl::is_trivially_move_constructible<
+ simple_pair<int, TrivialMoveCtor>>::value));
+
+ // Verify that types without trivial move constructors are
+ // correctly marked as such.
+ EXPECT_FALSE(absl::is_trivially_move_constructible<std::string>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<std::vector<int>>::value);
+
+ // Verify that simple_pairs of types without trivial move constructors
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::is_trivially_move_constructible<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::is_trivially_move_constructible<
+ simple_pair<std::string, int>>::value));
+
+ // Verify that arrays are not
+ using int10 = int[10];
+ EXPECT_FALSE(absl::is_trivially_move_constructible<int10>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialCopyCtor) {
// Verify that arithmetic types and pointers have trivial copy
// constructors.
@@ -498,6 +646,10 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
EXPECT_TRUE(absl::is_trivially_copy_constructible<std::string**>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial**>::value);
+ // Reference types
+ EXPECT_TRUE(absl::is_trivially_copy_constructible<int&>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<int&&>::value);
+
// types with compiler generated copy ctors
EXPECT_TRUE(absl::is_trivially_copy_constructible<Trivial>::value);
EXPECT_TRUE(absl::is_trivially_copy_constructible<TrivialCopyCtor>::value);
@@ -507,13 +659,13 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
absl::is_trivially_copy_constructible<NontrivialCopyCtor>::value);
EXPECT_FALSE(absl::is_trivially_copy_constructible<DeletedCopyCtor>::value);
EXPECT_FALSE(
- absl::is_trivially_copy_constructible<NonCopyable>::value);
+ absl::is_trivially_copy_constructible<MovableNonCopyable>::value);
+ EXPECT_FALSE(
+ absl::is_trivially_copy_constructible<NonCopyableOrMovable>::value);
-#ifdef ABSL_TRIVIALLY_CONSTRUCTIBLE_VERIFY_TRIVIALLY_DESTRUCTIBLE
// type with nontrivial destructor are nontrivial copy construbtible
EXPECT_FALSE(
absl::is_trivially_copy_constructible<NontrivialDestructor>::value);
-#endif
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_constructible<Base>::value);
@@ -543,6 +695,74 @@ TEST(TypeTraitsTest, TestTrivialCopyCtor) {
EXPECT_FALSE(absl::is_trivially_copy_constructible<int10>::value);
}
+TEST(TypeTraitsTest, TestTrivialMoveAssign) {
+ // Verify that arithmetic types and pointers have trivial move
+ // assignment operators.
+ EXPECT_TRUE(absl::is_trivially_move_assignable<bool>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<signed char>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<wchar_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<unsigned int>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<uint16_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<int64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<uint64_t>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<float>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<long double>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<const std::string*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<const Trivial*>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<std::string**>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial**>::value);
+
+ // const qualified types are not assignable
+ EXPECT_FALSE(absl::is_trivially_move_assignable<const int>::value);
+
+ // types with compiler generated move assignment
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<TrivialMoveAssign>::value);
+
+ // Verify that types without them (i.e. nontrivial or deleted) are not.
+ EXPECT_FALSE(absl::is_trivially_move_assignable<NontrivialCopyAssign>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<DeletedCopyAssign>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<NonCopyableOrMovable>::value);
+
+ // types with vtables
+ EXPECT_FALSE(absl::is_trivially_move_assignable<Base>::value);
+
+ // Verify that simple_pair is trivially assignable
+ EXPECT_TRUE(
+ (absl::is_trivially_move_assignable<simple_pair<int, char*>>::value));
+ EXPECT_TRUE(
+ (absl::is_trivially_move_assignable<simple_pair<int, Trivial>>::value));
+ EXPECT_TRUE((absl::is_trivially_move_assignable<
+ simple_pair<int, TrivialMoveAssign>>::value));
+
+ // Verify that types not trivially move assignable are
+ // correctly marked as such.
+ EXPECT_FALSE(absl::is_trivially_move_assignable<std::string>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<std::vector<int>>::value);
+
+ // Verify that simple_pairs of types not trivially move assignable
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::is_trivially_move_assignable<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::is_trivially_move_assignable<
+ simple_pair<std::string, int>>::value));
+
+ // Verify that arrays are not trivially move assignable
+ using int10 = int[10];
+ EXPECT_FALSE(absl::is_trivially_move_assignable<int10>::value);
+
+ // Verify that references are handled correctly
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&&>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<Trivial&>::value);
+}
+
TEST(TypeTraitsTest, TestTrivialCopyAssign) {
// Verify that arithmetic types and pointers have trivial copy
// assignment operators.
@@ -577,7 +797,8 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) {
// Verify that types without them (i.e. nontrivial or deleted) are not.
EXPECT_FALSE(absl::is_trivially_copy_assignable<NontrivialCopyAssign>::value);
EXPECT_FALSE(absl::is_trivially_copy_assignable<DeletedCopyAssign>::value);
- EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyable>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<MovableNonCopyable>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<NonCopyableOrMovable>::value);
// types with vtables
EXPECT_FALSE(absl::is_trivially_copy_assignable<Base>::value);
@@ -611,6 +832,116 @@ TEST(TypeTraitsTest, TestTrivialCopyAssign) {
EXPECT_TRUE(absl::is_trivially_copy_assignable<Trivial&>::value);
}
+TEST(TypeTraitsTest, TestTriviallyCopyable) {
+ // Verify that arithmetic types and pointers are trivially copyable.
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<bool>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<unsigned char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<signed char>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<wchar_t>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<unsigned int>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int16_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<uint16_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int64_t>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<uint64_t>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<float>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<double>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<long double>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<std::string*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial*>::value);
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ const std::string*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<const Trivial*>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<std::string**>::value);
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial**>::value);
+
+ // const qualified types are not assignable but are constructible
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<const int>::value);
+
+ // Trivial copy constructor/assignment and destructor.
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial>::value);
+ // Trivial copy assignment, but non-trivial copy constructor/destructor.
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ TrivialCopyAssign>::value);
+ // Trivial copy constructor, but non-trivial assignment.
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ TrivialCopyCtor>::value);
+
+ // Types with a non-trivial copy constructor/assignment
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NontrivialCopyCtor>::value);
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NontrivialCopyAssign>::value);
+
+ // Types without copy constructor/assignment, but with move
+ // MSVC disagrees with other compilers about this:
+ // EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ // MovableNonCopyable>::value);
+
+ // Types without copy/move constructor/assignment
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ NonCopyableOrMovable>::value);
+
+ // No copy assign, but has trivial copy constructor.
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<
+ DeletedCopyAssign>::value);
+
+ // types with vtables
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<Base>::value);
+
+ // Verify that simple_pair is trivially copyable if members are
+ EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, char*>>::value));
+ EXPECT_TRUE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, Trivial>>::value));
+
+ // Verify that types not trivially copyable are
+ // correctly marked as such.
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<std::string>::value);
+ EXPECT_FALSE(absl::type_traits_internal::is_trivially_copyable<
+ std::vector<int>>::value);
+
+ // Verify that simple_pairs of types not trivially copyable
+ // are not marked as trivial.
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, std::string>>::value));
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<std::string, int>>::value));
+ EXPECT_FALSE((absl::type_traits_internal::is_trivially_copyable<
+ simple_pair<int, TrivialCopyAssign>>::value));
+
+ // Verify that arrays of trivially copyable types are trivially copyable
+ using int10 = int[10];
+ EXPECT_TRUE(absl::type_traits_internal::is_trivially_copyable<int10>::value);
+ using int10x10 = int[10][10];
+ EXPECT_TRUE(
+ absl::type_traits_internal::is_trivially_copyable<int10x10>::value);
+
+ // Verify that references are handled correctly
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial&&>::value);
+ EXPECT_FALSE(
+ absl::type_traits_internal::is_trivially_copyable<Trivial&>::value);
+}
+
#define ABSL_INTERNAL_EXPECT_ALIAS_EQUIVALENCE(trait_name, ...) \
EXPECT_TRUE((std::is_same<typename std::trait_name<__VA_ARGS__>::type, \
absl::trait_name##_t<__VA_ARGS__>>::value))
@@ -953,4 +1284,85 @@ TEST(TypeTraitsTest, IsMoveAssignable) {
#endif // _LIBCPP_VERSION
}
+namespace adl_namespace {
+
+struct DeletedSwap {
+};
+
+void swap(DeletedSwap&, DeletedSwap&) = delete;
+
+struct SpecialNoexceptSwap {
+ SpecialNoexceptSwap(SpecialNoexceptSwap&&) {}
+ SpecialNoexceptSwap& operator=(SpecialNoexceptSwap&&) { return *this; }
+ ~SpecialNoexceptSwap() = default;
+};
+
+void swap(SpecialNoexceptSwap&, SpecialNoexceptSwap&) noexcept {}
+
+} // namespace adl_namespace
+
+TEST(TypeTraitsTest, IsSwappable) {
+ using absl::type_traits_internal::IsSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsSwappable<int>::value);
+
+ struct S {};
+ EXPECT_TRUE(IsSwappable<S>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoConstruct>::value, StdSwapIsUnconstrained::value);
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_EQ(IsSwappable<NoAssign>::value, StdSwapIsUnconstrained::value);
+
+ EXPECT_FALSE(IsSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
+TEST(TypeTraitsTest, IsNothrowSwappable) {
+ using absl::type_traits_internal::IsNothrowSwappable;
+ using absl::type_traits_internal::StdSwapIsUnconstrained;
+
+ EXPECT_TRUE(IsNothrowSwappable<int>::value);
+
+ struct NonNoexceptMoves {
+ NonNoexceptMoves(NonNoexceptMoves&&) {}
+ NonNoexceptMoves& operator=(NonNoexceptMoves&&) { return *this; }
+ ~NonNoexceptMoves() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NonNoexceptMoves>::value);
+
+ struct NoConstruct {
+ NoConstruct(NoConstruct&&) = delete;
+ NoConstruct& operator=(NoConstruct&&) { return *this; }
+ ~NoConstruct() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoConstruct>::value);
+
+ struct NoAssign {
+ NoAssign(NoAssign&&) {}
+ NoAssign& operator=(NoAssign&&) = delete;
+ ~NoAssign() = default;
+ };
+
+ EXPECT_FALSE(IsNothrowSwappable<NoAssign>::value);
+
+ EXPECT_FALSE(IsNothrowSwappable<adl_namespace::DeletedSwap>::value);
+
+ EXPECT_TRUE(IsNothrowSwappable<adl_namespace::SpecialNoexceptSwap>::value);
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/BUILD.bazel
index c906b8d750a..ea587bfa45a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/BUILD.bazel
@@ -4,7 +4,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -12,15 +12,46 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
+
+cc_library(
+ name = "bits",
+ hdrs = [
+ "bits.h",
+ "internal/bits.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_test(
+ name = "bits_test",
+ size = "small",
+ srcs = [
+ "bits_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":bits",
+ "//absl/random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
cc_library(
name = "int128",
@@ -31,7 +62,9 @@ cc_library(
],
hdrs = ["int128.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
+ ":bits",
"//absl/base:config",
"//absl/base:core_headers",
],
@@ -45,6 +78,7 @@ cc_test(
"int128_test.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":int128",
"//absl/base",
@@ -59,6 +93,7 @@ cc_test(
name = "int128_benchmark",
srcs = ["int128_benchmark.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":int128",
@@ -66,3 +101,15 @@ cc_test(
"@com_github_google_benchmark//:benchmark_main",
],
)
+
+cc_library(
+ name = "representation",
+ hdrs = [
+ "internal/representation.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits.h
new file mode 100644
index 00000000000..52013ad49bb
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits.h
@@ -0,0 +1,177 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: bits.h
+// -----------------------------------------------------------------------------
+//
+// This file contains implementations of C++20's bitwise math functions, as
+// defined by:
+//
+// P0553R4:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0553r4.html
+// P0556R3:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0556r3.html
+// P1355R2:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1355r2.html
+// P1956R1:
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1956r1.pdf
+//
+// When using a standard library that implements these functions, we use the
+// standard library's implementation.
+
+#ifndef ABSL_NUMERIC_BITS_H_
+#define ABSL_NUMERIC_BITS_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L) || \
+ (defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
+#include <bit>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/numeric/internal/bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+#if !(defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L)
+// rotating
+template <class T>
+ABSL_MUST_USE_RESULT constexpr
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ rotl(T x, int s) noexcept {
+ return numeric_internal::RotateLeft(x, s);
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT constexpr
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ rotr(T x, int s) noexcept {
+ return numeric_internal::RotateRight(x, s);
+}
+
+// Counting functions
+//
+// While these functions are typically constexpr, on some platforms, they may
+// not be marked as constexpr due to constraints of the compiler/available
+// intrinsics.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countl_zero(T x) noexcept {
+ return numeric_internal::CountLeadingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countl_one(T x) noexcept {
+ // Avoid integer promotion to a wider type
+ return countl_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countr_zero(T x) noexcept {
+ return numeric_internal::CountTrailingZeroes(x);
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CTZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ countr_one(T x) noexcept {
+ // Avoid integer promotion to a wider type
+ return countr_zero(static_cast<T>(~x));
+}
+
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline
+ typename std::enable_if<std::is_unsigned<T>::value, int>::type
+ popcount(T x) noexcept {
+ return numeric_internal::Popcount(x);
+}
+#else // defined(__cpp_lib_bitops) && __cpp_lib_bitops >= 201907L
+
+using std::countl_one;
+using std::countl_zero;
+using std::countr_one;
+using std::countr_zero;
+using std::popcount;
+using std::rotl;
+using std::rotr;
+
+#endif
+
+#if !(defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L)
+// Returns: true if x is an integral power of two; false otherwise.
+template <class T>
+constexpr inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
+has_single_bit(T x) noexcept {
+ return x != 0 && (x & (x - 1)) == 0;
+}
+
+// Returns: If x == 0, 0; otherwise one plus the base-2 logarithm of x, with any
+// fractional part discarded.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ bit_width(T x) noexcept {
+ return std::numeric_limits<T>::digits - countl_zero(x);
+}
+
+// Returns: If x == 0, 0; otherwise the maximal value y such that
+// has_single_bit(y) is true and y <= x.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ bit_floor(T x) noexcept {
+ return x == 0 ? 0 : T{1} << (bit_width(x) - 1);
+}
+
+// Returns: N, where N is the smallest power of 2 greater than or equal to x.
+//
+// Preconditions: N is representable as a value of type T.
+template <class T>
+ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ bit_ceil(T x) {
+ // If T is narrower than unsigned, T{1} << bit_width will be promoted. We
+ // want to force it to wraparound so that bit_ceil of an invalid value are not
+ // core constant expressions.
+ //
+ // BitCeilNonPowerOf2 triggers an overflow in constexpr contexts if we would
+ // undergo promotion to unsigned but not fit the result into T without
+ // truncation.
+ return has_single_bit(x) ? T{1} << (bit_width(x) - 1)
+ : numeric_internal::BitCeilNonPowerOf2(x);
+}
+#else // defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L
+
+using std::bit_ceil;
+using std::bit_floor;
+using std::bit_width;
+using std::has_single_bit;
+
+#endif
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_NUMERIC_BITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits_test.cc
new file mode 100644
index 00000000000..7c942aaecde
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/bits_test.cc
@@ -0,0 +1,573 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/numeric/bits.h"
+
+#include <limits>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/random.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+TEST(Rotate, Left) {
+ static_assert(rotl(uint8_t{0x12}, 0) == uint8_t{0x12}, "");
+ static_assert(rotl(uint16_t{0x1234}, 0) == uint16_t{0x1234}, "");
+ static_assert(rotl(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, "");
+ static_assert(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0) ==
+ uint64_t{0x12345678ABCDEF01ULL},
+ "");
+
+ EXPECT_EQ(rotl(uint8_t{0x12}, 0), uint8_t{0x12});
+ EXPECT_EQ(rotl(uint16_t{0x1234}, 0), uint16_t{0x1234});
+ EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 0),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotl(uint8_t{0x12}, 8), uint8_t{0x12});
+ EXPECT_EQ(rotl(uint16_t{0x1234}, 16), uint16_t{0x1234});
+ EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 64),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotl(uint8_t{0x12}, -8), uint8_t{0x12});
+ EXPECT_EQ(rotl(uint16_t{0x1234}, -16), uint16_t{0x1234});
+ EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -64),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotl(uint8_t{0x12}, 4), uint8_t{0x21});
+ EXPECT_EQ(rotl(uint16_t{0x1234}, 4), uint16_t{0x2341});
+ EXPECT_EQ(rotl(uint32_t{0x12345678UL}, 4), uint32_t{0x23456781UL});
+ EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, 4),
+ uint64_t{0x2345678ABCDEF011ULL});
+
+ EXPECT_EQ(rotl(uint8_t{0x12}, -4), uint8_t{0x21});
+ EXPECT_EQ(rotl(uint16_t{0x1234}, -4), uint16_t{0x4123});
+ EXPECT_EQ(rotl(uint32_t{0x12345678UL}, -4), uint32_t{0x81234567UL});
+ EXPECT_EQ(rotl(uint64_t{0x12345678ABCDEF01ULL}, -4),
+ uint64_t{0x112345678ABCDEF0ULL});
+}
+
+TEST(Rotate, Right) {
+ static_assert(rotr(uint8_t{0x12}, 0) == uint8_t{0x12}, "");
+ static_assert(rotr(uint16_t{0x1234}, 0) == uint16_t{0x1234}, "");
+ static_assert(rotr(uint32_t{0x12345678UL}, 0) == uint32_t{0x12345678UL}, "");
+ static_assert(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0) ==
+ uint64_t{0x12345678ABCDEF01ULL},
+ "");
+
+ EXPECT_EQ(rotr(uint8_t{0x12}, 0), uint8_t{0x12});
+ EXPECT_EQ(rotr(uint16_t{0x1234}, 0), uint16_t{0x1234});
+ EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 0), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 0),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotr(uint8_t{0x12}, 8), uint8_t{0x12});
+ EXPECT_EQ(rotr(uint16_t{0x1234}, 16), uint16_t{0x1234});
+ EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 32), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 64),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotr(uint8_t{0x12}, -8), uint8_t{0x12});
+ EXPECT_EQ(rotr(uint16_t{0x1234}, -16), uint16_t{0x1234});
+ EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -32), uint32_t{0x12345678UL});
+ EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -64),
+ uint64_t{0x12345678ABCDEF01ULL});
+
+ EXPECT_EQ(rotr(uint8_t{0x12}, 4), uint8_t{0x21});
+ EXPECT_EQ(rotr(uint16_t{0x1234}, 4), uint16_t{0x4123});
+ EXPECT_EQ(rotr(uint32_t{0x12345678UL}, 4), uint32_t{0x81234567UL});
+ EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, 4),
+ uint64_t{0x112345678ABCDEF0ULL});
+
+ EXPECT_EQ(rotr(uint8_t{0x12}, -4), uint8_t{0x21});
+ EXPECT_EQ(rotr(uint16_t{0x1234}, -4), uint16_t{0x2341});
+ EXPECT_EQ(rotr(uint32_t{0x12345678UL}, -4), uint32_t{0x23456781UL});
+ EXPECT_EQ(rotr(uint64_t{0x12345678ABCDEF01ULL}, -4),
+ uint64_t{0x2345678ABCDEF011ULL});
+}
+
+TEST(Rotate, Symmetry) {
+ // rotr(x, s) is equivalent to rotl(x, -s)
+ absl::BitGen rng;
+ constexpr int kTrials = 100;
+
+ for (int i = 0; i < kTrials; ++i) {
+ uint8_t value = absl::Uniform(rng, std::numeric_limits<uint8_t>::min(),
+ std::numeric_limits<uint8_t>::max());
+ int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint8_t>::digits,
+ 2 * std::numeric_limits<uint8_t>::digits);
+
+ EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ uint16_t value = absl::Uniform(rng, std::numeric_limits<uint16_t>::min(),
+ std::numeric_limits<uint16_t>::max());
+ int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint16_t>::digits,
+ 2 * std::numeric_limits<uint16_t>::digits);
+
+ EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ uint32_t value = absl::Uniform(rng, std::numeric_limits<uint32_t>::min(),
+ std::numeric_limits<uint32_t>::max());
+ int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint32_t>::digits,
+ 2 * std::numeric_limits<uint32_t>::digits);
+
+ EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ uint64_t value = absl::Uniform(rng, std::numeric_limits<uint64_t>::min(),
+ std::numeric_limits<uint64_t>::max());
+ int shift = absl::Uniform(rng, -2 * std::numeric_limits<uint64_t>::digits,
+ 2 * std::numeric_limits<uint64_t>::digits);
+
+ EXPECT_EQ(rotl(value, shift), rotr(value, -shift));
+ }
+}
+
+TEST(Counting, LeadingZeroes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+ static_assert(countl_zero(uint8_t{}) == 8, "");
+ static_assert(countl_zero(static_cast<uint8_t>(-1)) == 0, "");
+ static_assert(countl_zero(uint16_t{}) == 16, "");
+ static_assert(countl_zero(static_cast<uint16_t>(-1)) == 0, "");
+ static_assert(countl_zero(uint32_t{}) == 32, "");
+ static_assert(countl_zero(~uint32_t{}) == 0, "");
+ static_assert(countl_zero(uint64_t{}) == 64, "");
+ static_assert(countl_zero(~uint64_t{}) == 0, "");
+#endif
+
+ EXPECT_EQ(countl_zero(uint8_t{}), 8);
+ EXPECT_EQ(countl_zero(static_cast<uint8_t>(-1)), 0);
+ EXPECT_EQ(countl_zero(uint16_t{}), 16);
+ EXPECT_EQ(countl_zero(static_cast<uint16_t>(-1)), 0);
+ EXPECT_EQ(countl_zero(uint32_t{}), 32);
+ EXPECT_EQ(countl_zero(~uint32_t{}), 0);
+ EXPECT_EQ(countl_zero(uint64_t{}), 64);
+ EXPECT_EQ(countl_zero(~uint64_t{}), 0);
+
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(countl_zero(static_cast<uint8_t>(1u << i)), 7 - i);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ EXPECT_EQ(countl_zero(static_cast<uint16_t>(1u << i)), 15 - i);
+ }
+
+ for (int i = 0; i < 32; i++) {
+ EXPECT_EQ(countl_zero(uint32_t{1} << i), 31 - i);
+ }
+
+ for (int i = 0; i < 64; i++) {
+ EXPECT_EQ(countl_zero(uint64_t{1} << i), 63 - i);
+ }
+}
+
+TEST(Counting, LeadingOnes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+ static_assert(countl_one(uint8_t{}) == 0, "");
+ static_assert(countl_one(static_cast<uint8_t>(-1)) == 8, "");
+ static_assert(countl_one(uint16_t{}) == 0, "");
+ static_assert(countl_one(static_cast<uint16_t>(-1)) == 16, "");
+ static_assert(countl_one(uint32_t{}) == 0, "");
+ static_assert(countl_one(~uint32_t{}) == 32, "");
+ static_assert(countl_one(uint64_t{}) == 0, "");
+ static_assert(countl_one(~uint64_t{}) == 64, "");
+#endif
+
+ EXPECT_EQ(countl_one(uint8_t{}), 0);
+ EXPECT_EQ(countl_one(static_cast<uint8_t>(-1)), 8);
+ EXPECT_EQ(countl_one(uint16_t{}), 0);
+ EXPECT_EQ(countl_one(static_cast<uint16_t>(-1)), 16);
+ EXPECT_EQ(countl_one(uint32_t{}), 0);
+ EXPECT_EQ(countl_one(~uint32_t{}), 32);
+ EXPECT_EQ(countl_one(uint64_t{}), 0);
+ EXPECT_EQ(countl_one(~uint64_t{}), 64);
+}
+
+TEST(Counting, TrailingZeroes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ
+ static_assert(countr_zero(uint8_t{}) == 8, "");
+ static_assert(countr_zero(static_cast<uint8_t>(-1)) == 0, "");
+ static_assert(countr_zero(uint16_t{}) == 16, "");
+ static_assert(countr_zero(static_cast<uint16_t>(-1)) == 0, "");
+ static_assert(countr_zero(uint32_t{}) == 32, "");
+ static_assert(countr_zero(~uint32_t{}) == 0, "");
+ static_assert(countr_zero(uint64_t{}) == 64, "");
+ static_assert(countr_zero(~uint64_t{}) == 0, "");
+#endif
+
+ EXPECT_EQ(countr_zero(uint8_t{}), 8);
+ EXPECT_EQ(countr_zero(static_cast<uint8_t>(-1)), 0);
+ EXPECT_EQ(countr_zero(uint16_t{}), 16);
+ EXPECT_EQ(countr_zero(static_cast<uint16_t>(-1)), 0);
+ EXPECT_EQ(countr_zero(uint32_t{}), 32);
+ EXPECT_EQ(countr_zero(~uint32_t{}), 0);
+ EXPECT_EQ(countr_zero(uint64_t{}), 64);
+ EXPECT_EQ(countr_zero(~uint64_t{}), 0);
+}
+
+TEST(Counting, TrailingOnes) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CTZ
+ static_assert(countr_one(uint8_t{}) == 0, "");
+ static_assert(countr_one(static_cast<uint8_t>(-1)) == 8, "");
+ static_assert(countr_one(uint16_t{}) == 0, "");
+ static_assert(countr_one(static_cast<uint16_t>(-1)) == 16, "");
+ static_assert(countr_one(uint32_t{}) == 0, "");
+ static_assert(countr_one(~uint32_t{}) == 32, "");
+ static_assert(countr_one(uint64_t{}) == 0, "");
+ static_assert(countr_one(~uint64_t{}) == 64, "");
+#endif
+
+ EXPECT_EQ(countr_one(uint8_t{}), 0);
+ EXPECT_EQ(countr_one(static_cast<uint8_t>(-1)), 8);
+ EXPECT_EQ(countr_one(uint16_t{}), 0);
+ EXPECT_EQ(countr_one(static_cast<uint16_t>(-1)), 16);
+ EXPECT_EQ(countr_one(uint32_t{}), 0);
+ EXPECT_EQ(countr_one(~uint32_t{}), 32);
+ EXPECT_EQ(countr_one(uint64_t{}), 0);
+ EXPECT_EQ(countr_one(~uint64_t{}), 64);
+}
+
+TEST(Counting, Popcount) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT
+ static_assert(popcount(uint8_t{}) == 0, "");
+ static_assert(popcount(uint8_t{1}) == 1, "");
+ static_assert(popcount(static_cast<uint8_t>(-1)) == 8, "");
+ static_assert(popcount(uint16_t{}) == 0, "");
+ static_assert(popcount(uint16_t{1}) == 1, "");
+ static_assert(popcount(static_cast<uint16_t>(-1)) == 16, "");
+ static_assert(popcount(uint32_t{}) == 0, "");
+ static_assert(popcount(uint32_t{1}) == 1, "");
+ static_assert(popcount(~uint32_t{}) == 32, "");
+ static_assert(popcount(uint64_t{}) == 0, "");
+ static_assert(popcount(uint64_t{1}) == 1, "");
+ static_assert(popcount(~uint64_t{}) == 64, "");
+#endif // ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT
+
+ EXPECT_EQ(popcount(uint8_t{}), 0);
+ EXPECT_EQ(popcount(uint8_t{1}), 1);
+ EXPECT_EQ(popcount(static_cast<uint8_t>(-1)), 8);
+ EXPECT_EQ(popcount(uint16_t{}), 0);
+ EXPECT_EQ(popcount(uint16_t{1}), 1);
+ EXPECT_EQ(popcount(static_cast<uint16_t>(-1)), 16);
+ EXPECT_EQ(popcount(uint32_t{}), 0);
+ EXPECT_EQ(popcount(uint32_t{1}), 1);
+ EXPECT_EQ(popcount(~uint32_t{}), 32);
+ EXPECT_EQ(popcount(uint64_t{}), 0);
+ EXPECT_EQ(popcount(uint64_t{1}), 1);
+ EXPECT_EQ(popcount(~uint64_t{}), 64);
+
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(popcount(static_cast<uint8_t>(uint8_t{1} << i)), 1);
+ EXPECT_EQ(popcount(static_cast<uint8_t>(static_cast<uint8_t>(-1) ^
+ (uint8_t{1} << i))),
+ 7);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ EXPECT_EQ(popcount(static_cast<uint16_t>(uint16_t{1} << i)), 1);
+ EXPECT_EQ(popcount(static_cast<uint16_t>(static_cast<uint16_t>(-1) ^
+ (uint16_t{1} << i))),
+ 15);
+ }
+
+ for (int i = 0; i < 32; i++) {
+ EXPECT_EQ(popcount(uint32_t{1} << i), 1);
+ EXPECT_EQ(popcount(static_cast<uint32_t>(-1) ^ (uint32_t{1} << i)), 31);
+ }
+
+ for (int i = 0; i < 64; i++) {
+ EXPECT_EQ(popcount(uint64_t{1} << i), 1);
+ EXPECT_EQ(popcount(static_cast<uint64_t>(-1) ^ (uint64_t{1} << i)), 63);
+ }
+}
+
+template <typename T>
+struct PopcountInput {
+ T value = 0;
+ int expected = 0;
+};
+
+template <typename T>
+PopcountInput<T> GeneratePopcountInput(absl::BitGen& gen) {
+ PopcountInput<T> ret;
+ for (int i = 0; i < std::numeric_limits<T>::digits; i++) {
+ bool coin = absl::Bernoulli(gen, 0.2);
+ if (coin) {
+ ret.value |= T{1} << i;
+ ret.expected++;
+ }
+ }
+ return ret;
+}
+
+TEST(Counting, PopcountFuzz) {
+ absl::BitGen rng;
+ constexpr int kTrials = 100;
+
+ for (int i = 0; i < kTrials; ++i) {
+ auto input = GeneratePopcountInput<uint8_t>(rng);
+ EXPECT_EQ(popcount(input.value), input.expected);
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ auto input = GeneratePopcountInput<uint16_t>(rng);
+ EXPECT_EQ(popcount(input.value), input.expected);
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ auto input = GeneratePopcountInput<uint32_t>(rng);
+ EXPECT_EQ(popcount(input.value), input.expected);
+ }
+
+ for (int i = 0; i < kTrials; ++i) {
+ auto input = GeneratePopcountInput<uint64_t>(rng);
+ EXPECT_EQ(popcount(input.value), input.expected);
+ }
+}
+
+TEST(IntegralPowersOfTwo, SingleBit) {
+ EXPECT_FALSE(has_single_bit(uint8_t{}));
+ EXPECT_FALSE(has_single_bit(static_cast<uint8_t>(-1)));
+ EXPECT_FALSE(has_single_bit(uint16_t{}));
+ EXPECT_FALSE(has_single_bit(static_cast<uint16_t>(-1)));
+ EXPECT_FALSE(has_single_bit(uint32_t{}));
+ EXPECT_FALSE(has_single_bit(~uint32_t{}));
+ EXPECT_FALSE(has_single_bit(uint64_t{}));
+ EXPECT_FALSE(has_single_bit(~uint64_t{}));
+
+ static_assert(!has_single_bit(0u), "");
+ static_assert(has_single_bit(1u), "");
+ static_assert(has_single_bit(2u), "");
+ static_assert(!has_single_bit(3u), "");
+ static_assert(has_single_bit(4u), "");
+ static_assert(!has_single_bit(1337u), "");
+ static_assert(has_single_bit(65536u), "");
+ static_assert(has_single_bit(uint32_t{1} << 30), "");
+ static_assert(has_single_bit(uint64_t{1} << 42), "");
+
+ EXPECT_FALSE(has_single_bit(0u));
+ EXPECT_TRUE(has_single_bit(1u));
+ EXPECT_TRUE(has_single_bit(2u));
+ EXPECT_FALSE(has_single_bit(3u));
+ EXPECT_TRUE(has_single_bit(4u));
+ EXPECT_FALSE(has_single_bit(1337u));
+ EXPECT_TRUE(has_single_bit(65536u));
+ EXPECT_TRUE(has_single_bit(uint32_t{1} << 30));
+ EXPECT_TRUE(has_single_bit(uint64_t{1} << 42));
+
+ EXPECT_TRUE(has_single_bit(
+ static_cast<uint8_t>(std::numeric_limits<uint8_t>::max() / 2 + 1)));
+ EXPECT_TRUE(has_single_bit(
+ static_cast<uint16_t>(std::numeric_limits<uint16_t>::max() / 2 + 1)));
+ EXPECT_TRUE(has_single_bit(
+ static_cast<uint32_t>(std::numeric_limits<uint32_t>::max() / 2 + 1)));
+ EXPECT_TRUE(has_single_bit(
+ static_cast<uint64_t>(std::numeric_limits<uint64_t>::max() / 2 + 1)));
+}
+
+template <typename T, T arg, T = bit_ceil(arg)>
+bool IsBitCeilConstantExpression(int) {
+ return true;
+}
+template <typename T, T arg>
+bool IsBitCeilConstantExpression(char) {
+ return false;
+}
+
+TEST(IntegralPowersOfTwo, Ceiling) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+ static_assert(bit_ceil(0u) == 1, "");
+ static_assert(bit_ceil(1u) == 1, "");
+ static_assert(bit_ceil(2u) == 2, "");
+ static_assert(bit_ceil(3u) == 4, "");
+ static_assert(bit_ceil(4u) == 4, "");
+ static_assert(bit_ceil(1337u) == 2048, "");
+ static_assert(bit_ceil(65536u) == 65536, "");
+ static_assert(bit_ceil(65536u - 1337u) == 65536, "");
+ static_assert(bit_ceil(uint32_t{0x80000000}) == uint32_t{0x80000000}, "");
+ static_assert(bit_ceil(uint64_t{0x40000000000}) == uint64_t{0x40000000000},
+ "");
+ static_assert(
+ bit_ceil(uint64_t{0x8000000000000000}) == uint64_t{0x8000000000000000},
+ "");
+
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x0}>(0)));
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x80}>(0)));
+ EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0x81}>(0)));
+ EXPECT_FALSE((IsBitCeilConstantExpression<uint8_t, uint8_t{0xff}>(0)));
+
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x0}>(0)));
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8000}>(0)));
+ EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0x8001}>(0)));
+ EXPECT_FALSE((IsBitCeilConstantExpression<uint16_t, uint16_t{0xffff}>(0)));
+
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x0}>(0)));
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000000}>(0)));
+ EXPECT_FALSE(
+ (IsBitCeilConstantExpression<uint32_t, uint32_t{0x80000001}>(0)));
+ EXPECT_FALSE(
+ (IsBitCeilConstantExpression<uint32_t, uint32_t{0xffffffff}>(0)));
+
+ EXPECT_TRUE((IsBitCeilConstantExpression<uint64_t, uint64_t{0x0}>(0)));
+ EXPECT_TRUE(
+ (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000000}>(0)));
+ EXPECT_FALSE(
+ (IsBitCeilConstantExpression<uint64_t, uint64_t{0x8000000000000001}>(0)));
+ EXPECT_FALSE(
+ (IsBitCeilConstantExpression<uint64_t, uint64_t{0xffffffffffffffff}>(0)));
+#endif
+
+ EXPECT_EQ(bit_ceil(0u), 1);
+ EXPECT_EQ(bit_ceil(1u), 1);
+ EXPECT_EQ(bit_ceil(2u), 2);
+ EXPECT_EQ(bit_ceil(3u), 4);
+ EXPECT_EQ(bit_ceil(4u), 4);
+ EXPECT_EQ(bit_ceil(1337u), 2048);
+ EXPECT_EQ(bit_ceil(65536u), 65536);
+ EXPECT_EQ(bit_ceil(65536u - 1337u), 65536);
+ EXPECT_EQ(bit_ceil(uint64_t{0x40000000000}), uint64_t{0x40000000000});
+}
+
+TEST(IntegralPowersOfTwo, Floor) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+ static_assert(bit_floor(0u) == 0, "");
+ static_assert(bit_floor(1u) == 1, "");
+ static_assert(bit_floor(2u) == 2, "");
+ static_assert(bit_floor(3u) == 2, "");
+ static_assert(bit_floor(4u) == 4, "");
+ static_assert(bit_floor(1337u) == 1024, "");
+ static_assert(bit_floor(65536u) == 65536, "");
+ static_assert(bit_floor(65536u - 1337u) == 32768, "");
+ static_assert(bit_floor(uint64_t{0x40000000000}) == uint64_t{0x40000000000},
+ "");
+#endif
+
+ EXPECT_EQ(bit_floor(0u), 0);
+ EXPECT_EQ(bit_floor(1u), 1);
+ EXPECT_EQ(bit_floor(2u), 2);
+ EXPECT_EQ(bit_floor(3u), 2);
+ EXPECT_EQ(bit_floor(4u), 4);
+ EXPECT_EQ(bit_floor(1337u), 1024);
+ EXPECT_EQ(bit_floor(65536u), 65536);
+ EXPECT_EQ(bit_floor(65536u - 1337u), 32768);
+ EXPECT_EQ(bit_floor(uint64_t{0x40000000000}), uint64_t{0x40000000000});
+
+ for (int i = 0; i < 8; i++) {
+ uint8_t input = uint8_t{1} << i;
+ EXPECT_EQ(bit_floor(input), input);
+ if (i > 0) {
+ EXPECT_EQ(bit_floor(static_cast<uint8_t>(input + 1)), input);
+ }
+ }
+
+ for (int i = 0; i < 16; i++) {
+ uint16_t input = uint16_t{1} << i;
+ EXPECT_EQ(bit_floor(input), input);
+ if (i > 0) {
+ EXPECT_EQ(bit_floor(static_cast<uint16_t>(input + 1)), input);
+ }
+ }
+
+ for (int i = 0; i < 32; i++) {
+ uint32_t input = uint32_t{1} << i;
+ EXPECT_EQ(bit_floor(input), input);
+ if (i > 0) {
+ EXPECT_EQ(bit_floor(input + 1), input);
+ }
+ }
+
+ for (int i = 0; i < 64; i++) {
+ uint64_t input = uint64_t{1} << i;
+ EXPECT_EQ(bit_floor(input), input);
+ if (i > 0) {
+ EXPECT_EQ(bit_floor(input + 1), input);
+ }
+ }
+}
+
+TEST(IntegralPowersOfTwo, Width) {
+#if ABSL_INTERNAL_HAS_CONSTEXPR_CLZ
+ static_assert(bit_width(uint8_t{}) == 0, "");
+ static_assert(bit_width(uint8_t{1}) == 1, "");
+ static_assert(bit_width(uint8_t{3}) == 2, "");
+ static_assert(bit_width(static_cast<uint8_t>(-1)) == 8, "");
+ static_assert(bit_width(uint16_t{}) == 0, "");
+ static_assert(bit_width(uint16_t{1}) == 1, "");
+ static_assert(bit_width(uint16_t{3}) == 2, "");
+ static_assert(bit_width(static_cast<uint16_t>(-1)) == 16, "");
+ static_assert(bit_width(uint32_t{}) == 0, "");
+ static_assert(bit_width(uint32_t{1}) == 1, "");
+ static_assert(bit_width(uint32_t{3}) == 2, "");
+ static_assert(bit_width(~uint32_t{}) == 32, "");
+ static_assert(bit_width(uint64_t{}) == 0, "");
+ static_assert(bit_width(uint64_t{1}) == 1, "");
+ static_assert(bit_width(uint64_t{3}) == 2, "");
+ static_assert(bit_width(~uint64_t{}) == 64, "");
+#endif
+
+ EXPECT_EQ(bit_width(uint8_t{}), 0);
+ EXPECT_EQ(bit_width(uint8_t{1}), 1);
+ EXPECT_EQ(bit_width(uint8_t{3}), 2);
+ EXPECT_EQ(bit_width(static_cast<uint8_t>(-1)), 8);
+ EXPECT_EQ(bit_width(uint16_t{}), 0);
+ EXPECT_EQ(bit_width(uint16_t{1}), 1);
+ EXPECT_EQ(bit_width(uint16_t{3}), 2);
+ EXPECT_EQ(bit_width(static_cast<uint16_t>(-1)), 16);
+ EXPECT_EQ(bit_width(uint32_t{}), 0);
+ EXPECT_EQ(bit_width(uint32_t{1}), 1);
+ EXPECT_EQ(bit_width(uint32_t{3}), 2);
+ EXPECT_EQ(bit_width(~uint32_t{}), 32);
+ EXPECT_EQ(bit_width(uint64_t{}), 0);
+ EXPECT_EQ(bit_width(uint64_t{1}), 1);
+ EXPECT_EQ(bit_width(uint64_t{3}), 2);
+ EXPECT_EQ(bit_width(~uint64_t{}), 64);
+
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(bit_width(static_cast<uint8_t>(uint8_t{1} << i)), i + 1);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ EXPECT_EQ(bit_width(static_cast<uint16_t>(uint16_t{1} << i)), i + 1);
+ }
+
+ for (int i = 0; i < 32; i++) {
+ EXPECT_EQ(bit_width(uint32_t{1} << i), i + 1);
+ }
+
+ for (int i = 0; i < 64; i++) {
+ EXPECT_EQ(bit_width(uint64_t{1} << i), i + 1);
+ }
+}
+
+// On GCC and Clang, anticiapte that implementations will be constexpr
+#if defined(__GNUC__)
+static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT,
+ "popcount should be constexpr");
+static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CLZ, "clz should be constexpr");
+static_assert(ABSL_INTERNAL_HAS_CONSTEXPR_CTZ, "ctz should be constexpr");
+#endif
+
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.cc
index 3c37f252a79..5160df793ea 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/numeric/int128.h"
#include <stddef.h>
+
#include <cassert>
#include <iomanip>
#include <ostream> // NOLINT(readability/streams)
@@ -22,52 +23,38 @@
#include <string>
#include <type_traits>
+#include "absl/base/optimization.h"
+#include "absl/numeric/bits.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
-const uint128 kuint128max = MakeUint128(std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::max());
+ABSL_DLL const uint128 kuint128max = MakeUint128(
+ std::numeric_limits<uint64_t>::max(), std::numeric_limits<uint64_t>::max());
namespace {
// Returns the 0-based position of the last set bit (i.e., most significant bit)
-// in the given uint64_t. The argument may not be 0.
+// in the given uint128. The argument is not 0.
//
// For example:
// Given: 5 (decimal) == 101 (binary)
// Returns: 2
-#define STEP(T, n, pos, sh) \
- do { \
- if ((n) >= (static_cast<T>(1) << (sh))) { \
- (n) = (n) >> (sh); \
- (pos) |= (sh); \
- } \
- } while (0)
-static inline int Fls64(uint64_t n) {
- assert(n != 0);
- int pos = 0;
- STEP(uint64_t, n, pos, 0x20);
- uint32_t n32 = static_cast<uint32_t>(n);
- STEP(uint32_t, n32, pos, 0x10);
- STEP(uint32_t, n32, pos, 0x08);
- STEP(uint32_t, n32, pos, 0x04);
- return pos + ((uint64_t{0x3333333322221100} >> (n32 << 2)) & 0x3);
-}
-#undef STEP
-
-// Like Fls64() above, but returns the 0-based position of the last set bit
-// (i.e., most significant bit) in the given uint128. The argument may not be 0.
-static inline int Fls128(uint128 n) {
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) {
if (uint64_t hi = Uint128High64(n)) {
- return Fls64(hi) + 64;
+ ABSL_INTERNAL_ASSUME(hi != 0);
+ return 127 - countl_zero(hi);
}
- return Fls64(Uint128Low64(n));
+ const uint64_t low = Uint128Low64(n);
+ ABSL_INTERNAL_ASSUME(low != 0);
+ return 63 - countl_zero(low);
}
// Long division/modulo for uint128 implemented using the shift-subtract
// division algorithm adapted from:
-// http://stackoverflow.com/questions/5386377/division-without-using
-void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
- uint128* remainder_ret) {
+// https://stackoverflow.com/questions/5386377/division-without-using
+inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
+ uint128* remainder_ret) {
assert(divisor != 0);
if (divisor > dividend) {
@@ -123,6 +110,28 @@ uint128 MakeUint128FromFloat(T v) {
return MakeUint128(0, static_cast<uint64_t>(v));
}
+
+#if defined(__clang__) && !defined(__SSE3__)
+// Workaround for clang bug: https://bugs.llvm.org/show_bug.cgi?id=38289
+// Casting from long double to uint64_t is miscompiled and drops bits.
+// It is more work, so only use when we need the workaround.
+uint128 MakeUint128FromFloat(long double v) {
+ // Go 50 bits at a time, that fits in a double
+ static_assert(std::numeric_limits<double>::digits >= 50, "");
+ static_assert(std::numeric_limits<long double>::digits <= 150, "");
+ // Undefined behavior if v is not finite or cannot fit into uint128.
+ assert(std::isfinite(v) && v > -1 && v < std::ldexp(1.0L, 128));
+
+ v = std::ldexp(v, -100);
+ uint64_t w0 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+ v = std::ldexp(v - static_cast<double>(w0), 50);
+ uint64_t w1 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+ v = std::ldexp(v - static_cast<double>(w1), 50);
+ uint64_t w2 = static_cast<uint64_t>(static_cast<double>(std::trunc(v)));
+ return (static_cast<uint128>(w0) << 100) | (static_cast<uint128>(w1) << 50) |
+ static_cast<uint128>(w2);
+}
+#endif // __clang__ && !__SSE3__
} // namespace
uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
@@ -222,6 +231,112 @@ std::ostream& operator<<(std::ostream& os, uint128 v) {
return os << rep;
}
+namespace {
+
+uint128 UnsignedAbsoluteValue(int128 v) {
+ // Cast to uint128 before possibly negating because -Int128Min() is undefined.
+ return Int128High64(v) < 0 ? -uint128(v) : uint128(v);
+}
+
+} // namespace
+
+#if !defined(ABSL_HAVE_INTRINSIC_INT128)
+namespace {
+
+template <typename T>
+int128 MakeInt128FromFloat(T v) {
+ // Conversion when v is NaN or cannot fit into int128 would be undefined
+ // behavior if using an intrinsic 128-bit integer.
+ assert(std::isfinite(v) && (std::numeric_limits<T>::max_exponent <= 127 ||
+ (v >= -std::ldexp(static_cast<T>(1), 127) &&
+ v < std::ldexp(static_cast<T>(1), 127))));
+
+ // We must convert the absolute value and then negate as needed, because
+ // floating point types are typically sign-magnitude. Otherwise, the
+ // difference between the high and low 64 bits when interpreted as two's
+ // complement overwhelms the precision of the mantissa.
+ uint128 result = v < 0 ? -MakeUint128FromFloat(-v) : MakeUint128FromFloat(v);
+ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
+ Uint128Low64(result));
+}
+
+} // namespace
+
+int128::int128(float v) : int128(MakeInt128FromFloat(v)) {}
+int128::int128(double v) : int128(MakeInt128FromFloat(v)) {}
+int128::int128(long double v) : int128(MakeInt128FromFloat(v)) {}
+
+int128 operator/(int128 lhs, int128 rhs) {
+ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement.
+
+ uint128 quotient = 0;
+ uint128 remainder = 0;
+ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
+ &quotient, &remainder);
+ if ((Int128High64(lhs) < 0) != (Int128High64(rhs) < 0)) quotient = -quotient;
+ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(quotient)),
+ Uint128Low64(quotient));
+}
+
+int128 operator%(int128 lhs, int128 rhs) {
+ assert(lhs != Int128Min() || rhs != -1); // UB on two's complement.
+
+ uint128 quotient = 0;
+ uint128 remainder = 0;
+ DivModImpl(UnsignedAbsoluteValue(lhs), UnsignedAbsoluteValue(rhs),
+ &quotient, &remainder);
+ if (Int128High64(lhs) < 0) remainder = -remainder;
+ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(remainder)),
+ Uint128Low64(remainder));
+}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+std::ostream& operator<<(std::ostream& os, int128 v) {
+ std::ios_base::fmtflags flags = os.flags();
+ std::string rep;
+
+ // Add the sign if needed.
+ bool print_as_decimal =
+ (flags & std::ios::basefield) == std::ios::dec ||
+ (flags & std::ios::basefield) == std::ios_base::fmtflags();
+ if (print_as_decimal) {
+ if (Int128High64(v) < 0) {
+ rep = "-";
+ } else if (flags & std::ios::showpos) {
+ rep = "+";
+ }
+ }
+
+ rep.append(Uint128ToFormattedString(
+ print_as_decimal ? UnsignedAbsoluteValue(v) : uint128(v), os.flags()));
+
+ // Add the requisite padding.
+ std::streamsize width = os.width(0);
+ if (static_cast<size_t>(width) > rep.size()) {
+ switch (flags & std::ios::adjustfield) {
+ case std::ios::left:
+ rep.append(width - rep.size(), os.fill());
+ break;
+ case std::ios::internal:
+ if (print_as_decimal && (rep[0] == '+' || rep[0] == '-')) {
+ rep.insert(1, width - rep.size(), os.fill());
+ } else if ((flags & std::ios::basefield) == std::ios::hex &&
+ (flags & std::ios::showbase) && v != 0) {
+ rep.insert(2, width - rep.size(), os.fill());
+ } else {
+ rep.insert(0, width - rep.size(), os.fill());
+ }
+ break;
+ default: // std::ios::right
+ rep.insert(0, width - rep.size(), os.fill());
+ break;
+ }
+ }
+
+ return os << rep;
+}
+
+ABSL_NAMESPACE_END
} // namespace absl
namespace std {
@@ -248,4 +363,28 @@ constexpr int numeric_limits<absl::uint128>::max_exponent;
constexpr int numeric_limits<absl::uint128>::max_exponent10;
constexpr bool numeric_limits<absl::uint128>::traps;
constexpr bool numeric_limits<absl::uint128>::tinyness_before;
+
+constexpr bool numeric_limits<absl::int128>::is_specialized;
+constexpr bool numeric_limits<absl::int128>::is_signed;
+constexpr bool numeric_limits<absl::int128>::is_integer;
+constexpr bool numeric_limits<absl::int128>::is_exact;
+constexpr bool numeric_limits<absl::int128>::has_infinity;
+constexpr bool numeric_limits<absl::int128>::has_quiet_NaN;
+constexpr bool numeric_limits<absl::int128>::has_signaling_NaN;
+constexpr float_denorm_style numeric_limits<absl::int128>::has_denorm;
+constexpr bool numeric_limits<absl::int128>::has_denorm_loss;
+constexpr float_round_style numeric_limits<absl::int128>::round_style;
+constexpr bool numeric_limits<absl::int128>::is_iec559;
+constexpr bool numeric_limits<absl::int128>::is_bounded;
+constexpr bool numeric_limits<absl::int128>::is_modulo;
+constexpr int numeric_limits<absl::int128>::digits;
+constexpr int numeric_limits<absl::int128>::digits10;
+constexpr int numeric_limits<absl::int128>::max_digits10;
+constexpr int numeric_limits<absl::int128>::radix;
+constexpr int numeric_limits<absl::int128>::min_exponent;
+constexpr int numeric_limits<absl::int128>::min_exponent10;
+constexpr int numeric_limits<absl::int128>::max_exponent;
+constexpr int numeric_limits<absl::int128>::max_exponent10;
+constexpr bool numeric_limits<absl::int128>::traps;
+constexpr bool numeric_limits<absl::int128>::tinyness_before;
} // namespace std
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.h
index 9c36c57116c..0dd814a890e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,10 +17,7 @@
// File: int128.h
// -----------------------------------------------------------------------------
//
-// This header file defines 128-bit integer types.
-//
-// Currently, this file defines `uint128`, an unsigned 128-bit integer; a signed
-// 128-bit integer is forthcoming.
+// This header file defines 128-bit integer types, `uint128` and `int128`.
#ifndef ABSL_NUMERIC_INT128_H_
#define ABSL_NUMERIC_INT128_H_
@@ -43,16 +40,18 @@
// builtin type. We need to make sure not to define operator wchar_t()
// alongside operator unsigned short() in these instances.
#define ABSL_INTERNAL_WCHAR_T __wchar_t
-#if defined(_WIN64)
+#if defined(_M_X64)
#include <intrin.h>
#pragma intrinsic(_umul128)
-#endif // defined(_WIN64)
+#endif // defined(_M_X64)
#else // defined(_MSC_VER)
#define ABSL_INTERNAL_WCHAR_T wchar_t
#endif // defined(_MSC_VER)
namespace absl {
+ABSL_NAMESPACE_BEGIN
+class int128;
// uint128
//
@@ -117,6 +116,7 @@ class
constexpr uint128(__int128 v); // NOLINT(runtime/explicit)
constexpr uint128(unsigned __int128 v); // NOLINT(runtime/explicit)
#endif // ABSL_HAVE_INTRINSIC_INT128
+ constexpr uint128(int128 v); // NOLINT(runtime/explicit)
explicit uint128(float v);
explicit uint128(double v);
explicit uint128(long double v);
@@ -132,6 +132,7 @@ class
uint128& operator=(__int128 v);
uint128& operator=(unsigned __int128 v);
#endif // ABSL_HAVE_INTRINSIC_INT128
+ uint128& operator=(int128 v);
// Conversion operators to other arithmetic types
constexpr explicit operator bool() const;
@@ -233,7 +234,7 @@ class
// Prefer to use the constexpr `Uint128Max()`.
//
// TODO(absl-team) deprecate kuint128max once migration tool is released.
-extern const uint128 kuint128max;
+ABSL_DLL extern const uint128 kuint128max;
// allow uint128 to be logged
std::ostream& operator<<(std::ostream& os, uint128 v);
@@ -245,6 +246,7 @@ constexpr uint128 Uint128Max() {
(std::numeric_limits<uint64_t>::max)());
}
+ABSL_NAMESPACE_END
} // namespace absl
// Specialized numeric_limits for uint128.
@@ -292,12 +294,246 @@ class numeric_limits<absl::uint128> {
};
} // namespace std
-// TODO(absl-team): Implement signed 128-bit type
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// int128
+//
+// A signed 128-bit integer type. The API is meant to mimic an intrinsic
+// integral type as closely as is practical, including exhibiting undefined
+// behavior in analogous cases (e.g. division by zero).
+//
+// An `int128` supports the following:
+//
+// * Implicit construction from integral types
+// * Explicit conversion to integral types
+//
+// However, an `int128` differs from intrinsic integral types in the following
+// ways:
+//
+// * It is not implicitly convertible to other integral types.
+// * Requires explicit construction from and conversion to floating point
+// types.
+
+// Additionally, if your compiler supports `__int128`, `int128` is
+// interoperable with that type. (Abseil checks for this compatibility through
+// the `ABSL_HAVE_INTRINSIC_INT128` macro.)
+//
+// The design goal for `int128` is that it will be compatible with a future
+// `int128_t`, if that type becomes a part of the standard.
+//
+// Example:
+//
+// float y = absl::int128(17); // Error. int128 cannot be implicitly
+// // converted to float.
+//
+// absl::int128 v;
+// int64_t i = v; // Error
+// int64_t i = static_cast<int64_t>(v); // OK
+//
+class int128 {
+ public:
+ int128() = default;
+
+ // Constructors from arithmetic types
+ constexpr int128(int v); // NOLINT(runtime/explicit)
+ constexpr int128(unsigned int v); // NOLINT(runtime/explicit)
+ constexpr int128(long v); // NOLINT(runtime/int)
+ constexpr int128(unsigned long v); // NOLINT(runtime/int)
+ constexpr int128(long long v); // NOLINT(runtime/int)
+ constexpr int128(unsigned long long v); // NOLINT(runtime/int)
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ constexpr int128(__int128 v); // NOLINT(runtime/explicit)
+ constexpr explicit int128(unsigned __int128 v);
+#endif // ABSL_HAVE_INTRINSIC_INT128
+ constexpr explicit int128(uint128 v);
+ explicit int128(float v);
+ explicit int128(double v);
+ explicit int128(long double v);
+
+ // Assignment operators from arithmetic types
+ int128& operator=(int v);
+ int128& operator=(unsigned int v);
+ int128& operator=(long v); // NOLINT(runtime/int)
+ int128& operator=(unsigned long v); // NOLINT(runtime/int)
+ int128& operator=(long long v); // NOLINT(runtime/int)
+ int128& operator=(unsigned long long v); // NOLINT(runtime/int)
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ int128& operator=(__int128 v);
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+ // Conversion operators to other arithmetic types
+ constexpr explicit operator bool() const;
+ constexpr explicit operator char() const;
+ constexpr explicit operator signed char() const;
+ constexpr explicit operator unsigned char() const;
+ constexpr explicit operator char16_t() const;
+ constexpr explicit operator char32_t() const;
+ constexpr explicit operator ABSL_INTERNAL_WCHAR_T() const;
+ constexpr explicit operator short() const; // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ constexpr explicit operator unsigned short() const;
+ constexpr explicit operator int() const;
+ constexpr explicit operator unsigned int() const;
+ constexpr explicit operator long() const; // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ constexpr explicit operator unsigned long() const;
+ // NOLINTNEXTLINE(runtime/int)
+ constexpr explicit operator long long() const;
+ // NOLINTNEXTLINE(runtime/int)
+ constexpr explicit operator unsigned long long() const;
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ constexpr explicit operator __int128() const;
+ constexpr explicit operator unsigned __int128() const;
+#endif // ABSL_HAVE_INTRINSIC_INT128
+ explicit operator float() const;
+ explicit operator double() const;
+ explicit operator long double() const;
+
+ // Trivial copy constructor, assignment operator and destructor.
+
+ // Arithmetic operators
+ int128& operator+=(int128 other);
+ int128& operator-=(int128 other);
+ int128& operator*=(int128 other);
+ int128& operator/=(int128 other);
+ int128& operator%=(int128 other);
+ int128 operator++(int); // postfix increment: i++
+ int128 operator--(int); // postfix decrement: i--
+ int128& operator++(); // prefix increment: ++i
+ int128& operator--(); // prefix decrement: --i
+ int128& operator&=(int128 other);
+ int128& operator|=(int128 other);
+ int128& operator^=(int128 other);
+ int128& operator<<=(int amount);
+ int128& operator>>=(int amount);
+
+ // Int128Low64()
+ //
+ // Returns the lower 64-bit value of a `int128` value.
+ friend constexpr uint64_t Int128Low64(int128 v);
+
+ // Int128High64()
+ //
+ // Returns the higher 64-bit value of a `int128` value.
+ friend constexpr int64_t Int128High64(int128 v);
+
+ // MakeInt128()
+ //
+ // Constructs a `int128` numeric value from two 64-bit integers. Note that
+ // signedness is conveyed in the upper `high` value.
+ //
+ // (absl::int128(1) << 64) * high + low
+ //
+ // Note that this factory function is the only way to construct a `int128`
+ // from integer values greater than 2^64 or less than -2^64.
+ //
+ // Example:
+ //
+ // absl::int128 big = absl::MakeInt128(1, 0);
+ // absl::int128 big_n = absl::MakeInt128(-1, 0);
+ friend constexpr int128 MakeInt128(int64_t high, uint64_t low);
+
+ // Int128Max()
+ //
+ // Returns the maximum value for a 128-bit signed integer.
+ friend constexpr int128 Int128Max();
+
+ // Int128Min()
+ //
+ // Returns the minimum value for a 128-bit signed integer.
+ friend constexpr int128 Int128Min();
+
+ // Support for absl::Hash.
+ template <typename H>
+ friend H AbslHashValue(H h, int128 v) {
+ return H::combine(std::move(h), Int128High64(v), Int128Low64(v));
+ }
+
+ private:
+ constexpr int128(int64_t high, uint64_t low);
+
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ __int128 v_;
+#else // ABSL_HAVE_INTRINSIC_INT128
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+ uint64_t lo_;
+ int64_t hi_;
+#elif defined(ABSL_IS_BIG_ENDIAN)
+ int64_t hi_;
+ uint64_t lo_;
+#else // byte order
+#error "Unsupported byte order: must be little-endian or big-endian."
+#endif // byte order
+#endif // ABSL_HAVE_INTRINSIC_INT128
+};
+
+std::ostream& operator<<(std::ostream& os, int128 v);
+
+// TODO(absl-team) add operator>>(std::istream&, int128)
+
+constexpr int128 Int128Max() {
+ return int128((std::numeric_limits<int64_t>::max)(),
+ (std::numeric_limits<uint64_t>::max)());
+}
+
+constexpr int128 Int128Min() {
+ return int128((std::numeric_limits<int64_t>::min)(), 0);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// Specialized numeric_limits for int128.
+namespace std {
+template <>
+class numeric_limits<absl::int128> {
+ public:
+ static constexpr bool is_specialized = true;
+ static constexpr bool is_signed = true;
+ static constexpr bool is_integer = true;
+ static constexpr bool is_exact = true;
+ static constexpr bool has_infinity = false;
+ static constexpr bool has_quiet_NaN = false;
+ static constexpr bool has_signaling_NaN = false;
+ static constexpr float_denorm_style has_denorm = denorm_absent;
+ static constexpr bool has_denorm_loss = false;
+ static constexpr float_round_style round_style = round_toward_zero;
+ static constexpr bool is_iec559 = false;
+ static constexpr bool is_bounded = true;
+ static constexpr bool is_modulo = false;
+ static constexpr int digits = 127;
+ static constexpr int digits10 = 38;
+ static constexpr int max_digits10 = 0;
+ static constexpr int radix = 2;
+ static constexpr int min_exponent = 0;
+ static constexpr int min_exponent10 = 0;
+ static constexpr int max_exponent = 0;
+ static constexpr int max_exponent10 = 0;
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ static constexpr bool traps = numeric_limits<__int128>::traps;
+#else // ABSL_HAVE_INTRINSIC_INT128
+ static constexpr bool traps = numeric_limits<uint64_t>::traps;
+#endif // ABSL_HAVE_INTRINSIC_INT128
+ static constexpr bool tinyness_before = false;
+
+ static constexpr absl::int128 (min)() { return absl::Int128Min(); }
+ static constexpr absl::int128 lowest() { return absl::Int128Min(); }
+ static constexpr absl::int128 (max)() { return absl::Int128Max(); }
+ static constexpr absl::int128 epsilon() { return 0; }
+ static constexpr absl::int128 round_error() { return 0; }
+ static constexpr absl::int128 infinity() { return 0; }
+ static constexpr absl::int128 quiet_NaN() { return 0; }
+ static constexpr absl::int128 signaling_NaN() { return 0; }
+ static constexpr absl::int128 denorm_min() { return 0; }
+};
+} // namespace std
// --------------------------------------------------------------------------
// Implementation details follow
// --------------------------------------------------------------------------
namespace absl {
+ABSL_NAMESPACE_BEGIN
constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
return uint128(high, low);
@@ -340,6 +576,10 @@ inline uint128& uint128::operator=(unsigned __int128 v) {
}
#endif // ABSL_HAVE_INTRINSIC_INT128
+inline uint128& uint128::operator=(int128 v) {
+ return *this = uint128(v);
+}
+
// Arithmetic operators.
uint128 operator<<(uint128 lhs, int amount);
@@ -421,6 +661,9 @@ constexpr uint128::uint128(unsigned __int128 v)
hi_{static_cast<uint64_t>(v >> 64)} {}
#endif // ABSL_HAVE_INTRINSIC_INT128
+constexpr uint128::uint128(int128 v)
+ : lo_{Int128Low64(v)}, hi_{static_cast<uint64_t>(Int128High64(v))} {}
+
#elif defined(ABSL_IS_BIG_ENDIAN)
constexpr uint128::uint128(uint64_t high, uint64_t low)
@@ -451,6 +694,9 @@ constexpr uint128::uint128(unsigned __int128 v)
lo_{static_cast<uint64_t>(v & ~uint64_t{0})} {}
#endif // ABSL_HAVE_INTRINSIC_INT128
+constexpr uint128::uint128(int128 v)
+ : hi_{static_cast<uint64_t>(Int128High64(v))}, lo_{Int128Low64(v)} {}
+
#else // byte order
#error "Unsupported byte order: must be little-endian or big-endian."
#endif // byte order
@@ -546,28 +792,21 @@ inline bool operator!=(uint128 lhs, uint128 rhs) {
}
inline bool operator<(uint128 lhs, uint128 rhs) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ return static_cast<unsigned __int128>(lhs) <
+ static_cast<unsigned __int128>(rhs);
+#else
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) < Uint128Low64(rhs))
: (Uint128High64(lhs) < Uint128High64(rhs));
+#endif
}
-inline bool operator>(uint128 lhs, uint128 rhs) {
- return (Uint128High64(lhs) == Uint128High64(rhs))
- ? (Uint128Low64(lhs) > Uint128Low64(rhs))
- : (Uint128High64(lhs) > Uint128High64(rhs));
-}
+inline bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
-inline bool operator<=(uint128 lhs, uint128 rhs) {
- return (Uint128High64(lhs) == Uint128High64(rhs))
- ? (Uint128Low64(lhs) <= Uint128Low64(rhs))
- : (Uint128High64(lhs) <= Uint128High64(rhs));
-}
+inline bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
-inline bool operator>=(uint128 lhs, uint128 rhs) {
- return (Uint128High64(lhs) == Uint128High64(rhs))
- ? (Uint128Low64(lhs) >= Uint128Low64(rhs))
- : (Uint128High64(lhs) >= Uint128High64(rhs));
-}
+inline bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
// Unary operators.
@@ -624,6 +863,9 @@ inline uint128& uint128::operator^=(uint128 other) {
// Arithmetic operators.
inline uint128 operator<<(uint128 lhs, int amount) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ return static_cast<unsigned __int128>(lhs) << amount;
+#else
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
@@ -635,9 +877,13 @@ inline uint128 operator<<(uint128 lhs, int amount) {
return lhs;
}
return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
+#endif
}
inline uint128 operator>>(uint128 lhs, int amount) {
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+ return static_cast<unsigned __int128>(lhs) >> amount;
+#else
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
if (amount < 64) {
@@ -649,6 +895,7 @@ inline uint128 operator>>(uint128 lhs, int amount) {
return lhs;
}
return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
+#endif
}
inline uint128 operator+(uint128 lhs, uint128 rhs) {
@@ -675,7 +922,7 @@ inline uint128 operator*(uint128 lhs, uint128 rhs) {
// can be used for uint128 storage.
return static_cast<unsigned __int128>(lhs) *
static_cast<unsigned __int128>(rhs);
-#elif defined(_MSC_VER) && defined(_WIN64)
+#elif defined(_MSC_VER) && defined(_M_X64)
uint64_t carry;
uint64_t low = _umul128(Uint128Low64(lhs), Uint128Low64(rhs), &carry);
return MakeUint128(Uint128Low64(lhs) * Uint128High64(rhs) +
@@ -720,12 +967,124 @@ inline uint128& uint128::operator--() {
return *this;
}
+constexpr int128 MakeInt128(int64_t high, uint64_t low) {
+ return int128(high, low);
+}
+
+// Assignment from integer types.
+inline int128& int128::operator=(int v) {
+ return *this = int128(v);
+}
+
+inline int128& int128::operator=(unsigned int v) {
+ return *this = int128(v);
+}
+
+inline int128& int128::operator=(long v) { // NOLINT(runtime/int)
+ return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(unsigned long v) {
+ return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(long long v) {
+ return *this = int128(v);
+}
+
+// NOLINTNEXTLINE(runtime/int)
+inline int128& int128::operator=(unsigned long long v) {
+ return *this = int128(v);
+}
+
+// Arithmetic operators.
+
+int128 operator+(int128 lhs, int128 rhs);
+int128 operator-(int128 lhs, int128 rhs);
+int128 operator*(int128 lhs, int128 rhs);
+int128 operator/(int128 lhs, int128 rhs);
+int128 operator%(int128 lhs, int128 rhs);
+int128 operator|(int128 lhs, int128 rhs);
+int128 operator&(int128 lhs, int128 rhs);
+int128 operator^(int128 lhs, int128 rhs);
+int128 operator<<(int128 lhs, int amount);
+int128 operator>>(int128 lhs, int amount);
+
+inline int128& int128::operator+=(int128 other) {
+ *this = *this + other;
+ return *this;
+}
+
+inline int128& int128::operator-=(int128 other) {
+ *this = *this - other;
+ return *this;
+}
+
+inline int128& int128::operator*=(int128 other) {
+ *this = *this * other;
+ return *this;
+}
+
+inline int128& int128::operator/=(int128 other) {
+ *this = *this / other;
+ return *this;
+}
+
+inline int128& int128::operator%=(int128 other) {
+ *this = *this % other;
+ return *this;
+}
+
+inline int128& int128::operator|=(int128 other) {
+ *this = *this | other;
+ return *this;
+}
+
+inline int128& int128::operator&=(int128 other) {
+ *this = *this & other;
+ return *this;
+}
+
+inline int128& int128::operator^=(int128 other) {
+ *this = *this ^ other;
+ return *this;
+}
+
+inline int128& int128::operator<<=(int amount) {
+ *this = *this << amount;
+ return *this;
+}
+
+inline int128& int128::operator>>=(int amount) {
+ *this = *this >> amount;
+ return *this;
+}
+
+namespace int128_internal {
+
+// Casts from unsigned to signed while preserving the underlying binary
+// representation.
+constexpr int64_t BitCastToSigned(uint64_t v) {
+ // Casting an unsigned integer to a signed integer of the same
+ // width is implementation defined behavior if the source value would not fit
+ // in the destination type. We step around it with a roundtrip bitwise not
+ // operation to make sure this function remains constexpr. Clang, GCC, and
+ // MSVC optimize this to a no-op on x86-64.
+ return v & (uint64_t{1} << 63) ? ~static_cast<int64_t>(~v)
+ : static_cast<int64_t>(v);
+}
+
+} // namespace int128_internal
+
#if defined(ABSL_HAVE_INTRINSIC_INT128)
-#include "absl/numeric/int128_have_intrinsic.inc"
+#include "absl/numeric/int128_have_intrinsic.inc" // IWYU pragma: export
#else // ABSL_HAVE_INTRINSIC_INT128
-#include "absl/numeric/int128_no_intrinsic.inc"
+#include "absl/numeric/int128_no_intrinsic.inc" // IWYU pragma: export
#endif // ABSL_HAVE_INTRINSIC_INT128
+ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_INTERNAL_WCHAR_T
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_benchmark.cc
index 1cb7d0ed87e..eab1515c0ad 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/numeric/int128.h"
-
#include <algorithm>
#include <cstdint>
+#include <limits>
#include <random>
#include <vector>
#include "benchmark/benchmark.h"
#include "absl/base/config.h"
+#include "absl/numeric/int128.h"
namespace {
@@ -32,57 +32,85 @@ std::mt19937 MakeRandomEngine() {
return std::mt19937(seed);
}
-std::vector<std::pair<absl::uint128, absl::uint128>>
-GetRandomClass128SampleUniformDivisor() {
- std::vector<std::pair<absl::uint128, absl::uint128>> values;
+template <typename T,
+ typename H = typename std::conditional<
+ std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
+std::vector<std::pair<T, T>> GetRandomClass128SampleUniformDivisor() {
+ std::vector<std::pair<T, T>> values;
std::mt19937 random = MakeRandomEngine();
- std::uniform_int_distribution<uint64_t> uniform_uint64;
+ std::uniform_int_distribution<H> uniform_h;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- absl::uint128 a =
- absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
- absl::uint128 b =
- absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
- values.emplace_back(std::max(a, b),
- std::max(absl::uint128(2), std::min(a, b)));
+ T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+ T b{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+ values.emplace_back(std::max(a, b), std::max(T(2), std::min(a, b)));
}
return values;
}
+template <typename T>
void BM_DivideClass128UniformDivisor(benchmark::State& state) {
- auto values = GetRandomClass128SampleUniformDivisor();
+ auto values = GetRandomClass128SampleUniformDivisor<T>();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-BENCHMARK(BM_DivideClass128UniformDivisor);
+BENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_DivideClass128UniformDivisor, absl::int128);
+
+template <typename T>
+void BM_RemainderClass128UniformDivisor(benchmark::State& state) {
+ auto values = GetRandomClass128SampleUniformDivisor<T>();
+ while (state.KeepRunningBatch(values.size())) {
+ for (const auto& pair : values) {
+ benchmark::DoNotOptimize(pair.first % pair.second);
+ }
+ }
+}
+BENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_RemainderClass128UniformDivisor, absl::int128);
-std::vector<std::pair<absl::uint128, uint64_t>>
-GetRandomClass128SampleSmallDivisor() {
- std::vector<std::pair<absl::uint128, uint64_t>> values;
+template <typename T,
+ typename H = typename std::conditional<
+ std::numeric_limits<T>::is_signed, int64_t, uint64_t>::type>
+std::vector<std::pair<T, H>> GetRandomClass128SampleSmallDivisor() {
+ std::vector<std::pair<T, H>> values;
std::mt19937 random = MakeRandomEngine();
- std::uniform_int_distribution<uint64_t> uniform_uint64;
+ std::uniform_int_distribution<H> uniform_h;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- absl::uint128 a =
- absl::MakeUint128(uniform_uint64(random), uniform_uint64(random));
- uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
- values.emplace_back(std::max(a, absl::uint128(b)), b);
+ T a{absl::MakeUint128(uniform_h(random), uniform_h(random))};
+ H b{std::max(H{2}, uniform_h(random))};
+ values.emplace_back(std::max(a, T(b)), b);
}
return values;
}
+template <typename T>
void BM_DivideClass128SmallDivisor(benchmark::State& state) {
- auto values = GetRandomClass128SampleSmallDivisor();
+ auto values = GetRandomClass128SampleSmallDivisor<T>();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-BENCHMARK(BM_DivideClass128SmallDivisor);
+BENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_DivideClass128SmallDivisor, absl::int128);
+
+template <typename T>
+void BM_RemainderClass128SmallDivisor(benchmark::State& state) {
+ auto values = GetRandomClass128SampleSmallDivisor<T>();
+ while (state.KeepRunningBatch(values.size())) {
+ for (const auto& pair : values) {
+ benchmark::DoNotOptimize(pair.first % pair.second);
+ }
+ }
+}
+BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::uint128);
+BENCHMARK_TEMPLATE(BM_RemainderClass128SmallDivisor, absl::int128);
std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
std::vector<std::pair<absl::uint128, absl::uint128>> values;
@@ -121,74 +149,107 @@ BENCHMARK(BM_AddClass128);
// Some implementations of <random> do not support __int128 when it is
// available, so we make our own uniform_int_distribution-like type.
+template <typename T,
+ typename H = typename std::conditional<
+ std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
class UniformIntDistribution128 {
public:
// NOLINTNEXTLINE: mimicking std::uniform_int_distribution API
- unsigned __int128 operator()(std::mt19937& generator) {
- return (static_cast<unsigned __int128>(dist64_(generator)) << 64) |
- dist64_(generator);
+ T operator()(std::mt19937& generator) {
+ return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);
}
private:
- std::uniform_int_distribution<uint64_t> dist64_;
+ std::uniform_int_distribution<H> dist64_;
};
-std::vector<std::pair<unsigned __int128, unsigned __int128>>
-GetRandomIntrinsic128SampleUniformDivisor() {
- std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
+template <typename T,
+ typename H = typename std::conditional<
+ std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
+std::vector<std::pair<T, T>> GetRandomIntrinsic128SampleUniformDivisor() {
+ std::vector<std::pair<T, T>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128 uniform_uint128;
+ UniformIntDistribution128<T> uniform_128;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- unsigned __int128 a = uniform_uint128(random);
- unsigned __int128 b = uniform_uint128(random);
- values.emplace_back(
- std::max(a, b),
- std::max(static_cast<unsigned __int128>(2), std::min(a, b)));
+ T a = uniform_128(random);
+ T b = uniform_128(random);
+ values.emplace_back(std::max(a, b),
+ std::max(static_cast<T>(2), std::min(a, b)));
}
return values;
}
+template <typename T>
void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {
- auto values = GetRandomIntrinsic128SampleUniformDivisor();
+ auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-BENCHMARK(BM_DivideIntrinsic128UniformDivisor);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __int128);
+
+template <typename T>
+void BM_RemainderIntrinsic128UniformDivisor(benchmark::State& state) {
+ auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();
+ while (state.KeepRunningBatch(values.size())) {
+ for (const auto& pair : values) {
+ benchmark::DoNotOptimize(pair.first % pair.second);
+ }
+ }
+}
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __int128);
-std::vector<std::pair<unsigned __int128, uint64_t>>
-GetRandomIntrinsic128SampleSmallDivisor() {
- std::vector<std::pair<unsigned __int128, uint64_t>> values;
+template <typename T,
+ typename H = typename std::conditional<
+ std::is_same<T, __int128>::value, int64_t, uint64_t>::type>
+std::vector<std::pair<T, H>> GetRandomIntrinsic128SampleSmallDivisor() {
+ std::vector<std::pair<T, H>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128 uniform_uint128;
- std::uniform_int_distribution<uint64_t> uniform_uint64;
+ UniformIntDistribution128<T> uniform_int128;
+ std::uniform_int_distribution<H> uniform_int64;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- unsigned __int128 a = uniform_uint128(random);
- uint64_t b = std::max(uint64_t{2}, uniform_uint64(random));
- values.emplace_back(std::max(a, static_cast<unsigned __int128>(b)), b);
+ T a = uniform_int128(random);
+ H b = std::max(H{2}, uniform_int64(random));
+ values.emplace_back(std::max(a, static_cast<T>(b)), b);
}
return values;
}
+template <typename T>
void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {
- auto values = GetRandomIntrinsic128SampleSmallDivisor();
+ auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-BENCHMARK(BM_DivideIntrinsic128SmallDivisor);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128);
+
+template <typename T>
+void BM_RemainderIntrinsic128SmallDivisor(benchmark::State& state) {
+ auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();
+ while (state.KeepRunningBatch(values.size())) {
+ for (const auto& pair : values) {
+ benchmark::DoNotOptimize(pair.first % pair.second);
+ }
+ }
+}
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, unsigned __int128);
+BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128);
std::vector<std::pair<unsigned __int128, unsigned __int128>>
GetRandomIntrinsic128Sample() {
std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128 uniform_uint128;
+ UniformIntDistribution128<unsigned __int128> uniform_uint128;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
values.emplace_back(uniform_uint128(random), uniform_uint128(random));
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_have_intrinsic.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
index 0c8164a5444..d6c76dd320c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,3 +16,287 @@
// This file contains :int128 implementation details that depend on internal
// representation when ABSL_HAVE_INTRINSIC_INT128 is defined. This file is
// included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
+
+namespace int128_internal {
+
+// Casts from unsigned to signed while preserving the underlying binary
+// representation.
+constexpr __int128 BitCastToSigned(unsigned __int128 v) {
+ // Casting an unsigned integer to a signed integer of the same
+ // width is implementation defined behavior if the source value would not fit
+ // in the destination type. We step around it with a roundtrip bitwise not
+ // operation to make sure this function remains constexpr. Clang and GCC
+ // optimize this to a no-op on x86-64.
+ return v & (static_cast<unsigned __int128>(1) << 127)
+ ? ~static_cast<__int128>(~v)
+ : static_cast<__int128>(v);
+}
+
+} // namespace int128_internal
+
+inline int128& int128::operator=(__int128 v) {
+ v_ = v;
+ return *this;
+}
+
+constexpr uint64_t Int128Low64(int128 v) {
+ return static_cast<uint64_t>(v.v_ & ~uint64_t{0});
+}
+
+constexpr int64_t Int128High64(int128 v) {
+ // Initially cast to unsigned to prevent a right shift on a negative value.
+ return int128_internal::BitCastToSigned(
+ static_cast<uint64_t>(static_cast<unsigned __int128>(v.v_) >> 64));
+}
+
+constexpr int128::int128(int64_t high, uint64_t low)
+ // Initially cast to unsigned to prevent a left shift that overflows.
+ : v_(int128_internal::BitCastToSigned(static_cast<unsigned __int128>(high)
+ << 64) |
+ low) {}
+
+
+constexpr int128::int128(int v) : v_{v} {}
+
+constexpr int128::int128(long v) : v_{v} {} // NOLINT(runtime/int)
+
+constexpr int128::int128(long long v) : v_{v} {} // NOLINT(runtime/int)
+
+constexpr int128::int128(__int128 v) : v_{v} {}
+
+constexpr int128::int128(unsigned int v) : v_{v} {}
+
+constexpr int128::int128(unsigned long v) : v_{v} {} // NOLINT(runtime/int)
+
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : v_{v} {}
+
+constexpr int128::int128(unsigned __int128 v) : v_{static_cast<__int128>(v)} {}
+
+inline int128::int128(float v) {
+ v_ = static_cast<__int128>(v);
+}
+
+inline int128::int128(double v) {
+ v_ = static_cast<__int128>(v);
+}
+
+inline int128::int128(long double v) {
+ v_ = static_cast<__int128>(v);
+}
+
+constexpr int128::int128(uint128 v) : v_{static_cast<__int128>(v)} {}
+
+constexpr int128::operator bool() const { return static_cast<bool>(v_); }
+
+constexpr int128::operator char() const { return static_cast<char>(v_); }
+
+constexpr int128::operator signed char() const {
+ return static_cast<signed char>(v_);
+}
+
+constexpr int128::operator unsigned char() const {
+ return static_cast<unsigned char>(v_);
+}
+
+constexpr int128::operator char16_t() const {
+ return static_cast<char16_t>(v_);
+}
+
+constexpr int128::operator char32_t() const {
+ return static_cast<char32_t>(v_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(v_);
+}
+
+constexpr int128::operator short() const { // NOLINT(runtime/int)
+ return static_cast<short>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
+ return static_cast<unsigned short>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+ return static_cast<int>(v_);
+}
+
+constexpr int128::operator unsigned int() const {
+ return static_cast<unsigned int>(v_);
+}
+
+constexpr int128::operator long() const { // NOLINT(runtime/int)
+ return static_cast<long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator long long() const { // NOLINT(runtime/int)
+ return static_cast<long long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long long>(v_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator __int128() const { return v_; }
+
+constexpr int128::operator unsigned __int128() const {
+ return static_cast<unsigned __int128>(v_);
+}
+
+// Clang on PowerPC sometimes produces incorrect __int128 to floating point
+// conversions. In that case, we do the conversion with a similar implementation
+// to the conversion operators in int128_no_intrinsic.inc.
+#if defined(__clang__) && !defined(__ppc64__)
+inline int128::operator float() const { return static_cast<float>(v_); }
+
+inline int128::operator double () const { return static_cast<double>(v_); }
+
+inline int128::operator long double() const {
+ return static_cast<long double>(v_);
+}
+
+#else // Clang on PowerPC
+// Forward declaration for conversion operators to floating point types.
+int128 operator-(int128 v);
+bool operator!=(int128 lhs, int128 rhs);
+
+inline int128::operator float() const {
+ // We must convert the absolute value and then negate as needed, because
+ // floating point types are typically sign-magnitude. Otherwise, the
+ // difference between the high and low 64 bits when interpreted as two's
+ // complement overwhelms the precision of the mantissa.
+ //
+ // Also check to make sure we don't negate Int128Min()
+ return v_ < 0 && *this != Int128Min()
+ ? -static_cast<float>(-*this)
+ : static_cast<float>(Int128Low64(*this)) +
+ std::ldexp(static_cast<float>(Int128High64(*this)), 64);
+}
+
+inline int128::operator double() const {
+ // See comment in int128::operator float() above.
+ return v_ < 0 && *this != Int128Min()
+ ? -static_cast<double>(-*this)
+ : static_cast<double>(Int128Low64(*this)) +
+ std::ldexp(static_cast<double>(Int128High64(*this)), 64);
+}
+
+inline int128::operator long double() const {
+ // See comment in int128::operator float() above.
+ return v_ < 0 && *this != Int128Min()
+ ? -static_cast<long double>(-*this)
+ : static_cast<long double>(Int128Low64(*this)) +
+ std::ldexp(static_cast<long double>(Int128High64(*this)),
+ 64);
+}
+#endif // Clang on PowerPC
+
+// Comparison operators.
+
+inline bool operator==(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) == static_cast<__int128>(rhs);
+}
+
+inline bool operator!=(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) != static_cast<__int128>(rhs);
+}
+
+inline bool operator<(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) < static_cast<__int128>(rhs);
+}
+
+inline bool operator>(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) > static_cast<__int128>(rhs);
+}
+
+inline bool operator<=(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs);
+}
+
+inline bool operator>=(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs);
+}
+
+// Unary operators.
+
+inline int128 operator-(int128 v) {
+ return -static_cast<__int128>(v);
+}
+
+inline bool operator!(int128 v) {
+ return !static_cast<__int128>(v);
+}
+
+inline int128 operator~(int128 val) {
+ return ~static_cast<__int128>(val);
+}
+
+// Arithmetic operators.
+
+inline int128 operator+(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) + static_cast<__int128>(rhs);
+}
+
+inline int128 operator-(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) - static_cast<__int128>(rhs);
+}
+
+inline int128 operator*(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) * static_cast<__int128>(rhs);
+}
+
+inline int128 operator/(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) / static_cast<__int128>(rhs);
+}
+
+inline int128 operator%(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) % static_cast<__int128>(rhs);
+}
+
+inline int128 int128::operator++(int) {
+ int128 tmp(*this);
+ ++v_;
+ return tmp;
+}
+
+inline int128 int128::operator--(int) {
+ int128 tmp(*this);
+ --v_;
+ return tmp;
+}
+
+inline int128& int128::operator++() {
+ ++v_;
+ return *this;
+}
+
+inline int128& int128::operator--() {
+ --v_;
+ return *this;
+}
+
+inline int128 operator|(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) | static_cast<__int128>(rhs);
+}
+
+inline int128 operator&(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) & static_cast<__int128>(rhs);
+}
+
+inline int128 operator^(int128 lhs, int128 rhs) {
+ return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs);
+}
+
+inline int128 operator<<(int128 lhs, int amount) {
+ return static_cast<__int128>(lhs) << amount;
+}
+
+inline int128 operator>>(int128 lhs, int amount) {
+ return static_cast<__int128>(lhs) >> amount;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_no_intrinsic.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
index 08d68ac3ea5..c753771ae73 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,3 +16,293 @@
// This file contains :int128 implementation details that depend on internal
// representation when ABSL_HAVE_INTRINSIC_INT128 is *not* defined. This file
// is included by int128.h and relies on ABSL_INTERNAL_WCHAR_T being defined.
+
+constexpr uint64_t Int128Low64(int128 v) { return v.lo_; }
+
+constexpr int64_t Int128High64(int128 v) { return v.hi_; }
+
+#if defined(ABSL_IS_LITTLE_ENDIAN)
+
+constexpr int128::int128(int64_t high, uint64_t low) :
+ lo_(low), hi_(high) {}
+
+constexpr int128::int128(int v)
+ : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+constexpr int128::int128(long long v) // NOLINT(runtime/int)
+ : lo_{static_cast<uint64_t>(v)}, hi_{v < 0 ? ~int64_t{0} : 0} {}
+
+constexpr int128::int128(unsigned int v) : lo_{v}, hi_{0} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long v) : lo_{v}, hi_{0} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : lo_{v}, hi_{0} {}
+
+constexpr int128::int128(uint128 v)
+ : lo_{Uint128Low64(v)}, hi_{static_cast<int64_t>(Uint128High64(v))} {}
+
+#elif defined(ABSL_IS_BIG_ENDIAN)
+
+constexpr int128::int128(int64_t high, uint64_t low) :
+ hi_{high}, lo_{low} {}
+
+constexpr int128::int128(int v)
+ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+constexpr int128::int128(long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+constexpr int128::int128(long long v) // NOLINT(runtime/int)
+ : hi_{v < 0 ? ~int64_t{0} : 0}, lo_{static_cast<uint64_t>(v)} {}
+
+constexpr int128::int128(unsigned int v) : hi_{0}, lo_{v} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long v) : hi_{0}, lo_{v} {}
+// NOLINTNEXTLINE(runtime/int)
+constexpr int128::int128(unsigned long long v) : hi_{0}, lo_{v} {}
+
+constexpr int128::int128(uint128 v)
+ : hi_{static_cast<int64_t>(Uint128High64(v))}, lo_{Uint128Low64(v)} {}
+
+#else // byte order
+#error "Unsupported byte order: must be little-endian or big-endian."
+#endif // byte order
+
+constexpr int128::operator bool() const { return lo_ || hi_; }
+
+constexpr int128::operator char() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator signed char() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<signed char>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned char() const {
+ return static_cast<unsigned char>(lo_);
+}
+
+constexpr int128::operator char16_t() const {
+ return static_cast<char16_t>(lo_);
+}
+
+constexpr int128::operator char32_t() const {
+ return static_cast<char32_t>(lo_);
+}
+
+constexpr int128::operator ABSL_INTERNAL_WCHAR_T() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<ABSL_INTERNAL_WCHAR_T>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator short() const { // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<short>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned short() const { // NOLINT(runtime/int)
+ return static_cast<unsigned short>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator int() const {
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<int>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned int() const {
+ return static_cast<unsigned int>(lo_);
+}
+
+constexpr int128::operator long() const { // NOLINT(runtime/int)
+ // NOLINTNEXTLINE(runtime/int)
+ return static_cast<long>(static_cast<long long>(*this));
+}
+
+constexpr int128::operator unsigned long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long>(lo_); // NOLINT(runtime/int)
+}
+
+constexpr int128::operator long long() const { // NOLINT(runtime/int)
+ // We don't bother checking the value of hi_. If *this < 0, lo_'s high bit
+ // must be set in order for the value to fit into a long long. Conversely, if
+ // lo_'s high bit is set, *this must be < 0 for the value to fit.
+ return int128_internal::BitCastToSigned(lo_);
+}
+
+constexpr int128::operator unsigned long long() const { // NOLINT(runtime/int)
+ return static_cast<unsigned long long>(lo_); // NOLINT(runtime/int)
+}
+
+// Forward declaration for conversion operators to floating point types.
+int128 operator-(int128 v);
+bool operator!=(int128 lhs, int128 rhs);
+
+inline int128::operator float() const {
+ // We must convert the absolute value and then negate as needed, because
+ // floating point types are typically sign-magnitude. Otherwise, the
+ // difference between the high and low 64 bits when interpreted as two's
+ // complement overwhelms the precision of the mantissa.
+ //
+ // Also check to make sure we don't negate Int128Min()
+ return hi_ < 0 && *this != Int128Min()
+ ? -static_cast<float>(-*this)
+ : static_cast<float>(lo_) +
+ std::ldexp(static_cast<float>(hi_), 64);
+}
+
+inline int128::operator double() const {
+ // See comment in int128::operator float() above.
+ return hi_ < 0 && *this != Int128Min()
+ ? -static_cast<double>(-*this)
+ : static_cast<double>(lo_) +
+ std::ldexp(static_cast<double>(hi_), 64);
+}
+
+inline int128::operator long double() const {
+ // See comment in int128::operator float() above.
+ return hi_ < 0 && *this != Int128Min()
+ ? -static_cast<long double>(-*this)
+ : static_cast<long double>(lo_) +
+ std::ldexp(static_cast<long double>(hi_), 64);
+}
+
+// Comparison operators.
+
+inline bool operator==(int128 lhs, int128 rhs) {
+ return (Int128Low64(lhs) == Int128Low64(rhs) &&
+ Int128High64(lhs) == Int128High64(rhs));
+}
+
+inline bool operator!=(int128 lhs, int128 rhs) {
+ return !(lhs == rhs);
+}
+
+inline bool operator<(int128 lhs, int128 rhs) {
+ return (Int128High64(lhs) == Int128High64(rhs))
+ ? (Int128Low64(lhs) < Int128Low64(rhs))
+ : (Int128High64(lhs) < Int128High64(rhs));
+}
+
+inline bool operator>(int128 lhs, int128 rhs) {
+ return (Int128High64(lhs) == Int128High64(rhs))
+ ? (Int128Low64(lhs) > Int128Low64(rhs))
+ : (Int128High64(lhs) > Int128High64(rhs));
+}
+
+inline bool operator<=(int128 lhs, int128 rhs) {
+ return !(lhs > rhs);
+}
+
+inline bool operator>=(int128 lhs, int128 rhs) {
+ return !(lhs < rhs);
+}
+
+// Unary operators.
+
+inline int128 operator-(int128 v) {
+ int64_t hi = ~Int128High64(v);
+ uint64_t lo = ~Int128Low64(v) + 1;
+ if (lo == 0) ++hi; // carry
+ return MakeInt128(hi, lo);
+}
+
+inline bool operator!(int128 v) {
+ return !Int128Low64(v) && !Int128High64(v);
+}
+
+inline int128 operator~(int128 val) {
+ return MakeInt128(~Int128High64(val), ~Int128Low64(val));
+}
+
+// Arithmetic operators.
+
+inline int128 operator+(int128 lhs, int128 rhs) {
+ int128 result = MakeInt128(Int128High64(lhs) + Int128High64(rhs),
+ Int128Low64(lhs) + Int128Low64(rhs));
+ if (Int128Low64(result) < Int128Low64(lhs)) { // check for carry
+ return MakeInt128(Int128High64(result) + 1, Int128Low64(result));
+ }
+ return result;
+}
+
+inline int128 operator-(int128 lhs, int128 rhs) {
+ int128 result = MakeInt128(Int128High64(lhs) - Int128High64(rhs),
+ Int128Low64(lhs) - Int128Low64(rhs));
+ if (Int128Low64(lhs) < Int128Low64(rhs)) { // check for carry
+ return MakeInt128(Int128High64(result) - 1, Int128Low64(result));
+ }
+ return result;
+}
+
+inline int128 operator*(int128 lhs, int128 rhs) {
+ uint128 result = uint128(lhs) * rhs;
+ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
+ Uint128Low64(result));
+}
+
+inline int128 int128::operator++(int) {
+ int128 tmp(*this);
+ *this += 1;
+ return tmp;
+}
+
+inline int128 int128::operator--(int) {
+ int128 tmp(*this);
+ *this -= 1;
+ return tmp;
+}
+
+inline int128& int128::operator++() {
+ *this += 1;
+ return *this;
+}
+
+inline int128& int128::operator--() {
+ *this -= 1;
+ return *this;
+}
+
+inline int128 operator|(int128 lhs, int128 rhs) {
+ return MakeInt128(Int128High64(lhs) | Int128High64(rhs),
+ Int128Low64(lhs) | Int128Low64(rhs));
+}
+
+inline int128 operator&(int128 lhs, int128 rhs) {
+ return MakeInt128(Int128High64(lhs) & Int128High64(rhs),
+ Int128Low64(lhs) & Int128Low64(rhs));
+}
+
+inline int128 operator^(int128 lhs, int128 rhs) {
+ return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),
+ Int128Low64(lhs) ^ Int128Low64(rhs));
+}
+
+inline int128 operator<<(int128 lhs, int amount) {
+ // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+ if (amount < 64) {
+ if (amount != 0) {
+ return MakeInt128(
+ (Int128High64(lhs) << amount) |
+ static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),
+ Int128Low64(lhs) << amount);
+ }
+ return lhs;
+ }
+ return MakeInt128(static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)), 0);
+}
+
+inline int128 operator>>(int128 lhs, int amount) {
+ // uint64_t shifts of >= 64 are undefined, so we need some special-casing.
+ if (amount < 64) {
+ if (amount != 0) {
+ return MakeInt128(
+ Int128High64(lhs) >> amount,
+ (Int128Low64(lhs) >> amount) |
+ (static_cast<uint64_t>(Int128High64(lhs)) << (64 - amount)));
+ }
+ return lhs;
+ }
+ return MakeInt128(0,
+ static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)));
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_stream_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_stream_test.cc
index 09efaad4e7f..479ad66cf4d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_stream_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_stream_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -147,6 +147,735 @@ TEST(Uint128, OStreamFormatTest) {
}
}
+struct Int128TestCase {
+ absl::int128 value;
+ std::ios_base::fmtflags flags;
+ std::streamsize width;
+ const char* expected;
+};
+
+void CheckInt128Case(const Int128TestCase& test_case) {
+ std::ostringstream os;
+ os.flags(test_case.flags);
+ os.width(test_case.width);
+ os.fill(kFill);
+ os << test_case.value;
+ SCOPED_TRACE(StreamFormatToString(test_case.flags, test_case.width));
+ EXPECT_EQ(test_case.expected, os.str());
+}
+
+TEST(Int128, OStreamValueTest) {
+ CheckInt128Case({1, kDec, /*width = */ 0, "1"});
+ CheckInt128Case({1, kOct, /*width = */ 0, "1"});
+ CheckInt128Case({1, kHex, /*width = */ 0, "1"});
+ CheckInt128Case({9, kDec, /*width = */ 0, "9"});
+ CheckInt128Case({9, kOct, /*width = */ 0, "11"});
+ CheckInt128Case({9, kHex, /*width = */ 0, "9"});
+ CheckInt128Case({12345, kDec, /*width = */ 0, "12345"});
+ CheckInt128Case({12345, kOct, /*width = */ 0, "30071"});
+ CheckInt128Case({12345, kHex, /*width = */ 0, "3039"});
+ CheckInt128Case(
+ {0x8000000000000000, kDec, /*width = */ 0, "9223372036854775808"});
+ CheckInt128Case(
+ {0x8000000000000000, kOct, /*width = */ 0, "1000000000000000000000"});
+ CheckInt128Case(
+ {0x8000000000000000, kHex, /*width = */ 0, "8000000000000000"});
+ CheckInt128Case({std::numeric_limits<uint64_t>::max(), kDec,
+ /*width = */ 0, "18446744073709551615"});
+ CheckInt128Case({std::numeric_limits<uint64_t>::max(), kOct,
+ /*width = */ 0, "1777777777777777777777"});
+ CheckInt128Case({std::numeric_limits<uint64_t>::max(), kHex,
+ /*width = */ 0, "ffffffffffffffff"});
+ CheckInt128Case(
+ {absl::MakeInt128(1, 0), kDec, /*width = */ 0, "18446744073709551616"});
+ CheckInt128Case(
+ {absl::MakeInt128(1, 0), kOct, /*width = */ 0, "2000000000000000000000"});
+ CheckInt128Case(
+ {absl::MakeInt128(1, 0), kHex, /*width = */ 0, "10000000000000000"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+ std::numeric_limits<uint64_t>::max()),
+ std::ios::dec, /*width = */ 0,
+ "170141183460469231731687303715884105727"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+ std::numeric_limits<uint64_t>::max()),
+ std::ios::oct, /*width = */ 0,
+ "1777777777777777777777777777777777777777777"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::max(),
+ std::numeric_limits<uint64_t>::max()),
+ std::ios::hex, /*width = */ 0,
+ "7fffffffffffffffffffffffffffffff"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+ std::ios::dec, /*width = */ 0,
+ "-170141183460469231731687303715884105728"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+ std::ios::oct, /*width = */ 0,
+ "2000000000000000000000000000000000000000000"});
+ CheckInt128Case({absl::MakeInt128(std::numeric_limits<int64_t>::min(), 0),
+ std::ios::hex, /*width = */ 0,
+ "80000000000000000000000000000000"});
+ CheckInt128Case({-1, std::ios::dec, /*width = */ 0, "-1"});
+ CheckInt128Case({-1, std::ios::oct, /*width = */ 0,
+ "3777777777777777777777777777777777777777777"});
+ CheckInt128Case(
+ {-1, std::ios::hex, /*width = */ 0, "ffffffffffffffffffffffffffffffff"});
+ CheckInt128Case({-12345, std::ios::dec, /*width = */ 0, "-12345"});
+ CheckInt128Case({-12345, std::ios::oct, /*width = */ 0,
+ "3777777777777777777777777777777777777747707"});
+ CheckInt128Case({-12345, std::ios::hex, /*width = */ 0,
+ "ffffffffffffffffffffffffffffcfc7"});
+}
+
+std::vector<Int128TestCase> GetInt128FormatCases();
+TEST(Int128, OStreamFormatTest) {
+ for (const Int128TestCase& test_case : GetInt128FormatCases()) {
+ CheckInt128Case(test_case);
+ }
+}
+
+std::vector<Int128TestCase> GetInt128FormatCases() {
+ return {
+ {0, std::ios_base::fmtflags(), /*width = */ 0, "0"},
+ {0, std::ios_base::fmtflags(), /*width = */ 6, "_____0"},
+ {0, kPos, /*width = */ 0, "+0"},
+ {0, kPos, /*width = */ 6, "____+0"},
+ {0, kBase, /*width = */ 0, "0"},
+ {0, kBase, /*width = */ 6, "_____0"},
+ {0, kBase | kPos, /*width = */ 0, "+0"},
+ {0, kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kUpper, /*width = */ 0, "0"},
+ {0, kUpper, /*width = */ 6, "_____0"},
+ {0, kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kUpper | kPos, /*width = */ 6, "____+0"},
+ {0, kUpper | kBase, /*width = */ 0, "0"},
+ {0, kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kLeft, /*width = */ 0, "0"},
+ {0, kLeft, /*width = */ 6, "0_____"},
+ {0, kLeft | kPos, /*width = */ 0, "+0"},
+ {0, kLeft | kPos, /*width = */ 6, "+0____"},
+ {0, kLeft | kBase, /*width = */ 0, "0"},
+ {0, kLeft | kBase, /*width = */ 6, "0_____"},
+ {0, kLeft | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kLeft | kBase | kPos, /*width = */ 6, "+0____"},
+ {0, kLeft | kUpper, /*width = */ 0, "0"},
+ {0, kLeft | kUpper, /*width = */ 6, "0_____"},
+ {0, kLeft | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kLeft | kUpper | kPos, /*width = */ 6, "+0____"},
+ {0, kLeft | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+ {0, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"},
+ {0, kInt, /*width = */ 0, "0"},
+ {0, kInt, /*width = */ 6, "_____0"},
+ {0, kInt | kPos, /*width = */ 0, "+0"},
+ {0, kInt | kPos, /*width = */ 6, "+____0"},
+ {0, kInt | kBase, /*width = */ 0, "0"},
+ {0, kInt | kBase, /*width = */ 6, "_____0"},
+ {0, kInt | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kInt | kBase | kPos, /*width = */ 6, "+____0"},
+ {0, kInt | kUpper, /*width = */ 0, "0"},
+ {0, kInt | kUpper, /*width = */ 6, "_____0"},
+ {0, kInt | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kInt | kUpper | kPos, /*width = */ 6, "+____0"},
+ {0, kInt | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"},
+ {0, kRight, /*width = */ 0, "0"},
+ {0, kRight, /*width = */ 6, "_____0"},
+ {0, kRight | kPos, /*width = */ 0, "+0"},
+ {0, kRight | kPos, /*width = */ 6, "____+0"},
+ {0, kRight | kBase, /*width = */ 0, "0"},
+ {0, kRight | kBase, /*width = */ 6, "_____0"},
+ {0, kRight | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kRight | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kRight | kUpper, /*width = */ 0, "0"},
+ {0, kRight | kUpper, /*width = */ 6, "_____0"},
+ {0, kRight | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kRight | kUpper | kPos, /*width = */ 6, "____+0"},
+ {0, kRight | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kDec, /*width = */ 0, "0"},
+ {0, kDec, /*width = */ 6, "_____0"},
+ {0, kDec | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kBase, /*width = */ 0, "0"},
+ {0, kDec | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kUpper, /*width = */ 0, "0"},
+ {0, kDec | kUpper, /*width = */ 6, "_____0"},
+ {0, kDec | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kUpper | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kDec | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kLeft, /*width = */ 0, "0"},
+ {0, kDec | kLeft, /*width = */ 6, "0_____"},
+ {0, kDec | kLeft | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kLeft | kPos, /*width = */ 6, "+0____"},
+ {0, kDec | kLeft | kBase, /*width = */ 0, "0"},
+ {0, kDec | kLeft | kBase, /*width = */ 6, "0_____"},
+ {0, kDec | kLeft | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kLeft | kBase | kPos, /*width = */ 6, "+0____"},
+ {0, kDec | kLeft | kUpper, /*width = */ 0, "0"},
+ {0, kDec | kLeft | kUpper, /*width = */ 6, "0_____"},
+ {0, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+0____"},
+ {0, kDec | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kDec | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+ {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+0____"},
+ {0, kDec | kInt, /*width = */ 0, "0"},
+ {0, kDec | kInt, /*width = */ 6, "_____0"},
+ {0, kDec | kInt | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kInt | kPos, /*width = */ 6, "+____0"},
+ {0, kDec | kInt | kBase, /*width = */ 0, "0"},
+ {0, kDec | kInt | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kInt | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kInt | kBase | kPos, /*width = */ 6, "+____0"},
+ {0, kDec | kInt | kUpper, /*width = */ 0, "0"},
+ {0, kDec | kInt | kUpper, /*width = */ 6, "_____0"},
+ {0, kDec | kInt | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kInt | kUpper | kPos, /*width = */ 6, "+____0"},
+ {0, kDec | kInt | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kDec | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+____0"},
+ {0, kDec | kRight, /*width = */ 0, "0"},
+ {0, kDec | kRight, /*width = */ 6, "_____0"},
+ {0, kDec | kRight | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kRight | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kRight | kBase, /*width = */ 0, "0"},
+ {0, kDec | kRight | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kRight | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kRight | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kRight | kUpper, /*width = */ 0, "0"},
+ {0, kDec | kRight | kUpper, /*width = */ 6, "_____0"},
+ {0, kDec | kRight | kUpper | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kRight | kUpper | kPos, /*width = */ 6, "____+0"},
+ {0, kDec | kRight | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kDec | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+0"},
+ {0, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "____+0"},
+ {0, kOct, /*width = */ 0, "0"},
+ {0, kOct, /*width = */ 6, "_____0"},
+ {0, kOct | kPos, /*width = */ 0, "0"},
+ {0, kOct | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kBase, /*width = */ 0, "0"},
+ {0, kOct | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kUpper, /*width = */ 0, "0"},
+ {0, kOct | kUpper, /*width = */ 6, "_____0"},
+ {0, kOct | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kOct | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kOct | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kLeft, /*width = */ 0, "0"},
+ {0, kOct | kLeft, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kPos, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kPos, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kBase, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kBase, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kBase | kPos, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kUpper, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kUpper, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kUpper | kPos, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+ {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"},
+ {0, kOct | kInt, /*width = */ 0, "0"},
+ {0, kOct | kInt, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kPos, /*width = */ 0, "0"},
+ {0, kOct | kInt | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kBase, /*width = */ 0, "0"},
+ {0, kOct | kInt | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kInt | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kUpper, /*width = */ 0, "0"},
+ {0, kOct | kInt | kUpper, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kOct | kInt | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kOct | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kRight, /*width = */ 0, "0"},
+ {0, kOct | kRight, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kPos, /*width = */ 0, "0"},
+ {0, kOct | kRight | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kBase, /*width = */ 0, "0"},
+ {0, kOct | kRight | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kRight | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kUpper, /*width = */ 0, "0"},
+ {0, kOct | kRight | kUpper, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kOct | kRight | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kOct | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex, /*width = */ 0, "0"},
+ {0, kHex, /*width = */ 6, "_____0"},
+ {0, kHex | kPos, /*width = */ 0, "0"},
+ {0, kHex | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kBase, /*width = */ 0, "0"},
+ {0, kHex | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kUpper, /*width = */ 0, "0"},
+ {0, kHex | kUpper, /*width = */ 6, "_____0"},
+ {0, kHex | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kHex | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kHex | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kLeft, /*width = */ 0, "0"},
+ {0, kHex | kLeft, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kPos, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kPos, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kBase, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kBase, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kBase | kPos, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kUpper, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kUpper, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kUpper | kPos, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0_____"},
+ {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0_____"},
+ {0, kHex | kInt, /*width = */ 0, "0"},
+ {0, kHex | kInt, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kPos, /*width = */ 0, "0"},
+ {0, kHex | kInt | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kBase, /*width = */ 0, "0"},
+ {0, kHex | kInt | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kInt | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kUpper, /*width = */ 0, "0"},
+ {0, kHex | kInt | kUpper, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kHex | kInt | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kHex | kInt | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kRight, /*width = */ 0, "0"},
+ {0, kHex | kRight, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kPos, /*width = */ 0, "0"},
+ {0, kHex | kRight | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kBase, /*width = */ 0, "0"},
+ {0, kHex | kRight | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kRight | kBase | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kUpper, /*width = */ 0, "0"},
+ {0, kHex | kRight | kUpper, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kUpper | kPos, /*width = */ 0, "0"},
+ {0, kHex | kRight | kUpper | kPos, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kUpper | kBase, /*width = */ 0, "0"},
+ {0, kHex | kRight | kUpper | kBase, /*width = */ 6, "_____0"},
+ {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0"},
+ {0, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "_____0"},
+ {42, std::ios_base::fmtflags(), /*width = */ 0, "42"},
+ {42, std::ios_base::fmtflags(), /*width = */ 6, "____42"},
+ {42, kPos, /*width = */ 0, "+42"},
+ {42, kPos, /*width = */ 6, "___+42"},
+ {42, kBase, /*width = */ 0, "42"},
+ {42, kBase, /*width = */ 6, "____42"},
+ {42, kBase | kPos, /*width = */ 0, "+42"},
+ {42, kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kUpper, /*width = */ 0, "42"},
+ {42, kUpper, /*width = */ 6, "____42"},
+ {42, kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kUpper | kPos, /*width = */ 6, "___+42"},
+ {42, kUpper | kBase, /*width = */ 0, "42"},
+ {42, kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kLeft, /*width = */ 0, "42"},
+ {42, kLeft, /*width = */ 6, "42____"},
+ {42, kLeft | kPos, /*width = */ 0, "+42"},
+ {42, kLeft | kPos, /*width = */ 6, "+42___"},
+ {42, kLeft | kBase, /*width = */ 0, "42"},
+ {42, kLeft | kBase, /*width = */ 6, "42____"},
+ {42, kLeft | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kLeft | kBase | kPos, /*width = */ 6, "+42___"},
+ {42, kLeft | kUpper, /*width = */ 0, "42"},
+ {42, kLeft | kUpper, /*width = */ 6, "42____"},
+ {42, kLeft | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kLeft | kUpper | kPos, /*width = */ 6, "+42___"},
+ {42, kLeft | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kLeft | kUpper | kBase, /*width = */ 6, "42____"},
+ {42, kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"},
+ {42, kInt, /*width = */ 0, "42"},
+ {42, kInt, /*width = */ 6, "____42"},
+ {42, kInt | kPos, /*width = */ 0, "+42"},
+ {42, kInt | kPos, /*width = */ 6, "+___42"},
+ {42, kInt | kBase, /*width = */ 0, "42"},
+ {42, kInt | kBase, /*width = */ 6, "____42"},
+ {42, kInt | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kInt | kBase | kPos, /*width = */ 6, "+___42"},
+ {42, kInt | kUpper, /*width = */ 0, "42"},
+ {42, kInt | kUpper, /*width = */ 6, "____42"},
+ {42, kInt | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kInt | kUpper | kPos, /*width = */ 6, "+___42"},
+ {42, kInt | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kInt | kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"},
+ {42, kRight, /*width = */ 0, "42"},
+ {42, kRight, /*width = */ 6, "____42"},
+ {42, kRight | kPos, /*width = */ 0, "+42"},
+ {42, kRight | kPos, /*width = */ 6, "___+42"},
+ {42, kRight | kBase, /*width = */ 0, "42"},
+ {42, kRight | kBase, /*width = */ 6, "____42"},
+ {42, kRight | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kRight | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kRight | kUpper, /*width = */ 0, "42"},
+ {42, kRight | kUpper, /*width = */ 6, "____42"},
+ {42, kRight | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kRight | kUpper | kPos, /*width = */ 6, "___+42"},
+ {42, kRight | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kRight | kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kDec, /*width = */ 0, "42"},
+ {42, kDec, /*width = */ 6, "____42"},
+ {42, kDec | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kBase, /*width = */ 0, "42"},
+ {42, kDec | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kUpper, /*width = */ 0, "42"},
+ {42, kDec | kUpper, /*width = */ 6, "____42"},
+ {42, kDec | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kUpper | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kDec | kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kLeft, /*width = */ 0, "42"},
+ {42, kDec | kLeft, /*width = */ 6, "42____"},
+ {42, kDec | kLeft | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kLeft | kPos, /*width = */ 6, "+42___"},
+ {42, kDec | kLeft | kBase, /*width = */ 0, "42"},
+ {42, kDec | kLeft | kBase, /*width = */ 6, "42____"},
+ {42, kDec | kLeft | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kLeft | kBase | kPos, /*width = */ 6, "+42___"},
+ {42, kDec | kLeft | kUpper, /*width = */ 0, "42"},
+ {42, kDec | kLeft | kUpper, /*width = */ 6, "42____"},
+ {42, kDec | kLeft | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kLeft | kUpper | kPos, /*width = */ 6, "+42___"},
+ {42, kDec | kLeft | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kDec | kLeft | kUpper | kBase, /*width = */ 6, "42____"},
+ {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "+42___"},
+ {42, kDec | kInt, /*width = */ 0, "42"},
+ {42, kDec | kInt, /*width = */ 6, "____42"},
+ {42, kDec | kInt | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kInt | kPos, /*width = */ 6, "+___42"},
+ {42, kDec | kInt | kBase, /*width = */ 0, "42"},
+ {42, kDec | kInt | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kInt | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kInt | kBase | kPos, /*width = */ 6, "+___42"},
+ {42, kDec | kInt | kUpper, /*width = */ 0, "42"},
+ {42, kDec | kInt | kUpper, /*width = */ 6, "____42"},
+ {42, kDec | kInt | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kInt | kUpper | kPos, /*width = */ 6, "+___42"},
+ {42, kDec | kInt | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kDec | kInt | kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "+___42"},
+ {42, kDec | kRight, /*width = */ 0, "42"},
+ {42, kDec | kRight, /*width = */ 6, "____42"},
+ {42, kDec | kRight | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kRight | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kRight | kBase, /*width = */ 0, "42"},
+ {42, kDec | kRight | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kRight | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kRight | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kRight | kUpper, /*width = */ 0, "42"},
+ {42, kDec | kRight | kUpper, /*width = */ 6, "____42"},
+ {42, kDec | kRight | kUpper | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kRight | kUpper | kPos, /*width = */ 6, "___+42"},
+ {42, kDec | kRight | kUpper | kBase, /*width = */ 0, "42"},
+ {42, kDec | kRight | kUpper | kBase, /*width = */ 6, "____42"},
+ {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "+42"},
+ {42, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "___+42"},
+ {42, kOct, /*width = */ 0, "52"},
+ {42, kOct, /*width = */ 6, "____52"},
+ {42, kOct | kPos, /*width = */ 0, "52"},
+ {42, kOct | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kBase, /*width = */ 0, "052"},
+ {42, kOct | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kOct | kUpper, /*width = */ 0, "52"},
+ {42, kOct | kUpper, /*width = */ 6, "____52"},
+ {42, kOct | kUpper | kPos, /*width = */ 0, "52"},
+ {42, kOct | kUpper | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kUpper | kBase, /*width = */ 0, "052"},
+ {42, kOct | kUpper | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kUpper | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kOct | kLeft, /*width = */ 0, "52"},
+ {42, kOct | kLeft, /*width = */ 6, "52____"},
+ {42, kOct | kLeft | kPos, /*width = */ 0, "52"},
+ {42, kOct | kLeft | kPos, /*width = */ 6, "52____"},
+ {42, kOct | kLeft | kBase, /*width = */ 0, "052"},
+ {42, kOct | kLeft | kBase, /*width = */ 6, "052___"},
+ {42, kOct | kLeft | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kLeft | kBase | kPos, /*width = */ 6, "052___"},
+ {42, kOct | kLeft | kUpper, /*width = */ 0, "52"},
+ {42, kOct | kLeft | kUpper, /*width = */ 6, "52____"},
+ {42, kOct | kLeft | kUpper | kPos, /*width = */ 0, "52"},
+ {42, kOct | kLeft | kUpper | kPos, /*width = */ 6, "52____"},
+ {42, kOct | kLeft | kUpper | kBase, /*width = */ 0, "052"},
+ {42, kOct | kLeft | kUpper | kBase, /*width = */ 6, "052___"},
+ {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kLeft | kUpper | kBase | kPos, /*width = */ 6, "052___"},
+ {42, kOct | kInt, /*width = */ 0, "52"},
+ {42, kOct | kInt, /*width = */ 6, "____52"},
+ {42, kOct | kInt | kPos, /*width = */ 0, "52"},
+ {42, kOct | kInt | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kInt | kBase, /*width = */ 0, "052"},
+ {42, kOct | kInt | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kInt | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kInt | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kOct | kInt | kUpper, /*width = */ 0, "52"},
+ {42, kOct | kInt | kUpper, /*width = */ 6, "____52"},
+ {42, kOct | kInt | kUpper | kPos, /*width = */ 0, "52"},
+ {42, kOct | kInt | kUpper | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kInt | kUpper | kBase, /*width = */ 0, "052"},
+ {42, kOct | kInt | kUpper | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kInt | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kOct | kRight, /*width = */ 0, "52"},
+ {42, kOct | kRight, /*width = */ 6, "____52"},
+ {42, kOct | kRight | kPos, /*width = */ 0, "52"},
+ {42, kOct | kRight | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kRight | kBase, /*width = */ 0, "052"},
+ {42, kOct | kRight | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kRight | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kRight | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kOct | kRight | kUpper, /*width = */ 0, "52"},
+ {42, kOct | kRight | kUpper, /*width = */ 6, "____52"},
+ {42, kOct | kRight | kUpper | kPos, /*width = */ 0, "52"},
+ {42, kOct | kRight | kUpper | kPos, /*width = */ 6, "____52"},
+ {42, kOct | kRight | kUpper | kBase, /*width = */ 0, "052"},
+ {42, kOct | kRight | kUpper | kBase, /*width = */ 6, "___052"},
+ {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 0, "052"},
+ {42, kOct | kRight | kUpper | kBase | kPos, /*width = */ 6, "___052"},
+ {42, kHex, /*width = */ 0, "2a"},
+ {42, kHex, /*width = */ 6, "____2a"},
+ {42, kHex | kPos, /*width = */ 0, "2a"},
+ {42, kHex | kPos, /*width = */ 6, "____2a"},
+ {42, kHex | kBase, /*width = */ 0, "0x2a"},
+ {42, kHex | kBase, /*width = */ 6, "__0x2a"},
+ {42, kHex | kBase | kPos, /*width = */ 0, "0x2a"},
+ {42, kHex | kBase | kPos, /*width = */ 6, "__0x2a"},
+ {42, kHex | kUpper, /*width = */ 0, "2A"},
+ {42, kHex | kUpper, /*width = */ 6, "____2A"},
+ {42, kHex | kUpper | kPos, /*width = */ 0, "2A"},
+ {42, kHex | kUpper | kPos, /*width = */ 6, "____2A"},
+ {42, kHex | kUpper | kBase, /*width = */ 0, "0X2A"},
+ {42, kHex | kUpper | kBase, /*width = */ 6, "__0X2A"},
+ {42, kHex | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+ {42, kHex | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"},
+ {42, kHex | kLeft, /*width = */ 0, "2a"},
+ {42, kHex | kLeft, /*width = */ 6, "2a____"},
+ {42, kHex | kLeft | kPos, /*width = */ 0, "2a"},
+ {42, kHex | kLeft | kPos, /*width = */ 6, "2a____"},
+ {42, kHex | kLeft | kBase, /*width = */ 0, "0x2a"},
+ {42, kHex | kLeft | kBase, /*width = */ 6, "0x2a__"},
+ {42, kHex | kLeft | kBase | kPos, /*width = */ 0, "0x2a"},
+ {42, kHex | kLeft | kBase | kPos, /*width = */ 6, "0x2a__"},
+ {42, kHex | kLeft | kUpper, /*width = */ 0, "2A"},
+ {42, kHex | kLeft | kUpper, /*width = */ 6, "2A____"},
+ {42, kHex | kLeft | kUpper | kPos, /*width = */ 0, "2A"},
+ {42, kHex | kLeft | kUpper | kPos, /*width = */ 6, "2A____"},
+ {42, kHex | kLeft | kUpper | kBase, /*width = */ 0, "0X2A"},
+ {42, kHex | kLeft | kUpper | kBase, /*width = */ 6, "0X2A__"},
+ {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+ {42, kHex | kLeft | kUpper | kBase | kPos, /*width = */ 6, "0X2A__"},
+ {42, kHex | kInt, /*width = */ 0, "2a"},
+ {42, kHex | kInt, /*width = */ 6, "____2a"},
+ {42, kHex | kInt | kPos, /*width = */ 0, "2a"},
+ {42, kHex | kInt | kPos, /*width = */ 6, "____2a"},
+ {42, kHex | kInt | kBase, /*width = */ 0, "0x2a"},
+ {42, kHex | kInt | kBase, /*width = */ 6, "0x__2a"},
+ {42, kHex | kInt | kBase | kPos, /*width = */ 0, "0x2a"},
+ {42, kHex | kInt | kBase | kPos, /*width = */ 6, "0x__2a"},
+ {42, kHex | kInt | kUpper, /*width = */ 0, "2A"},
+ {42, kHex | kInt | kUpper, /*width = */ 6, "____2A"},
+ {42, kHex | kInt | kUpper | kPos, /*width = */ 0, "2A"},
+ {42, kHex | kInt | kUpper | kPos, /*width = */ 6, "____2A"},
+ {42, kHex | kInt | kUpper | kBase, /*width = */ 0, "0X2A"},
+ {42, kHex | kInt | kUpper | kBase, /*width = */ 6, "0X__2A"},
+ {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+ {42, kHex | kInt | kUpper | kBase | kPos, /*width = */ 6, "0X__2A"},
+ {42, kHex | kRight, /*width = */ 0, "2a"},
+ {42, kHex | kRight, /*width = */ 6, "____2a"},
+ {42, kHex | kRight | kPos, /*width = */ 0, "2a"},
+ {42, kHex | kRight | kPos, /*width = */ 6, "____2a"},
+ {42, kHex | kRight | kBase, /*width = */ 0, "0x2a"},
+ {42, kHex | kRight | kBase, /*width = */ 6, "__0x2a"},
+ {42, kHex | kRight | kBase | kPos, /*width = */ 0, "0x2a"},
+ {42, kHex | kRight | kBase | kPos, /*width = */ 6, "__0x2a"},
+ {42, kHex | kRight | kUpper, /*width = */ 0, "2A"},
+ {42, kHex | kRight | kUpper, /*width = */ 6, "____2A"},
+ {42, kHex | kRight | kUpper | kPos, /*width = */ 0, "2A"},
+ {42, kHex | kRight | kUpper | kPos, /*width = */ 6, "____2A"},
+ {42, kHex | kRight | kUpper | kBase, /*width = */ 0, "0X2A"},
+ {42, kHex | kRight | kUpper | kBase, /*width = */ 6, "__0X2A"},
+ {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 0, "0X2A"},
+ {42, kHex | kRight | kUpper | kBase | kPos, /*width = */ 6, "__0X2A"},
+ {-321, std::ios_base::fmtflags(), /*width = */ 0, "-321"},
+ {-321, std::ios_base::fmtflags(), /*width = */ 6, "__-321"},
+ {-321, kPos, /*width = */ 0, "-321"},
+ {-321, kPos, /*width = */ 6, "__-321"},
+ {-321, kBase, /*width = */ 0, "-321"},
+ {-321, kBase, /*width = */ 6, "__-321"},
+ {-321, kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kUpper, /*width = */ 0, "-321"},
+ {-321, kUpper, /*width = */ 6, "__-321"},
+ {-321, kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kUpper | kPos, /*width = */ 6, "__-321"},
+ {-321, kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kUpper | kBase, /*width = */ 6, "__-321"},
+ {-321, kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kLeft, /*width = */ 0, "-321"},
+ {-321, kLeft, /*width = */ 6, "-321__"},
+ {-321, kLeft | kPos, /*width = */ 0, "-321"},
+ {-321, kLeft | kPos, /*width = */ 6, "-321__"},
+ {-321, kLeft | kBase, /*width = */ 0, "-321"},
+ {-321, kLeft | kBase, /*width = */ 6, "-321__"},
+ {-321, kLeft | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kLeft | kBase | kPos, /*width = */ 6, "-321__"},
+ {-321, kLeft | kUpper, /*width = */ 0, "-321"},
+ {-321, kLeft | kUpper, /*width = */ 6, "-321__"},
+ {-321, kLeft | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kLeft | kUpper | kPos, /*width = */ 6, "-321__"},
+ {-321, kLeft | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kLeft | kUpper | kBase, /*width = */ 6, "-321__"},
+ {-321, kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"},
+ {-321, kInt, /*width = */ 0, "-321"},
+ {-321, kInt, /*width = */ 6, "-__321"},
+ {-321, kInt | kPos, /*width = */ 0, "-321"},
+ {-321, kInt | kPos, /*width = */ 6, "-__321"},
+ {-321, kInt | kBase, /*width = */ 0, "-321"},
+ {-321, kInt | kBase, /*width = */ 6, "-__321"},
+ {-321, kInt | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kInt | kBase | kPos, /*width = */ 6, "-__321"},
+ {-321, kInt | kUpper, /*width = */ 0, "-321"},
+ {-321, kInt | kUpper, /*width = */ 6, "-__321"},
+ {-321, kInt | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kInt | kUpper | kPos, /*width = */ 6, "-__321"},
+ {-321, kInt | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kInt | kUpper | kBase, /*width = */ 6, "-__321"},
+ {-321, kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"},
+ {-321, kRight, /*width = */ 0, "-321"},
+ {-321, kRight, /*width = */ 6, "__-321"},
+ {-321, kRight | kPos, /*width = */ 0, "-321"},
+ {-321, kRight | kPos, /*width = */ 6, "__-321"},
+ {-321, kRight | kBase, /*width = */ 0, "-321"},
+ {-321, kRight | kBase, /*width = */ 6, "__-321"},
+ {-321, kRight | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kRight | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kRight | kUpper, /*width = */ 0, "-321"},
+ {-321, kRight | kUpper, /*width = */ 6, "__-321"},
+ {-321, kRight | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kRight | kUpper | kPos, /*width = */ 6, "__-321"},
+ {-321, kRight | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kRight | kUpper | kBase, /*width = */ 6, "__-321"},
+ {-321, kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec, /*width = */ 0, "-321"},
+ {-321, kDec, /*width = */ 6, "__-321"},
+ {-321, kDec | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kBase, /*width = */ 6, "__-321"},
+ {-321, kDec | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kUpper, /*width = */ 0, "-321"},
+ {-321, kDec | kUpper, /*width = */ 6, "__-321"},
+ {-321, kDec | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kUpper | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kUpper | kBase, /*width = */ 6, "__-321"},
+ {-321, kDec | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kUpper | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kLeft, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kPos, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kBase, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kBase | kPos, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kUpper, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kUpper, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kUpper | kPos, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kUpper | kBase, /*width = */ 6, "-321__"},
+ {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kLeft | kUpper | kBase | kPos, /*width = */ 6, "-321__"},
+ {-321, kDec | kInt, /*width = */ 0, "-321"},
+ {-321, kDec | kInt, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kPos, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kBase, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kBase | kPos, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kUpper, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kUpper, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kUpper | kPos, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kUpper | kBase, /*width = */ 6, "-__321"},
+ {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kInt | kUpper | kBase | kPos, /*width = */ 6, "-__321"},
+ {-321, kDec | kRight, /*width = */ 0, "-321"},
+ {-321, kDec | kRight, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kBase, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kBase | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kUpper, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kUpper, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kUpper | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kUpper | kPos, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kUpper | kBase, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kUpper | kBase, /*width = */ 6, "__-321"},
+ {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 0, "-321"},
+ {-321, kDec | kRight | kUpper | kBase | kPos, /*width = */ 6, "__-321"}};
+}
+
std::vector<Uint128TestCase> GetUint128FormatCases() {
return {
{0, std::ios_base::fmtflags(), /*width = */ 0, "0"},
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_test.cc
index dfe3475aca0..bc86c714acc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/int128_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -51,7 +51,7 @@ template <typename T>
class Uint128FloatTraitsTest : public ::testing::Test {};
typedef ::testing::Types<float, double, long double> FloatingPointTypes;
-TYPED_TEST_CASE(Uint128IntegerTraitsTest, IntegerTypes);
+TYPED_TEST_SUITE(Uint128IntegerTraitsTest, IntegerTypes);
TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {
static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -62,7 +62,7 @@ TYPED_TEST(Uint128IntegerTraitsTest, ConstructAssignTest) {
"TypeParam must not be assignable from absl::uint128");
}
-TYPED_TEST_CASE(Uint128FloatTraitsTest, FloatingPointTypes);
+TYPED_TEST_SUITE(Uint128FloatTraitsTest, FloatingPointTypes);
TYPED_TEST(Uint128FloatTraitsTest, ConstructAssignTest) {
static_assert(std::is_constructible<absl::uint128, TypeParam>::value,
@@ -271,6 +271,20 @@ TEST(Uint128, ConversionTests) {
EXPECT_EQ(static_cast<absl::uint128>(round_to_zero), 0);
EXPECT_EQ(static_cast<absl::uint128>(round_to_five), 5);
EXPECT_EQ(static_cast<absl::uint128>(round_to_nine), 9);
+
+ absl::uint128 highest_precision_in_long_double =
+ ~absl::uint128{} >> (128 - std::numeric_limits<long double>::digits);
+ EXPECT_EQ(highest_precision_in_long_double,
+ static_cast<absl::uint128>(
+ static_cast<long double>(highest_precision_in_long_double)));
+ // Apply a mask just to make sure all the bits are the right place.
+ const absl::uint128 arbitrary_mask =
+ absl::MakeUint128(0xa29f622677ded751, 0xf8ca66add076f468);
+ EXPECT_EQ(highest_precision_in_long_double & arbitrary_mask,
+ static_cast<absl::uint128>(static_cast<long double>(
+ highest_precision_in_long_double & arbitrary_mask)));
+
+ EXPECT_EQ(static_cast<absl::uint128>(-0.1L), 0);
}
TEST(Uint128, OperatorAssignReturnRef) {
@@ -440,4 +454,772 @@ TEST(Uint128, NumericLimitsTest) {
EXPECT_EQ(absl::Uint128Max(), std::numeric_limits<absl::uint128>::max());
}
+TEST(Uint128, Hash) {
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly({
+ // Some simple values
+ absl::uint128{0},
+ absl::uint128{1},
+ ~absl::uint128{},
+ // 64 bit limits
+ absl::uint128{std::numeric_limits<int64_t>::max()},
+ absl::uint128{std::numeric_limits<uint64_t>::max()} + 0,
+ absl::uint128{std::numeric_limits<uint64_t>::max()} + 1,
+ absl::uint128{std::numeric_limits<uint64_t>::max()} + 2,
+ // Keeping high same
+ absl::uint128{1} << 62,
+ absl::uint128{1} << 63,
+ // Keeping low same
+ absl::uint128{1} << 64,
+ absl::uint128{1} << 65,
+ // 128 bit limits
+ std::numeric_limits<absl::uint128>::max(),
+ std::numeric_limits<absl::uint128>::max() - 1,
+ std::numeric_limits<absl::uint128>::min() + 1,
+ std::numeric_limits<absl::uint128>::min(),
+ }));
+}
+
+
+TEST(Int128Uint128, ConversionTest) {
+ absl::int128 nonnegative_signed_values[] = {
+ 0,
+ 1,
+ 0xffeeddccbbaa9988,
+ absl::MakeInt128(0x7766554433221100, 0),
+ absl::MakeInt128(0x1234567890abcdef, 0xfedcba0987654321),
+ absl::Int128Max()};
+ for (absl::int128 value : nonnegative_signed_values) {
+ EXPECT_EQ(value, absl::int128(absl::uint128(value)));
+
+ absl::uint128 assigned_value;
+ assigned_value = value;
+ EXPECT_EQ(value, absl::int128(assigned_value));
+ }
+
+ absl::int128 negative_values[] = {
+ -1, -0x1234567890abcdef,
+ absl::MakeInt128(-0x5544332211ffeedd, 0),
+ -absl::MakeInt128(0x76543210fedcba98, 0xabcdef0123456789)};
+ for (absl::int128 value : negative_values) {
+ EXPECT_EQ(absl::uint128(-value), -absl::uint128(value));
+
+ absl::uint128 assigned_value;
+ assigned_value = value;
+ EXPECT_EQ(absl::uint128(-value), -assigned_value);
+ }
+}
+
+template <typename T>
+class Int128IntegerTraitsTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128IntegerTraitsTest, IntegerTypes);
+
+TYPED_TEST(Int128IntegerTraitsTest, ConstructAssignTest) {
+ static_assert(std::is_constructible<absl::int128, TypeParam>::value,
+ "absl::int128 must be constructible from TypeParam");
+ static_assert(std::is_assignable<absl::int128&, TypeParam>::value,
+ "absl::int128 must be assignable from TypeParam");
+ static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,
+ "TypeParam must not be assignable from absl::int128");
+}
+
+template <typename T>
+class Int128FloatTraitsTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128FloatTraitsTest, FloatingPointTypes);
+
+TYPED_TEST(Int128FloatTraitsTest, ConstructAssignTest) {
+ static_assert(std::is_constructible<absl::int128, TypeParam>::value,
+ "absl::int128 must be constructible from TypeParam");
+ static_assert(!std::is_assignable<absl::int128&, TypeParam>::value,
+ "absl::int128 must not be assignable from TypeParam");
+ static_assert(!std::is_assignable<TypeParam&, absl::int128>::value,
+ "TypeParam must not be assignable from absl::int128");
+}
+
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+// These type traits done separately as TYPED_TEST requires typeinfo, and not
+// all platforms have this for __int128 even though they define the type.
+TEST(Int128, IntrinsicTypeTraitsTest) {
+ static_assert(std::is_constructible<absl::int128, __int128>::value,
+ "absl::int128 must be constructible from __int128");
+ static_assert(std::is_assignable<absl::int128&, __int128>::value,
+ "absl::int128 must be assignable from __int128");
+ static_assert(!std::is_assignable<__int128&, absl::int128>::value,
+ "__int128 must not be assignable from absl::int128");
+
+ static_assert(std::is_constructible<absl::int128, unsigned __int128>::value,
+ "absl::int128 must be constructible from unsigned __int128");
+ static_assert(!std::is_assignable<absl::int128&, unsigned __int128>::value,
+ "absl::int128 must be assignable from unsigned __int128");
+ static_assert(!std::is_assignable<unsigned __int128&, absl::int128>::value,
+ "unsigned __int128 must not be assignable from absl::int128");
+}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+TEST(Int128, TrivialTraitsTest) {
+ static_assert(absl::is_trivially_default_constructible<absl::int128>::value,
+ "");
+ static_assert(absl::is_trivially_copy_constructible<absl::int128>::value, "");
+ static_assert(absl::is_trivially_copy_assignable<absl::int128>::value, "");
+ static_assert(std::is_trivially_destructible<absl::int128>::value, "");
+}
+
+TEST(Int128, BoolConversionTest) {
+ EXPECT_FALSE(absl::int128(0));
+ for (int i = 0; i < 64; ++i) {
+ EXPECT_TRUE(absl::MakeInt128(0, uint64_t{1} << i));
+ }
+ for (int i = 0; i < 63; ++i) {
+ EXPECT_TRUE(absl::MakeInt128(int64_t{1} << i, 0));
+ }
+ EXPECT_TRUE(absl::Int128Min());
+
+ EXPECT_EQ(absl::int128(1), absl::int128(true));
+ EXPECT_EQ(absl::int128(0), absl::int128(false));
+}
+
+template <typename T>
+class Int128IntegerConversionTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128IntegerConversionTest, IntegerTypes);
+
+TYPED_TEST(Int128IntegerConversionTest, RoundTripTest) {
+ EXPECT_EQ(TypeParam{0}, static_cast<TypeParam>(absl::int128(0)));
+ EXPECT_EQ(std::numeric_limits<TypeParam>::min(),
+ static_cast<TypeParam>(
+ absl::int128(std::numeric_limits<TypeParam>::min())));
+ EXPECT_EQ(std::numeric_limits<TypeParam>::max(),
+ static_cast<TypeParam>(
+ absl::int128(std::numeric_limits<TypeParam>::max())));
+}
+
+template <typename T>
+class Int128FloatConversionTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE(Int128FloatConversionTest, FloatingPointTypes);
+
+TYPED_TEST(Int128FloatConversionTest, ConstructAndCastTest) {
+ // Conversions where the floating point values should be exactly the same.
+ // 0x9f5b is a randomly chosen small value.
+ for (int i = 0; i < 110; ++i) { // 110 = 126 - #bits in 0x9f5b
+ SCOPED_TRACE(::testing::Message() << "i = " << i);
+
+ TypeParam float_value = std::ldexp(static_cast<TypeParam>(0x9f5b), i);
+ absl::int128 int_value = absl::int128(0x9f5b) << i;
+
+ EXPECT_EQ(float_value, static_cast<TypeParam>(int_value));
+ EXPECT_EQ(-float_value, static_cast<TypeParam>(-int_value));
+ EXPECT_EQ(int_value, absl::int128(float_value));
+ EXPECT_EQ(-int_value, absl::int128(-float_value));
+ }
+
+ // Round trip conversions with a small sample of randomly generated uint64_t
+ // values (less than int64_t max so that value * 2^64 fits into int128).
+ uint64_t values[] = {0x6d4492c24fb86199, 0x26ead65e4cb359b5,
+ 0x2c43407433ba3fd1, 0x3b574ec668df6b55,
+ 0x1c750e55a29f4f0f};
+ for (uint64_t value : values) {
+ for (int i = 0; i <= 64; ++i) {
+ SCOPED_TRACE(::testing::Message()
+ << "value = " << value << "; i = " << i);
+
+ TypeParam fvalue = std::ldexp(static_cast<TypeParam>(value), i);
+ EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(absl::int128(fvalue)));
+ EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(-absl::int128(fvalue)));
+ EXPECT_DOUBLE_EQ(-fvalue, static_cast<TypeParam>(absl::int128(-fvalue)));
+ EXPECT_DOUBLE_EQ(fvalue, static_cast<TypeParam>(-absl::int128(-fvalue)));
+ }
+ }
+
+ // Round trip conversions with a small sample of random large positive values.
+ absl::int128 large_values[] = {
+ absl::MakeInt128(0x5b0640d96c7b3d9f, 0xb7a7189e51d18622),
+ absl::MakeInt128(0x34bed042c6f65270, 0x73b236570669a089),
+ absl::MakeInt128(0x43deba9e6da12724, 0xf7f0f83da686797d),
+ absl::MakeInt128(0x71e8d383be4e5589, 0x75c3f96fb00752b6)};
+ for (absl::int128 value : large_values) {
+ // Make value have as many significant bits as can be represented by
+ // the mantissa, also making sure the highest and lowest bit in the range
+ // are set.
+ value >>= (127 - std::numeric_limits<TypeParam>::digits);
+ value |= absl::int128(1) << (std::numeric_limits<TypeParam>::digits - 1);
+ value |= 1;
+ for (int i = 0; i < 127 - std::numeric_limits<TypeParam>::digits; ++i) {
+ absl::int128 int_value = value << i;
+ EXPECT_EQ(int_value,
+ static_cast<absl::int128>(static_cast<TypeParam>(int_value)));
+ EXPECT_EQ(-int_value,
+ static_cast<absl::int128>(static_cast<TypeParam>(-int_value)));
+ }
+ }
+
+ // Small sample of checks that rounding is toward zero
+ EXPECT_EQ(0, absl::int128(TypeParam(0.1)));
+ EXPECT_EQ(17, absl::int128(TypeParam(17.8)));
+ EXPECT_EQ(0, absl::int128(TypeParam(-0.8)));
+ EXPECT_EQ(-53, absl::int128(TypeParam(-53.1)));
+ EXPECT_EQ(0, absl::int128(TypeParam(0.5)));
+ EXPECT_EQ(0, absl::int128(TypeParam(-0.5)));
+ TypeParam just_lt_one = std::nexttoward(TypeParam(1), TypeParam(0));
+ EXPECT_EQ(0, absl::int128(just_lt_one));
+ TypeParam just_gt_minus_one = std::nexttoward(TypeParam(-1), TypeParam(0));
+ EXPECT_EQ(0, absl::int128(just_gt_minus_one));
+
+ // Check limits
+ EXPECT_DOUBLE_EQ(std::ldexp(static_cast<TypeParam>(1), 127),
+ static_cast<TypeParam>(absl::Int128Max()));
+ EXPECT_DOUBLE_EQ(-std::ldexp(static_cast<TypeParam>(1), 127),
+ static_cast<TypeParam>(absl::Int128Min()));
+}
+
+TEST(Int128, FactoryTest) {
+ EXPECT_EQ(absl::int128(-1), absl::MakeInt128(-1, -1));
+ EXPECT_EQ(absl::int128(-31), absl::MakeInt128(-1, -31));
+ EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::min()),
+ absl::MakeInt128(-1, std::numeric_limits<int64_t>::min()));
+ EXPECT_EQ(absl::int128(0), absl::MakeInt128(0, 0));
+ EXPECT_EQ(absl::int128(1), absl::MakeInt128(0, 1));
+ EXPECT_EQ(absl::int128(std::numeric_limits<int64_t>::max()),
+ absl::MakeInt128(0, std::numeric_limits<int64_t>::max()));
+}
+
+TEST(Int128, HighLowTest) {
+ struct HighLowPair {
+ int64_t high;
+ uint64_t low;
+ };
+ HighLowPair values[]{{0, 0}, {0, 1}, {1, 0}, {123, 456}, {-654, 321}};
+ for (const HighLowPair& pair : values) {
+ absl::int128 value = absl::MakeInt128(pair.high, pair.low);
+ EXPECT_EQ(pair.low, absl::Int128Low64(value));
+ EXPECT_EQ(pair.high, absl::Int128High64(value));
+ }
+}
+
+TEST(Int128, LimitsTest) {
+ EXPECT_EQ(absl::MakeInt128(0x7fffffffffffffff, 0xffffffffffffffff),
+ absl::Int128Max());
+ EXPECT_EQ(absl::Int128Max(), ~absl::Int128Min());
+}
+
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+TEST(Int128, IntrinsicConversionTest) {
+ __int128 intrinsic =
+ (static_cast<__int128>(0x3a5b76c209de76f6) << 64) + 0x1f25e1d63a2b46c5;
+ absl::int128 custom =
+ absl::MakeInt128(0x3a5b76c209de76f6, 0x1f25e1d63a2b46c5);
+
+ EXPECT_EQ(custom, absl::int128(intrinsic));
+ EXPECT_EQ(intrinsic, static_cast<__int128>(custom));
+}
+#endif // ABSL_HAVE_INTRINSIC_INT128
+
+TEST(Int128, ConstexprTest) {
+ constexpr absl::int128 zero = absl::int128();
+ constexpr absl::int128 one = 1;
+ constexpr absl::int128 minus_two = -2;
+ constexpr absl::int128 min = absl::Int128Min();
+ constexpr absl::int128 max = absl::Int128Max();
+ EXPECT_EQ(zero, absl::int128(0));
+ EXPECT_EQ(one, absl::int128(1));
+ EXPECT_EQ(minus_two, absl::MakeInt128(-1, -2));
+ EXPECT_GT(max, one);
+ EXPECT_LT(min, minus_two);
+}
+
+TEST(Int128, ComparisonTest) {
+ struct TestCase {
+ absl::int128 smaller;
+ absl::int128 larger;
+ };
+ TestCase cases[] = {
+ {absl::int128(0), absl::int128(123)},
+ {absl::MakeInt128(-12, 34), absl::MakeInt128(12, 34)},
+ {absl::MakeInt128(1, 1000), absl::MakeInt128(1000, 1)},
+ {absl::MakeInt128(-1000, 1000), absl::MakeInt128(-1, 1)},
+ };
+ for (const TestCase& pair : cases) {
+ SCOPED_TRACE(::testing::Message() << "pair.smaller = " << pair.smaller
+ << "; pair.larger = " << pair.larger);
+
+ EXPECT_TRUE(pair.smaller == pair.smaller); // NOLINT(readability/check)
+ EXPECT_TRUE(pair.larger == pair.larger); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.smaller == pair.larger); // NOLINT(readability/check)
+
+ EXPECT_TRUE(pair.smaller != pair.larger); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.smaller != pair.smaller); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.larger != pair.larger); // NOLINT(readability/check)
+
+ EXPECT_TRUE(pair.smaller < pair.larger); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.larger < pair.smaller); // NOLINT(readability/check)
+
+ EXPECT_TRUE(pair.larger > pair.smaller); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.smaller > pair.larger); // NOLINT(readability/check)
+
+ EXPECT_TRUE(pair.smaller <= pair.larger); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.larger <= pair.smaller); // NOLINT(readability/check)
+ EXPECT_TRUE(pair.smaller <= pair.smaller); // NOLINT(readability/check)
+ EXPECT_TRUE(pair.larger <= pair.larger); // NOLINT(readability/check)
+
+ EXPECT_TRUE(pair.larger >= pair.smaller); // NOLINT(readability/check)
+ EXPECT_FALSE(pair.smaller >= pair.larger); // NOLINT(readability/check)
+ EXPECT_TRUE(pair.smaller >= pair.smaller); // NOLINT(readability/check)
+ EXPECT_TRUE(pair.larger >= pair.larger); // NOLINT(readability/check)
+ }
+}
+
+TEST(Int128, UnaryNegationTest) {
+ int64_t values64[] = {0, 1, 12345, 0x4000000000000000,
+ std::numeric_limits<int64_t>::max()};
+ for (int64_t value : values64) {
+ SCOPED_TRACE(::testing::Message() << "value = " << value);
+
+ EXPECT_EQ(absl::int128(-value), -absl::int128(value));
+ EXPECT_EQ(absl::int128(value), -absl::int128(-value));
+ EXPECT_EQ(absl::MakeInt128(-value, 0), -absl::MakeInt128(value, 0));
+ EXPECT_EQ(absl::MakeInt128(value, 0), -absl::MakeInt128(-value, 0));
+ }
+}
+
+TEST(Int128, LogicalNotTest) {
+ EXPECT_TRUE(!absl::int128(0));
+ for (int i = 0; i < 64; ++i) {
+ EXPECT_FALSE(!absl::MakeInt128(0, uint64_t{1} << i));
+ }
+ for (int i = 0; i < 63; ++i) {
+ EXPECT_FALSE(!absl::MakeInt128(int64_t{1} << i, 0));
+ }
+}
+
+TEST(Int128, AdditionSubtractionTest) {
+ // 64 bit pairs that will not cause overflow / underflow. These test negative
+ // carry; positive carry must be checked separately.
+ std::pair<int64_t, int64_t> cases[]{
+ {0, 0}, // 0, 0
+ {0, 2945781290834}, // 0, +
+ {1908357619234, 0}, // +, 0
+ {0, -1204895918245}, // 0, -
+ {-2957928523560, 0}, // -, 0
+ {89023982312461, 98346012567134}, // +, +
+ {-63454234568239, -23456235230773}, // -, -
+ {98263457263502, -21428561935925}, // +, -
+ {-88235237438467, 15923659234573}, // -, +
+ };
+ for (const auto& pair : cases) {
+ SCOPED_TRACE(::testing::Message()
+ << "pair = {" << pair.first << ", " << pair.second << '}');
+
+ EXPECT_EQ(absl::int128(pair.first + pair.second),
+ absl::int128(pair.first) + absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.second + pair.first),
+ absl::int128(pair.second) += absl::int128(pair.first));
+
+ EXPECT_EQ(absl::int128(pair.first - pair.second),
+ absl::int128(pair.first) - absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.second - pair.first),
+ absl::int128(pair.second) -= absl::int128(pair.first));
+
+ EXPECT_EQ(
+ absl::MakeInt128(pair.second + pair.first, 0),
+ absl::MakeInt128(pair.second, 0) + absl::MakeInt128(pair.first, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first + pair.second, 0),
+ absl::MakeInt128(pair.first, 0) += absl::MakeInt128(pair.second, 0));
+
+ EXPECT_EQ(
+ absl::MakeInt128(pair.second - pair.first, 0),
+ absl::MakeInt128(pair.second, 0) - absl::MakeInt128(pair.first, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first - pair.second, 0),
+ absl::MakeInt128(pair.first, 0) -= absl::MakeInt128(pair.second, 0));
+ }
+
+ // check positive carry
+ EXPECT_EQ(absl::MakeInt128(31, 0),
+ absl::MakeInt128(20, 1) +
+ absl::MakeInt128(10, std::numeric_limits<uint64_t>::max()));
+}
+
+TEST(Int128, IncrementDecrementTest) {
+ absl::int128 value = 0;
+ EXPECT_EQ(0, value++);
+ EXPECT_EQ(1, value);
+ EXPECT_EQ(1, value--);
+ EXPECT_EQ(0, value);
+ EXPECT_EQ(-1, --value);
+ EXPECT_EQ(-1, value);
+ EXPECT_EQ(0, ++value);
+ EXPECT_EQ(0, value);
+}
+
+TEST(Int128, MultiplicationTest) {
+ // 1 bit x 1 bit, and negative combinations
+ for (int i = 0; i < 64; ++i) {
+ for (int j = 0; j < 127 - i; ++j) {
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ absl::int128 a = absl::int128(1) << i;
+ absl::int128 b = absl::int128(1) << j;
+ absl::int128 c = absl::int128(1) << (i + j);
+
+ EXPECT_EQ(c, a * b);
+ EXPECT_EQ(-c, -a * b);
+ EXPECT_EQ(-c, a * -b);
+ EXPECT_EQ(c, -a * -b);
+
+ EXPECT_EQ(c, absl::int128(a) *= b);
+ EXPECT_EQ(-c, absl::int128(-a) *= b);
+ EXPECT_EQ(-c, absl::int128(a) *= -b);
+ EXPECT_EQ(c, absl::int128(-a) *= -b);
+ }
+ }
+
+ // Pairs of random values that will not overflow signed 64-bit multiplication
+ std::pair<int64_t, int64_t> small_values[] = {
+ {0x5e61, 0xf29f79ca14b4}, // +, +
+ {0x3e033b, -0x612c0ee549}, // +, -
+ {-0x052ce7e8, 0x7c728f0f}, // -, +
+ {-0x3af7054626, -0xfb1e1d}, // -, -
+ };
+ for (const std::pair<int64_t, int64_t>& pair : small_values) {
+ SCOPED_TRACE(::testing::Message()
+ << "pair = {" << pair.first << ", " << pair.second << '}');
+
+ EXPECT_EQ(absl::int128(pair.first * pair.second),
+ absl::int128(pair.first) * absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.first * pair.second),
+ absl::int128(pair.first) *= absl::int128(pair.second));
+
+ EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),
+ absl::MakeInt128(pair.first, 0) * absl::int128(pair.second));
+ EXPECT_EQ(absl::MakeInt128(pair.first * pair.second, 0),
+ absl::MakeInt128(pair.first, 0) *= absl::int128(pair.second));
+ }
+
+ // Pairs of positive random values that will not overflow 64-bit
+ // multiplication and can be left shifted by 32 without overflow
+ std::pair<int64_t, int64_t> small_values2[] = {
+ {0x1bb0a110, 0x31487671},
+ {0x4792784e, 0x28add7d7},
+ {0x7b66553a, 0x11dff8ef},
+ };
+ for (const std::pair<int64_t, int64_t>& pair : small_values2) {
+ SCOPED_TRACE(::testing::Message()
+ << "pair = {" << pair.first << ", " << pair.second << '}');
+
+ absl::int128 a = absl::int128(pair.first << 32);
+ absl::int128 b = absl::int128(pair.second << 32);
+ absl::int128 c = absl::MakeInt128(pair.first * pair.second, 0);
+
+ EXPECT_EQ(c, a * b);
+ EXPECT_EQ(-c, -a * b);
+ EXPECT_EQ(-c, a * -b);
+ EXPECT_EQ(c, -a * -b);
+
+ EXPECT_EQ(c, absl::int128(a) *= b);
+ EXPECT_EQ(-c, absl::int128(-a) *= b);
+ EXPECT_EQ(-c, absl::int128(a) *= -b);
+ EXPECT_EQ(c, absl::int128(-a) *= -b);
+ }
+
+ // check 0, 1, and -1 behavior with large values
+ absl::int128 large_values[] = {
+ {absl::MakeInt128(0xd66f061af02d0408, 0x727d2846cb475b53)},
+ {absl::MakeInt128(0x27b8d5ed6104452d, 0x03f8a33b0ee1df4f)},
+ {-absl::MakeInt128(0x621b6626b9e8d042, 0x27311ac99df00938)},
+ {-absl::MakeInt128(0x34e0656f1e95fb60, 0x4281cfd731257a47)},
+ };
+ for (absl::int128 value : large_values) {
+ EXPECT_EQ(0, 0 * value);
+ EXPECT_EQ(0, value * 0);
+ EXPECT_EQ(0, absl::int128(0) *= value);
+ EXPECT_EQ(0, value *= 0);
+
+ EXPECT_EQ(value, 1 * value);
+ EXPECT_EQ(value, value * 1);
+ EXPECT_EQ(value, absl::int128(1) *= value);
+ EXPECT_EQ(value, value *= 1);
+
+ EXPECT_EQ(-value, -1 * value);
+ EXPECT_EQ(-value, value * -1);
+ EXPECT_EQ(-value, absl::int128(-1) *= value);
+ EXPECT_EQ(-value, value *= -1);
+ }
+
+ // Manually calculated random large value cases
+ EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),
+ absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) * 0x1a6037537b);
+ EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),
+ -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) * 0xe5a434cd14866e);
+ EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),
+ 0xa9b98a8ddf66bc * -absl::MakeInt128(0x81, 0x672e58231e2469d7));
+ EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),
+ -0x3e39341147 * -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));
+
+ EXPECT_EQ(absl::MakeInt128(0xcd0efd3442219bb, 0xde47c05bcd9df6e1),
+ absl::MakeInt128(0x7c6448, 0x3bc4285c47a9d253) *= 0x1a6037537b);
+ EXPECT_EQ(-absl::MakeInt128(0x1f8f149850b1e5e6, 0x1e50d6b52d272c3e),
+ -absl::MakeInt128(0x23, 0x2e68a513ca1b8859) *= 0xe5a434cd14866e);
+ EXPECT_EQ(-absl::MakeInt128(0x55cae732029d1fce, 0xca6474b6423263e4),
+ absl::int128(0xa9b98a8ddf66bc) *=
+ -absl::MakeInt128(0x81, 0x672e58231e2469d7));
+ EXPECT_EQ(absl::MakeInt128(0x19c8b7620b507dc4, 0xfec042b71a5f29a4),
+ absl::int128(-0x3e39341147) *=
+ -absl::MakeInt128(0x6a14b2, 0x5ed34cca42327b3c));
+}
+
+TEST(Int128, DivisionAndModuloTest) {
+ // Check against 64 bit division and modulo operators with a sample of
+ // randomly generated pairs.
+ std::pair<int64_t, int64_t> small_pairs[] = {
+ {0x15f2a64138, 0x67da05}, {0x5e56d194af43045f, 0xcf1543fb99},
+ {0x15e61ed052036a, -0xc8e6}, {0x88125a341e85, -0xd23fb77683},
+ {-0xc06e20, 0x5a}, {-0x4f100219aea3e85d, 0xdcc56cb4efe993},
+ {-0x168d629105, -0xa7}, {-0x7b44e92f03ab2375, -0x6516},
+ };
+ for (const std::pair<int64_t, int64_t>& pair : small_pairs) {
+ SCOPED_TRACE(::testing::Message()
+ << "pair = {" << pair.first << ", " << pair.second << '}');
+
+ absl::int128 dividend = pair.first;
+ absl::int128 divisor = pair.second;
+ int64_t quotient = pair.first / pair.second;
+ int64_t remainder = pair.first % pair.second;
+
+ EXPECT_EQ(quotient, dividend / divisor);
+ EXPECT_EQ(quotient, absl::int128(dividend) /= divisor);
+ EXPECT_EQ(remainder, dividend % divisor);
+ EXPECT_EQ(remainder, absl::int128(dividend) %= divisor);
+ }
+
+ // Test behavior with 0, 1, and -1 with a sample of randomly generated large
+ // values.
+ absl::int128 values[] = {
+ absl::MakeInt128(0x63d26ee688a962b2, 0x9e1411abda5c1d70),
+ absl::MakeInt128(0x152f385159d6f986, 0xbf8d48ef63da395d),
+ -absl::MakeInt128(0x3098d7567030038c, 0x14e7a8a098dc2164),
+ -absl::MakeInt128(0x49a037aca35c809f, 0xa6a87525480ef330),
+ };
+ for (absl::int128 value : values) {
+ SCOPED_TRACE(::testing::Message() << "value = " << value);
+
+ EXPECT_EQ(0, 0 / value);
+ EXPECT_EQ(0, absl::int128(0) /= value);
+ EXPECT_EQ(0, 0 % value);
+ EXPECT_EQ(0, absl::int128(0) %= value);
+
+ EXPECT_EQ(value, value / 1);
+ EXPECT_EQ(value, absl::int128(value) /= 1);
+ EXPECT_EQ(0, value % 1);
+ EXPECT_EQ(0, absl::int128(value) %= 1);
+
+ EXPECT_EQ(-value, value / -1);
+ EXPECT_EQ(-value, absl::int128(value) /= -1);
+ EXPECT_EQ(0, value % -1);
+ EXPECT_EQ(0, absl::int128(value) %= -1);
+ }
+
+ // Min and max values
+ EXPECT_EQ(0, absl::Int128Max() / absl::Int128Min());
+ EXPECT_EQ(absl::Int128Max(), absl::Int128Max() % absl::Int128Min());
+ EXPECT_EQ(-1, absl::Int128Min() / absl::Int128Max());
+ EXPECT_EQ(-1, absl::Int128Min() % absl::Int128Max());
+
+ // Power of two division and modulo of random large dividends
+ absl::int128 positive_values[] = {
+ absl::MakeInt128(0x21e1a1cc69574620, 0xe7ac447fab2fc869),
+ absl::MakeInt128(0x32c2ff3ab89e66e8, 0x03379a613fd1ce74),
+ absl::MakeInt128(0x6f32ca786184dcaf, 0x046f9c9ecb3a9ce1),
+ absl::MakeInt128(0x1aeb469dd990e0ee, 0xda2740f243cd37eb),
+ };
+ for (absl::int128 value : positive_values) {
+ for (int i = 0; i < 127; ++i) {
+ SCOPED_TRACE(::testing::Message()
+ << "value = " << value << "; i = " << i);
+ absl::int128 power_of_two = absl::int128(1) << i;
+
+ EXPECT_EQ(value >> i, value / power_of_two);
+ EXPECT_EQ(value >> i, absl::int128(value) /= power_of_two);
+ EXPECT_EQ(value & (power_of_two - 1), value % power_of_two);
+ EXPECT_EQ(value & (power_of_two - 1),
+ absl::int128(value) %= power_of_two);
+ }
+ }
+
+ // Manually calculated cases with random large dividends
+ struct DivisionModCase {
+ absl::int128 dividend;
+ absl::int128 divisor;
+ absl::int128 quotient;
+ absl::int128 remainder;
+ };
+ DivisionModCase manual_cases[] = {
+ {absl::MakeInt128(0x6ada48d489007966, 0x3c9c5c98150d5d69),
+ absl::MakeInt128(0x8bc308fb, 0x8cb9cc9a3b803344), 0xc3b87e08,
+ absl::MakeInt128(0x1b7db5e1, 0xd9eca34b7af04b49)},
+ {absl::MakeInt128(0xd6946511b5b, 0x4886c5c96546bf5f),
+ -absl::MakeInt128(0x263b, 0xfd516279efcfe2dc), -0x59cbabf0,
+ absl::MakeInt128(0x622, 0xf462909155651d1f)},
+ {-absl::MakeInt128(0x33db734f9e8d1399, 0x8447ac92482bca4d), 0x37495078240,
+ -absl::MakeInt128(0xf01f1, 0xbc0368bf9a77eae8), -0x21a508f404d},
+ {-absl::MakeInt128(0x13f837b409a07e7d, 0x7fc8e248a7d73560), -0x1b9f,
+ absl::MakeInt128(0xb9157556d724, 0xb14f635714d7563e), -0x1ade},
+ };
+ for (const DivisionModCase test_case : manual_cases) {
+ EXPECT_EQ(test_case.quotient, test_case.dividend / test_case.divisor);
+ EXPECT_EQ(test_case.quotient,
+ absl::int128(test_case.dividend) /= test_case.divisor);
+ EXPECT_EQ(test_case.remainder, test_case.dividend % test_case.divisor);
+ EXPECT_EQ(test_case.remainder,
+ absl::int128(test_case.dividend) %= test_case.divisor);
+ }
+}
+
+TEST(Int128, BitwiseLogicTest) {
+ EXPECT_EQ(absl::int128(-1), ~absl::int128(0));
+
+ absl::int128 values[]{
+ 0, -1, 0xde400bee05c3ff6b, absl::MakeInt128(0x7f32178dd81d634a, 0),
+ absl::MakeInt128(0xaf539057055613a9, 0x7d104d7d946c2e4d)};
+ for (absl::int128 value : values) {
+ EXPECT_EQ(value, ~~value);
+
+ EXPECT_EQ(value, value | value);
+ EXPECT_EQ(value, value & value);
+ EXPECT_EQ(0, value ^ value);
+
+ EXPECT_EQ(value, absl::int128(value) |= value);
+ EXPECT_EQ(value, absl::int128(value) &= value);
+ EXPECT_EQ(0, absl::int128(value) ^= value);
+
+ EXPECT_EQ(value, value | 0);
+ EXPECT_EQ(0, value & 0);
+ EXPECT_EQ(value, value ^ 0);
+
+ EXPECT_EQ(absl::int128(-1), value | absl::int128(-1));
+ EXPECT_EQ(value, value & absl::int128(-1));
+ EXPECT_EQ(~value, value ^ absl::int128(-1));
+ }
+
+ // small sample of randomly generated int64_t's
+ std::pair<int64_t, int64_t> pairs64[]{
+ {0x7f86797f5e991af4, 0x1ee30494fb007c97},
+ {0x0b278282bacf01af, 0x58780e0a57a49e86},
+ {0x059f266ccb93a666, 0x3d5b731bae9286f5},
+ {0x63c0c4820f12108c, 0x58166713c12e1c3a},
+ {0x381488bb2ed2a66e, 0x2220a3eb76a3698c},
+ {0x2a0a0dfb81e06f21, 0x4b60585927f5523c},
+ {0x555b1c3a03698537, 0x25478cd19d8e53cb},
+ {0x4750f6f27d779225, 0x16397553c6ff05fc},
+ };
+ for (const std::pair<int64_t, int64_t>& pair : pairs64) {
+ SCOPED_TRACE(::testing::Message()
+ << "pair = {" << pair.first << ", " << pair.second << '}');
+
+ EXPECT_EQ(absl::MakeInt128(~pair.first, ~pair.second),
+ ~absl::MakeInt128(pair.first, pair.second));
+
+ EXPECT_EQ(absl::int128(pair.first & pair.second),
+ absl::int128(pair.first) & absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.first | pair.second),
+ absl::int128(pair.first) | absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.first ^ pair.second),
+ absl::int128(pair.first) ^ absl::int128(pair.second));
+
+ EXPECT_EQ(absl::int128(pair.first & pair.second),
+ absl::int128(pair.first) &= absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.first | pair.second),
+ absl::int128(pair.first) |= absl::int128(pair.second));
+ EXPECT_EQ(absl::int128(pair.first ^ pair.second),
+ absl::int128(pair.first) ^= absl::int128(pair.second));
+
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first & pair.second, 0),
+ absl::MakeInt128(pair.first, 0) & absl::MakeInt128(pair.second, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first | pair.second, 0),
+ absl::MakeInt128(pair.first, 0) | absl::MakeInt128(pair.second, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first ^ pair.second, 0),
+ absl::MakeInt128(pair.first, 0) ^ absl::MakeInt128(pair.second, 0));
+
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first & pair.second, 0),
+ absl::MakeInt128(pair.first, 0) &= absl::MakeInt128(pair.second, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first | pair.second, 0),
+ absl::MakeInt128(pair.first, 0) |= absl::MakeInt128(pair.second, 0));
+ EXPECT_EQ(
+ absl::MakeInt128(pair.first ^ pair.second, 0),
+ absl::MakeInt128(pair.first, 0) ^= absl::MakeInt128(pair.second, 0));
+ }
+}
+
+TEST(Int128, BitwiseShiftTest) {
+ for (int i = 0; i < 64; ++i) {
+ for (int j = 0; j <= i; ++j) {
+ // Left shift from j-th bit to i-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) << (i - j));
+ EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) <<= (i - j));
+ }
+ }
+ for (int i = 0; i < 63; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ // Left shift from j-th bit to (i + 64)-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::int128(uint64_t{1} << j) << (i + 64 - j));
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::int128(uint64_t{1} << j) <<= (i + 64 - j));
+ }
+ for (int j = 0; j <= i; ++j) {
+ // Left shift from (j + 64)-th bit to (i + 64)-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::MakeInt128(uint64_t{1} << j, 0) << (i - j));
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::MakeInt128(uint64_t{1} << j, 0) <<= (i - j));
+ }
+ }
+
+ for (int i = 0; i < 64; ++i) {
+ for (int j = i; j < 64; ++j) {
+ // Right shift from j-th bit to i-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >> (j - i));
+ EXPECT_EQ(uint64_t{1} << i, absl::int128(uint64_t{1} << j) >>= (j - i));
+ }
+ for (int j = 0; j < 63; ++j) {
+ // Right shift from (j + 64)-th bit to i-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(uint64_t{1} << i,
+ absl::MakeInt128(uint64_t{1} << j, 0) >> (j + 64 - i));
+ EXPECT_EQ(uint64_t{1} << i,
+ absl::MakeInt128(uint64_t{1} << j, 0) >>= (j + 64 - i));
+ }
+ }
+ for (int i = 0; i < 63; ++i) {
+ for (int j = i; j < 63; ++j) {
+ // Right shift from (j + 64)-th bit to (i + 64)-th bit.
+ SCOPED_TRACE(::testing::Message() << "i = " << i << "; j = " << j);
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::MakeInt128(uint64_t{1} << j, 0) >> (j - i));
+ EXPECT_EQ(absl::MakeInt128(uint64_t{1} << i, 0),
+ absl::MakeInt128(uint64_t{1} << j, 0) >>= (j - i));
+ }
+ }
+}
+
+TEST(Int128, NumericLimitsTest) {
+ static_assert(std::numeric_limits<absl::int128>::is_specialized, "");
+ static_assert(std::numeric_limits<absl::int128>::is_signed, "");
+ static_assert(std::numeric_limits<absl::int128>::is_integer, "");
+ EXPECT_EQ(static_cast<int>(127 * std::log10(2)),
+ std::numeric_limits<absl::int128>::digits10);
+ EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::min());
+ EXPECT_EQ(absl::Int128Min(), std::numeric_limits<absl::int128>::lowest());
+ EXPECT_EQ(absl::Int128Max(), std::numeric_limits<absl::int128>::max());
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/bits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/bits.h
new file mode 100644
index 00000000000..bfef06bce1f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/bits.h
@@ -0,0 +1,358 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_NUMERIC_INTERNAL_BITS_H_
+#define ABSL_NUMERIC_INTERNAL_BITS_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+// Clang on Windows has __builtin_clzll; otherwise we need to use the
+// windows intrinsic functions.
+#if defined(_MSC_VER) && !defined(__clang__)
+#include <intrin.h>
+#endif
+
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+
+#if defined(__GNUC__) && !defined(__clang__)
+// GCC
+#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) 1
+#else
+#define ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(x) ABSL_HAVE_BUILTIN(x)
+#endif
+
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountl) && \
+ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
+#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_POPCOUNT
+#define ABSL_INTERNAL_HAS_CONSTEXPR_POPCOUNT 0
+#endif
+
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz) && \
+ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
+#define ABSL_INTERNAL_CONSTEXPR_CLZ constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_CLZ
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CLZ 0
+#endif
+
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz) && \
+ ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
+#define ABSL_INTERNAL_CONSTEXPR_CTZ constexpr
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 1
+#else
+#define ABSL_INTERNAL_CONSTEXPR_CTZ
+#define ABSL_INTERNAL_HAS_CONSTEXPR_CTZ 0
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace numeric_internal {
+
+constexpr bool IsPowerOf2(unsigned int x) noexcept {
+ return x != 0 && (x & (x - 1)) == 0;
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateRight(
+ T x, int s) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+
+ return static_cast<T>(x >> (s & (std::numeric_limits<T>::digits - 1))) |
+ static_cast<T>(x << ((-s) & (std::numeric_limits<T>::digits - 1)));
+}
+
+template <class T>
+ABSL_MUST_USE_RESULT ABSL_ATTRIBUTE_ALWAYS_INLINE constexpr T RotateLeft(
+ T x, int s) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+
+ return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) |
+ static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::digits - 1)));
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount32(uint32_t x) noexcept {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcount)
+ static_assert(sizeof(unsigned int) == sizeof(x),
+ "__builtin_popcount does not take 32-bit arg");
+ return __builtin_popcount(x);
+#else
+ x -= ((x >> 1) & 0x55555555);
+ x = ((x >> 2) & 0x33333333) + (x & 0x33333333);
+ return static_cast<int>((((x + (x >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount64(uint64_t x) noexcept {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_popcountll)
+ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
+ "__builtin_popcount does not take 64-bit arg");
+ return __builtin_popcountll(x);
+#else
+ x -= (x >> 1) & 0x5555555555555555ULL;
+ x = ((x >> 2) & 0x3333333333333333ULL) + (x & 0x3333333333333333ULL);
+ return static_cast<int>(
+ (((x + (x >> 4)) & 0xF0F0F0F0F0F0F0FULL) * 0x101010101010101ULL) >> 56);
+#endif
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_POPCOUNT inline int
+Popcount(T x) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+ static_assert(sizeof(x) <= sizeof(uint64_t), "T is too large");
+ return sizeof(x) <= sizeof(uint32_t) ? Popcount32(x) : Popcount64(x);
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes32(uint32_t x) {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clz)
+ // Use __builtin_clz, which uses the following instructions:
+ // x86: bsr, lzcnt
+ // ARM64: clz
+ // PPC: cntlzd
+
+ static_assert(sizeof(unsigned int) == sizeof(x),
+ "__builtin_clz does not take 32-bit arg");
+ // Handle 0 as a special case because __builtin_clz(0) is undefined.
+ return x == 0 ? 32 : __builtin_clz(x);
+#elif defined(_MSC_VER) && !defined(__clang__)
+ unsigned long result = 0; // NOLINT(runtime/int)
+ if (_BitScanReverse(&result, x)) {
+ return 31 - result;
+ }
+ return 32;
+#else
+ int zeroes = 28;
+ if (x >> 16) {
+ zeroes -= 16;
+ x >>= 16;
+ }
+ if (x >> 8) {
+ zeroes -= 8;
+ x >>= 8;
+ }
+ if (x >> 4) {
+ zeroes -= 4;
+ x >>= 4;
+ }
+ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes16(uint16_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_clzs)
+ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int)
+ "__builtin_clzs does not take 16-bit arg");
+ return x == 0 ? 16 : __builtin_clzs(x);
+#else
+ return CountLeadingZeroes32(x) - 16;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes64(uint64_t x) {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_clzll)
+ // Use __builtin_clzll, which uses the following instructions:
+ // x86: bsr, lzcnt
+ // ARM64: clz
+ // PPC: cntlzd
+ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
+ "__builtin_clzll does not take 64-bit arg");
+
+ // Handle 0 as a special case because __builtin_clzll(0) is undefined.
+ return x == 0 ? 64 : __builtin_clzll(x);
+#elif defined(_MSC_VER) && !defined(__clang__) && \
+ (defined(_M_X64) || defined(_M_ARM64))
+ // MSVC does not have __buitin_clzll. Use _BitScanReverse64.
+ unsigned long result = 0; // NOLINT(runtime/int)
+ if (_BitScanReverse64(&result, x)) {
+ return 63 - result;
+ }
+ return 64;
+#elif defined(_MSC_VER) && !defined(__clang__)
+ // MSVC does not have __buitin_clzll. Compose two calls to _BitScanReverse
+ unsigned long result = 0; // NOLINT(runtime/int)
+ if ((x >> 32) &&
+ _BitScanReverse(&result, static_cast<unsigned long>(x >> 32))) {
+ return 31 - result;
+ }
+ if (_BitScanReverse(&result, static_cast<unsigned long>(x))) {
+ return 63 - result;
+ }
+ return 64;
+#else
+ int zeroes = 60;
+ if (x >> 32) {
+ zeroes -= 32;
+ x >>= 32;
+ }
+ if (x >> 16) {
+ zeroes -= 16;
+ x >>= 16;
+ }
+ if (x >> 8) {
+ zeroes -= 8;
+ x >>= 8;
+ }
+ if (x >> 4) {
+ zeroes -= 4;
+ x >>= 4;
+ }
+ return "\4\3\2\2\1\1\1\1\0\0\0\0\0\0\0"[x] + zeroes;
+#endif
+}
+
+template <typename T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline int
+CountLeadingZeroes(T x) {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
+ return sizeof(T) <= sizeof(uint16_t)
+ ? CountLeadingZeroes16(static_cast<uint16_t>(x)) -
+ (std::numeric_limits<uint16_t>::digits -
+ std::numeric_limits<T>::digits)
+ : (sizeof(T) <= sizeof(uint32_t)
+ ? CountLeadingZeroes32(static_cast<uint32_t>(x)) -
+ (std::numeric_limits<uint32_t>::digits -
+ std::numeric_limits<T>::digits)
+ : CountLeadingZeroes64(x));
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero32(uint32_t x) {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctz)
+ static_assert(sizeof(unsigned int) == sizeof(x),
+ "__builtin_ctz does not take 32-bit arg");
+ return __builtin_ctz(x);
+#elif defined(_MSC_VER) && !defined(__clang__)
+ unsigned long result = 0; // NOLINT(runtime/int)
+ _BitScanForward(&result, x);
+ return result;
+#else
+ int c = 31;
+ x &= ~x + 1;
+ if (x & 0x0000FFFF) c -= 16;
+ if (x & 0x00FF00FF) c -= 8;
+ if (x & 0x0F0F0F0F) c -= 4;
+ if (x & 0x33333333) c -= 2;
+ if (x & 0x55555555) c -= 1;
+ return c;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero64(uint64_t x) {
+#if ABSL_NUMERIC_INTERNAL_HAVE_BUILTIN_OR_GCC(__builtin_ctzll)
+ static_assert(sizeof(unsigned long long) == sizeof(x), // NOLINT(runtime/int)
+ "__builtin_ctzll does not take 64-bit arg");
+ return __builtin_ctzll(x);
+#elif defined(_MSC_VER) && !defined(__clang__) && \
+ (defined(_M_X64) || defined(_M_ARM64))
+ unsigned long result = 0; // NOLINT(runtime/int)
+ _BitScanForward64(&result, x);
+ return result;
+#elif defined(_MSC_VER) && !defined(__clang__)
+ unsigned long result = 0; // NOLINT(runtime/int)
+ if (static_cast<uint32_t>(x) == 0) {
+ _BitScanForward(&result, static_cast<unsigned long>(x >> 32));
+ return result + 32;
+ }
+ _BitScanForward(&result, static_cast<unsigned long>(x));
+ return result;
+#else
+ int c = 63;
+ x &= ~x + 1;
+ if (x & 0x00000000FFFFFFFF) c -= 32;
+ if (x & 0x0000FFFF0000FFFF) c -= 16;
+ if (x & 0x00FF00FF00FF00FF) c -= 8;
+ if (x & 0x0F0F0F0F0F0F0F0F) c -= 4;
+ if (x & 0x3333333333333333) c -= 2;
+ if (x & 0x5555555555555555) c -= 1;
+ return c;
+#endif
+}
+
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroesNonzero16(uint16_t x) {
+#if ABSL_HAVE_BUILTIN(__builtin_ctzs)
+ static_assert(sizeof(unsigned short) == sizeof(x), // NOLINT(runtime/int)
+ "__builtin_ctzs does not take 16-bit arg");
+ return __builtin_ctzs(x);
+#else
+ return CountTrailingZeroesNonzero32(x);
+#endif
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CTZ inline int
+CountTrailingZeroes(T x) noexcept {
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
+ static_assert(IsPowerOf2(std::numeric_limits<T>::digits),
+ "T must have a power-of-2 size");
+ static_assert(sizeof(T) <= sizeof(uint64_t), "T too large");
+ return x == 0 ? std::numeric_limits<T>::digits
+ : (sizeof(T) <= sizeof(uint16_t)
+ ? CountTrailingZeroesNonzero16(static_cast<uint16_t>(x))
+ : (sizeof(T) <= sizeof(uint32_t)
+ ? CountTrailingZeroesNonzero32(
+ static_cast<uint32_t>(x))
+ : CountTrailingZeroesNonzero64(x)));
+}
+
+// If T is narrower than unsigned, T{1} << bit_width will be promoted. We
+// want to force it to wraparound so that bit_ceil of an invalid value are not
+// core constant expressions.
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ BitCeilPromotionHelper(T x, T promotion) {
+ return (T{1} << (x + promotion)) >> promotion;
+}
+
+template <class T>
+ABSL_ATTRIBUTE_ALWAYS_INLINE ABSL_INTERNAL_CONSTEXPR_CLZ inline
+ typename std::enable_if<std::is_unsigned<T>::value, T>::type
+ BitCeilNonPowerOf2(T x) {
+ // If T is narrower than unsigned, it undergoes promotion to unsigned when we
+ // shift. We calculate the number of bits added by the wider type.
+ return BitCeilPromotionHelper(
+ static_cast<T>(std::numeric_limits<T>::digits - CountLeadingZeroes(x)),
+ T{sizeof(T) >= sizeof(unsigned) ? 0
+ : std::numeric_limits<unsigned>::digits -
+ std::numeric_limits<T>::digits});
+}
+
+} // namespace numeric_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_NUMERIC_INTERNAL_BITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/representation.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/representation.h
new file mode 100644
index 00000000000..82d332fdde3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/numeric/internal/representation.h
@@ -0,0 +1,55 @@
+// 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_NUMERIC_INTERNAL_REPRESENTATION_H_
+#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_
+
+#include <limits>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace numeric_internal {
+
+// Returns true iff long double is represented as a pair of doubles added
+// together.
+inline constexpr bool IsDoubleDouble() {
+ // A double-double value always has exactly twice the precision of a double
+ // value--one double carries the high digits and one double carries the low
+ // digits. This property is not shared with any other common floating-point
+ // representation, so this test won't trigger false positives. For reference,
+ // this table gives the number of bits of precision of each common
+ // floating-point representation:
+ //
+ // type precision
+ // IEEE single 24 b
+ // IEEE double 53
+ // x86 long double 64
+ // double-double 106
+ // IEEE quadruple 113
+ //
+ // Note in particular that a quadruple-precision float has greater precision
+ // than a double-double float despite taking up the same amount of memory; the
+ // quad has more of its bits allocated to the mantissa than the double-double
+ // has.
+ return std::numeric_limits<long double>::digits ==
+ 2 * std::numeric_limits<double>::digits;
+}
+
+} // namespace numeric_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/BUILD.bazel
new file mode 100644
index 00000000000..66ffcbc7867
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/BUILD.bazel
@@ -0,0 +1,514 @@
+#
+# 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.
+#
+
+# ABSL random-number generation libraries.
+
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "random",
+ hdrs = ["random.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":seed_sequences",
+ "//absl/random/internal:nonsecure_base",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:pool_urbg",
+ "//absl/random/internal:randen_engine",
+ ],
+)
+
+cc_library(
+ name = "distributions",
+ srcs = [
+ "discrete_distribution.cc",
+ "gaussian_distribution.cc",
+ ],
+ hdrs = [
+ "bernoulli_distribution.h",
+ "beta_distribution.h",
+ "discrete_distribution.h",
+ "distributions.h",
+ "exponential_distribution.h",
+ "gaussian_distribution.h",
+ "log_uniform_int_distribution.h",
+ "poisson_distribution.h",
+ "uniform_int_distribution.h",
+ "uniform_real_distribution.h",
+ "zipf_distribution.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:base_internal",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ "//absl/numeric:bits",
+ "//absl/random/internal:distribution_caller",
+ "//absl/random/internal:fast_uniform_bits",
+ "//absl/random/internal:fastmath",
+ "//absl/random/internal:generate_real",
+ "//absl/random/internal:iostream_state_saver",
+ "//absl/random/internal:traits",
+ "//absl/random/internal:uniform_helper",
+ "//absl/random/internal:wide_multiply",
+ "//absl/strings",
+ ],
+)
+
+cc_library(
+ name = "seed_gen_exception",
+ srcs = ["seed_gen_exception.cc"],
+ hdrs = ["seed_gen_exception.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "seed_sequences",
+ srcs = ["seed_sequences.cc"],
+ hdrs = [
+ "seed_sequences.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":seed_gen_exception",
+ "//absl/container:inlined_vector",
+ "//absl/random/internal:nonsecure_base",
+ "//absl/random/internal:pool_urbg",
+ "//absl/random/internal:salted_seed_seq",
+ "//absl/random/internal:seed_material",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "bit_gen_ref",
+ hdrs = ["bit_gen_ref.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":random",
+ "//absl/base:core_headers",
+ "//absl/base:fast_type_id",
+ "//absl/meta:type_traits",
+ "//absl/random/internal:distribution_caller",
+ "//absl/random/internal:fast_uniform_bits",
+ ],
+)
+
+cc_library(
+ name = "mock_distributions",
+ testonly = 1,
+ hdrs = ["mock_distributions.h"],
+ deps = [
+ ":distributions",
+ ":mocking_bit_gen",
+ "//absl/meta:type_traits",
+ "//absl/random/internal:mock_overload_set",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_library(
+ name = "mocking_bit_gen",
+ testonly = 1,
+ hdrs = [
+ "mocking_bit_gen.h",
+ ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:fast_type_id",
+ "//absl/container:flat_hash_map",
+ "//absl/meta:type_traits",
+ "//absl/random/internal:distribution_caller",
+ "//absl/strings",
+ "//absl/types:span",
+ "//absl/types:variant",
+ "//absl/utility",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_test(
+ name = "bernoulli_distribution_test",
+ size = "small",
+ timeout = "eternal", # Android can take a very long time
+ srcs = ["bernoulli_distribution_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "beta_distribution_test",
+ size = "small",
+ timeout = "eternal", # Android can take a very long time
+ srcs = ["beta_distribution_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ flaky = 1,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/numeric:representation",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "distributions_test",
+ size = "small",
+ timeout = "moderate",
+ srcs = [
+ "distributions_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/random/internal:distribution_test_util",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "generators_test",
+ size = "small",
+ srcs = ["generators_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "log_uniform_int_distribution_test",
+ size = "medium",
+ srcs = [
+ "log_uniform_int_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "discrete_distribution_test",
+ size = "medium",
+ srcs = [
+ "discrete_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "poisson_distribution_test",
+ size = "small",
+ timeout = "eternal", # Android can take a very long time
+ srcs = [
+ "poisson_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ # Too Slow.
+ "no_test_android_arm",
+ "no_test_loonix",
+ ],
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/container:flat_hash_map",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "exponential_distribution_test",
+ size = "small",
+ srcs = ["exponential_distribution_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/numeric:representation",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "gaussian_distribution_test",
+ size = "small",
+ timeout = "eternal", # Android can take a very long time
+ srcs = [
+ "gaussian_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/numeric:representation",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "uniform_int_distribution_test",
+ size = "medium",
+ timeout = "long",
+ srcs = [
+ "uniform_int_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "uniform_real_distribution_test",
+ size = "medium",
+ srcs = [
+ "uniform_real_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "no_test_android_arm",
+ "no_test_android_arm64",
+ "no_test_android_x86",
+ ],
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/numeric:representation",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "zipf_distribution_test",
+ size = "medium",
+ srcs = [
+ "zipf_distribution_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distributions",
+ ":random",
+ "//absl/base:raw_logging_internal",
+ "//absl/random/internal:distribution_test_util",
+ "//absl/random/internal:pcg_engine",
+ "//absl/random/internal:sequence_urbg",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "bit_gen_ref_test",
+ size = "small",
+ srcs = ["bit_gen_ref_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":bit_gen_ref",
+ ":random",
+ "//absl/base:fast_type_id",
+ "//absl/random/internal:sequence_urbg",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "mocking_bit_gen_test",
+ size = "small",
+ srcs = ["mocking_bit_gen_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":bit_gen_ref",
+ ":mock_distributions",
+ ":mocking_bit_gen",
+ ":random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "mock_distributions_test",
+ size = "small",
+ srcs = ["mock_distributions_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":mock_distributions",
+ ":mocking_bit_gen",
+ ":random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "examples_test",
+ size = "small",
+ srcs = ["examples_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":random",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "seed_sequences_test",
+ size = "small",
+ srcs = ["seed_sequences_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":random",
+ ":seed_sequences",
+ "//absl/random/internal:nonsecure_base",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+BENCHMARK_TAGS = [
+ "benchmark",
+ "no_test_android_arm",
+ "no_test_android_arm64",
+ "no_test_android_x86",
+ "no_test_darwin_x86_64",
+ "no_test_ios_x86_64",
+ "no_test_loonix",
+ "no_test_msvc_x64",
+ "no_test_wasm",
+]
+
+# Benchmarks for various methods / test utilities
+cc_binary(
+ name = "benchmarks",
+ testonly = 1,
+ srcs = [
+ "benchmarks.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = BENCHMARK_TAGS,
+ deps = [
+ ":distributions",
+ ":random",
+ ":seed_sequences",
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ "//absl/random/internal:fast_uniform_bits",
+ "//absl/random/internal:randen_engine",
+ "@com_github_google_benchmark//:benchmark_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/benchmarks.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/benchmarks.cc
new file mode 100644
index 00000000000..87bbb9810a7
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/benchmarks.cc
@@ -0,0 +1,383 @@
+// 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.
+
+// Benchmarks for absl random distributions as well as a selection of the
+// C++ standard library random distributions.
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <initializer_list>
+#include <iterator>
+#include <limits>
+#include <random>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/macros.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/fast_uniform_bits.h"
+#include "absl/random/internal/randen_engine.h"
+#include "absl/random/log_uniform_int_distribution.h"
+#include "absl/random/poisson_distribution.h"
+#include "absl/random/random.h"
+#include "absl/random/uniform_int_distribution.h"
+#include "absl/random/uniform_real_distribution.h"
+#include "absl/random/zipf_distribution.h"
+#include "benchmark/benchmark.h"
+
+namespace {
+
+// Seed data to avoid reading random_device() for benchmarks.
+uint32_t kSeedData[] = {
+ 0x1B510052, 0x9A532915, 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+ 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915, 0xB6636521, 0xE7B9F9B6,
+ 0xFF34052E, 0xC5855664, 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A,
+ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623, 0xAD6EA6B0, 0x49A7DF7D,
+ 0x9CEE60B8, 0x8FEDB266, 0xECAA8C71, 0x699A18FF, 0x5664526C, 0xC2B19EE1,
+ 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E, 0x3F54989A, 0x5B429D65,
+ 0x6B8FE4D6, 0x99F73FD6, 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+ 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E, 0x09686B3F, 0x3EBAEFC9,
+ 0x3C971814, 0x6B6A70A1, 0x687F3584, 0x52A0E286, 0x13198A2E, 0x03707344,
+};
+
+// PrecompiledSeedSeq provides kSeedData to a conforming
+// random engine to speed initialization in the benchmarks.
+class PrecompiledSeedSeq {
+ public:
+ using result_type = uint32_t;
+
+ PrecompiledSeedSeq() {}
+
+ template <typename Iterator>
+ PrecompiledSeedSeq(Iterator begin, Iterator end) {}
+
+ template <typename T>
+ PrecompiledSeedSeq(std::initializer_list<T> il) {}
+
+ template <typename OutIterator>
+ void generate(OutIterator begin, OutIterator end) {
+ static size_t idx = 0;
+ for (; begin != end; begin++) {
+ *begin = kSeedData[idx++];
+ if (idx >= ABSL_ARRAYSIZE(kSeedData)) {
+ idx = 0;
+ }
+ }
+ }
+
+ size_t size() const { return ABSL_ARRAYSIZE(kSeedData); }
+
+ template <typename OutIterator>
+ void param(OutIterator out) const {
+ std::copy(std::begin(kSeedData), std::end(kSeedData), out);
+ }
+};
+
+// use_default_initialization<T> indicates whether the random engine
+// T must be default initialized, or whether we may initialize it using
+// a seed sequence. This is used because some engines do not accept seed
+// sequence-based initialization.
+template <typename E>
+using use_default_initialization = std::false_type;
+
+// make_engine<T, SSeq> returns a random_engine which is initialized,
+// either via the default constructor, when use_default_initialization<T>
+// is true, or via the indicated seed sequence, SSeq.
+template <typename Engine, typename SSeq = PrecompiledSeedSeq>
+typename absl::enable_if_t<!use_default_initialization<Engine>::value, Engine>
+make_engine() {
+ // Initialize the random engine using the seed sequence SSeq, which
+ // is constructed from the precompiled seed data.
+ SSeq seq(std::begin(kSeedData), std::end(kSeedData));
+ return Engine(seq);
+}
+
+template <typename Engine, typename SSeq = PrecompiledSeedSeq>
+typename absl::enable_if_t<use_default_initialization<Engine>::value, Engine>
+make_engine() {
+ // Initialize the random engine using the default constructor.
+ return Engine();
+}
+
+template <typename Engine, typename SSeq>
+void BM_Construct(benchmark::State& state) {
+ for (auto _ : state) {
+ auto rng = make_engine<Engine, SSeq>();
+ benchmark::DoNotOptimize(rng());
+ }
+}
+
+template <typename Engine>
+void BM_Direct(benchmark::State& state) {
+ using value_type = typename Engine::result_type;
+ // Direct use of the URBG.
+ auto rng = make_engine<Engine>();
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(rng());
+ }
+ state.SetBytesProcessed(sizeof(value_type) * state.iterations());
+}
+
+template <typename Engine>
+void BM_Generate(benchmark::State& state) {
+ // std::generate makes a copy of the RNG; thus this tests the
+ // copy-constructor efficiency.
+ using value_type = typename Engine::result_type;
+ std::vector<value_type> v(64);
+ auto rng = make_engine<Engine>();
+ while (state.KeepRunningBatch(64)) {
+ std::generate(std::begin(v), std::end(v), rng);
+ }
+}
+
+template <typename Engine, size_t elems>
+void BM_Shuffle(benchmark::State& state) {
+ // Direct use of the Engine.
+ std::vector<uint32_t> v(elems);
+ while (state.KeepRunningBatch(elems)) {
+ auto rng = make_engine<Engine>();
+ std::shuffle(std::begin(v), std::end(v), rng);
+ }
+}
+
+template <typename Engine, size_t elems>
+void BM_ShuffleReuse(benchmark::State& state) {
+ // Direct use of the Engine.
+ std::vector<uint32_t> v(elems);
+ auto rng = make_engine<Engine>();
+ while (state.KeepRunningBatch(elems)) {
+ std::shuffle(std::begin(v), std::end(v), rng);
+ }
+}
+
+template <typename Engine, typename Dist, typename... Args>
+void BM_Dist(benchmark::State& state, Args&&... args) {
+ using value_type = typename Dist::result_type;
+ auto rng = make_engine<Engine>();
+ Dist dis{std::forward<Args>(args)...};
+ // Compare the following loop performance:
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(dis(rng));
+ }
+ state.SetBytesProcessed(sizeof(value_type) * state.iterations());
+}
+
+template <typename Engine, typename Dist>
+void BM_Large(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ volatile value_type kMin = 0;
+ volatile value_type kMax = std::numeric_limits<value_type>::max() / 2 + 1;
+ BM_Dist<Engine, Dist>(state, kMin, kMax);
+}
+
+template <typename Engine, typename Dist>
+void BM_Small(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ volatile value_type kMin = 0;
+ volatile value_type kMax = std::numeric_limits<value_type>::max() / 64 + 1;
+ BM_Dist<Engine, Dist>(state, kMin, kMax);
+}
+
+template <typename Engine, typename Dist, int A>
+void BM_Bernoulli(benchmark::State& state) {
+ volatile double a = static_cast<double>(A) / 1000000;
+ BM_Dist<Engine, Dist>(state, a);
+}
+
+template <typename Engine, typename Dist, int A, int B>
+void BM_Beta(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ volatile value_type a = static_cast<value_type>(A) / 100;
+ volatile value_type b = static_cast<value_type>(B) / 100;
+ BM_Dist<Engine, Dist>(state, a, b);
+}
+
+template <typename Engine, typename Dist, int A>
+void BM_Gamma(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ volatile value_type a = static_cast<value_type>(A) / 100;
+ BM_Dist<Engine, Dist>(state, a);
+}
+
+template <typename Engine, typename Dist, int A = 100>
+void BM_Poisson(benchmark::State& state) {
+ volatile double a = static_cast<double>(A) / 100;
+ BM_Dist<Engine, Dist>(state, a);
+}
+
+template <typename Engine, typename Dist, int Q = 2, int V = 1>
+void BM_Zipf(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ volatile double q = Q;
+ volatile double v = V;
+ BM_Dist<Engine, Dist>(state, std::numeric_limits<value_type>::max(), q, v);
+}
+
+template <typename Engine, typename Dist>
+void BM_Thread(benchmark::State& state) {
+ using value_type = typename Dist::result_type;
+ auto rng = make_engine<Engine>();
+ Dist dis{};
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(dis(rng));
+ }
+ state.SetBytesProcessed(sizeof(value_type) * state.iterations());
+}
+
+// NOTES:
+//
+// std::geometric_distribution is similar to the zipf distributions.
+// The algorithm for the geometric_distribution is, basically,
+// floor(log(1-X) / log(1-p))
+
+// Normal benchmark suite
+#define BM_BASIC(Engine) \
+ BENCHMARK_TEMPLATE(BM_Construct, Engine, PrecompiledSeedSeq); \
+ BENCHMARK_TEMPLATE(BM_Construct, Engine, std::seed_seq); \
+ BENCHMARK_TEMPLATE(BM_Direct, Engine); \
+ BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 10); \
+ BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100); \
+ BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000); \
+ BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100); \
+ BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::random_internal::FastUniformBits<uint32_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::random_internal::FastUniformBits<uint64_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Large, Engine, \
+ std::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Large, Engine, \
+ std::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Large, Engine, \
+ absl::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Large, Engine, \
+ absl::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<float>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::uniform_real_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<float>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::uniform_real_distribution<double>)
+
+#define BM_COPY(Engine) BENCHMARK_TEMPLATE(BM_Generate, Engine)
+
+#define BM_THREAD(Engine) \
+ BENCHMARK_TEMPLATE(BM_Thread, Engine, \
+ absl::uniform_int_distribution<int64_t>) \
+ ->ThreadPerCpu(); \
+ BENCHMARK_TEMPLATE(BM_Thread, Engine, \
+ absl::uniform_real_distribution<double>) \
+ ->ThreadPerCpu(); \
+ BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 100)->ThreadPerCpu(); \
+ BENCHMARK_TEMPLATE(BM_Shuffle, Engine, 1000)->ThreadPerCpu(); \
+ BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 100)->ThreadPerCpu(); \
+ BENCHMARK_TEMPLATE(BM_ShuffleReuse, Engine, 1000)->ThreadPerCpu();
+
+#define BM_EXTENDED(Engine) \
+ /* -------------- Extended Uniform -----------------------*/ \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ std::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ std::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ absl::uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ absl::uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, std::uniform_real_distribution<float>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ std::uniform_real_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ absl::uniform_real_distribution<float>); \
+ BENCHMARK_TEMPLATE(BM_Small, Engine, \
+ absl::uniform_real_distribution<double>); \
+ /* -------------- Other -----------------------*/ \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::normal_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::gaussian_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::exponential_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, absl::exponential_distribution<double>); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \
+ 100); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \
+ 100); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \
+ 10 * 100); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \
+ 10 * 100); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, std::poisson_distribution<int64_t>, \
+ 13 * 100); \
+ BENCHMARK_TEMPLATE(BM_Poisson, Engine, absl::poisson_distribution<int64_t>, \
+ 13 * 100); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::log_uniform_int_distribution<int32_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, \
+ absl::log_uniform_int_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Dist, Engine, std::geometric_distribution<int64_t>); \
+ BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>); \
+ BENCHMARK_TEMPLATE(BM_Zipf, Engine, absl::zipf_distribution<uint64_t>, 2, \
+ 3); \
+ BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, std::bernoulli_distribution, \
+ 257305); \
+ BENCHMARK_TEMPLATE(BM_Bernoulli, Engine, absl::bernoulli_distribution, \
+ 257305); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 65, \
+ 41); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 99, \
+ 330); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 150, \
+ 150); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<double>, 410, \
+ 580); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 65, 41); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 99, \
+ 330); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 150, \
+ 150); \
+ BENCHMARK_TEMPLATE(BM_Beta, Engine, absl::beta_distribution<float>, 410, \
+ 580); \
+ BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<float>, 199); \
+ BENCHMARK_TEMPLATE(BM_Gamma, Engine, std::gamma_distribution<double>, 199);
+
+// ABSL Recommended interfaces.
+BM_BASIC(absl::InsecureBitGen); // === pcg64_2018_engine
+BM_BASIC(absl::BitGen); // === randen_engine<uint64_t>.
+BM_THREAD(absl::BitGen);
+BM_EXTENDED(absl::BitGen);
+
+// Instantiate benchmarks for multiple engines.
+using randen_engine_64 = absl::random_internal::randen_engine<uint64_t>;
+using randen_engine_32 = absl::random_internal::randen_engine<uint32_t>;
+
+// Comparison interfaces.
+BM_BASIC(std::mt19937_64);
+BM_COPY(std::mt19937_64);
+BM_EXTENDED(std::mt19937_64);
+BM_BASIC(randen_engine_64);
+BM_COPY(randen_engine_64);
+BM_EXTENDED(randen_engine_64);
+
+BM_BASIC(std::mt19937);
+BM_COPY(std::mt19937);
+BM_BASIC(randen_engine_32);
+BM_COPY(randen_engine_32);
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution.h
new file mode 100644
index 00000000000..25bd0d5ca42
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution.h
@@ -0,0 +1,200 @@
+// 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_BERNOULLI_DISTRIBUTION_H_
+#define ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
+
+#include <cstdint>
+#include <istream>
+#include <limits>
+
+#include "absl/base/optimization.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/iostream_state_saver.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::bernoulli_distribution is a drop in replacement for
+// std::bernoulli_distribution. It guarantees that (given a perfect
+// UniformRandomBitGenerator) the acceptance probability is *exactly* equal to
+// the given double.
+//
+// The implementation assumes that double is IEEE754
+class bernoulli_distribution {
+ public:
+ using result_type = bool;
+
+ class param_type {
+ public:
+ using distribution_type = bernoulli_distribution;
+
+ explicit param_type(double p = 0.5) : prob_(p) {
+ assert(p >= 0.0 && p <= 1.0);
+ }
+
+ double p() const { return prob_; }
+
+ friend bool operator==(const param_type& p1, const param_type& p2) {
+ return p1.p() == p2.p();
+ }
+ friend bool operator!=(const param_type& p1, const param_type& p2) {
+ return p1.p() != p2.p();
+ }
+
+ private:
+ double prob_;
+ };
+
+ bernoulli_distribution() : bernoulli_distribution(0.5) {}
+
+ explicit bernoulli_distribution(double p) : param_(p) {}
+
+ explicit bernoulli_distribution(param_type p) : param_(p) {}
+
+ // no-op
+ void reset() {}
+
+ template <typename URBG>
+ bool operator()(URBG& g) { // NOLINT(runtime/references)
+ return Generate(param_.p(), g);
+ }
+
+ template <typename URBG>
+ bool operator()(URBG& g, // NOLINT(runtime/references)
+ const param_type& param) {
+ return Generate(param.p(), g);
+ }
+
+ param_type param() const { return param_; }
+ void param(const param_type& param) { param_ = param; }
+
+ double p() const { return param_.p(); }
+
+ result_type(min)() const { return false; }
+ result_type(max)() const { return true; }
+
+ friend bool operator==(const bernoulli_distribution& d1,
+ const bernoulli_distribution& d2) {
+ return d1.param_ == d2.param_;
+ }
+
+ friend bool operator!=(const bernoulli_distribution& d1,
+ const bernoulli_distribution& d2) {
+ return d1.param_ != d2.param_;
+ }
+
+ private:
+ static constexpr uint64_t kP32 = static_cast<uint64_t>(1) << 32;
+
+ template <typename URBG>
+ static bool Generate(double p, URBG& g); // NOLINT(runtime/references)
+
+ param_type param_;
+};
+
+template <typename CharT, typename Traits>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const bernoulli_distribution& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<double>::kPrecision);
+ os << x.p();
+ return os;
+}
+
+template <typename CharT, typename Traits>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ bernoulli_distribution& x) { // NOLINT(runtime/references)
+ auto saver = random_internal::make_istream_state_saver(is);
+ auto p = random_internal::read_floating_point<double>(is);
+ if (!is.fail()) {
+ x.param(bernoulli_distribution::param_type(p));
+ }
+ return is;
+}
+
+template <typename URBG>
+bool bernoulli_distribution::Generate(double p,
+ URBG& g) { // NOLINT(runtime/references)
+ random_internal::FastUniformBits<uint32_t> fast_u32;
+
+ while (true) {
+ // There are two aspects of the definition of `c` below that are worth
+ // commenting on. First, because `p` is in the range [0, 1], `c` is in the
+ // range [0, 2^32] which does not fit in a uint32_t and therefore requires
+ // 64 bits.
+ //
+ // Second, `c` is constructed by first casting explicitly to a signed
+ // integer and then converting implicitly to an unsigned integer of the same
+ // size. This is done because the hardware conversion instructions produce
+ // signed integers from double; if taken as a uint64_t the conversion would
+ // be wrong for doubles greater than 2^63 (not relevant in this use-case).
+ // If converted directly to an unsigned integer, the compiler would end up
+ // emitting code to handle such large values that are not relevant due to
+ // the known bounds on `c`. To avoid these extra instructions this
+ // implementation converts first to the signed type and then use the
+ // implicit conversion to unsigned (which is a no-op).
+ const uint64_t c = static_cast<int64_t>(p * kP32);
+ const uint32_t v = fast_u32(g);
+ // FAST PATH: this path fails with probability 1/2^32. Note that simply
+ // returning v <= c would approximate P very well (up to an absolute error
+ // of 1/2^32); the slow path (taken in that range of possible error, in the
+ // case of equality) eliminates the remaining error.
+ if (ABSL_PREDICT_TRUE(v != c)) return v < c;
+
+ // It is guaranteed that `q` is strictly less than 1, because if `q` were
+ // greater than or equal to 1, the same would be true for `p`. Certainly `p`
+ // cannot be greater than 1, and if `p == 1`, then the fast path would
+ // necessary have been taken already.
+ const double q = static_cast<double>(c) / kP32;
+
+ // The probability of acceptance on the fast path is `q` and so the
+ // probability of acceptance here should be `p - q`.
+ //
+ // Note that `q` is obtained from `p` via some shifts and conversions, the
+ // upshot of which is that `q` is simply `p` with some of the
+ // least-significant bits of its mantissa set to zero. This means that the
+ // difference `p - q` will not have any rounding errors. To see why, pretend
+ // that double has 10 bits of resolution and q is obtained from `p` in such
+ // a way that the 4 least-significant bits of its mantissa are set to zero.
+ // For example:
+ // p = 1.1100111011 * 2^-1
+ // q = 1.1100110000 * 2^-1
+ // p - q = 1.011 * 2^-8
+ // The difference `p - q` has exactly the nonzero mantissa bits that were
+ // "lost" in `q` producing a number which is certainly representable in a
+ // double.
+ const double left = p - q;
+
+ // By construction, the probability of being on this slow path is 1/2^32, so
+ // P(accept in slow path) = P(accept| in slow path) * P(slow path),
+ // which means the probability of acceptance here is `1 / (left * kP32)`:
+ const double here = left * kP32;
+
+ // The simplest way to compute the result of this trial is to repeat the
+ // whole algorithm with the new probability. This terminates because even
+ // given arbitrarily unfriendly "random" bits, each iteration either
+ // multiplies a tiny probability by 2^32 (if c == 0) or strips off some
+ // number of nonzero mantissa bits. That process is bounded.
+ if (here == 0) return false;
+ p = here;
+ }
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_BERNOULLI_DISTRIBUTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution_test.cc
new file mode 100644
index 00000000000..b250f8787c6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bernoulli_distribution_test.cc
@@ -0,0 +1,217 @@
+// 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.
+
+#include "absl/random/bernoulli_distribution.h"
+
+#include <cmath>
+#include <cstddef>
+#include <random>
+#include <sstream>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+
+namespace {
+
+class BernoulliTest : public testing::TestWithParam<std::pair<double, size_t>> {
+};
+
+TEST_P(BernoulliTest, Serialize) {
+ const double d = GetParam().first;
+ absl::bernoulli_distribution before(d);
+
+ {
+ absl::bernoulli_distribution via_param{
+ absl::bernoulli_distribution::param_type(d)};
+ EXPECT_EQ(via_param, before);
+ }
+
+ std::stringstream ss;
+ ss << before;
+ absl::bernoulli_distribution after(0.6789);
+
+ EXPECT_NE(before.p(), after.p());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.p(), after.p());
+ EXPECT_EQ(before.param(), after.param());
+ EXPECT_EQ(before, after);
+}
+
+TEST_P(BernoulliTest, Accuracy) {
+ // Sadly, the claim to fame for this implementation is precise accuracy, which
+ // is very, very hard to measure, the improvements come as trials approach the
+ // limit of double accuracy; thus the outcome differs from the
+ // std::bernoulli_distribution with a probability of approximately 1 in 2^-53.
+ const std::pair<double, size_t> para = GetParam();
+ size_t trials = para.second;
+ double p = para.first;
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
+
+ size_t yes = 0;
+ absl::bernoulli_distribution dist(p);
+ for (size_t i = 0; i < trials; ++i) {
+ if (dist(rng)) yes++;
+ }
+
+ // Compute the distribution parameters for a binomial test, using a normal
+ // approximation for the confidence interval, as there are a sufficiently
+ // large number of trials that the central limit theorem applies.
+ const double stddev_p = std::sqrt((p * (1.0 - p)) / trials);
+ const double expected = trials * p;
+ const double stddev = trials * stddev_p;
+
+ // 5 sigma, approved by Richard Feynman
+ EXPECT_NEAR(yes, expected, 5 * stddev)
+ << "@" << p << ", "
+ << std::abs(static_cast<double>(yes) - expected) / stddev << " stddev";
+}
+
+// There must be many more trials to make the mean approximately normal for `p`
+// closes to 0 or 1.
+INSTANTIATE_TEST_SUITE_P(
+ All, BernoulliTest,
+ ::testing::Values(
+ // Typical values.
+ std::make_pair(0, 30000), std::make_pair(1e-3, 30000000),
+ std::make_pair(0.1, 3000000), std::make_pair(0.5, 3000000),
+ std::make_pair(0.9, 30000000), std::make_pair(0.999, 30000000),
+ std::make_pair(1, 30000),
+ // Boundary cases.
+ std::make_pair(std::nextafter(1.0, 0.0), 1), // ~1 - epsilon
+ std::make_pair(std::numeric_limits<double>::epsilon(), 1),
+ std::make_pair(std::nextafter(std::numeric_limits<double>::min(),
+ 1.0), // min + epsilon
+ 1),
+ std::make_pair(std::numeric_limits<double>::min(), // smallest normal
+ 1),
+ std::make_pair(
+ std::numeric_limits<double>::denorm_min(), // smallest denorm
+ 1),
+ std::make_pair(std::numeric_limits<double>::min() / 2, 1), // denorm
+ std::make_pair(std::nextafter(std::numeric_limits<double>::min(),
+ 0.0), // denorm_max
+ 1)));
+
+// NOTE: absl::bernoulli_distribution is not guaranteed to be stable.
+TEST(BernoulliTest, StabilityTest) {
+ // absl::bernoulli_distribution stability relies on FastUniformBits and
+ // integer arithmetic.
+ absl::random_internal::sequence_urbg urbg({
+ 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull,
+ 0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull,
+ 0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull,
+ 0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull,
+ 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full,
+ 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull,
+ 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull,
+ 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull,
+ 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull,
+ 0xe3fd722dc65ad09eull, 0x5a14fd21ea2a5705ull, 0x14e6ea4d6edb0c73ull,
+ 0x275b0dc7e0a18acfull, 0x36cebe0d2653682eull, 0x0361e9b23861596bull,
+ });
+
+ // Generate a string of '0' and '1' for the distribution output.
+ auto generate = [&urbg](absl::bernoulli_distribution& dist) {
+ std::string output;
+ output.reserve(36);
+ urbg.reset();
+ for (int i = 0; i < 35; i++) {
+ output.append(dist(urbg) ? "1" : "0");
+ }
+ return output;
+ };
+
+ const double kP = 0.0331289862362;
+ {
+ absl::bernoulli_distribution dist(kP);
+ auto v = generate(dist);
+ EXPECT_EQ(35, urbg.invocations());
+ EXPECT_EQ(v, "00000000000010000000000010000000000") << dist;
+ }
+ {
+ absl::bernoulli_distribution dist(kP * 10.0);
+ auto v = generate(dist);
+ EXPECT_EQ(35, urbg.invocations());
+ EXPECT_EQ(v, "00000100010010010010000011000011010") << dist;
+ }
+ {
+ absl::bernoulli_distribution dist(kP * 20.0);
+ auto v = generate(dist);
+ EXPECT_EQ(35, urbg.invocations());
+ EXPECT_EQ(v, "00011110010110110011011111110111011") << dist;
+ }
+ {
+ absl::bernoulli_distribution dist(1.0 - kP);
+ auto v = generate(dist);
+ EXPECT_EQ(35, urbg.invocations());
+ EXPECT_EQ(v, "11111111111111111111011111111111111") << dist;
+ }
+}
+
+TEST(BernoulliTest, StabilityTest2) {
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ // Generate a string of '0' and '1' for the distribution output.
+ auto generate = [&urbg](absl::bernoulli_distribution& dist) {
+ std::string output;
+ output.reserve(13);
+ urbg.reset();
+ for (int i = 0; i < 12; i++) {
+ output.append(dist(urbg) ? "1" : "0");
+ }
+ return output;
+ };
+
+ constexpr double b0 = 1.0 / 13.0 / 0.2;
+ constexpr double b1 = 2.0 / 13.0 / 0.2;
+ constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1));
+ {
+ absl::bernoulli_distribution dist(b0);
+ auto v = generate(dist);
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_EQ(v, "000011100101") << dist;
+ }
+ {
+ absl::bernoulli_distribution dist(b1);
+ auto v = generate(dist);
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_EQ(v, "001111101101") << dist;
+ }
+ {
+ absl::bernoulli_distribution dist(b3);
+ auto v = generate(dist);
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_EQ(v, "001111101111") << dist;
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution.h
new file mode 100644
index 00000000000..c154066fb81
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution_test.cc
new file mode 100644
index 00000000000..44cdfdd0499
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/beta_distribution_test.cc
@@ -0,0 +1,601 @@
+// 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.
+
+#include "absl/random/beta_distribution.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <unordered_map>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/numeric/internal/representation.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+template <typename IntType>
+class BetaDistributionInterfaceTest : public ::testing::Test {};
+
+// double-double arithmetic is not supported well by either GCC or Clang; see
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,
+// https://bugs.llvm.org/show_bug.cgi?id=49131, and
+// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests
+// with double doubles until compiler support is better.
+using RealTypes =
+ std::conditional<absl::numeric_internal::IsDoubleDouble(),
+ ::testing::Types<float, double>,
+ ::testing::Types<float, double, long double>>::type;
+TYPED_TEST_CASE(BetaDistributionInterfaceTest, RealTypes);
+
+TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
+ // The threshold for whether std::exp(1/a) is finite.
+ const TypeParam kSmallA =
+ 1.0f / std::log((std::numeric_limits<TypeParam>::max)());
+ // The threshold for whether a * std::log(a) is finite.
+ const TypeParam kLargeA =
+ std::exp(std::log((std::numeric_limits<TypeParam>::max)()) -
+ std::log(std::log((std::numeric_limits<TypeParam>::max)())));
+ using param_type = typename absl::beta_distribution<TypeParam>::param_type;
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ const TypeParam kValues[] = {
+ TypeParam(1e-20), TypeParam(1e-12), TypeParam(1e-8), TypeParam(1e-4),
+ TypeParam(1e-3), TypeParam(0.1), TypeParam(0.25),
+ std::nextafter(TypeParam(0.5), TypeParam(0)), // 0.5 - epsilon
+ std::nextafter(TypeParam(0.5), TypeParam(1)), // 0.5 + epsilon
+ TypeParam(0.5), TypeParam(1.0), //
+ std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon
+ std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon
+ TypeParam(12.5), TypeParam(1e2), TypeParam(1e8), TypeParam(1e12),
+ TypeParam(1e20), //
+ kSmallA, //
+ std::nextafter(kSmallA, TypeParam(0)), //
+ std::nextafter(kSmallA, TypeParam(1)), //
+ kLargeA, //
+ std::nextafter(kLargeA, TypeParam(0)), //
+ std::nextafter(kLargeA, std::numeric_limits<TypeParam>::max()),
+ // Boundary cases.
+ std::numeric_limits<TypeParam>::max(),
+ std::numeric_limits<TypeParam>::epsilon(),
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(1)), // min + epsilon
+ std::numeric_limits<TypeParam>::min(), // smallest normal
+ std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm
+ std::numeric_limits<TypeParam>::min() / 2, // denorm
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(0)), // denorm_max
+ };
+ for (TypeParam alpha : kValues) {
+ for (TypeParam beta : kValues) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("Smoke test for Beta(%a, %a)", alpha, beta));
+
+ param_type param(alpha, beta);
+ absl::beta_distribution<TypeParam> before(alpha, beta);
+ EXPECT_EQ(before.alpha(), param.alpha());
+ EXPECT_EQ(before.beta(), param.beta());
+
+ {
+ absl::beta_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ EXPECT_EQ(via_param.param(), before.param());
+ }
+
+ // Smoke test.
+ for (int i = 0; i < kCount; ++i) {
+ auto sample = before(gen);
+ EXPECT_TRUE(std::isfinite(sample));
+ EXPECT_GE(sample, before.min());
+ EXPECT_LE(sample, before.max());
+ }
+
+ // Validate stream serialization.
+ std::stringstream ss;
+ ss << before;
+ absl::beta_distribution<TypeParam> after(3.8f, 1.43f);
+ EXPECT_NE(before.alpha(), after.alpha());
+ EXPECT_NE(before.beta(), after.beta());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.alpha(), after.alpha());
+ EXPECT_EQ(before.beta(), after.beta());
+ EXPECT_EQ(before, after) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+ }
+ }
+}
+
+TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
+
+ // Extreme cases when the params are abnormal.
+ constexpr int kCount = 1000;
+ const TypeParam kSmallValues[] = {
+ std::numeric_limits<TypeParam>::min(),
+ std::numeric_limits<TypeParam>::denorm_min(),
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(0)), // denorm_max
+ std::numeric_limits<TypeParam>::epsilon(),
+ };
+ const TypeParam kLargeValues[] = {
+ std::numeric_limits<TypeParam>::max() * static_cast<TypeParam>(0.9999),
+ std::numeric_limits<TypeParam>::max() - 1,
+ std::numeric_limits<TypeParam>::max(),
+ };
+ {
+ // Small alpha and beta.
+ // Useful WolframAlpha plots:
+ // * plot InverseBetaRegularized[x, 0.0001, 0.0001] from 0.495 to 0.505
+ // * Beta[1.0, 0.0000001, 0.0000001]
+ // * Beta[0.9999, 0.0000001, 0.0000001]
+ for (TypeParam alpha : kSmallValues) {
+ for (TypeParam beta : kSmallValues) {
+ int zeros = 0;
+ int ones = 0;
+ absl::beta_distribution<TypeParam> d(alpha, beta);
+ for (int i = 0; i < kCount; ++i) {
+ TypeParam x = d(rng);
+ if (x == 0.0) {
+ zeros++;
+ } else if (x == 1.0) {
+ ones++;
+ }
+ }
+ EXPECT_EQ(ones + zeros, kCount);
+ if (alpha == beta) {
+ EXPECT_NE(ones, 0);
+ EXPECT_NE(zeros, 0);
+ }
+ }
+ }
+ }
+ {
+ // Small alpha, large beta.
+ // Useful WolframAlpha plots:
+ // * plot InverseBetaRegularized[x, 0.0001, 10000] from 0.995 to 1
+ // * Beta[0, 0.0000001, 1000000]
+ // * Beta[0.001, 0.0000001, 1000000]
+ // * Beta[1, 0.0000001, 1000000]
+ for (TypeParam alpha : kSmallValues) {
+ for (TypeParam beta : kLargeValues) {
+ absl::beta_distribution<TypeParam> d(alpha, beta);
+ for (int i = 0; i < kCount; ++i) {
+ EXPECT_EQ(d(rng), 0.0);
+ }
+ }
+ }
+ }
+ {
+ // Large alpha, small beta.
+ // Useful WolframAlpha plots:
+ // * plot InverseBetaRegularized[x, 10000, 0.0001] from 0 to 0.001
+ // * Beta[0.99, 1000000, 0.0000001]
+ // * Beta[1, 1000000, 0.0000001]
+ for (TypeParam alpha : kLargeValues) {
+ for (TypeParam beta : kSmallValues) {
+ absl::beta_distribution<TypeParam> d(alpha, beta);
+ for (int i = 0; i < kCount; ++i) {
+ EXPECT_EQ(d(rng), 1.0);
+ }
+ }
+ }
+ }
+ {
+ // Large alpha and beta.
+ absl::beta_distribution<TypeParam> d(std::numeric_limits<TypeParam>::max(),
+ std::numeric_limits<TypeParam>::max());
+ for (int i = 0; i < kCount; ++i) {
+ EXPECT_EQ(d(rng), 0.5);
+ }
+ }
+ {
+ // Large alpha and beta but unequal.
+ absl::beta_distribution<TypeParam> d(
+ std::numeric_limits<TypeParam>::max(),
+ std::numeric_limits<TypeParam>::max() * 0.9999);
+ for (int i = 0; i < kCount; ++i) {
+ TypeParam x = d(rng);
+ EXPECT_NE(x, 0.5f);
+ EXPECT_FLOAT_EQ(x, 0.500025f);
+ }
+ }
+}
+
+class BetaDistributionModel {
+ public:
+ explicit BetaDistributionModel(::testing::tuple<double, double> p)
+ : alpha_(::testing::get<0>(p)), beta_(::testing::get<1>(p)) {}
+
+ double Mean() const { return alpha_ / (alpha_ + beta_); }
+
+ double Variance() const {
+ return alpha_ * beta_ / (alpha_ + beta_ + 1) / (alpha_ + beta_) /
+ (alpha_ + beta_);
+ }
+
+ double Kurtosis() const {
+ return 3 + 6 *
+ ((alpha_ - beta_) * (alpha_ - beta_) * (alpha_ + beta_ + 1) -
+ alpha_ * beta_ * (2 + alpha_ + beta_)) /
+ alpha_ / beta_ / (alpha_ + beta_ + 2) / (alpha_ + beta_ + 3);
+ }
+
+ protected:
+ const double alpha_;
+ const double beta_;
+};
+
+class BetaDistributionTest
+ : public ::testing::TestWithParam<::testing::tuple<double, double>>,
+ public BetaDistributionModel {
+ public:
+ BetaDistributionTest() : BetaDistributionModel(GetParam()) {}
+
+ protected:
+ template <class D>
+ bool SingleZTestOnMeanAndVariance(double p, size_t samples);
+
+ template <class D>
+ bool SingleChiSquaredTest(double p, size_t samples, size_t buckets);
+
+ absl::InsecureBitGen rng_;
+};
+
+template <class D>
+bool BetaDistributionTest::SingleZTestOnMeanAndVariance(double p,
+ size_t samples) {
+ D dis(alpha_, beta_);
+
+ std::vector<double> data;
+ data.reserve(samples);
+ for (size_t i = 0; i < samples; i++) {
+ const double variate = dis(rng_);
+ EXPECT_FALSE(std::isnan(variate));
+ // Note that equality is allowed on both sides.
+ EXPECT_GE(variate, 0.0);
+ EXPECT_LE(variate, 1.0);
+ data.push_back(variate);
+ }
+
+ // We validate that the sample mean and sample variance are indeed from a
+ // Beta distribution with the given shape parameters.
+ const auto m = absl::random_internal::ComputeDistributionMoments(data);
+
+ // The variance of the sample mean is variance / n.
+ const double mean_stddev = std::sqrt(Variance() / static_cast<double>(m.n));
+
+ // The variance of the sample variance is (approximately):
+ // (kurtosis - 1) * variance^2 / n
+ const double variance_stddev = std::sqrt(
+ (Kurtosis() - 1) * Variance() * Variance() / static_cast<double>(m.n));
+ // z score for the sample variance.
+ const double z_variance = (m.variance - Variance()) / variance_stddev;
+
+ const double max_err = absl::random_internal::MaxErrorTolerance(p);
+ const double z_mean = absl::random_internal::ZScore(Mean(), m);
+ const bool pass =
+ absl::random_internal::Near("z", z_mean, 0.0, max_err) &&
+ absl::random_internal::Near("z_variance", z_variance, 0.0, max_err);
+ if (!pass) {
+ ABSL_INTERNAL_LOG(
+ INFO,
+ absl::StrFormat(
+ "Beta(%f, %f), "
+ "mean: sample %f, expect %f, which is %f stddevs away, "
+ "variance: sample %f, expect %f, which is %f stddevs away.",
+ alpha_, beta_, m.mean, Mean(),
+ std::abs(m.mean - Mean()) / mean_stddev, m.variance, Variance(),
+ std::abs(m.variance - Variance()) / variance_stddev));
+ }
+ return pass;
+}
+
+template <class D>
+bool BetaDistributionTest::SingleChiSquaredTest(double p, size_t samples,
+ size_t buckets) {
+ constexpr double kErr = 1e-7;
+ std::vector<double> cutoffs, expected;
+ const double bucket_width = 1.0 / static_cast<double>(buckets);
+ int i = 1;
+ int unmerged_buckets = 0;
+ for (; i < buckets; ++i) {
+ const double p = bucket_width * static_cast<double>(i);
+ const double boundary =
+ absl::random_internal::BetaIncompleteInv(alpha_, beta_, p);
+ // The intention is to add `boundary` to the list of `cutoffs`. It becomes
+ // problematic, however, when the boundary values are not monotone, due to
+ // numerical issues when computing the inverse regularized incomplete
+ // Beta function. In these cases, we merge that bucket with its previous
+ // neighbor and merge their expected counts.
+ if ((cutoffs.empty() && boundary < kErr) ||
+ (!cutoffs.empty() && boundary <= cutoffs.back())) {
+ unmerged_buckets++;
+ continue;
+ }
+ if (boundary >= 1.0 - 1e-10) {
+ break;
+ }
+ cutoffs.push_back(boundary);
+ expected.push_back(static_cast<double>(1 + unmerged_buckets) *
+ bucket_width * static_cast<double>(samples));
+ unmerged_buckets = 0;
+ }
+ cutoffs.push_back(std::numeric_limits<double>::infinity());
+ // Merge all remaining buckets.
+ expected.push_back(static_cast<double>(buckets - i + 1) * bucket_width *
+ static_cast<double>(samples));
+ // Make sure that we don't merge all the buckets, making this test
+ // meaningless.
+ EXPECT_GE(cutoffs.size(), 3) << alpha_ << ", " << beta_;
+
+ D dis(alpha_, beta_);
+
+ std::vector<int32_t> counts(cutoffs.size(), 0);
+ for (int i = 0; i < samples; i++) {
+ const double x = dis(rng_);
+ auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);
+ counts[std::distance(cutoffs.begin(), it)]++;
+ }
+
+ // Null-hypothesis is that the distribution is beta distributed with the
+ // provided alpha, beta params (not estimated from the data).
+ const int dof = cutoffs.size() - 1;
+
+ const double chi_square = absl::random_internal::ChiSquare(
+ counts.begin(), counts.end(), expected.begin(), expected.end());
+ const bool pass =
+ (absl::random_internal::ChiSquarePValue(chi_square, dof) >= p);
+ if (!pass) {
+ for (int i = 0; i < cutoffs.size(); i++) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("cutoff[%d] = %f, actual count %d, expected %d",
+ i, cutoffs[i], counts[i],
+ static_cast<int>(expected[i])));
+ }
+
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat(
+ "Beta(%f, %f) %s %f, p = %f", alpha_, beta_,
+ absl::random_internal::kChiSquared, chi_square,
+ absl::random_internal::ChiSquarePValue(chi_square, dof)));
+ }
+ return pass;
+}
+
+TEST_P(BetaDistributionTest, TestSampleStatistics) {
+ static constexpr int kRuns = 20;
+ static constexpr double kPFail = 0.02;
+ const double p =
+ absl::random_internal::RequiredSuccessProbability(kPFail, kRuns);
+ static constexpr int kSampleCount = 10000;
+ static constexpr int kBucketCount = 100;
+ int failed = 0;
+ for (int i = 0; i < kRuns; ++i) {
+ if (!SingleZTestOnMeanAndVariance<absl::beta_distribution<double>>(
+ p, kSampleCount)) {
+ failed++;
+ }
+ if (!SingleChiSquaredTest<absl::beta_distribution<double>>(
+ 0.005, kSampleCount, kBucketCount)) {
+ failed++;
+ }
+ }
+ // Set so that the test is not flaky at --runs_per_test=10000
+ EXPECT_LE(failed, 5);
+}
+
+std::string ParamName(
+ const ::testing::TestParamInfo<::testing::tuple<double, double>>& info) {
+ std::string name = absl::StrCat("alpha_", ::testing::get<0>(info.param),
+ "__beta_", ::testing::get<1>(info.param));
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_CASE_P(
+ TestSampleStatisticsCombinations, BetaDistributionTest,
+ ::testing::Combine(::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4),
+ ::testing::Values(0.1, 0.2, 0.9, 1.1, 2.5, 10.0, 123.4)),
+ ParamName);
+
+INSTANTIATE_TEST_CASE_P(
+ TestSampleStatistics_SelectedPairs, BetaDistributionTest,
+ ::testing::Values(std::make_pair(0.5, 1000), std::make_pair(1000, 0.5),
+ std::make_pair(900, 1000), std::make_pair(10000, 20000),
+ std::make_pair(4e5, 2e7), std::make_pair(1e7, 1e5)),
+ ParamName);
+
+// NOTE: absl::beta_distribution is not guaranteed to be stable.
+TEST(BetaDistributionTest, StabilityTest) {
+ // absl::beta_distribution stability relies on the stability of
+ // absl::random_interna::RandU64ToDouble, std::exp, std::log, std::pow,
+ // and std::sqrt.
+ //
+ // This test also depends on the stability of std::frexp.
+ using testing::ElementsAre;
+ absl::random_internal::sequence_urbg urbg({
+ 0xffff00000000e6c8ull, 0xffff0000000006c8ull, 0x800003766295CFA9ull,
+ 0x11C819684E734A41ull, 0x832603766295CFA9ull, 0x7fbe76c8b4395800ull,
+ 0xB3472DCA7B14A94Aull, 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull,
+ 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull, 0x00035C904C70A239ull,
+ 0x00009E0BCBAADE14ull, 0x0000000000622CA7ull, 0x4864f22c059bf29eull,
+ 0x247856d8b862665cull, 0xe46e86e9a1337e10ull, 0xd8c8541f3519b133ull,
+ 0xffe75b52c567b9e4ull, 0xfffff732e5709c5bull, 0xff1f7f0b983532acull,
+ 0x1ec2e8986d2362caull, 0xC332DDEFBE6C5AA5ull, 0x6558218568AB9702ull,
+ 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull, 0xECDD4775619F1510ull,
+ 0x814c8e35fe9a961aull, 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull,
+ 0x1224e62c978bbc7full, 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull,
+ 0x1bbc23cfa8fac721ull, 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull,
+ 0x836d794457c08849ull, 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull,
+ 0xb12d74fdd718c8c5ull, 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull,
+ 0x5738341045ba0d85ull, 0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull,
+ 0xffe6ea4d6edb0c73ull, 0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull,
+ 0xEAAD8E716B93D5A0ull, 0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull,
+ 0x8FF6E2FBF2122B64ull, 0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull,
+ 0xD1CFF191B3A8C1ADull, 0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull,
+ });
+
+ // Convert the real-valued result into a unit64 where we compare
+ // 5 (float) or 10 (double) decimal digits plus the base-2 exponent.
+ auto float_to_u64 = [](float d) {
+ int exp = 0;
+ auto f = std::frexp(d, &exp);
+ return (static_cast<uint64_t>(1e5 * f) * 10000) + std::abs(exp);
+ };
+ auto double_to_u64 = [](double d) {
+ int exp = 0;
+ auto f = std::frexp(d, &exp);
+ return (static_cast<uint64_t>(1e10 * f) * 10000) + std::abs(exp);
+ };
+
+ std::vector<uint64_t> output(20);
+ {
+ // Algorithm Joehnk (float)
+ absl::beta_distribution<float> dist(0.1f, 0.2f);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return float_to_u64(dist(urbg)); });
+ EXPECT_EQ(44, urbg.invocations());
+ EXPECT_THAT(output, //
+ testing::ElementsAre(
+ 998340000, 619030004, 500000001, 999990000, 996280000,
+ 500000001, 844740004, 847210001, 999970000, 872320000,
+ 585480007, 933280000, 869080042, 647670031, 528240004,
+ 969980004, 626050008, 915930002, 833440033, 878040015));
+ }
+
+ urbg.reset();
+ {
+ // Algorithm Joehnk (double)
+ absl::beta_distribution<double> dist(0.1, 0.2);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return double_to_u64(dist(urbg)); });
+ EXPECT_EQ(44, urbg.invocations());
+ EXPECT_THAT(
+ output, //
+ testing::ElementsAre(
+ 99834713000000, 61903356870004, 50000000000001, 99999721170000,
+ 99628374770000, 99999999990000, 84474397860004, 84721276240001,
+ 99997407490000, 87232528120000, 58548364780007, 93328932910000,
+ 86908237770042, 64767917930031, 52824581970004, 96998544140004,
+ 62605946270008, 91593604380002, 83345031740033, 87804397230015));
+ }
+
+ urbg.reset();
+ {
+ // Algorithm Cheng 1
+ absl::beta_distribution<double> dist(0.9, 2.0);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return double_to_u64(dist(urbg)); });
+ EXPECT_EQ(62, urbg.invocations());
+ EXPECT_THAT(
+ output, //
+ testing::ElementsAre(
+ 62069004780001, 64433204450001, 53607416560000, 89644295430008,
+ 61434586310019, 55172615890002, 62187161490000, 56433684810003,
+ 80454622050005, 86418558710003, 92920514700001, 64645184680001,
+ 58549183380000, 84881283650005, 71078728590002, 69949694970000,
+ 73157461710001, 68592191300001, 70747623900000, 78584696930005));
+ }
+
+ urbg.reset();
+ {
+ // Algorithm Cheng 2
+ absl::beta_distribution<double> dist(1.5, 2.5);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return double_to_u64(dist(urbg)); });
+ EXPECT_EQ(54, urbg.invocations());
+ EXPECT_THAT(
+ output, //
+ testing::ElementsAre(
+ 75000029250001, 76751482860001, 53264575220000, 69193133650005,
+ 78028324470013, 91573587560002, 59167523770000, 60658618560002,
+ 80075870540000, 94141320460004, 63196592770003, 78883906300002,
+ 96797992590001, 76907587800001, 56645167560000, 65408302280003,
+ 53401156320001, 64731238570000, 83065573750001, 79788333820001));
+ }
+}
+
+// This is an implementation-specific test. If any part of the implementation
+// changes, then it is likely that this test will change as well. Also, if
+// dependencies of the distribution change, such as RandU64ToDouble, then this
+// is also likely to change.
+TEST(BetaDistributionTest, AlgorithmBounds) {
+ {
+ absl::random_internal::sequence_urbg urbg(
+ {0x7fbe76c8b4395800ull, 0x8000000000000000ull});
+ // u=0.499, v=0.5
+ absl::beta_distribution<double> dist(1e-4, 1e-4);
+ double a = dist(urbg);
+ EXPECT_EQ(a, 2.0202860861567108529e-09);
+ EXPECT_EQ(2, urbg.invocations());
+ }
+
+ // Test that both the float & double algorithms appropriately reject the
+ // initial draw.
+ {
+ // 1/alpha = 1/beta = 2.
+ absl::beta_distribution<float> dist(0.5, 0.5);
+
+ // first two outputs are close to 1.0 - epsilon,
+ // thus: (u ^ 2 + v ^ 2) > 1.0
+ absl::random_internal::sequence_urbg urbg(
+ {0xffff00000006e6c8ull, 0xffff00000007c7c8ull, 0x800003766295CFA9ull,
+ 0x11C819684E734A41ull});
+ {
+ double y = absl::beta_distribution<double>(0.5, 0.5)(urbg);
+ EXPECT_EQ(4, urbg.invocations());
+ EXPECT_EQ(y, 0.9810668952633862) << y;
+ }
+
+ // ...and: log(u) * a ~= log(v) * b ~= -0.02
+ // thus z ~= -0.02 + log(1 + e(~0))
+ // ~= -0.02 + 0.69
+ // thus z > 0
+ urbg.reset();
+ {
+ float x = absl::beta_distribution<float>(0.5, 0.5)(urbg);
+ EXPECT_EQ(4, urbg.invocations());
+ EXPECT_NEAR(0.98106688261032104, x, 0.0000005) << x << "f";
+ }
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref.h
new file mode 100644
index 00000000000..9555460fd49
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref.h
@@ -0,0 +1,181 @@
+//
+// 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 "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 URBG, typename absl::enable_if_t<
+ (!std::is_same<URBG, BitGenRef>::value &&
+ random_internal::is_urbg<URBG>::value &&
+ !HasInvokeMock<URBG>::value)>* = nullptr>
+ BitGenRef(URBG& gen) // NOLINT
+ : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+ mock_call_(NotAMock),
+ generate_impl_fn_(ImplFn<URBG>) {}
+
+ template <typename URBG,
+ typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
+ random_internal::is_urbg<URBG>::value &&
+ HasInvokeMock<URBG>::value)>* = nullptr>
+ BitGenRef(URBG& gen) // 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref_test.cc
new file mode 100644
index 00000000000..1135cf2da0b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/bit_gen_ref_test.cc
@@ -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.
+//
+#include "absl/random/bit_gen_ref.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class ConstBitGen {
+ public:
+ // 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 1; }
+
+ // InvokeMock method
+ bool InvokeMock(base_internal::FastTypeIdType index, void*, void* result) {
+ *static_cast<int*>(result) = 42;
+ return true;
+ }
+};
+
+namespace {
+
+int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }
+
+template <typename T>
+class BitGenRefTest : public testing::Test {};
+
+using BitGenTypes =
+ ::testing::Types<absl::BitGen, absl::InsecureBitGen, std::mt19937,
+ std::mt19937_64, std::minstd_rand>;
+TYPED_TEST_SUITE(BitGenRefTest, BitGenTypes);
+
+TYPED_TEST(BitGenRefTest, BasicTest) {
+ TypeParam gen;
+ auto x = FnTest(gen);
+ EXPECT_NEAR(x, 4, 3);
+}
+
+TYPED_TEST(BitGenRefTest, Copyable) {
+ TypeParam gen;
+ absl::BitGenRef gen_ref(gen);
+ FnTest(gen_ref); // Copy
+}
+
+TEST(BitGenRefTest, PassThroughEquivalence) {
+ // sequence_urbg returns 64-bit results.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<uint64_t> output(12);
+
+ {
+ absl::BitGenRef view(urbg);
+ for (auto& v : output) {
+ v = view();
+ }
+ }
+
+ std::vector<uint64_t> expected(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ EXPECT_THAT(output, testing::Eq(expected));
+}
+
+TEST(BitGenRefTest, MockingBitGenBaseOverrides) {
+ ConstBitGen const_gen;
+ EXPECT_EQ(FnTest(const_gen), 42);
+
+ absl::BitGenRef gen_ref(const_gen);
+ EXPECT_EQ(FnTest(gen_ref), 42); // Copy
+}
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.cc
new file mode 100644
index 00000000000..081accee52a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.cc
@@ -0,0 +1,98 @@
+// 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.
+
+#include "absl/random/discrete_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Initializes the distribution table for Walker's Aliasing algorithm, described
+// in Knuth, Vol 2. as well as in https://en.wikipedia.org/wiki/Alias_method
+std::vector<std::pair<double, size_t>> InitDiscreteDistribution(
+ std::vector<double>* probabilities) {
+ // The empty-case should already be handled by the constructor.
+ assert(probabilities);
+ assert(!probabilities->empty());
+
+ // Step 1. Normalize the input probabilities to 1.0.
+ double sum = std::accumulate(std::begin(*probabilities),
+ std::end(*probabilities), 0.0);
+ if (std::fabs(sum - 1.0) > 1e-6) {
+ // Scale `probabilities` only when the sum is too far from 1.0. Scaling
+ // unconditionally will alter the probabilities slightly.
+ for (double& item : *probabilities) {
+ item = item / sum;
+ }
+ }
+
+ // Step 2. At this point `probabilities` is set to the conditional
+ // probabilities of each element which sum to 1.0, to within reasonable error.
+ // These values are used to construct the proportional probability tables for
+ // the selection phases of Walker's Aliasing algorithm.
+ //
+ // To construct the table, pick an element which is under-full (i.e., an
+ // element for which `(*probabilities)[i] < 1.0/n`), and pair it with an
+ // element which is over-full (i.e., an element for which
+ // `(*probabilities)[i] > 1.0/n`). The smaller value can always be retired.
+ // The larger may still be greater than 1.0/n, or may now be less than 1.0/n,
+ // and put back onto the appropriate collection.
+ const size_t n = probabilities->size();
+ std::vector<std::pair<double, size_t>> q;
+ q.reserve(n);
+
+ std::vector<size_t> over;
+ std::vector<size_t> under;
+ size_t idx = 0;
+ for (const double item : *probabilities) {
+ assert(item >= 0);
+ const double v = item * n;
+ q.emplace_back(v, 0);
+ if (v < 1.0) {
+ under.push_back(idx++);
+ } else {
+ over.push_back(idx++);
+ }
+ }
+ while (!over.empty() && !under.empty()) {
+ auto lo = under.back();
+ under.pop_back();
+ auto hi = over.back();
+ over.pop_back();
+
+ q[lo].second = hi;
+ const double r = q[hi].first - (1.0 - q[lo].first);
+ q[hi].first = r;
+ if (r < 1.0) {
+ under.push_back(hi);
+ } else {
+ over.push_back(hi);
+ }
+ }
+
+ // Due to rounding errors, there may be un-paired elements in either
+ // collection; these should all be values near 1.0. For these values, set `q`
+ // to 1.0 and set the alternate to the identity.
+ for (auto i : over) {
+ q[i] = {1.0, i};
+ }
+ for (auto i : under) {
+ q[i] = {1.0, i};
+ }
+ return q;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.h
new file mode 100644
index 00000000000..171aa11a1eb
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution.h
@@ -0,0 +1,247 @@
+// 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_DISCRETE_DISTRIBUTION_H_
+#define ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
+
+#include <cassert>
+#include <cmath>
+#include <istream>
+#include <limits>
+#include <numeric>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "absl/random/bernoulli_distribution.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/uniform_int_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::discrete_distribution
+//
+// A discrete distribution produces random integers i, where 0 <= i < n
+// distributed according to the discrete probability function:
+//
+// P(i|p0,...,pn−1)=pi
+//
+// This class is an implementation of discrete_distribution (see
+// [rand.dist.samp.discrete]).
+//
+// The algorithm used is Walker's Aliasing algorithm, described in Knuth, Vol 2.
+// absl::discrete_distribution takes O(N) time to precompute the probabilities
+// (where N is the number of possible outcomes in the distribution) at
+// construction, and then takes O(1) time for each variate generation. Many
+// other implementations also take O(N) time to construct an ordered sequence of
+// partial sums, plus O(log N) time per variate to binary search.
+//
+template <typename IntType = int>
+class discrete_distribution {
+ public:
+ using result_type = IntType;
+
+ class param_type {
+ public:
+ using distribution_type = discrete_distribution;
+
+ param_type() { init(); }
+
+ template <typename InputIterator>
+ explicit param_type(InputIterator begin, InputIterator end)
+ : p_(begin, end) {
+ init();
+ }
+
+ explicit param_type(std::initializer_list<double> weights) : p_(weights) {
+ init();
+ }
+
+ template <class UnaryOperation>
+ explicit param_type(size_t nw, double xmin, double xmax,
+ UnaryOperation fw) {
+ if (nw > 0) {
+ p_.reserve(nw);
+ double delta = (xmax - xmin) / static_cast<double>(nw);
+ assert(delta > 0);
+ double t = delta * 0.5;
+ for (size_t i = 0; i < nw; ++i) {
+ p_.push_back(fw(xmin + i * delta + t));
+ }
+ }
+ init();
+ }
+
+ const std::vector<double>& probabilities() const { return p_; }
+ size_t n() const { return p_.size() - 1; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.probabilities() == b.probabilities();
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class discrete_distribution;
+
+ void init();
+
+ std::vector<double> p_; // normalized probabilities
+ std::vector<std::pair<double, size_t>> q_; // (acceptance, alternate) pairs
+
+ static_assert(std::is_integral<result_type>::value,
+ "Class-template absl::discrete_distribution<> must be "
+ "parameterized using an integral type.");
+ };
+
+ discrete_distribution() : param_() {}
+
+ explicit discrete_distribution(const param_type& p) : param_(p) {}
+
+ template <typename InputIterator>
+ explicit discrete_distribution(InputIterator begin, InputIterator end)
+ : param_(begin, end) {}
+
+ explicit discrete_distribution(std::initializer_list<double> weights)
+ : param_(weights) {}
+
+ template <class UnaryOperation>
+ explicit discrete_distribution(size_t nw, double xmin, double xmax,
+ UnaryOperation fw)
+ : param_(nw, xmin, xmax, std::move(fw)) {}
+
+ 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);
+
+ const 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 static_cast<result_type>(param_.n());
+ } // inclusive
+
+ // NOTE [rand.dist.sample.discrete] returns a std::vector<double> not a
+ // const std::vector<double>&.
+ const std::vector<double>& probabilities() const {
+ return param_.probabilities();
+ }
+
+ friend bool operator==(const discrete_distribution& a,
+ const discrete_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const discrete_distribution& a,
+ const discrete_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+};
+
+// --------------------------------------------------------------------------
+// Implementation details only below
+// --------------------------------------------------------------------------
+
+namespace random_internal {
+
+// Using the vector `*probabilities`, whose values are the weights or
+// probabilities of an element being selected, constructs the proportional
+// probabilities used by the discrete distribution. `*probabilities` will be
+// scaled, if necessary, so that its entries sum to a value sufficiently close
+// to 1.0.
+std::vector<std::pair<double, size_t>> InitDiscreteDistribution(
+ std::vector<double>* probabilities);
+
+} // namespace random_internal
+
+template <typename IntType>
+void discrete_distribution<IntType>::param_type::init() {
+ if (p_.empty()) {
+ p_.push_back(1.0);
+ q_.emplace_back(1.0, 0);
+ } else {
+ assert(n() <= (std::numeric_limits<IntType>::max)());
+ q_ = random_internal::InitDiscreteDistribution(&p_);
+ }
+}
+
+template <typename IntType>
+template <typename URBG>
+typename discrete_distribution<IntType>::result_type
+discrete_distribution<IntType>::operator()(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ const auto idx = absl::uniform_int_distribution<result_type>(0, p.n())(g);
+ const auto& q = p.q_[idx];
+ const bool selected = absl::bernoulli_distribution(q.first)(g);
+ return selected ? idx : static_cast<result_type>(q.second);
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const discrete_distribution<IntType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ const auto& probabilities = x.param().probabilities();
+ os << probabilities.size();
+
+ os.precision(random_internal::stream_precision_helper<double>::kPrecision);
+ for (const auto& p : probabilities) {
+ os << os.fill() << p;
+ }
+ return os;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ discrete_distribution<IntType>& x) { // NOLINT(runtime/references)
+ using param_type = typename discrete_distribution<IntType>::param_type;
+ auto saver = random_internal::make_istream_state_saver(is);
+
+ size_t n;
+ std::vector<double> p;
+
+ is >> n;
+ if (is.fail()) return is;
+ if (n > 0) {
+ p.reserve(n);
+ for (IntType i = 0; i < n && !is.fail(); ++i) {
+ auto tmp = random_internal::read_floating_point<double>(is);
+ if (is.fail()) return is;
+ p.push_back(tmp);
+ }
+ }
+ x.param(param_type(p.begin(), p.end()));
+ return is;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_DISCRETE_DISTRIBUTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution_test.cc
new file mode 100644
index 00000000000..6d007006ef4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/discrete_distribution_test.cc
@@ -0,0 +1,250 @@
+// 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.
+
+#include "absl/random/discrete_distribution.h"
+
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <numeric>
+#include <random>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+template <typename IntType>
+class DiscreteDistributionTypeTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t,
+ uint32_t, int64_t, uint64_t>;
+TYPED_TEST_SUITE(DiscreteDistributionTypeTest, IntTypes);
+
+TYPED_TEST(DiscreteDistributionTypeTest, ParamSerializeTest) {
+ using param_type =
+ typename absl::discrete_distribution<TypeParam>::param_type;
+
+ absl::discrete_distribution<TypeParam> empty;
+ EXPECT_THAT(empty.probabilities(), testing::ElementsAre(1.0));
+
+ absl::discrete_distribution<TypeParam> before({1.0, 2.0, 1.0});
+
+ // Validate that the probabilities sum to 1.0. We picked values which
+ // can be represented exactly to avoid floating-point roundoff error.
+ double s = 0;
+ for (const auto& x : before.probabilities()) {
+ s += x;
+ }
+ EXPECT_EQ(s, 1.0);
+ EXPECT_THAT(before.probabilities(), testing::ElementsAre(0.25, 0.5, 0.25));
+
+ // Validate the same data via an initializer list.
+ {
+ std::vector<double> data({1.0, 2.0, 1.0});
+
+ absl::discrete_distribution<TypeParam> via_param{
+ param_type(std::begin(data), std::end(data))};
+
+ EXPECT_EQ(via_param, before);
+ }
+
+ std::stringstream ss;
+ ss << before;
+ absl::discrete_distribution<TypeParam> after;
+
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before, after);
+}
+
+TYPED_TEST(DiscreteDistributionTypeTest, Constructor) {
+ auto fn = [](double x) { return x; };
+ {
+ absl::discrete_distribution<int> unary(0, 1.0, 9.0, fn);
+ EXPECT_THAT(unary.probabilities(), testing::ElementsAre(1.0));
+ }
+
+ {
+ absl::discrete_distribution<int> unary(2, 1.0, 9.0, fn);
+ // => fn(1.0 + 0 * 4 + 2) => 3
+ // => fn(1.0 + 1 * 4 + 2) => 7
+ EXPECT_THAT(unary.probabilities(), testing::ElementsAre(0.3, 0.7));
+ }
+}
+
+TEST(DiscreteDistributionTest, InitDiscreteDistribution) {
+ using testing::Pair;
+
+ {
+ std::vector<double> p({1.0, 2.0, 3.0});
+ std::vector<std::pair<double, size_t>> q =
+ absl::random_internal::InitDiscreteDistribution(&p);
+
+ EXPECT_THAT(p, testing::ElementsAre(1 / 6.0, 2 / 6.0, 3 / 6.0));
+
+ // Each bucket is p=1/3, so bucket 0 will send half it's traffic
+ // to bucket 2, while the rest will retain all of their traffic.
+ EXPECT_THAT(q, testing::ElementsAre(Pair(0.5, 2), //
+ Pair(1.0, 1), //
+ Pair(1.0, 2)));
+ }
+
+ {
+ std::vector<double> p({1.0, 2.0, 3.0, 5.0, 2.0});
+
+ std::vector<std::pair<double, size_t>> q =
+ absl::random_internal::InitDiscreteDistribution(&p);
+
+ EXPECT_THAT(p, testing::ElementsAre(1 / 13.0, 2 / 13.0, 3 / 13.0, 5 / 13.0,
+ 2 / 13.0));
+
+ // A more complex bucketing solution: Each bucket has p=0.2
+ // So buckets 0, 1, 4 will send their alternate traffic elsewhere, which
+ // happens to be bucket 3.
+ // However, summing up that alternate traffic gives bucket 3 too much
+ // traffic, so it will send some traffic to bucket 2.
+ constexpr double b0 = 1.0 / 13.0 / 0.2;
+ constexpr double b1 = 2.0 / 13.0 / 0.2;
+ constexpr double b3 = (5.0 / 13.0 / 0.2) - ((1 - b0) + (1 - b1) + (1 - b1));
+
+ EXPECT_THAT(q, testing::ElementsAre(Pair(b0, 3), //
+ Pair(b1, 3), //
+ Pair(1.0, 2), //
+ Pair(b3, 2), //
+ Pair(b1, 3)));
+ }
+}
+
+TEST(DiscreteDistributionTest, ChiSquaredTest50) {
+ using absl::random_internal::kChiSquared;
+
+ constexpr size_t kTrials = 10000;
+ constexpr int kBuckets = 50; // inclusive, so actally +1
+
+ // 1-in-100000 threshold, but remember, there are about 8 tests
+ // in this file. And the test could fail for other reasons.
+ // Empirically validated with --runs_per_test=10000.
+ const int kThreshold =
+ absl::random_internal::ChiSquareValue(kBuckets, 0.99999);
+
+ std::vector<double> weights(kBuckets, 0);
+ std::iota(std::begin(weights), std::end(weights), 1);
+ absl::discrete_distribution<int> dist(std::begin(weights), std::end(weights));
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng(0x2B7E151628AED2A6);
+
+ std::vector<int32_t> counts(kBuckets, 0);
+ for (size_t i = 0; i < kTrials; i++) {
+ auto x = dist(rng);
+ counts[x]++;
+ }
+
+ // Scale weights.
+ double sum = 0;
+ for (double x : weights) {
+ sum += x;
+ }
+ for (double& x : weights) {
+ x = kTrials * (x / sum);
+ }
+
+ double chi_square =
+ absl::random_internal::ChiSquare(std::begin(counts), std::end(counts),
+ std::begin(weights), std::end(weights));
+
+ if (chi_square > kThreshold) {
+ double p_value =
+ absl::random_internal::ChiSquarePValue(chi_square, kBuckets);
+
+ // Chi-squared test failed. Output does not appear to be uniform.
+ std::string msg;
+ for (size_t i = 0; i < counts.size(); i++) {
+ absl::StrAppend(&msg, i, ": ", counts[i], " vs ", weights[i], "\n");
+ }
+ absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n");
+ absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ",
+ kThreshold);
+ ABSL_RAW_LOG(INFO, "%s", msg.c_str());
+ FAIL() << msg;
+ }
+}
+
+TEST(DiscreteDistributionTest, StabilityTest) {
+ // absl::discrete_distribution stabilitiy relies on
+ // absl::uniform_int_distribution and absl::bernoulli_distribution.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(6);
+
+ {
+ absl::discrete_distribution<int32_t> dist({1.0, 2.0, 3.0, 5.0, 2.0});
+ EXPECT_EQ(0, dist.min());
+ EXPECT_EQ(4, dist.max());
+ for (auto& v : output) {
+ v = dist(urbg);
+ }
+ EXPECT_EQ(12, urbg.invocations());
+ }
+
+ // With 12 calls to urbg, each call into discrete_distribution consumes
+ // precisely 2 values: one for the uniform call, and a second for the
+ // bernoulli.
+ //
+ // Given the alt mapping: 0=>3, 1=>3, 2=>2, 3=>2, 4=>3, we can
+ //
+ // uniform: 443210143131
+ // bernoulli: b0 000011100101
+ // bernoulli: b1 001111101101
+ // bernoulli: b2 111111111111
+ // bernoulli: b3 001111101111
+ // bernoulli: b4 001111101101
+ // ...
+ EXPECT_THAT(output, testing::ElementsAre(3, 3, 1, 3, 3, 3));
+
+ {
+ urbg.reset();
+ absl::discrete_distribution<int64_t> dist({1.0, 2.0, 3.0, 5.0, 2.0});
+ EXPECT_EQ(0, dist.min());
+ EXPECT_EQ(4, dist.max());
+ for (auto& v : output) {
+ v = dist(urbg);
+ }
+ EXPECT_EQ(12, urbg.invocations());
+ }
+ EXPECT_THAT(output, testing::ElementsAre(3, 3, 0, 3, 0, 4));
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions.h
new file mode 100644
index 00000000000..31c79694e51
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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 continuous uniform 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 <algorithm>
+#include <cmath>
+#include <limits>
+#include <random>
+#include <type_traits>
+
+#include "absl/base/internal/inline_variable.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/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"
+#include "absl/random/uniform_real_distribution.h"
+#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::is_signed<R>::value, 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 http://ecolego.facilia.se/ecolego/show/Log-Uniform%20Distribution
+//
+// 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(std::is_integral<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(std::is_integral<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(std::is_integral<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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions_test.cc
new file mode 100644
index 00000000000..5866a07257e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/distributions_test.cc
@@ -0,0 +1,455 @@
+// 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.
+
+#include "absl/random/distributions.h"
+
+#include <cmath>
+#include <cstdint>
+#include <random>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/random.h"
+
+namespace {
+
+constexpr int kSize = 400000;
+
+class RandomDistributionsTest : public testing::Test {};
+
+
+struct Invalid {};
+
+template <typename A, typename B>
+auto InferredUniformReturnT(int)
+ -> decltype(absl::Uniform(std::declval<absl::InsecureBitGen&>(),
+ std::declval<A>(), std::declval<B>()));
+
+template <typename, typename>
+Invalid InferredUniformReturnT(...);
+
+template <typename TagType, typename A, typename B>
+auto InferredTaggedUniformReturnT(int)
+ -> decltype(absl::Uniform(std::declval<TagType>(),
+ std::declval<absl::InsecureBitGen&>(),
+ std::declval<A>(), std::declval<B>()));
+
+template <typename, typename, typename>
+Invalid InferredTaggedUniformReturnT(...);
+
+// Given types <A, B, Expect>, CheckArgsInferType() verifies that
+//
+// absl::Uniform(gen, A{}, B{})
+//
+// returns the type "Expect".
+//
+// This interface can also be used to assert that a given absl::Uniform()
+// overload does not exist / will not compile. Given types <A, B>, the
+// expression
+//
+// decltype(absl::Uniform(..., std::declval<A>(), std::declval<B>()))
+//
+// will not compile, leaving the definition of InferredUniformReturnT<A, B> to
+// resolve (via SFINAE) to the overload which returns type "Invalid". This
+// allows tests to assert that an invocation such as
+//
+// absl::Uniform(gen, 1.23f, std::numeric_limits<int>::max() - 1)
+//
+// should not compile, since neither type, float nor int, can precisely
+// represent both endpoint-values. Writing:
+//
+// CheckArgsInferType<float, int, Invalid>()
+//
+// will assert that this overload does not exist.
+template <typename A, typename B, typename Expect>
+void CheckArgsInferType() {
+ static_assert(
+ absl::conjunction<
+ std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
+ std::is_same<Expect,
+ decltype(InferredUniformReturnT<B, A>(0))>>::value,
+ "");
+ static_assert(
+ absl::conjunction<
+ std::is_same<Expect, decltype(InferredTaggedUniformReturnT<
+ absl::IntervalOpenOpenTag, A, B>(0))>,
+ std::is_same<Expect,
+ decltype(InferredTaggedUniformReturnT<
+ absl::IntervalOpenOpenTag, B, A>(0))>>::value,
+ "");
+}
+
+template <typename A, typename B, typename ExplicitRet>
+auto ExplicitUniformReturnT(int) -> decltype(
+ absl::Uniform<ExplicitRet>(*std::declval<absl::InsecureBitGen*>(),
+ std::declval<A>(), std::declval<B>()));
+
+template <typename, typename, typename ExplicitRet>
+Invalid ExplicitUniformReturnT(...);
+
+template <typename TagType, typename A, typename B, typename ExplicitRet>
+auto ExplicitTaggedUniformReturnT(int) -> decltype(absl::Uniform<ExplicitRet>(
+ std::declval<TagType>(), *std::declval<absl::InsecureBitGen*>(),
+ std::declval<A>(), std::declval<B>()));
+
+template <typename, typename, typename, typename ExplicitRet>
+Invalid ExplicitTaggedUniformReturnT(...);
+
+// Given types <A, B, Expect>, CheckArgsReturnExpectedType() verifies that
+//
+// absl::Uniform<Expect>(gen, A{}, B{})
+//
+// returns the type "Expect", and that the function-overload has the signature
+//
+// Expect(URBG&, Expect, Expect)
+template <typename A, typename B, typename Expect>
+void CheckArgsReturnExpectedType() {
+ static_assert(
+ absl::conjunction<
+ std::is_same<Expect,
+ decltype(ExplicitUniformReturnT<A, B, Expect>(0))>,
+ std::is_same<Expect, decltype(ExplicitUniformReturnT<B, A, Expect>(
+ 0))>>::value,
+ "");
+ static_assert(
+ absl::conjunction<
+ std::is_same<Expect,
+ decltype(ExplicitTaggedUniformReturnT<
+ absl::IntervalOpenOpenTag, A, B, Expect>(0))>,
+ std::is_same<Expect, decltype(ExplicitTaggedUniformReturnT<
+ absl::IntervalOpenOpenTag, B, A,
+ Expect>(0))>>::value,
+ "");
+}
+
+TEST_F(RandomDistributionsTest, UniformTypeInference) {
+ // Infers common types.
+ CheckArgsInferType<uint16_t, uint16_t, uint16_t>();
+ CheckArgsInferType<uint32_t, uint32_t, uint32_t>();
+ CheckArgsInferType<uint64_t, uint64_t, uint64_t>();
+ CheckArgsInferType<int16_t, int16_t, int16_t>();
+ CheckArgsInferType<int32_t, int32_t, int32_t>();
+ CheckArgsInferType<int64_t, int64_t, int64_t>();
+ CheckArgsInferType<float, float, float>();
+ CheckArgsInferType<double, double, double>();
+
+ // Explicitly-specified return-values override inferences.
+ CheckArgsReturnExpectedType<int16_t, int16_t, int32_t>();
+ CheckArgsReturnExpectedType<uint16_t, uint16_t, int32_t>();
+ CheckArgsReturnExpectedType<int16_t, int16_t, int64_t>();
+ CheckArgsReturnExpectedType<int16_t, int32_t, int64_t>();
+ CheckArgsReturnExpectedType<int16_t, int32_t, double>();
+ CheckArgsReturnExpectedType<float, float, double>();
+ CheckArgsReturnExpectedType<int, int, int16_t>();
+
+ // Properly promotes uint16_t.
+ CheckArgsInferType<uint16_t, uint32_t, uint32_t>();
+ CheckArgsInferType<uint16_t, uint64_t, uint64_t>();
+ CheckArgsInferType<uint16_t, int32_t, int32_t>();
+ CheckArgsInferType<uint16_t, int64_t, int64_t>();
+ CheckArgsInferType<uint16_t, float, float>();
+ CheckArgsInferType<uint16_t, double, double>();
+
+ // Properly promotes int16_t.
+ CheckArgsInferType<int16_t, int32_t, int32_t>();
+ CheckArgsInferType<int16_t, int64_t, int64_t>();
+ CheckArgsInferType<int16_t, float, float>();
+ CheckArgsInferType<int16_t, double, double>();
+
+ // Invalid (u)int16_t-pairings do not compile.
+ // See "CheckArgsInferType" comments above, for how this is achieved.
+ CheckArgsInferType<uint16_t, int16_t, Invalid>();
+ CheckArgsInferType<int16_t, uint32_t, Invalid>();
+ CheckArgsInferType<int16_t, uint64_t, Invalid>();
+
+ // Properly promotes uint32_t.
+ CheckArgsInferType<uint32_t, uint64_t, uint64_t>();
+ CheckArgsInferType<uint32_t, int64_t, int64_t>();
+ CheckArgsInferType<uint32_t, double, double>();
+
+ // Properly promotes int32_t.
+ CheckArgsInferType<int32_t, int64_t, int64_t>();
+ CheckArgsInferType<int32_t, double, double>();
+
+ // Invalid (u)int32_t-pairings do not compile.
+ CheckArgsInferType<uint32_t, int32_t, Invalid>();
+ CheckArgsInferType<int32_t, uint64_t, Invalid>();
+ CheckArgsInferType<int32_t, float, Invalid>();
+ CheckArgsInferType<uint32_t, float, Invalid>();
+
+ // Invalid (u)int64_t-pairings do not compile.
+ CheckArgsInferType<uint64_t, int64_t, Invalid>();
+ CheckArgsInferType<int64_t, float, Invalid>();
+ CheckArgsInferType<int64_t, double, Invalid>();
+
+ // Properly promotes float.
+ CheckArgsInferType<float, double, double>();
+}
+
+TEST_F(RandomDistributionsTest, UniformExamples) {
+ // Examples.
+ absl::InsecureBitGen gen;
+ EXPECT_NE(1, absl::Uniform(gen, static_cast<uint16_t>(0), 1.0f));
+ EXPECT_NE(1, absl::Uniform(gen, 0, 1.0));
+ EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen,
+ static_cast<uint16_t>(0), 1.0f));
+ EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, 0, 1.0));
+ EXPECT_NE(1, absl::Uniform(absl::IntervalOpenOpen, gen, -1, 1.0));
+ EXPECT_NE(1, absl::Uniform<double>(absl::IntervalOpenOpen, gen, -1, 1));
+ EXPECT_NE(1, absl::Uniform<float>(absl::IntervalOpenOpen, gen, 0, 1));
+ EXPECT_NE(1, absl::Uniform<float>(gen, 0, 1));
+}
+
+TEST_F(RandomDistributionsTest, UniformNoBounds) {
+ absl::InsecureBitGen gen;
+
+ absl::Uniform<uint8_t>(gen);
+ absl::Uniform<uint16_t>(gen);
+ absl::Uniform<uint32_t>(gen);
+ absl::Uniform<uint64_t>(gen);
+}
+
+TEST_F(RandomDistributionsTest, UniformNonsenseRanges) {
+ // The ranges used in this test are undefined behavior.
+ // The results are arbitrary and subject to future changes.
+ absl::InsecureBitGen gen;
+
+ // <uint>
+ EXPECT_EQ(0, absl::Uniform<uint64_t>(gen, 0, 0));
+ EXPECT_EQ(1, absl::Uniform<uint64_t>(gen, 1, 0));
+ EXPECT_EQ(0, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 0, 0));
+ EXPECT_EQ(1, absl::Uniform<uint64_t>(absl::IntervalOpenOpen, gen, 1, 0));
+
+ constexpr auto m = (std::numeric_limits<uint64_t>::max)();
+
+ EXPECT_EQ(m, absl::Uniform(gen, m, m));
+ EXPECT_EQ(m, absl::Uniform(gen, m, m - 1));
+ EXPECT_EQ(m - 1, absl::Uniform(gen, m - 1, m));
+ EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m));
+ EXPECT_EQ(m, absl::Uniform(absl::IntervalOpenOpen, gen, m, m - 1));
+ EXPECT_EQ(m - 1, absl::Uniform(absl::IntervalOpenOpen, gen, m - 1, m));
+
+ // <int>
+ EXPECT_EQ(0, absl::Uniform<int64_t>(gen, 0, 0));
+ EXPECT_EQ(1, absl::Uniform<int64_t>(gen, 1, 0));
+ EXPECT_EQ(0, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 0, 0));
+ EXPECT_EQ(1, absl::Uniform<int64_t>(absl::IntervalOpenOpen, gen, 1, 0));
+
+ constexpr auto l = (std::numeric_limits<int64_t>::min)();
+ constexpr auto r = (std::numeric_limits<int64_t>::max)();
+
+ EXPECT_EQ(l, absl::Uniform(gen, l, l));
+ EXPECT_EQ(r, absl::Uniform(gen, r, r));
+ EXPECT_EQ(r, absl::Uniform(gen, r, r - 1));
+ EXPECT_EQ(r - 1, absl::Uniform(gen, r - 1, r));
+ EXPECT_EQ(l, absl::Uniform(absl::IntervalOpenOpen, gen, l, l));
+ EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r));
+ EXPECT_EQ(r, absl::Uniform(absl::IntervalOpenOpen, gen, r, r - 1));
+ EXPECT_EQ(r - 1, absl::Uniform(absl::IntervalOpenOpen, gen, r - 1, r));
+
+ // <double>
+ const double e = std::nextafter(1.0, 2.0); // 1 + epsilon
+ const double f = std::nextafter(1.0, 0.0); // 1 - epsilon
+ const double g = std::numeric_limits<double>::denorm_min();
+
+ EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, e));
+ EXPECT_EQ(1.0, absl::Uniform(gen, 1.0, f));
+ EXPECT_EQ(0.0, absl::Uniform(gen, 0.0, g));
+
+ EXPECT_EQ(e, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, e));
+ EXPECT_EQ(f, absl::Uniform(absl::IntervalOpenOpen, gen, 1.0, f));
+ EXPECT_EQ(g, absl::Uniform(absl::IntervalOpenOpen, gen, 0.0, g));
+}
+
+// TODO(lar): Validate properties of non-default interval-semantics.
+TEST_F(RandomDistributionsTest, UniformReal) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Uniform(gen, 0, 1.0);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(0.5, moments.mean, 0.02);
+ EXPECT_NEAR(1 / 12.0, moments.variance, 0.02);
+ EXPECT_NEAR(0.0, moments.skewness, 0.02);
+ EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02);
+}
+
+TEST_F(RandomDistributionsTest, UniformInt) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ const int64_t kMax = 1000000000000ll;
+ int64_t j = absl::Uniform(absl::IntervalClosedClosed, gen, 0, kMax);
+ // convert to double.
+ values[i] = static_cast<double>(j) / static_cast<double>(kMax);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(0.5, moments.mean, 0.02);
+ EXPECT_NEAR(1 / 12.0, moments.variance, 0.02);
+ EXPECT_NEAR(0.0, moments.skewness, 0.02);
+ EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.02);
+
+ /*
+ // NOTE: These are not supported by absl::Uniform, which is specialized
+ // on integer and real valued types.
+
+ enum E { E0, E1 }; // enum
+ enum S : int { S0, S1 }; // signed enum
+ enum U : unsigned int { U0, U1 }; // unsigned enum
+
+ absl::Uniform(gen, E0, E1);
+ absl::Uniform(gen, S0, S1);
+ absl::Uniform(gen, U0, U1);
+ */
+}
+
+TEST_F(RandomDistributionsTest, Exponential) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Exponential<double>(gen);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(1.0, moments.mean, 0.02);
+ EXPECT_NEAR(1.0, moments.variance, 0.025);
+ EXPECT_NEAR(2.0, moments.skewness, 0.1);
+ EXPECT_LT(5.0, moments.kurtosis);
+}
+
+TEST_F(RandomDistributionsTest, PoissonDefault) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Poisson<int64_t>(gen);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(1.0, moments.mean, 0.02);
+ EXPECT_NEAR(1.0, moments.variance, 0.02);
+ EXPECT_NEAR(1.0, moments.skewness, 0.025);
+ EXPECT_LT(2.0, moments.kurtosis);
+}
+
+TEST_F(RandomDistributionsTest, PoissonLarge) {
+ constexpr double kMean = 100000000.0;
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Poisson<int64_t>(gen, kMean);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(kMean, moments.mean, kMean * 0.015);
+ EXPECT_NEAR(kMean, moments.variance, kMean * 0.015);
+ EXPECT_NEAR(std::sqrt(kMean), moments.skewness, kMean * 0.02);
+ EXPECT_LT(2.0, moments.kurtosis);
+}
+
+TEST_F(RandomDistributionsTest, Bernoulli) {
+ constexpr double kP = 0.5151515151;
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Bernoulli(gen, kP);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(kP, moments.mean, 0.01);
+}
+
+TEST_F(RandomDistributionsTest, Beta) {
+ constexpr double kAlpha = 2.0;
+ constexpr double kBeta = 3.0;
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Beta(gen, kAlpha, kBeta);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(0.4, moments.mean, 0.01);
+}
+
+TEST_F(RandomDistributionsTest, Zipf) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Zipf<int64_t>(gen, 100);
+ }
+
+ // The mean of a zipf distribution is: H(N, s-1) / H(N,s).
+ // Given the parameter v = 1, this gives the following function:
+ // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(6.5944, moments.mean, 2000) << moments;
+}
+
+TEST_F(RandomDistributionsTest, Gaussian) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::Gaussian<double>(gen);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(0.0, moments.mean, 0.02);
+ EXPECT_NEAR(1.0, moments.variance, 0.04);
+ EXPECT_NEAR(0, moments.skewness, 0.2);
+ EXPECT_NEAR(3.0, moments.kurtosis, 0.5);
+}
+
+TEST_F(RandomDistributionsTest, LogUniform) {
+ std::vector<double> values(kSize);
+
+ absl::InsecureBitGen gen;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = absl::LogUniform<int64_t>(gen, 0, (1 << 10) - 1);
+ }
+
+ // The mean is the sum of the fractional means of the uniform distributions:
+ // [0..0][1..1][2..3][4..7][8..15][16..31][32..63]
+ // [64..127][128..255][256..511][512..1023]
+ const double mean = (0 + 1 + 1 + 2 + 3 + 4 + 7 + 8 + 15 + 16 + 31 + 32 + 63 +
+ 64 + 127 + 128 + 255 + 256 + 511 + 512 + 1023) /
+ (2.0 * 11.0);
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(mean, moments.mean, 2) << moments;
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/examples_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/examples_test.cc
new file mode 100644
index 00000000000..1dcb5146f3d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/examples_test.cc
@@ -0,0 +1,99 @@
+// 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.
+
+#include <cinttypes>
+#include <random>
+#include <sstream>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/random/random.h"
+
+template <typename T>
+void Use(T) {}
+
+TEST(Examples, Basic) {
+ absl::BitGen gen;
+ std::vector<int> objs = {10, 20, 30, 40, 50};
+
+ // Choose an element from a set.
+ auto elem = objs[absl::Uniform(gen, 0u, objs.size())];
+ Use(elem);
+
+ // Generate a uniform value between 1 and 6.
+ auto dice_roll = absl::Uniform<int>(absl::IntervalClosedClosed, gen, 1, 6);
+ Use(dice_roll);
+
+ // Generate a random byte.
+ auto byte = absl::Uniform<uint8_t>(gen);
+ Use(byte);
+
+ // Generate a fractional value from [0f, 1f).
+ auto fraction = absl::Uniform<float>(gen, 0, 1);
+ Use(fraction);
+
+ // Toss a fair coin; 50/50 probability.
+ bool coin_toss = absl::Bernoulli(gen, 0.5);
+ Use(coin_toss);
+
+ // Select a file size between 1k and 10MB, biased towards smaller file sizes.
+ auto file_size = absl::LogUniform<size_t>(gen, 1000, 10 * 1000 * 1000);
+ Use(file_size);
+
+ // Randomize (shuffle) a collection.
+ std::shuffle(std::begin(objs), std::end(objs), gen);
+}
+
+TEST(Examples, CreateingCorrelatedVariateSequences) {
+ // Unexpected PRNG correlation is often a source of bugs,
+ // so when using absl::BitGen it must be an intentional choice.
+ // NOTE: All of these only exhibit process-level stability.
+
+ // Create a correlated sequence from system entropy.
+ {
+ auto my_seed = absl::MakeSeedSeq();
+
+ absl::BitGen gen_1(my_seed);
+ absl::BitGen gen_2(my_seed); // Produces same variates as gen_1.
+
+ EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));
+ EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));
+ }
+
+ // Create a correlated sequence from an existing URBG.
+ {
+ absl::BitGen gen;
+
+ auto my_seed = absl::CreateSeedSeqFrom(&gen);
+ absl::BitGen gen_1(my_seed);
+ absl::BitGen gen_2(my_seed);
+
+ EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));
+ EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));
+ }
+
+ // An alternate construction which uses user-supplied data
+ // instead of a random seed.
+ {
+ const char kData[] = "A simple seed string";
+ std::seed_seq my_seed(std::begin(kData), std::end(kData));
+
+ absl::BitGen gen_1(my_seed);
+ absl::BitGen gen_2(my_seed);
+
+ EXPECT_EQ(absl::Bernoulli(gen_1, 0.5), absl::Bernoulli(gen_2, 0.5));
+ EXPECT_EQ(absl::Uniform<uint32_t>(gen_1), absl::Uniform<uint32_t>(gen_2));
+ }
+}
+
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution.h
new file mode 100644
index 00000000000..b5caf8a1e1f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution_test.cc
new file mode 100644
index 00000000000..af11d61c156
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/exponential_distribution_test.cc
@@ -0,0 +1,418 @@
+// 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.
+
+#include "absl/random/exponential_distribution.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <limits>
+#include <random>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/numeric/internal/representation.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+using absl::random_internal::kChiSquared;
+
+template <typename RealType>
+class ExponentialDistributionTypedTest : public ::testing::Test {};
+
+// double-double arithmetic is not supported well by either GCC or Clang; see
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,
+// https://bugs.llvm.org/show_bug.cgi?id=49131, and
+// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests
+// with double doubles until compiler support is better.
+using RealTypes =
+ std::conditional<absl::numeric_internal::IsDoubleDouble(),
+ ::testing::Types<float, double>,
+ ::testing::Types<float, double, long double>>::type;
+TYPED_TEST_CASE(ExponentialDistributionTypedTest, RealTypes);
+
+TYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) {
+ using param_type =
+ typename absl::exponential_distribution<TypeParam>::param_type;
+
+ const TypeParam kParams[] = {
+ // Cases around 1.
+ 1, //
+ std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon
+ std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon
+ // Typical cases.
+ TypeParam(1e-8), TypeParam(1e-4), TypeParam(1), TypeParam(2),
+ TypeParam(1e4), TypeParam(1e8), TypeParam(1e20), TypeParam(2.5),
+ // Boundary cases.
+ std::numeric_limits<TypeParam>::max(),
+ std::numeric_limits<TypeParam>::epsilon(),
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(1)), // min + epsilon
+ std::numeric_limits<TypeParam>::min(), // smallest normal
+ // There are some errors dealing with denorms on apple platforms.
+ std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm
+ std::numeric_limits<TypeParam>::min() / 2, // denorm
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(0)), // denorm_max
+ };
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+
+ for (const TypeParam lambda : kParams) {
+ // Some values may be invalid; skip those.
+ if (!std::isfinite(lambda)) continue;
+ ABSL_ASSERT(lambda > 0);
+
+ const param_type param(lambda);
+
+ absl::exponential_distribution<TypeParam> before(lambda);
+ EXPECT_EQ(before.lambda(), param.lambda());
+
+ {
+ absl::exponential_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ EXPECT_EQ(via_param.param(), before.param());
+ }
+
+ // Smoke test.
+ auto sample_min = before.max();
+ auto sample_max = before.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = before(gen);
+ EXPECT_GE(sample, before.min()) << before;
+ EXPECT_LE(sample, before.max()) << before;
+ if (sample > sample_max) sample_max = sample;
+ if (sample < sample_min) sample_min = sample;
+ }
+ if (!std::is_same<TypeParam, long double>::value) {
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrFormat("Range {%f}: %f, %f, lambda=%f", lambda,
+ sample_min, sample_max, lambda));
+ }
+
+ std::stringstream ss;
+ ss << before;
+
+ if (!std::isfinite(lambda)) {
+ // Streams do not deserialize inf/nan correctly.
+ continue;
+ }
+ // Validate stream serialization.
+ absl::exponential_distribution<TypeParam> after(34.56f);
+
+ EXPECT_NE(before.lambda(), after.lambda());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.lambda(), after.lambda()) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+ }
+}
+
+// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3667.htm
+
+class ExponentialModel {
+ public:
+ explicit ExponentialModel(double lambda)
+ : lambda_(lambda), beta_(1.0 / lambda) {}
+
+ double lambda() const { return lambda_; }
+
+ double mean() const { return beta_; }
+ double variance() const { return beta_ * beta_; }
+ double stddev() const { return std::sqrt(variance()); }
+ double skew() const { return 2; }
+ double kurtosis() const { return 6.0; }
+
+ double CDF(double x) { return 1.0 - std::exp(-lambda_ * x); }
+
+ // The inverse CDF, or PercentPoint function of the distribution
+ double InverseCDF(double p) {
+ ABSL_ASSERT(p >= 0.0);
+ ABSL_ASSERT(p < 1.0);
+ return -beta_ * std::log(1.0 - p);
+ }
+
+ private:
+ const double lambda_;
+ const double beta_;
+};
+
+struct Param {
+ double lambda;
+ double p_fail;
+ int trials;
+};
+
+class ExponentialDistributionTests : public testing::TestWithParam<Param>,
+ public ExponentialModel {
+ public:
+ ExponentialDistributionTests() : ExponentialModel(GetParam().lambda) {}
+
+ // SingleZTest provides a basic z-squared test of the mean vs. expected
+ // mean for data generated by the poisson distribution.
+ template <typename D>
+ bool SingleZTest(const double p, const size_t samples);
+
+ // SingleChiSquaredTest provides a basic chi-squared test of the normal
+ // distribution.
+ template <typename D>
+ double SingleChiSquaredTest();
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+template <typename D>
+bool ExponentialDistributionTests::SingleZTest(const double p,
+ const size_t samples) {
+ D dis(lambda());
+
+ std::vector<double> data;
+ data.reserve(samples);
+ for (size_t i = 0; i < samples; i++) {
+ const double x = dis(rng_);
+ data.push_back(x);
+ }
+
+ const auto m = absl::random_internal::ComputeDistributionMoments(data);
+ const double max_err = absl::random_internal::MaxErrorTolerance(p);
+ const double z = absl::random_internal::ZScore(mean(), m);
+ const bool pass = absl::random_internal::Near("z", z, 0.0, max_err);
+
+ if (!pass) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("p=%f max_err=%f\n"
+ " lambda=%f\n"
+ " mean=%f vs. %f\n"
+ " stddev=%f vs. %f\n"
+ " skewness=%f vs. %f\n"
+ " kurtosis=%f vs. %f\n"
+ " z=%f vs. 0",
+ p, max_err, lambda(), m.mean, mean(),
+ std::sqrt(m.variance), stddev(), m.skewness,
+ skew(), m.kurtosis, kurtosis(), z));
+ }
+ return pass;
+}
+
+template <typename D>
+double ExponentialDistributionTests::SingleChiSquaredTest() {
+ const size_t kSamples = 10000;
+ const int kBuckets = 50;
+
+ // The InverseCDF is the percent point function of the distribution, and can
+ // be used to assign buckets roughly uniformly.
+ std::vector<double> cutoffs;
+ const double kInc = 1.0 / static_cast<double>(kBuckets);
+ for (double p = kInc; p < 1.0; p += kInc) {
+ cutoffs.push_back(InverseCDF(p));
+ }
+ if (cutoffs.back() != std::numeric_limits<double>::infinity()) {
+ cutoffs.push_back(std::numeric_limits<double>::infinity());
+ }
+
+ D dis(lambda());
+
+ std::vector<int32_t> counts(cutoffs.size(), 0);
+ for (int j = 0; j < kSamples; j++) {
+ const double x = dis(rng_);
+ auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);
+ counts[std::distance(cutoffs.begin(), it)]++;
+ }
+
+ // Null-hypothesis is that the distribution is exponentially distributed
+ // with the provided lambda (not estimated from the data).
+ const int dof = static_cast<int>(counts.size()) - 1;
+
+ // Our threshold for logging is 1-in-50.
+ const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);
+
+ const double expected =
+ static_cast<double>(kSamples) / static_cast<double>(counts.size());
+
+ double chi_square = absl::random_internal::ChiSquareWithExpected(
+ std::begin(counts), std::end(counts), expected);
+ double p = absl::random_internal::ChiSquarePValue(chi_square, dof);
+
+ if (chi_square > threshold) {
+ for (int i = 0; i < cutoffs.size(); i++) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("%d : (%f) = %d", i, cutoffs[i], counts[i]));
+ }
+
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("lambda ", lambda(), "\n", //
+ " expected ", expected, "\n", //
+ kChiSquared, " ", chi_square, " (", p, ")\n",
+ kChiSquared, " @ 0.98 = ", threshold));
+ }
+ return p;
+}
+
+TEST_P(ExponentialDistributionTests, ZTest) {
+ const size_t kSamples = 10000;
+ const auto& param = GetParam();
+ const int expected_failures =
+ std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));
+ const double p = absl::random_internal::RequiredSuccessProbability(
+ param.p_fail, param.trials);
+
+ int failures = 0;
+ for (int i = 0; i < param.trials; i++) {
+ failures += SingleZTest<absl::exponential_distribution<double>>(p, kSamples)
+ ? 0
+ : 1;
+ }
+ EXPECT_LE(failures, expected_failures);
+}
+
+TEST_P(ExponentialDistributionTests, ChiSquaredTest) {
+ const int kTrials = 20;
+ int failures = 0;
+
+ for (int i = 0; i < kTrials; i++) {
+ double p_value =
+ SingleChiSquaredTest<absl::exponential_distribution<double>>();
+ if (p_value < 0.005) { // 1/200
+ failures++;
+ }
+ }
+
+ // There is a 0.10% chance of producing at least one failure, so raise the
+ // failure threshold high enough to allow for a flake rate < 10,000.
+ EXPECT_LE(failures, 4);
+}
+
+std::vector<Param> GenParams() {
+ return {
+ Param{1.0, 0.02, 100},
+ Param{2.5, 0.02, 100},
+ Param{10, 0.02, 100},
+ // large
+ Param{1e4, 0.02, 100},
+ Param{1e9, 0.02, 100},
+ // small
+ Param{0.1, 0.02, 100},
+ Param{1e-3, 0.02, 100},
+ Param{1e-5, 0.02, 100},
+ };
+}
+
+std::string ParamName(const ::testing::TestParamInfo<Param>& info) {
+ const auto& p = info.param;
+ std::string name = absl::StrCat("lambda_", absl::SixDigits(p.lambda));
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_CASE_P(All, ExponentialDistributionTests,
+ ::testing::ValuesIn(GenParams()), ParamName);
+
+// NOTE: absl::exponential_distribution is not guaranteed to be stable.
+TEST(ExponentialDistributionTest, StabilityTest) {
+ // absl::exponential_distribution stability relies on std::log1p and
+ // absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(14);
+
+ {
+ absl::exponential_distribution<double> dist;
+ std::generate(std::begin(output), std::end(output),
+ [&] { return static_cast<int>(10000.0 * dist(urbg)); });
+
+ EXPECT_EQ(14, urbg.invocations());
+ EXPECT_THAT(output,
+ testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,
+ 804, 126, 12337, 17984, 27002, 0, 71913));
+ }
+
+ urbg.reset();
+ {
+ absl::exponential_distribution<float> dist;
+ std::generate(std::begin(output), std::end(output),
+ [&] { return static_cast<int>(10000.0f * dist(urbg)); });
+
+ EXPECT_EQ(14, urbg.invocations());
+ EXPECT_THAT(output,
+ testing::ElementsAre(0, 71913, 14375, 5039, 1835, 861, 25936,
+ 804, 126, 12337, 17984, 27002, 0, 71913));
+ }
+}
+
+TEST(ExponentialDistributionTest, AlgorithmBounds) {
+ // Relies on absl::uniform_real_distribution, so some of these comments
+ // reference that.
+ absl::exponential_distribution<double> dist;
+
+ {
+ // This returns the smallest value >0 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0x0000000000000001ull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 5.42101086242752217004e-20);
+ }
+
+ {
+ // This returns a value very near 0.5 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 0.693147180559945175204);
+ }
+
+ {
+ // This returns the largest value <1 from absl::uniform_real_distribution.
+ // WolframAlpha: ~39.1439465808987766283058547296341915292187253
+ absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFeFull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 36.7368005696771007251);
+ }
+ {
+ // This *ALSO* returns the largest value <1.
+ absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 36.7368005696771007251);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.cc
new file mode 100644
index 00000000000..c7a72cb2f61
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.cc
@@ -0,0 +1,104 @@
+// BEGIN GENERATED CODE; DO NOT EDIT
+// clang-format off
+
+#include "absl/random/gaussian_distribution.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+const gaussian_distribution_base::Tables
+ gaussian_distribution_base::zg_ = {
+ {3.7130862467425505, 3.442619855899000214, 3.223084984581141565,
+ 3.083228858216868318, 2.978696252647779819, 2.894344007021528942,
+ 2.82312535054891045, 2.761169372387176857, 2.706113573121819549,
+ 2.656406411261359679, 2.610972248431847387, 2.56903362592493778,
+ 2.530009672388827457, 2.493454522095372106, 2.459018177411830486,
+ 2.426420645533749809, 2.395434278011062457, 2.365871370117638595,
+ 2.337575241339236776, 2.310413683698762988, 2.284274059677471769,
+ 2.25905957386919809, 2.234686395590979036, 2.21108140887870297,
+ 2.188180432076048731, 2.165926793748921497, 2.144270182360394905,
+ 2.123165708673976138, 2.102573135189237608, 2.082456237992015957,
+ 2.062782274508307978, 2.043521536655067194, 2.02464697337738464,
+ 2.006133869963471206, 1.987959574127619033, 1.970103260854325633,
+ 1.952545729553555764, 1.935269228296621957, 1.918257300864508963,
+ 1.901494653105150423, 1.884967035707758143, 1.868661140994487768,
+ 1.852564511728090002, 1.836665460258444904, 1.820952996596124418,
+ 1.805416764219227366, 1.790046982599857506, 1.77483439558606837,
+ 1.759770224899592339, 1.744846128113799244, 1.730054160563729182,
+ 1.71538674071366648, 1.700836618569915748, 1.686396846779167014,
+ 1.6720607540975998, 1.657821920954023254, 1.643674156862867441,
+ 1.629611479470633562, 1.615628095043159629, 1.601718380221376581,
+ 1.587876864890574558, 1.574098216022999264, 1.560377222366167382,
+ 1.546708779859908844, 1.533087877674041755, 1.519509584765938559,
+ 1.505969036863201937, 1.492461423781352714, 1.478981976989922842,
+ 1.465525957342709296, 1.452088642889222792, 1.438665316684561546,
+ 1.425251254514058319, 1.411841712447055919, 1.398431914131003539,
+ 1.385017037732650058, 1.371592202427340812, 1.358152454330141534,
+ 1.34469275175354519, 1.331207949665625279, 1.317692783209412299,
+ 1.304141850128615054, 1.290549591926194894, 1.27691027356015363,
+ 1.263217961454619287, 1.249466499573066436, 1.23564948326336066,
+ 1.221760230539994385, 1.207791750415947662, 1.193736707833126465,
+ 1.17958738466398616, 1.165335636164750222, 1.150972842148865416,
+ 1.136489852013158774, 1.121876922582540237, 1.107123647534034028,
+ 1.092218876907275371, 1.077150624892893482, 1.061905963694822042,
+ 1.046470900764042922, 1.030830236068192907, 1.014967395251327842,
+ 0.9988642334929808131, 0.9825008035154263464, 0.9658550794011470098,
+ 0.9489026255113034436, 0.9316161966151479401, 0.9139652510230292792,
+ 0.8959153525809346874, 0.8774274291129204872, 0.8584568431938099931,
+ 0.8389522142975741614, 0.8188539067003538507, 0.7980920606440534693,
+ 0.7765839878947563557, 0.7542306644540520688, 0.7309119106424850631,
+ 0.7064796113354325779, 0.6807479186691505202, 0.6534786387399710295,
+ 0.6243585973360461505, 0.5929629424714434327, 0.5586921784081798625,
+ 0.5206560387620546848, 0.4774378372966830431, 0.4265479863554152429,
+ 0.3628714310970211909, 0.2723208648139477384, 0},
+ {0.001014352564120377413, 0.002669629083880922793, 0.005548995220771345792,
+ 0.008624484412859888607, 0.01183947865788486861, 0.01516729801054656976,
+ 0.01859210273701129151, 0.02210330461592709475, 0.02569329193593428151,
+ 0.02935631744000685023, 0.03308788614622575758, 0.03688438878665621645,
+ 0.04074286807444417458, 0.04466086220049143157, 0.04863629585986780496,
+ 0.05266740190305100461, 0.05675266348104984759, 0.06089077034804041277,
+ 0.06508058521306804567, 0.06932111739357792179, 0.07361150188411341722,
+ 0.07795098251397346301, 0.08233889824223575293, 0.08677467189478028919,
+ 0.09125780082683036809, 0.095787849121731522, 0.1003644410286559929,
+ 0.1049872554094214289, 0.1096560210148404546, 0.1143705124488661323,
+ 0.1191305467076509556, 0.1239359802028679736, 0.1287867061959434012,
+ 0.1336826525834396151, 0.1386237799845948804, 0.1436100800906280339,
+ 0.1486415742423425057, 0.1537183122081819397, 0.1588403711394795748,
+ 0.1640078546834206341, 0.1692208922373653057, 0.1744796383307898324,
+ 0.1797842721232958407, 0.1851349970089926078, 0.1905320403191375633,
+ 0.1959756531162781534, 0.2014661100743140865, 0.2070037094399269362,
+ 0.2125887730717307134, 0.2182216465543058426, 0.2239026993850088965,
+ 0.229632325232116602, 0.2354109422634795556, 0.2412389935454402889,
+ 0.2471169475123218551, 0.2530452985073261551, 0.2590245673962052742,
+ 0.2650553022555897087, 0.271138079138385224, 0.2772735029191887857,
+ 0.2834622082232336471, 0.2897048604429605656, 0.2960021568469337061,
+ 0.3023548277864842593, 0.3087636380061818397, 0.3152293880650116065,
+ 0.3217529158759855901, 0.3283350983728509642, 0.3349768533135899506,
+ 0.3416791412315512977, 0.3484429675463274756, 0.355269384847918035,
+ 0.3621594953693184626, 0.3691144536644731522, 0.376135469510563536,
+ 0.3832238110559021416, 0.3903808082373155797, 0.3976078564938743676,
+ 0.404906420807223999, 0.4122780401026620578, 0.4197243320495753771,
+ 0.4272469983049970721, 0.4348478302499918513, 0.4425287152754694975,
+ 0.4502916436820402768, 0.458138716267873114, 0.4660721526894572309,
+ 0.4740943006930180559, 0.4822076463294863724, 0.4904148252838453348,
+ 0.4987186354709807201, 0.5071220510755701794, 0.5156282382440030565,
+ 0.5242405726729852944, 0.5329626593838373561, 0.5417983550254266145,
+ 0.5507517931146057588, 0.5598274127040882009, 0.5690299910679523787,
+ 0.5783646811197646898, 0.5878370544347081283, 0.5974531509445183408,
+ 0.6072195366251219584, 0.6171433708188825973, 0.6272324852499290282,
+ 0.6374954773350440806, 0.6479418211102242475, 0.6585820000500898219,
+ 0.6694276673488921414, 0.6804918409973358395, 0.6917891434366769676,
+ 0.7033360990161600101, 0.7151515074105005976, 0.7272569183441868201,
+ 0.7396772436726493094, 0.7524415591746134169, 0.7655841738977066102,
+ 0.7791460859296898134, 0.7931770117713072832, 0.8077382946829627652,
+ 0.8229072113814113187, 0.8387836052959920519, 0.8555006078694531446,
+ 0.873243048910072206, 0.8922816507840289901, 0.9130436479717434217,
+ 0.9362826816850632339, 0.9635996931270905952, 1}};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+// clang-format on
+// END GENERATED CODE
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.h
new file mode 100644
index 00000000000..4b07a5c0af9
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution.h
@@ -0,0 +1,275 @@
+// 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_GAUSSIAN_DISTRIBUTION_H_
+#define ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_
+
+// absl::gaussian_distribution implements the Ziggurat algorithm
+// for generating random gaussian numbers.
+//
+// Implementation based on "The Ziggurat Method for Generating Random Variables"
+// by George Marsaglia and Wai Wan Tsang: http://www.jstatsoft.org/v05/i08/
+//
+
+#include <cmath>
+#include <cstdint>
+#include <istream>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/config.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
+namespace random_internal {
+
+// absl::gaussian_distribution_base implements the underlying ziggurat algorithm
+// using the ziggurat tables generated by the gaussian_distribution_gentables
+// binary.
+//
+// The specific algorithm has some of the improvements suggested by the
+// 2005 paper, "An Improved Ziggurat Method to Generate Normal Random Samples",
+// Jurgen A Doornik. (https://www.doornik.com/research/ziggurat.pdf)
+class ABSL_DLL gaussian_distribution_base {
+ public:
+ template <typename URBG>
+ inline double zignor(URBG& g); // NOLINT(runtime/references)
+
+ private:
+ friend class TableGenerator;
+
+ template <typename URBG>
+ inline double zignor_fallback(URBG& g, // NOLINT(runtime/references)
+ bool neg);
+
+ // Constants used for the gaussian distribution.
+ static constexpr double kR = 3.442619855899; // Start of the tail.
+ static constexpr double kRInv = 0.29047645161474317; // ~= (1.0 / kR) .
+ static constexpr double kV = 9.91256303526217e-3;
+ static constexpr uint64_t kMask = 0x07f;
+
+ // The ziggurat tables store the pdf(f) and inverse-pdf(x) for equal-area
+ // points on one-half of the normal distribution, where the pdf function,
+ // pdf = e ^ (-1/2 *x^2), assumes that the mean = 0 & stddev = 1.
+ //
+ // These tables are just over 2kb in size; larger tables might improve the
+ // distributions, but also lead to more cache pollution.
+ //
+ // x = {3.71308, 3.44261, 3.22308, ..., 0}
+ // f = {0.00101, 0.00266, 0.00554, ..., 1}
+ struct Tables {
+ double x[kMask + 2];
+ double f[kMask + 2];
+ };
+ static const Tables zg_;
+ random_internal::FastUniformBits<uint64_t> fast_u64_;
+};
+
+} // namespace random_internal
+
+// absl::gaussian_distribution:
+// Generates a number conforming to a Gaussian distribution.
+template <typename RealType = double>
+class gaussian_distribution : random_internal::gaussian_distribution_base {
+ public:
+ using result_type = RealType;
+
+ class param_type {
+ public:
+ using distribution_type = gaussian_distribution;
+
+ explicit param_type(result_type mean = 0, result_type stddev = 1)
+ : mean_(mean), stddev_(stddev) {}
+
+ // Returns the mean distribution parameter. The mean specifies the location
+ // of the peak. The default value is 0.0.
+ result_type mean() const { return mean_; }
+
+ // Returns the deviation distribution parameter. The default value is 1.0.
+ result_type stddev() const { return stddev_; }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.mean_ == b.mean_ && a.stddev_ == b.stddev_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ result_type mean_;
+ result_type stddev_;
+
+ static_assert(
+ std::is_floating_point<RealType>::value,
+ "Class-template absl::gaussian_distribution<> must be parameterized "
+ "using a floating-point type.");
+ };
+
+ gaussian_distribution() : gaussian_distribution(0) {}
+
+ explicit gaussian_distribution(result_type mean, result_type stddev = 1)
+ : param_(mean, stddev) {}
+
+ explicit gaussian_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 -std::numeric_limits<result_type>::infinity();
+ }
+ result_type(max)() const {
+ return std::numeric_limits<result_type>::infinity();
+ }
+
+ result_type mean() const { return param_.mean(); }
+ result_type stddev() const { return param_.stddev(); }
+
+ friend bool operator==(const gaussian_distribution& a,
+ const gaussian_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const gaussian_distribution& a,
+ const gaussian_distribution& b) {
+ return a.param_ != b.param_;
+ }
+
+ private:
+ param_type param_;
+};
+
+// --------------------------------------------------------------------------
+// Implementation details only below
+// --------------------------------------------------------------------------
+
+template <typename RealType>
+template <typename URBG>
+typename gaussian_distribution<RealType>::result_type
+gaussian_distribution<RealType>::operator()(
+ URBG& g, // NOLINT(runtime/references)
+ const param_type& p) {
+ return p.mean() + p.stddev() * static_cast<result_type>(zignor(g));
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ const gaussian_distribution<RealType>& x) {
+ auto saver = random_internal::make_ostream_state_saver(os);
+ os.precision(random_internal::stream_precision_helper<RealType>::kPrecision);
+ os << x.mean() << os.fill() << x.stddev();
+ return os;
+}
+
+template <typename CharT, typename Traits, typename RealType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ gaussian_distribution<RealType>& x) { // NOLINT(runtime/references)
+ using result_type = typename gaussian_distribution<RealType>::result_type;
+ using param_type = typename gaussian_distribution<RealType>::param_type;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ auto mean = random_internal::read_floating_point<result_type>(is);
+ if (is.fail()) return is;
+ auto stddev = random_internal::read_floating_point<result_type>(is);
+ if (!is.fail()) {
+ x.param(param_type(mean, stddev));
+ }
+ return is;
+}
+
+namespace random_internal {
+
+template <typename URBG>
+inline double gaussian_distribution_base::zignor_fallback(URBG& g, bool neg) {
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+
+ // This fallback path happens approximately 0.05% of the time.
+ double x, y;
+ do {
+ // kRInv = 1/r, U(0, 1)
+ x = kRInv *
+ std::log(GenerateRealFromBits<double, GeneratePositiveTag, false>(
+ fast_u64_(g)));
+ y = -std::log(
+ GenerateRealFromBits<double, GeneratePositiveTag, false>(fast_u64_(g)));
+ } while ((y + y) < (x * x));
+ return neg ? (x - kR) : (kR - x);
+}
+
+template <typename URBG>
+inline double gaussian_distribution_base::zignor(
+ URBG& g) { // NOLINT(runtime/references)
+ using random_internal::GeneratePositiveTag;
+ using random_internal::GenerateRealFromBits;
+ using random_internal::GenerateSignedTag;
+
+ while (true) {
+ // We use a single uint64_t to generate both a double and a strip.
+ // These bits are unused when the generated double is > 1/2^5.
+ // This may introduce some bias from the duplicated low bits of small
+ // values (those smaller than 1/2^5, which all end up on the left tail).
+ uint64_t bits = fast_u64_(g);
+ int i = static_cast<int>(bits & kMask); // pick a random strip
+ double j = GenerateRealFromBits<double, GenerateSignedTag, false>(
+ bits); // U(-1, 1)
+ const double x = j * zg_.x[i];
+
+ // Retangular box. Handles >97% of all cases.
+ // For any given box, this handles between 75% and 99% of values.
+ // Equivalent to U(01) < (x[i+1] / x[i]), and when i == 0, ~93.5%
+ if (std::abs(x) < zg_.x[i + 1]) {
+ return x;
+ }
+
+ // i == 0: Base box. Sample using a ratio of uniforms.
+ if (i == 0) {
+ // This path happens about 0.05% of the time.
+ return zignor_fallback(g, j < 0);
+ }
+
+ // i > 0: Wedge samples using precomputed values.
+ double v = GenerateRealFromBits<double, GeneratePositiveTag, false>(
+ fast_u64_(g)); // U(0, 1)
+ if ((zg_.f[i + 1] + v * (zg_.f[i] - zg_.f[i + 1])) <
+ std::exp(-0.5 * x * x)) {
+ return x;
+ }
+
+ // The wedge was missed; reject the value and try again.
+ }
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_GAUSSIAN_DISTRIBUTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution_test.cc
new file mode 100644
index 00000000000..c0bac2b0dbe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/gaussian_distribution_test.cc
@@ -0,0 +1,563 @@
+// 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.
+
+#include "absl/random/gaussian_distribution.h"
+
+#include <algorithm>
+#include <cmath>
+#include <cstddef>
+#include <ios>
+#include <iterator>
+#include <random>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/numeric/internal/representation.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+using absl::random_internal::kChiSquared;
+
+template <typename RealType>
+class GaussianDistributionInterfaceTest : public ::testing::Test {};
+
+// double-double arithmetic is not supported well by either GCC or Clang; see
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,
+// https://bugs.llvm.org/show_bug.cgi?id=49131, and
+// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests
+// with double doubles until compiler support is better.
+using RealTypes =
+ std::conditional<absl::numeric_internal::IsDoubleDouble(),
+ ::testing::Types<float, double>,
+ ::testing::Types<float, double, long double>>::type;
+TYPED_TEST_CASE(GaussianDistributionInterfaceTest, RealTypes);
+
+TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) {
+ using param_type =
+ typename absl::gaussian_distribution<TypeParam>::param_type;
+
+ const TypeParam kParams[] = {
+ // Cases around 1.
+ 1, //
+ std::nextafter(TypeParam(1), TypeParam(0)), // 1 - epsilon
+ std::nextafter(TypeParam(1), TypeParam(2)), // 1 + epsilon
+ // Arbitrary values.
+ TypeParam(1e-8), TypeParam(1e-4), TypeParam(2), TypeParam(1e4),
+ TypeParam(1e8), TypeParam(1e20), TypeParam(2.5),
+ // Boundary cases.
+ std::numeric_limits<TypeParam>::infinity(),
+ std::numeric_limits<TypeParam>::max(),
+ std::numeric_limits<TypeParam>::epsilon(),
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(1)), // min + epsilon
+ std::numeric_limits<TypeParam>::min(), // smallest normal
+ // There are some errors dealing with denorms on apple platforms.
+ std::numeric_limits<TypeParam>::denorm_min(), // smallest denorm
+ std::numeric_limits<TypeParam>::min() / 2,
+ std::nextafter(std::numeric_limits<TypeParam>::min(),
+ TypeParam(0)), // denorm_max
+ };
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+
+ // Use a loop to generate the combinations of {+/-x, +/-y}, and assign x, y to
+ // all values in kParams,
+ for (const auto mod : {0, 1, 2, 3}) {
+ for (const auto x : kParams) {
+ if (!std::isfinite(x)) continue;
+ for (const auto y : kParams) {
+ const TypeParam mean = (mod & 0x1) ? -x : x;
+ const TypeParam stddev = (mod & 0x2) ? -y : y;
+ const param_type param(mean, stddev);
+
+ absl::gaussian_distribution<TypeParam> before(mean, stddev);
+ EXPECT_EQ(before.mean(), param.mean());
+ EXPECT_EQ(before.stddev(), param.stddev());
+
+ {
+ absl::gaussian_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ EXPECT_EQ(via_param.param(), before.param());
+ }
+
+ // Smoke test.
+ auto sample_min = before.max();
+ auto sample_max = before.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = before(gen);
+ if (sample > sample_max) sample_max = sample;
+ if (sample < sample_min) sample_min = sample;
+ EXPECT_GE(sample, before.min()) << before;
+ EXPECT_LE(sample, before.max()) << before;
+ }
+ if (!std::is_same<TypeParam, long double>::value) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("Range{%f, %f}: %f, %f", mean, stddev,
+ sample_min, sample_max));
+ }
+
+ std::stringstream ss;
+ ss << before;
+
+ if (!std::isfinite(mean) || !std::isfinite(stddev)) {
+ // Streams do not parse inf/nan.
+ continue;
+ }
+
+ // Validate stream serialization.
+ absl::gaussian_distribution<TypeParam> after(-0.53f, 2.3456f);
+
+ EXPECT_NE(before.mean(), after.mean());
+ EXPECT_NE(before.stddev(), after.stddev());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.mean(), after.mean());
+ EXPECT_EQ(before.stddev(), after.stddev()) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+ }
+ }
+ }
+}
+
+// http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm
+
+class GaussianModel {
+ public:
+ GaussianModel(double mean, double stddev) : mean_(mean), stddev_(stddev) {}
+
+ double mean() const { return mean_; }
+ double variance() const { return stddev() * stddev(); }
+ double stddev() const { return stddev_; }
+ double skew() const { return 0; }
+ double kurtosis() const { return 3.0; }
+
+ // The inverse CDF, or PercentPoint function.
+ double InverseCDF(double p) {
+ ABSL_ASSERT(p >= 0.0);
+ ABSL_ASSERT(p < 1.0);
+ return mean() + stddev() * -absl::random_internal::InverseNormalSurvival(p);
+ }
+
+ private:
+ const double mean_;
+ const double stddev_;
+};
+
+struct Param {
+ double mean;
+ double stddev;
+ double p_fail; // Z-Test probability of failure.
+ int trials; // Z-Test trials.
+};
+
+// GaussianDistributionTests implements a z-test for the gaussian
+// distribution.
+class GaussianDistributionTests : public testing::TestWithParam<Param>,
+ public GaussianModel {
+ public:
+ GaussianDistributionTests()
+ : GaussianModel(GetParam().mean, GetParam().stddev) {}
+
+ // SingleZTest provides a basic z-squared test of the mean vs. expected
+ // mean for data generated by the poisson distribution.
+ template <typename D>
+ bool SingleZTest(const double p, const size_t samples);
+
+ // SingleChiSquaredTest provides a basic chi-squared test of the normal
+ // distribution.
+ template <typename D>
+ double SingleChiSquaredTest();
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+template <typename D>
+bool GaussianDistributionTests::SingleZTest(const double p,
+ const size_t samples) {
+ D dis(mean(), stddev());
+
+ std::vector<double> data;
+ data.reserve(samples);
+ for (size_t i = 0; i < samples; i++) {
+ const double x = dis(rng_);
+ data.push_back(x);
+ }
+
+ const double max_err = absl::random_internal::MaxErrorTolerance(p);
+ const auto m = absl::random_internal::ComputeDistributionMoments(data);
+ const double z = absl::random_internal::ZScore(mean(), m);
+ const bool pass = absl::random_internal::Near("z", z, 0.0, max_err);
+
+ // NOTE: Informational statistical test:
+ //
+ // Compute the Jarque-Bera test statistic given the excess skewness
+ // and kurtosis. The statistic is drawn from a chi-square(2) distribution.
+ // https://en.wikipedia.org/wiki/Jarque%E2%80%93Bera_test
+ //
+ // The null-hypothesis (normal distribution) is rejected when
+ // (p = 0.05 => jb > 5.99)
+ // (p = 0.01 => jb > 9.21)
+ // NOTE: JB has a large type-I error rate, so it will reject the
+ // null-hypothesis even when it is true more often than the z-test.
+ //
+ const double jb =
+ static_cast<double>(m.n) / 6.0 *
+ (std::pow(m.skewness, 2.0) + std::pow(m.kurtosis - 3.0, 2.0) / 4.0);
+
+ if (!pass || jb > 9.21) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("p=%f max_err=%f\n"
+ " mean=%f vs. %f\n"
+ " stddev=%f vs. %f\n"
+ " skewness=%f vs. %f\n"
+ " kurtosis=%f vs. %f\n"
+ " z=%f vs. 0\n"
+ " jb=%f vs. 9.21",
+ p, max_err, m.mean, mean(), std::sqrt(m.variance),
+ stddev(), m.skewness, skew(), m.kurtosis,
+ kurtosis(), z, jb));
+ }
+ return pass;
+}
+
+template <typename D>
+double GaussianDistributionTests::SingleChiSquaredTest() {
+ const size_t kSamples = 10000;
+ const int kBuckets = 50;
+
+ // The InverseCDF is the percent point function of the
+ // distribution, and can be used to assign buckets
+ // roughly uniformly.
+ std::vector<double> cutoffs;
+ const double kInc = 1.0 / static_cast<double>(kBuckets);
+ for (double p = kInc; p < 1.0; p += kInc) {
+ cutoffs.push_back(InverseCDF(p));
+ }
+ if (cutoffs.back() != std::numeric_limits<double>::infinity()) {
+ cutoffs.push_back(std::numeric_limits<double>::infinity());
+ }
+
+ D dis(mean(), stddev());
+
+ std::vector<int32_t> counts(cutoffs.size(), 0);
+ for (int j = 0; j < kSamples; j++) {
+ const double x = dis(rng_);
+ auto it = std::upper_bound(cutoffs.begin(), cutoffs.end(), x);
+ counts[std::distance(cutoffs.begin(), it)]++;
+ }
+
+ // Null-hypothesis is that the distribution is a gaussian distribution
+ // with the provided mean and stddev (not estimated from the data).
+ const int dof = static_cast<int>(counts.size()) - 1;
+
+ // Our threshold for logging is 1-in-50.
+ const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);
+
+ const double expected =
+ static_cast<double>(kSamples) / static_cast<double>(counts.size());
+
+ double chi_square = absl::random_internal::ChiSquareWithExpected(
+ std::begin(counts), std::end(counts), expected);
+ double p = absl::random_internal::ChiSquarePValue(chi_square, dof);
+
+ // Log if the chi_square value is above the threshold.
+ if (chi_square > threshold) {
+ for (int i = 0; i < cutoffs.size(); i++) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("%d : (%f) = %d", i, cutoffs[i], counts[i]));
+ }
+
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrCat("mean=", mean(), " stddev=", stddev(), "\n", //
+ " expected ", expected, "\n", //
+ kChiSquared, " ", chi_square, " (", p, ")\n", //
+ kChiSquared, " @ 0.98 = ", threshold));
+ }
+ return p;
+}
+
+TEST_P(GaussianDistributionTests, ZTest) {
+ // TODO(absl-team): Run these tests against std::normal_distribution<double>
+ // to validate outcomes are similar.
+ const size_t kSamples = 10000;
+ const auto& param = GetParam();
+ const int expected_failures =
+ std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));
+ const double p = absl::random_internal::RequiredSuccessProbability(
+ param.p_fail, param.trials);
+
+ int failures = 0;
+ for (int i = 0; i < param.trials; i++) {
+ failures +=
+ SingleZTest<absl::gaussian_distribution<double>>(p, kSamples) ? 0 : 1;
+ }
+ EXPECT_LE(failures, expected_failures);
+}
+
+TEST_P(GaussianDistributionTests, ChiSquaredTest) {
+ const int kTrials = 20;
+ int failures = 0;
+
+ for (int i = 0; i < kTrials; i++) {
+ double p_value =
+ SingleChiSquaredTest<absl::gaussian_distribution<double>>();
+ if (p_value < 0.0025) { // 1/400
+ failures++;
+ }
+ }
+ // There is a 0.05% chance of producing at least one failure, so raise the
+ // failure threshold high enough to allow for a flake rate of less than one in
+ // 10,000.
+ EXPECT_LE(failures, 4);
+}
+
+std::vector<Param> GenParams() {
+ return {
+ // Mean around 0.
+ Param{0.0, 1.0, 0.01, 100},
+ Param{0.0, 1e2, 0.01, 100},
+ Param{0.0, 1e4, 0.01, 100},
+ Param{0.0, 1e8, 0.01, 100},
+ Param{0.0, 1e16, 0.01, 100},
+ Param{0.0, 1e-3, 0.01, 100},
+ Param{0.0, 1e-5, 0.01, 100},
+ Param{0.0, 1e-9, 0.01, 100},
+ Param{0.0, 1e-17, 0.01, 100},
+
+ // Mean around 1.
+ Param{1.0, 1.0, 0.01, 100},
+ Param{1.0, 1e2, 0.01, 100},
+ Param{1.0, 1e-2, 0.01, 100},
+
+ // Mean around 100 / -100
+ Param{1e2, 1.0, 0.01, 100},
+ Param{-1e2, 1.0, 0.01, 100},
+ Param{1e2, 1e6, 0.01, 100},
+ Param{-1e2, 1e6, 0.01, 100},
+
+ // More extreme
+ Param{1e4, 1e4, 0.01, 100},
+ Param{1e8, 1e4, 0.01, 100},
+ Param{1e12, 1e4, 0.01, 100},
+ };
+}
+
+std::string ParamName(const ::testing::TestParamInfo<Param>& info) {
+ const auto& p = info.param;
+ std::string name = absl::StrCat("mean_", absl::SixDigits(p.mean), "__stddev_",
+ absl::SixDigits(p.stddev));
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_SUITE_P(All, GaussianDistributionTests,
+ ::testing::ValuesIn(GenParams()), ParamName);
+
+// NOTE: absl::gaussian_distribution is not guaranteed to be stable.
+TEST(GaussianDistributionTest, StabilityTest) {
+ // absl::gaussian_distribution stability relies on the underlying zignor
+ // data, absl::random_interna::RandU64ToDouble, std::exp, std::log, and
+ // std::abs.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(11);
+
+ {
+ absl::gaussian_distribution<double> dist;
+ std::generate(std::begin(output), std::end(output),
+ [&] { return static_cast<int>(10000000.0 * dist(urbg)); });
+
+ EXPECT_EQ(13, urbg.invocations());
+ EXPECT_THAT(output, //
+ testing::ElementsAre(1494, 25518841, 9991550, 1351856,
+ -20373238, 3456682, 333530, -6804981,
+ -15279580, -16459654, 1494));
+ }
+
+ urbg.reset();
+ {
+ absl::gaussian_distribution<float> dist;
+ std::generate(std::begin(output), std::end(output),
+ [&] { return static_cast<int>(1000000.0f * dist(urbg)); });
+
+ EXPECT_EQ(13, urbg.invocations());
+ EXPECT_THAT(
+ output, //
+ testing::ElementsAre(149, 2551884, 999155, 135185, -2037323, 345668,
+ 33353, -680498, -1527958, -1645965, 149));
+ }
+}
+
+// This is an implementation-specific test. If any part of the implementation
+// changes, then it is likely that this test will change as well.
+// Also, if dependencies of the distribution change, such as RandU64ToDouble,
+// then this is also likely to change.
+TEST(GaussianDistributionTest, AlgorithmBounds) {
+ absl::gaussian_distribution<double> dist;
+
+ // In ~95% of cases, a single value is used to generate the output.
+ // for all inputs where |x| < 0.750461021389 this should be the case.
+ //
+ // The exact constraints are based on the ziggurat tables, and any
+ // changes to the ziggurat tables may require adjusting these bounds.
+ //
+ // for i in range(0, len(X)-1):
+ // print i, X[i+1]/X[i], (X[i+1]/X[i] > 0.984375)
+ //
+ // 0.125 <= |values| <= 0.75
+ const uint64_t kValues[] = {
+ 0x1000000000000100ull, 0x2000000000000100ull, 0x3000000000000100ull,
+ 0x4000000000000100ull, 0x5000000000000100ull, 0x6000000000000100ull,
+ // negative values
+ 0x9000000000000100ull, 0xa000000000000100ull, 0xb000000000000100ull,
+ 0xc000000000000100ull, 0xd000000000000100ull, 0xe000000000000100ull};
+
+ // 0.875 <= |values| <= 0.984375
+ const uint64_t kExtraValues[] = {
+ 0x7000000000000100ull, 0x7800000000000100ull, //
+ 0x7c00000000000100ull, 0x7e00000000000100ull, //
+ // negative values
+ 0xf000000000000100ull, 0xf800000000000100ull, //
+ 0xfc00000000000100ull, 0xfe00000000000100ull};
+
+ auto make_box = [](uint64_t v, uint64_t box) {
+ return (v & 0xffffffffffffff80ull) | box;
+ };
+
+ // The box is the lower 7 bits of the value. When the box == 0, then
+ // the algorithm uses an escape hatch to select the result for large
+ // outputs.
+ for (uint64_t box = 0; box < 0x7f; box++) {
+ for (const uint64_t v : kValues) {
+ // Extra values are added to the sequence to attempt to avoid
+ // infinite loops from rejection sampling on bugs/errors.
+ absl::random_internal::sequence_urbg urbg(
+ {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull});
+
+ auto a = dist(urbg);
+ EXPECT_EQ(1, urbg.invocations()) << box << " " << std::hex << v;
+ if (v & 0x8000000000000000ull) {
+ EXPECT_LT(a, 0.0) << box << " " << std::hex << v;
+ } else {
+ EXPECT_GT(a, 0.0) << box << " " << std::hex << v;
+ }
+ }
+ if (box > 10 && box < 100) {
+ // The center boxes use the fast algorithm for more
+ // than 98.4375% of values.
+ for (const uint64_t v : kExtraValues) {
+ absl::random_internal::sequence_urbg urbg(
+ {make_box(v, box), 0x0003eb76f6f7f755ull, 0x5FCEA50FDB2F953Bull});
+
+ auto a = dist(urbg);
+ EXPECT_EQ(1, urbg.invocations()) << box << " " << std::hex << v;
+ if (v & 0x8000000000000000ull) {
+ EXPECT_LT(a, 0.0) << box << " " << std::hex << v;
+ } else {
+ EXPECT_GT(a, 0.0) << box << " " << std::hex << v;
+ }
+ }
+ }
+ }
+
+ // When the box == 0, the fallback algorithm uses a ratio of uniforms,
+ // which consumes 2 additional values from the urbg.
+ // Fallback also requires that the initial value be > 0.9271586026096681.
+ auto make_fallback = [](uint64_t v) { return (v & 0xffffffffffffff80ull); };
+
+ double tail[2];
+ {
+ // 0.9375
+ absl::random_internal::sequence_urbg urbg(
+ {make_fallback(0x7800000000000000ull), 0x13CCA830EB61BD96ull,
+ 0x00000076f6f7f755ull});
+ tail[0] = dist(urbg);
+ EXPECT_EQ(3, urbg.invocations());
+ EXPECT_GT(tail[0], 0);
+ }
+ {
+ // -0.9375
+ absl::random_internal::sequence_urbg urbg(
+ {make_fallback(0xf800000000000000ull), 0x13CCA830EB61BD96ull,
+ 0x00000076f6f7f755ull});
+ tail[1] = dist(urbg);
+ EXPECT_EQ(3, urbg.invocations());
+ EXPECT_LT(tail[1], 0);
+ }
+ EXPECT_EQ(tail[0], -tail[1]);
+ EXPECT_EQ(418610, static_cast<int64_t>(tail[0] * 100000.0));
+
+ // When the box != 0, the fallback algorithm computes a wedge function.
+ // Depending on the box, the threshold for varies as high as
+ // 0.991522480228.
+ {
+ // 0.9921875, 0.875
+ absl::random_internal::sequence_urbg urbg(
+ {make_box(0x7f00000000000000ull, 120), 0xe000000000000001ull,
+ 0x13CCA830EB61BD96ull});
+ tail[0] = dist(urbg);
+ EXPECT_EQ(2, urbg.invocations());
+ EXPECT_GT(tail[0], 0);
+ }
+ {
+ // -0.9921875, 0.875
+ absl::random_internal::sequence_urbg urbg(
+ {make_box(0xff00000000000000ull, 120), 0xe000000000000001ull,
+ 0x13CCA830EB61BD96ull});
+ tail[1] = dist(urbg);
+ EXPECT_EQ(2, urbg.invocations());
+ EXPECT_LT(tail[1], 0);
+ }
+ EXPECT_EQ(tail[0], -tail[1]);
+ EXPECT_EQ(61948, static_cast<int64_t>(tail[0] * 100000.0));
+
+ // Fallback rejected, try again.
+ {
+ // -0.9921875, 0.0625
+ absl::random_internal::sequence_urbg urbg(
+ {make_box(0xff00000000000000ull, 120), 0x1000000000000001,
+ make_box(0x1000000000000100ull, 50), 0x13CCA830EB61BD96ull});
+ dist(urbg);
+ EXPECT_EQ(3, urbg.invocations());
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/generators_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/generators_test.cc
new file mode 100644
index 00000000000..41725f139cd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/generators_test.cc
@@ -0,0 +1,179 @@
+// 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.
+
+#include <cstddef>
+#include <cstdint>
+#include <random>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
+
+namespace {
+
+template <typename URBG>
+void TestUniform(URBG* gen) {
+ // [a, b) default-semantics, inferred types.
+ absl::Uniform(*gen, 0, 100); // int
+ absl::Uniform(*gen, 0, 1.0); // Promoted to double
+ absl::Uniform(*gen, 0.0f, 1.0); // Promoted to double
+ absl::Uniform(*gen, 0.0, 1.0); // double
+ absl::Uniform(*gen, -1, 1L); // Promoted to long
+
+ // Roll a die.
+ absl::Uniform(absl::IntervalClosedClosed, *gen, 1, 6);
+
+ // Get a fraction.
+ absl::Uniform(absl::IntervalOpenOpen, *gen, 0.0, 1.0);
+
+ // Assign a value to a random element.
+ std::vector<int> elems = {10, 20, 30, 40, 50};
+ elems[absl::Uniform(*gen, 0u, elems.size())] = 5;
+ elems[absl::Uniform<size_t>(*gen, 0, elems.size())] = 3;
+
+ // Choose some epsilon around zero.
+ absl::Uniform(absl::IntervalOpenOpen, *gen, -1.0, 1.0);
+
+ // (a, b) semantics, inferred types.
+ absl::Uniform(absl::IntervalOpenOpen, *gen, 0, 1.0); // Promoted to double
+
+ // Explict overriding of types.
+ absl::Uniform<int>(*gen, 0, 100);
+ absl::Uniform<int8_t>(*gen, 0, 100);
+ absl::Uniform<int16_t>(*gen, 0, 100);
+ absl::Uniform<uint16_t>(*gen, 0, 100);
+ absl::Uniform<int32_t>(*gen, 0, 1 << 10);
+ absl::Uniform<uint32_t>(*gen, 0, 1 << 10);
+ absl::Uniform<int64_t>(*gen, 0, 1 << 10);
+ absl::Uniform<uint64_t>(*gen, 0, 1 << 10);
+
+ absl::Uniform<float>(*gen, 0.0, 1.0);
+ absl::Uniform<float>(*gen, 0, 1);
+ absl::Uniform<float>(*gen, -1, 1);
+ absl::Uniform<double>(*gen, 0.0, 1.0);
+
+ absl::Uniform<float>(*gen, -1.0, 0);
+ absl::Uniform<double>(*gen, -1.0, 0);
+
+ // Tagged
+ absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1);
+ absl::Uniform<double>(absl::IntervalClosedOpen, *gen, 0, 1);
+ absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1);
+ absl::Uniform<double>(absl::IntervalOpenClosed, *gen, 0, 1);
+ absl::Uniform<double>(absl::IntervalClosedClosed, *gen, 0, 1);
+ absl::Uniform<double>(absl::IntervalOpenOpen, *gen, 0, 1);
+
+ absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100);
+ absl::Uniform<int>(absl::IntervalClosedOpen, *gen, 0, 100);
+ absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100);
+ absl::Uniform<int>(absl::IntervalOpenClosed, *gen, 0, 100);
+ absl::Uniform<int>(absl::IntervalClosedClosed, *gen, 0, 100);
+ absl::Uniform<int>(absl::IntervalOpenOpen, *gen, 0, 100);
+
+ // With *generator as an R-value reference.
+ absl::Uniform<int>(URBG(), 0, 100);
+ absl::Uniform<double>(URBG(), 0.0, 1.0);
+}
+
+template <typename URBG>
+void TestExponential(URBG* gen) {
+ absl::Exponential<float>(*gen);
+ absl::Exponential<double>(*gen);
+ absl::Exponential<double>(URBG());
+}
+
+template <typename URBG>
+void TestPoisson(URBG* gen) {
+ // [rand.dist.pois] Indicates that the std::poisson_distribution
+ // is parameterized by IntType, however MSVC does not allow 8-bit
+ // types.
+ absl::Poisson<int>(*gen);
+ absl::Poisson<int16_t>(*gen);
+ absl::Poisson<uint16_t>(*gen);
+ absl::Poisson<int32_t>(*gen);
+ absl::Poisson<uint32_t>(*gen);
+ absl::Poisson<int64_t>(*gen);
+ absl::Poisson<uint64_t>(*gen);
+ absl::Poisson<uint64_t>(URBG());
+}
+
+template <typename URBG>
+void TestBernoulli(URBG* gen) {
+ absl::Bernoulli(*gen, 0.5);
+ absl::Bernoulli(*gen, 0.5);
+}
+
+template <typename URBG>
+void TestZipf(URBG* gen) {
+ absl::Zipf<int>(*gen, 100);
+ absl::Zipf<int8_t>(*gen, 100);
+ absl::Zipf<int16_t>(*gen, 100);
+ absl::Zipf<uint16_t>(*gen, 100);
+ absl::Zipf<int32_t>(*gen, 1 << 10);
+ absl::Zipf<uint32_t>(*gen, 1 << 10);
+ absl::Zipf<int64_t>(*gen, 1 << 10);
+ absl::Zipf<uint64_t>(*gen, 1 << 10);
+ absl::Zipf<uint64_t>(URBG(), 1 << 10);
+}
+
+template <typename URBG>
+void TestGaussian(URBG* gen) {
+ absl::Gaussian<float>(*gen, 1.0, 1.0);
+ absl::Gaussian<double>(*gen, 1.0, 1.0);
+ absl::Gaussian<double>(URBG(), 1.0, 1.0);
+}
+
+template <typename URBG>
+void TestLogNormal(URBG* gen) {
+ absl::LogUniform<int>(*gen, 0, 100);
+ absl::LogUniform<int8_t>(*gen, 0, 100);
+ absl::LogUniform<int16_t>(*gen, 0, 100);
+ absl::LogUniform<uint16_t>(*gen, 0, 100);
+ absl::LogUniform<int32_t>(*gen, 0, 1 << 10);
+ absl::LogUniform<uint32_t>(*gen, 0, 1 << 10);
+ absl::LogUniform<int64_t>(*gen, 0, 1 << 10);
+ absl::LogUniform<uint64_t>(*gen, 0, 1 << 10);
+ absl::LogUniform<uint64_t>(URBG(), 0, 1 << 10);
+}
+
+template <typename URBG>
+void CompatibilityTest() {
+ URBG gen;
+
+ TestUniform(&gen);
+ TestExponential(&gen);
+ TestPoisson(&gen);
+ TestBernoulli(&gen);
+ TestZipf(&gen);
+ TestGaussian(&gen);
+ TestLogNormal(&gen);
+}
+
+TEST(std_mt19937_64, Compatibility) {
+ // Validate with std::mt19937_64
+ CompatibilityTest<std::mt19937_64>();
+}
+
+TEST(BitGen, Compatibility) {
+ // Validate with absl::BitGen
+ CompatibilityTest<absl::BitGen>();
+}
+
+TEST(InsecureBitGen, Compatibility) {
+ // Validate with absl::InsecureBitGen
+ CompatibilityTest<absl::InsecureBitGen>();
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/BUILD.bazel
new file mode 100644
index 00000000000..612b1505aab
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/BUILD.bazel
@@ -0,0 +1,739 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+
+# Internal-only implementation classes for Abseil Random
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
+ "ABSL_RANDOM_RANDEN_COPTS",
+ "ABSL_TEST_COPTS",
+ "absl_random_randen_copts_init",
+)
+
+package(default_visibility = [
+ "//absl/random:__pkg__",
+])
+
+licenses(["notice"])
+
+cc_library(
+ name = "traits",
+ hdrs = ["traits.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "distribution_caller",
+ hdrs = ["distribution_caller.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:fast_type_id",
+ "//absl/utility",
+ ],
+)
+
+cc_library(
+ name = "fast_uniform_bits",
+ hdrs = [
+ "fast_uniform_bits.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
+ name = "seed_material",
+ srcs = [
+ "seed_material.cc",
+ ],
+ hdrs = [
+ "seed_material.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS + select({
+ "//absl:msvc_compiler": ["-DEFAULTLIB:bcrypt.lib"],
+ "//absl:clang-cl_compiler": ["-DEFAULTLIB:bcrypt.lib"],
+ "//conditions:default": [],
+ }),
+ deps = [
+ ":fast_uniform_bits",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ "//absl/types:optional",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "pool_urbg",
+ srcs = [
+ "pool_urbg.cc",
+ ],
+ hdrs = [
+ "pool_urbg.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = select({
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
+ "//absl:wasm": [],
+ "//conditions:default": ["-pthread"],
+ }) + ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":randen",
+ ":seed_material",
+ ":traits",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:endian",
+ "//absl/base:raw_logging_internal",
+ "//absl/random:seed_gen_exception",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "explicit_seed_seq",
+ testonly = 1,
+ hdrs = [
+ "explicit_seed_seq.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:endian",
+ ],
+)
+
+cc_library(
+ name = "sequence_urbg",
+ testonly = 1,
+ hdrs = [
+ "sequence_urbg.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "salted_seed_seq",
+ hdrs = [
+ "salted_seed_seq.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":seed_material",
+ "//absl/container:inlined_vector",
+ "//absl/meta:type_traits",
+ "//absl/types:optional",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "iostream_state_saver",
+ hdrs = ["iostream_state_saver.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/meta:type_traits",
+ "//absl/numeric:int128",
+ ],
+)
+
+cc_library(
+ name = "generate_real",
+ hdrs = [
+ "generate_real.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":fastmath",
+ ":traits",
+ "//absl/meta:type_traits",
+ "//absl/numeric:bits",
+ ],
+)
+
+cc_library(
+ name = "fastmath",
+ hdrs = [
+ "fastmath.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = ["//absl/numeric:bits"],
+)
+
+cc_library(
+ name = "wide_multiply",
+ hdrs = ["wide_multiply.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":traits",
+ "//absl/base:config",
+ "//absl/numeric:bits",
+ "//absl/numeric:int128",
+ ],
+)
+
+cc_library(
+ name = "nonsecure_base",
+ hdrs = ["nonsecure_base.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":pool_urbg",
+ ":salted_seed_seq",
+ ":seed_material",
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ "//absl/types:optional",
+ "//absl/types:span",
+ ],
+)
+
+cc_library(
+ name = "pcg_engine",
+ hdrs = ["pcg_engine.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":fastmath",
+ ":iostream_state_saver",
+ "//absl/base:config",
+ "//absl/meta:type_traits",
+ "//absl/numeric:bits",
+ "//absl/numeric:int128",
+ ],
+)
+
+cc_library(
+ name = "randen_engine",
+ hdrs = ["randen_engine.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":iostream_state_saver",
+ ":randen",
+ "//absl/base:endian",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
+ name = "platform",
+ srcs = [
+ "randen_round_keys.cc",
+ ],
+ hdrs = [
+ "randen_traits.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ textual_hdrs = [
+ "platform.h",
+ ],
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "randen",
+ srcs = [
+ "randen.cc",
+ ],
+ hdrs = [
+ "randen.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":platform",
+ ":randen_hwaes",
+ ":randen_slow",
+ "//absl/base:raw_logging_internal",
+ ],
+)
+
+cc_library(
+ name = "randen_slow",
+ srcs = ["randen_slow.cc"],
+ hdrs = ["randen_slow.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":platform",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+absl_random_randen_copts_init()
+
+cc_library(
+ name = "randen_hwaes",
+ srcs = [
+ "randen_detect.cc",
+ ],
+ hdrs = [
+ "randen_detect.h",
+ "randen_hwaes.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":platform",
+ ":randen_hwaes_impl",
+ "//absl/base:config",
+ ],
+)
+
+# build with --save_temps to see assembly language output.
+cc_library(
+ name = "randen_hwaes_impl",
+ srcs = [
+ "randen_hwaes.cc",
+ "randen_hwaes.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS + ABSL_RANDOM_RANDEN_COPTS + select({
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
+ "//conditions:default": ["-Wno-pass-failed"],
+ }),
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":platform",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ ],
+)
+
+cc_binary(
+ name = "gaussian_distribution_gentables",
+ srcs = [
+ "gaussian_distribution_gentables.cc",
+ ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:core_headers",
+ "//absl/random:distributions",
+ ],
+)
+
+cc_library(
+ name = "distribution_test_util",
+ testonly = 1,
+ srcs = [
+ "chi_square.cc",
+ "distribution_test_util.cc",
+ ],
+ hdrs = [
+ "chi_square.h",
+ "distribution_test_util.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ "//absl/strings:str_format",
+ "//absl/types:span",
+ ],
+)
+
+# Common tags for tests, etc.
+ABSL_RANDOM_NONPORTABLE_TAGS = [
+ "no_test_android_arm",
+ "no_test_android_arm64",
+ "no_test_android_x86",
+ "no_test_darwin_x86_64",
+ "no_test_ios_x86_64",
+ "no_test_loonix",
+ "no_test_msvc_x64",
+ "no_test_wasm",
+]
+
+cc_test(
+ name = "traits_test",
+ size = "small",
+ srcs = ["traits_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":traits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "generate_real_test",
+ size = "small",
+ srcs = [
+ "generate_real_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":generate_real",
+ "//absl/flags:flag",
+ "//absl/numeric:bits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "distribution_test_util_test",
+ size = "small",
+ srcs = ["distribution_test_util_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distribution_test_util",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "fastmath_test",
+ size = "small",
+ srcs = ["fastmath_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":fastmath",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "explicit_seed_seq_test",
+ size = "small",
+ srcs = ["explicit_seed_seq_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":explicit_seed_seq",
+ "//absl/random:seed_sequences",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "salted_seed_seq_test",
+ size = "small",
+ srcs = ["salted_seed_seq_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":salted_seed_seq",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "chi_square_test",
+ size = "small",
+ srcs = [
+ "chi_square_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":distribution_test_util",
+ "//absl/base:core_headers",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "fast_uniform_bits_test",
+ size = "small",
+ srcs = [
+ "fast_uniform_bits_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":fast_uniform_bits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "mock_helpers",
+ hdrs = ["mock_helpers.h"],
+ deps = [
+ "//absl/base:fast_type_id",
+ "//absl/types:optional",
+ ],
+)
+
+cc_library(
+ name = "mock_overload_set",
+ testonly = 1,
+ hdrs = ["mock_overload_set.h"],
+ deps = [
+ ":mock_helpers",
+ "//absl/random:mocking_bit_gen",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_test(
+ name = "nonsecure_base_test",
+ size = "small",
+ srcs = [
+ "nonsecure_base_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":nonsecure_base",
+ "//absl/random",
+ "//absl/random:distributions",
+ "//absl/random:seed_sequences",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "seed_material_test",
+ size = "small",
+ srcs = ["seed_material_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":seed_material",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "pool_urbg_test",
+ size = "small",
+ srcs = [
+ "pool_urbg_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":pool_urbg",
+ "//absl/meta:type_traits",
+ "//absl/types:span",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "pcg_engine_test",
+ size = "medium", # Trying to measure accuracy.
+ srcs = ["pcg_engine_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ flaky = 1,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":explicit_seed_seq",
+ ":pcg_engine",
+ "//absl/time",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "randen_engine_test",
+ size = "medium",
+ srcs = [
+ "randen_engine_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":explicit_seed_seq",
+ ":randen_engine",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ "//absl/time",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "randen_test",
+ size = "small",
+ srcs = ["randen_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":randen",
+ "//absl/meta:type_traits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "randen_slow_test",
+ size = "small",
+ srcs = ["randen_slow_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":platform",
+ ":randen_slow",
+ "//absl/base:endian",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "randen_hwaes_test",
+ size = "small",
+ srcs = ["randen_hwaes_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ABSL_RANDOM_NONPORTABLE_TAGS,
+ deps = [
+ ":platform",
+ ":randen_hwaes",
+ ":randen_hwaes_impl", # build_cleaner: keep
+ "//absl/base:raw_logging_internal",
+ "//absl/strings:str_format",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_test(
+ name = "wide_multiply_test",
+ size = "small",
+ srcs = ["wide_multiply_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":wide_multiply",
+ "//absl/numeric:bits",
+ "//absl/numeric:int128",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "nanobenchmark",
+ srcs = ["nanobenchmark.cc"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ textual_hdrs = ["nanobenchmark.h"],
+ deps = [
+ ":platform",
+ ":randen_engine",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ ],
+)
+
+cc_library(
+ name = "uniform_helper",
+ hdrs = ["uniform_helper.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":traits",
+ "//absl/base:config",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_test(
+ name = "nanobenchmark_test",
+ size = "small",
+ srcs = ["nanobenchmark_test.cc"],
+ flaky = 1,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = [
+ "benchmark",
+ "no_test_ios_x86_64",
+ "no_test_loonix", # Crashing.
+ ],
+ deps = [
+ ":nanobenchmark",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ ],
+)
+
+cc_test(
+ name = "randen_benchmarks",
+ size = "medium",
+ timeout = "long",
+ srcs = ["randen_benchmarks.cc"],
+ copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,
+ flaky = 1,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ tags = ABSL_RANDOM_NONPORTABLE_TAGS + ["benchmark"],
+ deps = [
+ ":nanobenchmark",
+ ":platform",
+ ":randen",
+ ":randen_engine",
+ ":randen_hwaes",
+ ":randen_hwaes_impl",
+ ":randen_slow",
+ "//absl/base:raw_logging_internal",
+ "//absl/strings",
+ ],
+)
+
+cc_test(
+ name = "iostream_state_saver_test",
+ size = "small",
+ srcs = ["iostream_state_saver_test.cc"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":iostream_state_saver",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "uniform_helper_test",
+ size = "small",
+ srcs = ["uniform_helper_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":uniform_helper",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.cc
new file mode 100644
index 00000000000..640d48cea6f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.cc
@@ -0,0 +1,232 @@
+// 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.
+
+#include "absl/random/internal/chi_square.h"
+
+#include <cmath>
+
+#include "absl/random/internal/distribution_test_util.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+#if defined(__EMSCRIPTEN__)
+// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found.
+inline double fma(double x, double y, double z) {
+ return (x * y) + z;
+}
+#endif
+
+// Use Horner's method to evaluate a polynomial.
+template <typename T, unsigned N>
+inline T EvaluatePolynomial(T x, const T (&poly)[N]) {
+#if !defined(__EMSCRIPTEN__)
+ using std::fma;
+#endif
+ T p = poly[N - 1];
+ for (unsigned i = 2; i <= N; i++) {
+ p = fma(p, x, poly[N - i]);
+ }
+ return p;
+}
+
+static constexpr int kLargeDOF = 150;
+
+// Returns the probability of a normal z-value.
+//
+// Adapted from the POZ function in:
+// Ibbetson D, Algorithm 209
+// Collected Algorithms of the CACM 1963 p. 616
+//
+double POZ(double z) {
+ static constexpr double kP1[] = {
+ 0.797884560593, -0.531923007300, 0.319152932694,
+ -0.151968751364, 0.059054035642, -0.019198292004,
+ 0.005198775019, -0.001075204047, 0.000124818987,
+ };
+ static constexpr double kP2[] = {
+ 0.999936657524, 0.000535310849, -0.002141268741, 0.005353579108,
+ -0.009279453341, 0.011630447319, -0.010557625006, 0.006549791214,
+ -0.002034254874, -0.000794620820, 0.001390604284, -0.000676904986,
+ -0.000019538132, 0.000152529290, -0.000045255659,
+ };
+
+ const double kZMax = 6.0; // Maximum meaningful z-value.
+ if (z == 0.0) {
+ return 0.5;
+ }
+ double x;
+ double y = 0.5 * std::fabs(z);
+ if (y >= (kZMax * 0.5)) {
+ x = 1.0;
+ } else if (y < 1.0) {
+ double w = y * y;
+ x = EvaluatePolynomial(w, kP1) * y * 2.0;
+ } else {
+ y -= 2.0;
+ x = EvaluatePolynomial(y, kP2);
+ }
+ return z > 0.0 ? ((x + 1.0) * 0.5) : ((1.0 - x) * 0.5);
+}
+
+// Approximates the survival function of the normal distribution.
+//
+// Algorithm 26.2.18, from:
+// [Abramowitz and Stegun, Handbook of Mathematical Functions,p.932]
+// http://people.math.sfu.ca/~cbm/aands/abramowitz_and_stegun.pdf
+//
+double normal_survival(double z) {
+ // Maybe replace with the alternate formulation.
+ // 0.5 * erfc((x - mean)/(sqrt(2) * sigma))
+ static constexpr double kR[] = {
+ 1.0, 0.196854, 0.115194, 0.000344, 0.019527,
+ };
+ double r = EvaluatePolynomial(z, kR);
+ r *= r;
+ return 0.5 / (r * r);
+}
+
+} // namespace
+
+// Calculates the critical chi-square value given degrees-of-freedom and a
+// p-value, usually using bisection. Also known by the name CRITCHI.
+double ChiSquareValue(int dof, double p) {
+ static constexpr double kChiEpsilon =
+ 0.000001; // Accuracy of the approximation.
+ static constexpr double kChiMax =
+ 99999.0; // Maximum chi-squared value.
+
+ const double p_value = 1.0 - p;
+ if (dof < 1 || p_value > 1.0) {
+ return 0.0;
+ }
+
+ if (dof > kLargeDOF) {
+ // For large degrees of freedom, use the normal approximation by
+ // Wilson, E. B. and Hilferty, M. M. (1931)
+ // chi^2 - mean
+ // Z = --------------
+ // stddev
+ const double z = InverseNormalSurvival(p_value);
+ const double mean = 1 - 2.0 / (9 * dof);
+ const double variance = 2.0 / (9 * dof);
+ // Cannot use this method if the variance is 0.
+ if (variance != 0) {
+ return std::pow(z * std::sqrt(variance) + mean, 3.0) * dof;
+ }
+ }
+
+ if (p_value <= 0.0) return kChiMax;
+
+ // Otherwise search for the p value by bisection
+ double min_chisq = 0.0;
+ double max_chisq = kChiMax;
+ double current = dof / std::sqrt(p_value);
+ while ((max_chisq - min_chisq) > kChiEpsilon) {
+ if (ChiSquarePValue(current, dof) < p_value) {
+ max_chisq = current;
+ } else {
+ min_chisq = current;
+ }
+ current = (max_chisq + min_chisq) * 0.5;
+ }
+ return current;
+}
+
+// Calculates the p-value (probability) of a given chi-square value
+// and degrees of freedom.
+//
+// Adapted from the POCHISQ function from:
+// Hill, I. D. and Pike, M. C. Algorithm 299
+// Collected Algorithms of the CACM 1963 p. 243
+//
+double ChiSquarePValue(double chi_square, int dof) {
+ static constexpr double kLogSqrtPi =
+ 0.5723649429247000870717135; // Log[Sqrt[Pi]]
+ static constexpr double kInverseSqrtPi =
+ 0.5641895835477562869480795; // 1/(Sqrt[Pi])
+
+ // For large degrees of freedom, use the normal approximation by
+ // Wilson, E. B. and Hilferty, M. M. (1931)
+ // Via Wikipedia:
+ // By the Central Limit Theorem, because the chi-square distribution is the
+ // sum of k independent random variables with finite mean and variance, it
+ // converges to a normal distribution for large k.
+ if (dof > kLargeDOF) {
+ // Re-scale everything.
+ const double chi_square_scaled = std::pow(chi_square / dof, 1.0 / 3);
+ const double mean = 1 - 2.0 / (9 * dof);
+ const double variance = 2.0 / (9 * dof);
+ // If variance is 0, this method cannot be used.
+ if (variance != 0) {
+ const double z = (chi_square_scaled - mean) / std::sqrt(variance);
+ if (z > 0) {
+ return normal_survival(z);
+ } else if (z < 0) {
+ return 1.0 - normal_survival(-z);
+ } else {
+ return 0.5;
+ }
+ }
+ }
+
+ // The chi square function is >= 0 for any degrees of freedom.
+ // In other words, probability that the chi square function >= 0 is 1.
+ if (chi_square <= 0.0) return 1.0;
+
+ // If the degrees of freedom is zero, the chi square function is always 0 by
+ // definition. In other words, the probability that the chi square function
+ // is > 0 is zero (chi square values <= 0 have been filtered above).
+ if (dof < 1) return 0;
+
+ auto capped_exp = [](double x) { return x < -20 ? 0.0 : std::exp(x); };
+ static constexpr double kBigX = 20;
+
+ double a = 0.5 * chi_square;
+ const bool even = !(dof & 1); // True if dof is an even number.
+ const double y = capped_exp(-a);
+ double s = even ? y : (2.0 * POZ(-std::sqrt(chi_square)));
+
+ if (dof <= 2) {
+ return s;
+ }
+
+ chi_square = 0.5 * (dof - 1.0);
+ double z = (even ? 1.0 : 0.5);
+ if (a > kBigX) {
+ double e = (even ? 0.0 : kLogSqrtPi);
+ double c = std::log(a);
+ while (z <= chi_square) {
+ e = std::log(z) + e;
+ s += capped_exp(c * z - a - e);
+ z += 1.0;
+ }
+ return s;
+ }
+
+ double e = (even ? 1.0 : (kInverseSqrtPi / std::sqrt(a)));
+ double c = 0.0;
+ while (z <= chi_square) {
+ e = e * (a / z);
+ c = c + e;
+ z += 1.0;
+ }
+ return c * y + s;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.h
new file mode 100644
index 00000000000..07f4fbe5229
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square.h
@@ -0,0 +1,89 @@
+// 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_CHI_SQUARE_H_
+#define ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_
+
+// The chi-square statistic.
+//
+// Useful for evaluating if `D` independent random variables are behaving as
+// expected, or if two distributions are similar. (`D` is the degrees of
+// freedom).
+//
+// Each bucket should have an expected count of 10 or more for the chi square to
+// be meaningful.
+
+#include <cassert>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+constexpr const char kChiSquared[] = "chi-squared";
+
+// Returns the measured chi square value, using a single expected value. This
+// assumes that the values in [begin, end) are uniformly distributed.
+template <typename Iterator>
+double ChiSquareWithExpected(Iterator begin, Iterator end, double expected) {
+ // Compute the sum and the number of buckets.
+ assert(expected >= 10); // require at least 10 samples per bucket.
+ double chi_square = 0;
+ for (auto it = begin; it != end; it++) {
+ double d = static_cast<double>(*it) - expected;
+ chi_square += d * d;
+ }
+ chi_square = chi_square / expected;
+ return chi_square;
+}
+
+// Returns the measured chi square value, taking the actual value of each bucket
+// from the first set of iterators, and the expected value of each bucket from
+// the second set of iterators.
+template <typename Iterator, typename Expected>
+double ChiSquare(Iterator it, Iterator end, Expected eit, Expected eend) {
+ double chi_square = 0;
+ for (; it != end && eit != eend; ++it, ++eit) {
+ if (*it > 0) {
+ assert(*eit > 0);
+ }
+ double e = static_cast<double>(*eit);
+ double d = static_cast<double>(*it - *eit);
+ if (d != 0) {
+ assert(e > 0);
+ chi_square += (d * d) / e;
+ }
+ }
+ assert(it == end && eit == eend);
+ return chi_square;
+}
+
+// ======================================================================
+// The following methods can be used for an arbitrary significance level.
+//
+
+// Calculates critical chi-square values to produce the given p-value using a
+// bisection search for a value within epsilon, relying on the monotonicity of
+// ChiSquarePValue().
+double ChiSquareValue(int dof, double p);
+
+// Calculates the p-value (probability) of a given chi-square value.
+double ChiSquarePValue(double chi_square, int dof);
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_CHI_SQUARE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square_test.cc
new file mode 100644
index 00000000000..5025defac12
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/chi_square_test.cc
@@ -0,0 +1,365 @@
+// 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.
+
+#include "absl/random/internal/chi_square.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <numeric>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/base/macros.h"
+
+using absl::random_internal::ChiSquare;
+using absl::random_internal::ChiSquarePValue;
+using absl::random_internal::ChiSquareValue;
+using absl::random_internal::ChiSquareWithExpected;
+
+namespace {
+
+TEST(ChiSquare, Value) {
+ struct {
+ int line;
+ double chi_square;
+ int df;
+ double confidence;
+ } const specs[] = {
+ // Testing lookup at 1% confidence
+ {__LINE__, 0, 0, 0.01},
+ {__LINE__, 0.00016, 1, 0.01},
+ {__LINE__, 1.64650, 8, 0.01},
+ {__LINE__, 5.81221, 16, 0.01},
+ {__LINE__, 156.4319, 200, 0.01},
+ {__LINE__, 1121.3784, 1234, 0.01},
+ {__LINE__, 53557.1629, 54321, 0.01},
+ {__LINE__, 651662.6647, 654321, 0.01},
+
+ // Testing lookup at 99% confidence
+ {__LINE__, 0, 0, 0.99},
+ {__LINE__, 6.635, 1, 0.99},
+ {__LINE__, 20.090, 8, 0.99},
+ {__LINE__, 32.000, 16, 0.99},
+ {__LINE__, 249.4456, 200, 0.99},
+ {__LINE__, 1131.1573, 1023, 0.99},
+ {__LINE__, 1352.5038, 1234, 0.99},
+ {__LINE__, 55090.7356, 54321, 0.99},
+ {__LINE__, 656985.1514, 654321, 0.99},
+
+ // Testing lookup at 99.9% confidence
+ {__LINE__, 16.2659, 3, 0.999},
+ {__LINE__, 22.4580, 6, 0.999},
+ {__LINE__, 267.5409, 200, 0.999},
+ {__LINE__, 1168.5033, 1023, 0.999},
+ {__LINE__, 55345.1741, 54321, 0.999},
+ {__LINE__, 657861.7284, 654321, 0.999},
+ {__LINE__, 51.1772, 24, 0.999},
+ {__LINE__, 59.7003, 30, 0.999},
+ {__LINE__, 37.6984, 15, 0.999},
+ {__LINE__, 29.5898, 10, 0.999},
+ {__LINE__, 27.8776, 9, 0.999},
+
+ // Testing lookup at random confidences
+ {__LINE__, 0.000157088, 1, 0.01},
+ {__LINE__, 5.31852, 2, 0.93},
+ {__LINE__, 1.92256, 4, 0.25},
+ {__LINE__, 10.7709, 13, 0.37},
+ {__LINE__, 26.2514, 17, 0.93},
+ {__LINE__, 36.4799, 29, 0.84},
+ {__LINE__, 25.818, 31, 0.27},
+ {__LINE__, 63.3346, 64, 0.50},
+ {__LINE__, 196.211, 128, 0.9999},
+ {__LINE__, 215.21, 243, 0.10},
+ {__LINE__, 285.393, 256, 0.90},
+ {__LINE__, 984.504, 1024, 0.1923},
+ {__LINE__, 2043.85, 2048, 0.4783},
+ {__LINE__, 48004.6, 48273, 0.194},
+ };
+ for (const auto& spec : specs) {
+ SCOPED_TRACE(spec.line);
+ // Verify all values are have at most a 1% relative error.
+ const double val = ChiSquareValue(spec.df, spec.confidence);
+ const double err = std::max(5e-6, spec.chi_square / 5e3); // 1 part in 5000
+ EXPECT_NEAR(spec.chi_square, val, err) << spec.line;
+ }
+
+ // Relaxed test for extreme values, from
+ // http://www.ciphersbyritter.com/JAVASCRP/NORMCHIK.HTM#ChiSquare
+ EXPECT_NEAR(49.2680, ChiSquareValue(100, 1e-6), 5); // 0.000'005 mark
+ EXPECT_NEAR(123.499, ChiSquareValue(200, 1e-6), 5); // 0.000'005 mark
+
+ EXPECT_NEAR(149.449, ChiSquareValue(100, 0.999), 0.01);
+ EXPECT_NEAR(161.318, ChiSquareValue(100, 0.9999), 0.01);
+ EXPECT_NEAR(172.098, ChiSquareValue(100, 0.99999), 0.01);
+
+ EXPECT_NEAR(381.426, ChiSquareValue(300, 0.999), 0.05);
+ EXPECT_NEAR(399.756, ChiSquareValue(300, 0.9999), 0.1);
+ EXPECT_NEAR(416.126, ChiSquareValue(300, 0.99999), 0.2);
+}
+
+TEST(ChiSquareTest, PValue) {
+ struct {
+ int line;
+ double pval;
+ double chi_square;
+ int df;
+ } static const specs[] = {
+ {__LINE__, 1, 0, 0},
+ {__LINE__, 0, 0.001, 0},
+ {__LINE__, 1.000, 0, 453},
+ {__LINE__, 0.134471, 7972.52, 7834},
+ {__LINE__, 0.203922, 28.32, 23},
+ {__LINE__, 0.737171, 48274, 48472},
+ {__LINE__, 0.444146, 583.1234, 579},
+ {__LINE__, 0.294814, 138.2, 130},
+ {__LINE__, 0.0816532, 12.63, 7},
+ {__LINE__, 0, 682.32, 67},
+ {__LINE__, 0.49405, 999, 999},
+ {__LINE__, 1.000, 0, 9999},
+ {__LINE__, 0.997477, 0.00001, 1},
+ {__LINE__, 0, 5823.21, 5040},
+ };
+ for (const auto& spec : specs) {
+ SCOPED_TRACE(spec.line);
+ const double pval = ChiSquarePValue(spec.chi_square, spec.df);
+ EXPECT_NEAR(spec.pval, pval, 1e-3);
+ }
+}
+
+TEST(ChiSquareTest, CalcChiSquare) {
+ struct {
+ int line;
+ std::vector<int> expected;
+ std::vector<int> actual;
+ } const specs[] = {
+ {__LINE__,
+ {56, 234, 76, 1, 546, 1, 87, 345, 1, 234},
+ {2, 132, 4, 43, 234, 8, 345, 8, 236, 56}},
+ {__LINE__,
+ {123, 36, 234, 367, 345, 2, 456, 567, 234, 567},
+ {123, 56, 2345, 8, 345, 8, 2345, 23, 48, 267}},
+ {__LINE__,
+ {123, 234, 345, 456, 567, 678, 789, 890, 98, 76},
+ {123, 234, 345, 456, 567, 678, 789, 890, 98, 76}},
+ {__LINE__, {3, 675, 23, 86, 2, 8, 2}, {456, 675, 23, 86, 23, 65, 2}},
+ {__LINE__, {1}, {23}},
+ };
+ for (const auto& spec : specs) {
+ SCOPED_TRACE(spec.line);
+ double chi_square = 0;
+ for (int i = 0; i < spec.expected.size(); ++i) {
+ const double diff = spec.actual[i] - spec.expected[i];
+ chi_square += (diff * diff) / spec.expected[i];
+ }
+ EXPECT_NEAR(chi_square,
+ ChiSquare(std::begin(spec.actual), std::end(spec.actual),
+ std::begin(spec.expected), std::end(spec.expected)),
+ 1e-5);
+ }
+}
+
+TEST(ChiSquareTest, CalcChiSquareInt64) {
+ const int64_t data[3] = {910293487, 910292491, 910216780};
+ // $ python -c "import scipy.stats
+ // > print scipy.stats.chisquare([910293487, 910292491, 910216780])[0]"
+ // 4.25410123524
+ double sum = std::accumulate(std::begin(data), std::end(data), double{0});
+ size_t n = std::distance(std::begin(data), std::end(data));
+ double a = ChiSquareWithExpected(std::begin(data), std::end(data), sum / n);
+ EXPECT_NEAR(4.254101, a, 1e-6);
+
+ // ... Or with known values.
+ double b =
+ ChiSquareWithExpected(std::begin(data), std::end(data), 910267586.0);
+ EXPECT_NEAR(4.254101, b, 1e-6);
+}
+
+TEST(ChiSquareTest, TableData) {
+ // Test data from
+ // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3674.htm
+ // 0.90 0.95 0.975 0.99 0.999
+ const double data[100][5] = {
+ /* 1*/ {2.706, 3.841, 5.024, 6.635, 10.828},
+ /* 2*/ {4.605, 5.991, 7.378, 9.210, 13.816},
+ /* 3*/ {6.251, 7.815, 9.348, 11.345, 16.266},
+ /* 4*/ {7.779, 9.488, 11.143, 13.277, 18.467},
+ /* 5*/ {9.236, 11.070, 12.833, 15.086, 20.515},
+ /* 6*/ {10.645, 12.592, 14.449, 16.812, 22.458},
+ /* 7*/ {12.017, 14.067, 16.013, 18.475, 24.322},
+ /* 8*/ {13.362, 15.507, 17.535, 20.090, 26.125},
+ /* 9*/ {14.684, 16.919, 19.023, 21.666, 27.877},
+ /*10*/ {15.987, 18.307, 20.483, 23.209, 29.588},
+ /*11*/ {17.275, 19.675, 21.920, 24.725, 31.264},
+ /*12*/ {18.549, 21.026, 23.337, 26.217, 32.910},
+ /*13*/ {19.812, 22.362, 24.736, 27.688, 34.528},
+ /*14*/ {21.064, 23.685, 26.119, 29.141, 36.123},
+ /*15*/ {22.307, 24.996, 27.488, 30.578, 37.697},
+ /*16*/ {23.542, 26.296, 28.845, 32.000, 39.252},
+ /*17*/ {24.769, 27.587, 30.191, 33.409, 40.790},
+ /*18*/ {25.989, 28.869, 31.526, 34.805, 42.312},
+ /*19*/ {27.204, 30.144, 32.852, 36.191, 43.820},
+ /*20*/ {28.412, 31.410, 34.170, 37.566, 45.315},
+ /*21*/ {29.615, 32.671, 35.479, 38.932, 46.797},
+ /*22*/ {30.813, 33.924, 36.781, 40.289, 48.268},
+ /*23*/ {32.007, 35.172, 38.076, 41.638, 49.728},
+ /*24*/ {33.196, 36.415, 39.364, 42.980, 51.179},
+ /*25*/ {34.382, 37.652, 40.646, 44.314, 52.620},
+ /*26*/ {35.563, 38.885, 41.923, 45.642, 54.052},
+ /*27*/ {36.741, 40.113, 43.195, 46.963, 55.476},
+ /*28*/ {37.916, 41.337, 44.461, 48.278, 56.892},
+ /*29*/ {39.087, 42.557, 45.722, 49.588, 58.301},
+ /*30*/ {40.256, 43.773, 46.979, 50.892, 59.703},
+ /*31*/ {41.422, 44.985, 48.232, 52.191, 61.098},
+ /*32*/ {42.585, 46.194, 49.480, 53.486, 62.487},
+ /*33*/ {43.745, 47.400, 50.725, 54.776, 63.870},
+ /*34*/ {44.903, 48.602, 51.966, 56.061, 65.247},
+ /*35*/ {46.059, 49.802, 53.203, 57.342, 66.619},
+ /*36*/ {47.212, 50.998, 54.437, 58.619, 67.985},
+ /*37*/ {48.363, 52.192, 55.668, 59.893, 69.347},
+ /*38*/ {49.513, 53.384, 56.896, 61.162, 70.703},
+ /*39*/ {50.660, 54.572, 58.120, 62.428, 72.055},
+ /*40*/ {51.805, 55.758, 59.342, 63.691, 73.402},
+ /*41*/ {52.949, 56.942, 60.561, 64.950, 74.745},
+ /*42*/ {54.090, 58.124, 61.777, 66.206, 76.084},
+ /*43*/ {55.230, 59.304, 62.990, 67.459, 77.419},
+ /*44*/ {56.369, 60.481, 64.201, 68.710, 78.750},
+ /*45*/ {57.505, 61.656, 65.410, 69.957, 80.077},
+ /*46*/ {58.641, 62.830, 66.617, 71.201, 81.400},
+ /*47*/ {59.774, 64.001, 67.821, 72.443, 82.720},
+ /*48*/ {60.907, 65.171, 69.023, 73.683, 84.037},
+ /*49*/ {62.038, 66.339, 70.222, 74.919, 85.351},
+ /*50*/ {63.167, 67.505, 71.420, 76.154, 86.661},
+ /*51*/ {64.295, 68.669, 72.616, 77.386, 87.968},
+ /*52*/ {65.422, 69.832, 73.810, 78.616, 89.272},
+ /*53*/ {66.548, 70.993, 75.002, 79.843, 90.573},
+ /*54*/ {67.673, 72.153, 76.192, 81.069, 91.872},
+ /*55*/ {68.796, 73.311, 77.380, 82.292, 93.168},
+ /*56*/ {69.919, 74.468, 78.567, 83.513, 94.461},
+ /*57*/ {71.040, 75.624, 79.752, 84.733, 95.751},
+ /*58*/ {72.160, 76.778, 80.936, 85.950, 97.039},
+ /*59*/ {73.279, 77.931, 82.117, 87.166, 98.324},
+ /*60*/ {74.397, 79.082, 83.298, 88.379, 99.607},
+ /*61*/ {75.514, 80.232, 84.476, 89.591, 100.888},
+ /*62*/ {76.630, 81.381, 85.654, 90.802, 102.166},
+ /*63*/ {77.745, 82.529, 86.830, 92.010, 103.442},
+ /*64*/ {78.860, 83.675, 88.004, 93.217, 104.716},
+ /*65*/ {79.973, 84.821, 89.177, 94.422, 105.988},
+ /*66*/ {81.085, 85.965, 90.349, 95.626, 107.258},
+ /*67*/ {82.197, 87.108, 91.519, 96.828, 108.526},
+ /*68*/ {83.308, 88.250, 92.689, 98.028, 109.791},
+ /*69*/ {84.418, 89.391, 93.856, 99.228, 111.055},
+ /*70*/ {85.527, 90.531, 95.023, 100.425, 112.317},
+ /*71*/ {86.635, 91.670, 96.189, 101.621, 113.577},
+ /*72*/ {87.743, 92.808, 97.353, 102.816, 114.835},
+ /*73*/ {88.850, 93.945, 98.516, 104.010, 116.092},
+ /*74*/ {89.956, 95.081, 99.678, 105.202, 117.346},
+ /*75*/ {91.061, 96.217, 100.839, 106.393, 118.599},
+ /*76*/ {92.166, 97.351, 101.999, 107.583, 119.850},
+ /*77*/ {93.270, 98.484, 103.158, 108.771, 121.100},
+ /*78*/ {94.374, 99.617, 104.316, 109.958, 122.348},
+ /*79*/ {95.476, 100.749, 105.473, 111.144, 123.594},
+ /*80*/ {96.578, 101.879, 106.629, 112.329, 124.839},
+ /*81*/ {97.680, 103.010, 107.783, 113.512, 126.083},
+ /*82*/ {98.780, 104.139, 108.937, 114.695, 127.324},
+ /*83*/ {99.880, 105.267, 110.090, 115.876, 128.565},
+ /*84*/ {100.980, 106.395, 111.242, 117.057, 129.804},
+ /*85*/ {102.079, 107.522, 112.393, 118.236, 131.041},
+ /*86*/ {103.177, 108.648, 113.544, 119.414, 132.277},
+ /*87*/ {104.275, 109.773, 114.693, 120.591, 133.512},
+ /*88*/ {105.372, 110.898, 115.841, 121.767, 134.746},
+ /*89*/ {106.469, 112.022, 116.989, 122.942, 135.978},
+ /*90*/ {107.565, 113.145, 118.136, 124.116, 137.208},
+ /*91*/ {108.661, 114.268, 119.282, 125.289, 138.438},
+ /*92*/ {109.756, 115.390, 120.427, 126.462, 139.666},
+ /*93*/ {110.850, 116.511, 121.571, 127.633, 140.893},
+ /*94*/ {111.944, 117.632, 122.715, 128.803, 142.119},
+ /*95*/ {113.038, 118.752, 123.858, 129.973, 143.344},
+ /*96*/ {114.131, 119.871, 125.000, 131.141, 144.567},
+ /*97*/ {115.223, 120.990, 126.141, 132.309, 145.789},
+ /*98*/ {116.315, 122.108, 127.282, 133.476, 147.010},
+ /*99*/ {117.407, 123.225, 128.422, 134.642, 148.230},
+ /*100*/ {118.498, 124.342, 129.561, 135.807, 149.449}
+ /**/};
+
+ // 0.90 0.95 0.975 0.99 0.999
+ for (int i = 0; i < ABSL_ARRAYSIZE(data); i++) {
+ const double E = 0.0001;
+ EXPECT_NEAR(ChiSquarePValue(data[i][0], i + 1), 0.10, E)
+ << i << " " << data[i][0];
+ EXPECT_NEAR(ChiSquarePValue(data[i][1], i + 1), 0.05, E)
+ << i << " " << data[i][1];
+ EXPECT_NEAR(ChiSquarePValue(data[i][2], i + 1), 0.025, E)
+ << i << " " << data[i][2];
+ EXPECT_NEAR(ChiSquarePValue(data[i][3], i + 1), 0.01, E)
+ << i << " " << data[i][3];
+ EXPECT_NEAR(ChiSquarePValue(data[i][4], i + 1), 0.001, E)
+ << i << " " << data[i][4];
+
+ const double F = 0.1;
+ EXPECT_NEAR(ChiSquareValue(i + 1, 0.90), data[i][0], F) << i;
+ EXPECT_NEAR(ChiSquareValue(i + 1, 0.95), data[i][1], F) << i;
+ EXPECT_NEAR(ChiSquareValue(i + 1, 0.975), data[i][2], F) << i;
+ EXPECT_NEAR(ChiSquareValue(i + 1, 0.99), data[i][3], F) << i;
+ EXPECT_NEAR(ChiSquareValue(i + 1, 0.999), data[i][4], F) << i;
+ }
+}
+
+TEST(ChiSquareTest, ChiSquareTwoIterator) {
+ // Test data from http://www.stat.yale.edu/Courses/1997-98/101/chigf.htm
+ // Null-hypothesis: This data is normally distributed.
+ const int counts[10] = {6, 6, 18, 33, 38, 38, 28, 21, 9, 3};
+ const double expected[10] = {4.6, 8.8, 18.4, 30.0, 38.2,
+ 38.2, 30.0, 18.4, 8.8, 4.6};
+ double chi_square = ChiSquare(std::begin(counts), std::end(counts),
+ std::begin(expected), std::end(expected));
+ EXPECT_NEAR(chi_square, 2.69, 0.001);
+
+ // Degrees of freedom: 10 bins. two estimated parameters. = 10 - 2 - 1.
+ const int dof = 7;
+ // The critical value of 7, 95% => 14.067 (see above test)
+ double p_value_05 = ChiSquarePValue(14.067, dof);
+ EXPECT_NEAR(p_value_05, 0.05, 0.001); // 95%-ile p-value
+
+ double p_actual = ChiSquarePValue(chi_square, dof);
+ EXPECT_GT(p_actual, 0.05); // Accept the null hypothesis.
+}
+
+TEST(ChiSquareTest, DiceRolls) {
+ // Assume we are testing 102 fair dice rolls.
+ // Null-hypothesis: This data is fairly distributed.
+ //
+ // The dof value of 4, @95% = 9.488 (see above test)
+ // The dof value of 5, @95% = 11.070
+ const int rolls[6] = {22, 11, 17, 14, 20, 18};
+ double sum = std::accumulate(std::begin(rolls), std::end(rolls), double{0});
+ size_t n = std::distance(std::begin(rolls), std::end(rolls));
+
+ double a = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), sum / n);
+ EXPECT_NEAR(a, 4.70588, 1e-5);
+ EXPECT_LT(a, ChiSquareValue(4, 0.95));
+
+ double p_a = ChiSquarePValue(a, 4);
+ EXPECT_NEAR(p_a, 0.318828, 1e-5); // Accept the null hypothesis.
+
+ double b = ChiSquareWithExpected(std::begin(rolls), std::end(rolls), 17.0);
+ EXPECT_NEAR(b, 4.70588, 1e-5);
+ EXPECT_LT(b, ChiSquareValue(5, 0.95));
+
+ double p_b = ChiSquarePValue(b, 5);
+ EXPECT_NEAR(p_b, 0.4528180, 1e-5); // Accept the null hypothesis.
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_caller.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_caller.h
new file mode 100644
index 00000000000..fc81b787ebe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_caller.h
@@ -0,0 +1,92 @@
+//
+// 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 "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 {
+ // 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.cc
new file mode 100644
index 00000000000..e9005658c0a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.cc
@@ -0,0 +1,418 @@
+// 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.
+
+#include "absl/random/internal/distribution_test_util.h"
+
+#include <cassert>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+#if defined(__EMSCRIPTEN__)
+// Workaround __EMSCRIPTEN__ error: llvm_fma_f64 not found.
+inline double fma(double x, double y, double z) { return (x * y) + z; }
+#endif
+
+} // namespace
+
+DistributionMoments ComputeDistributionMoments(
+ absl::Span<const double> data_points) {
+ DistributionMoments result;
+
+ // Compute m1
+ for (double x : data_points) {
+ result.n++;
+ result.mean += x;
+ }
+ result.mean /= static_cast<double>(result.n);
+
+ // Compute m2, m3, m4
+ for (double x : data_points) {
+ double v = x - result.mean;
+ result.variance += v * v;
+ result.skewness += v * v * v;
+ result.kurtosis += v * v * v * v;
+ }
+ result.variance /= static_cast<double>(result.n - 1);
+
+ result.skewness /= static_cast<double>(result.n);
+ result.skewness /= std::pow(result.variance, 1.5);
+
+ result.kurtosis /= static_cast<double>(result.n);
+ result.kurtosis /= std::pow(result.variance, 2.0);
+ return result;
+
+ // When validating the min/max count, the following confidence intervals may
+ // be of use:
+ // 3.291 * stddev = 99.9% CI
+ // 2.576 * stddev = 99% CI
+ // 1.96 * stddev = 95% CI
+ // 1.65 * stddev = 90% CI
+}
+
+std::ostream& operator<<(std::ostream& os, const DistributionMoments& moments) {
+ return os << absl::StrFormat("mean=%f, stddev=%f, skewness=%f, kurtosis=%f",
+ moments.mean, std::sqrt(moments.variance),
+ moments.skewness, moments.kurtosis);
+}
+
+double InverseNormalSurvival(double x) {
+ // inv_sf(u) = -sqrt(2) * erfinv(2u-1)
+ static constexpr double kSqrt2 = 1.4142135623730950488;
+ return -kSqrt2 * absl::random_internal::erfinv(2 * x - 1.0);
+}
+
+bool Near(absl::string_view msg, double actual, double expected, double bound) {
+ assert(bound > 0.0);
+ double delta = fabs(expected - actual);
+ if (delta < bound) {
+ return true;
+ }
+
+ std::string formatted = absl::StrCat(
+ msg, " actual=", actual, " expected=", expected, " err=", delta / bound);
+ ABSL_RAW_LOG(INFO, "%s", formatted.c_str());
+ return false;
+}
+
+// TODO(absl-team): Replace with an "ABSL_HAVE_SPECIAL_MATH" and try
+// to use std::beta(). As of this writing P0226R1 is not implemented
+// in libc++: http://libcxx.llvm.org/cxx1z_status.html
+double beta(double p, double q) {
+ // Beta(x, y) = Gamma(x) * Gamma(y) / Gamma(x+y)
+ double lbeta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);
+ return std::exp(lbeta);
+}
+
+// Approximation to inverse of the Error Function in double precision.
+// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf)
+double erfinv(double x) {
+#if !defined(__EMSCRIPTEN__)
+ using std::fma;
+#endif
+
+ double w = 0.0;
+ double p = 0.0;
+ w = -std::log((1.0 - x) * (1.0 + x));
+ if (w < 6.250000) {
+ w = w - 3.125000;
+ p = -3.6444120640178196996e-21;
+ p = fma(p, w, -1.685059138182016589e-19);
+ p = fma(p, w, 1.2858480715256400167e-18);
+ p = fma(p, w, 1.115787767802518096e-17);
+ p = fma(p, w, -1.333171662854620906e-16);
+ p = fma(p, w, 2.0972767875968561637e-17);
+ p = fma(p, w, 6.6376381343583238325e-15);
+ p = fma(p, w, -4.0545662729752068639e-14);
+ p = fma(p, w, -8.1519341976054721522e-14);
+ p = fma(p, w, 2.6335093153082322977e-12);
+ p = fma(p, w, -1.2975133253453532498e-11);
+ p = fma(p, w, -5.4154120542946279317e-11);
+ p = fma(p, w, 1.051212273321532285e-09);
+ p = fma(p, w, -4.1126339803469836976e-09);
+ p = fma(p, w, -2.9070369957882005086e-08);
+ p = fma(p, w, 4.2347877827932403518e-07);
+ p = fma(p, w, -1.3654692000834678645e-06);
+ p = fma(p, w, -1.3882523362786468719e-05);
+ p = fma(p, w, 0.0001867342080340571352);
+ p = fma(p, w, -0.00074070253416626697512);
+ p = fma(p, w, -0.0060336708714301490533);
+ p = fma(p, w, 0.24015818242558961693);
+ p = fma(p, w, 1.6536545626831027356);
+ } else if (w < 16.000000) {
+ w = std::sqrt(w) - 3.250000;
+ p = 2.2137376921775787049e-09;
+ p = fma(p, w, 9.0756561938885390979e-08);
+ p = fma(p, w, -2.7517406297064545428e-07);
+ p = fma(p, w, 1.8239629214389227755e-08);
+ p = fma(p, w, 1.5027403968909827627e-06);
+ p = fma(p, w, -4.013867526981545969e-06);
+ p = fma(p, w, 2.9234449089955446044e-06);
+ p = fma(p, w, 1.2475304481671778723e-05);
+ p = fma(p, w, -4.7318229009055733981e-05);
+ p = fma(p, w, 6.8284851459573175448e-05);
+ p = fma(p, w, 2.4031110387097893999e-05);
+ p = fma(p, w, -0.0003550375203628474796);
+ p = fma(p, w, 0.00095328937973738049703);
+ p = fma(p, w, -0.0016882755560235047313);
+ p = fma(p, w, 0.0024914420961078508066);
+ p = fma(p, w, -0.0037512085075692412107);
+ p = fma(p, w, 0.005370914553590063617);
+ p = fma(p, w, 1.0052589676941592334);
+ p = fma(p, w, 3.0838856104922207635);
+ } else {
+ w = std::sqrt(w) - 5.000000;
+ p = -2.7109920616438573243e-11;
+ p = fma(p, w, -2.5556418169965252055e-10);
+ p = fma(p, w, 1.5076572693500548083e-09);
+ p = fma(p, w, -3.7894654401267369937e-09);
+ p = fma(p, w, 7.6157012080783393804e-09);
+ p = fma(p, w, -1.4960026627149240478e-08);
+ p = fma(p, w, 2.9147953450901080826e-08);
+ p = fma(p, w, -6.7711997758452339498e-08);
+ p = fma(p, w, 2.2900482228026654717e-07);
+ p = fma(p, w, -9.9298272942317002539e-07);
+ p = fma(p, w, 4.5260625972231537039e-06);
+ p = fma(p, w, -1.9681778105531670567e-05);
+ p = fma(p, w, 7.5995277030017761139e-05);
+ p = fma(p, w, -0.00021503011930044477347);
+ p = fma(p, w, -0.00013871931833623122026);
+ p = fma(p, w, 1.0103004648645343977);
+ p = fma(p, w, 4.8499064014085844221);
+ }
+ return p * x;
+}
+
+namespace {
+
+// Direct implementation of AS63, BETAIN()
+// https://www.jstor.org/stable/2346797?seq=3#page_scan_tab_contents.
+//
+// BETAIN(x, p, q, beta)
+// x: the value of the upper limit x.
+// p: the value of the parameter p.
+// q: the value of the parameter q.
+// beta: the value of ln B(p, q)
+//
+double BetaIncompleteImpl(const double x, const double p, const double q,
+ const double beta) {
+ if (p < (p + q) * x) {
+ // Incomplete beta function is symmetrical, so return the complement.
+ return 1. - BetaIncompleteImpl(1.0 - x, q, p, beta);
+ }
+
+ double psq = p + q;
+ const double kErr = 1e-14;
+ const double xc = 1. - x;
+ const double pre =
+ std::exp(p * std::log(x) + (q - 1.) * std::log(xc) - beta) / p;
+
+ double term = 1.;
+ double ai = 1.;
+ double result = 1.;
+ int ns = static_cast<int>(q + xc * psq);
+
+ // Use the soper reduction forumla.
+ double rx = (ns == 0) ? x : x / xc;
+ double temp = q - ai;
+ for (;;) {
+ term = term * temp * rx / (p + ai);
+ result = result + term;
+ temp = std::fabs(term);
+ if (temp < kErr && temp < kErr * result) {
+ return result * pre;
+ }
+ ai = ai + 1.;
+ --ns;
+ if (ns >= 0) {
+ temp = q - ai;
+ if (ns == 0) {
+ rx = x;
+ }
+ } else {
+ temp = psq;
+ psq = psq + 1.;
+ }
+ }
+
+ // NOTE: See also TOMS Alogrithm 708.
+ // http://www.netlib.org/toms/index.html
+ //
+ // NOTE: The NWSC library also includes BRATIO / ISUBX (p87)
+ // https://archive.org/details/DTIC_ADA261511/page/n75
+}
+
+// Direct implementation of AS109, XINBTA(p, q, beta, alpha)
+// https://www.jstor.org/stable/2346798?read-now=1&seq=4#page_scan_tab_contents
+// https://www.jstor.org/stable/2346887?seq=1#page_scan_tab_contents
+//
+// XINBTA(p, q, beta, alhpa)
+// p: the value of the parameter p.
+// q: the value of the parameter q.
+// beta: the value of ln B(p, q)
+// alpha: the value of the lower tail area.
+//
+double BetaIncompleteInvImpl(const double p, const double q, const double beta,
+ const double alpha) {
+ if (alpha < 0.5) {
+ // Inverse Incomplete beta function is symmetrical, return the complement.
+ return 1. - BetaIncompleteInvImpl(q, p, beta, 1. - alpha);
+ }
+ const double kErr = 1e-14;
+ double value = kErr;
+
+ // Compute the initial estimate.
+ {
+ double r = std::sqrt(-std::log(alpha * alpha));
+ double y =
+ r - fma(r, 0.27061, 2.30753) / fma(r, fma(r, 0.04481, 0.99229), 1.0);
+ if (p > 1. && q > 1.) {
+ r = (y * y - 3.) / 6.;
+ double s = 1. / (p + p - 1.);
+ double t = 1. / (q + q - 1.);
+ double h = 2. / s + t;
+ double w =
+ y * std::sqrt(h + r) / h - (t - s) * (r + 5. / 6. - t / (3. * h));
+ value = p / (p + q * std::exp(w + w));
+ } else {
+ r = q + q;
+ double t = 1.0 / (9. * q);
+ double u = 1.0 - t + y * std::sqrt(t);
+ t = r * (u * u * u);
+ if (t <= 0) {
+ value = 1.0 - std::exp((std::log((1.0 - alpha) * q) + beta) / q);
+ } else {
+ t = (4.0 * p + r - 2.0) / t;
+ if (t <= 1) {
+ value = std::exp((std::log(alpha * p) + beta) / p);
+ } else {
+ value = 1.0 - 2.0 / (t + 1.0);
+ }
+ }
+ }
+ }
+
+ // Solve for x using a modified newton-raphson method using the function
+ // BetaIncomplete.
+ {
+ value = std::max(value, kErr);
+ value = std::min(value, 1.0 - kErr);
+
+ const double r = 1.0 - p;
+ const double t = 1.0 - q;
+ double y;
+ double yprev = 0;
+ double sq = 1;
+ double prev = 1;
+ for (;;) {
+ if (value < 0 || value > 1.0) {
+ // Error case; value went infinite.
+ return std::numeric_limits<double>::infinity();
+ } else if (value == 0 || value == 1) {
+ y = value;
+ } else {
+ y = BetaIncompleteImpl(value, p, q, beta);
+ if (!std::isfinite(y)) {
+ return y;
+ }
+ }
+ y = (y - alpha) *
+ std::exp(beta + r * std::log(value) + t * std::log(1.0 - value));
+ if (y * yprev <= 0) {
+ prev = std::max(sq, std::numeric_limits<double>::min());
+ }
+ double g = 1.0;
+ for (;;) {
+ const double adj = g * y;
+ const double adj_sq = adj * adj;
+ if (adj_sq >= prev) {
+ g = g / 3.0;
+ continue;
+ }
+ const double tx = value - adj;
+ if (tx < 0 || tx > 1) {
+ g = g / 3.0;
+ continue;
+ }
+ if (prev < kErr) {
+ return value;
+ }
+ if (y * y < kErr) {
+ return value;
+ }
+ if (tx == value) {
+ return value;
+ }
+ if (tx == 0 || tx == 1) {
+ g = g / 3.0;
+ continue;
+ }
+ value = tx;
+ yprev = y;
+ break;
+ }
+ }
+ }
+
+ // NOTES: See also: Asymptotic inversion of the incomplete beta function.
+ // https://core.ac.uk/download/pdf/82140723.pdf
+ //
+ // NOTE: See the Boost library documentation as well:
+ // https://www.boost.org/doc/libs/1_52_0/libs/math/doc/sf_and_dist/html/math_toolkit/special/sf_beta/ibeta_function.html
+}
+
+} // namespace
+
+double BetaIncomplete(const double x, const double p, const double q) {
+ // Error cases.
+ if (p < 0 || q < 0 || x < 0 || x > 1.0) {
+ return std::numeric_limits<double>::infinity();
+ }
+ if (x == 0 || x == 1) {
+ return x;
+ }
+ // ln(Beta(p, q))
+ double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);
+ return BetaIncompleteImpl(x, p, q, beta);
+}
+
+double BetaIncompleteInv(const double p, const double q, const double alpha) {
+ // Error cases.
+ if (p < 0 || q < 0 || alpha < 0 || alpha > 1.0) {
+ return std::numeric_limits<double>::infinity();
+ }
+ if (alpha == 0 || alpha == 1) {
+ return alpha;
+ }
+ // ln(Beta(p, q))
+ double beta = std::lgamma(p) + std::lgamma(q) - std::lgamma(p + q);
+ return BetaIncompleteInvImpl(p, q, beta, alpha);
+}
+
+// Given `num_trials` trials each with probability `p` of success, the
+// probability of no failures is `p^k`. To ensure the probability of a failure
+// is no more than `p_fail`, it must be that `p^k == 1 - p_fail`. This function
+// computes `p` from that equation.
+double RequiredSuccessProbability(const double p_fail, const int num_trials) {
+ double p = std::exp(std::log(1.0 - p_fail) / static_cast<double>(num_trials));
+ ABSL_ASSERT(p > 0);
+ return p;
+}
+
+double ZScore(double expected_mean, const DistributionMoments& moments) {
+ return (moments.mean - expected_mean) /
+ (std::sqrt(moments.variance) /
+ std::sqrt(static_cast<double>(moments.n)));
+}
+
+double MaxErrorTolerance(double acceptance_probability) {
+ double one_sided_pvalue = 0.5 * (1.0 - acceptance_probability);
+ const double max_err = InverseNormalSurvival(one_sided_pvalue);
+ ABSL_ASSERT(max_err > 0);
+ return max_err;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.h
new file mode 100644
index 00000000000..6d94cf6c97b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util.h
@@ -0,0 +1,113 @@
+// 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_DISTRIBUTION_TEST_UTIL_H_
+#define ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_
+
+#include <cstddef>
+#include <iostream>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+// NOTE: The functions in this file are test only, and are should not be used in
+// non-test code.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// http://webspace.ship.edu/pgmarr/Geo441/Lectures/Lec%205%20-%20Normality%20Testing.pdf
+
+// Compute the 1st to 4th standard moments:
+// mean, variance, skewness, and kurtosis.
+// http://www.itl.nist.gov/div898/handbook/eda/section3/eda35b.htm
+struct DistributionMoments {
+ size_t n = 0;
+ double mean = 0.0;
+ double variance = 0.0;
+ double skewness = 0.0;
+ double kurtosis = 0.0;
+};
+DistributionMoments ComputeDistributionMoments(
+ absl::Span<const double> data_points);
+
+std::ostream& operator<<(std::ostream& os, const DistributionMoments& moments);
+
+// Computes the Z-score for a set of data with the given distribution moments
+// compared against `expected_mean`.
+double ZScore(double expected_mean, const DistributionMoments& moments);
+
+// Returns the probability of success required for a single trial to ensure that
+// after `num_trials` trials, the probability of at least one failure is no more
+// than `p_fail`.
+double RequiredSuccessProbability(double p_fail, int num_trials);
+
+// Computes the maximum distance from the mean tolerable, for Z-Tests that are
+// expected to pass with `acceptance_probability`. Will terminate if the
+// resulting tolerance is zero (due to passing in 0.0 for
+// `acceptance_probability` or rounding errors).
+//
+// For example,
+// MaxErrorTolerance(0.001) = 0.0
+// MaxErrorTolerance(0.5) = ~0.47
+// MaxErrorTolerance(1.0) = inf
+double MaxErrorTolerance(double acceptance_probability);
+
+// Approximation to inverse of the Error Function in double precision.
+// (http://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf)
+double erfinv(double x);
+
+// Beta(p, q) = Gamma(p) * Gamma(q) / Gamma(p+q)
+double beta(double p, double q);
+
+// The inverse of the normal survival function.
+double InverseNormalSurvival(double x);
+
+// Returns whether actual is "near" expected, based on the bound.
+bool Near(absl::string_view msg, double actual, double expected, double bound);
+
+// Implements the incomplete regularized beta function, AS63, BETAIN.
+// https://www.jstor.org/stable/2346797
+//
+// BetaIncomplete(x, p, q), where
+// `x` is the value of the upper limit
+// `p` is beta parameter p, `q` is beta parameter q.
+//
+// NOTE: This is a test-only function which is only accurate to within, at most,
+// 1e-13 of the actual value.
+//
+double BetaIncomplete(double x, double p, double q);
+
+// Implements the inverse of the incomplete regularized beta function, AS109,
+// XINBTA.
+// https://www.jstor.org/stable/2346798
+// https://www.jstor.org/stable/2346887
+//
+// BetaIncompleteInv(p, q, beta, alhpa)
+// `p` is beta parameter p, `q` is beta parameter q.
+// `alpha` is the value of the lower tail area.
+//
+// NOTE: This is a test-only function and, when successful, is only accurate to
+// within ~1e-6 of the actual value; there are some cases where it diverges from
+// the actual value by much more than that. The function uses Newton's method,
+// and thus the runtime is highly variable.
+double BetaIncompleteInv(double p, double q, double alpha);
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTION_TEST_UTIL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util_test.cc
new file mode 100644
index 00000000000..c49d44fb479
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/distribution_test_util_test.cc
@@ -0,0 +1,193 @@
+// 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.
+
+#include "absl/random/internal/distribution_test_util.h"
+
+#include "gtest/gtest.h"
+
+namespace {
+
+TEST(TestUtil, InverseErf) {
+ const struct {
+ const double z;
+ const double value;
+ } kErfInvTable[] = {
+ {0.0000001, 8.86227e-8},
+ {0.00001, 8.86227e-6},
+ {0.5, 0.4769362762044},
+ {0.6, 0.5951160814499},
+ {0.99999, 3.1234132743},
+ {0.9999999, 3.7665625816},
+ {0.999999944, 3.8403850690566985}, // = log((1-x) * (1+x)) =~ 16.004
+ {0.999999999, 4.3200053849134452},
+ };
+
+ for (const auto& data : kErfInvTable) {
+ auto value = absl::random_internal::erfinv(data.z);
+
+ // Log using the Wolfram-alpha function name & parameters.
+ EXPECT_NEAR(value, data.value, 1e-8)
+ << " InverseErf[" << data.z << "] (expected=" << data.value << ") -> "
+ << value;
+ }
+}
+
+const struct {
+ const double p;
+ const double q;
+ const double x;
+ const double alpha;
+} kBetaTable[] = {
+ {0.5, 0.5, 0.01, 0.06376856085851985},
+ {0.5, 0.5, 0.1, 0.2048327646991335},
+ {0.5, 0.5, 1, 1},
+ {1, 0.5, 0, 0},
+ {1, 0.5, 0.01, 0.005012562893380045},
+ {1, 0.5, 0.1, 0.0513167019494862},
+ {1, 0.5, 0.5, 0.2928932188134525},
+ {1, 1, 0.5, 0.5},
+ {2, 2, 0.1, 0.028},
+ {2, 2, 0.2, 0.104},
+ {2, 2, 0.3, 0.216},
+ {2, 2, 0.4, 0.352},
+ {2, 2, 0.5, 0.5},
+ {2, 2, 0.6, 0.648},
+ {2, 2, 0.7, 0.784},
+ {2, 2, 0.8, 0.896},
+ {2, 2, 0.9, 0.972},
+ {5.5, 5, 0.5, 0.4361908850559777},
+ {10, 0.5, 0.9, 0.1516409096346979},
+ {10, 5, 0.5, 0.08978271484375},
+ {10, 5, 1, 1},
+ {10, 10, 0.5, 0.5},
+ {20, 5, 0.8, 0.4598773297575791},
+ {20, 10, 0.6, 0.2146816102371739},
+ {20, 10, 0.8, 0.9507364826957875},
+ {20, 20, 0.5, 0.5},
+ {20, 20, 0.6, 0.8979413687105918},
+ {30, 10, 0.7, 0.2241297491808366},
+ {30, 10, 0.8, 0.7586405487192086},
+ {40, 20, 0.7, 0.7001783247477069},
+ {1, 0.5, 0.1, 0.0513167019494862},
+ {1, 0.5, 0.2, 0.1055728090000841},
+ {1, 0.5, 0.3, 0.1633399734659245},
+ {1, 0.5, 0.4, 0.2254033307585166},
+ {1, 2, 0.2, 0.36},
+ {1, 3, 0.2, 0.488},
+ {1, 4, 0.2, 0.5904},
+ {1, 5, 0.2, 0.67232},
+ {2, 2, 0.3, 0.216},
+ {3, 2, 0.3, 0.0837},
+ {4, 2, 0.3, 0.03078},
+ {5, 2, 0.3, 0.010935},
+
+ // These values test small & large points along the range of the Beta
+ // function.
+ //
+ // When selecting test points, remember that if BetaIncomplete(x, p, q)
+ // returns the same value to within the limits of precision over a large
+ // domain of the input, x, then BetaIncompleteInv(alpha, p, q) may return an
+ // essentially arbitrary value where BetaIncomplete(x, p, q) =~ alpha.
+
+ // BetaRegularized[x, 0.00001, 0.00001],
+ // For x in {~0.001 ... ~0.999}, => ~0.5
+ {1e-5, 1e-5, 1e-5, 0.4999424388184638311},
+ {1e-5, 1e-5, (1.0 - 1e-8), 0.5000920948389232964},
+
+ // BetaRegularized[x, 0.00001, 10000].
+ // For x in {~epsilon ... 1.0}, => ~1
+ {1e-5, 1e5, 1e-6, 0.9999817708130066936},
+ {1e-5, 1e5, (1.0 - 1e-7), 1.0},
+
+ // BetaRegularized[x, 10000, 0.00001].
+ // For x in {0 .. 1-epsilon}, => ~0
+ {1e5, 1e-5, 1e-6, 0},
+ {1e5, 1e-5, (1.0 - 1e-6), 1.8229186993306369e-5},
+};
+
+TEST(BetaTest, BetaIncomplete) {
+ for (const auto& data : kBetaTable) {
+ auto value = absl::random_internal::BetaIncomplete(data.x, data.p, data.q);
+
+ // Log using the Wolfram-alpha function name & parameters.
+ EXPECT_NEAR(value, data.alpha, 1e-12)
+ << " BetaRegularized[" << data.x << ", " << data.p << ", " << data.q
+ << "] (expected=" << data.alpha << ") -> " << value;
+ }
+}
+
+TEST(BetaTest, BetaIncompleteInv) {
+ for (const auto& data : kBetaTable) {
+ auto value =
+ absl::random_internal::BetaIncompleteInv(data.p, data.q, data.alpha);
+
+ // Log using the Wolfram-alpha function name & parameters.
+ EXPECT_NEAR(value, data.x, 1e-6)
+ << " InverseBetaRegularized[" << data.alpha << ", " << data.p << ", "
+ << data.q << "] (expected=" << data.x << ") -> " << value;
+ }
+}
+
+TEST(MaxErrorTolerance, MaxErrorTolerance) {
+ std::vector<std::pair<double, double>> cases = {
+ {0.0000001, 8.86227e-8 * 1.41421356237},
+ {0.00001, 8.86227e-6 * 1.41421356237},
+ {0.5, 0.4769362762044 * 1.41421356237},
+ {0.6, 0.5951160814499 * 1.41421356237},
+ {0.99999, 3.1234132743 * 1.41421356237},
+ {0.9999999, 3.7665625816 * 1.41421356237},
+ {0.999999944, 3.8403850690566985 * 1.41421356237},
+ {0.999999999, 4.3200053849134452 * 1.41421356237}};
+ for (auto entry : cases) {
+ EXPECT_NEAR(absl::random_internal::MaxErrorTolerance(entry.first),
+ entry.second, 1e-8);
+ }
+}
+
+TEST(ZScore, WithSameMean) {
+ absl::random_internal::DistributionMoments m;
+ m.n = 100;
+ m.mean = 5;
+ m.variance = 1;
+ EXPECT_NEAR(absl::random_internal::ZScore(5, m), 0, 1e-12);
+
+ m.n = 1;
+ m.mean = 0;
+ m.variance = 1;
+ EXPECT_NEAR(absl::random_internal::ZScore(0, m), 0, 1e-12);
+
+ m.n = 10000;
+ m.mean = -5;
+ m.variance = 100;
+ EXPECT_NEAR(absl::random_internal::ZScore(-5, m), 0, 1e-12);
+}
+
+TEST(ZScore, DifferentMean) {
+ absl::random_internal::DistributionMoments m;
+ m.n = 100;
+ m.mean = 5;
+ m.variance = 1;
+ EXPECT_NEAR(absl::random_internal::ZScore(4, m), 10, 1e-12);
+
+ m.n = 1;
+ m.mean = 0;
+ m.variance = 1;
+ EXPECT_NEAR(absl::random_internal::ZScore(-1, m), 1, 1e-12);
+
+ m.n = 10000;
+ m.mean = -5;
+ m.variance = 100;
+ EXPECT_NEAR(absl::random_internal::ZScore(-4, m), -10, 1e-12);
+}
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq.h
new file mode 100644
index 00000000000..e3aa31a184a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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 : little_endian::FromHost32(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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc
new file mode 100644
index 00000000000..a55ad73948b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc
@@ -0,0 +1,204 @@
+// 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.
+
+#include "absl/random/internal/explicit_seed_seq.h"
+
+#include <iterator>
+#include <random>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/seed_sequences.h"
+
+namespace {
+
+template <typename Sseq>
+bool ConformsToInterface() {
+ // Check that the SeedSequence can be default-constructed.
+ { Sseq default_constructed_seq; }
+ // Check that the SeedSequence can be constructed with two iterators.
+ {
+ uint32_t init_array[] = {1, 3, 5, 7, 9};
+ Sseq iterator_constructed_seq(init_array, &init_array[5]);
+ }
+ // Check that the SeedSequence can be std::initializer_list-constructed.
+ { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; }
+ // Check that param() and size() return state provided to constructor.
+ {
+ uint32_t init_array[] = {1, 2, 3, 4, 5};
+ Sseq seq(init_array, &init_array[ABSL_ARRAYSIZE(init_array)]);
+ EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array));
+
+ uint32_t state_array[ABSL_ARRAYSIZE(init_array)];
+ seq.param(state_array);
+
+ for (int i = 0; i < ABSL_ARRAYSIZE(state_array); i++) {
+ EXPECT_EQ(state_array[i], i + 1);
+ }
+ }
+ // Check for presence of generate() method.
+ {
+ Sseq seq;
+ uint32_t seeds[5];
+
+ seq.generate(seeds, &seeds[ABSL_ARRAYSIZE(seeds)]);
+ }
+ return true;
+}
+} // namespace
+
+TEST(SeedSequences, CheckInterfaces) {
+ // Control case
+ EXPECT_TRUE(ConformsToInterface<std::seed_seq>());
+
+ // Abseil classes
+ EXPECT_TRUE(ConformsToInterface<absl::random_internal::ExplicitSeedSeq>());
+}
+
+TEST(ExplicitSeedSeq, DefaultConstructorGeneratesZeros) {
+ const size_t kNumBlocks = 128;
+
+ uint32_t outputs[kNumBlocks];
+ absl::random_internal::ExplicitSeedSeq seq;
+ seq.generate(outputs, &outputs[kNumBlocks]);
+
+ for (uint32_t& seed : outputs) {
+ EXPECT_EQ(seed, 0);
+ }
+}
+
+TEST(ExplicitSeeqSeq, SeedMaterialIsForwardedIdentically) {
+ const size_t kNumBlocks = 128;
+
+ uint32_t seed_material[kNumBlocks];
+ std::random_device urandom{"/dev/urandom"};
+ for (uint32_t& seed : seed_material) {
+ seed = urandom();
+ }
+ absl::random_internal::ExplicitSeedSeq seq(seed_material,
+ &seed_material[kNumBlocks]);
+
+ // Check that output is same as seed-material provided to constructor.
+ {
+ const size_t kNumGenerated = kNumBlocks / 2;
+ uint32_t outputs[kNumGenerated];
+ seq.generate(outputs, &outputs[kNumGenerated]);
+ for (size_t i = 0; i < kNumGenerated; i++) {
+ EXPECT_EQ(outputs[i], seed_material[i]);
+ }
+ }
+ // Check that SeedSequence is stateless between invocations: Despite the last
+ // invocation of generate() only consuming half of the input-entropy, the same
+ // entropy will be recycled for the next invocation.
+ {
+ const size_t kNumGenerated = kNumBlocks;
+ uint32_t outputs[kNumGenerated];
+ seq.generate(outputs, &outputs[kNumGenerated]);
+ for (size_t i = 0; i < kNumGenerated; i++) {
+ EXPECT_EQ(outputs[i], seed_material[i]);
+ }
+ }
+ // Check that when more seed-material is asked for than is provided, nonzero
+ // values are still written.
+ {
+ const size_t kNumGenerated = kNumBlocks * 2;
+ uint32_t outputs[kNumGenerated];
+ seq.generate(outputs, &outputs[kNumGenerated]);
+ for (size_t i = 0; i < kNumGenerated; i++) {
+ EXPECT_EQ(outputs[i], seed_material[i % kNumBlocks]);
+ }
+ }
+}
+
+TEST(ExplicitSeedSeq, CopyAndMoveConstructors) {
+ using testing::Each;
+ using testing::Eq;
+ using testing::Not;
+ using testing::Pointwise;
+
+ uint32_t entropy[4];
+ std::random_device urandom("/dev/urandom");
+ for (uint32_t& entry : entropy) {
+ entry = urandom();
+ }
+ absl::random_internal::ExplicitSeedSeq seq_from_entropy(std::begin(entropy),
+ std::end(entropy));
+ // Copy constructor.
+ {
+ absl::random_internal::ExplicitSeedSeq seq_copy(seq_from_entropy);
+ EXPECT_EQ(seq_copy.size(), seq_from_entropy.size());
+
+ std::vector<uint32_t> seeds_1;
+ seeds_1.resize(1000, 0);
+ std::vector<uint32_t> seeds_2;
+ seeds_2.resize(1000, 1);
+
+ seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
+ seq_copy.generate(seeds_2.begin(), seeds_2.end());
+
+ EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));
+ }
+ // Assignment operator.
+ {
+ for (uint32_t& entry : entropy) {
+ entry = urandom();
+ }
+ absl::random_internal::ExplicitSeedSeq another_seq(std::begin(entropy),
+ std::end(entropy));
+
+ std::vector<uint32_t> seeds_1;
+ seeds_1.resize(1000, 0);
+ std::vector<uint32_t> seeds_2;
+ seeds_2.resize(1000, 0);
+
+ seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
+ another_seq.generate(seeds_2.begin(), seeds_2.end());
+
+ // Assert precondition: Sequences generated by seed-sequences are not equal.
+ EXPECT_THAT(seeds_1, Not(Pointwise(Eq(), seeds_2)));
+
+ // Apply the assignment-operator.
+ another_seq = seq_from_entropy;
+
+ // Re-generate seeds.
+ seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
+ another_seq.generate(seeds_2.begin(), seeds_2.end());
+
+ // Seeds generated by seed-sequences should now be equal.
+ EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));
+ }
+ // Move constructor.
+ {
+ // Get seeds from seed-sequence constructed from entropy.
+ std::vector<uint32_t> seeds_1;
+ seeds_1.resize(1000, 0);
+ seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
+
+ // Apply move-constructor move the sequence to another instance.
+ absl::random_internal::ExplicitSeedSeq moved_seq(
+ std::move(seq_from_entropy));
+ std::vector<uint32_t> seeds_2;
+ seeds_2.resize(1000, 1);
+ moved_seq.generate(seeds_2.begin(), seeds_2.end());
+ // Verify that seeds produced by moved-instance are the same as original.
+ EXPECT_THAT(seeds_1, Pointwise(Eq(), seeds_2));
+
+ // Verify that the moved-from instance now behaves like a
+ // default-constructed instance.
+ EXPECT_EQ(seq_from_entropy.size(), 0);
+ seq_from_entropy.generate(seeds_1.begin(), seeds_1.end());
+ EXPECT_THAT(seeds_1, Each(Eq(0)));
+ }
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits.h
new file mode 100644
index 00000000000..425aaf7d830
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits.h
@@ -0,0 +1,268 @@
+// 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_FAST_UNIFORM_BITS_H_
+#define ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+// Returns true if the input value is zero or a power of two. Useful for
+// determining if the range of output values in a URBG
+template <typename UIntType>
+constexpr bool IsPowerOfTwoOrZero(UIntType n) {
+ return (n == 0) || ((n & (n - 1)) == 0);
+}
+
+// Computes the length of the range of values producible by the URBG, or returns
+// zero if that would encompass the entire range of representable values in
+// URBG::result_type.
+template <typename URBG>
+constexpr typename URBG::result_type RangeSize() {
+ using result_type = typename URBG::result_type;
+ static_assert((URBG::max)() != (URBG::min)(), "URBG range cannot be 0.");
+ return ((URBG::max)() == (std::numeric_limits<result_type>::max)() &&
+ (URBG::min)() == std::numeric_limits<result_type>::lowest())
+ ? result_type{0}
+ : ((URBG::max)() - (URBG::min)() + result_type{1});
+}
+
+// Computes the floor of the log. (i.e., std::floor(std::log2(N));
+template <typename UIntType>
+constexpr UIntType IntegerLog2(UIntType n) {
+ return (n <= 1) ? 0 : 1 + IntegerLog2(n >> 1);
+}
+
+// Returns the number of bits of randomness returned through
+// `PowerOfTwoVariate(urbg)`.
+template <typename URBG>
+constexpr size_t NumBits() {
+ return RangeSize<URBG>() == 0
+ ? std::numeric_limits<typename URBG::result_type>::digits
+ : IntegerLog2(RangeSize<URBG>());
+}
+
+// Given a shift value `n`, constructs a mask with exactly the low `n` bits set.
+// If `n == 0`, all bits are set.
+template <typename UIntType>
+constexpr UIntType MaskFromShift(size_t n) {
+ return ((n % std::numeric_limits<UIntType>::digits) == 0)
+ ? ~UIntType{0}
+ : (UIntType{1} << n) - UIntType{1};
+}
+
+// Tags used to dispatch FastUniformBits::generate to the simple or more complex
+// entropy extraction algorithm.
+struct SimplifiedLoopTag {};
+struct RejectionLoopTag {};
+
+// FastUniformBits implements a fast path to acquire uniform independent bits
+// from a type which conforms to the [rand.req.urbg] concept.
+// Parameterized by:
+// `UIntType`: the result (output) type
+//
+// The std::independent_bits_engine [rand.adapt.ibits] adaptor can be
+// instantiated from an existing generator through a copy or a move. It does
+// not, however, facilitate the production of pseudorandom bits from an un-owned
+// generator that will outlive the std::independent_bits_engine instance.
+template <typename UIntType = uint64_t>
+class FastUniformBits {
+ public:
+ using result_type = UIntType;
+
+ static constexpr result_type(min)() { return 0; }
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ template <typename URBG>
+ result_type operator()(URBG& g); // NOLINT(runtime/references)
+
+ private:
+ static_assert(std::is_unsigned<UIntType>::value,
+ "Class-template FastUniformBits<> must be parameterized using "
+ "an unsigned type.");
+
+ // Generate() generates a random value, dispatched on whether
+ // the underlying URBG must use rejection sampling to generate a value,
+ // or whether a simplified loop will suffice.
+ template <typename URBG>
+ result_type Generate(URBG& g, // NOLINT(runtime/references)
+ SimplifiedLoopTag);
+
+ template <typename URBG>
+ result_type Generate(URBG& g, // NOLINT(runtime/references)
+ RejectionLoopTag);
+};
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::operator()(URBG& g) { // NOLINT(runtime/references)
+ // kRangeMask is the mask used when sampling variates from the URBG when the
+ // width of the URBG range is not a power of 2.
+ // Y = (2 ^ kRange) - 1
+ static_assert((URBG::max)() > (URBG::min)(),
+ "URBG::max and URBG::min may not be equal.");
+
+ using tag = absl::conditional_t<IsPowerOfTwoOrZero(RangeSize<URBG>()),
+ SimplifiedLoopTag, RejectionLoopTag>;
+ return Generate(g, tag{});
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
+ SimplifiedLoopTag) {
+ // The simplified version of FastUniformBits works only on URBGs that have
+ // a range that is a power of 2. In this case we simply loop and shift without
+ // attempting to balance the bits across calls.
+ static_assert(IsPowerOfTwoOrZero(RangeSize<URBG>()),
+ "incorrect Generate tag for URBG instance");
+
+ static constexpr size_t kResultBits =
+ std::numeric_limits<result_type>::digits;
+ static constexpr size_t kUrbgBits = NumBits<URBG>();
+ static constexpr size_t kIters =
+ (kResultBits / kUrbgBits) + (kResultBits % kUrbgBits != 0);
+ static constexpr size_t kShift = (kIters == 1) ? 0 : kUrbgBits;
+ static constexpr auto kMin = (URBG::min)();
+
+ result_type r = static_cast<result_type>(g() - kMin);
+ for (size_t n = 1; n < kIters; ++n) {
+ r = (r << kShift) + static_cast<result_type>(g() - kMin);
+ }
+ return r;
+}
+
+template <typename UIntType>
+template <typename URBG>
+typename FastUniformBits<UIntType>::result_type
+FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
+ RejectionLoopTag) {
+ static_assert(!IsPowerOfTwoOrZero(RangeSize<URBG>()),
+ "incorrect Generate tag for URBG instance");
+ using urbg_result_type = typename URBG::result_type;
+
+ // See [rand.adapt.ibits] for more details on the constants calculated below.
+ //
+ // It is preferable to use roughly the same number of bits from each generator
+ // call, however this is only possible when the number of bits provided by the
+ // URBG is a divisor of the number of bits in `result_type`. In all other
+ // cases, the number of bits used cannot always be the same, but it can be
+ // guaranteed to be off by at most 1. Thus we run two loops, one with a
+ // smaller bit-width size (`kSmallWidth`) and one with a larger width size
+ // (satisfying `kLargeWidth == kSmallWidth + 1`). The loops are run
+ // `kSmallIters` and `kLargeIters` times respectively such
+ // that
+ //
+ // `kResultBits == kSmallIters * kSmallBits
+ // + kLargeIters * kLargeBits`
+ //
+ // where `kResultBits` is the total number of bits in `result_type`.
+ //
+ static constexpr size_t kResultBits =
+ std::numeric_limits<result_type>::digits; // w
+ static constexpr urbg_result_type kUrbgRange = RangeSize<URBG>(); // R
+ static constexpr size_t kUrbgBits = NumBits<URBG>(); // m
+
+ // compute the initial estimate of the bits used.
+ // [rand.adapt.ibits] 2 (c)
+ static constexpr size_t kA = // ceil(w/m)
+ (kResultBits / kUrbgBits) + ((kResultBits % kUrbgBits) != 0); // n'
+
+ static constexpr size_t kABits = kResultBits / kA; // w0'
+ static constexpr urbg_result_type kARejection =
+ ((kUrbgRange >> kABits) << kABits); // y0'
+
+ // refine the selection to reduce the rejection frequency.
+ static constexpr size_t kTotalIters =
+ ((kUrbgRange - kARejection) <= (kARejection / kA)) ? kA : (kA + 1); // n
+
+ // [rand.adapt.ibits] 2 (b)
+ static constexpr size_t kSmallIters =
+ kTotalIters - (kResultBits % kTotalIters); // n0
+ static constexpr size_t kSmallBits = kResultBits / kTotalIters; // w0
+ static constexpr urbg_result_type kSmallRejection =
+ ((kUrbgRange >> kSmallBits) << kSmallBits); // y0
+
+ static constexpr size_t kLargeBits = kSmallBits + 1; // w0+1
+ static constexpr urbg_result_type kLargeRejection =
+ ((kUrbgRange >> kLargeBits) << kLargeBits); // y1
+
+ //
+ // Because `kLargeBits == kSmallBits + 1`, it follows that
+ //
+ // `kResultBits == kSmallIters * kSmallBits + kLargeIters`
+ //
+ // and therefore
+ //
+ // `kLargeIters == kTotalWidth % kSmallWidth`
+ //
+ // Intuitively, each iteration with the large width accounts for one unit
+ // of the remainder when `kTotalWidth` is divided by `kSmallWidth`. As
+ // mentioned above, if the URBG width is a divisor of `kTotalWidth`, then
+ // there would be no need for any large iterations (i.e., one loop would
+ // suffice), and indeed, in this case, `kLargeIters` would be zero.
+ static_assert(kResultBits == kSmallIters * kSmallBits +
+ (kTotalIters - kSmallIters) * kLargeBits,
+ "Error in looping constant calculations.");
+
+ // The small shift is essentially small bits, but due to the potential
+ // of generating a smaller result_type from a larger urbg type, the actual
+ // shift might be 0.
+ static constexpr size_t kSmallShift = kSmallBits % kResultBits;
+ static constexpr auto kSmallMask =
+ MaskFromShift<urbg_result_type>(kSmallShift);
+ static constexpr size_t kLargeShift = kLargeBits % kResultBits;
+ static constexpr auto kLargeMask =
+ MaskFromShift<urbg_result_type>(kLargeShift);
+
+ static constexpr auto kMin = (URBG::min)();
+
+ result_type s = 0;
+ for (size_t n = 0; n < kSmallIters; ++n) {
+ urbg_result_type v;
+ do {
+ v = g() - kMin;
+ } while (v >= kSmallRejection);
+
+ s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);
+ }
+
+ for (size_t n = kSmallIters; n < kTotalIters; ++n) {
+ urbg_result_type v;
+ do {
+ v = g() - kMin;
+ } while (v >= kLargeRejection);
+
+ s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);
+ }
+ return s;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_FAST_UNIFORM_BITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
new file mode 100644
index 00000000000..cee702df852
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
@@ -0,0 +1,336 @@
+// 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.
+
+#include "absl/random/internal/fast_uniform_bits.h"
+
+#include <random>
+
+#include "gtest/gtest.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+template <typename IntType>
+class FastUniformBitsTypedTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;
+
+TYPED_TEST_SUITE(FastUniformBitsTypedTest, IntTypes);
+
+TYPED_TEST(FastUniformBitsTypedTest, BasicTest) {
+ using Limits = std::numeric_limits<TypeParam>;
+ using FastBits = FastUniformBits<TypeParam>;
+
+ EXPECT_EQ(0, (FastBits::min)());
+ EXPECT_EQ((Limits::max)(), (FastBits::max)());
+
+ constexpr int kIters = 10000;
+ std::random_device rd;
+ std::mt19937 gen(rd());
+ FastBits fast;
+ for (int i = 0; i < kIters; i++) {
+ const auto v = fast(gen);
+ EXPECT_LE(v, (FastBits::max)());
+ EXPECT_GE(v, (FastBits::min)());
+ }
+}
+
+template <typename UIntType, UIntType Lo, UIntType Hi, UIntType Val = Lo>
+struct FakeUrbg {
+ using result_type = UIntType;
+
+ FakeUrbg() = default;
+ explicit FakeUrbg(bool r) : reject(r) {}
+
+ static constexpr result_type(max)() { return Hi; }
+ static constexpr result_type(min)() { return Lo; }
+ result_type operator()() {
+ // when reject is set, return Hi half the time.
+ return ((++calls % 2) == 1 && reject) ? Hi : Val;
+ }
+
+ bool reject = false;
+ size_t calls = 0;
+};
+
+TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{0}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{1}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{2}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{3}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{4}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint8_t{16}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint8_t{17}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint8_t>::max)()));
+
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{0}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{1}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{2}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{3}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{4}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint16_t{16}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint16_t{17}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint16_t>::max)()));
+
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{0}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{1}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{2}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{3}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint32_t{32}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint32_t{17}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint32_t>::max)()));
+
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{0}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{1}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{2}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{3}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{4}));
+ EXPECT_TRUE(IsPowerOfTwoOrZero(uint64_t{64}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero(uint64_t{17}));
+ EXPECT_FALSE(IsPowerOfTwoOrZero((std::numeric_limits<uint64_t>::max)()));
+}
+
+TEST(FastUniformBitsTest, IntegerLog2) {
+ EXPECT_EQ(0, IntegerLog2(uint16_t{0}));
+ EXPECT_EQ(0, IntegerLog2(uint16_t{1}));
+ EXPECT_EQ(1, IntegerLog2(uint16_t{2}));
+ EXPECT_EQ(1, IntegerLog2(uint16_t{3}));
+ EXPECT_EQ(2, IntegerLog2(uint16_t{4}));
+ EXPECT_EQ(2, IntegerLog2(uint16_t{5}));
+ EXPECT_EQ(2, IntegerLog2(uint16_t{7}));
+ EXPECT_EQ(3, IntegerLog2(uint16_t{8}));
+ EXPECT_EQ(63, IntegerLog2((std::numeric_limits<uint64_t>::max)()));
+}
+
+TEST(FastUniformBitsTest, RangeSize) {
+ EXPECT_EQ(2, (RangeSize<FakeUrbg<uint8_t, 0, 1>>()));
+ EXPECT_EQ(3, (RangeSize<FakeUrbg<uint8_t, 0, 2>>()));
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 0, 3>>()));
+ // EXPECT_EQ(0, (RangeSize<FakeUrbg<uint8_t, 2, 2>>()));
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint8_t, 2, 5>>()));
+ EXPECT_EQ(5, (RangeSize<FakeUrbg<uint8_t, 2, 6>>()));
+ EXPECT_EQ(9, (RangeSize<FakeUrbg<uint8_t, 2, 10>>()));
+ EXPECT_EQ(
+ 0, (RangeSize<
+ FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>()));
+
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 0, 3>>()));
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint16_t, 2, 5>>()));
+ EXPECT_EQ(5, (RangeSize<FakeUrbg<uint16_t, 2, 6>>()));
+ EXPECT_EQ(18, (RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()));
+ EXPECT_EQ(
+ 0, (RangeSize<
+ FakeUrbg<uint16_t, 0, (std::numeric_limits<uint16_t>::max)()>>()));
+
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 0, 3>>()));
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint32_t, 2, 5>>()));
+ EXPECT_EQ(5, (RangeSize<FakeUrbg<uint32_t, 2, 6>>()));
+ EXPECT_EQ(18, (RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()));
+ EXPECT_EQ(0, (RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()));
+ EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()));
+ EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()));
+ EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()));
+ EXPECT_EQ(
+ 0, (RangeSize<
+ FakeUrbg<uint32_t, 0, (std::numeric_limits<uint32_t>::max)()>>()));
+
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 0, 3>>()));
+ EXPECT_EQ(4, (RangeSize<FakeUrbg<uint64_t, 2, 5>>()));
+ EXPECT_EQ(5, (RangeSize<FakeUrbg<uint64_t, 2, 6>>()));
+ EXPECT_EQ(18, (RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()));
+ EXPECT_EQ(0x100000000, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()));
+ EXPECT_EQ(0xffffffff, (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()));
+ EXPECT_EQ(0xfffffffe, (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()));
+ EXPECT_EQ(0xfffffffd, (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()));
+ EXPECT_EQ(0, (RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffff>>()));
+ EXPECT_EQ(0xffffffffffffffff,
+ (RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffff>>()));
+ EXPECT_EQ(0xfffffffffffffffe,
+ (RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffe>>()));
+ EXPECT_EQ(0xfffffffffffffffd,
+ (RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffe>>()));
+ EXPECT_EQ(
+ 0, (RangeSize<
+ FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>()));
+}
+
+// The constants need to be choosen so that an infinite rejection loop doesn't
+// happen...
+using Urng1_5bit = FakeUrbg<uint8_t, 0, 2, 0>; // ~1.5 bits (range 3)
+using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
+using Urng22bits = FakeUrbg<uint32_t, 0, 0x3fffff, 0x301020>;
+using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>; // ~31.9 bits
+using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+using Urng33bits =
+ FakeUrbg<uint64_t, 1, 0x1ffffffff, 0x013301033>; // ~32.9 bits
+using Urng63bits = FakeUrbg<uint64_t, 1, 0xfffffffffffffffe,
+ 0xfedcba9012345678>; // ~63.9 bits
+using Urng64bits =
+ FakeUrbg<uint64_t, 0, 0xffffffffffffffff, 0x123456780fedcba9>;
+
+TEST(FastUniformBitsTest, OutputsUpTo32Bits) {
+ // Tests that how values are composed; the single-bit deltas should be spread
+ // across each invocation.
+ Urng1_5bit urng1_5;
+ Urng4bits urng4;
+ Urng22bits urng22;
+ Urng31bits urng31;
+ Urng32bits urng32;
+ Urng33bits urng33;
+ Urng63bits urng63;
+ Urng64bits urng64;
+
+ // 8-bit types
+ {
+ FastUniformBits<uint8_t> fast8;
+ EXPECT_EQ(0x0, fast8(urng1_5));
+ EXPECT_EQ(0x11, fast8(urng4));
+ EXPECT_EQ(0x20, fast8(urng22));
+ EXPECT_EQ(0x2, fast8(urng31));
+ EXPECT_EQ(0x1, fast8(urng32));
+ EXPECT_EQ(0x32, fast8(urng33));
+ EXPECT_EQ(0x77, fast8(urng63));
+ EXPECT_EQ(0xa9, fast8(urng64));
+ }
+
+ // 16-bit types
+ {
+ FastUniformBits<uint16_t> fast16;
+ EXPECT_EQ(0x0, fast16(urng1_5));
+ EXPECT_EQ(0x1111, fast16(urng4));
+ EXPECT_EQ(0x1020, fast16(urng22));
+ EXPECT_EQ(0x0f02, fast16(urng31));
+ EXPECT_EQ(0x0f01, fast16(urng32));
+ EXPECT_EQ(0x1032, fast16(urng33));
+ EXPECT_EQ(0x5677, fast16(urng63));
+ EXPECT_EQ(0xcba9, fast16(urng64));
+ }
+
+ // 32-bit types
+ {
+ FastUniformBits<uint32_t> fast32;
+ EXPECT_EQ(0x0, fast32(urng1_5));
+ EXPECT_EQ(0x11111111, fast32(urng4));
+ EXPECT_EQ(0x08301020, fast32(urng22));
+ EXPECT_EQ(0x0f020f02, fast32(urng31));
+ EXPECT_EQ(0x74010f01, fast32(urng32));
+ EXPECT_EQ(0x13301032, fast32(urng33));
+ EXPECT_EQ(0x12345677, fast32(urng63));
+ EXPECT_EQ(0x0fedcba9, fast32(urng64));
+ }
+}
+
+TEST(FastUniformBitsTest, Outputs64Bits) {
+ // Tests that how values are composed; the single-bit deltas should be spread
+ // across each invocation.
+ FastUniformBits<uint64_t> fast64;
+
+ {
+ FakeUrbg<uint8_t, 0, 1, 0> urng0;
+ FakeUrbg<uint8_t, 0, 1, 1> urng1;
+ Urng4bits urng4;
+ Urng22bits urng22;
+ Urng31bits urng31;
+ Urng32bits urng32;
+ Urng33bits urng33;
+ Urng63bits urng63;
+ Urng64bits urng64;
+
+ // somewhat degenerate cases only create a single bit.
+ EXPECT_EQ(0x0, fast64(urng0));
+ EXPECT_EQ(64, urng0.calls);
+ EXPECT_EQ(0xffffffffffffffff, fast64(urng1));
+ EXPECT_EQ(64, urng1.calls);
+
+ // less degenerate cases.
+ EXPECT_EQ(0x1111111111111111, fast64(urng4));
+ EXPECT_EQ(16, urng4.calls);
+ EXPECT_EQ(0x01020c0408301020, fast64(urng22));
+ EXPECT_EQ(3, urng22.calls);
+ EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
+ EXPECT_EQ(3, urng31.calls);
+ EXPECT_EQ(0x74010f0174010f01, fast64(urng32));
+ EXPECT_EQ(2, urng32.calls);
+ EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+ EXPECT_EQ(3, urng33.calls);
+ EXPECT_EQ(0x1234567712345677, fast64(urng63));
+ EXPECT_EQ(2, urng63.calls);
+ EXPECT_EQ(0x123456780fedcba9, fast64(urng64));
+ EXPECT_EQ(1, urng64.calls);
+ }
+
+ // The 1.5 bit case is somewhat interesting in that the algorithm refinement
+ // causes one extra small sample. Comments here reference the names used in
+ // [rand.adapt.ibits] that correspond to this case.
+ {
+ Urng1_5bit urng1_5;
+
+ // w = 64
+ // R = 3
+ // m = 1
+ // n' = 64
+ // w0' = 1
+ // y0' = 2
+ // n = (1 <= 0) > 64 : 65 = 65
+ // n0 = 65 - (64%65) = 1
+ // n1 = 64
+ // w0 = 0
+ // y0 = 3
+ // w1 = 1
+ // y1 = 2
+ EXPECT_EQ(0x0, fast64(urng1_5));
+ EXPECT_EQ(65, urng1_5.calls);
+ }
+
+ // Validate rejections for non-power-of-2 cases.
+ {
+ Urng1_5bit urng1_5(true);
+ Urng31bits urng31(true);
+ Urng33bits urng33(true);
+ Urng63bits urng63(true);
+
+ // For 1.5 bits, there would be 1+2*64, except the first
+ // value was accepted and shifted off the end.
+ EXPECT_EQ(0, fast64(urng1_5));
+ EXPECT_EQ(128, urng1_5.calls);
+ EXPECT_EQ(0x387811c3c0870f02, fast64(urng31));
+ EXPECT_EQ(6, urng31.calls);
+ EXPECT_EQ(0x808194040cb01032, fast64(urng33));
+ EXPECT_EQ(6, urng33.calls);
+ EXPECT_EQ(0x1234567712345677, fast64(urng63));
+ EXPECT_EQ(4, urng63.calls);
+ }
+}
+
+TEST(FastUniformBitsTest, URBG32bitRegression) {
+ // Validate with deterministic 32-bit std::minstd_rand
+ // to ensure that operator() performs as expected.
+
+ EXPECT_EQ(2147483646, RangeSize<std::minstd_rand>());
+ EXPECT_EQ(30, IntegerLog2(RangeSize<std::minstd_rand>()));
+
+ std::minstd_rand gen(1);
+ FastUniformBits<uint64_t> fast64;
+
+ EXPECT_EQ(0x05e47095f8791f45, fast64(gen));
+ EXPECT_EQ(0x028be17e3c07c122, fast64(gen));
+ EXPECT_EQ(0x55d2847c1626e8c2, fast64(gen));
+}
+
+} // namespace
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath.h
new file mode 100644
index 00000000000..963b7690f1a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath.h
@@ -0,0 +1,57 @@
+// 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_FASTMATH_H_
+#define ABSL_RANDOM_INTERNAL_FASTMATH_H_
+
+// This file contains fast math functions (bitwise ops as well as some others)
+// which are implementation details of various absl random number distributions.
+
+#include <cassert>
+#include <cmath>
+#include <cstdint>
+
+#include "absl/numeric/bits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Compute log2(n) using integer operations.
+// While std::log2 is more accurate than std::log(n) / std::log(2), for
+// very large numbers--those close to std::numeric_limits<uint64_t>::max() - 2,
+// for instance--std::log2 rounds up rather than down, which introduces
+// definite skew in the results.
+inline int IntLog2Floor(uint64_t n) {
+ return (n <= 1) ? 0 : (63 - countl_zero(n));
+}
+inline int IntLog2Ceil(uint64_t n) {
+ return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
+}
+
+inline double StirlingLogFactorial(double n) {
+ assert(n >= 1);
+ // Using Stirling's approximation.
+ constexpr double kLog2PI = 1.83787706640934548356;
+ const double logn = std::log(n);
+ const double ninv = 1.0 / static_cast<double>(n);
+ return n * logn - n + 0.5 * (kLog2PI + logn) + (1.0 / 12.0) * ninv -
+ (1.0 / 360.0) * ninv * ninv * ninv;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_FASTMATH_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath_test.cc
new file mode 100644
index 00000000000..0d6f9dc1577
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/fastmath_test.cc
@@ -0,0 +1,97 @@
+// 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.
+
+#include "absl/random/internal/fastmath.h"
+
+#include "gtest/gtest.h"
+
+#if defined(__native_client__) || defined(__EMSCRIPTEN__)
+// NACL has a less accurate implementation of std::log2 than most of
+// the other platforms. For some values which should have integral results,
+// sometimes NACL returns slightly larger values.
+//
+// The MUSL libc used by emscripten also has a similar bug.
+#define ABSL_RANDOM_INACCURATE_LOG2
+#endif
+
+namespace {
+
+TEST(FastMathTest, IntLog2FloorTest) {
+ using absl::random_internal::IntLog2Floor;
+ constexpr uint64_t kZero = 0;
+ EXPECT_EQ(0, IntLog2Floor(0)); // boundary. return 0.
+ EXPECT_EQ(0, IntLog2Floor(1));
+ EXPECT_EQ(1, IntLog2Floor(2));
+ EXPECT_EQ(63, IntLog2Floor(~kZero));
+
+ // A boundary case: Converting 0xffffffffffffffff requires > 53
+ // bits of precision, so the conversion to double rounds up,
+ // and the result of std::log2(x) > IntLog2Floor(x).
+ EXPECT_LT(IntLog2Floor(~kZero), static_cast<int>(std::log2(~kZero)));
+
+ for (int i = 0; i < 64; i++) {
+ const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i;
+ EXPECT_EQ(i, IntLog2Floor(i_pow_2));
+ EXPECT_EQ(i, static_cast<int>(std::log2(i_pow_2)));
+
+ uint64_t y = i_pow_2;
+ for (int j = i - 1; j > 0; --j) {
+ y = y | (i_pow_2 >> j);
+ EXPECT_EQ(i, IntLog2Floor(y));
+ }
+ }
+}
+
+TEST(FastMathTest, IntLog2CeilTest) {
+ using absl::random_internal::IntLog2Ceil;
+ constexpr uint64_t kZero = 0;
+ EXPECT_EQ(0, IntLog2Ceil(0)); // boundary. return 0.
+ EXPECT_EQ(0, IntLog2Ceil(1));
+ EXPECT_EQ(1, IntLog2Ceil(2));
+ EXPECT_EQ(64, IntLog2Ceil(~kZero));
+
+ // A boundary case: Converting 0xffffffffffffffff requires > 53
+ // bits of precision, so the conversion to double rounds up,
+ // and the result of std::log2(x) > IntLog2Floor(x).
+ EXPECT_LE(IntLog2Ceil(~kZero), static_cast<int>(std::log2(~kZero)));
+
+ for (int i = 0; i < 64; i++) {
+ const uint64_t i_pow_2 = static_cast<uint64_t>(1) << i;
+ EXPECT_EQ(i, IntLog2Ceil(i_pow_2));
+#ifndef ABSL_RANDOM_INACCURATE_LOG2
+ EXPECT_EQ(i, static_cast<int>(std::ceil(std::log2(i_pow_2))));
+#endif
+
+ uint64_t y = i_pow_2;
+ for (int j = i - 1; j > 0; --j) {
+ y = y | (i_pow_2 >> j);
+ EXPECT_EQ(i + 1, IntLog2Ceil(y));
+ }
+ }
+}
+
+TEST(FastMathTest, StirlingLogFactorial) {
+ using absl::random_internal::StirlingLogFactorial;
+
+ EXPECT_NEAR(StirlingLogFactorial(1.0), 0, 1e-3);
+ EXPECT_NEAR(StirlingLogFactorial(1.50), 0.284683, 1e-3);
+ EXPECT_NEAR(StirlingLogFactorial(2.0), 0.69314718056, 1e-4);
+
+ for (int i = 2; i < 50; i++) {
+ double d = static_cast<double>(i);
+ EXPECT_NEAR(StirlingLogFactorial(d), std::lgamma(d + 1), 3e-5);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc
new file mode 100644
index 00000000000..a95333d55f5
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc
@@ -0,0 +1,143 @@
+// 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.
+
+// Generates gaussian_distribution.cc
+//
+// $ blaze run :gaussian_distribution_gentables > gaussian_distribution.cc
+//
+#include "absl/random/gaussian_distribution.h"
+
+#include <cmath>
+#include <cstddef>
+#include <iostream>
+#include <limits>
+#include <string>
+
+#include "absl/base/macros.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+template <typename T, size_t N>
+void FormatArrayContents(std::ostream* os, T (&data)[N]) {
+ if (!std::numeric_limits<T>::is_exact) {
+ // Note: T is either an integer or a float.
+ // float requires higher precision to ensure that values are
+ // reproduced exactly.
+ // Trivia: C99 has hexadecimal floating point literals, but C++11 does not.
+ // Using them would remove all concern of precision loss.
+ os->precision(std::numeric_limits<T>::max_digits10 + 2);
+ }
+ *os << " {";
+ std::string separator = "";
+ for (size_t i = 0; i < N; ++i) {
+ *os << separator << data[i];
+ if ((i + 1) % 3 != 0) {
+ separator = ", ";
+ } else {
+ separator = ",\n ";
+ }
+ }
+ *os << "}";
+}
+
+} // namespace
+
+class TableGenerator : public gaussian_distribution_base {
+ public:
+ TableGenerator();
+ void Print(std::ostream* os);
+
+ using gaussian_distribution_base::kMask;
+ using gaussian_distribution_base::kR;
+ using gaussian_distribution_base::kV;
+
+ private:
+ Tables tables_;
+};
+
+// Ziggurat gaussian initialization. For an explanation of the algorithm, see
+// the Marsaglia paper, "The Ziggurat Method for Generating Random Variables".
+// http://www.jstatsoft.org/v05/i08/
+//
+// Further details are available in the Doornik paper
+// https://www.doornik.com/research/ziggurat.pdf
+//
+TableGenerator::TableGenerator() {
+ // The constants here should match the values in gaussian_distribution.h
+ static constexpr int kC = kMask + 1;
+
+ static_assert((ABSL_ARRAYSIZE(tables_.x) == kC + 1),
+ "xArray must be length kMask + 2");
+
+ static_assert((ABSL_ARRAYSIZE(tables_.x) == ABSL_ARRAYSIZE(tables_.f)),
+ "fx and x arrays must be identical length");
+
+ auto f = [](double x) { return std::exp(-0.5 * x * x); };
+ auto f_inv = [](double x) { return std::sqrt(-2.0 * std::log(x)); };
+
+ tables_.x[0] = kV / f(kR);
+ tables_.f[0] = f(tables_.x[0]);
+
+ tables_.x[1] = kR;
+ tables_.f[1] = f(tables_.x[1]);
+
+ tables_.x[kC] = 0.0;
+ tables_.f[kC] = f(tables_.x[kC]); // 1.0
+
+ for (int i = 2; i < kC; i++) {
+ double v = (kV / tables_.x[i - 1]) + tables_.f[i - 1];
+ tables_.x[i] = f_inv(v);
+ tables_.f[i] = v;
+ }
+}
+
+void TableGenerator::Print(std::ostream* os) {
+ *os << "// BEGIN GENERATED CODE; DO NOT EDIT\n"
+ "// clang-format off\n"
+ "\n"
+ "#include \"absl/random/gaussian_distribution.h\"\n"
+ "\n"
+ "namespace absl {\n"
+ "ABSL_NAMESPACE_BEGIN\n"
+ "namespace random_internal {\n"
+ "\n"
+ "const gaussian_distribution_base::Tables\n"
+ " gaussian_distribution_base::zg_ = {\n";
+ FormatArrayContents(os, tables_.x);
+ *os << ",\n";
+ FormatArrayContents(os, tables_.f);
+ *os << "};\n"
+ "\n"
+ "} // namespace random_internal\n"
+ "ABSL_NAMESPACE_END\n"
+ "} // namespace absl\n"
+ "\n"
+ "// clang-format on\n"
+ "// END GENERATED CODE";
+ *os << std::endl;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+int main(int, char**) {
+ std::cerr << "\nCopy the output to gaussian_distribution.cc" << std::endl;
+ absl::random_internal::TableGenerator generator;
+ generator.Print(&std::cout);
+ return 0;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real.h
new file mode 100644
index 00000000000..4f62873d5d8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real.h
@@ -0,0 +1,146 @@
+// 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_GENERATE_REAL_H_
+#define ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
+
+// This file contains some implementation details which are used by one or more
+// of the absl random number distributions.
+
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
+#include "absl/random/internal/fastmath.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Tristate tag types controlling the output of GenerateRealFromBits.
+struct GeneratePositiveTag {};
+struct GenerateNegativeTag {};
+struct GenerateSignedTag {};
+
+// GenerateRealFromBits generates a single real value from a single 64-bit
+// `bits` with template fields controlling the output.
+//
+// The `SignedTag` parameter controls whether positive, negative,
+// or either signed/unsigned may be returned.
+// When SignedTag == GeneratePositiveTag, range is U(0, 1)
+// When SignedTag == GenerateNegativeTag, range is U(-1, 0)
+// When SignedTag == GenerateSignedTag, range is U(-1, 1)
+//
+// When the `IncludeZero` parameter is true, the function may return 0 for some
+// inputs, otherwise it never returns 0.
+//
+// When a value in U(0,1) is required, use:
+// Uniform64ToReal<double, PositiveValueT, true>;
+//
+// When a value in U(-1,1) is required, use:
+// Uniform64ToReal<double, SignedValueT, false>;
+//
+// This generates more distinct values than the mathematical equivalent
+// `U(0, 1) * 2.0 - 1.0`.
+//
+// Scaling the result by powers of 2 (and avoiding a multiply) is also possible:
+// GenerateRealFromBits<double>(..., -1); => U(0, 0.5)
+// GenerateRealFromBits<double>(..., 1); => U(0, 2)
+//
+template <typename RealType, // Real type, either float or double.
+ typename SignedTag = GeneratePositiveTag, // Whether a positive,
+ // negative, or signed
+ // value is generated.
+ bool IncludeZero = true>
+inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 0) {
+ using real_type = RealType;
+ using uint_type = absl::conditional_t<std::is_same<real_type, float>::value,
+ uint32_t, uint64_t>;
+
+ static_assert(
+ (std::is_same<double, real_type>::value ||
+ std::is_same<float, real_type>::value),
+ "GenerateRealFromBits must be parameterized by either float or double.");
+
+ static_assert(sizeof(uint_type) == sizeof(real_type),
+ "Mismatched unsinged and real types.");
+
+ static_assert((std::numeric_limits<real_type>::is_iec559 &&
+ std::numeric_limits<real_type>::radix == 2),
+ "RealType representation is not IEEE 754 binary.");
+
+ static_assert((std::is_same<SignedTag, GeneratePositiveTag>::value ||
+ std::is_same<SignedTag, GenerateNegativeTag>::value ||
+ std::is_same<SignedTag, GenerateSignedTag>::value),
+ "");
+
+ static constexpr int kExp = std::numeric_limits<real_type>::digits - 1;
+ static constexpr uint_type kMask = (static_cast<uint_type>(1) << kExp) - 1u;
+ static constexpr int kUintBits = sizeof(uint_type) * 8;
+
+ int exp = exp_bias + int{std::numeric_limits<real_type>::max_exponent - 2};
+
+ // Determine the sign bit.
+ // Depending on the SignedTag, this may use the left-most bit
+ // or it may be a constant value.
+ uint_type sign = std::is_same<SignedTag, GenerateNegativeTag>::value
+ ? (static_cast<uint_type>(1) << (kUintBits - 1))
+ : 0;
+ if (std::is_same<SignedTag, GenerateSignedTag>::value) {
+ if (std::is_same<uint_type, uint64_t>::value) {
+ sign = bits & uint64_t{0x8000000000000000};
+ }
+ if (std::is_same<uint_type, uint32_t>::value) {
+ const uint64_t tmp = bits & uint64_t{0x8000000000000000};
+ sign = static_cast<uint32_t>(tmp >> 32);
+ }
+ // adjust the bits and the exponent to account for removing
+ // the leading bit.
+ bits = bits & uint64_t{0x7FFFFFFFFFFFFFFF};
+ exp++;
+ }
+ if (IncludeZero) {
+ if (bits == 0u) return 0;
+ }
+
+ // Number of leading zeros is mapped to the exponent: 2^-clz
+ // bits is 0..01xxxxxx. After shifting, we're left with 1xxx...0..0
+ int clz = countl_zero(bits);
+ bits <<= (IncludeZero ? clz : (clz & 63)); // remove 0-bits.
+ exp -= clz; // set the exponent.
+ bits >>= (63 - kExp);
+
+ // Construct the 32-bit or 64-bit IEEE 754 floating-point value from
+ // the individual fields: sign, exp, mantissa(bits).
+ uint_type val =
+ (std::is_same<SignedTag, GeneratePositiveTag>::value ? 0u : sign) |
+ (static_cast<uint_type>(exp) << kExp) |
+ (static_cast<uint_type>(bits) & kMask);
+
+ // bit_cast to the output-type
+ real_type result;
+ memcpy(static_cast<void*>(&result), static_cast<const void*>(&val),
+ sizeof(result));
+ return result;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_GENERATE_REAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real_test.cc
new file mode 100644
index 00000000000..b099dbf35fe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/generate_real_test.cc
@@ -0,0 +1,496 @@
+// 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.
+
+#include "absl/random/internal/generate_real.h"
+
+#include <cfloat>
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/numeric/bits.h"
+
+ABSL_FLAG(int64_t, absl_random_test_trials, 50000,
+ "Number of trials for the probability tests.");
+
+using absl::random_internal::GenerateNegativeTag;
+using absl::random_internal::GeneratePositiveTag;
+using absl::random_internal::GenerateRealFromBits;
+using absl::random_internal::GenerateSignedTag;
+
+namespace {
+
+TEST(GenerateRealTest, U64ToFloat_Positive_NoZero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GeneratePositiveTag, false>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 2.710505431e-20f);
+ EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);
+ EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Positive_Zero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);
+ EXPECT_EQ(ToFloat(0x0000000000000001), 5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), 0.5);
+ EXPECT_EQ(ToFloat(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Negative_NoZero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GenerateNegativeTag, false>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), -2.710505431e-20f);
+ EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);
+ EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Negative_Zero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GenerateNegativeTag, true>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 0.0);
+ EXPECT_EQ(ToFloat(0x0000000000000001), -5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), -0.5);
+ EXPECT_EQ(ToFloat(0x8000000000000001), -0.5);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Signed_NoZero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GenerateSignedTag, false>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), -5.421010862e-20f);
+ EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Signed_Zero_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GenerateSignedTag, true>(a);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 0);
+ EXPECT_EQ(ToFloat(0x0000000000000001), 1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 0.9999999404f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), 0);
+ EXPECT_EQ(ToFloat(0x8000000000000001), -1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloat_Signed_Bias_Test) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GenerateSignedTag, true>(a, 1);
+ };
+ EXPECT_EQ(ToFloat(0x0000000000000000), 0);
+ EXPECT_EQ(ToFloat(0x0000000000000001), 2 * 1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), 2 * 0.9999999404f);
+ EXPECT_EQ(ToFloat(0x8000000000000000), 0);
+ EXPECT_EQ(ToFloat(0x8000000000000001), 2 * -1.084202172e-19f);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 2 * -0.9999999404f);
+}
+
+TEST(GenerateRealTest, U64ToFloatTest) {
+ auto ToFloat = [](uint64_t a) -> float {
+ return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
+ };
+
+ EXPECT_EQ(ToFloat(0x0000000000000000), 0.0f);
+
+ EXPECT_EQ(ToFloat(0x8000000000000000), 0.5f);
+ EXPECT_EQ(ToFloat(0x8000000000000001), 0.5f);
+ EXPECT_EQ(ToFloat(0x800000FFFFFFFFFF), 0.5f);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), 0.9999999404f);
+
+ EXPECT_GT(ToFloat(0x0000000000000001), 0.0f);
+
+ EXPECT_NE(ToFloat(0x7FFFFF0000000000), ToFloat(0x7FFFFEFFFFFFFFFF));
+
+ EXPECT_LT(ToFloat(0xFFFFFFFFFFFFFFFF), 1.0f);
+ int32_t two_to_24 = 1 << 24;
+ EXPECT_EQ(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24),
+ two_to_24 - 1);
+ EXPECT_NE(static_cast<int32_t>(ToFloat(0xFFFFFFFFFFFFFFFF) * two_to_24 * 2),
+ two_to_24 * 2 - 1);
+ EXPECT_EQ(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFF0000000000));
+ EXPECT_NE(ToFloat(0xFFFFFFFFFFFFFFFF), ToFloat(0xFFFFFEFFFFFFFFFF));
+ EXPECT_EQ(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF8000000000));
+ EXPECT_NE(ToFloat(0x7FFFFFFFFFFFFFFF), ToFloat(0x7FFFFF7FFFFFFFFF));
+ EXPECT_EQ(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFC000000000));
+ EXPECT_NE(ToFloat(0x3FFFFFFFFFFFFFFF), ToFloat(0x3FFFFFBFFFFFFFFF));
+
+ // For values where every bit counts, the values scale as multiples of the
+ // input.
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_EQ(i * ToFloat(0x0000000000000001), ToFloat(i));
+ }
+
+ // For each i: value generated from (1 << i).
+ float exp_values[64];
+ exp_values[63] = 0.5f;
+ for (int i = 62; i >= 0; --i) exp_values[i] = 0.5f * exp_values[i + 1];
+ constexpr uint64_t one = 1;
+ for (int i = 0; i < 64; ++i) {
+ EXPECT_EQ(ToFloat(one << i), exp_values[i]);
+ for (int j = 1; j < FLT_MANT_DIG && i - j >= 0; ++j) {
+ EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]);
+ EXPECT_EQ(ToFloat((one << i) + (one << (i - j))),
+ exp_values[i] + exp_values[i - j]);
+ }
+ for (int j = FLT_MANT_DIG; i - j >= 0; ++j) {
+ EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]);
+ EXPECT_EQ(ToFloat((one << i) + (one << (i - j))), exp_values[i]);
+ }
+ }
+}
+
+TEST(GenerateRealTest, U64ToDouble_Positive_NoZero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GeneratePositiveTag, false>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 2.710505431213761085e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000002), 1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);
+ EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Positive_Zero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);
+ EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Negative_NoZero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateNegativeTag, false>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), -2.710505431213761085e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Negative_Zero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateNegativeTag, true>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
+ EXPECT_EQ(ToDouble(0x0000000000000001), -5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000002), -1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0x8000000000000000), -0.5);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -0.5);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Signed_NoZero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateSignedTag, false>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978);
+ EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_Signed_Zero_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateSignedTag, true>(a);
+ };
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978);
+ EXPECT_EQ(ToDouble(0x8000000000000000), 0);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978);
+}
+
+TEST(GenerateRealTest, U64ToDouble_GenerateSignedTag_Bias_Test) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateSignedTag, true>(a, -1);
+ };
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19 / 2);
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), 0.999999999999999888978 / 2);
+ EXPECT_EQ(ToDouble(0x8000000000000000), 0);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19 / 2);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), -0.999999999999999888978 / 2);
+}
+
+TEST(GenerateRealTest, U64ToDoubleTest) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GeneratePositiveTag, true>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
+ EXPECT_EQ(ToDouble(0x0000000000000000), 0.0);
+
+ EXPECT_EQ(ToDouble(0x0000000000000001), 5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x7fffffffffffffef), 0.499999999999999944489);
+ EXPECT_EQ(ToDouble(0x8000000000000000), 0.5);
+
+ // For values > 0.5, RandU64ToDouble discards up to 11 bits. (64-53).
+ EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0x80000000000007FF), 0.5);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), 0.999999999999999888978);
+ EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF));
+
+ EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFF), 1.0);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF800));
+ EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFF), ToDouble(0xFFFFFFFFFFFFF7FF));
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00));
+ EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFBFF));
+ EXPECT_EQ(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFE00));
+ EXPECT_NE(ToDouble(0x3FFFFFFFFFFFFFFF), ToDouble(0x3FFFFFFFFFFFFDFF));
+
+ EXPECT_EQ(ToDouble(0x1000000000000001), 0.0625);
+ EXPECT_EQ(ToDouble(0x2000000000000001), 0.125);
+ EXPECT_EQ(ToDouble(0x3000000000000001), 0.1875);
+ EXPECT_EQ(ToDouble(0x4000000000000001), 0.25);
+ EXPECT_EQ(ToDouble(0x5000000000000001), 0.3125);
+ EXPECT_EQ(ToDouble(0x6000000000000001), 0.375);
+ EXPECT_EQ(ToDouble(0x7000000000000001), 0.4375);
+ EXPECT_EQ(ToDouble(0x8000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0x9000000000000001), 0.5625);
+ EXPECT_EQ(ToDouble(0xa000000000000001), 0.625);
+ EXPECT_EQ(ToDouble(0xb000000000000001), 0.6875);
+ EXPECT_EQ(ToDouble(0xc000000000000001), 0.75);
+ EXPECT_EQ(ToDouble(0xd000000000000001), 0.8125);
+ EXPECT_EQ(ToDouble(0xe000000000000001), 0.875);
+ EXPECT_EQ(ToDouble(0xf000000000000001), 0.9375);
+
+ // Large powers of 2.
+ int64_t two_to_53 = int64_t{1} << 53;
+ EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53),
+ two_to_53 - 1);
+ EXPECT_NE(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53 * 2),
+ two_to_53 * 2 - 1);
+
+ // For values where every bit counts, the values scale as multiples of the
+ // input.
+ for (int i = 0; i < 100; ++i) {
+ EXPECT_EQ(i * ToDouble(0x0000000000000001), ToDouble(i));
+ }
+
+ // For each i: value generated from (1 << i).
+ double exp_values[64];
+ exp_values[63] = 0.5;
+ for (int i = 62; i >= 0; --i) exp_values[i] = 0.5 * exp_values[i + 1];
+ constexpr uint64_t one = 1;
+ for (int i = 0; i < 64; ++i) {
+ EXPECT_EQ(ToDouble(one << i), exp_values[i]);
+ for (int j = 1; j < DBL_MANT_DIG && i - j >= 0; ++j) {
+ EXPECT_NE(exp_values[i] + exp_values[i - j], exp_values[i]);
+ EXPECT_EQ(ToDouble((one << i) + (one << (i - j))),
+ exp_values[i] + exp_values[i - j]);
+ }
+ for (int j = DBL_MANT_DIG; i - j >= 0; ++j) {
+ EXPECT_EQ(exp_values[i] + exp_values[i - j], exp_values[i]);
+ EXPECT_EQ(ToDouble((one << i) + (one << (i - j))), exp_values[i]);
+ }
+ }
+}
+
+TEST(GenerateRealTest, U64ToDoubleSignedTest) {
+ auto ToDouble = [](uint64_t a) {
+ return GenerateRealFromBits<double, GenerateSignedTag, false>(a);
+ };
+
+ EXPECT_EQ(ToDouble(0x0000000000000000), 5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x0000000000000001), 1.084202172485504434e-19);
+
+ EXPECT_EQ(ToDouble(0x8000000000000000), -5.42101086242752217004e-20);
+ EXPECT_EQ(ToDouble(0x8000000000000001), -1.084202172485504434e-19);
+
+ const double e_plus = ToDouble(0x0000000000000001);
+ const double e_minus = ToDouble(0x8000000000000001);
+ EXPECT_EQ(e_plus, 1.084202172485504434e-19);
+ EXPECT_EQ(e_minus, -1.084202172485504434e-19);
+
+ EXPECT_EQ(ToDouble(0x3fffffffffffffef), 0.499999999999999944489);
+ EXPECT_EQ(ToDouble(0xbfffffffffffffef), -0.499999999999999944489);
+
+ // For values > 0.5, RandU64ToDouble discards up to 10 bits. (63-53).
+ EXPECT_EQ(ToDouble(0x4000000000000000), 0.5);
+ EXPECT_EQ(ToDouble(0x4000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0x40000000000003FF), 0.5);
+
+ EXPECT_EQ(ToDouble(0xC000000000000000), -0.5);
+ EXPECT_EQ(ToDouble(0xC000000000000001), -0.5);
+ EXPECT_EQ(ToDouble(0xC0000000000003FF), -0.5);
+
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFe), 0.999999999999999888978);
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999999999888978);
+
+ EXPECT_NE(ToDouble(0x7FFFFFFFFFFFF800), ToDouble(0x7FFFFFFFFFFFF7FF));
+
+ EXPECT_LT(ToDouble(0x7FFFFFFFFFFFFFFF), 1.0);
+ EXPECT_GT(ToDouble(0x7FFFFFFFFFFFFFFF), 0.9999999999);
+
+ EXPECT_GT(ToDouble(0xFFFFFFFFFFFFFFFe), -1.0);
+ EXPECT_LT(ToDouble(0xFFFFFFFFFFFFFFFe), -0.999999999);
+
+ EXPECT_EQ(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFFC00));
+ EXPECT_EQ(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFFC00));
+ EXPECT_NE(ToDouble(0xFFFFFFFFFFFFFFFe), ToDouble(0xFFFFFFFFFFFFF3FF));
+ EXPECT_NE(ToDouble(0x7FFFFFFFFFFFFFFF), ToDouble(0x7FFFFFFFFFFFF3FF));
+
+ EXPECT_EQ(ToDouble(0x1000000000000001), 0.125);
+ EXPECT_EQ(ToDouble(0x2000000000000001), 0.25);
+ EXPECT_EQ(ToDouble(0x3000000000000001), 0.375);
+ EXPECT_EQ(ToDouble(0x4000000000000001), 0.5);
+ EXPECT_EQ(ToDouble(0x5000000000000001), 0.625);
+ EXPECT_EQ(ToDouble(0x6000000000000001), 0.75);
+ EXPECT_EQ(ToDouble(0x7000000000000001), 0.875);
+ EXPECT_EQ(ToDouble(0x7800000000000001), 0.9375);
+ EXPECT_EQ(ToDouble(0x7c00000000000001), 0.96875);
+ EXPECT_EQ(ToDouble(0x7e00000000000001), 0.984375);
+ EXPECT_EQ(ToDouble(0x7f00000000000001), 0.9921875);
+
+ // 0x8000000000000000 ~= 0
+ EXPECT_EQ(ToDouble(0x9000000000000001), -0.125);
+ EXPECT_EQ(ToDouble(0xa000000000000001), -0.25);
+ EXPECT_EQ(ToDouble(0xb000000000000001), -0.375);
+ EXPECT_EQ(ToDouble(0xc000000000000001), -0.5);
+ EXPECT_EQ(ToDouble(0xd000000000000001), -0.625);
+ EXPECT_EQ(ToDouble(0xe000000000000001), -0.75);
+ EXPECT_EQ(ToDouble(0xf000000000000001), -0.875);
+
+ // Large powers of 2.
+ int64_t two_to_53 = int64_t{1} << 53;
+ EXPECT_EQ(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53),
+ two_to_53 - 1);
+ EXPECT_EQ(static_cast<int64_t>(ToDouble(0xFFFFFFFFFFFFFFFF) * two_to_53),
+ -(two_to_53 - 1));
+
+ EXPECT_NE(static_cast<int64_t>(ToDouble(0x7FFFFFFFFFFFFFFF) * two_to_53 * 2),
+ two_to_53 * 2 - 1);
+
+ // For values where every bit counts, the values scale as multiples of the
+ // input.
+ for (int i = 1; i < 100; ++i) {
+ EXPECT_EQ(i * e_plus, ToDouble(i)) << i;
+ EXPECT_EQ(i * e_minus, ToDouble(0x8000000000000000 | i)) << i;
+ }
+}
+
+TEST(GenerateRealTest, ExhaustiveFloat) {
+ auto ToFloat = [](uint64_t a) {
+ return GenerateRealFromBits<float, GeneratePositiveTag, true>(a);
+ };
+
+ // Rely on RandU64ToFloat generating values from greatest to least when
+ // supplied with uint64_t values from greatest (0xfff...) to least (0x0).
+ // Thus, this algorithm stores the previous value, and if the new value is at
+ // greater than or equal to the previous value, then there is a collision in
+ // the generation algorithm.
+ //
+ // Use the computation below to convert the random value into a result:
+ // double res = a() * (1.0f - sample) + b() * sample;
+ float last_f = 1.0, last_g = 2.0;
+ uint64_t f_collisions = 0, g_collisions = 0;
+ uint64_t f_unique = 0, g_unique = 0;
+ uint64_t total = 0;
+ auto count = [&](const float r) {
+ total++;
+ // `f` is mapped to the range [0, 1) (default)
+ const float f = 0.0f * (1.0f - r) + 1.0f * r;
+ if (f >= last_f) {
+ f_collisions++;
+ } else {
+ f_unique++;
+ last_f = f;
+ }
+ // `g` is mapped to the range [1, 2)
+ const float g = 1.0f * (1.0f - r) + 2.0f * r;
+ if (g >= last_g) {
+ g_collisions++;
+ } else {
+ g_unique++;
+ last_g = g;
+ }
+ };
+
+ size_t limit = absl::GetFlag(FLAGS_absl_random_test_trials);
+
+ // Generate all uint64_t which have unique floating point values.
+ // Counting down from 0xFFFFFFFFFFFFFFFFu ... 0x0u
+ uint64_t x = ~uint64_t(0);
+ for (; x != 0 && limit > 0;) {
+ constexpr int kDig = (64 - FLT_MANT_DIG);
+ // Set a decrement value & the next point at which to change
+ // the decrement value. By default these are 1, 0.
+ uint64_t dec = 1;
+ uint64_t chk = 0;
+
+ // Adjust decrement and check value based on how many leading 0
+ // bits are set in the current value.
+ const int clz = absl::countl_zero(x);
+ if (clz < kDig) {
+ dec <<= (kDig - clz);
+ chk = (~uint64_t(0)) >> (clz + 1);
+ }
+ for (; x > chk && limit > 0; x -= dec) {
+ count(ToFloat(x));
+ --limit;
+ }
+ }
+
+ static_assert(FLT_MANT_DIG == 24,
+ "The float type is expected to have a 24 bit mantissa.");
+
+ if (limit != 0) {
+ // There are between 2^28 and 2^29 unique values in the range [0, 1). For
+ // the low values of x, there are 2^24 -1 unique values. Once x > 2^24,
+ // there are 40 * 2^24 unique values. Thus:
+ // (2 + 4 + 8 ... + 2^23) + 40 * 2^23
+ EXPECT_LT(1 << 28, f_unique);
+ EXPECT_EQ((1 << 24) + 40 * (1 << 23) - 1, f_unique);
+ EXPECT_EQ(total, f_unique);
+ EXPECT_EQ(0, f_collisions);
+
+ // Expect at least 2^23 unique values for the range [1, 2)
+ EXPECT_LE(1 << 23, g_unique);
+ EXPECT_EQ(total - g_unique, g_collisions);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver.h
new file mode 100644
index 00000000000..e6e242ee1e6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver.h
@@ -0,0 +1,245 @@
+// 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_IOSTREAM_STATE_SAVER_H_
+#define ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
+
+#include <cmath>
+#include <iostream>
+#include <limits>
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/int128.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// The null_state_saver does nothing.
+template <typename T>
+class null_state_saver {
+ public:
+ using stream_type = T;
+ using flags_type = std::ios_base::fmtflags;
+
+ null_state_saver(T&, flags_type) {}
+ ~null_state_saver() {}
+};
+
+// ostream_state_saver is a RAII object to save and restore the common
+// basic_ostream flags used when implementing `operator <<()` on any of
+// the absl random distributions.
+template <typename OStream>
+class ostream_state_saver {
+ public:
+ using ostream_type = OStream;
+ using flags_type = std::ios_base::fmtflags;
+ using fill_type = typename ostream_type::char_type;
+ using precision_type = std::streamsize;
+
+ ostream_state_saver(ostream_type& os, // NOLINT(runtime/references)
+ flags_type flags, fill_type fill)
+ : os_(os),
+ flags_(os.flags(flags)),
+ fill_(os.fill(fill)),
+ precision_(os.precision()) {
+ // Save state in initialized variables.
+ }
+
+ ~ostream_state_saver() {
+ // Restore saved state.
+ os_.precision(precision_);
+ os_.fill(fill_);
+ os_.flags(flags_);
+ }
+
+ private:
+ ostream_type& os_;
+ const flags_type flags_;
+ const fill_type fill_;
+ const precision_type precision_;
+};
+
+#if defined(__NDK_MAJOR__) && __NDK_MAJOR__ < 16
+#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 1
+#else
+#define ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT 0
+#endif
+
+template <typename CharT, typename Traits>
+ostream_state_saver<std::basic_ostream<CharT, Traits>> make_ostream_state_saver(
+ std::basic_ostream<CharT, Traits>& os, // NOLINT(runtime/references)
+ std::ios_base::fmtflags flags = std::ios_base::dec | std::ios_base::left |
+#if ABSL_RANDOM_INTERNAL_IOSTREAM_HEXFLOAT
+ std::ios_base::fixed |
+#endif
+ std::ios_base::scientific) {
+ using result_type = ostream_state_saver<std::basic_ostream<CharT, Traits>>;
+ return result_type(os, flags, os.widen(' '));
+}
+
+template <typename T>
+typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
+ null_state_saver<T>>
+make_ostream_state_saver(T& is, // NOLINT(runtime/references)
+ std::ios_base::fmtflags flags = std::ios_base::dec) {
+ std::cerr << "null_state_saver";
+ using result_type = null_state_saver<T>;
+ return result_type(is, flags);
+}
+
+// stream_precision_helper<type>::kPrecision returns the base 10 precision
+// required to stream and reconstruct a real type exact binary value through
+// a binary->decimal->binary transition.
+template <typename T>
+struct stream_precision_helper {
+ // max_digits10 may be 0 on MSVC; if so, use digits10 + 3.
+ static constexpr int kPrecision =
+ (std::numeric_limits<T>::max_digits10 > std::numeric_limits<T>::digits10)
+ ? std::numeric_limits<T>::max_digits10
+ : (std::numeric_limits<T>::digits10 + 3);
+};
+
+template <>
+struct stream_precision_helper<float> {
+ static constexpr int kPrecision = 9;
+};
+template <>
+struct stream_precision_helper<double> {
+ static constexpr int kPrecision = 17;
+};
+template <>
+struct stream_precision_helper<long double> {
+ static constexpr int kPrecision = 36; // assuming fp128
+};
+
+// istream_state_saver is a RAII object to save and restore the common
+// std::basic_istream<> flags used when implementing `operator >>()` on any of
+// the absl random distributions.
+template <typename IStream>
+class istream_state_saver {
+ public:
+ using istream_type = IStream;
+ using flags_type = std::ios_base::fmtflags;
+
+ istream_state_saver(istream_type& is, // NOLINT(runtime/references)
+ flags_type flags)
+ : is_(is), flags_(is.flags(flags)) {}
+
+ ~istream_state_saver() { is_.flags(flags_); }
+
+ private:
+ istream_type& is_;
+ flags_type flags_;
+};
+
+template <typename CharT, typename Traits>
+istream_state_saver<std::basic_istream<CharT, Traits>> make_istream_state_saver(
+ std::basic_istream<CharT, Traits>& is, // NOLINT(runtime/references)
+ std::ios_base::fmtflags flags = std::ios_base::dec |
+ std::ios_base::scientific |
+ std::ios_base::skipws) {
+ using result_type = istream_state_saver<std::basic_istream<CharT, Traits>>;
+ return result_type(is, flags);
+}
+
+template <typename T>
+typename absl::enable_if_t<!std::is_base_of<std::ios_base, T>::value,
+ null_state_saver<T>>
+make_istream_state_saver(T& is, // NOLINT(runtime/references)
+ std::ios_base::fmtflags flags = std::ios_base::dec) {
+ using result_type = null_state_saver<T>;
+ return result_type(is, flags);
+}
+
+// stream_format_type<T> is a helper struct to convert types which
+// basic_iostream cannot output as decimal numbers into types which
+// basic_iostream can output as decimal numbers. Specifically:
+// * signed/unsigned char-width types are converted to int.
+// * TODO(lar): __int128 => uint128, except there is no operator << yet.
+//
+template <typename T>
+struct stream_format_type
+ : public std::conditional<(sizeof(T) == sizeof(char)), int, T> {};
+
+// stream_u128_helper allows us to write out either absl::uint128 or
+// __uint128_t types in the same way, which enables their use as internal
+// state of PRNG engines.
+template <typename T>
+struct stream_u128_helper;
+
+template <>
+struct stream_u128_helper<absl::uint128> {
+ template <typename IStream>
+ inline absl::uint128 read(IStream& in) {
+ uint64_t h = 0;
+ uint64_t l = 0;
+ in >> h >> l;
+ return absl::MakeUint128(h, l);
+ }
+
+ template <typename OStream>
+ inline void write(absl::uint128 val, OStream& out) {
+ uint64_t h = absl::Uint128High64(val);
+ uint64_t l = absl::Uint128Low64(val);
+ out << h << out.fill() << l;
+ }
+};
+
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+template <>
+struct stream_u128_helper<__uint128_t> {
+ template <typename IStream>
+ inline __uint128_t read(IStream& in) {
+ uint64_t h = 0;
+ uint64_t l = 0;
+ in >> h >> l;
+ return (static_cast<__uint128_t>(h) << 64) | l;
+ }
+
+ template <typename OStream>
+ inline void write(__uint128_t val, OStream& out) {
+ uint64_t h = static_cast<uint64_t>(val >> 64u);
+ uint64_t l = static_cast<uint64_t>(val);
+ out << h << out.fill() << l;
+ }
+};
+#endif
+
+template <typename FloatType, typename IStream>
+inline FloatType read_floating_point(IStream& is) {
+ static_assert(std::is_floating_point<FloatType>::value, "");
+ FloatType dest;
+ is >> dest;
+ // Parsing a double value may report a subnormal value as an error
+ // despite being able to represent it.
+ // See https://stackoverflow.com/q/52410931/3286653
+ // It may also report an underflow when parsing DOUBLE_MIN as an
+ // ERANGE error, as the parsed value may be smaller than DOUBLE_MIN
+ // and rounded up.
+ // See: https://stackoverflow.com/q/42005462
+ if (is.fail() &&
+ (std::fabs(dest) == (std::numeric_limits<FloatType>::min)() ||
+ std::fpclassify(dest) == FP_SUBNORMAL)) {
+ is.clear(is.rdstate() & (~std::ios_base::failbit));
+ }
+ return dest;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_IOSTREAM_STATE_SAVER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
new file mode 100644
index 00000000000..6e66266cc08
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
@@ -0,0 +1,372 @@
+// 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.
+
+#include "absl/random/internal/iostream_state_saver.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <sstream>
+#include <string>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::random_internal::make_istream_state_saver;
+using absl::random_internal::make_ostream_state_saver;
+using absl::random_internal::stream_precision_helper;
+
+template <typename T>
+typename absl::enable_if_t<std::is_integral<T>::value, T> //
+StreamRoundTrip(T t) {
+ std::stringstream ss;
+ {
+ auto saver = make_ostream_state_saver(ss);
+ ss.precision(stream_precision_helper<T>::kPrecision);
+ ss << t;
+ }
+ T result = 0;
+ {
+ auto saver = make_istream_state_saver(ss);
+ ss >> result;
+ }
+ EXPECT_FALSE(ss.fail()) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+
+ return result;
+}
+
+template <typename T>
+typename absl::enable_if_t<std::is_floating_point<T>::value, T> //
+StreamRoundTrip(T t) {
+ std::stringstream ss;
+ {
+ auto saver = make_ostream_state_saver(ss);
+ ss.precision(stream_precision_helper<T>::kPrecision);
+ ss << t;
+ }
+ T result = 0;
+ {
+ auto saver = make_istream_state_saver(ss);
+ result = absl::random_internal::read_floating_point<T>(ss);
+ }
+ EXPECT_FALSE(ss.fail()) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+
+ return result;
+}
+
+TEST(IOStreamStateSaver, BasicSaverState) {
+ std::stringstream ss;
+ ss.precision(2);
+ ss.fill('x');
+ ss.flags(std::ios_base::dec | std::ios_base::right);
+
+ {
+ auto saver = make_ostream_state_saver(ss);
+ ss.precision(10);
+ EXPECT_NE('x', ss.fill());
+ EXPECT_EQ(10, ss.precision());
+ EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags());
+
+ ss << 1.23;
+ }
+
+ EXPECT_EQ('x', ss.fill());
+ EXPECT_EQ(2, ss.precision());
+ EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags());
+}
+
+TEST(IOStreamStateSaver, RoundTripInts) {
+ const uint64_t kUintValues[] = {
+ 0,
+ 1,
+ static_cast<uint64_t>(-1),
+ 2,
+ static_cast<uint64_t>(-2),
+
+ 1 << 7,
+ 1 << 8,
+ 1 << 16,
+ 1ull << 32,
+ 1ull << 50,
+ 1ull << 62,
+ 1ull << 63,
+
+ (1 << 7) - 1,
+ (1 << 8) - 1,
+ (1 << 16) - 1,
+ (1ull << 32) - 1,
+ (1ull << 50) - 1,
+ (1ull << 62) - 1,
+ (1ull << 63) - 1,
+
+ static_cast<uint64_t>(-(1 << 8)),
+ static_cast<uint64_t>(-(1 << 16)),
+ static_cast<uint64_t>(-(1ll << 32)),
+ static_cast<uint64_t>(-(1ll << 50)),
+ static_cast<uint64_t>(-(1ll << 62)),
+
+ static_cast<uint64_t>(-(1 << 8) - 1),
+ static_cast<uint64_t>(-(1 << 16) - 1),
+ static_cast<uint64_t>(-(1ll << 32) - 1),
+ static_cast<uint64_t>(-(1ll << 50) - 1),
+ static_cast<uint64_t>(-(1ll << 62) - 1),
+ };
+
+ for (const uint64_t u : kUintValues) {
+ EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u));
+
+ int64_t x = static_cast<int64_t>(u);
+ EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
+
+ double d = static_cast<double>(x);
+ EXPECT_EQ(d, StreamRoundTrip<double>(d));
+
+ float f = d;
+ EXPECT_EQ(f, StreamRoundTrip<float>(f));
+ }
+}
+
+TEST(IOStreamStateSaver, RoundTripFloats) {
+ static_assert(
+ stream_precision_helper<float>::kPrecision >= 9,
+ "stream_precision_helper<float>::kPrecision should be at least 9");
+
+ const float kValues[] = {
+ 1,
+ std::nextafter(1.0f, 0.0f), // 1 - epsilon
+ std::nextafter(1.0f, 2.0f), // 1 + epsilon
+
+ 1.0e+1f,
+ 1.0e-1f,
+ 1.0e+2f,
+ 1.0e-2f,
+ 1.0e+10f,
+ 1.0e-10f,
+
+ 0.00000051110000111311111111f,
+ -0.00000051110000111211111111f,
+
+ 1.234678912345678912345e+6f,
+ 1.234678912345678912345e-6f,
+ 1.234678912345678912345e+30f,
+ 1.234678912345678912345e-30f,
+ 1.234678912345678912345e+38f,
+ 1.0234678912345678912345e-38f,
+
+ // Boundary cases.
+ std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::epsilon(),
+ std::nextafter(std::numeric_limits<float>::min(),
+ 1.0f), // min + epsilon
+ std::numeric_limits<float>::min(), // smallest normal
+ // There are some errors dealing with denorms on apple platforms.
+ std::numeric_limits<float>::denorm_min(), // smallest denorm
+ std::numeric_limits<float>::min() / 2,
+ std::nextafter(std::numeric_limits<float>::min(),
+ 0.0f), // denorm_max
+ std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f),
+ };
+
+ for (const float f : kValues) {
+ EXPECT_EQ(f, StreamRoundTrip<float>(f));
+ EXPECT_EQ(-f, StreamRoundTrip<float>(-f));
+
+ double d = f;
+ EXPECT_EQ(d, StreamRoundTrip<double>(d));
+ EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
+
+ // Avoid undefined behavior (overflow/underflow).
+ if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&
+ f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {
+ int64_t x = static_cast<int64_t>(f);
+ EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
+ }
+ }
+}
+
+TEST(IOStreamStateSaver, RoundTripDoubles) {
+ static_assert(
+ stream_precision_helper<double>::kPrecision >= 17,
+ "stream_precision_helper<double>::kPrecision should be at least 17");
+
+ const double kValues[] = {
+ 1,
+ std::nextafter(1.0, 0.0), // 1 - epsilon
+ std::nextafter(1.0, 2.0), // 1 + epsilon
+
+ 1.0e+1,
+ 1.0e-1,
+ 1.0e+2,
+ 1.0e-2,
+ 1.0e+10,
+ 1.0e-10,
+
+ 0.00000051110000111311111111,
+ -0.00000051110000111211111111,
+
+ 1.234678912345678912345e+6,
+ 1.234678912345678912345e-6,
+ 1.234678912345678912345e+30,
+ 1.234678912345678912345e-30,
+ 1.234678912345678912345e+38,
+ 1.0234678912345678912345e-38,
+
+ 1.0e+100,
+ 1.0e-100,
+ 1.234678912345678912345e+308,
+ 1.0234678912345678912345e-308,
+ 2.22507385850720138e-308,
+
+ // Boundary cases.
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::lowest(),
+ std::numeric_limits<double>::epsilon(),
+ std::nextafter(std::numeric_limits<double>::min(),
+ 1.0), // min + epsilon
+ std::numeric_limits<double>::min(), // smallest normal
+ // There are some errors dealing with denorms on apple platforms.
+ std::numeric_limits<double>::denorm_min(), // smallest denorm
+ std::numeric_limits<double>::min() / 2,
+ std::nextafter(std::numeric_limits<double>::min(),
+ 0.0), // denorm_max
+ std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f),
+ };
+
+ for (const double d : kValues) {
+ EXPECT_EQ(d, StreamRoundTrip<double>(d));
+ EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
+
+ // Avoid undefined behavior (overflow/underflow).
+ if (d <= std::numeric_limits<float>::max() &&
+ d >= std::numeric_limits<float>::lowest()) {
+ float f = static_cast<float>(d);
+ EXPECT_EQ(f, StreamRoundTrip<float>(f));
+ }
+
+ // Avoid undefined behavior (overflow/underflow).
+ if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&
+ d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {
+ int64_t x = static_cast<int64_t>(d);
+ EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
+ }
+ }
+}
+
+TEST(IOStreamStateSaver, RoundTripLongDoubles) {
+ // Technically, C++ only guarantees that long double is at least as large as a
+ // double. Practically it varies from 64-bits to 128-bits.
+ //
+ // So it is best to consider long double a best-effort extended precision
+ // type.
+
+ static_assert(
+ stream_precision_helper<long double>::kPrecision >= 36,
+ "stream_precision_helper<long double>::kPrecision should be at least 36");
+
+ using real_type = long double;
+ const real_type kValues[] = {
+ 1,
+ std::nextafter(1.0, 0.0), // 1 - epsilon
+ std::nextafter(1.0, 2.0), // 1 + epsilon
+
+ 1.0e+1,
+ 1.0e-1,
+ 1.0e+2,
+ 1.0e-2,
+ 1.0e+10,
+ 1.0e-10,
+
+ 0.00000051110000111311111111,
+ -0.00000051110000111211111111,
+
+ 1.2346789123456789123456789123456789e+6,
+ 1.2346789123456789123456789123456789e-6,
+ 1.2346789123456789123456789123456789e+30,
+ 1.2346789123456789123456789123456789e-30,
+ 1.2346789123456789123456789123456789e+38,
+ 1.2346789123456789123456789123456789e-38,
+ 1.2346789123456789123456789123456789e+308,
+ 1.2346789123456789123456789123456789e-308,
+
+ 1.0e+100,
+ 1.0e-100,
+ 1.234678912345678912345e+308,
+ 1.0234678912345678912345e-308,
+
+ // Boundary cases.
+ std::numeric_limits<real_type>::max(),
+ std::numeric_limits<real_type>::lowest(),
+ std::numeric_limits<real_type>::epsilon(),
+ std::nextafter(std::numeric_limits<real_type>::min(),
+ real_type(1)), // min + epsilon
+ std::numeric_limits<real_type>::min(), // smallest normal
+ // There are some errors dealing with denorms on apple platforms.
+ std::numeric_limits<real_type>::denorm_min(), // smallest denorm
+ std::numeric_limits<real_type>::min() / 2,
+ std::nextafter(std::numeric_limits<real_type>::min(),
+ 0.0), // denorm_max
+ std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f),
+ };
+
+ int index = -1;
+ for (const long double dd : kValues) {
+ index++;
+ EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index;
+ EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index;
+
+ // Avoid undefined behavior (overflow/underflow).
+ if (dd <= std::numeric_limits<double>::max() &&
+ dd >= std::numeric_limits<double>::lowest()) {
+ double d = static_cast<double>(dd);
+ EXPECT_EQ(d, StreamRoundTrip<double>(d));
+ }
+
+ // Avoid undefined behavior (overflow/underflow).
+ if (dd <= std::numeric_limits<int64_t>::max() &&
+ dd >= std::numeric_limits<int64_t>::lowest()) {
+ int64_t x = static_cast<int64_t>(dd);
+ EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
+ }
+ }
+}
+
+TEST(StrToDTest, DoubleMin) {
+ const char kV[] = "2.22507385850720138e-308";
+ char* end;
+ double x = std::strtod(kV, &end);
+ EXPECT_EQ(std::numeric_limits<double>::min(), x);
+ // errno may equal ERANGE.
+}
+
+TEST(StrToDTest, DoubleDenormMin) {
+ const char kV[] = "4.94065645841246544e-324";
+ char* end;
+ double x = std::strtod(kV, &end);
+ EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x);
+ // errno may equal ERANGE.
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_helpers.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_helpers.h
new file mode 100644
index 00000000000..9d6ab21ef54
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_helpers.h
@@ -0,0 +1,134 @@
+//
+// 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 <tuple>
+#include <type_traits>
+
+#include "absl/base/internal/fast_type_id.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// 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 implemenation 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).
+ //
+ // 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 auto MockFor(MockURBG& m)
+ -> decltype(m.template RegisterMock<
+ typename KeySignature<KeyT>::result_type,
+ typename KeySignature<KeyT>::arg_tuple_type>(
+ m, std::declval<IdType>())) {
+ return m.template RegisterMock<typename KeySignature<KeyT>::result_type,
+ typename KeySignature<KeyT>::arg_tuple_type>(
+ m, ::absl::base_internal::FastTypeId<KeyT>());
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_MOCK_HELPERS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_overload_set.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_overload_set.h
new file mode 100644
index 00000000000..0d9c6c120c0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/mock_overload_set.h
@@ -0,0 +1,100 @@
+//
+// 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 <type_traits>
+
+#include "gmock/gmock.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 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 Ret, typename... Args>
+struct MockSingleOverload<DistrT, 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).gmock_Call(matchers...)) {
+ static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
+ "Mocking requires an absl::MockingBitGen");
+ return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matchers...);
+ }
+};
+
+template <typename DistrT, typename Ret, typename Arg, typename... Args>
+struct MockSingleOverload<DistrT, 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).gmock_Call(matcher,
+ matchers...)) {
+ static_assert(std::is_base_of<MockingBitGen, MockURBG>::value,
+ "Mocking requires an absl::MockingBitGen");
+ return MockHelpers::MockFor<KeyT>(gen).gmock_Call(matcher, matchers...);
+ }
+};
+
+// 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>
+struct MockOverloadSet;
+
+template <typename DistrT, typename Sig>
+struct MockOverloadSet<DistrT, Sig> : public MockSingleOverload<DistrT, Sig> {
+ using MockSingleOverload<DistrT, Sig>::gmock_Call;
+};
+
+template <typename DistrT, typename FirstSig, typename... Rest>
+struct MockOverloadSet<DistrT, FirstSig, Rest...>
+ : public MockSingleOverload<DistrT, FirstSig>,
+ public MockOverloadSet<DistrT, Rest...> {
+ using MockSingleOverload<DistrT, FirstSig>::gmock_Call;
+ using MockOverloadSet<DistrT, Rest...>::gmock_Call;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif // ABSL_RANDOM_INTERNAL_MOCK_OVERLOAD_SET_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.cc
new file mode 100644
index 00000000000..c9181813f7f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.cc
@@ -0,0 +1,804 @@
+// 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.
+
+#include "absl/random/internal/nanobenchmark.h"
+
+#include <sys/types.h>
+
+#include <algorithm> // sort
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring> // memcpy
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_engine.h"
+
+// OS
+#if defined(_WIN32) || defined(_WIN64)
+#define ABSL_OS_WIN
+#include <windows.h> // NOLINT
+
+#elif defined(__ANDROID__)
+#define ABSL_OS_ANDROID
+
+#elif defined(__linux__)
+#define ABSL_OS_LINUX
+#include <sched.h> // NOLINT
+#include <sys/syscall.h> // NOLINT
+#endif
+
+#if defined(ABSL_ARCH_X86_64) && !defined(ABSL_OS_WIN)
+#include <cpuid.h> // NOLINT
+#endif
+
+// __ppc_get_timebase_freq
+#if defined(ABSL_ARCH_PPC)
+#include <sys/platform/ppc.h> // NOLINT
+#endif
+
+// clock_gettime
+#if defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
+#include <time.h> // NOLINT
+#endif
+
+// ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE prevents inlining of the method.
+#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __attribute__((noinline))
+#elif defined(_MSC_VER)
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE __declspec(noinline)
+#else
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal_nanobenchmark {
+namespace {
+
+// For code folding.
+namespace platform {
+#if defined(ABSL_ARCH_X86_64)
+
+// TODO(janwas): Merge with the one in randen_hwaes.cc?
+void Cpuid(const uint32_t level, const uint32_t count,
+ uint32_t* ABSL_RANDOM_INTERNAL_RESTRICT abcd) {
+#if defined(ABSL_OS_WIN)
+ int regs[4];
+ __cpuidex(regs, level, count);
+ for (int i = 0; i < 4; ++i) {
+ abcd[i] = regs[i];
+ }
+#else
+ uint32_t a, b, c, d;
+ __cpuid_count(level, count, a, b, c, d);
+ abcd[0] = a;
+ abcd[1] = b;
+ abcd[2] = c;
+ abcd[3] = d;
+#endif
+}
+
+std::string BrandString() {
+ char brand_string[49];
+ uint32_t abcd[4];
+
+ // Check if brand string is supported (it is on all reasonable Intel/AMD)
+ Cpuid(0x80000000U, 0, abcd);
+ if (abcd[0] < 0x80000004U) {
+ return std::string();
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ Cpuid(0x80000002U + i, 0, abcd);
+ memcpy(brand_string + i * 16, &abcd, sizeof(abcd));
+ }
+ brand_string[48] = 0;
+ return brand_string;
+}
+
+// Returns the frequency quoted inside the brand string. This does not
+// account for throttling nor Turbo Boost.
+double NominalClockRate() {
+ const std::string& brand_string = BrandString();
+ // Brand strings include the maximum configured frequency. These prefixes are
+ // defined by Intel CPUID documentation.
+ const char* prefixes[3] = {"MHz", "GHz", "THz"};
+ const double multipliers[3] = {1E6, 1E9, 1E12};
+ for (size_t i = 0; i < 3; ++i) {
+ const size_t pos_prefix = brand_string.find(prefixes[i]);
+ if (pos_prefix != std::string::npos) {
+ const size_t pos_space = brand_string.rfind(' ', pos_prefix - 1);
+ if (pos_space != std::string::npos) {
+ const std::string digits =
+ brand_string.substr(pos_space + 1, pos_prefix - pos_space - 1);
+ return std::stod(digits) * multipliers[i];
+ }
+ }
+ }
+
+ return 0.0;
+}
+
+#endif // ABSL_ARCH_X86_64
+} // namespace platform
+
+// Prevents the compiler from eliding the computations that led to "output".
+template <class T>
+inline void PreventElision(T&& output) {
+#ifndef ABSL_OS_WIN
+ // Works by indicating to the compiler that "output" is being read and
+ // modified. The +r constraint avoids unnecessary writes to memory, but only
+ // works for built-in types (typically FuncOutput).
+ asm volatile("" : "+r"(output) : : "memory");
+#else
+ // MSVC does not support inline assembly anymore (and never supported GCC's
+ // RTL constraints). Self-assignment with #pragma optimize("off") might be
+ // expected to prevent elision, but it does not with MSVC 2015. Type-punning
+ // with volatile pointers generates inefficient code on MSVC 2017.
+ static std::atomic<T> dummy(T{});
+ dummy.store(output, std::memory_order_relaxed);
+#endif
+}
+
+namespace timer {
+
+// Start/Stop return absolute timestamps and must be placed immediately before
+// and after the region to measure. We provide separate Start/Stop functions
+// because they use different fences.
+//
+// Background: RDTSC is not 'serializing'; earlier instructions may complete
+// after it, and/or later instructions may complete before it. 'Fences' ensure
+// regions' elapsed times are independent of such reordering. The only
+// documented unprivileged serializing instruction is CPUID, which acts as a
+// full fence (no reordering across it in either direction). Unfortunately
+// the latency of CPUID varies wildly (perhaps made worse by not initializing
+// its EAX input). Because it cannot reliably be deducted from the region's
+// elapsed time, it must not be included in the region to measure (i.e.
+// between the two RDTSC).
+//
+// The newer RDTSCP is sometimes described as serializing, but it actually
+// only serves as a half-fence with release semantics. Although all
+// instructions in the region will complete before the final timestamp is
+// captured, subsequent instructions may leak into the region and increase the
+// elapsed time. Inserting another fence after the final RDTSCP would prevent
+// such reordering without affecting the measured region.
+//
+// Fortunately, such a fence exists. The LFENCE instruction is only documented
+// to delay later loads until earlier loads are visible. However, Intel's
+// reference manual says it acts as a full fence (waiting until all earlier
+// instructions have completed, and delaying later instructions until it
+// completes). AMD assigns the same behavior to MFENCE.
+//
+// We need a fence before the initial RDTSC to prevent earlier instructions
+// from leaking into the region, and arguably another after RDTSC to avoid
+// region instructions from completing before the timestamp is recorded.
+// When surrounded by fences, the additional RDTSCP half-fence provides no
+// benefit, so the initial timestamp can be recorded via RDTSC, which has
+// lower overhead than RDTSCP because it does not read TSC_AUX. In summary,
+// we define Start = LFENCE/RDTSC/LFENCE; Stop = RDTSCP/LFENCE.
+//
+// Using Start+Start leads to higher variance and overhead than Stop+Stop.
+// However, Stop+Stop includes an LFENCE in the region measurements, which
+// adds a delay dependent on earlier loads. The combination of Start+Stop
+// is faster than Start+Start and more consistent than Stop+Stop because
+// the first LFENCE already delayed subsequent loads before the measured
+// region. This combination seems not to have been considered in prior work:
+// http://akaros.cs.berkeley.edu/lxr/akaros/kern/arch/x86/rdtsc_test.c
+//
+// Note: performance counters can measure 'exact' instructions-retired or
+// (unhalted) cycle counts. The RDPMC instruction is not serializing and also
+// requires fences. Unfortunately, it is not accessible on all OSes and we
+// prefer to avoid kernel-mode drivers. Performance counters are also affected
+// by several under/over-count errata, so we use the TSC instead.
+
+// Returns a 64-bit timestamp in unit of 'ticks'; to convert to seconds,
+// divide by InvariantTicksPerSecond.
+inline uint64_t Start64() {
+ uint64_t t;
+#if defined(ABSL_ARCH_PPC)
+ asm volatile("mfspr %0, %1" : "=r"(t) : "i"(268));
+#elif defined(ABSL_ARCH_X86_64)
+#if defined(ABSL_OS_WIN)
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+ t = __rdtsc();
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+#else
+ asm volatile(
+ "lfence\n\t"
+ "rdtsc\n\t"
+ "shl $32, %%rdx\n\t"
+ "or %%rdx, %0\n\t"
+ "lfence"
+ : "=a"(t)
+ :
+ // "memory" avoids reordering. rdx = TSC >> 32.
+ // "cc" = flags modified by SHL.
+ : "rdx", "memory", "cc");
+#endif
+#else
+ // Fall back to OS - unsure how to reliably query cntvct_el0 frequency.
+ timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ t = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+#endif
+ return t;
+}
+
+inline uint64_t Stop64() {
+ uint64_t t;
+#if defined(ABSL_ARCH_X86_64)
+#if defined(ABSL_OS_WIN)
+ _ReadWriteBarrier();
+ unsigned aux;
+ t = __rdtscp(&aux);
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+#else
+ // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx).
+ asm volatile(
+ "rdtscp\n\t"
+ "shl $32, %%rdx\n\t"
+ "or %%rdx, %0\n\t"
+ "lfence"
+ : "=a"(t)
+ :
+ // "memory" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32.
+ // "cc" = flags modified by SHL.
+ : "rcx", "rdx", "memory", "cc");
+#endif
+#else
+ t = Start64();
+#endif
+ return t;
+}
+
+// Returns a 32-bit timestamp with about 4 cycles less overhead than
+// Start64. Only suitable for measuring very short regions because the
+// timestamp overflows about once a second.
+inline uint32_t Start32() {
+ uint32_t t;
+#if defined(ABSL_ARCH_X86_64)
+#if defined(ABSL_OS_WIN)
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+ t = static_cast<uint32_t>(__rdtsc());
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+#else
+ asm volatile(
+ "lfence\n\t"
+ "rdtsc\n\t"
+ "lfence"
+ : "=a"(t)
+ :
+ // "memory" avoids reordering. rdx = TSC >> 32.
+ : "rdx", "memory");
+#endif
+#else
+ t = static_cast<uint32_t>(Start64());
+#endif
+ return t;
+}
+
+inline uint32_t Stop32() {
+ uint32_t t;
+#if defined(ABSL_ARCH_X86_64)
+#if defined(ABSL_OS_WIN)
+ _ReadWriteBarrier();
+ unsigned aux;
+ t = static_cast<uint32_t>(__rdtscp(&aux));
+ _ReadWriteBarrier();
+ _mm_lfence();
+ _ReadWriteBarrier();
+#else
+ // Use inline asm because __rdtscp generates code to store TSC_AUX (ecx).
+ asm volatile(
+ "rdtscp\n\t"
+ "lfence"
+ : "=a"(t)
+ :
+ // "memory" avoids reordering. rcx = TSC_AUX. rdx = TSC >> 32.
+ : "rcx", "rdx", "memory");
+#endif
+#else
+ t = static_cast<uint32_t>(Stop64());
+#endif
+ return t;
+}
+
+} // namespace timer
+
+namespace robust_statistics {
+
+// Sorts integral values in ascending order (e.g. for Mode). About 3x faster
+// than std::sort for input distributions with very few unique values.
+template <class T>
+void CountingSort(T* values, size_t num_values) {
+ // Unique values and their frequency (similar to flat_map).
+ using Unique = std::pair<T, int>;
+ std::vector<Unique> unique;
+ for (size_t i = 0; i < num_values; ++i) {
+ const T value = values[i];
+ const auto pos =
+ std::find_if(unique.begin(), unique.end(),
+ [value](const Unique u) { return u.first == value; });
+ if (pos == unique.end()) {
+ unique.push_back(std::make_pair(value, 1));
+ } else {
+ ++pos->second;
+ }
+ }
+
+ // Sort in ascending order of value (pair.first).
+ std::sort(unique.begin(), unique.end());
+
+ // Write that many copies of each unique value to the array.
+ T* ABSL_RANDOM_INTERNAL_RESTRICT p = values;
+ for (const auto& value_count : unique) {
+ std::fill(p, p + value_count.second, value_count.first);
+ p += value_count.second;
+ }
+ ABSL_RAW_CHECK(p == values + num_values, "Did not produce enough output");
+}
+
+// @return i in [idx_begin, idx_begin + half_count) that minimizes
+// sorted[i + half_count] - sorted[i].
+template <typename T>
+size_t MinRange(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted,
+ const size_t idx_begin, const size_t half_count) {
+ T min_range = (std::numeric_limits<T>::max)();
+ size_t min_idx = 0;
+
+ for (size_t idx = idx_begin; idx < idx_begin + half_count; ++idx) {
+ ABSL_RAW_CHECK(sorted[idx] <= sorted[idx + half_count], "Not sorted");
+ const T range = sorted[idx + half_count] - sorted[idx];
+ if (range < min_range) {
+ min_range = range;
+ min_idx = idx;
+ }
+ }
+
+ return min_idx;
+}
+
+// Returns an estimate of the mode by calling MinRange on successively
+// halved intervals. "sorted" must be in ascending order. This is the
+// Half Sample Mode estimator proposed by Bickel in "On a fast, robust
+// estimator of the mode", with complexity O(N log N). The mode is less
+// affected by outliers in highly-skewed distributions than the median.
+// The averaging operation below assumes "T" is an unsigned integer type.
+template <typename T>
+T ModeOfSorted(const T* const ABSL_RANDOM_INTERNAL_RESTRICT sorted,
+ const size_t num_values) {
+ size_t idx_begin = 0;
+ size_t half_count = num_values / 2;
+ while (half_count > 1) {
+ idx_begin = MinRange(sorted, idx_begin, half_count);
+ half_count >>= 1;
+ }
+
+ const T x = sorted[idx_begin + 0];
+ if (half_count == 0) {
+ return x;
+ }
+ ABSL_RAW_CHECK(half_count == 1, "Should stop at half_count=1");
+ const T average = (x + sorted[idx_begin + 1] + 1) / 2;
+ return average;
+}
+
+// Returns the mode. Side effect: sorts "values".
+template <typename T>
+T Mode(T* values, const size_t num_values) {
+ CountingSort(values, num_values);
+ return ModeOfSorted(values, num_values);
+}
+
+template <typename T, size_t N>
+T Mode(T (&values)[N]) {
+ return Mode(&values[0], N);
+}
+
+// Returns the median value. Side effect: sorts "values".
+template <typename T>
+T Median(T* values, const size_t num_values) {
+ ABSL_RAW_CHECK(num_values != 0, "Empty input");
+ std::sort(values, values + num_values);
+ const size_t half = num_values / 2;
+ // Odd count: return middle
+ if (num_values % 2) {
+ return values[half];
+ }
+ // Even count: return average of middle two.
+ return (values[half] + values[half - 1] + 1) / 2;
+}
+
+// Returns a robust measure of variability.
+template <typename T>
+T MedianAbsoluteDeviation(const T* values, const size_t num_values,
+ const T median) {
+ ABSL_RAW_CHECK(num_values != 0, "Empty input");
+ std::vector<T> abs_deviations;
+ abs_deviations.reserve(num_values);
+ for (size_t i = 0; i < num_values; ++i) {
+ const int64_t abs = std::abs(int64_t(values[i]) - int64_t(median));
+ abs_deviations.push_back(static_cast<T>(abs));
+ }
+ return Median(abs_deviations.data(), num_values);
+}
+
+} // namespace robust_statistics
+
+// Ticks := platform-specific timer values (CPU cycles on x86). Must be
+// unsigned to guarantee wraparound on overflow. 32 bit timers are faster to
+// read than 64 bit.
+using Ticks = uint32_t;
+
+// Returns timer overhead / minimum measurable difference.
+Ticks TimerResolution() {
+ // Nested loop avoids exceeding stack/L1 capacity.
+ Ticks repetitions[Params::kTimerSamples];
+ for (size_t rep = 0; rep < Params::kTimerSamples; ++rep) {
+ Ticks samples[Params::kTimerSamples];
+ for (size_t i = 0; i < Params::kTimerSamples; ++i) {
+ const Ticks t0 = timer::Start32();
+ const Ticks t1 = timer::Stop32();
+ samples[i] = t1 - t0;
+ }
+ repetitions[rep] = robust_statistics::Mode(samples);
+ }
+ return robust_statistics::Mode(repetitions);
+}
+
+static const Ticks timer_resolution = TimerResolution();
+
+// Estimates the expected value of "lambda" values with a variable number of
+// samples until the variability "rel_mad" is less than "max_rel_mad".
+template <class Lambda>
+Ticks SampleUntilStable(const double max_rel_mad, double* rel_mad,
+ const Params& p, const Lambda& lambda) {
+ auto measure_duration = [&lambda]() -> Ticks {
+ const Ticks t0 = timer::Start32();
+ lambda();
+ const Ticks t1 = timer::Stop32();
+ return t1 - t0;
+ };
+
+ // Choose initial samples_per_eval based on a single estimated duration.
+ Ticks est = measure_duration();
+ static const double ticks_per_second = InvariantTicksPerSecond();
+ const size_t ticks_per_eval = ticks_per_second * p.seconds_per_eval;
+ size_t samples_per_eval = ticks_per_eval / est;
+ samples_per_eval = (std::max)(samples_per_eval, p.min_samples_per_eval);
+
+ std::vector<Ticks> samples;
+ samples.reserve(1 + samples_per_eval);
+ samples.push_back(est);
+
+ // Percentage is too strict for tiny differences, so also allow a small
+ // absolute "median absolute deviation".
+ const Ticks max_abs_mad = (timer_resolution + 99) / 100;
+ *rel_mad = 0.0; // ensure initialized
+
+ for (size_t eval = 0; eval < p.max_evals; ++eval, samples_per_eval *= 2) {
+ samples.reserve(samples.size() + samples_per_eval);
+ for (size_t i = 0; i < samples_per_eval; ++i) {
+ const Ticks r = measure_duration();
+ samples.push_back(r);
+ }
+
+ if (samples.size() >= p.min_mode_samples) {
+ est = robust_statistics::Mode(samples.data(), samples.size());
+ } else {
+ // For "few" (depends also on the variance) samples, Median is safer.
+ est = robust_statistics::Median(samples.data(), samples.size());
+ }
+ ABSL_RAW_CHECK(est != 0, "Estimator returned zero duration");
+
+ // Median absolute deviation (mad) is a robust measure of 'variability'.
+ const Ticks abs_mad = robust_statistics::MedianAbsoluteDeviation(
+ samples.data(), samples.size(), est);
+ *rel_mad = static_cast<double>(static_cast<int>(abs_mad)) / est;
+
+ if (*rel_mad <= max_rel_mad || abs_mad <= max_abs_mad) {
+ if (p.verbose) {
+ ABSL_RAW_LOG(INFO,
+ "%6zu samples => %5u (abs_mad=%4u, rel_mad=%4.2f%%)\n",
+ samples.size(), est, abs_mad, *rel_mad * 100.0);
+ }
+ return est;
+ }
+ }
+
+ if (p.verbose) {
+ ABSL_RAW_LOG(WARNING,
+ "rel_mad=%4.2f%% still exceeds %4.2f%% after %6zu samples.\n",
+ *rel_mad * 100.0, max_rel_mad * 100.0, samples.size());
+ }
+ return est;
+}
+
+using InputVec = std::vector<FuncInput>;
+
+// Returns vector of unique input values.
+InputVec UniqueInputs(const FuncInput* inputs, const size_t num_inputs) {
+ InputVec unique(inputs, inputs + num_inputs);
+ std::sort(unique.begin(), unique.end());
+ unique.erase(std::unique(unique.begin(), unique.end()), unique.end());
+ return unique;
+}
+
+// Returns how often we need to call func for sufficient precision, or zero
+// on failure (e.g. the elapsed time is too long for a 32-bit tick count).
+size_t NumSkip(const Func func, const void* arg, const InputVec& unique,
+ const Params& p) {
+ // Min elapsed ticks for any input.
+ Ticks min_duration = ~0u;
+
+ for (const FuncInput input : unique) {
+ // Make sure a 32-bit timer is sufficient.
+ const uint64_t t0 = timer::Start64();
+ PreventElision(func(arg, input));
+ const uint64_t t1 = timer::Stop64();
+ const uint64_t elapsed = t1 - t0;
+ if (elapsed >= (1ULL << 30)) {
+ ABSL_RAW_LOG(WARNING,
+ "Measurement failed: need 64-bit timer for input=%zu\n",
+ static_cast<size_t>(input));
+ return 0;
+ }
+
+ double rel_mad;
+ const Ticks total = SampleUntilStable(
+ p.target_rel_mad, &rel_mad, p,
+ [func, arg, input]() { PreventElision(func(arg, input)); });
+ min_duration = (std::min)(min_duration, total - timer_resolution);
+ }
+
+ // Number of repetitions required to reach the target resolution.
+ const size_t max_skip = p.precision_divisor;
+ // Number of repetitions given the estimated duration.
+ const size_t num_skip =
+ min_duration == 0 ? 0 : (max_skip + min_duration - 1) / min_duration;
+ if (p.verbose) {
+ ABSL_RAW_LOG(INFO, "res=%u max_skip=%zu min_dur=%u num_skip=%zu\n",
+ timer_resolution, max_skip, min_duration, num_skip);
+ }
+ return num_skip;
+}
+
+// Replicates inputs until we can omit "num_skip" occurrences of an input.
+InputVec ReplicateInputs(const FuncInput* inputs, const size_t num_inputs,
+ const size_t num_unique, const size_t num_skip,
+ const Params& p) {
+ InputVec full;
+ if (num_unique == 1) {
+ full.assign(p.subset_ratio * num_skip, inputs[0]);
+ return full;
+ }
+
+ full.reserve(p.subset_ratio * num_skip * num_inputs);
+ for (size_t i = 0; i < p.subset_ratio * num_skip; ++i) {
+ full.insert(full.end(), inputs, inputs + num_inputs);
+ }
+ absl::random_internal::randen_engine<uint32_t> rng;
+ std::shuffle(full.begin(), full.end(), rng);
+ return full;
+}
+
+// Copies the "full" to "subset" in the same order, but with "num_skip"
+// randomly selected occurrences of "input_to_skip" removed.
+void FillSubset(const InputVec& full, const FuncInput input_to_skip,
+ const size_t num_skip, InputVec* subset) {
+ const size_t count = std::count(full.begin(), full.end(), input_to_skip);
+ // Generate num_skip random indices: which occurrence to skip.
+ std::vector<uint32_t> omit;
+ // Replacement for std::iota, not yet available in MSVC builds.
+ omit.reserve(count);
+ for (size_t i = 0; i < count; ++i) {
+ omit.push_back(i);
+ }
+ // omit[] is the same on every call, but that's OK because they identify the
+ // Nth instance of input_to_skip, so the position within full[] differs.
+ absl::random_internal::randen_engine<uint32_t> rng;
+ std::shuffle(omit.begin(), omit.end(), rng);
+ omit.resize(num_skip);
+ std::sort(omit.begin(), omit.end());
+
+ uint32_t occurrence = ~0u; // 0 after preincrement
+ size_t idx_omit = 0; // cursor within omit[]
+ size_t idx_subset = 0; // cursor within *subset
+ for (const FuncInput next : full) {
+ if (next == input_to_skip) {
+ ++occurrence;
+ // Haven't removed enough already
+ if (idx_omit < num_skip) {
+ // This one is up for removal
+ if (occurrence == omit[idx_omit]) {
+ ++idx_omit;
+ continue;
+ }
+ }
+ }
+ if (idx_subset < subset->size()) {
+ (*subset)[idx_subset++] = next;
+ }
+ }
+ ABSL_RAW_CHECK(idx_subset == subset->size(), "idx_subset not at end");
+ ABSL_RAW_CHECK(idx_omit == omit.size(), "idx_omit not at end");
+ ABSL_RAW_CHECK(occurrence == count - 1, "occurrence not at end");
+}
+
+// Returns total ticks elapsed for all inputs.
+Ticks TotalDuration(const Func func, const void* arg, const InputVec* inputs,
+ const Params& p, double* max_rel_mad) {
+ double rel_mad;
+ const Ticks duration =
+ SampleUntilStable(p.target_rel_mad, &rel_mad, p, [func, arg, inputs]() {
+ for (const FuncInput input : *inputs) {
+ PreventElision(func(arg, input));
+ }
+ });
+ *max_rel_mad = (std::max)(*max_rel_mad, rel_mad);
+ return duration;
+}
+
+// (Nearly) empty Func for measuring timer overhead/resolution.
+ABSL_RANDOM_INTERNAL_ATTRIBUTE_NEVER_INLINE FuncOutput
+EmptyFunc(const void* arg, const FuncInput input) {
+ return input;
+}
+
+// Returns overhead of accessing inputs[] and calling a function; this will
+// be deducted from future TotalDuration return values.
+Ticks Overhead(const void* arg, const InputVec* inputs, const Params& p) {
+ double rel_mad;
+ // Zero tolerance because repeatability is crucial and EmptyFunc is fast.
+ return SampleUntilStable(0.0, &rel_mad, p, [arg, inputs]() {
+ for (const FuncInput input : *inputs) {
+ PreventElision(EmptyFunc(arg, input));
+ }
+ });
+}
+
+} // namespace
+
+void PinThreadToCPU(int cpu) {
+ // We might migrate to another CPU before pinning below, but at least cpu
+ // will be one of the CPUs on which this thread ran.
+#if defined(ABSL_OS_WIN)
+ if (cpu < 0) {
+ cpu = static_cast<int>(GetCurrentProcessorNumber());
+ ABSL_RAW_CHECK(cpu >= 0, "PinThreadToCPU detect failed");
+ if (cpu >= 64) {
+ // NOTE: On wine, at least, GetCurrentProcessorNumber() sometimes returns
+ // a value > 64, which is out of range. When this happens, log a message
+ // and don't set a cpu affinity.
+ ABSL_RAW_LOG(ERROR, "Invalid CPU number: %d", cpu);
+ return;
+ }
+ } else if (cpu >= 64) {
+ // User specified an explicit CPU affinity > the valid range.
+ ABSL_RAW_LOG(FATAL, "Invalid CPU number: %d", cpu);
+ }
+ const DWORD_PTR prev = SetThreadAffinityMask(GetCurrentThread(), 1ULL << cpu);
+ ABSL_RAW_CHECK(prev != 0, "SetAffinity failed");
+#elif defined(ABSL_OS_LINUX) && !defined(ABSL_OS_ANDROID)
+ if (cpu < 0) {
+ cpu = sched_getcpu();
+ ABSL_RAW_CHECK(cpu >= 0, "PinThreadToCPU detect failed");
+ }
+ const pid_t pid = 0; // current thread
+ cpu_set_t set;
+ CPU_ZERO(&set);
+ CPU_SET(cpu, &set);
+ const int err = sched_setaffinity(pid, sizeof(set), &set);
+ ABSL_RAW_CHECK(err == 0, "SetAffinity failed");
+#endif
+}
+
+// Returns tick rate. Invariant means the tick counter frequency is independent
+// of CPU throttling or sleep. May be expensive, caller should cache the result.
+double InvariantTicksPerSecond() {
+#if defined(ABSL_ARCH_PPC)
+ return __ppc_get_timebase_freq();
+#elif defined(ABSL_ARCH_X86_64)
+ // We assume the TSC is invariant; it is on all recent Intel/AMD CPUs.
+ return platform::NominalClockRate();
+#else
+ // Fall back to clock_gettime nanoseconds.
+ return 1E9;
+#endif
+}
+
+size_t MeasureImpl(const Func func, const void* arg, const size_t num_skip,
+ const InputVec& unique, const InputVec& full,
+ const Params& p, Result* results) {
+ const float mul = 1.0f / static_cast<int>(num_skip);
+
+ InputVec subset(full.size() - num_skip);
+ const Ticks overhead = Overhead(arg, &full, p);
+ const Ticks overhead_skip = Overhead(arg, &subset, p);
+ if (overhead < overhead_skip) {
+ ABSL_RAW_LOG(WARNING, "Measurement failed: overhead %u < %u\n", overhead,
+ overhead_skip);
+ return 0;
+ }
+
+ if (p.verbose) {
+ ABSL_RAW_LOG(INFO, "#inputs=%5zu,%5zu overhead=%5u,%5u\n", full.size(),
+ subset.size(), overhead, overhead_skip);
+ }
+
+ double max_rel_mad = 0.0;
+ const Ticks total = TotalDuration(func, arg, &full, p, &max_rel_mad);
+
+ for (size_t i = 0; i < unique.size(); ++i) {
+ FillSubset(full, unique[i], num_skip, &subset);
+ const Ticks total_skip = TotalDuration(func, arg, &subset, p, &max_rel_mad);
+
+ if (total < total_skip) {
+ ABSL_RAW_LOG(WARNING, "Measurement failed: total %u < %u\n", total,
+ total_skip);
+ return 0;
+ }
+
+ const Ticks duration = (total - overhead) - (total_skip - overhead_skip);
+ results[i].input = unique[i];
+ results[i].ticks = duration * mul;
+ results[i].variability = max_rel_mad;
+ }
+
+ return unique.size();
+}
+
+size_t Measure(const Func func, const void* arg, const FuncInput* inputs,
+ const size_t num_inputs, Result* results, const Params& p) {
+ ABSL_RAW_CHECK(num_inputs != 0, "No inputs");
+
+ const InputVec unique = UniqueInputs(inputs, num_inputs);
+ const size_t num_skip = NumSkip(func, arg, unique, p); // never 0
+ if (num_skip == 0) return 0; // NumSkip already printed error message
+
+ const InputVec full =
+ ReplicateInputs(inputs, num_inputs, unique.size(), num_skip, p);
+
+ // MeasureImpl may fail up to p.max_measure_retries times.
+ for (size_t i = 0; i < p.max_measure_retries; i++) {
+ auto result = MeasureImpl(func, arg, num_skip, unique, full, p, results);
+ if (result != 0) {
+ return result;
+ }
+ }
+ // All retries failed. (Unusual)
+ return 0;
+}
+
+} // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark.h
new file mode 100644
index 00000000000..a5097ba27b0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark_test.cc
new file mode 100644
index 00000000000..f1571e269ff
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nanobenchmark_test.cc
@@ -0,0 +1,77 @@
+// 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.
+
+#include "absl/random/internal/nanobenchmark.h"
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/strings/numbers.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal_nanobenchmark {
+namespace {
+
+uint64_t Div(const void*, FuncInput in) {
+ // Here we're measuring the throughput because benchmark invocations are
+ // independent.
+ const int64_t d1 = 0xFFFFFFFFFFll / int64_t(in); // IDIV
+ return d1;
+}
+
+template <size_t N>
+void MeasureDiv(const FuncInput (&inputs)[N]) {
+ Result results[N];
+ Params params;
+ params.max_evals = 6; // avoid test timeout
+ const size_t num_results = Measure(&Div, nullptr, inputs, N, results, params);
+ if (num_results == 0) {
+ ABSL_RAW_LOG(
+ WARNING,
+ "WARNING: Measurement failed, should not happen when using "
+ "PinThreadToCPU unless the region to measure takes > 1 second.\n");
+ return;
+ }
+ for (size_t i = 0; i < num_results; ++i) {
+ ABSL_RAW_LOG(INFO, "%5zu: %6.2f ticks; MAD=%4.2f%%\n", results[i].input,
+ results[i].ticks, results[i].variability * 100.0);
+ ABSL_RAW_CHECK(results[i].ticks != 0.0f, "Zero duration");
+ }
+}
+
+void RunAll(const int argc, char* argv[]) {
+ // Avoid migrating between cores - important on multi-socket systems.
+ int cpu = -1;
+ if (argc == 2) {
+ if (!absl::SimpleAtoi(argv[1], &cpu)) {
+ ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n");
+ }
+ }
+ PinThreadToCPU(cpu);
+
+ // unpredictable == 1 but the compiler doesn't know that.
+ const FuncInput unpredictable = argc != 999;
+ static const FuncInput inputs[] = {unpredictable * 10, unpredictable * 100};
+
+ MeasureDiv(inputs);
+}
+
+} // namespace
+} // namespace random_internal_nanobenchmark
+ABSL_NAMESPACE_END
+} // namespace absl
+
+int main(int argc, char* argv[]) {
+ absl::random_internal_nanobenchmark::RunAll(argc, argv);
+ return 0;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base.h
new file mode 100644
index 00000000000..730fa2ea12d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base.h
@@ -0,0 +1,150 @@
+// 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 <iostream>
+#include <iterator>
+#include <random>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "absl/base/macros.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/optional.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced
+// by a thread-unique URBG-instance.
+template <typename URBG>
+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:
+ // Seeder is a custom seed sequence type where generate() fills the provided
+ // buffer via the RandenPool entropy source.
+ struct Seeder {
+ 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) {
+ if (begin != end) {
+ // begin, end must be random access iterators assignable from uint32_t.
+ generate_impl(
+ std::integral_constant<bool, sizeof(*begin) == sizeof(uint32_t)>{},
+ begin, end);
+ }
+ }
+
+ // Commonly, generate is invoked with a pointer to a buffer which
+ // can be cast to a uint32_t.
+ template <typename RandomAccessIterator>
+ void generate_impl(std::integral_constant<bool, true>,
+ RandomAccessIterator begin, RandomAccessIterator end) {
+ auto buffer = absl::MakeSpan(begin, end);
+ auto target = absl::MakeSpan(reinterpret_cast<uint32_t*>(buffer.data()),
+ buffer.size());
+ RandenPool<uint32_t>::Fill(target);
+ }
+
+ // The non-uint32_t case should be uncommon, and involves an extra copy,
+ // filling the uint32_t buffer and then mixing into the output.
+ template <typename RandomAccessIterator>
+ void generate_impl(std::integral_constant<bool, false>,
+ 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);
+ }
+ };
+
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base_test.cc
new file mode 100644
index 00000000000..698027fc6e0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/nonsecure_base_test.cc
@@ -0,0 +1,245 @@
+// 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.
+
+#include "absl/random/internal/nonsecure_base.h"
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+#include <random>
+#include <sstream>
+
+#include "gtest/gtest.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+
+using ExampleNonsecureURBG =
+ absl::random_internal::NonsecureURBGBase<std::mt19937>;
+
+template <typename T>
+void Use(const T&) {}
+
+} // namespace
+
+TEST(NonsecureURBGBase, DefaultConstructorIsValid) {
+ ExampleNonsecureURBG urbg;
+}
+
+// Ensure that the recommended template-instantiations are valid.
+TEST(RecommendedTemplates, CanBeConstructed) {
+ absl::BitGen default_generator;
+ absl::InsecureBitGen insecure_generator;
+}
+
+TEST(RecommendedTemplates, CanDiscardValues) {
+ absl::BitGen default_generator;
+ absl::InsecureBitGen insecure_generator;
+
+ default_generator.discard(5);
+ insecure_generator.discard(5);
+}
+
+TEST(NonsecureURBGBase, StandardInterface) {
+ // Names after definition of [rand.req.urbg] in C++ standard.
+ // e us a value of E
+ // v is a lvalue of E
+ // x, y are possibly const values of E
+ // s is a value of T
+ // q is a value satisfying requirements of seed_sequence
+ // z is a value of type unsigned long long
+ // os is a some specialization of basic_ostream
+ // is is a some specialization of basic_istream
+
+ using E = absl::random_internal::NonsecureURBGBase<std::minstd_rand>;
+
+ using T = typename E::result_type;
+
+ static_assert(!std::is_copy_constructible<E>::value,
+ "NonsecureURBGBase should not be copy constructible");
+
+ static_assert(!absl::is_copy_assignable<E>::value,
+ "NonsecureURBGBase should not be copy assignable");
+
+ static_assert(std::is_move_constructible<E>::value,
+ "NonsecureURBGBase should be move constructible");
+
+ static_assert(absl::is_move_assignable<E>::value,
+ "NonsecureURBGBase should be move assignable");
+
+ static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
+ "return type of operator() must be result_type");
+
+ {
+ const E x, y;
+ Use(x);
+ Use(y);
+
+ static_assert(std::is_same<decltype(x == y), bool>::value,
+ "return type of operator== must be bool");
+
+ static_assert(std::is_same<decltype(x != y), bool>::value,
+ "return type of operator== must be bool");
+ }
+
+ E e;
+ std::seed_seq q{1, 2, 3};
+
+ E{};
+ E{q};
+
+ // Copy constructor not supported.
+ // E{x};
+
+ // result_type seed constructor not supported.
+ // E{T{1}};
+
+ // Move constructors are supported.
+ {
+ E tmp(q);
+ E m = std::move(tmp);
+ E n(std::move(m));
+ EXPECT_TRUE(e != n);
+ }
+
+ // Comparisons work.
+ {
+ // MSVC emits error 2718 when using EXPECT_EQ(e, x)
+ // * actual parameter with __declspec(align('#')) won't be aligned
+ E a(q);
+ E b(q);
+
+ EXPECT_TRUE(a != e);
+ EXPECT_TRUE(a == b);
+
+ a();
+ EXPECT_TRUE(a != b);
+ }
+
+ // e.seed(s) not supported.
+
+ // [rand.req.eng] specifies the parameter as 'unsigned long long'
+ // e.discard(unsigned long long) is supported.
+ unsigned long long z = 1; // NOLINT(runtime/int)
+ e.discard(z);
+}
+
+TEST(NonsecureURBGBase, SeedSeqConstructorIsValid) {
+ std::seed_seq seq;
+ ExampleNonsecureURBG rbg(seq);
+}
+
+TEST(NonsecureURBGBase, CompatibleWithDistributionUtils) {
+ ExampleNonsecureURBG rbg;
+
+ absl::Uniform(rbg, 0, 100);
+ absl::Uniform(rbg, 0.5, 0.7);
+ absl::Poisson<uint32_t>(rbg);
+ absl::Exponential<float>(rbg);
+}
+
+TEST(NonsecureURBGBase, CompatibleWithStdDistributions) {
+ ExampleNonsecureURBG rbg;
+
+ // Cast to void to suppress [[nodiscard]] warnings
+ static_cast<void>(std::uniform_int_distribution<uint32_t>(0, 100)(rbg));
+ static_cast<void>(std::uniform_real_distribution<float>()(rbg));
+ static_cast<void>(std::bernoulli_distribution(0.2)(rbg));
+}
+
+TEST(NonsecureURBGBase, ConsecutiveDefaultInstancesYieldUniqueVariates) {
+ const size_t kNumSamples = 128;
+
+ ExampleNonsecureURBG rbg1;
+ ExampleNonsecureURBG rbg2;
+
+ for (size_t i = 0; i < kNumSamples; i++) {
+ EXPECT_NE(rbg1(), rbg2());
+ }
+}
+
+TEST(NonsecureURBGBase, EqualSeedSequencesYieldEqualVariates) {
+ std::seed_seq seq;
+
+ ExampleNonsecureURBG rbg1(seq);
+ ExampleNonsecureURBG rbg2(seq);
+
+ // ExampleNonsecureURBG rbg3({1, 2, 3}); // Should not compile.
+
+ for (uint32_t i = 0; i < 1000; i++) {
+ EXPECT_EQ(rbg1(), rbg2());
+ }
+
+ rbg1.discard(100);
+ rbg2.discard(100);
+
+ // The sequences should continue after discarding
+ for (uint32_t i = 0; i < 1000; i++) {
+ EXPECT_EQ(rbg1(), rbg2());
+ }
+}
+
+// This is a PRNG-compatible type specifically designed to test
+// that NonsecureURBGBase::Seeder can correctly handle iterators
+// to arbitrary non-uint32_t size types.
+template <typename T>
+struct SeederTestEngine {
+ using result_type = 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)();
+ }
+
+ template <class SeedSequence,
+ typename = typename absl::enable_if_t<
+ !std::is_same<SeedSequence, SeederTestEngine>::value>>
+ explicit SeederTestEngine(SeedSequence&& seq) {
+ seed(seq);
+ }
+
+ SeederTestEngine(const SeederTestEngine&) = default;
+ SeederTestEngine& operator=(const SeederTestEngine&) = default;
+ SeederTestEngine(SeederTestEngine&&) = default;
+ SeederTestEngine& operator=(SeederTestEngine&&) = default;
+
+ result_type operator()() { return state[0]; }
+
+ template <class SeedSequence>
+ void seed(SeedSequence&& seq) {
+ std::fill(std::begin(state), std::end(state), T(0));
+ seq.generate(std::begin(state), std::end(state));
+ }
+
+ T state[2];
+};
+
+TEST(NonsecureURBGBase, SeederWorksForU32) {
+ using U32 =
+ absl::random_internal::NonsecureURBGBase<SeederTestEngine<uint32_t>>;
+ U32 x;
+ EXPECT_NE(0, x());
+}
+
+TEST(NonsecureURBGBase, SeederWorksForU64) {
+ using U64 =
+ absl::random_internal::NonsecureURBGBase<SeederTestEngine<uint64_t>>;
+
+ U64 x;
+ EXPECT_NE(0, x());
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine.h
new file mode 100644
index 00000000000..8efaf2e09a1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine.h
@@ -0,0 +1,308 @@
+// 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:
+#if ABSL_HAVE_INTRINSIC_INT128
+ using state_type = __uint128_t;
+ static inline constexpr state_type make_u128(uint64_t a, uint64_t b) {
+ return (static_cast<__uint128_t>(a) << 64) | b;
+ }
+#else
+ using state_type = absl::uint128;
+ static inline constexpr state_type make_u128(uint64_t a, uint64_t b) {
+ return absl::MakeUint128(a, b);
+ }
+#endif
+
+ static inline constexpr state_type multiplier() {
+ return make_u128(kMultA, kMultB);
+ }
+ static inline constexpr state_type increment() {
+ return make_u128(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 {
+#if ABSL_HAVE_INTRINSIC_INT128
+ using state_type = __uint128_t;
+#else
+ using state_type = absl::uint128;
+#endif
+ using result_type = uint64_t;
+
+ inline uint64_t operator()(state_type state) {
+ // This is equivalent to the xsl_rr_128_64 mixing function.
+#if ABSL_HAVE_INTRINSIC_INT128
+ uint64_t rotate = static_cast<uint64_t>(state >> 122u);
+ state ^= state >> 64;
+ uint64_t s = static_cast<uint64_t>(state);
+#else
+ uint64_t h = Uint128High64(state);
+ uint64_t rotate = h >> 58u;
+ uint64_t s = Uint128Low64(state) ^ h;
+#endif
+ return rotr(s, 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine_test.cc
new file mode 100644
index 00000000000..4d763e89eb5
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pcg_engine_test.cc
@@ -0,0 +1,638 @@
+// 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.
+
+#include "absl/random/internal/pcg_engine.h"
+
+#include <algorithm>
+#include <bitset>
+#include <random>
+#include <sstream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/internal/explicit_seed_seq.h"
+#include "absl/time/clock.h"
+
+#define UPDATE_GOLDEN 0
+
+namespace {
+
+using absl::random_internal::ExplicitSeedSeq;
+using absl::random_internal::pcg32_2018_engine;
+using absl::random_internal::pcg64_2018_engine;
+
+template <typename EngineType>
+class PCGEngineTest : public ::testing::Test {};
+
+using EngineTypes = ::testing::Types<pcg64_2018_engine, pcg32_2018_engine>;
+
+TYPED_TEST_SUITE(PCGEngineTest, EngineTypes);
+
+TYPED_TEST(PCGEngineTest, VerifyReseedChangesAllValues) {
+ using engine_type = TypeParam;
+ using result_type = typename engine_type::result_type;
+
+ const size_t kNumOutputs = 16;
+ engine_type engine;
+
+ // MSVC emits error 2719 without the use of std::ref below.
+ // * formal parameter with __declspec(align('#')) won't be aligned
+
+ {
+ std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};
+ engine.seed(seq1);
+ }
+ result_type a[kNumOutputs];
+ std::generate(std::begin(a), std::end(a), std::ref(engine));
+
+ {
+ std::random_device rd;
+ std::seed_seq seq2{rd(), rd(), rd()};
+ engine.seed(seq2);
+ }
+ result_type b[kNumOutputs];
+ std::generate(std::begin(b), std::end(b), std::ref(engine));
+
+ // Verify that two uncorrelated values have ~50% of there bits in common. Use
+ // a 10% margin-of-error to reduce flakiness.
+ size_t changed_bits = 0;
+ size_t unchanged_bits = 0;
+ size_t total_set = 0;
+ size_t total_bits = 0;
+ size_t equal_count = 0;
+ for (size_t i = 0; i < kNumOutputs; ++i) {
+ equal_count += (a[i] == b[i]) ? 1 : 0;
+ std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
+ changed_bits += bitset.count();
+ unchanged_bits += bitset.size() - bitset.count();
+
+ std::bitset<sizeof(result_type) * 8> a_set(a[i]);
+ std::bitset<sizeof(result_type) * 8> b_set(b[i]);
+ total_set += a_set.count() + b_set.count();
+ total_bits += 2 * 8 * sizeof(result_type);
+ }
+ // On average, half the bits are changed between two calls.
+ EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
+ EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
+
+ // verify using a quick normal-approximation to the binomial.
+ EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
+ << "@" << total_set / static_cast<double>(total_bits);
+
+ // Also, A[i] == B[i] with probability (1/range) * N.
+ // Give this a pretty wide latitude, though.
+ const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
+ EXPECT_LE(equal_count, 1.0 + kExpected);
+}
+
+// Number of values that needs to be consumed to clean two sizes of buffer
+// and trigger third refresh. (slightly overestimates the actual state size).
+constexpr size_t kTwoBufferValues = 16;
+
+TYPED_TEST(PCGEngineTest, VerifyDiscard) {
+ using engine_type = TypeParam;
+
+ for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {
+ engine_type engine_used;
+ for (size_t i = 0; i < num_used; ++i) {
+ engine_used();
+ }
+
+ for (size_t num_discard = 0; num_discard < kTwoBufferValues;
+ ++num_discard) {
+ engine_type engine1 = engine_used;
+ engine_type engine2 = engine_used;
+ for (size_t i = 0; i < num_discard; ++i) {
+ engine1();
+ }
+ engine2.discard(num_discard);
+ for (size_t i = 0; i < kTwoBufferValues; ++i) {
+ const auto r1 = engine1();
+ const auto r2 = engine2();
+ ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard;
+ }
+ }
+ }
+}
+
+TYPED_TEST(PCGEngineTest, StreamOperatorsResult) {
+ using engine_type = TypeParam;
+
+ std::wostringstream os;
+ std::wistringstream is;
+ engine_type engine;
+
+ EXPECT_EQ(&(os << engine), &os);
+ EXPECT_EQ(&(is >> engine), &is);
+}
+
+TYPED_TEST(PCGEngineTest, StreamSerialization) {
+ using engine_type = TypeParam;
+
+ for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ engine_type engine(seed_sequence);
+ engine.discard(discard);
+
+ std::stringstream stream;
+ stream << engine;
+
+ engine_type new_engine;
+ stream >> new_engine;
+ for (size_t i = 0; i < 64; ++i) {
+ EXPECT_EQ(engine(), new_engine()) << " " << i;
+ }
+ }
+}
+
+constexpr size_t kNumGoldenOutputs = 127;
+
+// This test is checking if randen_engine is meets interface requirements
+// defined in [rand.req.urbg].
+TYPED_TEST(PCGEngineTest, RandomNumberEngineInterface) {
+ using engine_type = TypeParam;
+
+ using E = engine_type;
+ using T = typename E::result_type;
+
+ static_assert(std::is_copy_constructible<E>::value,
+ "engine_type must be copy constructible");
+
+ static_assert(absl::is_copy_assignable<E>::value,
+ "engine_type must be copy assignable");
+
+ static_assert(std::is_move_constructible<E>::value,
+ "engine_type must be move constructible");
+
+ static_assert(absl::is_move_assignable<E>::value,
+ "engine_type must be move assignable");
+
+ static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
+ "return type of operator() must be result_type");
+
+ // Names after definition of [rand.req.urbg] in C++ standard.
+ // e us a value of E
+ // v is a lvalue of E
+ // x, y are possibly const values of E
+ // s is a value of T
+ // q is a value satisfying requirements of seed_sequence
+ // z is a value of type unsigned long long
+ // os is a some specialization of basic_ostream
+ // is is a some specialization of basic_istream
+
+ E e, v;
+ const E x, y;
+ T s = 1;
+ std::seed_seq q{1, 2, 3};
+ unsigned long long z = 1; // NOLINT(runtime/int)
+ std::wostringstream os;
+ std::wistringstream is;
+
+ E{};
+ E{x};
+ E{s};
+ E{q};
+
+ e.seed();
+
+ // MSVC emits error 2718 when using EXPECT_EQ(e, x)
+ // * actual parameter with __declspec(align('#')) won't be aligned
+ EXPECT_TRUE(e == x);
+
+ e.seed(q);
+ {
+ E tmp(q);
+ EXPECT_TRUE(e == tmp);
+ }
+
+ e();
+ {
+ E tmp(q);
+ EXPECT_TRUE(e != tmp);
+ }
+
+ e.discard(z);
+
+ static_assert(std::is_same<decltype(x == y), bool>::value,
+ "return type of operator== must be bool");
+
+ static_assert(std::is_same<decltype(x != y), bool>::value,
+ "return type of operator== must be bool");
+}
+
+TYPED_TEST(PCGEngineTest, RandenEngineSFINAETest) {
+ using engine_type = TypeParam;
+ using result_type = typename engine_type::result_type;
+
+ {
+ engine_type engine(result_type(1));
+ engine.seed(result_type(1));
+ }
+
+ {
+ result_type n = 1;
+ engine_type engine(n);
+ engine.seed(n);
+ }
+
+ {
+ engine_type engine(1);
+ engine.seed(1);
+ }
+
+ {
+ int n = 1;
+ engine_type engine(n);
+ engine.seed(n);
+ }
+
+ {
+ std::seed_seq seed_seq;
+ engine_type engine(seed_seq);
+ engine.seed(seed_seq);
+ }
+
+ {
+ engine_type engine{std::seed_seq()};
+ engine.seed(std::seed_seq());
+ }
+}
+
+// ------------------------------------------------------------------
+// Stability tests for pcg64_2018_engine
+// ------------------------------------------------------------------
+TEST(PCG642018EngineTest, VerifyGolden) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0x01070196e695f8f1, 0x703ec840c59f4493, 0xe54954914b3a44fa,
+ 0x96130ff204b9285e, 0x7d9fdef535ceb21a, 0x666feed42e1219a0,
+ 0x981f685721c8326f, 0xad80710d6eab4dda, 0xe202c480b037a029,
+ 0x5d3390eaedd907e2, 0x0756befb39c6b8aa, 0x1fb44ba6634d62a3,
+ 0x8d20423662426642, 0x34ea910167a39fb4, 0x93010b43a80d0ab6,
+ 0x663db08a98fc568a, 0x720b0a1335956fae, 0x2c35483e31e1d3ba,
+ 0x429f39776337409d, 0xb46d99e638687344, 0x105370b96aedcaee,
+ 0x3999e92f811cff71, 0xd230f8bcb591cfc9, 0x0dce3db2ba7bdea5,
+ 0xcf2f52c91eec99af, 0x2bc7c24a8b998a39, 0xbd8af1b0d599a19c,
+ 0x56bc45abc66059f5, 0x170a46dc170f7f1e, 0xc25daf5277b85fad,
+ 0xe629c2e0c948eadb, 0x1720a796915542ed, 0x22fb0caa4f909951,
+ 0x7e0c0f4175acd83d, 0xd9fcab37ff2a860c, 0xab2280fb2054bad1,
+ 0x58e8a06f37fa9e99, 0xc3a52a30b06528c7, 0x0175f773a13fc1bd,
+ 0x731cfc584b00e840, 0x404cc7b2648069cb, 0x5bc29153b0b7f783,
+ 0x771310a38cc999d1, 0x766a572f0a71a916, 0x90f450fb4fc48348,
+ 0xf080ea3e1c7b1a0d, 0x15471a4507d66a44, 0x7d58e55a78f3df69,
+ 0x0130a094576ac99c, 0x46669cb2d04b1d87, 0x17ab5bed20191840,
+ 0x95b177d260adff3e, 0x025fb624b6ee4c07, 0xb35de4330154a95f,
+ 0xe8510fff67e24c79, 0x132c3cbcd76ed2d3, 0x35e7cc145a093904,
+ 0x9f5b5b5f81583b79, 0x3ee749a533966233, 0x4af85886cdeda8cd,
+ 0x0ca5380ecb3ef3aa, 0x4f674eb7661d3192, 0x88a29aad00cd7733,
+ 0x70b627ca045ffac6, 0x5912b43ea887623d, 0x95dc9fc6f62cf221,
+ 0x926081a12a5c905b, 0x9c57d4cd7dfce651, 0x85ab2cbf23e3bb5d,
+ 0xc5cd669f63023152, 0x3067be0fad5d898e, 0x12b56f444cb53d05,
+ 0xbc2e5a640c3434fc, 0x9280bff0e4613fe1, 0x98819094c528743e,
+ 0x999d1c98d829df33, 0x9ff82a012dc89242, 0xf99183ed39c8be94,
+ 0xf0f59161cd421c55, 0x3c705730c2f6c48d, 0x66ad85c6e9278a61,
+ 0x2a3428e4a428d5d0, 0x79207d68fd04940d, 0xea7f2b402edc8430,
+ 0xa06b419ac857f63b, 0xcb1dd0e6fbc47e1c, 0x4f55229200ada6a4,
+ 0x9647b5e6359c927f, 0x30bf8f9197c7efe5, 0xa79519529cc384d0,
+ 0xbb22c4f339ad6497, 0xd7b9782f59d14175, 0x0dff12fff2ec0118,
+ 0xa331ad8305343a7c, 0x48dad7e3f17e0862, 0x324c6fb3fd3c9665,
+ 0xf0e4350e7933dfc4, 0x7ccda2f30b8b03b6, 0xa0afc6179005de40,
+ 0xee65da6d063b3a30, 0xb9506f42f2bfe87a, 0xc9a2e26b0ef5baa0,
+ 0x39fa9d4f495011d6, 0xbecc21a45d023948, 0x6bf484c6593f737f,
+ 0x8065e0070cadc3b7, 0x9ef617ed8d419799, 0xac692cf8c233dd15,
+ 0xd2ed87583c4ebb98, 0xad95ba1bebfedc62, 0x9b60b160a8264e43,
+ 0x0bc8c45f71fcf25b, 0x4a78035cdf1c9931, 0x4602dc106667e029,
+ 0xb335a3c250498ac8, 0x0256ebc4df20cab8, 0x0c61efd153f0c8d9,
+ 0xe5d0150a4f806f88, 0x99d6521d351e7d87, 0x8d4888c9f80f4325,
+ 0x106c5735c1ba868d, 0x73414881b880a878, 0x808a9a58a3064751,
+ 0x339a29f3746de3d5, 0x5410d7fa4f873896, 0xd84623c81d7b8a03,
+ 0x1f7c7e7a7f47f462,
+ };
+
+ pcg64_2018_engine engine(0);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed();
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(PCG642018EngineTest, VerifyGoldenSeeded) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0xb03988f1e39691ee, 0xbd2a1eb5ac31e97a, 0x8f00d6d433634d02,
+ 0x1823c28d483d5776, 0x000c3ee3e1aeb74a, 0xfa82ef27a4f3df9c,
+ 0xc6f382308654e454, 0x414afb1a238996c2, 0x4703a4bc252eb411,
+ 0x99d64f62c8f7f654, 0xbb07ebe11a34fa44, 0x79eb06a363c06131,
+ 0xf66ad3756f1c6b21, 0x130c01d5e869f457, 0x5ca2b9963aecbc81,
+ 0xfef7bebc1de27e6c, 0x1d174faa5ed2cdbf, 0xd75b7a773f2bb889,
+ 0xc35c872327a170a5, 0x46da6d88646a42fe, 0x4622985e0442dae2,
+ 0xbe3cbd67297f1f9b, 0xe7c37b4a4798bfd1, 0x173d5dfad15a25c3,
+ 0x0eb6849ba2961522, 0xb0ff7246e6700d73, 0x88cb9c42d3afa577,
+ 0xb609731dbd94d917, 0xd3941cda04b40081, 0x28d140f7409bea3a,
+ 0x3c96699a920a124a, 0xdb28be521958b2fd, 0x0a3f44db3d4c5124,
+ 0x7ac8e60ba13b70d2, 0x75f03a41ded5195a, 0xaed10ac7c4e4825d,
+ 0xb92a3b18aadb7adc, 0xda45e0081f2bca46, 0x74d39ab3753143fc,
+ 0xb686038018fac9ca, 0x4cc309fe99542dbb, 0xf3e1a4fcb311097c,
+ 0x58763d6fa698d69d, 0xd11c365dbecd8d60, 0x2c15d55725b1dee7,
+ 0x89805f254d85658c, 0x2374c44dfc62158b, 0x9a8350fa7995328d,
+ 0x198f838970cf91da, 0x96aff569562c0e53, 0xd76c8c52b7ec6e3f,
+ 0x23a01cd9ae4baa81, 0x3adb366b6d02a893, 0xb3313e2a4c5b333f,
+ 0x04c11230b96a5425, 0x1f7f7af04787d571, 0xaddb019365275ec7,
+ 0x5c960468ccb09f42, 0x8438db698c69a44a, 0x492be1e46111637e,
+ 0x9c6c01e18100c610, 0xbfe48e75b7d0aceb, 0xb5e0b89ec1ce6a00,
+ 0x9d280ecbc2fe8997, 0x290d9e991ba5fcab, 0xeec5bec7d9d2a4f0,
+ 0x726e81488f19150e, 0x1a6df7955a7e462c, 0x37a12d174ba46bb5,
+ 0x3cdcdffd96b1b5c5, 0x2c5d5ac10661a26e, 0xa742ed18f22e50c4,
+ 0x00e0ed88ff0d8a35, 0x3d3c1718cb1efc0b, 0x1d70c51ffbccbf11,
+ 0xfbbb895132a4092f, 0x619d27f2fb095f24, 0x69af68200985e5c4,
+ 0xbee4885f57373f8d, 0x10b7a6bfe0587e40, 0xa885e6cf2f7e5f0a,
+ 0x59f879464f767550, 0x24e805d69056990d, 0x860970b911095891,
+ 0xca3189954f84170d, 0x6652a5edd4590134, 0x5e1008cef76174bf,
+ 0xcbd417881f2bcfe5, 0xfd49fc9d706ecd17, 0xeebf540221ebd066,
+ 0x46af7679464504cb, 0xd4028486946956f1, 0xd4f41864b86c2103,
+ 0x7af090e751583372, 0x98cdaa09278cb642, 0xffd42b921215602f,
+ 0x1d05bec8466b1740, 0xf036fa78a0132044, 0x787880589d1ecc78,
+ 0x5644552cfef33230, 0x0a97e275fe06884b, 0x96d1b13333d470b5,
+ 0xc8b3cdad52d3b034, 0x091357b9db7376fd, 0xa5fe4232555edf8c,
+ 0x3371bc3b6ada76b5, 0x7deeb2300477c995, 0x6fc6d4244f2849c1,
+ 0x750e8cc797ca340a, 0x81728613cd79899f, 0x3467f4ee6f9aeb93,
+ 0x5ef0a905f58c640f, 0x432db85e5101c98a, 0x6488e96f46ac80c2,
+ 0x22fddb282625048c, 0x15b287a0bc2d4c5d, 0xa7e2343ef1f28bce,
+ 0xc87ee1aa89bed09e, 0x220610107812c5e9, 0xcbdab6fcd640f586,
+ 0x8d41047970928784, 0x1aa431509ec1ade0, 0xac3f0be53f518ddc,
+ 0x16f4428ad81d0cbb, 0x675b13c2736fc4bb, 0x6db073afdd87e32d,
+ 0x572f3ca2f1a078c6,
+ };
+
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ pcg64_2018_engine engine(seed_sequence);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed(seed_sequence);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(PCG642018EngineTest, VerifyGoldenFromDeserializedEngine) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0xdd425b47b4113dea, 0x1b07176479d444b0, 0x6b391027586f2e42,
+ 0xa166f2b15f4a2143, 0xffb6dbd7a179ee97, 0xb2c00035365bf0b1,
+ 0x8fbb518b45855521, 0xfc789a55ddf87c3b, 0x429531f0f17ff355,
+ 0xbe708560d603d283, 0x5bff415175c5cb6b, 0xe813491f4ad45394,
+ 0xa853f4506d55880d, 0x7e538453e568172e, 0xe101f1e098ddd0ec,
+ 0x6ee31266ee4c766d, 0xa8786d92d66b39d7, 0xfee622a2acf5e5b0,
+ 0x5fe8e82c102fa7b3, 0x01f10be4cdb53c9d, 0xbe0545366f857022,
+ 0x12e74f010a339bca, 0xb10d85ca40d5ce34, 0xe80d6feba5054875,
+ 0x2b7c1ee6d567d4ee, 0x2a9cd043bfd03b66, 0x5cfc531bd239f3f1,
+ 0x1c4734e4647d70f5, 0x85a8f60f006b5760, 0x6a4239ce76dca387,
+ 0x8da0f86d7339335c, 0xf055b0468551374d, 0x486e8567e9bea9a0,
+ 0x4cb531b8405192dd, 0xf813b1ee3157110b, 0x214c2a664a875d8e,
+ 0x74531237b29b35f7, 0xa6f0267bb77a771e, 0x64b552bff54184a4,
+ 0xa2d6f7af2d75b6fc, 0x460a10018e03b5ab, 0x76fd1fdcb81d0800,
+ 0x76f5f81805070d9d, 0x1fb75cb1a70b289a, 0x9dfd25a022c4b27f,
+ 0x9a31a14a80528e9e, 0x910dc565ddc25820, 0xd6aef8e2b0936c10,
+ 0xe1773c507fe70225, 0xe027fd7aadd632bc, 0xc1fecb427089c8b8,
+ 0xb5c74c69fa9dbf26, 0x71bf9b0e4670227d, 0x25f48fad205dcfdd,
+ 0x905248ec4d689c56, 0x5c2b7631b0de5c9d, 0x9f2ee0f8f485036c,
+ 0xfd6ce4ebb90bf7ea, 0xd435d20046085574, 0x6b7eadcb0625f986,
+ 0x679d7d44b48be89e, 0x49683b8e1cdc49de, 0x4366cf76e9a2f4ca,
+ 0x54026ec1cdad7bed, 0xa9a04385207f28d3, 0xc8e66de4eba074b2,
+ 0x40b08c42de0f4cc0, 0x1d4c5e0e93c5bbc0, 0x19b80792e470ae2d,
+ 0x6fcaaeaa4c2a5bd9, 0xa92cb07c4238438e, 0x8bb5c918a007e298,
+ 0x7cd671e944874cf4, 0x88166470b1ba3cac, 0xd013d476eaeeade6,
+ 0xcee416947189b3c3, 0x5d7c16ab0dce6088, 0xd3578a5c32b13d27,
+ 0x3875db5adc9cc973, 0xfbdaba01c5b5dc56, 0xffc4fdd391b231c3,
+ 0x2334520ecb164fec, 0x361c115e7b6de1fa, 0xeee58106cc3563d7,
+ 0x8b7f35a8db25ebb8, 0xb29d00211e2cafa6, 0x22a39fe4614b646b,
+ 0x92ca6de8b998506d, 0x40922fe3d388d1db, 0x9da47f1e540f802a,
+ 0x811dceebf16a25db, 0xf6524ae22e0e53a9, 0x52d9e780a16eb99d,
+ 0x4f504286bb830207, 0xf6654d4786bd5cc3, 0x00bd98316003a7e1,
+ 0xefda054a6ab8f5f3, 0x46cfb0f4c1872827, 0xc22b316965c0f3b2,
+ 0xd1a28087c7e7562a, 0xaa4f6a094b7f5cff, 0xfe2bc853a041f7da,
+ 0xe9d531402a83c3ba, 0xe545d8663d3ce4dd, 0xfa2dcd7d91a13fa8,
+ 0xda1a080e52a127b8, 0x19c98f1f809c3d84, 0x2cef109af4678c88,
+ 0x53462accab3b9132, 0x176b13a80415394e, 0xea70047ef6bc178b,
+ 0x57bca80506d6dcdf, 0xd853ba09ff09f5c4, 0x75f4df3a7ddd4775,
+ 0x209c367ade62f4fe, 0xa9a0bbc74d5f4682, 0x5dfe34bada86c21a,
+ 0xc2c05bbcd38566d1, 0x6de8088e348c916a, 0x6a7001c6000c2196,
+ 0xd9fb51865fc4a367, 0x12f320e444ece8ff, 0x6d56f7f793d65035,
+ 0x138f31b7a865f8aa, 0x58fc68b4026b9adf, 0xcd48954b79fb6436,
+ 0x27dfce4a0232af87,
+ };
+
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ std::seed_seq seed_sequence{1, 2, 3};
+ pcg64_2018_engine engine(seed_sequence);
+ std::ostringstream stream;
+ stream << engine;
+ auto str = stream.str();
+ printf("%s\n\n", str.c_str());
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ pcg64_2018_engine engine;
+ std::istringstream stream(
+ "2549297995355413924 4865540595714422341 6364136223846793005 "
+ "1442695040888963407 18088519957565336995 4845369368158826708");
+ stream >> engine;
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+// ------------------------------------------------------------------
+// Stability tests for pcg32_2018_engine
+// ------------------------------------------------------------------
+TEST(PCG322018EngineTest, VerifyGolden) {
+ constexpr uint32_t kGolden[kNumGoldenOutputs] = {
+ 0x7a7ecbd9, 0x89fd6c06, 0xae646aa8, 0xcd3cf945, 0x6204b303, 0x198c8585,
+ 0x49fce611, 0xd1e9297a, 0x142d9440, 0xee75f56b, 0x473a9117, 0xe3a45903,
+ 0xbce807a1, 0xe54e5f4d, 0x497d6c51, 0x61829166, 0xa740474b, 0x031912a8,
+ 0x9de3defa, 0xd266dbf1, 0x0f38bebb, 0xec3c4f65, 0x07c5057d, 0xbbce03c8,
+ 0xfd2ac7a8, 0xffcf4773, 0x5b10affb, 0xede1c842, 0xe22b01b7, 0xda133c8c,
+ 0xaf89b0f4, 0x25d1b8bc, 0x9f625482, 0x7bfd6882, 0x2e2210c0, 0x2c8fb9a6,
+ 0x42cb3b83, 0x40ce0dab, 0x644a3510, 0x36230ef2, 0xe2cb6d43, 0x1012b343,
+ 0x746c6c9f, 0x36714cf8, 0xed1f5026, 0x8bbbf83e, 0xe98710f4, 0x8a2afa36,
+ 0x09035349, 0x6dc1a487, 0x682b634b, 0xc106794f, 0x7dd78beb, 0x628c262b,
+ 0x852fb232, 0xb153ac4c, 0x4f169d1b, 0xa69ab774, 0x4bd4b6f2, 0xdc351dd3,
+ 0x93ff3c8c, 0xa30819ab, 0xff07758c, 0x5ab13c62, 0xd16d7fb5, 0xc4950ffa,
+ 0xd309ae49, 0xb9677a87, 0x4464e317, 0x90dc44f1, 0xc694c1d4, 0x1d5e1168,
+ 0xadf37a2d, 0xda38990d, 0x1ec4bd33, 0x36ca25ce, 0xfa0dc76a, 0x968a9d43,
+ 0x6950ac39, 0xdd3276bc, 0x06d5a71e, 0x1f6f282d, 0x5c626c62, 0xdde3fc31,
+ 0x152194ce, 0xc35ed14c, 0xb1f7224e, 0x47f76bb8, 0xb34fdd08, 0x7011395e,
+ 0x162d2a49, 0x0d1bf09f, 0x9428a952, 0x03c5c344, 0xd3525616, 0x7816fff3,
+ 0x6bceb8a8, 0x8345a081, 0x366420fd, 0x182abeda, 0x70f82745, 0xaf15ded8,
+ 0xc7f52ca2, 0xa98db9c5, 0x919d99ba, 0x9c376c1c, 0xed8d34c2, 0x716ae9f5,
+ 0xef062fa5, 0xee3b6c56, 0x52325658, 0x61afa9c3, 0xfdaf02f0, 0x961cf3ab,
+ 0x9f291565, 0x4fbf3045, 0x0590c899, 0xde901385, 0x45005ffb, 0x509db162,
+ 0x262fa941, 0x4c421653, 0x4b17c21e, 0xea0d1530, 0xde803845, 0x61bfd515,
+ 0x438523ef,
+ };
+
+ pcg32_2018_engine engine(0);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%08x, ", engine());
+ if (i % 6 == 5) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed();
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(PCG322018EngineTest, VerifyGoldenSeeded) {
+ constexpr uint32_t kGolden[kNumGoldenOutputs] = {
+ 0x60b5a64c, 0x978502f9, 0x80a75f60, 0x241f1158, 0xa4cd1dbb, 0xe7284017,
+ 0x3b678da5, 0x5223ec99, 0xe4bdd5d9, 0x72190e6d, 0xe6e702c9, 0xff80c768,
+ 0xcf126ed3, 0x1fbd20ab, 0x60980489, 0xbc72bf89, 0x407ac6c0, 0x00bf3c51,
+ 0xf9087897, 0x172e4eb6, 0xe9e4f443, 0x1a6098bf, 0xbf44f8c2, 0xdd84a0e5,
+ 0xd9a52364, 0xc0e2e786, 0x061ae2ba, 0x9facb8e3, 0x6109432d, 0xd4e0a013,
+ 0xbd8eb9a6, 0x7e86c3b6, 0x629c0e68, 0x05337430, 0xb495b9f4, 0x11ccd65d,
+ 0xb578db25, 0x66f1246d, 0x6ef20a7f, 0x5e429812, 0x11772130, 0xb944b5c2,
+ 0x01624128, 0xa2385ab7, 0xd3e10d35, 0xbe570ec3, 0xc951656f, 0xbe8944a0,
+ 0x7be41062, 0x5709f919, 0xd745feda, 0x9870b9ae, 0xb44b8168, 0x19e7683b,
+ 0xded8017f, 0xc6e4d544, 0x91ae4225, 0xd6745fba, 0xb992f284, 0x65b12b33,
+ 0xa9d5fdb4, 0xf105ce1a, 0x35ca1a6e, 0x2ff70dd0, 0xd8335e49, 0xfb71ddf2,
+ 0xcaeabb89, 0x5c6f5f84, 0x9a811a7d, 0xbcecbbd1, 0x0f661ba0, 0x9ad93b9d,
+ 0xedd23e0b, 0x42062f48, 0xd38dd7e4, 0x6cd63c9c, 0x640b98ae, 0x4bff5653,
+ 0x12626371, 0x13266017, 0xe7a698d8, 0x39c74667, 0xe8fdf2e3, 0x52803bf8,
+ 0x2af6895b, 0x91335b7b, 0x699e4961, 0x00a40fff, 0x253ff2b6, 0x4a6cf672,
+ 0x9584e85f, 0xf2a5000c, 0x4d58aba8, 0xb8513e6a, 0x767fad65, 0x8e326f9e,
+ 0x182f15a1, 0x163dab52, 0xdf99c780, 0x047282a1, 0xee4f90dd, 0xd50394ae,
+ 0x6c9fd5f0, 0xb06a9194, 0x387e3840, 0x04a9487b, 0xf678a4c2, 0xd0a78810,
+ 0xd502c97e, 0xd6a9b12a, 0x4accc5dc, 0x416ed53e, 0x50411536, 0xeeb89c24,
+ 0x813a7902, 0x034ebca6, 0xffa52e7c, 0x7ecd3d0e, 0xfa37a0d2, 0xb1fbe2c1,
+ 0xb7efc6d1, 0xefa4ccee, 0xf6f80424, 0x2283f3d9, 0x68732284, 0x94f3b5c8,
+ 0xbbdeceb9,
+ };
+
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ pcg32_2018_engine engine(seed_sequence);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%08x, ", engine());
+ if (i % 6 == 5) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed(seed_sequence);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(PCG322018EngineTest, VerifyGoldenFromDeserializedEngine) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0x780f7042, 0xba137215, 0x43ab6f22, 0x0cb55f46, 0x44b2627d, 0x835597af,
+ 0xea973ea1, 0x0d2abd35, 0x4fdd601c, 0xac4342fe, 0x7db7e93c, 0xe56ebcaf,
+ 0x3596470a, 0x7770a9ad, 0x9b893320, 0x57db3415, 0xb432de54, 0xa02baf71,
+ 0xa256aadb, 0x88921fc7, 0xa35fa6b3, 0xde3eca46, 0x605739a7, 0xa890b82b,
+ 0xe457b7ad, 0x335fb903, 0xeb06790c, 0xb3c54bf6, 0x6141e442, 0xa599a482,
+ 0xb78987cc, 0xc61dfe9d, 0x0f1d6ace, 0x17460594, 0x8f6a5061, 0x083dc354,
+ 0xe9c337fb, 0xcfd105f7, 0x926764b6, 0x638d24dc, 0xeaac650a, 0x67d2cb9c,
+ 0xd807733c, 0x205fc52e, 0xf5399e2e, 0x6c46ddcc, 0xb603e875, 0xce113a25,
+ 0x3c8d4813, 0xfb584db8, 0xf6d255ff, 0xea80954f, 0x42e8be85, 0xb2feee72,
+ 0x62bd8d16, 0x1be4a142, 0x97dca1a4, 0xdd6e7333, 0xb2caa20e, 0xa12b1588,
+ 0xeb3a5a1a, 0x6fa5ba89, 0x077ea931, 0x8ddb1713, 0x0dd03079, 0x2c2ba965,
+ 0xa77fac17, 0xc8325742, 0x8bb893bf, 0xc2315741, 0xeaceee92, 0x81dd2ee2,
+ 0xe5214216, 0x1b9b8fb2, 0x01646d03, 0x24facc25, 0xd8c0e0bb, 0xa33fe106,
+ 0xf34fe976, 0xb3b4b44e, 0x65618fed, 0x032c6192, 0xa9dd72ce, 0xf391887b,
+ 0xf41c6a6e, 0x05c4bd6d, 0x37fa260e, 0x46b05659, 0xb5f6348a, 0x62d26d89,
+ 0x39f6452d, 0xb17b30a2, 0xbdd82743, 0x38ecae3b, 0xfe90f0a2, 0xcb2d226d,
+ 0xcf8a0b1c, 0x0eed3d4d, 0xa1f69cfc, 0xd7ac3ba5, 0xce9d9a6b, 0x121deb4c,
+ 0x4a0d03f3, 0xc1821ed1, 0x59c249ac, 0xc0abb474, 0x28149985, 0xfd9a82ba,
+ 0x5960c3b2, 0xeff00cba, 0x6073aa17, 0x25dc0919, 0x9976626e, 0xdd2ccc33,
+ 0x39ecb6ec, 0xc6e15d13, 0xfac94cfd, 0x28cfd34f, 0xf2d2c32d, 0x51c23d08,
+ 0x4fdb2f48, 0x97baa807, 0xf2c1004c, 0xc4ae8136, 0x71f31c94, 0x8c92d601,
+ 0x36caf5cd,
+ };
+
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ std::seed_seq seed_sequence{1, 2, 3};
+ pcg32_2018_engine engine(seed_sequence);
+ std::ostringstream stream;
+ stream << engine;
+ auto str = stream.str();
+ printf("%s\n\n", str.c_str());
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%08x, ", engine());
+ if (i % 6 == 5) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+
+ EXPECT_FALSE(true);
+#else
+ pcg32_2018_engine engine;
+ std::istringstream stream(
+ "6364136223846793005 1442695040888963407 6537028157270659894");
+ stream >> engine;
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/platform.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/platform.h
new file mode 100644
index 00000000000..bbdb4e62081
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/platform.h
@@ -0,0 +1,171 @@
+// 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_PLATFORM_H_
+#define ABSL_RANDOM_INTERNAL_PLATFORM_H_
+
+// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
+// symbols from arbitrary system and other headers, since it may be built
+// with different flags from other targets, using different levels of
+// optimization, potentially introducing ODR violations.
+
+// -----------------------------------------------------------------------------
+// Platform Feature Checks
+// -----------------------------------------------------------------------------
+
+// Currently supported operating systems and associated preprocessor
+// symbols:
+//
+// Linux and Linux-derived __linux__
+// Android __ANDROID__ (implies __linux__)
+// Linux (non-Android) __linux__ && !__ANDROID__
+// Darwin (macOS and iOS) __APPLE__
+// Akaros (http://akaros.org) __ros__
+// Windows _WIN32
+// NaCL __native_client__
+// AsmJS __asmjs__
+// WebAssembly __wasm__
+// Fuchsia __Fuchsia__
+//
+// Note that since Android defines both __ANDROID__ and __linux__, one
+// may probe for either Linux or Android by simply testing for __linux__.
+//
+// NOTE: For __APPLE__ platforms, we use #include <TargetConditionals.h>
+// to distinguish os variants.
+//
+// http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system
+
+#if defined(__APPLE__)
+#include <TargetConditionals.h>
+#endif
+
+// -----------------------------------------------------------------------------
+// Architecture Checks
+// -----------------------------------------------------------------------------
+
+// These preprocessor directives are trying to determine CPU architecture,
+// including necessary headers to support hardware AES.
+//
+// ABSL_ARCH_{X86/PPC/ARM} macros determine the platform.
+#if defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64) || \
+ defined(_M_X64)
+#define ABSL_ARCH_X86_64
+#elif defined(__i386) || defined(_M_IX86)
+#define ABSL_ARCH_X86_32
+#elif defined(__aarch64__) || defined(__arm64__) || defined(_M_ARM64)
+#define ABSL_ARCH_AARCH64
+#elif defined(__arm__) || defined(__ARMEL__) || defined(_M_ARM)
+#define ABSL_ARCH_ARM
+#elif defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__PPC__)
+#define ABSL_ARCH_PPC
+#else
+// Unsupported architecture.
+// * https://sourceforge.net/p/predef/wiki/Architectures/
+// * https://msdn.microsoft.com/en-us/library/b0084kay.aspx
+// * for gcc, clang: "echo | gcc -E -dM -"
+#endif
+
+// -----------------------------------------------------------------------------
+// Attribute Checks
+// -----------------------------------------------------------------------------
+
+// ABSL_RANDOM_INTERNAL_RESTRICT annotates whether pointers may be considered
+// to be unaliased.
+#if defined(__clang__) || defined(__GNUC__)
+#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict__
+#elif defined(_MSC_VER)
+#define ABSL_RANDOM_INTERNAL_RESTRICT __restrict
+#else
+#define ABSL_RANDOM_INTERNAL_RESTRICT
+#endif
+
+// ABSL_HAVE_ACCELERATED_AES indicates whether the currently active compiler
+// flags (e.g. -maes) allow using hardware accelerated AES instructions, which
+// implies us assuming that the target platform supports them.
+#define ABSL_HAVE_ACCELERATED_AES 0
+
+#if defined(ABSL_ARCH_X86_64)
+
+#if defined(__AES__) || defined(__AVX__)
+#undef ABSL_HAVE_ACCELERATED_AES
+#define ABSL_HAVE_ACCELERATED_AES 1
+#endif
+
+#elif defined(ABSL_ARCH_PPC)
+
+// Rely on VSX and CRYPTO extensions for vcipher on PowerPC.
+#if (defined(__VEC__) || defined(__ALTIVEC__)) && defined(__VSX__) && \
+ defined(__CRYPTO__)
+#undef ABSL_HAVE_ACCELERATED_AES
+#define ABSL_HAVE_ACCELERATED_AES 1
+#endif
+
+#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
+
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf
+// Rely on NEON+CRYPTO extensions for ARM.
+#if defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO)
+#undef ABSL_HAVE_ACCELERATED_AES
+#define ABSL_HAVE_ACCELERATED_AES 1
+#endif
+
+#endif
+
+// NaCl does not allow AES.
+#if defined(__native_client__)
+#undef ABSL_HAVE_ACCELERATED_AES
+#define ABSL_HAVE_ACCELERATED_AES 0
+#endif
+
+// ABSL_RANDOM_INTERNAL_AES_DISPATCH indicates whether the currently active
+// platform has, or should use run-time dispatch for selecting the
+// acclerated Randen implementation.
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
+
+#if defined(ABSL_ARCH_X86_64)
+// Dispatch is available on x86_64
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
+#elif defined(__linux__) && defined(ABSL_ARCH_PPC)
+// Or when running linux PPC
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
+#elif defined(__linux__) && defined(ABSL_ARCH_AARCH64)
+// Or when running linux AArch64
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
+#elif defined(__linux__) && defined(ABSL_ARCH_ARM) && (__ARM_ARCH >= 8)
+// Or when running linux ARM v8 or higher.
+// (This captures a lot of Android configurations.)
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 1
+#endif
+
+// NaCl does not allow dispatch.
+#if defined(__native_client__)
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
+#endif
+
+// iOS does not support dispatch, even on x86, since applications
+// should be bundled as fat binaries, with a different build tailored for
+// each specific supported platform/architecture.
+#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \
+ (defined(TARGET_OS_IPHONE_SIMULATOR) && TARGET_OS_IPHONE_SIMULATOR)
+#undef ABSL_RANDOM_INTERNAL_AES_DISPATCH
+#define ABSL_RANDOM_INTERNAL_AES_DISPATCH 0
+#endif
+
+#endif // ABSL_RANDOM_INTERNAL_PLATFORM_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.cc
new file mode 100644
index 00000000000..5bee530770e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.cc
@@ -0,0 +1,254 @@
+// 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.
+
+#include "absl/random/internal/pool_urbg.h"
+
+#include <algorithm>
+#include <atomic>
+#include <cstdint>
+#include <cstring>
+#include <iterator>
+
+#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/spinlock.h"
+#include "absl/base/internal/sysinfo.h"
+#include "absl/base/internal/unaligned_access.h"
+#include "absl/base/optimization.h"
+#include "absl/random/internal/randen.h"
+#include "absl/random/internal/seed_material.h"
+#include "absl/random/seed_gen_exception.h"
+
+using absl::base_internal::SpinLock;
+using absl::base_internal::SpinLockHolder;
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+// RandenPoolEntry is a thread-safe pseudorandom bit generator, implementing a
+// single generator within a RandenPool<T>. It is an internal implementation
+// detail, and does not aim to conform to [rand.req.urng].
+//
+// NOTE: There are alignment issues when used on ARM, for instance.
+// See the allocation code in PoolAlignedAlloc().
+class RandenPoolEntry {
+ public:
+ static constexpr size_t kState = RandenTraits::kStateBytes / sizeof(uint32_t);
+ static constexpr size_t kCapacity =
+ RandenTraits::kCapacityBytes / sizeof(uint32_t);
+
+ void Init(absl::Span<const uint32_t> data) {
+ SpinLockHolder l(&mu_); // Always uncontested.
+ std::copy(data.begin(), data.end(), std::begin(state_));
+ next_ = kState;
+ }
+
+ // Copy bytes into out.
+ void Fill(uint8_t* out, size_t bytes) ABSL_LOCKS_EXCLUDED(mu_);
+
+ // Returns random bits from the buffer in units of T.
+ template <typename T>
+ inline T Generate() ABSL_LOCKS_EXCLUDED(mu_);
+
+ inline void MaybeRefill() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ if (next_ >= kState) {
+ next_ = kCapacity;
+ impl_.Generate(state_);
+ }
+ }
+
+ private:
+ // Randen URBG state.
+ uint32_t state_[kState] ABSL_GUARDED_BY(mu_); // First to satisfy alignment.
+ SpinLock mu_;
+ const Randen impl_;
+ size_t next_ ABSL_GUARDED_BY(mu_);
+};
+
+template <>
+inline uint8_t RandenPoolEntry::Generate<uint8_t>() {
+ SpinLockHolder l(&mu_);
+ MaybeRefill();
+ return static_cast<uint8_t>(state_[next_++]);
+}
+
+template <>
+inline uint16_t RandenPoolEntry::Generate<uint16_t>() {
+ SpinLockHolder l(&mu_);
+ MaybeRefill();
+ return static_cast<uint16_t>(state_[next_++]);
+}
+
+template <>
+inline uint32_t RandenPoolEntry::Generate<uint32_t>() {
+ SpinLockHolder l(&mu_);
+ MaybeRefill();
+ return state_[next_++];
+}
+
+template <>
+inline uint64_t RandenPoolEntry::Generate<uint64_t>() {
+ SpinLockHolder l(&mu_);
+ if (next_ >= kState - 1) {
+ next_ = kCapacity;
+ impl_.Generate(state_);
+ }
+ auto p = state_ + next_;
+ next_ += 2;
+
+ uint64_t result;
+ std::memcpy(&result, p, sizeof(result));
+ return result;
+}
+
+void RandenPoolEntry::Fill(uint8_t* out, size_t bytes) {
+ SpinLockHolder l(&mu_);
+ while (bytes > 0) {
+ MaybeRefill();
+ size_t remaining = (kState - next_) * sizeof(state_[0]);
+ size_t to_copy = std::min(bytes, remaining);
+ std::memcpy(out, &state_[next_], to_copy);
+ out += to_copy;
+ bytes -= to_copy;
+ next_ += (to_copy + sizeof(state_[0]) - 1) / sizeof(state_[0]);
+ }
+}
+
+// Number of pooled urbg entries.
+static constexpr int kPoolSize = 8;
+
+// Shared pool entries.
+static absl::once_flag pool_once;
+ABSL_CACHELINE_ALIGNED static RandenPoolEntry* shared_pools[kPoolSize];
+
+// Returns an id in the range [0 ... kPoolSize), which indexes into the
+// pool of random engines.
+//
+// Each thread to access the pool is assigned a sequential ID (without reuse)
+// from the pool-id space; the id is cached in a thread_local variable.
+// This id is assigned based on the arrival-order of the thread to the
+// GetPoolID call; this has no binary, CL, or runtime stability because
+// on subsequent runs the order within the same program may be significantly
+// different. However, as other thread IDs are not assigned sequentially,
+// this is not expected to matter.
+int GetPoolID() {
+ static_assert(kPoolSize >= 1,
+ "At least one urbg instance is required for PoolURBG");
+
+ ABSL_CONST_INIT static std::atomic<int64_t> sequence{0};
+
+#ifdef ABSL_HAVE_THREAD_LOCAL
+ static thread_local int my_pool_id = -1;
+ if (ABSL_PREDICT_FALSE(my_pool_id < 0)) {
+ my_pool_id = (sequence++ % kPoolSize);
+ }
+ return my_pool_id;
+#else
+ static pthread_key_t tid_key = [] {
+ pthread_key_t tmp_key;
+ int err = pthread_key_create(&tmp_key, nullptr);
+ if (err) {
+ ABSL_RAW_LOG(FATAL, "pthread_key_create failed with %d", err);
+ }
+ return tmp_key;
+ }();
+
+ // Store the value in the pthread_{get/set}specific. However an uninitialized
+ // value is 0, so add +1 to distinguish from the null value.
+ intptr_t my_pool_id =
+ reinterpret_cast<intptr_t>(pthread_getspecific(tid_key));
+ if (ABSL_PREDICT_FALSE(my_pool_id == 0)) {
+ // No allocated ID, allocate the next value, cache it, and return.
+ my_pool_id = (sequence++ % kPoolSize) + 1;
+ int err = pthread_setspecific(tid_key, reinterpret_cast<void*>(my_pool_id));
+ if (err) {
+ ABSL_RAW_LOG(FATAL, "pthread_setspecific failed with %d", err);
+ }
+ }
+ return my_pool_id - 1;
+#endif
+}
+
+// Allocate a RandenPoolEntry with at least 32-byte alignment, which is required
+// by ARM platform code.
+RandenPoolEntry* PoolAlignedAlloc() {
+ constexpr size_t kAlignment =
+ ABSL_CACHELINE_SIZE > 32 ? ABSL_CACHELINE_SIZE : 32;
+
+ // Not all the platforms that we build for have std::aligned_alloc, however
+ // since we never free these objects, we can over allocate and munge the
+ // pointers to the correct alignment.
+ void* memory = std::malloc(sizeof(RandenPoolEntry) + kAlignment);
+ auto x = reinterpret_cast<intptr_t>(memory);
+ auto y = x % kAlignment;
+ void* aligned =
+ (y == 0) ? memory : reinterpret_cast<void*>(x + kAlignment - y);
+ return new (aligned) RandenPoolEntry();
+}
+
+// Allocate and initialize kPoolSize objects of type RandenPoolEntry.
+//
+// The initialization strategy is to initialize one object directly from
+// OS entropy, then to use that object to seed all of the individual
+// pool instances.
+void InitPoolURBG() {
+ static constexpr size_t kSeedSize =
+ RandenTraits::kStateBytes / sizeof(uint32_t);
+ // Read the seed data from OS entropy once.
+ uint32_t seed_material[kPoolSize * kSeedSize];
+ if (!random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::MakeSpan(seed_material))) {
+ random_internal::ThrowSeedGenException();
+ }
+ for (int i = 0; i < kPoolSize; i++) {
+ shared_pools[i] = PoolAlignedAlloc();
+ shared_pools[i]->Init(
+ absl::MakeSpan(&seed_material[i * kSeedSize], kSeedSize));
+ }
+}
+
+// Returns the pool entry for the current thread.
+RandenPoolEntry* GetPoolForCurrentThread() {
+ absl::call_once(pool_once, InitPoolURBG);
+ return shared_pools[GetPoolID()];
+}
+
+} // namespace
+
+template <typename T>
+typename RandenPool<T>::result_type RandenPool<T>::Generate() {
+ auto* pool = GetPoolForCurrentThread();
+ return pool->Generate<T>();
+}
+
+template <typename T>
+void RandenPool<T>::Fill(absl::Span<result_type> data) {
+ auto* pool = GetPoolForCurrentThread();
+ pool->Fill(reinterpret_cast<uint8_t*>(data.data()),
+ data.size() * sizeof(result_type));
+}
+
+template class RandenPool<uint8_t>;
+template class RandenPool<uint16_t>;
+template class RandenPool<uint32_t>;
+template class RandenPool<uint64_t>;
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.h
new file mode 100644
index 00000000000..05721929f54
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg.h
@@ -0,0 +1,131 @@
+// 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_POOL_URBG_H_
+#define ABSL_RANDOM_INTERNAL_POOL_URBG_H_
+
+#include <cinttypes>
+#include <limits>
+
+#include "absl/random/internal/traits.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// RandenPool is a thread-safe random number generator [random.req.urbg] that
+// uses an underlying pool of Randen generators to generate values. Each thread
+// has affinity to one instance of the underlying pool generators. Concurrent
+// access is guarded by a spin-lock.
+template <typename T>
+class RandenPool {
+ public:
+ using result_type = T;
+ static_assert(std::is_unsigned<result_type>::value,
+ "RandenPool 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)();
+ }
+
+ RandenPool() {}
+
+ // Returns a single value.
+ inline result_type operator()() { return Generate(); }
+
+ // Fill data with random values.
+ static void Fill(absl::Span<result_type> data);
+
+ protected:
+ // Generate returns a single value.
+ static result_type Generate();
+};
+
+extern template class RandenPool<uint8_t>;
+extern template class RandenPool<uint16_t>;
+extern template class RandenPool<uint32_t>;
+extern template class RandenPool<uint64_t>;
+
+// PoolURBG uses an underlying pool of random generators to implement a
+// thread-compatible [random.req.urbg] interface with an internal cache of
+// values.
+template <typename T, size_t kBufferSize>
+class PoolURBG {
+ // Inheritance to access the protected static members of RandenPool.
+ using unsigned_type = typename make_unsigned_bits<T>::type;
+ using PoolType = RandenPool<unsigned_type>;
+ using SpanType = absl::Span<unsigned_type>;
+
+ static constexpr size_t kInitialBuffer = kBufferSize + 1;
+ static constexpr size_t kHalfBuffer = kBufferSize / 2;
+
+ public:
+ using result_type = T;
+
+ static_assert(std::is_unsigned<result_type>::value,
+ "PoolURBG must be parameterized by an unsigned integer type");
+
+ static_assert(kBufferSize > 1,
+ "PoolURBG must be parameterized by a buffer-size > 1");
+
+ static_assert(kBufferSize <= 256,
+ "PoolURBG must be parameterized by a buffer-size <= 256");
+
+ static constexpr result_type(min)() {
+ return (std::numeric_limits<result_type>::min)();
+ }
+
+ static constexpr result_type(max)() {
+ return (std::numeric_limits<result_type>::max)();
+ }
+
+ PoolURBG() : next_(kInitialBuffer) {}
+
+ // copy-constructor does not copy cache.
+ PoolURBG(const PoolURBG&) : next_(kInitialBuffer) {}
+ const PoolURBG& operator=(const PoolURBG&) {
+ next_ = kInitialBuffer;
+ return *this;
+ }
+
+ // move-constructor does move cache.
+ PoolURBG(PoolURBG&&) = default;
+ PoolURBG& operator=(PoolURBG&&) = default;
+
+ inline result_type operator()() {
+ if (next_ >= kBufferSize) {
+ next_ = (kBufferSize > 2 && next_ > kBufferSize) ? kHalfBuffer : 0;
+ PoolType::Fill(SpanType(reinterpret_cast<unsigned_type*>(state_ + next_),
+ kBufferSize - next_));
+ }
+ return state_[next_++];
+ }
+
+ private:
+ // Buffer size.
+ size_t next_; // index within state_
+ result_type state_[kBufferSize];
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_POOL_URBG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg_test.cc
new file mode 100644
index 00000000000..53f4eacf16f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/pool_urbg_test.cc
@@ -0,0 +1,182 @@
+// 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.
+
+#include "absl/random/internal/pool_urbg.h"
+
+#include <algorithm>
+#include <bitset>
+#include <cmath>
+#include <cstdint>
+#include <iterator>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/span.h"
+
+using absl::random_internal::PoolURBG;
+using absl::random_internal::RandenPool;
+
+namespace {
+
+// is_randen_pool trait is true when parameterized by an RandenPool
+template <typename T>
+using is_randen_pool = typename absl::disjunction< //
+ std::is_same<T, RandenPool<uint8_t>>, //
+ std::is_same<T, RandenPool<uint16_t>>, //
+ std::is_same<T, RandenPool<uint32_t>>, //
+ std::is_same<T, RandenPool<uint64_t>>>; //
+
+// MyFill either calls RandenPool::Fill() or std::generate(..., rng)
+template <typename T, typename V>
+typename absl::enable_if_t<absl::negation<is_randen_pool<T>>::value, void> //
+MyFill(T& rng, absl::Span<V> data) { // NOLINT(runtime/references)
+ std::generate(std::begin(data), std::end(data), rng);
+}
+
+template <typename T, typename V>
+typename absl::enable_if_t<is_randen_pool<T>::value, void> //
+MyFill(T& rng, absl::Span<V> data) { // NOLINT(runtime/references)
+ rng.Fill(data);
+}
+
+template <typename EngineType>
+class PoolURBGTypedTest : public ::testing::Test {};
+
+using EngineTypes = ::testing::Types< //
+ RandenPool<uint8_t>, //
+ RandenPool<uint16_t>, //
+ RandenPool<uint32_t>, //
+ RandenPool<uint64_t>, //
+ PoolURBG<uint8_t, 2>, //
+ PoolURBG<uint16_t, 2>, //
+ PoolURBG<uint32_t, 2>, //
+ PoolURBG<uint64_t, 2>, //
+ PoolURBG<unsigned int, 8>, // NOLINT(runtime/int)
+ PoolURBG<unsigned long, 8>, // NOLINT(runtime/int)
+ PoolURBG<unsigned long int, 4>, // NOLINT(runtime/int)
+ PoolURBG<unsigned long long, 4>>; // NOLINT(runtime/int)
+
+TYPED_TEST_SUITE(PoolURBGTypedTest, EngineTypes);
+
+// This test is checks that the engines meet the URBG interface requirements
+// defined in [rand.req.urbg].
+TYPED_TEST(PoolURBGTypedTest, URBGInterface) {
+ using E = TypeParam;
+ using T = typename E::result_type;
+
+ static_assert(std::is_copy_constructible<E>::value,
+ "engine must be copy constructible");
+
+ static_assert(absl::is_copy_assignable<E>::value,
+ "engine must be copy assignable");
+
+ E e;
+ const E x;
+
+ e();
+
+ static_assert(std::is_same<decltype(e()), T>::value,
+ "return type of operator() must be result_type");
+
+ E u0(x);
+ u0();
+
+ E u1 = e;
+ u1();
+}
+
+// This validates that sequences are independent.
+TYPED_TEST(PoolURBGTypedTest, VerifySequences) {
+ using E = TypeParam;
+ using result_type = typename E::result_type;
+
+ E rng;
+ (void)rng(); // Discard one value.
+
+ constexpr int kNumOutputs = 64;
+ result_type a[kNumOutputs];
+ result_type b[kNumOutputs];
+ std::fill(std::begin(b), std::end(b), 0);
+
+ // Fill a using Fill or generate, depending on the engine type.
+ {
+ E x = rng;
+ MyFill(x, absl::MakeSpan(a));
+ }
+
+ // Fill b using std::generate().
+ {
+ E x = rng;
+ std::generate(std::begin(b), std::end(b), x);
+ }
+
+ // Test that generated sequence changed as sequence of bits, i.e. if about
+ // half of the bites were flipped between two non-correlated values.
+ size_t changed_bits = 0;
+ size_t unchanged_bits = 0;
+ size_t total_set = 0;
+ size_t total_bits = 0;
+ size_t equal_count = 0;
+ for (size_t i = 0; i < kNumOutputs; ++i) {
+ equal_count += (a[i] == b[i]) ? 1 : 0;
+ std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
+ changed_bits += bitset.count();
+ unchanged_bits += bitset.size() - bitset.count();
+
+ std::bitset<sizeof(result_type) * 8> a_set(a[i]);
+ std::bitset<sizeof(result_type) * 8> b_set(b[i]);
+ total_set += a_set.count() + b_set.count();
+ total_bits += 2 * 8 * sizeof(result_type);
+ }
+ // On average, half the bits are changed between two calls.
+ EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
+ EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
+
+ // verify using a quick normal-approximation to the binomial.
+ EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
+ << "@" << total_set / static_cast<double>(total_bits);
+
+ // Also, A[i] == B[i] with probability (1/range) * N.
+ // Give this a pretty wide latitude, though.
+ const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
+ EXPECT_LE(equal_count, 1.0 + kExpected);
+}
+
+} // namespace
+
+/*
+$ nanobenchmarks 1 RandenPool construct
+$ nanobenchmarks 1 PoolURBG construct
+
+RandenPool<uint32_t> | 1 | 1000 | 48482.00 ticks | 48.48 ticks | 13.9 ns
+RandenPool<uint32_t> | 10 | 2000 | 1028795.00 ticks | 51.44 ticks | 14.7 ns
+RandenPool<uint32_t> | 100 | 1000 | 5119968.00 ticks | 51.20 ticks | 14.6 ns
+RandenPool<uint32_t> | 1000 | 500 | 25867936.00 ticks | 51.74 ticks | 14.8 ns
+
+RandenPool<uint64_t> | 1 | 1000 | 49921.00 ticks | 49.92 ticks | 14.3 ns
+RandenPool<uint64_t> | 10 | 2000 | 1208269.00 ticks | 60.41 ticks | 17.3 ns
+RandenPool<uint64_t> | 100 | 1000 | 5844955.00 ticks | 58.45 ticks | 16.7 ns
+RandenPool<uint64_t> | 1000 | 500 | 28767404.00 ticks | 57.53 ticks | 16.4 ns
+
+PoolURBG<uint32_t,8> | 1 | 1000 | 86431.00 ticks | 86.43 ticks | 24.7 ns
+PoolURBG<uint32_t,8> | 10 | 1000 | 206191.00 ticks | 20.62 ticks | 5.9 ns
+PoolURBG<uint32_t,8> | 100 | 1000 | 1516049.00 ticks | 15.16 ticks | 4.3 ns
+PoolURBG<uint32_t,8> | 1000 | 500 | 7613936.00 ticks | 15.23 ticks | 4.4 ns
+
+PoolURBG<uint64_t,4> | 1 | 1000 | 96668.00 ticks | 96.67 ticks | 27.6 ns
+PoolURBG<uint64_t,4> | 10 | 1000 | 282423.00 ticks | 28.24 ticks | 8.1 ns
+PoolURBG<uint64_t,4> | 100 | 1000 | 2609587.00 ticks | 26.10 ticks | 7.5 ns
+PoolURBG<uint64_t,4> | 1000 | 500 | 12408757.00 ticks | 24.82 ticks | 7.1 ns
+
+*/
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.cc
new file mode 100644
index 00000000000..c1bc0444354
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.cc
@@ -0,0 +1,91 @@
+// 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.
+
+#include "absl/random/internal/randen.h"
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/randen_detect.h"
+
+// 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.
+//
+// High-level summary:
+// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
+// a sponge-like random generator that requires a cryptographic permutation.
+// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
+// achieving backtracking resistance with only one Permute() per buffer.
+//
+// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
+// Function" constructs up to 1024-bit permutations using an improved
+// Generalized Feistel network with 2-round AES-128 functions. This Feistel
+// block shuffle achieves diffusion faster and is less vulnerable to
+// sliced-biclique attacks than the Type-2 cyclic shuffle.
+//
+// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
+// property" extends the same kind of improved Feistel block shuffle to 16
+// branches, which enables a 2048-bit permutation.
+//
+// We combine these three ideas and also change Simpira's subround keys from
+// structured/low-entropy counters to digits of Pi.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+struct RandenState {
+ const void* keys;
+ bool has_crypto;
+};
+
+RandenState GetRandenState() {
+ static const RandenState state = []() {
+ RandenState tmp;
+#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
+ // HW AES Dispatch.
+ if (HasRandenHwAesImplementation() && CPUSupportsRandenHwAes()) {
+ tmp.has_crypto = true;
+ tmp.keys = RandenHwAes::GetKeys();
+ } else {
+ tmp.has_crypto = false;
+ tmp.keys = RandenSlow::GetKeys();
+ }
+#elif ABSL_HAVE_ACCELERATED_AES
+ // HW AES is enabled.
+ tmp.has_crypto = true;
+ tmp.keys = RandenHwAes::GetKeys();
+#else
+ // HW AES is disabled.
+ tmp.has_crypto = false;
+ tmp.keys = RandenSlow::GetKeys();
+#endif
+ return tmp;
+ }();
+ return state;
+}
+
+} // namespace
+
+Randen::Randen() {
+ auto tmp = GetRandenState();
+ keys_ = tmp.keys;
+#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
+ has_crypto_ = tmp.has_crypto;
+#endif
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.h
new file mode 100644
index 00000000000..9a3840b8f16
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen.h
@@ -0,0 +1,102 @@
+// 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_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_H_
+
+#include <cstddef>
+
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_hwaes.h"
+#include "absl/random/internal/randen_slow.h"
+#include "absl/random/internal/randen_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// 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.
+//
+// Randen implements the basic state manipulation methods.
+class Randen {
+ public:
+ static constexpr size_t kStateBytes = RandenTraits::kStateBytes;
+ static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
+ static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes;
+
+ ~Randen() = default;
+
+ Randen();
+
+ // Generate updates the randen sponge. The outer portion of the sponge
+ // (kCapacityBytes .. kStateBytes) may be consumed as PRNG state.
+ template <typename T, size_t N>
+ void Generate(T (&state)[N]) const {
+ static_assert(N * sizeof(T) == kStateBytes,
+ "Randen::Generate() requires kStateBytes of state");
+#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
+ // HW AES Dispatch.
+ if (has_crypto_) {
+ RandenHwAes::Generate(keys_, state);
+ } else {
+ RandenSlow::Generate(keys_, state);
+ }
+#elif ABSL_HAVE_ACCELERATED_AES
+ // HW AES is enabled.
+ RandenHwAes::Generate(keys_, state);
+#else
+ // HW AES is disabled.
+ RandenSlow::Generate(keys_, state);
+#endif
+ }
+
+ // Absorb incorporates additional seed material into the randen sponge. After
+ // absorb returns, Generate must be called before the state may be consumed.
+ template <typename S, size_t M, typename T, size_t N>
+ void Absorb(const S (&seed)[M], T (&state)[N]) const {
+ static_assert(M * sizeof(S) == RandenTraits::kSeedBytes,
+ "Randen::Absorb() requires kSeedBytes of seed");
+
+ static_assert(N * sizeof(T) == RandenTraits::kStateBytes,
+ "Randen::Absorb() requires kStateBytes of state");
+#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
+ // HW AES Dispatch.
+ if (has_crypto_) {
+ RandenHwAes::Absorb(seed, state);
+ } else {
+ RandenSlow::Absorb(seed, state);
+ }
+#elif ABSL_HAVE_ACCELERATED_AES
+ // HW AES is enabled.
+ RandenHwAes::Absorb(seed, state);
+#else
+ // HW AES is disabled.
+ RandenSlow::Absorb(seed, state);
+#endif
+ }
+
+ private:
+ const void* keys_;
+#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
+ bool has_crypto_;
+#endif
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_benchmarks.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_benchmarks.cc
new file mode 100644
index 00000000000..f589172c046
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_benchmarks.cc
@@ -0,0 +1,174 @@
+// 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.
+//
+#include "absl/random/internal/randen.h"
+
+#include <cstdint>
+#include <cstdio>
+#include <cstring>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/nanobenchmark.h"
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_engine.h"
+#include "absl/random/internal/randen_hwaes.h"
+#include "absl/random/internal/randen_slow.h"
+#include "absl/strings/numbers.h"
+
+namespace {
+
+using absl::random_internal::Randen;
+using absl::random_internal::RandenHwAes;
+using absl::random_internal::RandenSlow;
+
+using absl::random_internal_nanobenchmark::FuncInput;
+using absl::random_internal_nanobenchmark::FuncOutput;
+using absl::random_internal_nanobenchmark::InvariantTicksPerSecond;
+using absl::random_internal_nanobenchmark::MeasureClosure;
+using absl::random_internal_nanobenchmark::Params;
+using absl::random_internal_nanobenchmark::PinThreadToCPU;
+using absl::random_internal_nanobenchmark::Result;
+
+// Local state parameters.
+static constexpr size_t kStateSizeT = Randen::kStateBytes / sizeof(uint64_t);
+static constexpr size_t kSeedSizeT = Randen::kSeedBytes / sizeof(uint32_t);
+
+// Randen implementation benchmarks.
+template <typename T>
+struct AbsorbFn : public T {
+ mutable uint64_t state[kStateSizeT] = {};
+ mutable uint32_t seed[kSeedSizeT] = {};
+
+ static constexpr size_t bytes() { return sizeof(seed); }
+
+ FuncOutput operator()(const FuncInput num_iters) const {
+ for (size_t i = 0; i < num_iters; ++i) {
+ this->Absorb(seed, state);
+ }
+ return state[0];
+ }
+};
+
+template <typename T>
+struct GenerateFn : public T {
+ mutable uint64_t state[kStateSizeT];
+ GenerateFn() { std::memset(state, 0, sizeof(state)); }
+
+ static constexpr size_t bytes() { return sizeof(state); }
+
+ FuncOutput operator()(const FuncInput num_iters) const {
+ const auto* keys = this->GetKeys();
+ for (size_t i = 0; i < num_iters; ++i) {
+ this->Generate(keys, state);
+ }
+ return state[0];
+ }
+};
+
+template <typename UInt>
+struct Engine {
+ mutable absl::random_internal::randen_engine<UInt> rng;
+
+ static constexpr size_t bytes() { return sizeof(UInt); }
+
+ FuncOutput operator()(const FuncInput num_iters) const {
+ for (size_t i = 0; i < num_iters - 1; ++i) {
+ rng();
+ }
+ return rng();
+ }
+};
+
+template <size_t N>
+void Print(const char* name, const size_t n, const Result (&results)[N],
+ const size_t bytes) {
+ if (n == 0) {
+ ABSL_RAW_LOG(
+ WARNING,
+ "WARNING: Measurement failed, should not happen when using "
+ "PinThreadToCPU unless the region to measure takes > 1 second.\n");
+ return;
+ }
+
+ static const double ns_per_tick = 1e9 / InvariantTicksPerSecond();
+ static constexpr const double kNsPerS = 1e9; // ns/s
+ static constexpr const double kMBPerByte = 1.0 / 1048576.0; // Mb / b
+ static auto header = [] {
+ return printf("%20s %8s: %12s ticks; %9s (%9s) %8s\n", "Name", "Count",
+ "Total", "Variance", "Time", "bytes/s");
+ }();
+ (void)header;
+
+ for (size_t i = 0; i < n; ++i) {
+ const double ticks_per_call = results[i].ticks / results[i].input;
+ const double ns_per_call = ns_per_tick * ticks_per_call;
+ const double bytes_per_ns = bytes / ns_per_call;
+ const double mb_per_s = bytes_per_ns * kNsPerS * kMBPerByte;
+ // Output
+ printf("%20s %8zu: %12.2f ticks; MAD=%4.2f%% (%6.1f ns) %8.1f Mb/s\n",
+ name, results[i].input, results[i].ticks,
+ results[i].variability * 100.0, ns_per_call, mb_per_s);
+ }
+}
+
+// Fails here
+template <typename Op, size_t N>
+void Measure(const char* name, const FuncInput (&inputs)[N]) {
+ Op op;
+
+ Result results[N];
+ Params params;
+ params.verbose = false;
+ params.max_evals = 6; // avoid test timeout
+ const size_t num_results = MeasureClosure(op, inputs, N, results, params);
+ Print(name, num_results, results, op.bytes());
+}
+
+// unpredictable == 1 but the compiler does not know that.
+void RunAll(const int argc, char* argv[]) {
+ if (argc == 2) {
+ int cpu = -1;
+ if (!absl::SimpleAtoi(argv[1], &cpu)) {
+ ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n");
+ }
+ PinThreadToCPU(cpu);
+ }
+
+ // The compiler cannot reduce this to a constant.
+ const FuncInput unpredictable = (argc != 999);
+ static const FuncInput inputs[] = {unpredictable * 100, unpredictable * 1000};
+
+#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES
+ Measure<AbsorbFn<RandenHwAes>>("Absorb (HwAes)", inputs);
+#endif
+ Measure<AbsorbFn<RandenSlow>>("Absorb (Slow)", inputs);
+
+#if !defined(ABSL_INTERNAL_DISABLE_AES) && ABSL_HAVE_ACCELERATED_AES
+ Measure<GenerateFn<RandenHwAes>>("Generate (HwAes)", inputs);
+#endif
+ Measure<GenerateFn<RandenSlow>>("Generate (Slow)", inputs);
+
+ // Measure the production engine.
+ static const FuncInput inputs1[] = {unpredictable * 1000,
+ unpredictable * 10000};
+ Measure<Engine<uint64_t>>("randen_engine<uint64_t>", inputs1);
+ Measure<Engine<uint32_t>>("randen_engine<uint32_t>", inputs1);
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ RunAll(argc, argv);
+ return 0;
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.cc
new file mode 100644
index 00000000000..bbe7b965329
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.cc
@@ -0,0 +1,221 @@
+// 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.
+
+// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
+// symbols from arbitrary system and other headers, since it may be built
+// with different flags from other targets, using different levels of
+// optimization, potentially introducing ODR violations.
+
+#include "absl/random/internal/randen_detect.h"
+
+#include <cstdint>
+#include <cstring>
+
+#include "absl/random/internal/platform.h"
+
+#if defined(ABSL_ARCH_X86_64)
+#define ABSL_INTERNAL_USE_X86_CPUID
+#elif defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \
+ defined(ABSL_ARCH_AARCH64)
+#if defined(__ANDROID__)
+#define ABSL_INTERNAL_USE_ANDROID_GETAUXVAL
+#define ABSL_INTERNAL_USE_GETAUXVAL
+#elif defined(__linux__)
+#define ABSL_INTERNAL_USE_LINUX_GETAUXVAL
+#define ABSL_INTERNAL_USE_GETAUXVAL
+#endif
+#endif
+
+#if defined(ABSL_INTERNAL_USE_X86_CPUID)
+#if defined(_WIN32) || defined(_WIN64)
+#include <intrin.h> // NOLINT(build/include_order)
+#pragma intrinsic(__cpuid)
+#else
+// MSVC-equivalent __cpuid intrinsic function.
+static void __cpuid(int cpu_info[4], int info_type) {
+ __asm__ volatile("cpuid \n\t"
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
+ "=d"(cpu_info[3])
+ : "a"(info_type), "c"(0));
+}
+#endif
+#endif // ABSL_INTERNAL_USE_X86_CPUID
+
+// On linux, just use the c-library getauxval call.
+#if defined(ABSL_INTERNAL_USE_LINUX_GETAUXVAL)
+
+extern "C" unsigned long getauxval(unsigned long type); // NOLINT(runtime/int)
+
+static uint32_t GetAuxval(uint32_t hwcap_type) {
+ return static_cast<uint32_t>(getauxval(hwcap_type));
+}
+
+#endif
+
+// On android, probe the system's C library for getauxval().
+// This is the same technique used by the android NDK cpu features library
+// as well as the google open-source cpu_features library.
+//
+// TODO(absl-team): Consider implementing a fallback of directly reading
+// /proc/self/auxval.
+#if defined(ABSL_INTERNAL_USE_ANDROID_GETAUXVAL)
+#include <dlfcn.h>
+
+static uint32_t GetAuxval(uint32_t hwcap_type) {
+ // NOLINTNEXTLINE(runtime/int)
+ typedef unsigned long (*getauxval_func_t)(unsigned long);
+
+ dlerror(); // Cleaning error state before calling dlopen.
+ void* libc_handle = dlopen("libc.so", RTLD_NOW);
+ if (!libc_handle) {
+ return 0;
+ }
+ uint32_t result = 0;
+ void* sym = dlsym(libc_handle, "getauxval");
+ if (sym) {
+ getauxval_func_t func;
+ memcpy(&func, &sym, sizeof(func));
+ result = static_cast<uint32_t>((*func)(hwcap_type));
+ }
+ dlclose(libc_handle);
+ return result;
+}
+
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// The default return at the end of the function might be unreachable depending
+// on the configuration. Ignore that warning.
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code-return"
+#endif
+
+// CPUSupportsRandenHwAes returns whether the CPU is a microarchitecture
+// which supports the crpyto/aes instructions or extensions necessary to use the
+// accelerated RandenHwAes implementation.
+//
+// 1. For x86 it is sufficient to use the CPUID instruction to detect whether
+// the cpu supports AES instructions. Done.
+//
+// Fon non-x86 it is much more complicated.
+//
+// 2. When ABSL_INTERNAL_USE_GETAUXVAL is defined, use getauxval() (either
+// the direct c-library version, or the android probing version which loads
+// libc), and read the hardware capability bits.
+// This is based on the technique used by boringssl uses to detect
+// cpu capabilities, and should allow us to enable crypto in the android
+// builds where it is supported.
+//
+// 3. Use the default for the compiler architecture.
+//
+
+bool CPUSupportsRandenHwAes() {
+#if defined(ABSL_INTERNAL_USE_X86_CPUID)
+ // 1. For x86: Use CPUID to detect the required AES instruction set.
+ int regs[4];
+ __cpuid(reinterpret_cast<int*>(regs), 1);
+ return regs[2] & (1 << 25); // AES
+
+#elif defined(ABSL_INTERNAL_USE_GETAUXVAL)
+ // 2. Use getauxval() to read the hardware bits and determine
+ // cpu capabilities.
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+#if defined(ABSL_ARCH_PPC)
+ // For Power / PPC: Expect that the cpu supports VCRYPTO
+ // See https://members.openpowerfoundation.org/document/dl/576
+ // VCRYPTO should be present in POWER8 >= 2.07.
+ // Uses Linux kernel constants from arch/powerpc/include/uapi/asm/cputable.h
+ static const uint32_t kVCRYPTO = 0x02000000;
+ const uint32_t hwcap = GetAuxval(AT_HWCAP2);
+ return (hwcap & kVCRYPTO) != 0;
+
+#elif defined(ABSL_ARCH_ARM)
+ // For ARM: Require crypto+neon
+ // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html
+ // Uses Linux kernel constants from arch/arm64/include/asm/hwcap.h
+ static const uint32_t kNEON = 1 << 12;
+ uint32_t hwcap = GetAuxval(AT_HWCAP);
+ if ((hwcap & kNEON) == 0) {
+ return false;
+ }
+
+ // And use it again to detect AES.
+ static const uint32_t kAES = 1 << 0;
+ const uint32_t hwcap2 = GetAuxval(AT_HWCAP2);
+ return (hwcap2 & kAES) != 0;
+
+#elif defined(ABSL_ARCH_AARCH64)
+ // For AARCH64: Require crypto+neon
+ // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500f/CIHBIBBA.html
+ static const uint32_t kNEON = 1 << 1;
+ static const uint32_t kAES = 1 << 3;
+ const uint32_t hwcap = GetAuxval(AT_HWCAP);
+ return ((hwcap & kNEON) != 0) && ((hwcap & kAES) != 0);
+#endif
+
+#else // ABSL_INTERNAL_USE_GETAUXVAL
+ // 3. By default, assume that the compiler default.
+ return ABSL_HAVE_ACCELERATED_AES ? true : false;
+
+#endif
+ // NOTE: There are some other techniques that may be worth trying:
+ //
+ // * Use an environment variable: ABSL_RANDOM_USE_HWAES
+ //
+ // * Rely on compiler-generated target-based dispatch.
+ // Using x86/gcc it might look something like this:
+ //
+ // int __attribute__((target("aes"))) HasAes() { return 1; }
+ // int __attribute__((target("default"))) HasAes() { return 0; }
+ //
+ // This does not work on all architecture/compiler combinations.
+ //
+ // * On Linux consider reading /proc/cpuinfo and/or /proc/self/auxv.
+ // These files have lines which are easy to parse; for ARM/AARCH64 it is quite
+ // easy to find the Features: line and extract aes / neon. Likewise for
+ // PPC.
+ //
+ // * Fork a process and test for SIGILL:
+ //
+ // * Many architectures have instructions to read the ISA. Unfortunately
+ // most of those require that the code is running in ring 0 /
+ // protected-mode.
+ //
+ // There are several examples. e.g. Valgrind detects PPC ISA 2.07:
+ // https://github.com/lu-zero/valgrind/blob/master/none/tests/ppc64/test_isa_2_07_part1.c
+ //
+ // MRS <Xt>, ID_AA64ISAR0_EL1 ; Read ID_AA64ISAR0_EL1 into Xt
+ //
+ // uint64_t val;
+ // __asm __volatile("mrs %0, id_aa64isar0_el1" :"=&r" (val));
+ //
+ // * Use a CPUID-style heuristic database.
+ //
+ // * On Apple (__APPLE__), AES is available on Arm v8.
+ // https://stackoverflow.com/questions/45637888/how-to-determine-armv8-features-at-runtime-on-ios
+}
+
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.h
new file mode 100644
index 00000000000..f283f432264
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_detect.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_RANDOM_INTERNAL_RANDEN_DETECT_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Returns whether the current CPU supports RandenHwAes implementation.
+// This typically involves supporting cryptographic extensions on whichever
+// platform is currently running.
+bool CPUSupportsRandenHwAes();
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_DETECT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine.h
new file mode 100644
index 00000000000..92bb8905f73
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine.h
@@ -0,0 +1,232 @@
+// 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(16) 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)();
+ }
+
+ explicit randen_engine(result_type seed_value = 0) { 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);
+ }
+
+ randen_engine(const randen_engine&) = default;
+
+ // Returns random bits from the buffer in units of result_type.
+ result_type operator()() {
+ // Refill the buffer if needed (unlikely).
+ if (next_ >= kStateSizeT) {
+ next_ = kCapacityT;
+ impl_.Generate(state_);
+ }
+
+ return little_endian::ToHost(state_[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
+ // mimics behaviour of reseed
+ std::fill(std::begin(state_), std::begin(state_) + kCapacityT, 0);
+ std::fill(std::begin(state_) + kCapacityT, std::end(state_), 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(std::begin(buffer) + requested_entropy, std::end(buffer), 0);
+ seq.generate(std::begin(buffer), std::begin(buffer) + requested_entropy);
+ // 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 prefering 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(std::begin(buffer), std::end(buffer));
+ }
+ 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;
+ while (count > 0) {
+ next_ = kCapacityT;
+ impl_.Generate(state_);
+ step = std::min<uint64_t>(kRateT, count);
+ count -= step;
+ }
+ next_ += step;
+ }
+
+ bool operator==(const randen_engine& other) const {
+ return next_ == other.next_ &&
+ std::equal(std::begin(state_), std::end(state_),
+ std::begin(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);
+ for (const auto& elem : engine.state_) {
+ // 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(elem))
+ << 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(engine.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);
+
+ // First kCapacityT are `inner', the others are accessible random bits.
+ alignas(16) result_type state_[kStateSizeT];
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine_test.cc
new file mode 100644
index 00000000000..c8e7685bdda
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_engine_test.cc
@@ -0,0 +1,656 @@
+// 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.
+
+#include "absl/random/internal/randen_engine.h"
+
+#include <algorithm>
+#include <bitset>
+#include <random>
+#include <sstream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/explicit_seed_seq.h"
+#include "absl/strings/str_cat.h"
+#include "absl/time/clock.h"
+
+#define UPDATE_GOLDEN 0
+
+using randen_u64 = absl::random_internal::randen_engine<uint64_t>;
+using randen_u32 = absl::random_internal::randen_engine<uint32_t>;
+using absl::random_internal::ExplicitSeedSeq;
+
+namespace {
+
+template <typename UIntType>
+class RandenEngineTypedTest : public ::testing::Test {};
+
+using UIntTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t>;
+
+TYPED_TEST_SUITE(RandenEngineTypedTest, UIntTypes);
+
+TYPED_TEST(RandenEngineTypedTest, VerifyReseedChangesAllValues) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+ using result_type = typename randen::result_type;
+
+ const size_t kNumOutputs = (sizeof(randen) * 2 / sizeof(TypeParam)) + 1;
+ randen engine;
+
+ // MSVC emits error 2719 without the use of std::ref below.
+ // * formal parameter with __declspec(align('#')) won't be aligned
+
+ {
+ std::seed_seq seq1{1, 2, 3, 4, 5, 6, 7};
+ engine.seed(seq1);
+ }
+ result_type a[kNumOutputs];
+ std::generate(std::begin(a), std::end(a), std::ref(engine));
+
+ {
+ std::random_device rd;
+ std::seed_seq seq2{rd(), rd(), rd()};
+ engine.seed(seq2);
+ }
+ result_type b[kNumOutputs];
+ std::generate(std::begin(b), std::end(b), std::ref(engine));
+
+ // Test that generated sequence changed as sequence of bits, i.e. if about
+ // half of the bites were flipped between two non-correlated values.
+ size_t changed_bits = 0;
+ size_t unchanged_bits = 0;
+ size_t total_set = 0;
+ size_t total_bits = 0;
+ size_t equal_count = 0;
+ for (size_t i = 0; i < kNumOutputs; ++i) {
+ equal_count += (a[i] == b[i]) ? 1 : 0;
+ std::bitset<sizeof(result_type) * 8> bitset(a[i] ^ b[i]);
+ changed_bits += bitset.count();
+ unchanged_bits += bitset.size() - bitset.count();
+
+ std::bitset<sizeof(result_type) * 8> a_set(a[i]);
+ std::bitset<sizeof(result_type) * 8> b_set(b[i]);
+ total_set += a_set.count() + b_set.count();
+ total_bits += 2 * 8 * sizeof(result_type);
+ }
+ // On average, half the bits are changed between two calls.
+ EXPECT_LE(changed_bits, 0.60 * (changed_bits + unchanged_bits));
+ EXPECT_GE(changed_bits, 0.40 * (changed_bits + unchanged_bits));
+
+ // Verify using a quick normal-approximation to the binomial.
+ EXPECT_NEAR(total_set, total_bits * 0.5, 4 * std::sqrt(total_bits))
+ << "@" << total_set / static_cast<double>(total_bits);
+
+ // Also, A[i] == B[i] with probability (1/range) * N.
+ // Give this a pretty wide latitude, though.
+ const double kExpected = kNumOutputs / (1.0 * sizeof(result_type) * 8);
+ EXPECT_LE(equal_count, 1.0 + kExpected);
+}
+
+// Number of values that needs to be consumed to clean two sizes of buffer
+// and trigger third refresh. (slightly overestimates the actual state size).
+constexpr size_t kTwoBufferValues = sizeof(randen_u64) / sizeof(uint16_t) + 1;
+
+TYPED_TEST(RandenEngineTypedTest, VerifyDiscard) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+
+ for (size_t num_used = 0; num_used < kTwoBufferValues; ++num_used) {
+ randen engine_used;
+ for (size_t i = 0; i < num_used; ++i) {
+ engine_used();
+ }
+
+ for (size_t num_discard = 0; num_discard < kTwoBufferValues;
+ ++num_discard) {
+ randen engine1 = engine_used;
+ randen engine2 = engine_used;
+ for (size_t i = 0; i < num_discard; ++i) {
+ engine1();
+ }
+ engine2.discard(num_discard);
+ for (size_t i = 0; i < kTwoBufferValues; ++i) {
+ const auto r1 = engine1();
+ const auto r2 = engine2();
+ ASSERT_EQ(r1, r2) << "used=" << num_used << " discard=" << num_discard;
+ }
+ }
+ }
+}
+
+TYPED_TEST(RandenEngineTypedTest, StreamOperatorsResult) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+ std::wostringstream os;
+ std::wistringstream is;
+ randen engine;
+
+ EXPECT_EQ(&(os << engine), &os);
+ EXPECT_EQ(&(is >> engine), &is);
+}
+
+TYPED_TEST(RandenEngineTypedTest, StreamSerialization) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+
+ for (size_t discard = 0; discard < kTwoBufferValues; ++discard) {
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ randen engine(seed_sequence);
+ engine.discard(discard);
+
+ std::stringstream stream;
+ stream << engine;
+
+ randen new_engine;
+ stream >> new_engine;
+ for (size_t i = 0; i < 64; ++i) {
+ EXPECT_EQ(engine(), new_engine()) << " " << i;
+ }
+ }
+}
+
+constexpr size_t kNumGoldenOutputs = 127;
+
+// This test is checking if randen_engine is meets interface requirements
+// defined in [rand.req.urbg].
+TYPED_TEST(RandenEngineTypedTest, RandomNumberEngineInterface) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+
+ using E = randen;
+ using T = typename E::result_type;
+
+ static_assert(std::is_copy_constructible<E>::value,
+ "randen_engine must be copy constructible");
+
+ static_assert(absl::is_copy_assignable<E>::value,
+ "randen_engine must be copy assignable");
+
+ static_assert(std::is_move_constructible<E>::value,
+ "randen_engine must be move constructible");
+
+ static_assert(absl::is_move_assignable<E>::value,
+ "randen_engine must be move assignable");
+
+ static_assert(std::is_same<decltype(std::declval<E>()()), T>::value,
+ "return type of operator() must be result_type");
+
+ // Names after definition of [rand.req.urbg] in C++ standard.
+ // e us a value of E
+ // v is a lvalue of E
+ // x, y are possibly const values of E
+ // s is a value of T
+ // q is a value satisfying requirements of seed_sequence
+ // z is a value of type unsigned long long
+ // os is a some specialization of basic_ostream
+ // is is a some specialization of basic_istream
+
+ E e, v;
+ const E x, y;
+ T s = 1;
+ std::seed_seq q{1, 2, 3};
+ unsigned long long z = 1; // NOLINT(runtime/int)
+ std::wostringstream os;
+ std::wistringstream is;
+
+ E{};
+ E{x};
+ E{s};
+ E{q};
+
+ e.seed();
+
+ // MSVC emits error 2718 when using EXPECT_EQ(e, x)
+ // * actual parameter with __declspec(align('#')) won't be aligned
+ EXPECT_TRUE(e == x);
+
+ e.seed(q);
+ {
+ E tmp(q);
+ EXPECT_TRUE(e == tmp);
+ }
+
+ e();
+ {
+ E tmp(q);
+ EXPECT_TRUE(e != tmp);
+ }
+
+ e.discard(z);
+
+ static_assert(std::is_same<decltype(x == y), bool>::value,
+ "return type of operator== must be bool");
+
+ static_assert(std::is_same<decltype(x != y), bool>::value,
+ "return type of operator== must be bool");
+}
+
+TYPED_TEST(RandenEngineTypedTest, RandenEngineSFINAETest) {
+ using randen = typename absl::random_internal::randen_engine<TypeParam>;
+ using result_type = typename randen::result_type;
+
+ {
+ randen engine(result_type(1));
+ engine.seed(result_type(1));
+ }
+
+ {
+ result_type n = 1;
+ randen engine(n);
+ engine.seed(n);
+ }
+
+ {
+ randen engine(1);
+ engine.seed(1);
+ }
+
+ {
+ int n = 1;
+ randen engine(n);
+ engine.seed(n);
+ }
+
+ {
+ std::seed_seq seed_seq;
+ randen engine(seed_seq);
+ engine.seed(seed_seq);
+ }
+
+ {
+ randen engine{std::seed_seq()};
+ engine.seed(std::seed_seq());
+ }
+}
+
+TEST(RandenTest, VerifyGoldenRanden64Default) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0xc3c14f134e433977, 0xdda9f47cd90410ee, 0x887bf3087fd8ca10,
+ 0xf0b780f545c72912, 0x15dbb1d37696599f, 0x30ec63baff3c6d59,
+ 0xb29f73606f7f20a6, 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e,
+ 0x9cbf605e3fd9de8a, 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5,
+ 0xf4b327fe0fc73c37, 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d,
+ 0xd5af05dd3eff9556, 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c,
+ 0x58d3575834956d42, 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3,
+ 0x497cabf3431154fc, 0x4e24370570029a8b, 0xd88b5749f090e5ea,
+ 0xc651a582a970692f, 0x78fcec2cbb6342f5, 0x463cb745612f55db,
+ 0x352ee4ad1816afe3, 0x026ff374c101da7e, 0x811ef0821c3de851,
+ 0x6f7e616704c4fa59, 0xa0660379992d58fc, 0x04b0a374a3b795c7,
+ 0x915f3445685da798, 0x26802a8ac76571ce, 0x4663352533ce1882,
+ 0xb9fdefb4a24dc738, 0x5588ba3a4d6e6c51, 0xa2101a42d35f1956,
+ 0x607195a5e200f5fd, 0x7e100308f3290764, 0xe1e5e03c759c0709,
+ 0x082572cc5da6606f, 0xcbcf585399e432f1, 0xe8a2be4f8335d8f1,
+ 0x0904469acbfee8f2, 0xf08bd31b6daecd51, 0x08e8a1f1a69da69a,
+ 0x6542a20aad57bff5, 0x2e9705bb053d6b46, 0xda2fc9db0713c391,
+ 0x78e3a810213b6ffb, 0xdc16a59cdd85f8a6, 0xc0932718cd55781f,
+ 0xb9bfb29c2b20bfe5, 0xb97289c1be0f2f9c, 0xc0a2a0e403a892d4,
+ 0x5524bb834771435b, 0x8265da3d39d1a750, 0xff4af3ab8d1b78c5,
+ 0xf0ec5f424bcad77f, 0x66e455f627495189, 0xc82d3120b57e3270,
+ 0x3424e47dc22596e3, 0xbc0c95129ccedcdd, 0xc191c595afc4dcbf,
+ 0x120392bd2bb70939, 0x7f90650ea6cd6ab4, 0x7287491832695ad3,
+ 0xa7c8fac5a7917eb0, 0xd088cb9418be0361, 0x7c1bf9839c7c1ce5,
+ 0xe2e991fa58e1e79e, 0x78565cdefd28c4ad, 0x7351b9fef98bafad,
+ 0x2a9eac28b08c96bf, 0x6c4f179696cb2225, 0x13a685861bab87e0,
+ 0x64c6de5aa0501971, 0x30537425cac70991, 0x01590d9dc6c532b7,
+ 0x7e05e3aa8ec720dc, 0x74a07d9c54e3e63f, 0x738184388f3bc1d2,
+ 0x26ffdc5067be3acb, 0x6bcdf185561f255f, 0xa0eaf2e1cf99b1c6,
+ 0x171df81934f68604, 0x7ea5a21665683e5a, 0x5d1cb02075ba1cea,
+ 0x957f38cbd2123fdf, 0xba6364eff80de02f, 0x606e0a0e41d452ee,
+ 0x892d8317de82f7a2, 0xe707b1db50f7b43e, 0x4eb28826766fcf5b,
+ 0x5a362d56e80a0951, 0x6ee217df16527d78, 0xf6737962ba6b23dd,
+ 0x443e63857d4076ca, 0x790d9a5f048adfeb, 0xd796b052151ee94d,
+ 0x033ed95c12b04a03, 0x8b833ff84893da5d, 0x3d6724b1bb15eab9,
+ 0x9877c4225061ca76, 0xd68d6810adf74fb3, 0x42e5352fe30ce989,
+ 0x265b565a7431fde7, 0x3cdbf7e358df4b8b, 0x2922a47f6d3e8779,
+ 0x52d2242f65b37f88, 0x5d836d6e2958d6b5, 0x29d40f00566d5e26,
+ 0x288db0e1124b14a0, 0x6c056608b7d9c1b6, 0x0b9471bdb8f19d32,
+ 0x8fb946504faa6c9d, 0x8943a9464540251c, 0xfd1fe27d144a09e0,
+ 0xea6ac458da141bda, 0x8048f217633fce36, 0xfeda1384ade74d31,
+ 0x4334b8b02ff7612f, 0xdbc8441f5227e216, 0x096d119a3605c85b,
+ 0x2b72b31c21b7d7d0};
+
+ randen_u64 engine;
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed();
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(RandenTest, VerifyGoldenRanden64Seeded) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0x83a9e58f94d3dcd5, 0x70bbdff3d97949fb, 0x0438481f7471c1b4,
+ 0x34fdc58ee5fb5930, 0xceee4f2d2a937d17, 0xb5a26a68e432aea9,
+ 0x8b64774a3fb51740, 0xd89ac1fc74249c74, 0x03910d1d23fc3fdf,
+ 0xd38f630878aa897f, 0x0ee8f0f5615f7e44, 0x98f5a53df8279d52,
+ 0xb403f52c25938d0e, 0x240072996ea6e838, 0xd3a791246190fa61,
+ 0xaaedd3df7a7b4f80, 0xc6eacabe05deaf6e, 0xb7967dd8790edf4d,
+ 0x9a0a8e67e049d279, 0x0494f606aebc23e7, 0x598dcd687bc3e0ee,
+ 0x010ac81802d452a1, 0x6407c87160aa2842, 0x5a56e276486f93a0,
+ 0xc887a399d46a8f02, 0x9e1e6100fe93b740, 0x12d02e330f8901f6,
+ 0xc39ca52b47e790b7, 0xb0b0a2fa11e82e61, 0x1542d841a303806a,
+ 0x1fe659fd7d6e9d86, 0xb8c90d80746541ac, 0x239d56a5669ddc94,
+ 0xd40db57c8123d13c, 0x3abc2414153a0db0, 0x9bad665630cb8d61,
+ 0x0bd1fb90ee3f4bbc, 0x8f0b4d7e079b4e42, 0xfa0fb0e0ee59e793,
+ 0x51080b283e071100, 0x2c4b9e715081cc15, 0xbe10ed49de4941df,
+ 0xf8eaac9d4b1b0d37, 0x4bcce4b54605e139, 0xa64722b76765dda6,
+ 0xb9377d738ca28ab5, 0x779fad81a8ccc1af, 0x65cb3ee61ffd3ba7,
+ 0xd74e79087862836f, 0xd05b9c584c3f25bf, 0x2ba93a4693579827,
+ 0xd81530aff05420ce, 0xec06cea215478621, 0x4b1798a6796d65ad,
+ 0xf142f3fb3a6f6fa6, 0x002b7bf7e237b560, 0xf47f2605ef65b4f8,
+ 0x9804ec5517effc18, 0xaed3d7f8b7d481cd, 0x5651c24c1ce338d1,
+ 0x3e7a38208bf0a3c6, 0x6796a7b614534aed, 0x0d0f3b848358460f,
+ 0x0fa5fe7600b19524, 0x2b0cf38253faaedc, 0x10df9188233a9fd6,
+ 0x3a10033880138b59, 0x5fb0b0d23948e80f, 0x9e76f7b02fbf5350,
+ 0x0816052304b1a985, 0x30c9880db41fd218, 0x14aa399b65e20f28,
+ 0xe1454a8cace787b4, 0x325ac971b6c6f0f5, 0x716b1aa2784f3d36,
+ 0x3d5ce14accfd144f, 0x6c0c97710f651792, 0xbc5b0f59fb333532,
+ 0x2a90a7d2140470bc, 0x8da269f55c1e1c8d, 0xcfc37143895792ca,
+ 0xbe21eab1f30b238f, 0x8c47229dee4d65fd, 0x5743614ed1ed7d54,
+ 0x351372a99e9c476e, 0x2bd5ea15e5db085f, 0x6925fde46e0af4ca,
+ 0xed3eda2bdc1f45bd, 0xdef68c68d460fa6e, 0xe42a0de76253e2b5,
+ 0x4e5176dcbc29c305, 0xbfd85fba9f810f6e, 0x76a5a2a9beb815c6,
+ 0x01edc4ddceaf414c, 0xa4e98904b4bb3b4b, 0x00bd63ac7d2f1ddd,
+ 0xb8491fe6e998ddbb, 0xb386a3463dda6800, 0x0081887688871619,
+ 0x33d394b3344e9a38, 0x815dba65a3a8baf9, 0x4232f6ec02c2fd1a,
+ 0xb5cff603edd20834, 0x580189243f687663, 0xa8d5a2cbdc27fe99,
+ 0x725d881693fa0131, 0xa2be2c13db2c7ac5, 0x7b6a9614b509fd78,
+ 0xb6b136d71e717636, 0x660f1a71aff046ea, 0x0ba10ae346c8ec9e,
+ 0xe66dde53e3145b41, 0x3b18288c88c26be6, 0x4d9d9d2ff02db933,
+ 0x4167da8c70f46e8a, 0xf183beef8c6318b4, 0x4d889e1e71eeeef1,
+ 0x7175c71ad6689b6b, 0xfb9e42beacd1b7dd, 0xc33d0e91b29b5e0d,
+ 0xd39b83291ce47922, 0xc4d570fb8493d12e, 0x23d5a5724f424ae6,
+ 0x5245f161876b6616, 0x38d77dbd21ab578d, 0x9c3423311f4ecbfe,
+ 0x76fe31389bacd9d5,
+ };
+
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ randen_u64 engine(seed_sequence);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed(seed_sequence);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(RandenTest, VerifyGoldenRanden32Default) {
+ constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {
+ 0x4e433977, 0xc3c14f13, 0xd90410ee, 0xdda9f47c, 0x7fd8ca10, 0x887bf308,
+ 0x45c72912, 0xf0b780f5, 0x7696599f, 0x15dbb1d3, 0xff3c6d59, 0x30ec63ba,
+ 0x6f7f20a6, 0xb29f7360, 0x6f49a54c, 0x02808a31, 0xd5c8e50e, 0x3b8feaf9,
+ 0x3fd9de8a, 0x9cbf605e, 0x78183bbb, 0xc970ae1a, 0x56301ed5, 0xd8b2ffd3,
+ 0x0fc73c37, 0xf4b327fe, 0xeb8f9a19, 0xcdfd8d76, 0x91420c9d, 0xc3a506eb,
+ 0x3eff9556, 0xd5af05dd, 0x8f83c4a1, 0x48db1bb7, 0x0d6bfe8c, 0x7023920e,
+ 0x34956d42, 0x58d35758, 0x6b87b840, 0xed1ef4c2, 0x3e0b2df3, 0x8eef32a2,
+ 0x431154fc, 0x497cabf3, 0x70029a8b, 0x4e243705, 0xf090e5ea, 0xd88b5749,
+ 0xa970692f, 0xc651a582, 0xbb6342f5, 0x78fcec2c, 0x612f55db, 0x463cb745,
+ 0x1816afe3, 0x352ee4ad, 0xc101da7e, 0x026ff374, 0x1c3de851, 0x811ef082,
+ 0x04c4fa59, 0x6f7e6167, 0x992d58fc, 0xa0660379, 0xa3b795c7, 0x04b0a374,
+ 0x685da798, 0x915f3445, 0xc76571ce, 0x26802a8a, 0x33ce1882, 0x46633525,
+ 0xa24dc738, 0xb9fdefb4, 0x4d6e6c51, 0x5588ba3a, 0xd35f1956, 0xa2101a42,
+ 0xe200f5fd, 0x607195a5, 0xf3290764, 0x7e100308, 0x759c0709, 0xe1e5e03c,
+ 0x5da6606f, 0x082572cc, 0x99e432f1, 0xcbcf5853, 0x8335d8f1, 0xe8a2be4f,
+ 0xcbfee8f2, 0x0904469a, 0x6daecd51, 0xf08bd31b, 0xa69da69a, 0x08e8a1f1,
+ 0xad57bff5, 0x6542a20a, 0x053d6b46, 0x2e9705bb, 0x0713c391, 0xda2fc9db,
+ 0x213b6ffb, 0x78e3a810, 0xdd85f8a6, 0xdc16a59c, 0xcd55781f, 0xc0932718,
+ 0x2b20bfe5, 0xb9bfb29c, 0xbe0f2f9c, 0xb97289c1, 0x03a892d4, 0xc0a2a0e4,
+ 0x4771435b, 0x5524bb83, 0x39d1a750, 0x8265da3d, 0x8d1b78c5, 0xff4af3ab,
+ 0x4bcad77f, 0xf0ec5f42, 0x27495189, 0x66e455f6, 0xb57e3270, 0xc82d3120,
+ 0xc22596e3, 0x3424e47d, 0x9ccedcdd, 0xbc0c9512, 0xafc4dcbf, 0xc191c595,
+ 0x2bb70939, 0x120392bd, 0xa6cd6ab4, 0x7f90650e, 0x32695ad3, 0x72874918,
+ 0xa7917eb0, 0xa7c8fac5, 0x18be0361, 0xd088cb94, 0x9c7c1ce5, 0x7c1bf983,
+ 0x58e1e79e, 0xe2e991fa, 0xfd28c4ad, 0x78565cde, 0xf98bafad, 0x7351b9fe,
+ 0xb08c96bf, 0x2a9eac28, 0x96cb2225, 0x6c4f1796, 0x1bab87e0, 0x13a68586,
+ 0xa0501971, 0x64c6de5a, 0xcac70991, 0x30537425, 0xc6c532b7, 0x01590d9d,
+ 0x8ec720dc, 0x7e05e3aa, 0x54e3e63f, 0x74a07d9c, 0x8f3bc1d2, 0x73818438,
+ 0x67be3acb, 0x26ffdc50, 0x561f255f, 0x6bcdf185, 0xcf99b1c6, 0xa0eaf2e1,
+ 0x34f68604, 0x171df819, 0x65683e5a, 0x7ea5a216, 0x75ba1cea, 0x5d1cb020,
+ 0xd2123fdf, 0x957f38cb, 0xf80de02f, 0xba6364ef, 0x41d452ee, 0x606e0a0e,
+ 0xde82f7a2, 0x892d8317, 0x50f7b43e, 0xe707b1db, 0x766fcf5b, 0x4eb28826,
+ 0xe80a0951, 0x5a362d56, 0x16527d78, 0x6ee217df, 0xba6b23dd, 0xf6737962,
+ 0x7d4076ca, 0x443e6385, 0x048adfeb, 0x790d9a5f, 0x151ee94d, 0xd796b052,
+ 0x12b04a03, 0x033ed95c, 0x4893da5d, 0x8b833ff8, 0xbb15eab9, 0x3d6724b1,
+ 0x5061ca76, 0x9877c422, 0xadf74fb3, 0xd68d6810, 0xe30ce989, 0x42e5352f,
+ 0x7431fde7, 0x265b565a, 0x58df4b8b, 0x3cdbf7e3, 0x6d3e8779, 0x2922a47f,
+ 0x65b37f88, 0x52d2242f, 0x2958d6b5, 0x5d836d6e, 0x566d5e26, 0x29d40f00,
+ 0x124b14a0, 0x288db0e1, 0xb7d9c1b6, 0x6c056608, 0xb8f19d32, 0x0b9471bd,
+ 0x4faa6c9d, 0x8fb94650, 0x4540251c, 0x8943a946, 0x144a09e0, 0xfd1fe27d,
+ 0xda141bda, 0xea6ac458, 0x633fce36, 0x8048f217, 0xade74d31, 0xfeda1384,
+ 0x2ff7612f, 0x4334b8b0, 0x5227e216, 0xdbc8441f, 0x3605c85b, 0x096d119a,
+ 0x21b7d7d0, 0x2b72b31c};
+
+ randen_u32 engine;
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {
+ printf("0x%08x, ", engine());
+ if (i % 6 == 5) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed();
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(RandenTest, VerifyGoldenRanden32Seeded) {
+ constexpr uint64_t kGolden[2 * kNumGoldenOutputs] = {
+ 0x94d3dcd5, 0x83a9e58f, 0xd97949fb, 0x70bbdff3, 0x7471c1b4, 0x0438481f,
+ 0xe5fb5930, 0x34fdc58e, 0x2a937d17, 0xceee4f2d, 0xe432aea9, 0xb5a26a68,
+ 0x3fb51740, 0x8b64774a, 0x74249c74, 0xd89ac1fc, 0x23fc3fdf, 0x03910d1d,
+ 0x78aa897f, 0xd38f6308, 0x615f7e44, 0x0ee8f0f5, 0xf8279d52, 0x98f5a53d,
+ 0x25938d0e, 0xb403f52c, 0x6ea6e838, 0x24007299, 0x6190fa61, 0xd3a79124,
+ 0x7a7b4f80, 0xaaedd3df, 0x05deaf6e, 0xc6eacabe, 0x790edf4d, 0xb7967dd8,
+ 0xe049d279, 0x9a0a8e67, 0xaebc23e7, 0x0494f606, 0x7bc3e0ee, 0x598dcd68,
+ 0x02d452a1, 0x010ac818, 0x60aa2842, 0x6407c871, 0x486f93a0, 0x5a56e276,
+ 0xd46a8f02, 0xc887a399, 0xfe93b740, 0x9e1e6100, 0x0f8901f6, 0x12d02e33,
+ 0x47e790b7, 0xc39ca52b, 0x11e82e61, 0xb0b0a2fa, 0xa303806a, 0x1542d841,
+ 0x7d6e9d86, 0x1fe659fd, 0x746541ac, 0xb8c90d80, 0x669ddc94, 0x239d56a5,
+ 0x8123d13c, 0xd40db57c, 0x153a0db0, 0x3abc2414, 0x30cb8d61, 0x9bad6656,
+ 0xee3f4bbc, 0x0bd1fb90, 0x079b4e42, 0x8f0b4d7e, 0xee59e793, 0xfa0fb0e0,
+ 0x3e071100, 0x51080b28, 0x5081cc15, 0x2c4b9e71, 0xde4941df, 0xbe10ed49,
+ 0x4b1b0d37, 0xf8eaac9d, 0x4605e139, 0x4bcce4b5, 0x6765dda6, 0xa64722b7,
+ 0x8ca28ab5, 0xb9377d73, 0xa8ccc1af, 0x779fad81, 0x1ffd3ba7, 0x65cb3ee6,
+ 0x7862836f, 0xd74e7908, 0x4c3f25bf, 0xd05b9c58, 0x93579827, 0x2ba93a46,
+ 0xf05420ce, 0xd81530af, 0x15478621, 0xec06cea2, 0x796d65ad, 0x4b1798a6,
+ 0x3a6f6fa6, 0xf142f3fb, 0xe237b560, 0x002b7bf7, 0xef65b4f8, 0xf47f2605,
+ 0x17effc18, 0x9804ec55, 0xb7d481cd, 0xaed3d7f8, 0x1ce338d1, 0x5651c24c,
+ 0x8bf0a3c6, 0x3e7a3820, 0x14534aed, 0x6796a7b6, 0x8358460f, 0x0d0f3b84,
+ 0x00b19524, 0x0fa5fe76, 0x53faaedc, 0x2b0cf382, 0x233a9fd6, 0x10df9188,
+ 0x80138b59, 0x3a100338, 0x3948e80f, 0x5fb0b0d2, 0x2fbf5350, 0x9e76f7b0,
+ 0x04b1a985, 0x08160523, 0xb41fd218, 0x30c9880d, 0x65e20f28, 0x14aa399b,
+ 0xace787b4, 0xe1454a8c, 0xb6c6f0f5, 0x325ac971, 0x784f3d36, 0x716b1aa2,
+ 0xccfd144f, 0x3d5ce14a, 0x0f651792, 0x6c0c9771, 0xfb333532, 0xbc5b0f59,
+ 0x140470bc, 0x2a90a7d2, 0x5c1e1c8d, 0x8da269f5, 0x895792ca, 0xcfc37143,
+ 0xf30b238f, 0xbe21eab1, 0xee4d65fd, 0x8c47229d, 0xd1ed7d54, 0x5743614e,
+ 0x9e9c476e, 0x351372a9, 0xe5db085f, 0x2bd5ea15, 0x6e0af4ca, 0x6925fde4,
+ 0xdc1f45bd, 0xed3eda2b, 0xd460fa6e, 0xdef68c68, 0x6253e2b5, 0xe42a0de7,
+ 0xbc29c305, 0x4e5176dc, 0x9f810f6e, 0xbfd85fba, 0xbeb815c6, 0x76a5a2a9,
+ 0xceaf414c, 0x01edc4dd, 0xb4bb3b4b, 0xa4e98904, 0x7d2f1ddd, 0x00bd63ac,
+ 0xe998ddbb, 0xb8491fe6, 0x3dda6800, 0xb386a346, 0x88871619, 0x00818876,
+ 0x344e9a38, 0x33d394b3, 0xa3a8baf9, 0x815dba65, 0x02c2fd1a, 0x4232f6ec,
+ 0xedd20834, 0xb5cff603, 0x3f687663, 0x58018924, 0xdc27fe99, 0xa8d5a2cb,
+ 0x93fa0131, 0x725d8816, 0xdb2c7ac5, 0xa2be2c13, 0xb509fd78, 0x7b6a9614,
+ 0x1e717636, 0xb6b136d7, 0xaff046ea, 0x660f1a71, 0x46c8ec9e, 0x0ba10ae3,
+ 0xe3145b41, 0xe66dde53, 0x88c26be6, 0x3b18288c, 0xf02db933, 0x4d9d9d2f,
+ 0x70f46e8a, 0x4167da8c, 0x8c6318b4, 0xf183beef, 0x71eeeef1, 0x4d889e1e,
+ 0xd6689b6b, 0x7175c71a, 0xacd1b7dd, 0xfb9e42be, 0xb29b5e0d, 0xc33d0e91,
+ 0x1ce47922, 0xd39b8329, 0x8493d12e, 0xc4d570fb, 0x4f424ae6, 0x23d5a572,
+ 0x876b6616, 0x5245f161, 0x21ab578d, 0x38d77dbd, 0x1f4ecbfe, 0x9c342331,
+ 0x9bacd9d5, 0x76fe3138,
+ };
+
+ ExplicitSeedSeq seed_sequence{12, 34, 56};
+ randen_u32 engine(seed_sequence);
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ for (size_t i = 0; i < 2 * kNumGoldenOutputs; ++i) {
+ printf("0x%08x, ", engine());
+ if (i % 6 == 5) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+ engine.seed(seed_sequence);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(RandenTest, VerifyGoldenFromDeserializedEngine) {
+ constexpr uint64_t kGolden[kNumGoldenOutputs] = {
+ 0x067f9f9ab919657a, 0x0534605912988583, 0x8a303f72feaa673f,
+ 0x77b7fd747909185c, 0xd9af90403c56d891, 0xd939c6cb204d14b5,
+ 0x7fbe6b954a47b483, 0x8b31a47cc34c768d, 0x3a9e546da2701a9c,
+ 0x5246539046253e71, 0x417191ffb2a848a1, 0x7b1c7bf5a5001d09,
+ 0x9489b15d194f2361, 0xfcebdeea3bcd2461, 0xd643027c854cec97,
+ 0x5885397f91e0d21c, 0x53173b0efae30d58, 0x1c9c71168449fac1,
+ 0xe358202b711ed8aa, 0x94e3918ed1d8227c, 0x5bb4e251450144cf,
+ 0xb5c7a519b489af3b, 0x6f8b560b1f7b3469, 0xfde11dd4a1c74eef,
+ 0x33383d2f76457dcf, 0x3060c0ec6db9fce1, 0x18f451fcddeec766,
+ 0xe73c5d6b9f26da2a, 0x8d4cc566671b32a4, 0xb8189b73776bc9ff,
+ 0x497a70f9caf0bc23, 0x23afcc509791dcea, 0x18af70dc4b27d306,
+ 0xd3853f955a0ce5b9, 0x441db6c01a0afb17, 0xd0136c3fb8e1f13f,
+ 0x5e4fd6fc2f33783c, 0xe0d24548adb5da51, 0x0f4d8362a7d3485a,
+ 0x9f572d68270fa563, 0x6351fbc823024393, 0xa66dbfc61810e9ab,
+ 0x0ff17fc14b651af8, 0xd74c55dafb99e623, 0x36303bc1ad85c6c2,
+ 0x4920cd6a2af7e897, 0x0b8848addc30fecd, 0x9e1562eda6488e93,
+ 0x197553807d607828, 0xbef5eaeda5e21235, 0x18d91d2616aca527,
+ 0xb7821937f5c873cd, 0x2cd4ae5650dbeefc, 0xb35a64376f75ffdf,
+ 0x9226d414d647fe07, 0x663f3db455bbb35e, 0xa829eead6ae93247,
+ 0x7fd69c204dd0d25f, 0xbe1411f891c9acb1, 0xd476f34a506d5f11,
+ 0xf423d2831649c5ca, 0x1e503962951abd75, 0xeccc9e8b1e34b537,
+ 0xb11a147294044854, 0xc4cf27f0abf4929d, 0xe9193abf6fa24c8c,
+ 0xa94a259e3aba8808, 0x21dc414197deffa3, 0xa2ae211d1ff622ae,
+ 0xfe3995c46be5a4f4, 0xe9984c284bf11128, 0xcb1ce9d2f0851a80,
+ 0x42fee17971d87cd8, 0xac76a98d177adc88, 0xa0973b3dedc4af6f,
+ 0xdf56d6bbcb1b8e86, 0xf1e6485f407b11c9, 0x2c63de4deccb15c0,
+ 0x6fe69db32ed4fad7, 0xaa51a65f84bca1f1, 0x242f2ee81d608afc,
+ 0x8eb88b2b69fc153b, 0x22c20098baf73fd1, 0x57759466f576488c,
+ 0x075ca562cea1be9d, 0x9a74814d73d28891, 0x73d1555fc02f4d3d,
+ 0xc17f8f210ee89337, 0x46cca7999eaeafd4, 0x5db8d6a327a0d8ac,
+ 0xb79b4f93c738d7a1, 0x9994512f0036ded1, 0xd3883026f38747f4,
+ 0xf31f7458078d097c, 0x736ce4d480680669, 0x7a496f4c7e1033e3,
+ 0xecf85bf297fbc68c, 0x9e37e1d0f24f3c4e, 0x15b6e067ca0746fc,
+ 0xdd4a39905c5db81c, 0xb5dfafa7bcfdf7da, 0xca6646fb6f92a276,
+ 0x1c6b35f363ef0efd, 0x6a33d06037ad9f76, 0x45544241afd8f80f,
+ 0x83f8d83f859c90c5, 0x22aea9c5365e8c19, 0xfac35b11f20b6a6a,
+ 0xd1acf49d1a27dd2f, 0xf281cd09c4fed405, 0x076000a42cd38e4f,
+ 0x6ace300565070445, 0x463a62781bddc4db, 0x1477126b46b569ac,
+ 0x127f2bb15035fbb8, 0xdfa30946049c04a8, 0x89072a586ba8dd3e,
+ 0x62c809582bb7e74d, 0x22c0c3641406c28b, 0x9b66e36c47ff004d,
+ 0xb9cd2c7519653330, 0x18608d79cd7a598d, 0x92c0bd1323e53e32,
+ 0x887ff00de8524aa5, 0xa074410b787abd10, 0x18ab41b8057a2063,
+ 0x1560abf26bc5f987};
+
+#if UPDATE_GOLDEN
+ (void)kGolden; // Silence warning.
+ std::seed_seq seed_sequence{1, 2, 3, 4, 5};
+ randen_u64 engine(seed_sequence);
+ std::ostringstream stream;
+ stream << engine;
+ auto str = stream.str();
+ printf("%s\n\n", str.c_str());
+ for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
+ printf("0x%016lx, ", engine());
+ if (i % 3 == 2) {
+ printf("\n");
+ }
+ }
+ printf("\n\n\n");
+#else
+ randen_u64 engine;
+ std::istringstream stream(
+ "0 0 9824501439887287479 3242284395352394785 243836530774933777 "
+ "4047941804708365596 17165468127298385802 949276103645889255 "
+ "10659970394998657921 1657570836810929787 11697746266668051452 "
+ "9967209969299905230 14140390331161524430 7383014124183271684 "
+ "13146719127702337852 13983155220295807171 11121125587542359264 "
+ "195757810993252695 17138580243103178492 11326030747260920501 "
+ "8585097322474965590 18342582839328350995 15052982824209724634 "
+ "7321861343874683609 1806786911778767826 10100850842665572955 "
+ "9249328950653985078 13600624835326909759 11137960060943860251 "
+ "10208781341792329629 9282723971471525577 16373271619486811032 32");
+ stream >> engine;
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, engine());
+ }
+#endif
+}
+
+TEST(RandenTest, IsFastOrSlow) {
+ // randen_engine typically costs ~5ns per value for the optimized code paths,
+ // and the ~1000ns per value for slow code paths. However when running under
+ // msan, asan, etc. it can take much longer.
+ //
+ // The estimated operation time is something like:
+ //
+ // linux, optimized ~5ns
+ // ppc, optimized ~7ns
+ // nacl (slow), ~1100ns
+ //
+ // `kCount` is chosen below so that, in debug builds and without hardware
+ // acceleration, the test (assuming ~1us per call) should finish in ~0.1s
+ static constexpr size_t kCount = 100000;
+ randen_u64 engine;
+ randen_u64::result_type sum = 0;
+ auto start = absl::GetCurrentTimeNanos();
+ for (int i = 0; i < kCount; i++) {
+ sum += engine();
+ }
+ auto duration = absl::GetCurrentTimeNanos() - start;
+
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat(static_cast<double>(duration) /
+ static_cast<double>(kCount),
+ "ns"));
+
+ EXPECT_GT(sum, 0);
+ EXPECT_GE(duration, kCount); // Should be slower than 1ns per call.
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.cc
new file mode 100644
index 00000000000..b5a3f90aee6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.cc
@@ -0,0 +1,573 @@
+// 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.
+
+// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
+// symbols from arbitrary system and other headers, since it may be built
+// with different flags from other targets, using different levels of
+// optimization, potentially introducing ODR violations.
+
+#include "absl/random/internal/randen_hwaes.h"
+
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/attributes.h"
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_traits.h"
+
+// ABSL_RANDEN_HWAES_IMPL indicates whether this file will contain
+// a hardware accelerated implementation of randen, or whether it
+// will contain stubs that exit the process.
+#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
+// The platform.h directives are sufficient to indicate whether
+// we should build accelerated implementations for x86.
+#if (ABSL_HAVE_ACCELERATED_AES || ABSL_RANDOM_INTERNAL_AES_DISPATCH)
+#define ABSL_RANDEN_HWAES_IMPL 1
+#endif
+#elif defined(ABSL_ARCH_PPC)
+// The platform.h directives are sufficient to indicate whether
+// we should build accelerated implementations for PPC.
+//
+// NOTE: This has mostly been tested on 64-bit Power variants,
+// and not embedded cpus such as powerpc32-8540
+#if ABSL_HAVE_ACCELERATED_AES
+#define ABSL_RANDEN_HWAES_IMPL 1
+#endif
+#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
+// ARM is somewhat more complicated. We might support crypto natively...
+#if ABSL_HAVE_ACCELERATED_AES || \
+ (defined(__ARM_NEON) && defined(__ARM_FEATURE_CRYPTO))
+#define ABSL_RANDEN_HWAES_IMPL 1
+
+#elif ABSL_RANDOM_INTERNAL_AES_DISPATCH && !defined(__APPLE__) && \
+ (defined(__GNUC__) && __GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ > 9)
+// ...or, on GCC, we can use an ASM directive to
+// instruct the assember to allow crypto instructions.
+#define ABSL_RANDEN_HWAES_IMPL 1
+#define ABSL_RANDEN_HWAES_IMPL_CRYPTO_DIRECTIVE 1
+#endif
+#else
+// HWAES is unsupported by these architectures / platforms:
+// __myriad2__
+// __mips__
+//
+// Other architectures / platforms are unknown.
+//
+// See the Abseil documentation on supported macros at:
+// https://abseil.io/docs/cpp/platforms/macros
+#endif
+
+#if !defined(ABSL_RANDEN_HWAES_IMPL)
+// No accelerated implementation is supported.
+// The RandenHwAes functions are stubs that print an error and exit.
+
+#include <cstdio>
+#include <cstdlib>
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// No accelerated implementation.
+bool HasRandenHwAesImplementation() { return false; }
+
+// NOLINTNEXTLINE
+const void* RandenHwAes::GetKeys() {
+ // Attempted to dispatch to an unsupported dispatch target.
+ const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
+ fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
+ exit(1);
+ return nullptr;
+}
+
+// NOLINTNEXTLINE
+void RandenHwAes::Absorb(const void*, void*) {
+ // Attempted to dispatch to an unsupported dispatch target.
+ const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
+ fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
+ exit(1);
+}
+
+// NOLINTNEXTLINE
+void RandenHwAes::Generate(const void*, void*) {
+ // Attempted to dispatch to an unsupported dispatch target.
+ const int d = ABSL_RANDOM_INTERNAL_AES_DISPATCH;
+ fprintf(stderr, "AES Hardware detection failed (%d).\n", d);
+ exit(1);
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#else // defined(ABSL_RANDEN_HWAES_IMPL)
+//
+// Accelerated implementations are supported.
+// We need the per-architecture includes and defines.
+//
+namespace {
+
+using absl::random_internal::RandenTraits;
+
+// Randen operates on 128-bit vectors.
+struct alignas(16) u64x2 {
+ uint64_t data[2];
+};
+
+} // namespace
+
+// TARGET_CRYPTO defines a crypto attribute for each architecture.
+//
+// NOTE: Evaluate whether we should eliminate ABSL_TARGET_CRYPTO.
+#if (defined(__clang__) || defined(__GNUC__))
+#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
+#define ABSL_TARGET_CRYPTO __attribute__((target("aes")))
+#elif defined(ABSL_ARCH_PPC)
+#define ABSL_TARGET_CRYPTO __attribute__((target("crypto")))
+#else
+#define ABSL_TARGET_CRYPTO
+#endif
+#else
+#define ABSL_TARGET_CRYPTO
+#endif
+
+#if defined(ABSL_ARCH_PPC)
+// NOTE: Keep in mind that PPC can operate in little-endian or big-endian mode,
+// however the PPC altivec vector registers (and thus the AES instructions)
+// always operate in big-endian mode.
+
+#include <altivec.h>
+// <altivec.h> #defines vector __vector; in C++, this is bad form.
+#undef vector
+#undef bool
+
+// Rely on the PowerPC AltiVec vector operations for accelerated AES
+// instructions. GCC support of the PPC vector types is described in:
+// https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/PowerPC-AltiVec_002fVSX-Built-in-Functions.html
+//
+// Already provides operator^=.
+using Vector128 = __vector unsigned long long; // NOLINT(runtime/int)
+
+namespace {
+inline ABSL_TARGET_CRYPTO Vector128 ReverseBytes(const Vector128& v) {
+ // Reverses the bytes of the vector.
+ const __vector unsigned char perm = {15, 14, 13, 12, 11, 10, 9, 8,
+ 7, 6, 5, 4, 3, 2, 1, 0};
+ return vec_perm(v, v, perm);
+}
+
+// WARNING: these load/store in native byte order. It is OK to load and then
+// store an unchanged vector, but interpreting the bits as a number or input
+// to AES will have undefined results.
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
+ return vec_vsx_ld(0, reinterpret_cast<const Vector128*>(from));
+}
+
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
+ vec_vsx_st(v, 0, reinterpret_cast<Vector128*>(to));
+}
+
+// One round of AES. "round_key" is a public constant for breaking the
+// symmetry of AES (ensures previously equal columns differ afterwards).
+inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
+ const Vector128& round_key) {
+ return Vector128(__builtin_crypto_vcipher(state, round_key));
+}
+
+// Enables native loads in the round loop by pre-swapping.
+inline ABSL_TARGET_CRYPTO void SwapEndian(u64x2* state) {
+ for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
+ Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block);
+ }
+}
+
+} // namespace
+
+#elif defined(ABSL_ARCH_ARM) || defined(ABSL_ARCH_AARCH64)
+
+// This asm directive will cause the file to be compiled with crypto extensions
+// whether or not the cpu-architecture supports it.
+#if ABSL_RANDEN_HWAES_IMPL_CRYPTO_DIRECTIVE
+asm(".arch_extension crypto\n");
+
+// Override missing defines.
+#if !defined(__ARM_NEON)
+#define __ARM_NEON 1
+#endif
+
+#if !defined(__ARM_FEATURE_CRYPTO)
+#define __ARM_FEATURE_CRYPTO 1
+#endif
+
+#endif
+
+// Rely on the ARM NEON+Crypto advanced simd types, defined in <arm_neon.h>.
+// uint8x16_t is the user alias for underlying __simd128_uint8_t type.
+// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
+//
+// <arm_neon> defines the following
+//
+// typedef __attribute__((neon_vector_type(16))) uint8_t uint8x16_t;
+// typedef __attribute__((neon_vector_type(16))) int8_t int8x16_t;
+// typedef __attribute__((neon_polyvector_type(16))) int8_t poly8x16_t;
+//
+// vld1q_v
+// vst1q_v
+// vaeseq_v
+// vaesmcq_v
+#include <arm_neon.h>
+
+// Already provides operator^=.
+using Vector128 = uint8x16_t;
+
+namespace {
+
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
+ return vld1q_u8(reinterpret_cast<const uint8_t*>(from));
+}
+
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
+ vst1q_u8(reinterpret_cast<uint8_t*>(to), v);
+}
+
+// One round of AES. "round_key" is a public constant for breaking the
+// symmetry of AES (ensures previously equal columns differ afterwards).
+inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
+ const Vector128& round_key) {
+ // It is important to always use the full round function - omitting the
+ // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]
+ // and does not help because we never decrypt.
+ //
+ // Note that ARM divides AES instructions differently than x86 / PPC,
+ // And we need to skip the first AddRoundKey step and add an extra
+ // AddRoundKey step to the end. Lucky for us this is just XOR.
+ return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;
+}
+
+inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
+
+} // namespace
+
+#elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
+// On x86 we rely on the aesni instructions
+#include <wmmintrin.h>
+
+namespace {
+
+// Vector128 class is only wrapper for __m128i, benchmark indicates that it's
+// faster than using __m128i directly.
+class Vector128 {
+ public:
+ // Convert from/to intrinsics.
+ inline explicit Vector128(const __m128i& Vector128) : data_(Vector128) {}
+
+ inline __m128i data() const { return data_; }
+
+ inline Vector128& operator^=(const Vector128& other) {
+ data_ = _mm_xor_si128(data_, other.data());
+ return *this;
+ }
+
+ private:
+ __m128i data_;
+};
+
+inline ABSL_TARGET_CRYPTO Vector128 Vector128Load(const void* from) {
+ return Vector128(_mm_load_si128(reinterpret_cast<const __m128i*>(from)));
+}
+
+inline ABSL_TARGET_CRYPTO void Vector128Store(const Vector128& v, void* to) {
+ _mm_store_si128(reinterpret_cast<__m128i*>(to), v.data());
+}
+
+// One round of AES. "round_key" is a public constant for breaking the
+// symmetry of AES (ensures previously equal columns differ afterwards).
+inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
+ const Vector128& round_key) {
+ // It is important to always use the full round function - omitting the
+ // final MixColumns reduces security [https://eprint.iacr.org/2010/041.pdf]
+ // and does not help because we never decrypt.
+ return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));
+}
+
+inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
+
+} // namespace
+
+#endif
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#endif
+
+// At this point, all of the platform-specific features have been defined /
+// implemented.
+//
+// REQUIRES: using Vector128 = ...
+// REQUIRES: Vector128 Vector128Load(void*) {...}
+// REQUIRES: void Vector128Store(Vector128, void*) {...}
+// REQUIRES: Vector128 AesRound(Vector128, Vector128) {...}
+// REQUIRES: void SwapEndian(uint64_t*) {...}
+//
+// PROVIDES: absl::random_internal::RandenHwAes::Absorb
+// PROVIDES: absl::random_internal::RandenHwAes::Generate
+namespace {
+
+// Block shuffles applies a shuffle to the entire state between AES rounds.
+// Improved odd-even shuffle from "New criterion for diffusion property".
+inline ABSL_TARGET_CRYPTO void BlockShuffle(u64x2* state) {
+ static_assert(RandenTraits::kFeistelBlocks == 16,
+ "Expecting 16 FeistelBlocks.");
+
+ constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
+ 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
+
+ const Vector128 v0 = Vector128Load(state + shuffle[0]);
+ const Vector128 v1 = Vector128Load(state + shuffle[1]);
+ const Vector128 v2 = Vector128Load(state + shuffle[2]);
+ const Vector128 v3 = Vector128Load(state + shuffle[3]);
+ const Vector128 v4 = Vector128Load(state + shuffle[4]);
+ const Vector128 v5 = Vector128Load(state + shuffle[5]);
+ const Vector128 v6 = Vector128Load(state + shuffle[6]);
+ const Vector128 v7 = Vector128Load(state + shuffle[7]);
+ const Vector128 w0 = Vector128Load(state + shuffle[8]);
+ const Vector128 w1 = Vector128Load(state + shuffle[9]);
+ const Vector128 w2 = Vector128Load(state + shuffle[10]);
+ const Vector128 w3 = Vector128Load(state + shuffle[11]);
+ const Vector128 w4 = Vector128Load(state + shuffle[12]);
+ const Vector128 w5 = Vector128Load(state + shuffle[13]);
+ const Vector128 w6 = Vector128Load(state + shuffle[14]);
+ const Vector128 w7 = Vector128Load(state + shuffle[15]);
+
+ Vector128Store(v0, state + 0);
+ Vector128Store(v1, state + 1);
+ Vector128Store(v2, state + 2);
+ Vector128Store(v3, state + 3);
+ Vector128Store(v4, state + 4);
+ Vector128Store(v5, state + 5);
+ Vector128Store(v6, state + 6);
+ Vector128Store(v7, state + 7);
+ Vector128Store(w0, state + 8);
+ Vector128Store(w1, state + 9);
+ Vector128Store(w2, state + 10);
+ Vector128Store(w3, state + 11);
+ Vector128Store(w4, state + 12);
+ Vector128Store(w5, state + 13);
+ Vector128Store(w6, state + 14);
+ Vector128Store(w7, state + 15);
+}
+
+// Feistel round function using two AES subrounds. Very similar to F()
+// from Simpira v2, but with independent subround keys. Uses 17 AES rounds
+// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in
+// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
+// XORs are 'free' (included in the second AES instruction).
+inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound(
+ u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ static_assert(RandenTraits::kFeistelBlocks == 16,
+ "Expecting 16 FeistelBlocks.");
+
+ // MSVC does a horrible job at unrolling loops.
+ // So we unroll the loop by hand to improve the performance.
+ const Vector128 s0 = Vector128Load(state + 0);
+ const Vector128 s1 = Vector128Load(state + 1);
+ const Vector128 s2 = Vector128Load(state + 2);
+ const Vector128 s3 = Vector128Load(state + 3);
+ const Vector128 s4 = Vector128Load(state + 4);
+ const Vector128 s5 = Vector128Load(state + 5);
+ const Vector128 s6 = Vector128Load(state + 6);
+ const Vector128 s7 = Vector128Load(state + 7);
+ const Vector128 s8 = Vector128Load(state + 8);
+ const Vector128 s9 = Vector128Load(state + 9);
+ const Vector128 s10 = Vector128Load(state + 10);
+ const Vector128 s11 = Vector128Load(state + 11);
+ const Vector128 s12 = Vector128Load(state + 12);
+ const Vector128 s13 = Vector128Load(state + 13);
+ const Vector128 s14 = Vector128Load(state + 14);
+ const Vector128 s15 = Vector128Load(state + 15);
+
+ // Encode even blocks with keys.
+ const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0));
+ const Vector128 e2 = AesRound(s2, Vector128Load(keys + 1));
+ const Vector128 e4 = AesRound(s4, Vector128Load(keys + 2));
+ const Vector128 e6 = AesRound(s6, Vector128Load(keys + 3));
+ const Vector128 e8 = AesRound(s8, Vector128Load(keys + 4));
+ const Vector128 e10 = AesRound(s10, Vector128Load(keys + 5));
+ const Vector128 e12 = AesRound(s12, Vector128Load(keys + 6));
+ const Vector128 e14 = AesRound(s14, Vector128Load(keys + 7));
+
+ // Encode odd blocks with even output from above.
+ const Vector128 o1 = AesRound(e0, s1);
+ const Vector128 o3 = AesRound(e2, s3);
+ const Vector128 o5 = AesRound(e4, s5);
+ const Vector128 o7 = AesRound(e6, s7);
+ const Vector128 o9 = AesRound(e8, s9);
+ const Vector128 o11 = AesRound(e10, s11);
+ const Vector128 o13 = AesRound(e12, s13);
+ const Vector128 o15 = AesRound(e14, s15);
+
+ // Store odd blocks. (These will be shuffled later).
+ Vector128Store(o1, state + 1);
+ Vector128Store(o3, state + 3);
+ Vector128Store(o5, state + 5);
+ Vector128Store(o7, state + 7);
+ Vector128Store(o9, state + 9);
+ Vector128Store(o11, state + 11);
+ Vector128Store(o13, state + 13);
+ Vector128Store(o15, state + 15);
+
+ return keys + 8;
+}
+
+// Cryptographic permutation based via type-2 Generalized Feistel Network.
+// Indistinguishable from ideal by chosen-ciphertext adversaries using less than
+// 2^64 queries if the round function is a PRF. This is similar to the b=8 case
+// of Simpira v2, but more efficient than its generic construction for b=16.
+inline ABSL_TARGET_CRYPTO void Permute(
+ u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ // (Successfully unrolled; the first iteration jumps into the second half)
+#ifdef __clang__
+#pragma clang loop unroll_count(2)
+#endif
+ for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
+ keys = FeistelRound(state, keys);
+ BlockShuffle(state);
+ }
+}
+
+} // namespace
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+bool HasRandenHwAesImplementation() { return true; }
+
+const void* ABSL_TARGET_CRYPTO RandenHwAes::GetKeys() {
+ // Round keys for one AES per Feistel round and branch.
+ // The canonical implementation uses first digits of Pi.
+#if defined(ABSL_ARCH_PPC)
+ return kRandenRoundKeysBE;
+#else
+ return kRandenRoundKeys;
+#endif
+}
+
+// NOLINTNEXTLINE
+void ABSL_TARGET_CRYPTO RandenHwAes::Absorb(const void* seed_void,
+ void* state_void) {
+ static_assert(RandenTraits::kCapacityBytes / sizeof(Vector128) == 1,
+ "Unexpected Randen kCapacityBlocks");
+ static_assert(RandenTraits::kStateBytes / sizeof(Vector128) == 16,
+ "Unexpected Randen kStateBlocks");
+
+ auto* state =
+ reinterpret_cast<u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
+ const auto* seed =
+ reinterpret_cast<const u64x2 * ABSL_RANDOM_INTERNAL_RESTRICT>(seed_void);
+
+ Vector128 b1 = Vector128Load(state + 1);
+ b1 ^= Vector128Load(seed + 0);
+ Vector128Store(b1, state + 1);
+
+ Vector128 b2 = Vector128Load(state + 2);
+ b2 ^= Vector128Load(seed + 1);
+ Vector128Store(b2, state + 2);
+
+ Vector128 b3 = Vector128Load(state + 3);
+ b3 ^= Vector128Load(seed + 2);
+ Vector128Store(b3, state + 3);
+
+ Vector128 b4 = Vector128Load(state + 4);
+ b4 ^= Vector128Load(seed + 3);
+ Vector128Store(b4, state + 4);
+
+ Vector128 b5 = Vector128Load(state + 5);
+ b5 ^= Vector128Load(seed + 4);
+ Vector128Store(b5, state + 5);
+
+ Vector128 b6 = Vector128Load(state + 6);
+ b6 ^= Vector128Load(seed + 5);
+ Vector128Store(b6, state + 6);
+
+ Vector128 b7 = Vector128Load(state + 7);
+ b7 ^= Vector128Load(seed + 6);
+ Vector128Store(b7, state + 7);
+
+ Vector128 b8 = Vector128Load(state + 8);
+ b8 ^= Vector128Load(seed + 7);
+ Vector128Store(b8, state + 8);
+
+ Vector128 b9 = Vector128Load(state + 9);
+ b9 ^= Vector128Load(seed + 8);
+ Vector128Store(b9, state + 9);
+
+ Vector128 b10 = Vector128Load(state + 10);
+ b10 ^= Vector128Load(seed + 9);
+ Vector128Store(b10, state + 10);
+
+ Vector128 b11 = Vector128Load(state + 11);
+ b11 ^= Vector128Load(seed + 10);
+ Vector128Store(b11, state + 11);
+
+ Vector128 b12 = Vector128Load(state + 12);
+ b12 ^= Vector128Load(seed + 11);
+ Vector128Store(b12, state + 12);
+
+ Vector128 b13 = Vector128Load(state + 13);
+ b13 ^= Vector128Load(seed + 12);
+ Vector128Store(b13, state + 13);
+
+ Vector128 b14 = Vector128Load(state + 14);
+ b14 ^= Vector128Load(seed + 13);
+ Vector128Store(b14, state + 14);
+
+ Vector128 b15 = Vector128Load(state + 15);
+ b15 ^= Vector128Load(seed + 14);
+ Vector128Store(b15, state + 15);
+}
+
+// NOLINTNEXTLINE
+void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void,
+ void* state_void) {
+ static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128),
+ "Capacity mismatch");
+
+ auto* state = reinterpret_cast<u64x2*>(state_void);
+ const auto* keys = reinterpret_cast<const u64x2*>(keys_void);
+
+ const Vector128 prev_inner = Vector128Load(state);
+
+ SwapEndian(state);
+
+ Permute(state, keys);
+
+ SwapEndian(state);
+
+ // Ensure backtracking resistance.
+ Vector128 inner = Vector128Load(state);
+ inner ^= prev_inner;
+ Vector128Store(inner, state);
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // (ABSL_RANDEN_HWAES_IMPL)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.h
new file mode 100644
index 00000000000..71a7f69f25b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes.h
@@ -0,0 +1,50 @@
+// 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_HWAES_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
+
+#include "absl/base/config.h"
+
+// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
+// symbols from arbitrary system and other headers, since it may be built
+// with different flags from other targets, using different levels of
+// optimization, potentially introducing ODR violations.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// 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.
+//
+// RandenHwAes implements the basic state manipulation methods.
+class RandenHwAes {
+ public:
+ static void Generate(const void* keys, void* state_void);
+ static void Absorb(const void* seed_void, void* state_void);
+ static const void* GetKeys();
+};
+
+// HasRandenHwAesImplementation returns true when there is an accelerated
+// implementation, and false otherwise. If there is no implementation,
+// then attempting to use it will abort the program.
+bool HasRandenHwAesImplementation();
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_HWAES_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes_test.cc
new file mode 100644
index 00000000000..66ddb43fd6a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_hwaes_test.cc
@@ -0,0 +1,104 @@
+// 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.
+
+#include "absl/random/internal/randen_hwaes.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_detect.h"
+#include "absl/random/internal/randen_traits.h"
+#include "absl/strings/str_format.h"
+
+namespace {
+
+using absl::random_internal::RandenHwAes;
+using absl::random_internal::RandenTraits;
+
+// Local state parameters.
+constexpr size_t kSeedBytes =
+ RandenTraits::kStateBytes - RandenTraits::kCapacityBytes;
+constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t);
+constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t);
+
+struct alignas(16) randen {
+ uint64_t state[kStateSizeT];
+ uint32_t seed[kSeedSizeT];
+};
+
+TEST(RandenHwAesTest, Default) {
+ EXPECT_TRUE(absl::random_internal::CPUSupportsRandenHwAes());
+
+ constexpr uint64_t kGolden[] = {
+ 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977,
+ 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912,
+ 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6,
+ 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a,
+ 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37,
+ 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556,
+ 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42,
+ 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc,
+ 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f,
+ 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3,
+ 0x026ff374c101da7e, 0x811ef0821c3de851,
+ };
+
+ alignas(16) randen d;
+ memset(d.state, 0, sizeof(d.state));
+ RandenHwAes::Generate(RandenHwAes::GetKeys(), d.state);
+
+ uint64_t* id = d.state;
+ for (const auto& elem : kGolden) {
+ auto a = absl::StrFormat("%#x", elem);
+ auto b = absl::StrFormat("%#x", *id++);
+ EXPECT_EQ(a, b);
+ }
+}
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ testing::InitGoogleTest(&argc, argv);
+
+ ABSL_RAW_LOG(INFO, "ABSL_HAVE_ACCELERATED_AES=%d", ABSL_HAVE_ACCELERATED_AES);
+ ABSL_RAW_LOG(INFO, "ABSL_RANDOM_INTERNAL_AES_DISPATCH=%d",
+ ABSL_RANDOM_INTERNAL_AES_DISPATCH);
+
+#if defined(ABSL_ARCH_X86_64)
+ ABSL_RAW_LOG(INFO, "ABSL_ARCH_X86_64");
+#elif defined(ABSL_ARCH_X86_32)
+ ABSL_RAW_LOG(INFO, "ABSL_ARCH_X86_32");
+#elif defined(ABSL_ARCH_AARCH64)
+ ABSL_RAW_LOG(INFO, "ABSL_ARCH_AARCH64");
+#elif defined(ABSL_ARCH_ARM)
+ ABSL_RAW_LOG(INFO, "ABSL_ARCH_ARM");
+#elif defined(ABSL_ARCH_PPC)
+ ABSL_RAW_LOG(INFO, "ABSL_ARCH_PPC");
+#else
+ ABSL_RAW_LOG(INFO, "ARCH Unknown");
+#endif
+
+ int x = absl::random_internal::HasRandenHwAesImplementation();
+ ABSL_RAW_LOG(INFO, "HasRandenHwAesImplementation = %d", x);
+
+ int y = absl::random_internal::CPUSupportsRandenHwAes();
+ ABSL_RAW_LOG(INFO, "CPUSupportsRandenHwAes = %d", x);
+
+ if (!x || !y) {
+ ABSL_RAW_LOG(INFO, "Skipping Randen HWAES tests.");
+ return 0;
+ }
+ return RUN_ALL_TESTS();
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_round_keys.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_round_keys.cc
new file mode 100644
index 00000000000..5fb3ca556db
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_round_keys.cc
@@ -0,0 +1,462 @@
+// 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.
+
+#include "absl/random/internal/randen_traits.h"
+
+// This file contains only the round keys for randen.
+//
+// "Nothing up my sleeve" numbers from the first hex digits of Pi, obtained
+// from http://hexpi.sourceforge.net/. The array was generated by following
+// Python script:
+
+/*
+python >tmp.cc << EOF
+"""Generates Randen round keys array from pi-hex.62500.txt file."""
+import binascii
+
+KEYS = 17 * 8
+
+def chunks(l, n):
+ """Yield successive n-sized chunks from l."""
+ for i in range(0, len(l), n):
+ yield l[i:i + n]
+
+def pairwise(t):
+ """Transforms sequence into sequence of pairs."""
+ it = iter(t)
+ return zip(it,it)
+
+def digits_from_pi():
+ """Reads digits from hexpi.sourceforge.net file."""
+ with open("pi-hex.62500.txt") as file:
+ return file.read()
+
+def digits_from_urandom():
+ """Reads digits from /dev/urandom."""
+ with open("/dev/urandom") as file:
+ return binascii.hexlify(file.read(KEYS * 16))
+
+def print_row(b)
+ print(" 0x{0}, 0x{1}, 0x{2}, 0x{3}, 0x{4}, 0x{5}, 0x{6}, 0x{7}, 0x{8}, 0x{9},
+0x{10}, 0x{11}, 0x{12}, 0x{13}, 0x{14}, 0x{15},".format(*b))
+
+
+digits = digits_from_pi()
+#digits = digits_from_urandom()
+
+print("namespace {")
+print("static constexpr size_t kKeyBytes = {0};\n".format(KEYS * 16))
+print("}")
+
+print("alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {")
+
+for i, u16 in zip(range(KEYS), chunks(digits, 32)):
+ b = list(chunks(u16, 2))
+ print_row(b)
+
+print("};")
+
+print("alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {")
+
+for i, u16 in zip(range(KEYS), chunks(digits, 32)):
+ b = list(chunks(u16, 2))
+ b.reverse()
+ print_row(b)
+
+print("};")
+
+EOF
+
+*/
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+static constexpr size_t kKeyBytes = 2176;
+}
+
+alignas(16) const unsigned char kRandenRoundKeysBE[kKeyBytes] = {
+ 0x24, 0x3F, 0x6A, 0x88, 0x85, 0xA3, 0x08, 0xD3, 0x13, 0x19, 0x8A, 0x2E,
+ 0x03, 0x70, 0x73, 0x44, 0xA4, 0x09, 0x38, 0x22, 0x29, 0x9F, 0x31, 0xD0,
+ 0x08, 0x2E, 0xFA, 0x98, 0xEC, 0x4E, 0x6C, 0x89, 0x45, 0x28, 0x21, 0xE6,
+ 0x38, 0xD0, 0x13, 0x77, 0xBE, 0x54, 0x66, 0xCF, 0x34, 0xE9, 0x0C, 0x6C,
+ 0xC0, 0xAC, 0x29, 0xB7, 0xC9, 0x7C, 0x50, 0xDD, 0x3F, 0x84, 0xD5, 0xB5,
+ 0xB5, 0x47, 0x09, 0x17, 0x92, 0x16, 0xD5, 0xD9, 0x89, 0x79, 0xFB, 0x1B,
+ 0xD1, 0x31, 0x0B, 0xA6, 0x98, 0xDF, 0xB5, 0xAC, 0x2F, 0xFD, 0x72, 0xDB,
+ 0xD0, 0x1A, 0xDF, 0xB7, 0xB8, 0xE1, 0xAF, 0xED, 0x6A, 0x26, 0x7E, 0x96,
+ 0xBA, 0x7C, 0x90, 0x45, 0xF1, 0x2C, 0x7F, 0x99, 0x24, 0xA1, 0x99, 0x47,
+ 0xB3, 0x91, 0x6C, 0xF7, 0x08, 0x01, 0xF2, 0xE2, 0x85, 0x8E, 0xFC, 0x16,
+ 0x63, 0x69, 0x20, 0xD8, 0x71, 0x57, 0x4E, 0x69, 0xA4, 0x58, 0xFE, 0xA3,
+ 0xF4, 0x93, 0x3D, 0x7E, 0x0D, 0x95, 0x74, 0x8F, 0x72, 0x8E, 0xB6, 0x58,
+ 0x71, 0x8B, 0xCD, 0x58, 0x82, 0x15, 0x4A, 0xEE, 0x7B, 0x54, 0xA4, 0x1D,
+ 0xC2, 0x5A, 0x59, 0xB5, 0x9C, 0x30, 0xD5, 0x39, 0x2A, 0xF2, 0x60, 0x13,
+ 0xC5, 0xD1, 0xB0, 0x23, 0x28, 0x60, 0x85, 0xF0, 0xCA, 0x41, 0x79, 0x18,
+ 0xB8, 0xDB, 0x38, 0xEF, 0x8E, 0x79, 0xDC, 0xB0, 0x60, 0x3A, 0x18, 0x0E,
+ 0x6C, 0x9E, 0x0E, 0x8B, 0xB0, 0x1E, 0x8A, 0x3E, 0xD7, 0x15, 0x77, 0xC1,
+ 0xBD, 0x31, 0x4B, 0x27, 0x78, 0xAF, 0x2F, 0xDA, 0x55, 0x60, 0x5C, 0x60,
+ 0xE6, 0x55, 0x25, 0xF3, 0xAA, 0x55, 0xAB, 0x94, 0x57, 0x48, 0x98, 0x62,
+ 0x63, 0xE8, 0x14, 0x40, 0x55, 0xCA, 0x39, 0x6A, 0x2A, 0xAB, 0x10, 0xB6,
+ 0xB4, 0xCC, 0x5C, 0x34, 0x11, 0x41, 0xE8, 0xCE, 0xA1, 0x54, 0x86, 0xAF,
+ 0x7C, 0x72, 0xE9, 0x93, 0xB3, 0xEE, 0x14, 0x11, 0x63, 0x6F, 0xBC, 0x2A,
+ 0x2B, 0xA9, 0xC5, 0x5D, 0x74, 0x18, 0x31, 0xF6, 0xCE, 0x5C, 0x3E, 0x16,
+ 0x9B, 0x87, 0x93, 0x1E, 0xAF, 0xD6, 0xBA, 0x33, 0x6C, 0x24, 0xCF, 0x5C,
+ 0x7A, 0x32, 0x53, 0x81, 0x28, 0x95, 0x86, 0x77, 0x3B, 0x8F, 0x48, 0x98,
+ 0x6B, 0x4B, 0xB9, 0xAF, 0xC4, 0xBF, 0xE8, 0x1B, 0x66, 0x28, 0x21, 0x93,
+ 0x61, 0xD8, 0x09, 0xCC, 0xFB, 0x21, 0xA9, 0x91, 0x48, 0x7C, 0xAC, 0x60,
+ 0x5D, 0xEC, 0x80, 0x32, 0xEF, 0x84, 0x5D, 0x5D, 0xE9, 0x85, 0x75, 0xB1,
+ 0xDC, 0x26, 0x23, 0x02, 0xEB, 0x65, 0x1B, 0x88, 0x23, 0x89, 0x3E, 0x81,
+ 0xD3, 0x96, 0xAC, 0xC5, 0x0F, 0x6D, 0x6F, 0xF3, 0x83, 0xF4, 0x42, 0x39,
+ 0x2E, 0x0B, 0x44, 0x82, 0xA4, 0x84, 0x20, 0x04, 0x69, 0xC8, 0xF0, 0x4A,
+ 0x9E, 0x1F, 0x9B, 0x5E, 0x21, 0xC6, 0x68, 0x42, 0xF6, 0xE9, 0x6C, 0x9A,
+ 0x67, 0x0C, 0x9C, 0x61, 0xAB, 0xD3, 0x88, 0xF0, 0x6A, 0x51, 0xA0, 0xD2,
+ 0xD8, 0x54, 0x2F, 0x68, 0x96, 0x0F, 0xA7, 0x28, 0xAB, 0x51, 0x33, 0xA3,
+ 0x6E, 0xEF, 0x0B, 0x6C, 0x13, 0x7A, 0x3B, 0xE4, 0xBA, 0x3B, 0xF0, 0x50,
+ 0x7E, 0xFB, 0x2A, 0x98, 0xA1, 0xF1, 0x65, 0x1D, 0x39, 0xAF, 0x01, 0x76,
+ 0x66, 0xCA, 0x59, 0x3E, 0x82, 0x43, 0x0E, 0x88, 0x8C, 0xEE, 0x86, 0x19,
+ 0x45, 0x6F, 0x9F, 0xB4, 0x7D, 0x84, 0xA5, 0xC3, 0x3B, 0x8B, 0x5E, 0xBE,
+ 0xE0, 0x6F, 0x75, 0xD8, 0x85, 0xC1, 0x20, 0x73, 0x40, 0x1A, 0x44, 0x9F,
+ 0x56, 0xC1, 0x6A, 0xA6, 0x4E, 0xD3, 0xAA, 0x62, 0x36, 0x3F, 0x77, 0x06,
+ 0x1B, 0xFE, 0xDF, 0x72, 0x42, 0x9B, 0x02, 0x3D, 0x37, 0xD0, 0xD7, 0x24,
+ 0xD0, 0x0A, 0x12, 0x48, 0xDB, 0x0F, 0xEA, 0xD3, 0x49, 0xF1, 0xC0, 0x9B,
+ 0x07, 0x53, 0x72, 0xC9, 0x80, 0x99, 0x1B, 0x7B, 0x25, 0xD4, 0x79, 0xD8,
+ 0xF6, 0xE8, 0xDE, 0xF7, 0xE3, 0xFE, 0x50, 0x1A, 0xB6, 0x79, 0x4C, 0x3B,
+ 0x97, 0x6C, 0xE0, 0xBD, 0x04, 0xC0, 0x06, 0xBA, 0xC1, 0xA9, 0x4F, 0xB6,
+ 0x40, 0x9F, 0x60, 0xC4, 0x5E, 0x5C, 0x9E, 0xC2, 0x19, 0x6A, 0x24, 0x63,
+ 0x68, 0xFB, 0x6F, 0xAF, 0x3E, 0x6C, 0x53, 0xB5, 0x13, 0x39, 0xB2, 0xEB,
+ 0x3B, 0x52, 0xEC, 0x6F, 0x6D, 0xFC, 0x51, 0x1F, 0x9B, 0x30, 0x95, 0x2C,
+ 0xCC, 0x81, 0x45, 0x44, 0xAF, 0x5E, 0xBD, 0x09, 0xBE, 0xE3, 0xD0, 0x04,
+ 0xDE, 0x33, 0x4A, 0xFD, 0x66, 0x0F, 0x28, 0x07, 0x19, 0x2E, 0x4B, 0xB3,
+ 0xC0, 0xCB, 0xA8, 0x57, 0x45, 0xC8, 0x74, 0x0F, 0xD2, 0x0B, 0x5F, 0x39,
+ 0xB9, 0xD3, 0xFB, 0xDB, 0x55, 0x79, 0xC0, 0xBD, 0x1A, 0x60, 0x32, 0x0A,
+ 0xD6, 0xA1, 0x00, 0xC6, 0x40, 0x2C, 0x72, 0x79, 0x67, 0x9F, 0x25, 0xFE,
+ 0xFB, 0x1F, 0xA3, 0xCC, 0x8E, 0xA5, 0xE9, 0xF8, 0xDB, 0x32, 0x22, 0xF8,
+ 0x3C, 0x75, 0x16, 0xDF, 0xFD, 0x61, 0x6B, 0x15, 0x2F, 0x50, 0x1E, 0xC8,
+ 0xAD, 0x05, 0x52, 0xAB, 0x32, 0x3D, 0xB5, 0xFA, 0xFD, 0x23, 0x87, 0x60,
+ 0x53, 0x31, 0x7B, 0x48, 0x3E, 0x00, 0xDF, 0x82, 0x9E, 0x5C, 0x57, 0xBB,
+ 0xCA, 0x6F, 0x8C, 0xA0, 0x1A, 0x87, 0x56, 0x2E, 0xDF, 0x17, 0x69, 0xDB,
+ 0xD5, 0x42, 0xA8, 0xF6, 0x28, 0x7E, 0xFF, 0xC3, 0xAC, 0x67, 0x32, 0xC6,
+ 0x8C, 0x4F, 0x55, 0x73, 0x69, 0x5B, 0x27, 0xB0, 0xBB, 0xCA, 0x58, 0xC8,
+ 0xE1, 0xFF, 0xA3, 0x5D, 0xB8, 0xF0, 0x11, 0xA0, 0x10, 0xFA, 0x3D, 0x98,
+ 0xFD, 0x21, 0x83, 0xB8, 0x4A, 0xFC, 0xB5, 0x6C, 0x2D, 0xD1, 0xD3, 0x5B,
+ 0x9A, 0x53, 0xE4, 0x79, 0xB6, 0xF8, 0x45, 0x65, 0xD2, 0x8E, 0x49, 0xBC,
+ 0x4B, 0xFB, 0x97, 0x90, 0xE1, 0xDD, 0xF2, 0xDA, 0xA4, 0xCB, 0x7E, 0x33,
+ 0x62, 0xFB, 0x13, 0x41, 0xCE, 0xE4, 0xC6, 0xE8, 0xEF, 0x20, 0xCA, 0xDA,
+ 0x36, 0x77, 0x4C, 0x01, 0xD0, 0x7E, 0x9E, 0xFE, 0x2B, 0xF1, 0x1F, 0xB4,
+ 0x95, 0xDB, 0xDA, 0x4D, 0xAE, 0x90, 0x91, 0x98, 0xEA, 0xAD, 0x8E, 0x71,
+ 0x6B, 0x93, 0xD5, 0xA0, 0xD0, 0x8E, 0xD1, 0xD0, 0xAF, 0xC7, 0x25, 0xE0,
+ 0x8E, 0x3C, 0x5B, 0x2F, 0x8E, 0x75, 0x94, 0xB7, 0x8F, 0xF6, 0xE2, 0xFB,
+ 0xF2, 0x12, 0x2B, 0x64, 0x88, 0x88, 0xB8, 0x12, 0x90, 0x0D, 0xF0, 0x1C,
+ 0x4F, 0xAD, 0x5E, 0xA0, 0x68, 0x8F, 0xC3, 0x1C, 0xD1, 0xCF, 0xF1, 0x91,
+ 0xB3, 0xA8, 0xC1, 0xAD, 0x2F, 0x2F, 0x22, 0x18, 0xBE, 0x0E, 0x17, 0x77,
+ 0xEA, 0x75, 0x2D, 0xFE, 0x8B, 0x02, 0x1F, 0xA1, 0xE5, 0xA0, 0xCC, 0x0F,
+ 0xB5, 0x6F, 0x74, 0xE8, 0x18, 0xAC, 0xF3, 0xD6, 0xCE, 0x89, 0xE2, 0x99,
+ 0xB4, 0xA8, 0x4F, 0xE0, 0xFD, 0x13, 0xE0, 0xB7, 0x7C, 0xC4, 0x3B, 0x81,
+ 0xD2, 0xAD, 0xA8, 0xD9, 0x16, 0x5F, 0xA2, 0x66, 0x80, 0x95, 0x77, 0x05,
+ 0x93, 0xCC, 0x73, 0x14, 0x21, 0x1A, 0x14, 0x77, 0xE6, 0xAD, 0x20, 0x65,
+ 0x77, 0xB5, 0xFA, 0x86, 0xC7, 0x54, 0x42, 0xF5, 0xFB, 0x9D, 0x35, 0xCF,
+ 0xEB, 0xCD, 0xAF, 0x0C, 0x7B, 0x3E, 0x89, 0xA0, 0xD6, 0x41, 0x1B, 0xD3,
+ 0xAE, 0x1E, 0x7E, 0x49, 0x00, 0x25, 0x0E, 0x2D, 0x20, 0x71, 0xB3, 0x5E,
+ 0x22, 0x68, 0x00, 0xBB, 0x57, 0xB8, 0xE0, 0xAF, 0x24, 0x64, 0x36, 0x9B,
+ 0xF0, 0x09, 0xB9, 0x1E, 0x55, 0x63, 0x91, 0x1D, 0x59, 0xDF, 0xA6, 0xAA,
+ 0x78, 0xC1, 0x43, 0x89, 0xD9, 0x5A, 0x53, 0x7F, 0x20, 0x7D, 0x5B, 0xA2,
+ 0x02, 0xE5, 0xB9, 0xC5, 0x83, 0x26, 0x03, 0x76, 0x62, 0x95, 0xCF, 0xA9,
+ 0x11, 0xC8, 0x19, 0x68, 0x4E, 0x73, 0x4A, 0x41, 0xB3, 0x47, 0x2D, 0xCA,
+ 0x7B, 0x14, 0xA9, 0x4A, 0x1B, 0x51, 0x00, 0x52, 0x9A, 0x53, 0x29, 0x15,
+ 0xD6, 0x0F, 0x57, 0x3F, 0xBC, 0x9B, 0xC6, 0xE4, 0x2B, 0x60, 0xA4, 0x76,
+ 0x81, 0xE6, 0x74, 0x00, 0x08, 0xBA, 0x6F, 0xB5, 0x57, 0x1B, 0xE9, 0x1F,
+ 0xF2, 0x96, 0xEC, 0x6B, 0x2A, 0x0D, 0xD9, 0x15, 0xB6, 0x63, 0x65, 0x21,
+ 0xE7, 0xB9, 0xF9, 0xB6, 0xFF, 0x34, 0x05, 0x2E, 0xC5, 0x85, 0x56, 0x64,
+ 0x53, 0xB0, 0x2D, 0x5D, 0xA9, 0x9F, 0x8F, 0xA1, 0x08, 0xBA, 0x47, 0x99,
+ 0x6E, 0x85, 0x07, 0x6A, 0x4B, 0x7A, 0x70, 0xE9, 0xB5, 0xB3, 0x29, 0x44,
+ 0xDB, 0x75, 0x09, 0x2E, 0xC4, 0x19, 0x26, 0x23, 0xAD, 0x6E, 0xA6, 0xB0,
+ 0x49, 0xA7, 0xDF, 0x7D, 0x9C, 0xEE, 0x60, 0xB8, 0x8F, 0xED, 0xB2, 0x66,
+ 0xEC, 0xAA, 0x8C, 0x71, 0x69, 0x9A, 0x18, 0xFF, 0x56, 0x64, 0x52, 0x6C,
+ 0xC2, 0xB1, 0x9E, 0xE1, 0x19, 0x36, 0x02, 0xA5, 0x75, 0x09, 0x4C, 0x29,
+ 0xA0, 0x59, 0x13, 0x40, 0xE4, 0x18, 0x3A, 0x3E, 0x3F, 0x54, 0x98, 0x9A,
+ 0x5B, 0x42, 0x9D, 0x65, 0x6B, 0x8F, 0xE4, 0xD6, 0x99, 0xF7, 0x3F, 0xD6,
+ 0xA1, 0xD2, 0x9C, 0x07, 0xEF, 0xE8, 0x30, 0xF5, 0x4D, 0x2D, 0x38, 0xE6,
+ 0xF0, 0x25, 0x5D, 0xC1, 0x4C, 0xDD, 0x20, 0x86, 0x84, 0x70, 0xEB, 0x26,
+ 0x63, 0x82, 0xE9, 0xC6, 0x02, 0x1E, 0xCC, 0x5E, 0x09, 0x68, 0x6B, 0x3F,
+ 0x3E, 0xBA, 0xEF, 0xC9, 0x3C, 0x97, 0x18, 0x14, 0x6B, 0x6A, 0x70, 0xA1,
+ 0x68, 0x7F, 0x35, 0x84, 0x52, 0xA0, 0xE2, 0x86, 0xB7, 0x9C, 0x53, 0x05,
+ 0xAA, 0x50, 0x07, 0x37, 0x3E, 0x07, 0x84, 0x1C, 0x7F, 0xDE, 0xAE, 0x5C,
+ 0x8E, 0x7D, 0x44, 0xEC, 0x57, 0x16, 0xF2, 0xB8, 0xB0, 0x3A, 0xDA, 0x37,
+ 0xF0, 0x50, 0x0C, 0x0D, 0xF0, 0x1C, 0x1F, 0x04, 0x02, 0x00, 0xB3, 0xFF,
+ 0xAE, 0x0C, 0xF5, 0x1A, 0x3C, 0xB5, 0x74, 0xB2, 0x25, 0x83, 0x7A, 0x58,
+ 0xDC, 0x09, 0x21, 0xBD, 0xD1, 0x91, 0x13, 0xF9, 0x7C, 0xA9, 0x2F, 0xF6,
+ 0x94, 0x32, 0x47, 0x73, 0x22, 0xF5, 0x47, 0x01, 0x3A, 0xE5, 0xE5, 0x81,
+ 0x37, 0xC2, 0xDA, 0xDC, 0xC8, 0xB5, 0x76, 0x34, 0x9A, 0xF3, 0xDD, 0xA7,
+ 0xA9, 0x44, 0x61, 0x46, 0x0F, 0xD0, 0x03, 0x0E, 0xEC, 0xC8, 0xC7, 0x3E,
+ 0xA4, 0x75, 0x1E, 0x41, 0xE2, 0x38, 0xCD, 0x99, 0x3B, 0xEA, 0x0E, 0x2F,
+ 0x32, 0x80, 0xBB, 0xA1, 0x18, 0x3E, 0xB3, 0x31, 0x4E, 0x54, 0x8B, 0x38,
+ 0x4F, 0x6D, 0xB9, 0x08, 0x6F, 0x42, 0x0D, 0x03, 0xF6, 0x0A, 0x04, 0xBF,
+ 0x2C, 0xB8, 0x12, 0x90, 0x24, 0x97, 0x7C, 0x79, 0x56, 0x79, 0xB0, 0x72,
+ 0xBC, 0xAF, 0x89, 0xAF, 0xDE, 0x9A, 0x77, 0x1F, 0xD9, 0x93, 0x08, 0x10,
+ 0xB3, 0x8B, 0xAE, 0x12, 0xDC, 0xCF, 0x3F, 0x2E, 0x55, 0x12, 0x72, 0x1F,
+ 0x2E, 0x6B, 0x71, 0x24, 0x50, 0x1A, 0xDD, 0xE6, 0x9F, 0x84, 0xCD, 0x87,
+ 0x7A, 0x58, 0x47, 0x18, 0x74, 0x08, 0xDA, 0x17, 0xBC, 0x9F, 0x9A, 0xBC,
+ 0xE9, 0x4B, 0x7D, 0x8C, 0xEC, 0x7A, 0xEC, 0x3A, 0xDB, 0x85, 0x1D, 0xFA,
+ 0x63, 0x09, 0x43, 0x66, 0xC4, 0x64, 0xC3, 0xD2, 0xEF, 0x1C, 0x18, 0x47,
+ 0x32, 0x15, 0xD8, 0x08, 0xDD, 0x43, 0x3B, 0x37, 0x24, 0xC2, 0xBA, 0x16,
+ 0x12, 0xA1, 0x4D, 0x43, 0x2A, 0x65, 0xC4, 0x51, 0x50, 0x94, 0x00, 0x02,
+ 0x13, 0x3A, 0xE4, 0xDD, 0x71, 0xDF, 0xF8, 0x9E, 0x10, 0x31, 0x4E, 0x55,
+ 0x81, 0xAC, 0x77, 0xD6, 0x5F, 0x11, 0x19, 0x9B, 0x04, 0x35, 0x56, 0xF1,
+ 0xD7, 0xA3, 0xC7, 0x6B, 0x3C, 0x11, 0x18, 0x3B, 0x59, 0x24, 0xA5, 0x09,
+ 0xF2, 0x8F, 0xE6, 0xED, 0x97, 0xF1, 0xFB, 0xFA, 0x9E, 0xBA, 0xBF, 0x2C,
+ 0x1E, 0x15, 0x3C, 0x6E, 0x86, 0xE3, 0x45, 0x70, 0xEA, 0xE9, 0x6F, 0xB1,
+ 0x86, 0x0E, 0x5E, 0x0A, 0x5A, 0x3E, 0x2A, 0xB3, 0x77, 0x1F, 0xE7, 0x1C,
+ 0x4E, 0x3D, 0x06, 0xFA, 0x29, 0x65, 0xDC, 0xB9, 0x99, 0xE7, 0x1D, 0x0F,
+ 0x80, 0x3E, 0x89, 0xD6, 0x52, 0x66, 0xC8, 0x25, 0x2E, 0x4C, 0xC9, 0x78,
+ 0x9C, 0x10, 0xB3, 0x6A, 0xC6, 0x15, 0x0E, 0xBA, 0x94, 0xE2, 0xEA, 0x78,
+ 0xA6, 0xFC, 0x3C, 0x53, 0x1E, 0x0A, 0x2D, 0xF4, 0xF2, 0xF7, 0x4E, 0xA7,
+ 0x36, 0x1D, 0x2B, 0x3D, 0x19, 0x39, 0x26, 0x0F, 0x19, 0xC2, 0x79, 0x60,
+ 0x52, 0x23, 0xA7, 0x08, 0xF7, 0x13, 0x12, 0xB6, 0xEB, 0xAD, 0xFE, 0x6E,
+ 0xEA, 0xC3, 0x1F, 0x66, 0xE3, 0xBC, 0x45, 0x95, 0xA6, 0x7B, 0xC8, 0x83,
+ 0xB1, 0x7F, 0x37, 0xD1, 0x01, 0x8C, 0xFF, 0x28, 0xC3, 0x32, 0xDD, 0xEF,
+ 0xBE, 0x6C, 0x5A, 0xA5, 0x65, 0x58, 0x21, 0x85, 0x68, 0xAB, 0x97, 0x02,
+ 0xEE, 0xCE, 0xA5, 0x0F, 0xDB, 0x2F, 0x95, 0x3B, 0x2A, 0xEF, 0x7D, 0xAD,
+ 0x5B, 0x6E, 0x2F, 0x84, 0x15, 0x21, 0xB6, 0x28, 0x29, 0x07, 0x61, 0x70,
+ 0xEC, 0xDD, 0x47, 0x75, 0x61, 0x9F, 0x15, 0x10, 0x13, 0xCC, 0xA8, 0x30,
+ 0xEB, 0x61, 0xBD, 0x96, 0x03, 0x34, 0xFE, 0x1E, 0xAA, 0x03, 0x63, 0xCF,
+ 0xB5, 0x73, 0x5C, 0x90, 0x4C, 0x70, 0xA2, 0x39, 0xD5, 0x9E, 0x9E, 0x0B,
+ 0xCB, 0xAA, 0xDE, 0x14, 0xEE, 0xCC, 0x86, 0xBC, 0x60, 0x62, 0x2C, 0xA7,
+ 0x9C, 0xAB, 0x5C, 0xAB, 0xB2, 0xF3, 0x84, 0x6E, 0x64, 0x8B, 0x1E, 0xAF,
+ 0x19, 0xBD, 0xF0, 0xCA, 0xA0, 0x23, 0x69, 0xB9, 0x65, 0x5A, 0xBB, 0x50,
+ 0x40, 0x68, 0x5A, 0x32, 0x3C, 0x2A, 0xB4, 0xB3, 0x31, 0x9E, 0xE9, 0xD5,
+ 0xC0, 0x21, 0xB8, 0xF7, 0x9B, 0x54, 0x0B, 0x19, 0x87, 0x5F, 0xA0, 0x99,
+ 0x95, 0xF7, 0x99, 0x7E, 0x62, 0x3D, 0x7D, 0xA8, 0xF8, 0x37, 0x88, 0x9A,
+ 0x97, 0xE3, 0x2D, 0x77, 0x11, 0xED, 0x93, 0x5F, 0x16, 0x68, 0x12, 0x81,
+ 0x0E, 0x35, 0x88, 0x29, 0xC7, 0xE6, 0x1F, 0xD6, 0x96, 0xDE, 0xDF, 0xA1,
+ 0x78, 0x58, 0xBA, 0x99, 0x57, 0xF5, 0x84, 0xA5, 0x1B, 0x22, 0x72, 0x63,
+ 0x9B, 0x83, 0xC3, 0xFF, 0x1A, 0xC2, 0x46, 0x96, 0xCD, 0xB3, 0x0A, 0xEB,
+ 0x53, 0x2E, 0x30, 0x54, 0x8F, 0xD9, 0x48, 0xE4, 0x6D, 0xBC, 0x31, 0x28,
+ 0x58, 0xEB, 0xF2, 0xEF, 0x34, 0xC6, 0xFF, 0xEA, 0xFE, 0x28, 0xED, 0x61,
+ 0xEE, 0x7C, 0x3C, 0x73, 0x5D, 0x4A, 0x14, 0xD9, 0xE8, 0x64, 0xB7, 0xE3,
+ 0x42, 0x10, 0x5D, 0x14, 0x20, 0x3E, 0x13, 0xE0, 0x45, 0xEE, 0xE2, 0xB6,
+ 0xA3, 0xAA, 0xAB, 0xEA, 0xDB, 0x6C, 0x4F, 0x15, 0xFA, 0xCB, 0x4F, 0xD0,
+ 0xC7, 0x42, 0xF4, 0x42, 0xEF, 0x6A, 0xBB, 0xB5, 0x65, 0x4F, 0x3B, 0x1D,
+ 0x41, 0xCD, 0x21, 0x05, 0xD8, 0x1E, 0x79, 0x9E, 0x86, 0x85, 0x4D, 0xC7,
+ 0xE4, 0x4B, 0x47, 0x6A, 0x3D, 0x81, 0x62, 0x50, 0xCF, 0x62, 0xA1, 0xF2,
+ 0x5B, 0x8D, 0x26, 0x46, 0xFC, 0x88, 0x83, 0xA0, 0xC1, 0xC7, 0xB6, 0xA3,
+ 0x7F, 0x15, 0x24, 0xC3, 0x69, 0xCB, 0x74, 0x92, 0x47, 0x84, 0x8A, 0x0B,
+ 0x56, 0x92, 0xB2, 0x85, 0x09, 0x5B, 0xBF, 0x00, 0xAD, 0x19, 0x48, 0x9D,
+ 0x14, 0x62, 0xB1, 0x74, 0x23, 0x82, 0x0D, 0x00, 0x58, 0x42, 0x8D, 0x2A,
+ 0x0C, 0x55, 0xF5, 0xEA, 0x1D, 0xAD, 0xF4, 0x3E, 0x23, 0x3F, 0x70, 0x61,
+ 0x33, 0x72, 0xF0, 0x92, 0x8D, 0x93, 0x7E, 0x41, 0xD6, 0x5F, 0xEC, 0xF1,
+ 0x6C, 0x22, 0x3B, 0xDB, 0x7C, 0xDE, 0x37, 0x59, 0xCB, 0xEE, 0x74, 0x60,
+ 0x40, 0x85, 0xF2, 0xA7, 0xCE, 0x77, 0x32, 0x6E, 0xA6, 0x07, 0x80, 0x84,
+ 0x19, 0xF8, 0x50, 0x9E, 0xE8, 0xEF, 0xD8, 0x55, 0x61, 0xD9, 0x97, 0x35,
+ 0xA9, 0x69, 0xA7, 0xAA, 0xC5, 0x0C, 0x06, 0xC2, 0x5A, 0x04, 0xAB, 0xFC,
+ 0x80, 0x0B, 0xCA, 0xDC, 0x9E, 0x44, 0x7A, 0x2E, 0xC3, 0x45, 0x34, 0x84,
+ 0xFD, 0xD5, 0x67, 0x05, 0x0E, 0x1E, 0x9E, 0xC9, 0xDB, 0x73, 0xDB, 0xD3,
+ 0x10, 0x55, 0x88, 0xCD, 0x67, 0x5F, 0xDA, 0x79, 0xE3, 0x67, 0x43, 0x40,
+ 0xC5, 0xC4, 0x34, 0x65, 0x71, 0x3E, 0x38, 0xD8, 0x3D, 0x28, 0xF8, 0x9E,
+ 0xF1, 0x6D, 0xFF, 0x20, 0x15, 0x3E, 0x21, 0xE7, 0x8F, 0xB0, 0x3D, 0x4A,
+ 0xE6, 0xE3, 0x9F, 0x2B, 0xDB, 0x83, 0xAD, 0xF7, 0xE9, 0x3D, 0x5A, 0x68,
+ 0x94, 0x81, 0x40, 0xF7, 0xF6, 0x4C, 0x26, 0x1C, 0x94, 0x69, 0x29, 0x34,
+ 0x41, 0x15, 0x20, 0xF7, 0x76, 0x02, 0xD4, 0xF7, 0xBC, 0xF4, 0x6B, 0x2E,
+ 0xD4, 0xA1, 0x00, 0x68, 0xD4, 0x08, 0x24, 0x71, 0x33, 0x20, 0xF4, 0x6A,
+ 0x43, 0xB7, 0xD4, 0xB7, 0x50, 0x00, 0x61, 0xAF, 0x1E, 0x39, 0xF6, 0x2E,
+ 0x97, 0x24, 0x45, 0x46,
+};
+
+alignas(16) const unsigned char kRandenRoundKeys[kKeyBytes] = {
+ 0x44, 0x73, 0x70, 0x03, 0x2E, 0x8A, 0x19, 0x13, 0xD3, 0x08, 0xA3, 0x85,
+ 0x88, 0x6A, 0x3F, 0x24, 0x89, 0x6C, 0x4E, 0xEC, 0x98, 0xFA, 0x2E, 0x08,
+ 0xD0, 0x31, 0x9F, 0x29, 0x22, 0x38, 0x09, 0xA4, 0x6C, 0x0C, 0xE9, 0x34,
+ 0xCF, 0x66, 0x54, 0xBE, 0x77, 0x13, 0xD0, 0x38, 0xE6, 0x21, 0x28, 0x45,
+ 0x17, 0x09, 0x47, 0xB5, 0xB5, 0xD5, 0x84, 0x3F, 0xDD, 0x50, 0x7C, 0xC9,
+ 0xB7, 0x29, 0xAC, 0xC0, 0xAC, 0xB5, 0xDF, 0x98, 0xA6, 0x0B, 0x31, 0xD1,
+ 0x1B, 0xFB, 0x79, 0x89, 0xD9, 0xD5, 0x16, 0x92, 0x96, 0x7E, 0x26, 0x6A,
+ 0xED, 0xAF, 0xE1, 0xB8, 0xB7, 0xDF, 0x1A, 0xD0, 0xDB, 0x72, 0xFD, 0x2F,
+ 0xF7, 0x6C, 0x91, 0xB3, 0x47, 0x99, 0xA1, 0x24, 0x99, 0x7F, 0x2C, 0xF1,
+ 0x45, 0x90, 0x7C, 0xBA, 0x69, 0x4E, 0x57, 0x71, 0xD8, 0x20, 0x69, 0x63,
+ 0x16, 0xFC, 0x8E, 0x85, 0xE2, 0xF2, 0x01, 0x08, 0x58, 0xB6, 0x8E, 0x72,
+ 0x8F, 0x74, 0x95, 0x0D, 0x7E, 0x3D, 0x93, 0xF4, 0xA3, 0xFE, 0x58, 0xA4,
+ 0xB5, 0x59, 0x5A, 0xC2, 0x1D, 0xA4, 0x54, 0x7B, 0xEE, 0x4A, 0x15, 0x82,
+ 0x58, 0xCD, 0x8B, 0x71, 0xF0, 0x85, 0x60, 0x28, 0x23, 0xB0, 0xD1, 0xC5,
+ 0x13, 0x60, 0xF2, 0x2A, 0x39, 0xD5, 0x30, 0x9C, 0x0E, 0x18, 0x3A, 0x60,
+ 0xB0, 0xDC, 0x79, 0x8E, 0xEF, 0x38, 0xDB, 0xB8, 0x18, 0x79, 0x41, 0xCA,
+ 0x27, 0x4B, 0x31, 0xBD, 0xC1, 0x77, 0x15, 0xD7, 0x3E, 0x8A, 0x1E, 0xB0,
+ 0x8B, 0x0E, 0x9E, 0x6C, 0x94, 0xAB, 0x55, 0xAA, 0xF3, 0x25, 0x55, 0xE6,
+ 0x60, 0x5C, 0x60, 0x55, 0xDA, 0x2F, 0xAF, 0x78, 0xB6, 0x10, 0xAB, 0x2A,
+ 0x6A, 0x39, 0xCA, 0x55, 0x40, 0x14, 0xE8, 0x63, 0x62, 0x98, 0x48, 0x57,
+ 0x93, 0xE9, 0x72, 0x7C, 0xAF, 0x86, 0x54, 0xA1, 0xCE, 0xE8, 0x41, 0x11,
+ 0x34, 0x5C, 0xCC, 0xB4, 0xF6, 0x31, 0x18, 0x74, 0x5D, 0xC5, 0xA9, 0x2B,
+ 0x2A, 0xBC, 0x6F, 0x63, 0x11, 0x14, 0xEE, 0xB3, 0x5C, 0xCF, 0x24, 0x6C,
+ 0x33, 0xBA, 0xD6, 0xAF, 0x1E, 0x93, 0x87, 0x9B, 0x16, 0x3E, 0x5C, 0xCE,
+ 0xAF, 0xB9, 0x4B, 0x6B, 0x98, 0x48, 0x8F, 0x3B, 0x77, 0x86, 0x95, 0x28,
+ 0x81, 0x53, 0x32, 0x7A, 0x91, 0xA9, 0x21, 0xFB, 0xCC, 0x09, 0xD8, 0x61,
+ 0x93, 0x21, 0x28, 0x66, 0x1B, 0xE8, 0xBF, 0xC4, 0xB1, 0x75, 0x85, 0xE9,
+ 0x5D, 0x5D, 0x84, 0xEF, 0x32, 0x80, 0xEC, 0x5D, 0x60, 0xAC, 0x7C, 0x48,
+ 0xC5, 0xAC, 0x96, 0xD3, 0x81, 0x3E, 0x89, 0x23, 0x88, 0x1B, 0x65, 0xEB,
+ 0x02, 0x23, 0x26, 0xDC, 0x04, 0x20, 0x84, 0xA4, 0x82, 0x44, 0x0B, 0x2E,
+ 0x39, 0x42, 0xF4, 0x83, 0xF3, 0x6F, 0x6D, 0x0F, 0x9A, 0x6C, 0xE9, 0xF6,
+ 0x42, 0x68, 0xC6, 0x21, 0x5E, 0x9B, 0x1F, 0x9E, 0x4A, 0xF0, 0xC8, 0x69,
+ 0x68, 0x2F, 0x54, 0xD8, 0xD2, 0xA0, 0x51, 0x6A, 0xF0, 0x88, 0xD3, 0xAB,
+ 0x61, 0x9C, 0x0C, 0x67, 0xE4, 0x3B, 0x7A, 0x13, 0x6C, 0x0B, 0xEF, 0x6E,
+ 0xA3, 0x33, 0x51, 0xAB, 0x28, 0xA7, 0x0F, 0x96, 0x76, 0x01, 0xAF, 0x39,
+ 0x1D, 0x65, 0xF1, 0xA1, 0x98, 0x2A, 0xFB, 0x7E, 0x50, 0xF0, 0x3B, 0xBA,
+ 0xB4, 0x9F, 0x6F, 0x45, 0x19, 0x86, 0xEE, 0x8C, 0x88, 0x0E, 0x43, 0x82,
+ 0x3E, 0x59, 0xCA, 0x66, 0x73, 0x20, 0xC1, 0x85, 0xD8, 0x75, 0x6F, 0xE0,
+ 0xBE, 0x5E, 0x8B, 0x3B, 0xC3, 0xA5, 0x84, 0x7D, 0x06, 0x77, 0x3F, 0x36,
+ 0x62, 0xAA, 0xD3, 0x4E, 0xA6, 0x6A, 0xC1, 0x56, 0x9F, 0x44, 0x1A, 0x40,
+ 0x48, 0x12, 0x0A, 0xD0, 0x24, 0xD7, 0xD0, 0x37, 0x3D, 0x02, 0x9B, 0x42,
+ 0x72, 0xDF, 0xFE, 0x1B, 0x7B, 0x1B, 0x99, 0x80, 0xC9, 0x72, 0x53, 0x07,
+ 0x9B, 0xC0, 0xF1, 0x49, 0xD3, 0xEA, 0x0F, 0xDB, 0x3B, 0x4C, 0x79, 0xB6,
+ 0x1A, 0x50, 0xFE, 0xE3, 0xF7, 0xDE, 0xE8, 0xF6, 0xD8, 0x79, 0xD4, 0x25,
+ 0xC4, 0x60, 0x9F, 0x40, 0xB6, 0x4F, 0xA9, 0xC1, 0xBA, 0x06, 0xC0, 0x04,
+ 0xBD, 0xE0, 0x6C, 0x97, 0xB5, 0x53, 0x6C, 0x3E, 0xAF, 0x6F, 0xFB, 0x68,
+ 0x63, 0x24, 0x6A, 0x19, 0xC2, 0x9E, 0x5C, 0x5E, 0x2C, 0x95, 0x30, 0x9B,
+ 0x1F, 0x51, 0xFC, 0x6D, 0x6F, 0xEC, 0x52, 0x3B, 0xEB, 0xB2, 0x39, 0x13,
+ 0xFD, 0x4A, 0x33, 0xDE, 0x04, 0xD0, 0xE3, 0xBE, 0x09, 0xBD, 0x5E, 0xAF,
+ 0x44, 0x45, 0x81, 0xCC, 0x0F, 0x74, 0xC8, 0x45, 0x57, 0xA8, 0xCB, 0xC0,
+ 0xB3, 0x4B, 0x2E, 0x19, 0x07, 0x28, 0x0F, 0x66, 0x0A, 0x32, 0x60, 0x1A,
+ 0xBD, 0xC0, 0x79, 0x55, 0xDB, 0xFB, 0xD3, 0xB9, 0x39, 0x5F, 0x0B, 0xD2,
+ 0xCC, 0xA3, 0x1F, 0xFB, 0xFE, 0x25, 0x9F, 0x67, 0x79, 0x72, 0x2C, 0x40,
+ 0xC6, 0x00, 0xA1, 0xD6, 0x15, 0x6B, 0x61, 0xFD, 0xDF, 0x16, 0x75, 0x3C,
+ 0xF8, 0x22, 0x32, 0xDB, 0xF8, 0xE9, 0xA5, 0x8E, 0x60, 0x87, 0x23, 0xFD,
+ 0xFA, 0xB5, 0x3D, 0x32, 0xAB, 0x52, 0x05, 0xAD, 0xC8, 0x1E, 0x50, 0x2F,
+ 0xA0, 0x8C, 0x6F, 0xCA, 0xBB, 0x57, 0x5C, 0x9E, 0x82, 0xDF, 0x00, 0x3E,
+ 0x48, 0x7B, 0x31, 0x53, 0xC3, 0xFF, 0x7E, 0x28, 0xF6, 0xA8, 0x42, 0xD5,
+ 0xDB, 0x69, 0x17, 0xDF, 0x2E, 0x56, 0x87, 0x1A, 0xC8, 0x58, 0xCA, 0xBB,
+ 0xB0, 0x27, 0x5B, 0x69, 0x73, 0x55, 0x4F, 0x8C, 0xC6, 0x32, 0x67, 0xAC,
+ 0xB8, 0x83, 0x21, 0xFD, 0x98, 0x3D, 0xFA, 0x10, 0xA0, 0x11, 0xF0, 0xB8,
+ 0x5D, 0xA3, 0xFF, 0xE1, 0x65, 0x45, 0xF8, 0xB6, 0x79, 0xE4, 0x53, 0x9A,
+ 0x5B, 0xD3, 0xD1, 0x2D, 0x6C, 0xB5, 0xFC, 0x4A, 0x33, 0x7E, 0xCB, 0xA4,
+ 0xDA, 0xF2, 0xDD, 0xE1, 0x90, 0x97, 0xFB, 0x4B, 0xBC, 0x49, 0x8E, 0xD2,
+ 0x01, 0x4C, 0x77, 0x36, 0xDA, 0xCA, 0x20, 0xEF, 0xE8, 0xC6, 0xE4, 0xCE,
+ 0x41, 0x13, 0xFB, 0x62, 0x98, 0x91, 0x90, 0xAE, 0x4D, 0xDA, 0xDB, 0x95,
+ 0xB4, 0x1F, 0xF1, 0x2B, 0xFE, 0x9E, 0x7E, 0xD0, 0xE0, 0x25, 0xC7, 0xAF,
+ 0xD0, 0xD1, 0x8E, 0xD0, 0xA0, 0xD5, 0x93, 0x6B, 0x71, 0x8E, 0xAD, 0xEA,
+ 0x64, 0x2B, 0x12, 0xF2, 0xFB, 0xE2, 0xF6, 0x8F, 0xB7, 0x94, 0x75, 0x8E,
+ 0x2F, 0x5B, 0x3C, 0x8E, 0x1C, 0xC3, 0x8F, 0x68, 0xA0, 0x5E, 0xAD, 0x4F,
+ 0x1C, 0xF0, 0x0D, 0x90, 0x12, 0xB8, 0x88, 0x88, 0x77, 0x17, 0x0E, 0xBE,
+ 0x18, 0x22, 0x2F, 0x2F, 0xAD, 0xC1, 0xA8, 0xB3, 0x91, 0xF1, 0xCF, 0xD1,
+ 0xE8, 0x74, 0x6F, 0xB5, 0x0F, 0xCC, 0xA0, 0xE5, 0xA1, 0x1F, 0x02, 0x8B,
+ 0xFE, 0x2D, 0x75, 0xEA, 0xB7, 0xE0, 0x13, 0xFD, 0xE0, 0x4F, 0xA8, 0xB4,
+ 0x99, 0xE2, 0x89, 0xCE, 0xD6, 0xF3, 0xAC, 0x18, 0x05, 0x77, 0x95, 0x80,
+ 0x66, 0xA2, 0x5F, 0x16, 0xD9, 0xA8, 0xAD, 0xD2, 0x81, 0x3B, 0xC4, 0x7C,
+ 0x86, 0xFA, 0xB5, 0x77, 0x65, 0x20, 0xAD, 0xE6, 0x77, 0x14, 0x1A, 0x21,
+ 0x14, 0x73, 0xCC, 0x93, 0xA0, 0x89, 0x3E, 0x7B, 0x0C, 0xAF, 0xCD, 0xEB,
+ 0xCF, 0x35, 0x9D, 0xFB, 0xF5, 0x42, 0x54, 0xC7, 0x5E, 0xB3, 0x71, 0x20,
+ 0x2D, 0x0E, 0x25, 0x00, 0x49, 0x7E, 0x1E, 0xAE, 0xD3, 0x1B, 0x41, 0xD6,
+ 0x1E, 0xB9, 0x09, 0xF0, 0x9B, 0x36, 0x64, 0x24, 0xAF, 0xE0, 0xB8, 0x57,
+ 0xBB, 0x00, 0x68, 0x22, 0x7F, 0x53, 0x5A, 0xD9, 0x89, 0x43, 0xC1, 0x78,
+ 0xAA, 0xA6, 0xDF, 0x59, 0x1D, 0x91, 0x63, 0x55, 0xA9, 0xCF, 0x95, 0x62,
+ 0x76, 0x03, 0x26, 0x83, 0xC5, 0xB9, 0xE5, 0x02, 0xA2, 0x5B, 0x7D, 0x20,
+ 0x4A, 0xA9, 0x14, 0x7B, 0xCA, 0x2D, 0x47, 0xB3, 0x41, 0x4A, 0x73, 0x4E,
+ 0x68, 0x19, 0xC8, 0x11, 0xE4, 0xC6, 0x9B, 0xBC, 0x3F, 0x57, 0x0F, 0xD6,
+ 0x15, 0x29, 0x53, 0x9A, 0x52, 0x00, 0x51, 0x1B, 0x1F, 0xE9, 0x1B, 0x57,
+ 0xB5, 0x6F, 0xBA, 0x08, 0x00, 0x74, 0xE6, 0x81, 0x76, 0xA4, 0x60, 0x2B,
+ 0xB6, 0xF9, 0xB9, 0xE7, 0x21, 0x65, 0x63, 0xB6, 0x15, 0xD9, 0x0D, 0x2A,
+ 0x6B, 0xEC, 0x96, 0xF2, 0xA1, 0x8F, 0x9F, 0xA9, 0x5D, 0x2D, 0xB0, 0x53,
+ 0x64, 0x56, 0x85, 0xC5, 0x2E, 0x05, 0x34, 0xFF, 0x44, 0x29, 0xB3, 0xB5,
+ 0xE9, 0x70, 0x7A, 0x4B, 0x6A, 0x07, 0x85, 0x6E, 0x99, 0x47, 0xBA, 0x08,
+ 0x7D, 0xDF, 0xA7, 0x49, 0xB0, 0xA6, 0x6E, 0xAD, 0x23, 0x26, 0x19, 0xC4,
+ 0x2E, 0x09, 0x75, 0xDB, 0xFF, 0x18, 0x9A, 0x69, 0x71, 0x8C, 0xAA, 0xEC,
+ 0x66, 0xB2, 0xED, 0x8F, 0xB8, 0x60, 0xEE, 0x9C, 0x29, 0x4C, 0x09, 0x75,
+ 0xA5, 0x02, 0x36, 0x19, 0xE1, 0x9E, 0xB1, 0xC2, 0x6C, 0x52, 0x64, 0x56,
+ 0x65, 0x9D, 0x42, 0x5B, 0x9A, 0x98, 0x54, 0x3F, 0x3E, 0x3A, 0x18, 0xE4,
+ 0x40, 0x13, 0x59, 0xA0, 0xF5, 0x30, 0xE8, 0xEF, 0x07, 0x9C, 0xD2, 0xA1,
+ 0xD6, 0x3F, 0xF7, 0x99, 0xD6, 0xE4, 0x8F, 0x6B, 0x26, 0xEB, 0x70, 0x84,
+ 0x86, 0x20, 0xDD, 0x4C, 0xC1, 0x5D, 0x25, 0xF0, 0xE6, 0x38, 0x2D, 0x4D,
+ 0xC9, 0xEF, 0xBA, 0x3E, 0x3F, 0x6B, 0x68, 0x09, 0x5E, 0xCC, 0x1E, 0x02,
+ 0xC6, 0xE9, 0x82, 0x63, 0x86, 0xE2, 0xA0, 0x52, 0x84, 0x35, 0x7F, 0x68,
+ 0xA1, 0x70, 0x6A, 0x6B, 0x14, 0x18, 0x97, 0x3C, 0x5C, 0xAE, 0xDE, 0x7F,
+ 0x1C, 0x84, 0x07, 0x3E, 0x37, 0x07, 0x50, 0xAA, 0x05, 0x53, 0x9C, 0xB7,
+ 0x0D, 0x0C, 0x50, 0xF0, 0x37, 0xDA, 0x3A, 0xB0, 0xB8, 0xF2, 0x16, 0x57,
+ 0xEC, 0x44, 0x7D, 0x8E, 0xB2, 0x74, 0xB5, 0x3C, 0x1A, 0xF5, 0x0C, 0xAE,
+ 0xFF, 0xB3, 0x00, 0x02, 0x04, 0x1F, 0x1C, 0xF0, 0xF6, 0x2F, 0xA9, 0x7C,
+ 0xF9, 0x13, 0x91, 0xD1, 0xBD, 0x21, 0x09, 0xDC, 0x58, 0x7A, 0x83, 0x25,
+ 0xDC, 0xDA, 0xC2, 0x37, 0x81, 0xE5, 0xE5, 0x3A, 0x01, 0x47, 0xF5, 0x22,
+ 0x73, 0x47, 0x32, 0x94, 0x0E, 0x03, 0xD0, 0x0F, 0x46, 0x61, 0x44, 0xA9,
+ 0xA7, 0xDD, 0xF3, 0x9A, 0x34, 0x76, 0xB5, 0xC8, 0x2F, 0x0E, 0xEA, 0x3B,
+ 0x99, 0xCD, 0x38, 0xE2, 0x41, 0x1E, 0x75, 0xA4, 0x3E, 0xC7, 0xC8, 0xEC,
+ 0x08, 0xB9, 0x6D, 0x4F, 0x38, 0x8B, 0x54, 0x4E, 0x31, 0xB3, 0x3E, 0x18,
+ 0xA1, 0xBB, 0x80, 0x32, 0x79, 0x7C, 0x97, 0x24, 0x90, 0x12, 0xB8, 0x2C,
+ 0xBF, 0x04, 0x0A, 0xF6, 0x03, 0x0D, 0x42, 0x6F, 0x10, 0x08, 0x93, 0xD9,
+ 0x1F, 0x77, 0x9A, 0xDE, 0xAF, 0x89, 0xAF, 0xBC, 0x72, 0xB0, 0x79, 0x56,
+ 0x24, 0x71, 0x6B, 0x2E, 0x1F, 0x72, 0x12, 0x55, 0x2E, 0x3F, 0xCF, 0xDC,
+ 0x12, 0xAE, 0x8B, 0xB3, 0x17, 0xDA, 0x08, 0x74, 0x18, 0x47, 0x58, 0x7A,
+ 0x87, 0xCD, 0x84, 0x9F, 0xE6, 0xDD, 0x1A, 0x50, 0xFA, 0x1D, 0x85, 0xDB,
+ 0x3A, 0xEC, 0x7A, 0xEC, 0x8C, 0x7D, 0x4B, 0xE9, 0xBC, 0x9A, 0x9F, 0xBC,
+ 0x08, 0xD8, 0x15, 0x32, 0x47, 0x18, 0x1C, 0xEF, 0xD2, 0xC3, 0x64, 0xC4,
+ 0x66, 0x43, 0x09, 0x63, 0x51, 0xC4, 0x65, 0x2A, 0x43, 0x4D, 0xA1, 0x12,
+ 0x16, 0xBA, 0xC2, 0x24, 0x37, 0x3B, 0x43, 0xDD, 0x55, 0x4E, 0x31, 0x10,
+ 0x9E, 0xF8, 0xDF, 0x71, 0xDD, 0xE4, 0x3A, 0x13, 0x02, 0x00, 0x94, 0x50,
+ 0x6B, 0xC7, 0xA3, 0xD7, 0xF1, 0x56, 0x35, 0x04, 0x9B, 0x19, 0x11, 0x5F,
+ 0xD6, 0x77, 0xAC, 0x81, 0xFA, 0xFB, 0xF1, 0x97, 0xED, 0xE6, 0x8F, 0xF2,
+ 0x09, 0xA5, 0x24, 0x59, 0x3B, 0x18, 0x11, 0x3C, 0xB1, 0x6F, 0xE9, 0xEA,
+ 0x70, 0x45, 0xE3, 0x86, 0x6E, 0x3C, 0x15, 0x1E, 0x2C, 0xBF, 0xBA, 0x9E,
+ 0xFA, 0x06, 0x3D, 0x4E, 0x1C, 0xE7, 0x1F, 0x77, 0xB3, 0x2A, 0x3E, 0x5A,
+ 0x0A, 0x5E, 0x0E, 0x86, 0x25, 0xC8, 0x66, 0x52, 0xD6, 0x89, 0x3E, 0x80,
+ 0x0F, 0x1D, 0xE7, 0x99, 0xB9, 0xDC, 0x65, 0x29, 0x78, 0xEA, 0xE2, 0x94,
+ 0xBA, 0x0E, 0x15, 0xC6, 0x6A, 0xB3, 0x10, 0x9C, 0x78, 0xC9, 0x4C, 0x2E,
+ 0x3D, 0x2B, 0x1D, 0x36, 0xA7, 0x4E, 0xF7, 0xF2, 0xF4, 0x2D, 0x0A, 0x1E,
+ 0x53, 0x3C, 0xFC, 0xA6, 0xB6, 0x12, 0x13, 0xF7, 0x08, 0xA7, 0x23, 0x52,
+ 0x60, 0x79, 0xC2, 0x19, 0x0F, 0x26, 0x39, 0x19, 0x83, 0xC8, 0x7B, 0xA6,
+ 0x95, 0x45, 0xBC, 0xE3, 0x66, 0x1F, 0xC3, 0xEA, 0x6E, 0xFE, 0xAD, 0xEB,
+ 0xA5, 0x5A, 0x6C, 0xBE, 0xEF, 0xDD, 0x32, 0xC3, 0x28, 0xFF, 0x8C, 0x01,
+ 0xD1, 0x37, 0x7F, 0xB1, 0x3B, 0x95, 0x2F, 0xDB, 0x0F, 0xA5, 0xCE, 0xEE,
+ 0x02, 0x97, 0xAB, 0x68, 0x85, 0x21, 0x58, 0x65, 0x70, 0x61, 0x07, 0x29,
+ 0x28, 0xB6, 0x21, 0x15, 0x84, 0x2F, 0x6E, 0x5B, 0xAD, 0x7D, 0xEF, 0x2A,
+ 0x96, 0xBD, 0x61, 0xEB, 0x30, 0xA8, 0xCC, 0x13, 0x10, 0x15, 0x9F, 0x61,
+ 0x75, 0x47, 0xDD, 0xEC, 0x39, 0xA2, 0x70, 0x4C, 0x90, 0x5C, 0x73, 0xB5,
+ 0xCF, 0x63, 0x03, 0xAA, 0x1E, 0xFE, 0x34, 0x03, 0xA7, 0x2C, 0x62, 0x60,
+ 0xBC, 0x86, 0xCC, 0xEE, 0x14, 0xDE, 0xAA, 0xCB, 0x0B, 0x9E, 0x9E, 0xD5,
+ 0xCA, 0xF0, 0xBD, 0x19, 0xAF, 0x1E, 0x8B, 0x64, 0x6E, 0x84, 0xF3, 0xB2,
+ 0xAB, 0x5C, 0xAB, 0x9C, 0xB3, 0xB4, 0x2A, 0x3C, 0x32, 0x5A, 0x68, 0x40,
+ 0x50, 0xBB, 0x5A, 0x65, 0xB9, 0x69, 0x23, 0xA0, 0x99, 0xA0, 0x5F, 0x87,
+ 0x19, 0x0B, 0x54, 0x9B, 0xF7, 0xB8, 0x21, 0xC0, 0xD5, 0xE9, 0x9E, 0x31,
+ 0x77, 0x2D, 0xE3, 0x97, 0x9A, 0x88, 0x37, 0xF8, 0xA8, 0x7D, 0x3D, 0x62,
+ 0x7E, 0x99, 0xF7, 0x95, 0xD6, 0x1F, 0xE6, 0xC7, 0x29, 0x88, 0x35, 0x0E,
+ 0x81, 0x12, 0x68, 0x16, 0x5F, 0x93, 0xED, 0x11, 0x63, 0x72, 0x22, 0x1B,
+ 0xA5, 0x84, 0xF5, 0x57, 0x99, 0xBA, 0x58, 0x78, 0xA1, 0xDF, 0xDE, 0x96,
+ 0x54, 0x30, 0x2E, 0x53, 0xEB, 0x0A, 0xB3, 0xCD, 0x96, 0x46, 0xC2, 0x1A,
+ 0xFF, 0xC3, 0x83, 0x9B, 0xEA, 0xFF, 0xC6, 0x34, 0xEF, 0xF2, 0xEB, 0x58,
+ 0x28, 0x31, 0xBC, 0x6D, 0xE4, 0x48, 0xD9, 0x8F, 0xE3, 0xB7, 0x64, 0xE8,
+ 0xD9, 0x14, 0x4A, 0x5D, 0x73, 0x3C, 0x7C, 0xEE, 0x61, 0xED, 0x28, 0xFE,
+ 0xEA, 0xAB, 0xAA, 0xA3, 0xB6, 0xE2, 0xEE, 0x45, 0xE0, 0x13, 0x3E, 0x20,
+ 0x14, 0x5D, 0x10, 0x42, 0xB5, 0xBB, 0x6A, 0xEF, 0x42, 0xF4, 0x42, 0xC7,
+ 0xD0, 0x4F, 0xCB, 0xFA, 0x15, 0x4F, 0x6C, 0xDB, 0xC7, 0x4D, 0x85, 0x86,
+ 0x9E, 0x79, 0x1E, 0xD8, 0x05, 0x21, 0xCD, 0x41, 0x1D, 0x3B, 0x4F, 0x65,
+ 0x46, 0x26, 0x8D, 0x5B, 0xF2, 0xA1, 0x62, 0xCF, 0x50, 0x62, 0x81, 0x3D,
+ 0x6A, 0x47, 0x4B, 0xE4, 0x92, 0x74, 0xCB, 0x69, 0xC3, 0x24, 0x15, 0x7F,
+ 0xA3, 0xB6, 0xC7, 0xC1, 0xA0, 0x83, 0x88, 0xFC, 0x9D, 0x48, 0x19, 0xAD,
+ 0x00, 0xBF, 0x5B, 0x09, 0x85, 0xB2, 0x92, 0x56, 0x0B, 0x8A, 0x84, 0x47,
+ 0xEA, 0xF5, 0x55, 0x0C, 0x2A, 0x8D, 0x42, 0x58, 0x00, 0x0D, 0x82, 0x23,
+ 0x74, 0xB1, 0x62, 0x14, 0x41, 0x7E, 0x93, 0x8D, 0x92, 0xF0, 0x72, 0x33,
+ 0x61, 0x70, 0x3F, 0x23, 0x3E, 0xF4, 0xAD, 0x1D, 0x60, 0x74, 0xEE, 0xCB,
+ 0x59, 0x37, 0xDE, 0x7C, 0xDB, 0x3B, 0x22, 0x6C, 0xF1, 0xEC, 0x5F, 0xD6,
+ 0x9E, 0x50, 0xF8, 0x19, 0x84, 0x80, 0x07, 0xA6, 0x6E, 0x32, 0x77, 0xCE,
+ 0xA7, 0xF2, 0x85, 0x40, 0xC2, 0x06, 0x0C, 0xC5, 0xAA, 0xA7, 0x69, 0xA9,
+ 0x35, 0x97, 0xD9, 0x61, 0x55, 0xD8, 0xEF, 0xE8, 0x84, 0x34, 0x45, 0xC3,
+ 0x2E, 0x7A, 0x44, 0x9E, 0xDC, 0xCA, 0x0B, 0x80, 0xFC, 0xAB, 0x04, 0x5A,
+ 0xCD, 0x88, 0x55, 0x10, 0xD3, 0xDB, 0x73, 0xDB, 0xC9, 0x9E, 0x1E, 0x0E,
+ 0x05, 0x67, 0xD5, 0xFD, 0xD8, 0x38, 0x3E, 0x71, 0x65, 0x34, 0xC4, 0xC5,
+ 0x40, 0x43, 0x67, 0xE3, 0x79, 0xDA, 0x5F, 0x67, 0x4A, 0x3D, 0xB0, 0x8F,
+ 0xE7, 0x21, 0x3E, 0x15, 0x20, 0xFF, 0x6D, 0xF1, 0x9E, 0xF8, 0x28, 0x3D,
+ 0xF7, 0x40, 0x81, 0x94, 0x68, 0x5A, 0x3D, 0xE9, 0xF7, 0xAD, 0x83, 0xDB,
+ 0x2B, 0x9F, 0xE3, 0xE6, 0xF7, 0xD4, 0x02, 0x76, 0xF7, 0x20, 0x15, 0x41,
+ 0x34, 0x29, 0x69, 0x94, 0x1C, 0x26, 0x4C, 0xF6, 0x6A, 0xF4, 0x20, 0x33,
+ 0x71, 0x24, 0x08, 0xD4, 0x68, 0x00, 0xA1, 0xD4, 0x2E, 0x6B, 0xF4, 0xBC,
+ 0x46, 0x45, 0x24, 0x97, 0x2E, 0xF6, 0x39, 0x1E, 0xAF, 0x61, 0x00, 0x50,
+ 0xB7, 0xD4, 0xB7, 0x43,
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.cc
new file mode 100644
index 00000000000..4e5f3dc1c7b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.cc
@@ -0,0 +1,457 @@
+// 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.
+
+#include "absl/random/internal/randen_slow.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+
+#include "absl/base/attributes.h"
+#include "absl/random/internal/platform.h"
+#include "absl/random/internal/randen_traits.h"
+
+#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE \
+ __attribute__((always_inline))
+#elif defined(_MSC_VER)
+// We can achieve something similar to attribute((always_inline)) with MSVC by
+// using the __forceinline keyword, however this is not perfect. MSVC is
+// much less aggressive about inlining, and even with the __forceinline keyword.
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE __forceinline
+#else
+#define ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE
+#endif
+
+namespace {
+
+// AES portions based on rijndael-alg-fst.c,
+// https://fastcrypto.org/front/misc/rijndael-alg-fst.c
+//
+// Implementation of
+// http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+constexpr uint32_t te0[256] = {
+ 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd,
+ 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d,
+ 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d,
+ 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b,
+ 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7,
+ 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a,
+ 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4,
+ 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f,
+ 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1,
+ 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d,
+ 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e,
+ 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb,
+ 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e,
+ 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c,
+ 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46,
+ 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a,
+ 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7,
+ 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81,
+ 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe,
+ 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
+ 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a,
+ 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f,
+ 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2,
+ 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395,
+ 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e,
+ 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c,
+ 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256,
+ 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4,
+ 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4,
+ 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7,
+ 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa,
+ 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818,
+ 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1,
+ 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21,
+ 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42,
+ 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12,
+ 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158,
+ 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133,
+ 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22,
+ 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a,
+ 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631,
+ 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
+ 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a,
+};
+
+constexpr uint32_t te1[256] = {
+ 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b,
+ 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b,
+ 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282,
+ 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0,
+ 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4,
+ 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626,
+ 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5,
+ 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515,
+ 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696,
+ 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2,
+ 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383,
+ 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0,
+ 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3,
+ 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded,
+ 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb,
+ 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf,
+ 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d,
+ 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f,
+ 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3,
+ 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
+ 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff,
+ 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec,
+ 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7,
+ 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373,
+ 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a,
+ 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414,
+ 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232,
+ 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c,
+ 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595,
+ 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d,
+ 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656,
+ 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808,
+ 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6,
+ 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f,
+ 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e,
+ 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e,
+ 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1,
+ 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111,
+ 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e,
+ 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf,
+ 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6,
+ 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f,
+ 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616,
+};
+
+constexpr uint32_t te2[256] = {
+ 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b,
+ 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b,
+ 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82,
+ 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0,
+ 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4,
+ 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26,
+ 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5,
+ 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15,
+ 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796,
+ 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2,
+ 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83,
+ 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0,
+ 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3,
+ 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed,
+ 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb,
+ 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf,
+ 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d,
+ 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f,
+ 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3,
+ 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
+ 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff,
+ 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec,
+ 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7,
+ 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673,
+ 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a,
+ 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814,
+ 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432,
+ 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c,
+ 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195,
+ 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d,
+ 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56,
+ 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008,
+ 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6,
+ 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f,
+ 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e,
+ 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e,
+ 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1,
+ 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211,
+ 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e,
+ 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df,
+ 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6,
+ 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f,
+ 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16,
+};
+
+constexpr uint32_t te3[256] = {
+ 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6,
+ 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56,
+ 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f,
+ 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb,
+ 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753,
+ 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c,
+ 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451,
+ 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a,
+ 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137,
+ 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf,
+ 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d,
+ 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b,
+ 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd,
+ 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1,
+ 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d,
+ 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85,
+ 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a,
+ 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe,
+ 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d,
+ 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
+ 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5,
+ 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3,
+ 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255,
+ 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6,
+ 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54,
+ 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28,
+ 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664,
+ 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8,
+ 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431,
+ 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da,
+ 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac,
+ 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810,
+ 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157,
+ 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e,
+ 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c,
+ 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c,
+ 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899,
+ 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322,
+ 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c,
+ 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5,
+ 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7,
+ 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e,
+ 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c,
+};
+
+// Software implementation of the Vector128 class, using uint32_t
+// as an underlying vector register.
+struct alignas(16) Vector128 {
+ uint32_t s[4];
+};
+
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
+Vector128Load(const void* from) {
+ Vector128 result;
+ const uint8_t* src = reinterpret_cast<const uint8_t*>(from);
+ result.s[0] = static_cast<uint32_t>(src[0]) << 24 |
+ static_cast<uint32_t>(src[1]) << 16 |
+ static_cast<uint32_t>(src[2]) << 8 |
+ static_cast<uint32_t>(src[3]);
+ result.s[1] = static_cast<uint32_t>(src[4]) << 24 |
+ static_cast<uint32_t>(src[5]) << 16 |
+ static_cast<uint32_t>(src[6]) << 8 |
+ static_cast<uint32_t>(src[7]);
+ result.s[2] = static_cast<uint32_t>(src[8]) << 24 |
+ static_cast<uint32_t>(src[9]) << 16 |
+ static_cast<uint32_t>(src[10]) << 8 |
+ static_cast<uint32_t>(src[11]);
+ result.s[3] = static_cast<uint32_t>(src[12]) << 24 |
+ static_cast<uint32_t>(src[13]) << 16 |
+ static_cast<uint32_t>(src[14]) << 8 |
+ static_cast<uint32_t>(src[15]);
+ return result;
+}
+
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Vector128Store(
+ const Vector128& v, void* to) {
+ uint8_t* dst = reinterpret_cast<uint8_t*>(to);
+ dst[0] = static_cast<uint8_t>(v.s[0] >> 24);
+ dst[1] = static_cast<uint8_t>(v.s[0] >> 16);
+ dst[2] = static_cast<uint8_t>(v.s[0] >> 8);
+ dst[3] = static_cast<uint8_t>(v.s[0]);
+ dst[4] = static_cast<uint8_t>(v.s[1] >> 24);
+ dst[5] = static_cast<uint8_t>(v.s[1] >> 16);
+ dst[6] = static_cast<uint8_t>(v.s[1] >> 8);
+ dst[7] = static_cast<uint8_t>(v.s[1]);
+ dst[8] = static_cast<uint8_t>(v.s[2] >> 24);
+ dst[9] = static_cast<uint8_t>(v.s[2] >> 16);
+ dst[10] = static_cast<uint8_t>(v.s[2] >> 8);
+ dst[11] = static_cast<uint8_t>(v.s[2]);
+ dst[12] = static_cast<uint8_t>(v.s[3] >> 24);
+ dst[13] = static_cast<uint8_t>(v.s[3] >> 16);
+ dst[14] = static_cast<uint8_t>(v.s[3] >> 8);
+ dst[15] = static_cast<uint8_t>(v.s[3]);
+}
+
+// One round of AES. "round_key" is a public constant for breaking the
+// symmetry of AES (ensures previously equal columns differ afterwards).
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
+AesRound(const Vector128& state, const Vector128& round_key) {
+ Vector128 result;
+ result.s[0] = round_key.s[0] ^ //
+ te0[uint8_t(state.s[0] >> 24)] ^ //
+ te1[uint8_t(state.s[1] >> 16)] ^ //
+ te2[uint8_t(state.s[2] >> 8)] ^ //
+ te3[uint8_t(state.s[3])];
+ result.s[1] = round_key.s[1] ^ //
+ te0[uint8_t(state.s[1] >> 24)] ^ //
+ te1[uint8_t(state.s[2] >> 16)] ^ //
+ te2[uint8_t(state.s[3] >> 8)] ^ //
+ te3[uint8_t(state.s[0])];
+ result.s[2] = round_key.s[2] ^ //
+ te0[uint8_t(state.s[2] >> 24)] ^ //
+ te1[uint8_t(state.s[3] >> 16)] ^ //
+ te2[uint8_t(state.s[0] >> 8)] ^ //
+ te3[uint8_t(state.s[1])];
+ result.s[3] = round_key.s[3] ^ //
+ te0[uint8_t(state.s[3] >> 24)] ^ //
+ te1[uint8_t(state.s[0] >> 16)] ^ //
+ te2[uint8_t(state.s[1] >> 8)] ^ //
+ te3[uint8_t(state.s[2])];
+ return result;
+}
+
+using ::absl::random_internal::RandenTraits;
+
+// Randen operates on 128-bit vectors.
+struct alignas(16) u64x2 {
+ uint64_t data[2];
+};
+
+// The improved Feistel block shuffle function for 16 blocks.
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
+ u64x2* state) {
+ static_assert(RandenTraits::kFeistelBlocks == 16,
+ "Feistel block shuffle only works for 16 blocks.");
+
+ constexpr size_t shuffle[RandenTraits::kFeistelBlocks] = {
+ 7, 2, 13, 4, 11, 8, 3, 6, 15, 0, 9, 10, 1, 14, 5, 12};
+
+ // The fully unrolled loop without the memcpy improves the speed by about
+ // 30% over the equivalent:
+#if 0
+ u64x2 source[RandenTraits::kFeistelBlocks];
+ std::memcpy(source, state, sizeof(source));
+ for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {
+ const u64x2 v0 = source[shuffle[i]];
+ state[i] = v0;
+ }
+ return;
+#endif
+
+ const u64x2 v0 = state[shuffle[0]];
+ const u64x2 v1 = state[shuffle[1]];
+ const u64x2 v2 = state[shuffle[2]];
+ const u64x2 v3 = state[shuffle[3]];
+ const u64x2 v4 = state[shuffle[4]];
+ const u64x2 v5 = state[shuffle[5]];
+ const u64x2 v6 = state[shuffle[6]];
+ const u64x2 v7 = state[shuffle[7]];
+ const u64x2 w0 = state[shuffle[8]];
+ const u64x2 w1 = state[shuffle[9]];
+ const u64x2 w2 = state[shuffle[10]];
+ const u64x2 w3 = state[shuffle[11]];
+ const u64x2 w4 = state[shuffle[12]];
+ const u64x2 w5 = state[shuffle[13]];
+ const u64x2 w6 = state[shuffle[14]];
+ const u64x2 w7 = state[shuffle[15]];
+ state[0] = v0;
+ state[1] = v1;
+ state[2] = v2;
+ state[3] = v3;
+ state[4] = v4;
+ state[5] = v5;
+ state[6] = v6;
+ state[7] = v7;
+ state[8] = w0;
+ state[9] = w1;
+ state[10] = w2;
+ state[11] = w3;
+ state[12] = w4;
+ state[13] = w5;
+ state[14] = w6;
+ state[15] = w7;
+}
+
+// Feistel round function using two AES subrounds. Very similar to F()
+// from Simpira v2, but with independent subround keys. Uses 17 AES rounds
+// per 16 bytes (vs. 10 for AES-CTR). Computing eight round functions in
+// parallel hides the 7-cycle AESNI latency on HSW. Note that the Feistel
+// XORs are 'free' (included in the second AES instruction).
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const u64x2* FeistelRound(
+ u64x2* ABSL_RANDOM_INTERNAL_RESTRICT state,
+ const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ for (size_t branch = 0; branch < RandenTraits::kFeistelBlocks; branch += 4) {
+ const Vector128 s0 = Vector128Load(state + branch);
+ const Vector128 s1 = Vector128Load(state + branch + 1);
+ const Vector128 f0 = AesRound(s0, Vector128Load(keys));
+ keys++;
+ const Vector128 o1 = AesRound(f0, s1);
+ Vector128Store(o1, state + branch + 1);
+
+ // Manually unroll this loop once. about 10% better than not unrolled.
+ const Vector128 s2 = Vector128Load(state + branch + 2);
+ const Vector128 s3 = Vector128Load(state + branch + 3);
+ const Vector128 f2 = AesRound(s2, Vector128Load(keys));
+ keys++;
+ const Vector128 o3 = AesRound(f2, s3);
+ Vector128Store(o3, state + branch + 3);
+ }
+ return keys;
+}
+
+// Cryptographic permutation based via type-2 Generalized Feistel Network.
+// Indistinguishable from ideal by chosen-ciphertext adversaries using less than
+// 2^64 queries if the round function is a PRF. This is similar to the b=8 case
+// of Simpira v2, but more efficient than its generic construction for b=16.
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void Permute(
+ u64x2* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
+ keys = FeistelRound(state, keys);
+ BlockShuffle(state);
+ }
+}
+
+} // namespace
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+const void* RandenSlow::GetKeys() {
+ // Round keys for one AES per Feistel round and branch.
+ // The canonical implementation uses first digits of Pi.
+ return kRandenRoundKeys;
+}
+
+void RandenSlow::Absorb(const void* seed_void, void* state_void) {
+ auto* state =
+ reinterpret_cast<uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(state_void);
+ const auto* seed =
+ reinterpret_cast<const uint64_t * ABSL_RANDOM_INTERNAL_RESTRICT>(
+ seed_void);
+
+ constexpr size_t kCapacityBlocks =
+ RandenTraits::kCapacityBytes / sizeof(uint64_t);
+ static_assert(
+ kCapacityBlocks * sizeof(uint64_t) == RandenTraits::kCapacityBytes,
+ "Not i*V");
+
+ for (size_t i = kCapacityBlocks;
+ i < RandenTraits::kStateBytes / sizeof(uint64_t); ++i) {
+ state[i] ^= seed[i - kCapacityBlocks];
+ }
+}
+
+void RandenSlow::Generate(const void* keys_void, void* state_void) {
+ static_assert(RandenTraits::kCapacityBytes == sizeof(u64x2),
+ "Capacity mismatch");
+
+ auto* state = reinterpret_cast<u64x2*>(state_void);
+ const auto* keys = reinterpret_cast<const u64x2*>(keys_void);
+
+ const u64x2 prev_inner = state[0];
+
+ Permute(state, keys);
+
+ // Ensure backtracking resistance.
+ state[0].data[0] ^= prev_inner.data[0];
+ state[0].data[1] ^= prev_inner.data[1];
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.h
new file mode 100644
index 00000000000..532c3a8991e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow.h
@@ -0,0 +1,40 @@
+// 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_SLOW_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
+
+#include <cstddef>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// RANDen = RANDom generator or beetroots in Swiss High German.
+// RandenSlow implements the basic state manipulation methods for
+// architectures lacking AES hardware acceleration intrinsics.
+class RandenSlow {
+ public:
+ static void Generate(const void* keys, void* state_void);
+ static void Absorb(const void* seed_void, void* state_void);
+ static const void* GetKeys();
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_SLOW_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow_test.cc
new file mode 100644
index 00000000000..4861ffa4f18
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_slow_test.cc
@@ -0,0 +1,64 @@
+// 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.
+
+#include "absl/random/internal/randen_slow.h"
+
+#include <cstring>
+
+#include "gtest/gtest.h"
+#include "absl/base/internal/endian.h"
+#include "absl/random/internal/randen_traits.h"
+
+namespace {
+
+using absl::random_internal::RandenSlow;
+using absl::random_internal::RandenTraits;
+
+// Local state parameters.
+constexpr size_t kSeedBytes =
+ RandenTraits::kStateBytes - RandenTraits::kCapacityBytes;
+constexpr size_t kStateSizeT = RandenTraits::kStateBytes / sizeof(uint64_t);
+constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t);
+
+struct alignas(16) randen {
+ uint64_t state[kStateSizeT];
+ uint32_t seed[kSeedSizeT];
+};
+
+TEST(RandenSlowTest, Default) {
+ constexpr uint64_t kGolden[] = {
+ 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977,
+ 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912,
+ 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6,
+ 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a,
+ 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37,
+ 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556,
+ 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42,
+ 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc,
+ 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f,
+ 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3,
+ 0x026ff374c101da7e, 0x811ef0821c3de851,
+ };
+
+ alignas(16) randen d;
+ std::memset(d.state, 0, sizeof(d.state));
+ RandenSlow::Generate(RandenSlow::GetKeys(), d.state);
+
+ uint64_t* id = d.state;
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(absl::little_endian::FromHost64(elem), *id++);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_test.cc
new file mode 100644
index 00000000000..c186fe0d686
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_test.cc
@@ -0,0 +1,70 @@
+// 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.
+
+#include "absl/random/internal/randen.h"
+
+#include <cstring>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+
+namespace {
+
+using absl::random_internal::Randen;
+
+// Local state parameters.
+constexpr size_t kStateSizeT = Randen::kStateBytes / sizeof(uint64_t);
+
+TEST(RandenTest, CopyAndMove) {
+ static_assert(std::is_copy_constructible<Randen>::value,
+ "Randen must be copy constructible");
+
+ static_assert(absl::is_copy_assignable<Randen>::value,
+ "Randen must be copy assignable");
+
+ static_assert(std::is_move_constructible<Randen>::value,
+ "Randen must be move constructible");
+
+ static_assert(absl::is_move_assignable<Randen>::value,
+ "Randen must be move assignable");
+}
+
+TEST(RandenTest, Default) {
+ constexpr uint64_t kGolden[] = {
+ 0x6c6534090ee6d3ee, 0x044e2b9b9d5333c6, 0xc3c14f134e433977,
+ 0xdda9f47cd90410ee, 0x887bf3087fd8ca10, 0xf0b780f545c72912,
+ 0x15dbb1d37696599f, 0x30ec63baff3c6d59, 0xb29f73606f7f20a6,
+ 0x02808a316f49a54c, 0x3b8feaf9d5c8e50e, 0x9cbf605e3fd9de8a,
+ 0xc970ae1a78183bbb, 0xd8b2ffd356301ed5, 0xf4b327fe0fc73c37,
+ 0xcdfd8d76eb8f9a19, 0xc3a506eb91420c9d, 0xd5af05dd3eff9556,
+ 0x48db1bb78f83c4a1, 0x7023920e0d6bfe8c, 0x58d3575834956d42,
+ 0xed1ef4c26b87b840, 0x8eef32a23e0b2df3, 0x497cabf3431154fc,
+ 0x4e24370570029a8b, 0xd88b5749f090e5ea, 0xc651a582a970692f,
+ 0x78fcec2cbb6342f5, 0x463cb745612f55db, 0x352ee4ad1816afe3,
+ 0x026ff374c101da7e, 0x811ef0821c3de851,
+ };
+
+ alignas(16) uint64_t state[kStateSizeT];
+ std::memset(state, 0, sizeof(state));
+
+ Randen r;
+ r.Generate(state);
+
+ auto id = std::begin(state);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, *id++);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_traits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_traits.h
new file mode 100644
index 00000000000..120022c9fb8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/randen_traits.h
@@ -0,0 +1,88 @@
+// 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_TRAITS_H_
+#define ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_
+
+// HERMETIC NOTE: The randen_hwaes target must not introduce duplicate
+// symbols from arbitrary system and other headers, since it may be built
+// with different flags from other targets, using different levels of
+// optimization, potentially introducing ODR violations.
+
+#include <cstddef>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// 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.
+//
+// High-level summary:
+// 1) Reverie (see "A Robust and Sponge-Like PRNG with Improved Efficiency") is
+// a sponge-like random generator that requires a cryptographic permutation.
+// It improves upon "Provably Robust Sponge-Based PRNGs and KDFs" by
+// achieving backtracking resistance with only one Permute() per buffer.
+//
+// 2) "Simpira v2: A Family of Efficient Permutations Using the AES Round
+// Function" constructs up to 1024-bit permutations using an improved
+// Generalized Feistel network with 2-round AES-128 functions. This Feistel
+// block shuffle achieves diffusion faster and is less vulnerable to
+// sliced-biclique attacks than the Type-2 cyclic shuffle.
+//
+// 3) "Improving the Generalized Feistel" and "New criterion for diffusion
+// property" extends the same kind of improved Feistel block shuffle to 16
+// branches, which enables a 2048-bit permutation.
+//
+// Combine these three ideas and also change Simpira's subround keys from
+// structured/low-entropy counters to digits of Pi (or other random source).
+
+// RandenTraits contains the basic algorithm traits, such as the size of the
+// state, seed, sponge, etc.
+struct RandenTraits {
+ // Size of the entire sponge / state for the randen PRNG.
+ static constexpr size_t kStateBytes = 256; // 2048-bit
+
+ // Size of the 'inner' (inaccessible) part of the sponge. Larger values would
+ // require more frequent calls to RandenGenerate.
+ static constexpr size_t kCapacityBytes = 16; // 128-bit
+
+ // Size of the default seed consumed by the sponge.
+ static constexpr size_t kSeedBytes = kStateBytes - kCapacityBytes;
+
+ // Assuming 128-bit blocks, the number of blocks in the state.
+ // Largest size for which security proofs are known.
+ static constexpr size_t kFeistelBlocks = 16;
+
+ // Ensures SPRP security and two full subblock diffusions.
+ // Must be > 4 * log2(kFeistelBlocks).
+ static constexpr size_t kFeistelRounds = 16 + 1;
+
+ // Size of the key. A 128-bit key block is used for every-other
+ // feistel block (Type-2 generalized Feistel network) in each round.
+ static constexpr size_t kKeyBytes = 16 * kFeistelRounds * kFeistelBlocks / 2;
+};
+
+// Randen key arrays. In randen_round_keys.cc
+extern const unsigned char kRandenRoundKeys[RandenTraits::kKeyBytes];
+extern const unsigned char kRandenRoundKeysBE[RandenTraits::kKeyBytes];
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_TRAITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq.h
new file mode 100644
index 00000000000..5953a090f80
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq.h
@@ -0,0 +1,167 @@
+// 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_SALTED_SEED_SEQ_H_
+#define ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_
+
+#include <cstdint>
+#include <cstdlib>
+#include <initializer_list>
+#include <iterator>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/seed_material.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// This class conforms to the C++ Standard "Seed Sequence" concept
+// [rand.req.seedseq].
+//
+// A `SaltedSeedSeq` is meant to wrap an existing seed sequence and modify
+// generated sequence by mixing with extra entropy. This entropy may be
+// build-dependent or process-dependent. The implementation may change to be
+// have either or both kinds of entropy. If salt is not available sequence is
+// not modified.
+template <typename SSeq>
+class SaltedSeedSeq {
+ public:
+ using inner_sequence_type = SSeq;
+ using result_type = typename SSeq::result_type;
+
+ SaltedSeedSeq() : seq_(absl::make_unique<SSeq>()) {}
+
+ template <typename Iterator>
+ SaltedSeedSeq(Iterator begin, Iterator end)
+ : seq_(absl::make_unique<SSeq>(begin, end)) {}
+
+ template <typename T>
+ SaltedSeedSeq(std::initializer_list<T> il)
+ : SaltedSeedSeq(il.begin(), il.end()) {}
+
+ SaltedSeedSeq(const SaltedSeedSeq&) = delete;
+ SaltedSeedSeq& operator=(const SaltedSeedSeq&) = delete;
+
+ SaltedSeedSeq(SaltedSeedSeq&&) = default;
+ SaltedSeedSeq& operator=(SaltedSeedSeq&&) = default;
+
+ template <typename RandomAccessIterator>
+ void generate(RandomAccessIterator begin, RandomAccessIterator end) {
+ // The common case is that generate is called with ContiguousIterators
+ // to uint arrays. Such contiguous memory regions may be optimized,
+ // which we detect here.
+ using tag = absl::conditional_t<
+ (std::is_pointer<RandomAccessIterator>::value &&
+ std::is_same<absl::decay_t<decltype(*begin)>, uint32_t>::value),
+ ContiguousAndUint32Tag, DefaultTag>;
+ if (begin != end) {
+ generate_impl(begin, end, tag{});
+ }
+ }
+
+ template <typename OutIterator>
+ void param(OutIterator out) const {
+ seq_->param(out);
+ }
+
+ size_t size() const { return seq_->size(); }
+
+ private:
+ struct ContiguousAndUint32Tag {};
+ struct DefaultTag {};
+
+ // Generate which requires the iterators are contiguous pointers to uint32_t.
+ void generate_impl(uint32_t* begin, uint32_t* end, ContiguousAndUint32Tag) {
+ generate_contiguous(absl::MakeSpan(begin, end));
+ }
+
+ // The uncommon case for generate is that it is called with iterators over
+ // some other buffer type which is assignable from a 32-bit value. In this
+ // case we allocate a temporary 32-bit buffer and then copy-assign back
+ // to the initial inputs.
+ template <typename RandomAccessIterator>
+ void generate_impl(RandomAccessIterator begin, RandomAccessIterator end,
+ DefaultTag) {
+ return generate_and_copy(std::distance(begin, end), begin);
+ }
+
+ // Fills the initial seed buffer the underlying SSeq::generate() call,
+ // mixing in the salt material.
+ void generate_contiguous(absl::Span<uint32_t> buffer) {
+ seq_->generate(buffer.begin(), buffer.end());
+ const uint32_t salt = absl::random_internal::GetSaltMaterial().value_or(0);
+ MixIntoSeedMaterial(absl::MakeConstSpan(&salt, 1), buffer);
+ }
+
+ // Allocates a seed buffer of `n` elements, generates the seed, then
+ // copies the result into the `out` iterator.
+ template <typename Iterator>
+ void generate_and_copy(size_t n, Iterator out) {
+ // Allocate a temporary buffer, generate, and then copy.
+ absl::InlinedVector<uint32_t, 8> data(n, 0);
+ generate_contiguous(absl::MakeSpan(data.data(), data.size()));
+ std::copy(data.begin(), data.end(), out);
+ }
+
+ // Because [rand.req.seedseq] is not required to be copy-constructible,
+ // copy-assignable nor movable, we wrap it with unique pointer to be able
+ // to move SaltedSeedSeq.
+ std::unique_ptr<SSeq> seq_;
+};
+
+// is_salted_seed_seq indicates whether the type is a SaltedSeedSeq.
+template <typename T, typename = void>
+struct is_salted_seed_seq : public std::false_type {};
+
+template <typename T>
+struct is_salted_seed_seq<
+ T, typename std::enable_if<std::is_same<
+ T, SaltedSeedSeq<typename T::inner_sequence_type>>::value>::type>
+ : public std::true_type {};
+
+// MakeSaltedSeedSeq returns a salted variant of the seed sequence.
+// When provided with an existing SaltedSeedSeq, returns the input parameter,
+// otherwise constructs a new SaltedSeedSeq which embodies the original
+// non-salted seed parameters.
+template <
+ typename SSeq, //
+ typename EnableIf = absl::enable_if_t<is_salted_seed_seq<SSeq>::value>>
+SSeq MakeSaltedSeedSeq(SSeq&& seq) {
+ return SSeq(std::forward<SSeq>(seq));
+}
+
+template <
+ typename SSeq, //
+ typename EnableIf = absl::enable_if_t<!is_salted_seed_seq<SSeq>::value>>
+SaltedSeedSeq<typename std::decay<SSeq>::type> MakeSaltedSeedSeq(SSeq&& seq) {
+ using sseq_type = typename std::decay<SSeq>::type;
+ using result_type = typename sseq_type::result_type;
+
+ absl::InlinedVector<result_type, 8> data;
+ seq.param(std::back_inserter(data));
+ return SaltedSeedSeq<sseq_type>(data.begin(), data.end());
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_SALTED_SEED_SEQ_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq_test.cc
new file mode 100644
index 00000000000..0bf19a63ef8
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/salted_seed_seq_test.cc
@@ -0,0 +1,168 @@
+// 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.
+
+#include "absl/random/internal/salted_seed_seq.h"
+
+#include <iterator>
+#include <random>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+using absl::random_internal::GetSaltMaterial;
+using absl::random_internal::MakeSaltedSeedSeq;
+using absl::random_internal::SaltedSeedSeq;
+using testing::Eq;
+using testing::Pointwise;
+
+namespace {
+
+template <typename Sseq>
+void ConformsToInterface() {
+ // Check that the SeedSequence can be default-constructed.
+ { Sseq default_constructed_seq; }
+ // Check that the SeedSequence can be constructed with two iterators.
+ {
+ uint32_t init_array[] = {1, 3, 5, 7, 9};
+ Sseq iterator_constructed_seq(std::begin(init_array), std::end(init_array));
+ }
+ // Check that the SeedSequence can be std::initializer_list-constructed.
+ { Sseq list_constructed_seq = {1, 3, 5, 7, 9, 11, 13}; }
+ // Check that param() and size() return state provided to constructor.
+ {
+ uint32_t init_array[] = {1, 2, 3, 4, 5};
+ Sseq seq(std::begin(init_array), std::end(init_array));
+ EXPECT_EQ(seq.size(), ABSL_ARRAYSIZE(init_array));
+
+ std::vector<uint32_t> state_vector;
+ seq.param(std::back_inserter(state_vector));
+
+ EXPECT_EQ(state_vector.size(), ABSL_ARRAYSIZE(init_array));
+ for (int i = 0; i < state_vector.size(); i++) {
+ EXPECT_EQ(state_vector[i], i + 1);
+ }
+ }
+ // Check for presence of generate() method.
+ {
+ Sseq seq;
+ uint32_t seeds[5];
+
+ seq.generate(std::begin(seeds), std::end(seeds));
+ }
+}
+
+TEST(SaltedSeedSeq, CheckInterfaces) {
+ // Control case
+ ConformsToInterface<std::seed_seq>();
+
+ // Abseil classes
+ ConformsToInterface<SaltedSeedSeq<std::seed_seq>>();
+}
+
+TEST(SaltedSeedSeq, CheckConstructingFromOtherSequence) {
+ std::vector<uint32_t> seed_values(10, 1);
+ std::seed_seq seq(seed_values.begin(), seed_values.end());
+ auto salted_seq = MakeSaltedSeedSeq(std::move(seq));
+
+ EXPECT_EQ(seq.size(), salted_seq.size());
+
+ std::vector<uint32_t> param_result;
+ seq.param(std::back_inserter(param_result));
+
+ EXPECT_EQ(seed_values, param_result);
+}
+
+TEST(SaltedSeedSeq, SaltedSaltedSeedSeqIsNotDoubleSalted) {
+ uint32_t init[] = {1, 3, 5, 7, 9};
+
+ std::seed_seq seq(std::begin(init), std::end(init));
+
+ // The first salting.
+ SaltedSeedSeq<std::seed_seq> salted_seq = MakeSaltedSeedSeq(std::move(seq));
+ uint32_t a[16];
+ salted_seq.generate(std::begin(a), std::end(a));
+
+ // The second salting.
+ SaltedSeedSeq<std::seed_seq> salted_salted_seq =
+ MakeSaltedSeedSeq(std::move(salted_seq));
+ uint32_t b[16];
+ salted_salted_seq.generate(std::begin(b), std::end(b));
+
+ // ... both should be equal.
+ EXPECT_THAT(b, Pointwise(Eq(), a)) << "a[0] " << a[0];
+}
+
+TEST(SaltedSeedSeq, SeedMaterialIsSalted) {
+ const size_t kNumBlocks = 16;
+
+ uint32_t seed_material[kNumBlocks];
+ std::random_device urandom{"/dev/urandom"};
+ for (uint32_t& seed : seed_material) {
+ seed = urandom();
+ }
+
+ std::seed_seq seq(std::begin(seed_material), std::end(seed_material));
+ SaltedSeedSeq<std::seed_seq> salted_seq(std::begin(seed_material),
+ std::end(seed_material));
+
+ bool salt_is_available = GetSaltMaterial().has_value();
+
+ // If salt is available generated sequence should be different.
+ if (salt_is_available) {
+ uint32_t outputs[kNumBlocks];
+ uint32_t salted_outputs[kNumBlocks];
+
+ seq.generate(std::begin(outputs), std::end(outputs));
+ salted_seq.generate(std::begin(salted_outputs), std::end(salted_outputs));
+
+ EXPECT_THAT(outputs, Pointwise(testing::Ne(), salted_outputs));
+ }
+}
+
+TEST(SaltedSeedSeq, GenerateAcceptsDifferentTypes) {
+ const size_t kNumBlocks = 4;
+
+ SaltedSeedSeq<std::seed_seq> seq({1, 2, 3});
+
+ uint32_t expected[kNumBlocks];
+ seq.generate(std::begin(expected), std::end(expected));
+
+ // 32-bit outputs
+ {
+ unsigned long seed_material[kNumBlocks]; // NOLINT(runtime/int)
+ seq.generate(std::begin(seed_material), std::end(seed_material));
+ EXPECT_THAT(seed_material, Pointwise(Eq(), expected));
+ }
+ {
+ unsigned int seed_material[kNumBlocks]; // NOLINT(runtime/int)
+ seq.generate(std::begin(seed_material), std::end(seed_material));
+ EXPECT_THAT(seed_material, Pointwise(Eq(), expected));
+ }
+
+ // 64-bit outputs.
+ {
+ uint64_t seed_material[kNumBlocks];
+ seq.generate(std::begin(seed_material), std::end(seed_material));
+ EXPECT_THAT(seed_material, Pointwise(Eq(), expected));
+ }
+ {
+ int64_t seed_material[kNumBlocks];
+ seq.generate(std::begin(seed_material), std::end(seed_material));
+ EXPECT_THAT(seed_material, Pointwise(Eq(), expected));
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.cc
new file mode 100644
index 00000000000..4d38a57419e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.cc
@@ -0,0 +1,219 @@
+// 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.
+
+#include "absl/random/internal/seed_material.h"
+
+#include <fcntl.h>
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#include <algorithm>
+#include <cerrno>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+
+#if defined(__native_client__)
+
+#include <nacl/nacl_random.h>
+#define ABSL_RANDOM_USE_NACL_SECURE_RANDOM 1
+
+#elif defined(_WIN32)
+
+#include <windows.h>
+#define ABSL_RANDOM_USE_BCRYPT 1
+#pragma comment(lib, "bcrypt.lib")
+
+#elif defined(__Fuchsia__)
+#include <zircon/syscalls.h>
+
+#endif
+
+#if defined(ABSL_RANDOM_USE_BCRYPT)
+#include <bcrypt.h>
+
+#ifndef BCRYPT_SUCCESS
+#define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+#endif
+// Also link bcrypt; this can be done via linker options or:
+// #pragma comment(lib, "bcrypt.lib")
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+namespace {
+
+// Read OS Entropy for random number seeds.
+// TODO(absl-team): Possibly place a cap on how much entropy may be read at a
+// time.
+
+#if defined(ABSL_RANDOM_USE_BCRYPT)
+
+// On Windows potentially use the BCRYPT CNG API to read available entropy.
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
+ BCRYPT_ALG_HANDLE hProvider;
+ NTSTATUS ret;
+ ret = BCryptOpenAlgorithmProvider(&hProvider, BCRYPT_RNG_ALGORITHM,
+ MS_PRIMITIVE_PROVIDER, 0);
+ if (!(BCRYPT_SUCCESS(ret))) {
+ ABSL_RAW_LOG(ERROR, "Failed to open crypto provider.");
+ return false;
+ }
+ ret = BCryptGenRandom(
+ hProvider, // provider
+ reinterpret_cast<UCHAR*>(values.data()), // buffer
+ static_cast<ULONG>(sizeof(uint32_t) * values.size()), // bytes
+ 0); // flags
+ BCryptCloseAlgorithmProvider(hProvider, 0);
+ return BCRYPT_SUCCESS(ret);
+}
+
+#elif defined(ABSL_RANDOM_USE_NACL_SECURE_RANDOM)
+
+// On NaCL use nacl_secure_random to acquire bytes.
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
+ auto buffer = reinterpret_cast<uint8_t*>(values.data());
+ size_t buffer_size = sizeof(uint32_t) * values.size();
+
+ uint8_t* output_ptr = buffer;
+ while (buffer_size > 0) {
+ size_t nread = 0;
+ const int error = nacl_secure_random(output_ptr, buffer_size, &nread);
+ if (error != 0 || nread > buffer_size) {
+ ABSL_RAW_LOG(ERROR, "Failed to read secure_random seed data: %d", error);
+ return false;
+ }
+ output_ptr += nread;
+ buffer_size -= nread;
+ }
+ return true;
+}
+
+#elif defined(__Fuchsia__)
+
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
+ auto buffer = reinterpret_cast<uint8_t*>(values.data());
+ size_t buffer_size = sizeof(uint32_t) * values.size();
+ zx_cprng_draw(buffer, buffer_size);
+ return true;
+}
+
+#else
+
+// On *nix, read entropy from /dev/urandom.
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
+ const char kEntropyFile[] = "/dev/urandom";
+
+ auto buffer = reinterpret_cast<uint8_t*>(values.data());
+ size_t buffer_size = sizeof(uint32_t) * values.size();
+
+ int dev_urandom = open(kEntropyFile, O_RDONLY);
+ bool success = (-1 != dev_urandom);
+ if (!success) {
+ return false;
+ }
+
+ while (success && buffer_size > 0) {
+ int bytes_read = read(dev_urandom, buffer, buffer_size);
+ int read_error = errno;
+ success = (bytes_read > 0);
+ if (success) {
+ buffer += bytes_read;
+ buffer_size -= bytes_read;
+ } else if (bytes_read == -1 && read_error == EINTR) {
+ success = true; // Need to try again.
+ }
+ }
+ close(dev_urandom);
+ return success;
+}
+
+#endif
+
+} // namespace
+
+bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values) {
+ assert(values.data() != nullptr);
+ if (values.data() == nullptr) {
+ return false;
+ }
+ if (values.empty()) {
+ return true;
+ }
+ return ReadSeedMaterialFromOSEntropyImpl(values);
+}
+
+void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
+ absl::Span<uint32_t> seed_material) {
+ // Algorithm is based on code available at
+ // https://gist.github.com/imneme/540829265469e673d045
+ constexpr uint32_t kInitVal = 0x43b0d7e5;
+ constexpr uint32_t kHashMul = 0x931e8875;
+ constexpr uint32_t kMixMulL = 0xca01f9dd;
+ constexpr uint32_t kMixMulR = 0x4973f715;
+ constexpr uint32_t kShiftSize = sizeof(uint32_t) * 8 / 2;
+
+ uint32_t hash_const = kInitVal;
+ auto hash = [&](uint32_t value) {
+ value ^= hash_const;
+ hash_const *= kHashMul;
+ value *= hash_const;
+ value ^= value >> kShiftSize;
+ return value;
+ };
+
+ auto mix = [&](uint32_t x, uint32_t y) {
+ uint32_t result = kMixMulL * x - kMixMulR * y;
+ result ^= result >> kShiftSize;
+ return result;
+ };
+
+ for (const auto& seq_val : sequence) {
+ for (auto& elem : seed_material) {
+ elem = mix(elem, hash(seq_val));
+ }
+ }
+}
+
+absl::optional<uint32_t> GetSaltMaterial() {
+ // Salt must be common for all generators within the same process so read it
+ // only once and store in static variable.
+ static const auto salt_material = []() -> absl::optional<uint32_t> {
+ uint32_t salt_value = 0;
+
+ if (random_internal::ReadSeedMaterialFromOSEntropy(
+ MakeSpan(&salt_value, 1))) {
+ return salt_value;
+ }
+
+ return absl::nullopt;
+ }();
+
+ return salt_material;
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.h
new file mode 100644
index 00000000000..4be10e92568
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material.h
@@ -0,0 +1,104 @@
+// 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_SEED_MATERIAL_H_
+#define ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
+
+#include <cassert>
+#include <cstdint>
+#include <cstdlib>
+#include <string>
+#include <vector>
+
+#include "absl/base/attributes.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Returns the number of 32-bit blocks needed to contain the given number of
+// bits.
+constexpr size_t SeedBitsToBlocks(size_t seed_size) {
+ return (seed_size + 31) / 32;
+}
+
+// Amount of entropy (measured in bits) used to instantiate a Seed Sequence,
+// with which to create a URBG.
+constexpr size_t kEntropyBitsNeeded = 256;
+
+// Amount of entropy (measured in 32-bit blocks) used to instantiate a Seed
+// Sequence, with which to create a URBG.
+constexpr size_t kEntropyBlocksNeeded =
+ random_internal::SeedBitsToBlocks(kEntropyBitsNeeded);
+
+static_assert(kEntropyBlocksNeeded > 0,
+ "Entropy used to seed URBGs must be nonzero.");
+
+// Attempts to fill a span of uint32_t-values using an OS-provided source of
+// true entropy (eg. /dev/urandom) into an array of uint32_t blocks of data. The
+// resulting array may be used to initialize an instance of a class conforming
+// to the C++ Standard "Seed Sequence" concept [rand.req.seedseq].
+//
+// If values.data() == nullptr, the behavior is undefined.
+ABSL_MUST_USE_RESULT
+bool ReadSeedMaterialFromOSEntropy(absl::Span<uint32_t> values);
+
+// Attempts to fill a span of uint32_t-values using variates generated by an
+// existing instance of a class conforming to the C++ Standard "Uniform Random
+// Bit Generator" concept [rand.req.urng]. The resulting data may be used to
+// initialize an instance of a class conforming to the C++ Standard
+// "Seed Sequence" concept [rand.req.seedseq].
+//
+// If urbg == nullptr or values.data() == nullptr, the behavior is undefined.
+template <typename URBG>
+ABSL_MUST_USE_RESULT bool ReadSeedMaterialFromURBG(
+ URBG* urbg, absl::Span<uint32_t> values) {
+ random_internal::FastUniformBits<uint32_t> distr;
+
+ assert(urbg != nullptr && values.data() != nullptr);
+ if (urbg == nullptr || values.data() == nullptr) {
+ return false;
+ }
+
+ for (uint32_t& seed_value : values) {
+ seed_value = distr(*urbg);
+ }
+ return true;
+}
+
+// Mixes given sequence of values with into given sequence of seed material.
+// Time complexity of this function is O(sequence.size() *
+// seed_material.size()).
+//
+// Algorithm is based on code available at
+// https://gist.github.com/imneme/540829265469e673d045
+// by Melissa O'Neill.
+void MixIntoSeedMaterial(absl::Span<const uint32_t> sequence,
+ absl::Span<uint32_t> seed_material);
+
+// Returns salt value.
+//
+// Salt is obtained only once and stored in static variable.
+//
+// May return empty value if optaining the salt was not possible.
+absl::optional<uint32_t> GetSaltMaterial();
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_SEED_MATERIAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material_test.cc
new file mode 100644
index 00000000000..6db2820ec70
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/seed_material_test.cc
@@ -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.
+
+#include "absl/random/internal/seed_material.h"
+
+#include <bitset>
+#include <cstdlib>
+#include <cstring>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#ifdef __ANDROID__
+// Android assert messages only go to system log, so death tests cannot inspect
+// the message for matching.
+#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+ EXPECT_DEATH_IF_SUPPORTED(statement, ".*")
+#else
+#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
+ EXPECT_DEATH_IF_SUPPORTED(statement, regex)
+#endif
+
+namespace {
+
+using testing::Each;
+using testing::ElementsAre;
+using testing::Eq;
+using testing::Ne;
+using testing::Pointwise;
+
+TEST(SeedBitsToBlocks, VerifyCases) {
+ EXPECT_EQ(0, absl::random_internal::SeedBitsToBlocks(0));
+ EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(1));
+ EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(31));
+ EXPECT_EQ(1, absl::random_internal::SeedBitsToBlocks(32));
+ EXPECT_EQ(2, absl::random_internal::SeedBitsToBlocks(33));
+ EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(127));
+ EXPECT_EQ(4, absl::random_internal::SeedBitsToBlocks(128));
+ EXPECT_EQ(5, absl::random_internal::SeedBitsToBlocks(129));
+}
+
+TEST(ReadSeedMaterialFromOSEntropy, SuccessiveReadsAreDistinct) {
+ constexpr size_t kSeedMaterialSize = 64;
+ uint32_t seed_material_1[kSeedMaterialSize] = {};
+ uint32_t seed_material_2[kSeedMaterialSize] = {};
+
+ EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::Span<uint32_t>(seed_material_1, kSeedMaterialSize)));
+ EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::Span<uint32_t>(seed_material_2, kSeedMaterialSize)));
+
+ EXPECT_THAT(seed_material_1, Pointwise(Ne(), seed_material_2));
+}
+
+TEST(ReadSeedMaterialFromOSEntropy, ReadZeroBytesIsNoOp) {
+ uint32_t seed_material[32] = {};
+ std::memset(seed_material, 0xAA, sizeof(seed_material));
+ EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::Span<uint32_t>(seed_material, 0)));
+
+ EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));
+}
+
+TEST(ReadSeedMaterialFromOSEntropy, NullPtrVectorArgument) {
+#ifdef NDEBUG
+ EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::Span<uint32_t>(nullptr, 32)));
+#else
+ bool result;
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(
+ result = absl::random_internal::ReadSeedMaterialFromOSEntropy(
+ absl::Span<uint32_t>(nullptr, 32)),
+ "!= nullptr");
+ (void)result; // suppress unused-variable warning
+#endif
+}
+
+TEST(ReadSeedMaterialFromURBG, SeedMaterialEqualsVariateSequence) {
+ // Two default-constructed instances of std::mt19937_64 are guaranteed to
+ // produce equal variate-sequences.
+ std::mt19937 urbg_1;
+ std::mt19937 urbg_2;
+ constexpr size_t kSeedMaterialSize = 1024;
+ uint32_t seed_material[kSeedMaterialSize] = {};
+
+ EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(
+ &urbg_1, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));
+ for (uint32_t seed : seed_material) {
+ EXPECT_EQ(seed, urbg_2());
+ }
+}
+
+TEST(ReadSeedMaterialFromURBG, ReadZeroBytesIsNoOp) {
+ std::mt19937_64 urbg;
+ uint32_t seed_material[32];
+ std::memset(seed_material, 0xAA, sizeof(seed_material));
+ EXPECT_TRUE(absl::random_internal::ReadSeedMaterialFromURBG(
+ &urbg, absl::Span<uint32_t>(seed_material, 0)));
+
+ EXPECT_THAT(seed_material, Each(Eq(0xAAAAAAAA)));
+}
+
+TEST(ReadSeedMaterialFromURBG, NullUrbgArgument) {
+ constexpr size_t kSeedMaterialSize = 32;
+ uint32_t seed_material[kSeedMaterialSize];
+#ifdef NDEBUG
+ EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(
+ nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)));
+#else
+ bool result;
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(
+ result = absl::random_internal::ReadSeedMaterialFromURBG<std::mt19937_64>(
+ nullptr, absl::Span<uint32_t>(seed_material, kSeedMaterialSize)),
+ "!= nullptr");
+ (void)result; // suppress unused-variable warning
+#endif
+}
+
+TEST(ReadSeedMaterialFromURBG, NullPtrVectorArgument) {
+ std::mt19937_64 urbg;
+#ifdef NDEBUG
+ EXPECT_FALSE(absl::random_internal::ReadSeedMaterialFromURBG(
+ &urbg, absl::Span<uint32_t>(nullptr, 32)));
+#else
+ bool result;
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(
+ result = absl::random_internal::ReadSeedMaterialFromURBG(
+ &urbg, absl::Span<uint32_t>(nullptr, 32)),
+ "!= nullptr");
+ (void)result; // suppress unused-variable warning
+#endif
+}
+
+// The avalanche effect is a desirable cryptographic property of hashes in which
+// changing a single bit in the input causes each bit of the output to be
+// changed with probability near 50%.
+//
+// https://en.wikipedia.org/wiki/Avalanche_effect
+
+TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitLong) {
+ std::vector<uint32_t> seed_material = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ // For every 32-bit number with exactly one bit set, verify the avalanche
+ // effect holds. In order to reduce flakiness of tests, accept values
+ // anywhere in the range of 30%-70%.
+ for (uint32_t v = 1; v != 0; v <<= 1) {
+ std::vector<uint32_t> seed_material_copy = seed_material;
+ absl::random_internal::MixIntoSeedMaterial(
+ absl::Span<uint32_t>(&v, 1),
+ absl::Span<uint32_t>(seed_material_copy.data(),
+ seed_material_copy.size()));
+
+ uint32_t changed_bits = 0;
+ for (size_t i = 0; i < seed_material.size(); i++) {
+ std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^
+ seed_material_copy[i]);
+ changed_bits += bitset.count();
+ }
+
+ EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());
+ EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());
+ }
+}
+
+TEST(MixSequenceIntoSeedMaterial, AvalancheEffectTestOneBitShort) {
+ std::vector<uint32_t> seed_material = {1};
+
+ // For every 32-bit number with exactly one bit set, verify the avalanche
+ // effect holds. In order to reduce flakiness of tests, accept values
+ // anywhere in the range of 30%-70%.
+ for (uint32_t v = 1; v != 0; v <<= 1) {
+ std::vector<uint32_t> seed_material_copy = seed_material;
+ absl::random_internal::MixIntoSeedMaterial(
+ absl::Span<uint32_t>(&v, 1),
+ absl::Span<uint32_t>(seed_material_copy.data(),
+ seed_material_copy.size()));
+
+ uint32_t changed_bits = 0;
+ for (size_t i = 0; i < seed_material.size(); i++) {
+ std::bitset<sizeof(uint32_t) * 8> bitset(seed_material[i] ^
+ seed_material_copy[i]);
+ changed_bits += bitset.count();
+ }
+
+ EXPECT_LE(changed_bits, 0.7 * sizeof(uint32_t) * 8 * seed_material.size());
+ EXPECT_GE(changed_bits, 0.3 * sizeof(uint32_t) * 8 * seed_material.size());
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/sequence_urbg.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/sequence_urbg.h
new file mode 100644
index 00000000000..bc96a12cd29
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits.h
new file mode 100644
index 00000000000..75772bd9abb
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits.h
@@ -0,0 +1,101 @@
+// 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_TRAITS_H_
+#define ABSL_RANDOM_INTERNAL_TRAITS_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// random_internal::is_widening_convertible<A, B>
+//
+// Returns whether a type A is widening-convertible to a type B.
+//
+// A is widening-convertible to B means:
+// A a = <any number>;
+// B b = a;
+// A c = b;
+// EXPECT_EQ(a, c);
+template <typename A, typename B>
+class is_widening_convertible {
+ // As long as there are enough bits in the exact part of a number:
+ // - unsigned can fit in float, signed, unsigned
+ // - signed can fit in float, signed
+ // - float can fit in float
+ // So we define rank to be:
+ // - rank(float) -> 2
+ // - rank(signed) -> 1
+ // - rank(unsigned) -> 0
+ template <class T>
+ static constexpr int rank() {
+ return !std::numeric_limits<T>::is_integer +
+ std::numeric_limits<T>::is_signed;
+ }
+
+ public:
+ // If an arithmetic-type B can represent at least as many digits as a type A,
+ // and B belongs to a rank no lower than A, then A can be safely represented
+ // by B through a widening-conversion.
+ static constexpr bool value =
+ std::numeric_limits<A>::digits <= std::numeric_limits<B>::digits &&
+ rank<A>() <= rank<B>();
+};
+
+// unsigned_bits<N>::type returns the unsigned int type with the indicated
+// number of bits.
+template <size_t N>
+struct unsigned_bits;
+
+template <>
+struct unsigned_bits<8> {
+ using type = uint8_t;
+};
+template <>
+struct unsigned_bits<16> {
+ using type = uint16_t;
+};
+template <>
+struct unsigned_bits<32> {
+ using type = uint32_t;
+};
+template <>
+struct unsigned_bits<64> {
+ using type = uint64_t;
+};
+
+#ifdef ABSL_HAVE_INTRINSIC_INT128
+template <>
+struct unsigned_bits<128> {
+ using type = __uint128_t;
+};
+#endif
+
+template <typename IntType>
+struct make_unsigned_bits {
+ using type = typename unsigned_bits<std::numeric_limits<
+ typename std::make_unsigned<IntType>::type>::digits>::type;
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_TRAITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits_test.cc
new file mode 100644
index 00000000000..a844887d3e4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/traits_test.cc
@@ -0,0 +1,126 @@
+// 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.
+
+#include "absl/random/internal/traits.h"
+
+#include <cstdint>
+#include <type_traits>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::random_internal::is_widening_convertible;
+
+// CheckWideningConvertsToSelf<T1, T2, ...>()
+//
+// For each type T, checks:
+// - T IS widening-convertible to itself.
+//
+template <typename T>
+void CheckWideningConvertsToSelf() {
+ static_assert(is_widening_convertible<T, T>::value,
+ "Type is not convertible to self!");
+}
+
+template <typename T, typename Next, typename... Args>
+void CheckWideningConvertsToSelf() {
+ CheckWideningConvertsToSelf<T>();
+ CheckWideningConvertsToSelf<Next, Args...>();
+}
+
+// CheckNotWideningConvertibleWithSigned<T1, T2, ...>()
+//
+// For each unsigned-type T, checks that:
+// - T is NOT widening-convertible to Signed(T)
+// - Signed(T) is NOT widening-convertible to T
+//
+template <typename T>
+void CheckNotWideningConvertibleWithSigned() {
+ using signed_t = typename std::make_signed<T>::type;
+
+ static_assert(!is_widening_convertible<T, signed_t>::value,
+ "Unsigned type is convertible to same-sized signed-type!");
+ static_assert(!is_widening_convertible<signed_t, T>::value,
+ "Signed type is convertible to same-sized unsigned-type!");
+}
+
+template <typename T, typename Next, typename... Args>
+void CheckNotWideningConvertibleWithSigned() {
+ CheckNotWideningConvertibleWithSigned<T>();
+ CheckWideningConvertsToSelf<Next, Args...>();
+}
+
+// CheckWideningConvertsToLargerType<T1, T2, ...>()
+//
+// For each successive unsigned-types {Ti, Ti+1}, checks that:
+// - Ti IS widening-convertible to Ti+1
+// - Ti IS widening-convertible to Signed(Ti+1)
+// - Signed(Ti) is NOT widening-convertible to Ti
+// - Signed(Ti) IS widening-convertible to Ti+1
+template <typename T, typename Higher>
+void CheckWideningConvertsToLargerTypes() {
+ using signed_t = typename std::make_signed<T>::type;
+ using higher_t = Higher;
+ using signed_higher_t = typename std::make_signed<Higher>::type;
+
+ static_assert(is_widening_convertible<T, higher_t>::value,
+ "Type not embeddable into larger type!");
+ static_assert(is_widening_convertible<T, signed_higher_t>::value,
+ "Type not embeddable into larger signed type!");
+ static_assert(!is_widening_convertible<signed_t, higher_t>::value,
+ "Signed type is embeddable into larger unsigned type!");
+ static_assert(is_widening_convertible<signed_t, signed_higher_t>::value,
+ "Signed type not embeddable into larger signed type!");
+}
+
+template <typename T, typename Higher, typename Next, typename... Args>
+void CheckWideningConvertsToLargerTypes() {
+ CheckWideningConvertsToLargerTypes<T, Higher>();
+ CheckWideningConvertsToLargerTypes<Higher, Next, Args...>();
+}
+
+// CheckWideningConvertsTo<T, U, [expect]>
+//
+// Checks that T DOES widening-convert to U.
+// If "expect" is false, then asserts that T does NOT widening-convert to U.
+template <typename T, typename U, bool expect = true>
+void CheckWideningConvertsTo() {
+ static_assert(is_widening_convertible<T, U>::value == expect,
+ "Unexpected result for is_widening_convertible<T, U>!");
+}
+
+TEST(TraitsTest, IsWideningConvertibleTest) {
+ constexpr bool kInvalid = false;
+
+ CheckWideningConvertsToSelf<
+ uint8_t, uint16_t, uint32_t, uint64_t,
+ int8_t, int16_t, int32_t, int64_t,
+ float, double>();
+ CheckNotWideningConvertibleWithSigned<
+ uint8_t, uint16_t, uint32_t, uint64_t>();
+ CheckWideningConvertsToLargerTypes<
+ uint8_t, uint16_t, uint32_t, uint64_t>();
+
+ CheckWideningConvertsTo<float, double>();
+ CheckWideningConvertsTo<uint16_t, float>();
+ CheckWideningConvertsTo<uint32_t, double>();
+ CheckWideningConvertsTo<uint64_t, double, kInvalid>();
+ CheckWideningConvertsTo<double, float, kInvalid>();
+
+ CheckWideningConvertsTo<bool, int>();
+ CheckWideningConvertsTo<bool, float>();
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper.h
new file mode 100644
index 00000000000..1243bc1c62a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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<
+ std::is_integral<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<
+ std::is_integral<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<
+ std::is_integral<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<std::is_integral<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<std::is_integral<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 distribtuion 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper_test.cc
new file mode 100644
index 00000000000..173c49b0b7f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/uniform_helper_test.cc
@@ -0,0 +1,279 @@
+// 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.
+
+#include "absl/random/internal/uniform_helper.h"
+
+#include <cmath>
+#include <cstdint>
+#include <random>
+
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::IntervalClosedClosedTag;
+using absl::IntervalClosedOpenTag;
+using absl::IntervalOpenClosedTag;
+using absl::IntervalOpenOpenTag;
+using absl::random_internal::uniform_inferred_return_t;
+using absl::random_internal::uniform_lower_bound;
+using absl::random_internal::uniform_upper_bound;
+
+class UniformHelperTest : public testing::Test {};
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsGeneral) {
+ constexpr IntervalClosedClosedTag IntervalClosedClosed;
+ constexpr IntervalClosedOpenTag IntervalClosedOpen;
+ constexpr IntervalOpenClosedTag IntervalOpenClosed;
+ constexpr IntervalOpenOpenTag IntervalOpenOpen;
+
+ // absl::uniform_int_distribution natively assumes IntervalClosedClosed
+ // absl::uniform_real_distribution natively assumes IntervalClosedOpen
+
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, 0, 100), 1);
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, 0, 100), 1);
+ EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, 0, 1.0), 0);
+ EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, 0, 1.0), 0);
+ EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, 0, 1.0), 0);
+ EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, 0, 1.0), 0);
+
+ EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, 0, 100), 0);
+ EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, 0, 100), 0);
+ EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, 0, 1.0), 0);
+ EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, 0, 1.0), 0);
+ EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, 0, 1.0), 0);
+ EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, 0, 1.0), 0);
+
+ EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, 0, 100), 99);
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, 0, 100), 99);
+ EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, 0, 1.0), 1.0);
+ EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, 0, 1.0), 1.0);
+ EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, 0, 1.0), 1.0);
+ EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, 0, 1.0), 1.0);
+
+ EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, 0, 100), 100);
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0, 100), 100);
+ EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, 0, 1.0), 1.0);
+ EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, 0, 1.0), 1.0);
+ EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, 0, 1.0), 1.0);
+ EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, 0, 1.0), 1.0);
+
+ // Negative value tests
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, -100, -1), -99);
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenOpen, -100, -1), -99);
+ EXPECT_GT(uniform_lower_bound<float>(IntervalOpenClosed, -2.0, -1.0), -2.0);
+ EXPECT_GT(uniform_lower_bound<float>(IntervalOpenOpen, -2.0, -1.0), -2.0);
+ EXPECT_GT(uniform_lower_bound<double>(IntervalOpenClosed, -2.0, -1.0), -2.0);
+ EXPECT_GT(uniform_lower_bound<double>(IntervalOpenOpen, -2.0, -1.0), -2.0);
+
+ EXPECT_EQ(uniform_lower_bound(IntervalClosedClosed, -100, -1), -100);
+ EXPECT_EQ(uniform_lower_bound(IntervalClosedOpen, -100, -1), -100);
+ EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedClosed, -2.0, -1.0), -2.0);
+ EXPECT_EQ(uniform_lower_bound<float>(IntervalClosedOpen, -2.0, -1.0), -2.0);
+ EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedClosed, -2.0, -1.0),
+ -2.0);
+ EXPECT_EQ(uniform_lower_bound<double>(IntervalClosedOpen, -2.0, -1.0), -2.0);
+
+ EXPECT_EQ(uniform_upper_bound(IntervalOpenOpen, -100, -1), -2);
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedOpen, -100, -1), -2);
+ EXPECT_EQ(uniform_upper_bound<float>(IntervalOpenOpen, -2.0, -1.0), -1.0);
+ EXPECT_EQ(uniform_upper_bound<float>(IntervalClosedOpen, -2.0, -1.0), -1.0);
+ EXPECT_EQ(uniform_upper_bound<double>(IntervalOpenOpen, -2.0, -1.0), -1.0);
+ EXPECT_EQ(uniform_upper_bound<double>(IntervalClosedOpen, -2.0, -1.0), -1.0);
+
+ EXPECT_EQ(uniform_upper_bound(IntervalOpenClosed, -100, -1), -1);
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, -100, -1), -1);
+ EXPECT_GT(uniform_upper_bound<float>(IntervalOpenClosed, -2.0, -1.0), -1.0);
+ EXPECT_GT(uniform_upper_bound<float>(IntervalClosedClosed, -2.0, -1.0), -1.0);
+ EXPECT_GT(uniform_upper_bound<double>(IntervalOpenClosed, -2.0, -1.0), -1.0);
+ EXPECT_GT(uniform_upper_bound<double>(IntervalClosedClosed, -2.0, -1.0),
+ -1.0);
+
+ EXPECT_GT(uniform_lower_bound(IntervalOpenClosed, 1.0, 2.0), 1.0);
+ EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, +0.0), 1.0);
+ EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -0.0), 1.0);
+ EXPECT_LT(uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0), 1.0);
+}
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsIntBounds) {
+ // Verifies the saturating nature of uniform_lower_bound and
+ // uniform_upper_bound
+ constexpr IntervalOpenOpenTag IntervalOpenOpen;
+
+ // uint max.
+ constexpr auto m = (std::numeric_limits<uint64_t>::max)();
+
+ EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0u, 0u));
+ EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m, m));
+ EXPECT_EQ(m, uniform_lower_bound(IntervalOpenOpen, m - 1, m - 1));
+ EXPECT_EQ(0, uniform_upper_bound(IntervalOpenOpen, 0u, 0u));
+ EXPECT_EQ(m - 1, uniform_upper_bound(IntervalOpenOpen, m, m));
+
+ // int min/max
+ constexpr auto l = (std::numeric_limits<int64_t>::min)();
+ constexpr auto r = (std::numeric_limits<int64_t>::max)();
+ EXPECT_EQ(1, uniform_lower_bound(IntervalOpenOpen, 0, 0));
+ EXPECT_EQ(l + 1, uniform_lower_bound(IntervalOpenOpen, l, l));
+ EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r - 1, r - 1));
+ EXPECT_EQ(r, uniform_lower_bound(IntervalOpenOpen, r, r));
+ EXPECT_EQ(-1, uniform_upper_bound(IntervalOpenOpen, 0, 0));
+ EXPECT_EQ(l, uniform_upper_bound(IntervalOpenOpen, l, l));
+ EXPECT_EQ(r - 1, uniform_upper_bound(IntervalOpenOpen, r, r));
+}
+
+TEST_F(UniformHelperTest, UniformBoundFunctionsRealBounds) {
+ // absl::uniform_real_distribution natively assumes IntervalClosedOpen;
+ // use the inverse here so each bound has to change.
+ constexpr IntervalOpenClosedTag IntervalOpenClosed;
+
+ // Edge cases: the next value toward itself is itself.
+ EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, 1.0, 1.0));
+ EXPECT_EQ(1.0f, uniform_lower_bound(IntervalOpenClosed, 1.0f, 1.0f));
+
+ // rightmost and leftmost finite values.
+ constexpr auto r = (std::numeric_limits<double>::max)();
+ const auto re = std::nexttoward(r, 0.0);
+ constexpr auto l = -r;
+ const auto le = std::nexttoward(l, 0.0);
+
+ EXPECT_EQ(l, uniform_lower_bound(IntervalOpenClosed, l, l)); // (l,l)
+ EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, r, r)); // (r,r)
+ EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, r)); // (l,r)
+ EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, 0.0)); // (l, 0)
+ EXPECT_EQ(le, uniform_lower_bound(IntervalOpenClosed, l, le)); // (l, le)
+ EXPECT_EQ(r, uniform_lower_bound(IntervalOpenClosed, re, r)); // (re, r)
+
+ EXPECT_EQ(le, uniform_upper_bound(IntervalOpenClosed, l, l)); // (l,l)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, r, r)); // (r,r)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, r)); // (l,r)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, l, re)); // (l,re)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, 0.0, r)); // (0, r)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, re, r)); // (re, r)
+ EXPECT_EQ(r, uniform_upper_bound(IntervalOpenClosed, le, re)); // (le, re)
+
+ const double e = std::nextafter(1.0, 2.0); // 1 + epsilon
+ const double f = std::nextafter(1.0, 0.0); // 1 - epsilon
+
+ // (1.0, 1.0 + epsilon)
+ EXPECT_EQ(e, uniform_lower_bound(IntervalOpenClosed, 1.0, e));
+ EXPECT_EQ(std::nextafter(e, 2.0),
+ uniform_upper_bound(IntervalOpenClosed, 1.0, e));
+
+ // (1.0-epsilon, 1.0)
+ EXPECT_EQ(1.0, uniform_lower_bound(IntervalOpenClosed, f, 1.0));
+ EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, f, 1.0));
+
+ // denorm cases.
+ const double g = std::numeric_limits<double>::denorm_min();
+ const double h = std::nextafter(g, 1.0);
+
+ // (0, denorm_min)
+ EXPECT_EQ(g, uniform_lower_bound(IntervalOpenClosed, 0.0, g));
+ EXPECT_EQ(h, uniform_upper_bound(IntervalOpenClosed, 0.0, g));
+
+ // (denorm_min, 1.0)
+ EXPECT_EQ(h, uniform_lower_bound(IntervalOpenClosed, g, 1.0));
+ EXPECT_EQ(e, uniform_upper_bound(IntervalOpenClosed, g, 1.0));
+
+ // Edge cases: invalid bounds.
+ EXPECT_EQ(f, uniform_lower_bound(IntervalOpenClosed, 1.0, -1.0));
+}
+
+struct Invalid {};
+
+template <typename A, typename B>
+auto InferredUniformReturnT(int) -> uniform_inferred_return_t<A, B>;
+
+template <typename, typename>
+Invalid InferredUniformReturnT(...);
+
+// Given types <A, B, Expect>, CheckArgsInferType() verifies that
+//
+// uniform_inferred_return_t<A, B> and
+// uniform_inferred_return_t<B, A>
+//
+// returns the type "Expect".
+//
+// This interface can also be used to assert that a given inferred return types
+// are invalid. Writing:
+//
+// CheckArgsInferType<float, int, Invalid>()
+//
+// will assert that this overload does not exist.
+template <typename A, typename B, typename Expect>
+void CheckArgsInferType() {
+ static_assert(
+ absl::conjunction<
+ std::is_same<Expect, decltype(InferredUniformReturnT<A, B>(0))>,
+ std::is_same<Expect,
+ decltype(InferredUniformReturnT<B, A>(0))>>::value,
+ "");
+}
+
+TEST_F(UniformHelperTest, UniformTypeInference) {
+ // Infers common types.
+ CheckArgsInferType<uint16_t, uint16_t, uint16_t>();
+ CheckArgsInferType<uint32_t, uint32_t, uint32_t>();
+ CheckArgsInferType<uint64_t, uint64_t, uint64_t>();
+ CheckArgsInferType<int16_t, int16_t, int16_t>();
+ CheckArgsInferType<int32_t, int32_t, int32_t>();
+ CheckArgsInferType<int64_t, int64_t, int64_t>();
+ CheckArgsInferType<float, float, float>();
+ CheckArgsInferType<double, double, double>();
+
+ // Properly promotes uint16_t.
+ CheckArgsInferType<uint16_t, uint32_t, uint32_t>();
+ CheckArgsInferType<uint16_t, uint64_t, uint64_t>();
+ CheckArgsInferType<uint16_t, int32_t, int32_t>();
+ CheckArgsInferType<uint16_t, int64_t, int64_t>();
+ CheckArgsInferType<uint16_t, float, float>();
+ CheckArgsInferType<uint16_t, double, double>();
+
+ // Properly promotes int16_t.
+ CheckArgsInferType<int16_t, int32_t, int32_t>();
+ CheckArgsInferType<int16_t, int64_t, int64_t>();
+ CheckArgsInferType<int16_t, float, float>();
+ CheckArgsInferType<int16_t, double, double>();
+
+ // Invalid (u)int16_t-pairings do not compile.
+ // See "CheckArgsInferType" comments above, for how this is achieved.
+ CheckArgsInferType<uint16_t, int16_t, Invalid>();
+ CheckArgsInferType<int16_t, uint32_t, Invalid>();
+ CheckArgsInferType<int16_t, uint64_t, Invalid>();
+
+ // Properly promotes uint32_t.
+ CheckArgsInferType<uint32_t, uint64_t, uint64_t>();
+ CheckArgsInferType<uint32_t, int64_t, int64_t>();
+ CheckArgsInferType<uint32_t, double, double>();
+
+ // Properly promotes int32_t.
+ CheckArgsInferType<int32_t, int64_t, int64_t>();
+ CheckArgsInferType<int32_t, double, double>();
+
+ // Invalid (u)int32_t-pairings do not compile.
+ CheckArgsInferType<uint32_t, int32_t, Invalid>();
+ CheckArgsInferType<int32_t, uint64_t, Invalid>();
+ CheckArgsInferType<int32_t, float, Invalid>();
+ CheckArgsInferType<uint32_t, float, Invalid>();
+
+ // Invalid (u)int64_t-pairings do not compile.
+ CheckArgsInferType<uint64_t, int64_t, Invalid>();
+ CheckArgsInferType<int64_t, float, Invalid>();
+ CheckArgsInferType<int64_t, double, Invalid>();
+
+ // Properly promotes float.
+ CheckArgsInferType<float, double, double>();
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply.h
new file mode 100644
index 00000000000..b6e6c4b6aad
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply.h
@@ -0,0 +1,111 @@
+// 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_WIDE_MULTIPLY_H_
+#define ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
+
+#include <cstdint>
+#include <limits>
+#include <type_traits>
+
+#if (defined(_WIN32) || defined(_WIN64)) && defined(_M_IA64)
+#include <intrin.h> // NOLINT(build/include_order)
+#pragma intrinsic(_umul128)
+#define ABSL_INTERNAL_USE_UMUL128 1
+#endif
+
+#include "absl/base/config.h"
+#include "absl/numeric/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/random/internal/traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// Helper object to multiply two 64-bit values to a 128-bit value.
+// MultiplyU64ToU128 multiplies two 64-bit values to a 128-bit value.
+// If an intrinsic is available, it is used, otherwise use native 32-bit
+// multiplies to construct the result.
+inline absl::uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ return absl::uint128(static_cast<__uint128_t>(a) * b);
+#elif defined(ABSL_INTERNAL_USE_UMUL128)
+ // uint64_t * uint64_t => uint128 multiply using imul intrinsic on MSVC.
+ uint64_t high = 0;
+ const uint64_t low = _umul128(a, b, &high);
+ return absl::MakeUint128(high, low);
+#else
+ // uint128(a) * uint128(b) in emulated mode computes a full 128-bit x 128-bit
+ // multiply. However there are many cases where that is not necessary, and it
+ // is only necessary to support a 64-bit x 64-bit = 128-bit multiply. This is
+ // for those cases.
+ const uint64_t a00 = static_cast<uint32_t>(a);
+ const uint64_t a32 = a >> 32;
+ const uint64_t b00 = static_cast<uint32_t>(b);
+ const uint64_t b32 = b >> 32;
+
+ const uint64_t c00 = a00 * b00;
+ const uint64_t c32a = a00 * b32;
+ const uint64_t c32b = a32 * b00;
+ const uint64_t c64 = a32 * b32;
+
+ const uint32_t carry =
+ static_cast<uint32_t>(((c00 >> 32) + static_cast<uint32_t>(c32a) +
+ static_cast<uint32_t>(c32b)) >>
+ 32);
+
+ return absl::MakeUint128(c64 + (c32a >> 32) + (c32b >> 32) + carry,
+ c00 + (c32a << 32) + (c32b << 32));
+#endif
+}
+
+// wide_multiply<T> multiplies two N-bit values to a 2N-bit result.
+template <typename UIntType>
+struct wide_multiply {
+ static constexpr size_t kN = std::numeric_limits<UIntType>::digits;
+ using input_type = UIntType;
+ using result_type = typename random_internal::unsigned_bits<kN * 2>::type;
+
+ static result_type multiply(input_type a, input_type b) {
+ return static_cast<result_type>(a) * b;
+ }
+
+ static input_type hi(result_type r) { return r >> kN; }
+ static input_type lo(result_type r) { return r; }
+
+ static_assert(std::is_unsigned<UIntType>::value,
+ "Class-template wide_multiply<> argument must be unsigned.");
+};
+
+#ifndef ABSL_HAVE_INTRINSIC_INT128
+template <>
+struct wide_multiply<uint64_t> {
+ using input_type = uint64_t;
+ using result_type = absl::uint128;
+
+ static result_type multiply(uint64_t a, uint64_t b) {
+ return MultiplyU64ToU128(a, b);
+ }
+
+ static uint64_t hi(result_type r) { return absl::Uint128High64(r); }
+ static uint64_t lo(result_type r) { return absl::Uint128Low64(r); }
+};
+#endif
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_WIDE_MULTIPLY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply_test.cc
new file mode 100644
index 00000000000..e276cb51cf1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/internal/wide_multiply_test.cc
@@ -0,0 +1,65 @@
+// 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.
+
+#include "absl/random/internal/wide_multiply.h"
+
+#include "gtest/gtest.h"
+#include "absl/numeric/int128.h"
+
+using absl::random_internal::MultiplyU64ToU128;
+
+namespace {
+
+TEST(WideMultiplyTest, MultiplyU64ToU128Test) {
+ constexpr uint64_t k1 = 1;
+ constexpr uint64_t kMax = ~static_cast<uint64_t>(0);
+
+ EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
+
+ // Max uint64_t
+ EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
+ absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
+ EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
+ EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(1, kMax));
+ for (int i = 0; i < 64; ++i) {
+ EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+ MultiplyU64ToU128(kMax, k1 << i));
+ EXPECT_EQ(absl::MakeUint128(0, kMax) << i,
+ MultiplyU64ToU128(k1 << i, kMax));
+ }
+
+ // 1-bit x 1-bit.
+ for (int i = 0; i < 64; ++i) {
+ for (int j = 0; j < 64; ++j) {
+ EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+ MultiplyU64ToU128(k1 << i, k1 << j));
+ EXPECT_EQ(absl::MakeUint128(0, 1) << (i + j),
+ MultiplyU64ToU128(k1 << i, k1 << j));
+ }
+ }
+
+ // Verified multiplies
+ EXPECT_EQ(MultiplyU64ToU128(0xffffeeeeddddcccc, 0xbbbbaaaa99998888),
+ absl::MakeUint128(0xbbbb9e2692c5dddc, 0xc28f7531048d2c60));
+ EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfedcba9876543210),
+ absl::MakeUint128(0x0121fa00ad77d742, 0x2236d88fe5618cf0));
+ EXPECT_EQ(MultiplyU64ToU128(0x0123456789abcdef, 0xfdb97531eca86420),
+ absl::MakeUint128(0x0120ae99d26725fc, 0xce197f0ecac319e0));
+ EXPECT_EQ(MultiplyU64ToU128(0x97a87f4f261ba3f2, 0xfedcba9876543210),
+ absl::MakeUint128(0x96fbf1a8ae78d0ba, 0x5a6dd4b71f278320));
+ EXPECT_EQ(MultiplyU64ToU128(0xfedcba9876543210, 0xfdb97531eca86420),
+ absl::MakeUint128(0xfc98c6981a413e22, 0x342d0bbf48948200));
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution.h
new file mode 100644
index 00000000000..43e101169c3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution.h
@@ -0,0 +1,257 @@
+// 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)(bit_width(range()),
+ static_cast<unsigned_type>(
+ 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(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(std::is_integral<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 (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(p.base(), d);
+ const double s = (r * 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>(lo, 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc
new file mode 100644
index 00000000000..5e780d96d30
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc
@@ -0,0 +1,280 @@
+// 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.
+
+#include "absl/random/log_uniform_int_distribution.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+template <typename IntType>
+class LogUniformIntDistributionTypeTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<int8_t, int16_t, int32_t, int64_t, //
+ uint8_t, uint16_t, uint32_t, uint64_t>;
+TYPED_TEST_CASE(LogUniformIntDistributionTypeTest, IntTypes);
+
+TYPED_TEST(LogUniformIntDistributionTypeTest, SerializeTest) {
+ using param_type =
+ typename absl::log_uniform_int_distribution<TypeParam>::param_type;
+ using Limits = std::numeric_limits<TypeParam>;
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ for (const auto& param : {
+ param_type(0, 1), //
+ param_type(0, 2), //
+ param_type(0, 2, 10), //
+ param_type(9, 32, 4), //
+ param_type(1, 101, 10), //
+ param_type(1, Limits::max() / 2), //
+ param_type(0, Limits::max() - 1), //
+ param_type(0, Limits::max(), 2), //
+ param_type(0, Limits::max(), 10), //
+ param_type(Limits::min(), 0), //
+ param_type(Limits::lowest(), Limits::max()), //
+ param_type(Limits::min(), Limits::max()), //
+ }) {
+ // Validate parameters.
+ const auto min = param.min();
+ const auto max = param.max();
+ const auto base = param.base();
+ absl::log_uniform_int_distribution<TypeParam> before(min, max, base);
+ EXPECT_EQ(before.min(), param.min());
+ EXPECT_EQ(before.max(), param.max());
+ EXPECT_EQ(before.base(), param.base());
+
+ {
+ absl::log_uniform_int_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ }
+
+ // Validate stream serialization.
+ std::stringstream ss;
+ ss << before;
+
+ absl::log_uniform_int_distribution<TypeParam> after(3, 6, 17);
+
+ EXPECT_NE(before.max(), after.max());
+ EXPECT_NE(before.base(), after.base());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.min(), after.min());
+ EXPECT_EQ(before.max(), after.max());
+ EXPECT_EQ(before.base(), after.base());
+ EXPECT_EQ(before.param(), after.param());
+ EXPECT_EQ(before, after);
+
+ // Smoke test.
+ auto sample_min = after.max();
+ auto sample_max = after.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = after(gen);
+ EXPECT_GE(sample, after.min());
+ EXPECT_LE(sample, after.max());
+ if (sample > sample_max) sample_max = sample;
+ if (sample < sample_min) sample_min = sample;
+ }
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("Range: ", +sample_min, ", ", +sample_max));
+ }
+}
+
+using log_uniform_i32 = absl::log_uniform_int_distribution<int32_t>;
+
+class LogUniformIntChiSquaredTest
+ : public testing::TestWithParam<log_uniform_i32::param_type> {
+ public:
+ // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for
+ // data generated by the log-uniform-int distribution.
+ double ChiSquaredTestImpl();
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+double LogUniformIntChiSquaredTest::ChiSquaredTestImpl() {
+ using absl::random_internal::kChiSquared;
+
+ const auto& param = GetParam();
+
+ // Check the distribution of L=log(log_uniform_int_distribution, base),
+ // expecting that L is roughly uniformly distributed, that is:
+ //
+ // P[L=0] ~= P[L=1] ~= ... ~= P[L=log(max)]
+ //
+ // For a total of X entries, each bucket should contain some number of samples
+ // in the interval [X/k - a, X/k + a].
+ //
+ // Where `a` is approximately sqrt(X/k). This is validated by bucketing
+ // according to the log function and using a chi-squared test for uniformity.
+
+ const bool is_2 = (param.base() == 2);
+ const double base_log = 1.0 / std::log(param.base());
+ const auto bucket_index = [base_log, is_2, &param](int32_t x) {
+ uint64_t y = static_cast<uint64_t>(x) - param.min();
+ return (y == 0) ? 0
+ : is_2 ? static_cast<int>(1 + std::log2(y))
+ : static_cast<int>(1 + std::log(y) * base_log);
+ };
+ const int max_bucket = bucket_index(param.max()); // inclusive
+ const size_t trials = 15 + (max_bucket + 1) * 10;
+
+ log_uniform_i32 dist(param);
+
+ std::vector<int64_t> buckets(max_bucket + 1);
+ for (size_t i = 0; i < trials; ++i) {
+ const auto sample = dist(rng_);
+ // Check the bounds.
+ ABSL_ASSERT(sample <= dist.max());
+ ABSL_ASSERT(sample >= dist.min());
+ // Convert the output of the generator to one of num_bucket buckets.
+ int bucket = bucket_index(sample);
+ ABSL_ASSERT(bucket <= max_bucket);
+ ++buckets[bucket];
+ }
+
+ // The null-hypothesis is that the distribution is uniform with respect to
+ // log-uniform-int bucketization.
+ const int dof = buckets.size() - 1;
+ const double expected = trials / static_cast<double>(buckets.size());
+
+ const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);
+
+ double chi_square = absl::random_internal::ChiSquareWithExpected(
+ std::begin(buckets), std::end(buckets), expected);
+
+ const double p = absl::random_internal::ChiSquarePValue(chi_square, dof);
+
+ if (chi_square > threshold) {
+ ABSL_INTERNAL_LOG(INFO, "values");
+ for (size_t i = 0; i < buckets.size(); i++) {
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat(i, ": ", buckets[i]));
+ }
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrFormat("trials=%d\n"
+ "%s(data, %d) = %f (%f)\n"
+ "%s @ 0.98 = %f",
+ trials, kChiSquared, dof, chi_square, p,
+ kChiSquared, threshold));
+ }
+ return p;
+}
+
+TEST_P(LogUniformIntChiSquaredTest, MultiTest) {
+ const int kTrials = 5;
+ int failures = 0;
+ for (int i = 0; i < kTrials; i++) {
+ double p_value = ChiSquaredTestImpl();
+ if (p_value < 0.005) {
+ failures++;
+ }
+ }
+
+ // There is a 0.10% chance of producing at least one failure, so raise the
+ // failure threshold high enough to allow for a flake rate < 10,000.
+ EXPECT_LE(failures, 4);
+}
+
+// Generate the parameters for the test.
+std::vector<log_uniform_i32::param_type> GenParams() {
+ using Param = log_uniform_i32::param_type;
+ using Limits = std::numeric_limits<int32_t>;
+
+ return std::vector<Param>{
+ Param{0, 1, 2},
+ Param{1, 1, 2},
+ Param{0, 2, 2},
+ Param{0, 3, 2},
+ Param{0, 4, 2},
+ Param{0, 9, 10},
+ Param{0, 10, 10},
+ Param{0, 11, 10},
+ Param{1, 10, 10},
+ Param{0, (1 << 8) - 1, 2},
+ Param{0, (1 << 8), 2},
+ Param{0, (1 << 30) - 1, 2},
+ Param{-1000, 1000, 10},
+ Param{0, Limits::max(), 2},
+ Param{0, Limits::max(), 3},
+ Param{0, Limits::max(), 10},
+ Param{Limits::min(), 0},
+ Param{Limits::min(), Limits::max(), 2},
+ };
+}
+
+std::string ParamName(
+ const ::testing::TestParamInfo<log_uniform_i32::param_type>& info) {
+ const auto& p = info.param;
+ std::string name =
+ absl::StrCat("min_", p.min(), "__max_", p.max(), "__base_", p.base());
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_SUITE_P(All, LogUniformIntChiSquaredTest,
+ ::testing::ValuesIn(GenParams()), ParamName);
+
+// NOTE: absl::log_uniform_int_distribution is not guaranteed to be stable.
+TEST(LogUniformIntDistributionTest, StabilityTest) {
+ using testing::ElementsAre;
+ // absl::uniform_int_distribution stability relies on
+ // absl::random_internal::LeadingSetBit, std::log, std::pow.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(6);
+
+ {
+ absl::log_uniform_int_distribution<int32_t> dist(0, 256);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ EXPECT_THAT(output, ElementsAre(256, 66, 4, 6, 57, 103));
+ }
+ urbg.reset();
+ {
+ absl::log_uniform_int_distribution<int32_t> dist(0, 256, 10);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ EXPECT_THAT(output, ElementsAre(8, 4, 0, 0, 0, 69));
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions.h
new file mode 100644
index 00000000000..764ab370abe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions.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.
+//
+// -----------------------------------------------------------------------------
+// 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 <limits>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/random/distributions.h"
+#include "absl/random/internal/mock_overload_set.h"
+#include "absl/random/mocking_bit_gen.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::MockOverloadSet<
+ random_internal::UniformDistributionWrapper<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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions_test.cc
new file mode 100644
index 00000000000..de23bafe1e5
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mock_distributions_test.cc
@@ -0,0 +1,72 @@
+// 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.
+
+#include "absl/random/mock_distributions.h"
+
+#include "gtest/gtest.h"
+#include "absl/random/mocking_bit_gen.h"
+#include "absl/random/random.h"
+
+namespace {
+using ::testing::Return;
+
+TEST(MockDistributions, Examples) {
+ absl::MockingBitGen gen;
+
+ EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+ .WillOnce(Return(20));
+ EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+ EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+ EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+ .WillOnce(Return(5.0));
+ EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+ EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+ EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+ .WillOnce(Return(42));
+ EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+ EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+ EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
+ EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+ EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+ EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+ .WillOnce(Return(true));
+ EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+ EXPECT_NE(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
+ EXPECT_CALL(absl::MockBeta<double>(), Call(gen, 3.0, 2.0))
+ .WillOnce(Return(0.567));
+ EXPECT_EQ(absl::Beta<double>(gen, 3.0, 2.0), 0.567);
+
+ EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+ EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+ .WillOnce(Return(1221));
+ EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+ EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+ EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+ .WillOnce(Return(0.001));
+ EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+ EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+ EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+ .WillOnce(Return(2040));
+ EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen.h
new file mode 100644
index 00000000000..7b2b80eb35c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen.h
@@ -0,0 +1,240 @@
+// 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 <iterator>
+#include <limits>
+#include <memory>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.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/distributions.h"
+#include "absl/random/internal/distribution_caller.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace random_internal {
+template <typename>
+struct DistributionCaller;
+class MockHelpers;
+
+} // namespace random_internal
+class BitGenRef;
+
+// 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) / 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.
+//
+class MockingBitGen {
+ public:
+ MockingBitGen() = default;
+ ~MockingBitGen() = 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 ResultT, typename Tuple>
+ struct MockFnCaller;
+
+ // specialization for std::tuple.
+ template <typename MockFnType, typename ResultT, typename... Args>
+ struct MockFnCaller<MockFnType, ResultT, std::tuple<Args...>> {
+ MockFnType* fn;
+ inline ResultT operator()(Args... args) {
+ return fn->Call(std::move(args)...);
+ }
+ };
+
+ // 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 ResultT, typename ArgTupleT>
+ class FunctionHolderImpl final : public FunctionHolder {
+ public:
+ void Apply(void* args_tuple, void* result) override {
+ // 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, 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>
+ auto RegisterMock(SelfT&, base_internal::FastTypeIdType type)
+ -> decltype(GetMockFnType(std::declval<ResultT>(),
+ std::declval<ArgTupleT>()))& {
+ using MockFnType = decltype(GetMockFnType(std::declval<ResultT>(),
+ std::declval<ArgTupleT>()));
+
+ using WrappedFnType = absl::conditional_t<
+ std::is_same<SelfT, ::testing::NiceMock<absl::MockingBitGen>>::value,
+ ::testing::NiceMock<MockFnType>,
+ absl::conditional_t<
+ std::is_same<SelfT,
+ ::testing::NaggyMock<absl::MockingBitGen>>::value,
+ ::testing::NaggyMock<MockFnType>,
+ absl::conditional_t<
+ std::is_same<SelfT,
+ ::testing::StrictMock<absl::MockingBitGen>>::value,
+ ::testing::StrictMock<MockFnType>, MockFnType>>>;
+
+ using ImplT = FunctionHolderImpl<WrappedFnType, 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
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_MOCKING_BIT_GEN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen_test.cc
new file mode 100644
index 00000000000..f63b6e420e0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/mocking_bit_gen_test.cc
@@ -0,0 +1,392 @@
+//
+// 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.
+//
+#include "absl/random/mocking_bit_gen.h"
+
+#include <numeric>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest-spi.h"
+#include "gtest/gtest.h"
+#include "absl/random/bit_gen_ref.h"
+#include "absl/random/mock_distributions.h"
+#include "absl/random/random.h"
+
+namespace {
+
+using ::testing::_;
+using ::testing::Ne;
+using ::testing::Return;
+
+TEST(BasicMocking, AllDistributionsAreOverridable) {
+ absl::MockingBitGen gen;
+
+ EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+ .WillOnce(Return(20));
+ EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+ EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+ EXPECT_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+ .WillOnce(Return(5.0));
+ EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+ EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+ EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+ .WillOnce(Return(42));
+ EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+ EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+ EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(500));
+ EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+ EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+ EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+ .WillOnce(Return(true));
+ EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+ EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+ EXPECT_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+ .WillOnce(Return(1221));
+ EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+ EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+ EXPECT_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+ .WillOnce(Return(0.001));
+ EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+ EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
+ EXPECT_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+ .WillOnce(Return(500000));
+ EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 500000);
+}
+
+TEST(BasicMocking, OnDistribution) {
+ absl::MockingBitGen gen;
+
+ EXPECT_NE(absl::Uniform<int>(gen, 1, 1000000), 20);
+ ON_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+ .WillByDefault(Return(20));
+ EXPECT_EQ(absl::Uniform<int>(gen, 1, 1000000), 20);
+
+ EXPECT_NE(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+ ON_CALL(absl::MockUniform<double>(), Call(gen, 0.0, 100.0))
+ .WillByDefault(Return(5.0));
+ EXPECT_EQ(absl::Uniform<double>(gen, 0.0, 100.0), 5.0);
+
+ EXPECT_NE(absl::Exponential<double>(gen, 1.0), 42);
+ ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+ .WillByDefault(Return(42));
+ EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 42);
+
+ EXPECT_NE(absl::Poisson<int>(gen, 1.0), 500);
+ ON_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillByDefault(Return(500));
+ EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 500);
+
+ EXPECT_NE(absl::Bernoulli(gen, 0.000001), true);
+ ON_CALL(absl::MockBernoulli(), Call(gen, 0.000001))
+ .WillByDefault(Return(true));
+ EXPECT_EQ(absl::Bernoulli(gen, 0.000001), true);
+
+ EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+ ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+ .WillByDefault(Return(1221));
+ EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+
+ EXPECT_NE(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+ ON_CALL(absl::MockGaussian<double>(), Call(gen, 0.0, 1.0))
+ .WillByDefault(Return(0.001));
+ EXPECT_EQ(absl::Gaussian<double>(gen, 0.0, 1.0), 0.001);
+
+ EXPECT_NE(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+ ON_CALL(absl::MockLogUniform<int>(), Call(gen, 0, 1000000, 2))
+ .WillByDefault(Return(2040));
+ EXPECT_EQ(absl::LogUniform<int>(gen, 0, 1000000, 2), 2040);
+}
+
+TEST(BasicMocking, GMockMatchers) {
+ absl::MockingBitGen gen;
+
+ EXPECT_NE(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+ ON_CALL(absl::MockZipf<int>(), Call(gen, 1000000, 2.0, 1.0))
+ .WillByDefault(Return(1221));
+ EXPECT_EQ(absl::Zipf<int>(gen, 1000000, 2.0, 1.0), 1221);
+}
+
+TEST(BasicMocking, OverridesWithMultipleGMockExpectations) {
+ absl::MockingBitGen gen;
+
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 10000))
+ .WillOnce(Return(20))
+ .WillOnce(Return(40))
+ .WillOnce(Return(60));
+ EXPECT_EQ(absl::Uniform(gen, 1, 10000), 20);
+ EXPECT_EQ(absl::Uniform(gen, 1, 10000), 40);
+ EXPECT_EQ(absl::Uniform(gen, 1, 10000), 60);
+}
+
+TEST(BasicMocking, DefaultArgument) {
+ absl::MockingBitGen gen;
+
+ ON_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+ .WillByDefault(Return(200));
+
+ EXPECT_EQ(absl::Exponential<double>(gen), 200);
+ EXPECT_EQ(absl::Exponential<double>(gen, 1.0), 200);
+}
+
+TEST(BasicMocking, MultipleGenerators) {
+ auto get_value = [](absl::BitGenRef gen_ref) {
+ return absl::Uniform(gen_ref, 1, 1000000);
+ };
+ absl::MockingBitGen unmocked_generator;
+ absl::MockingBitGen mocked_with_3;
+ absl::MockingBitGen mocked_with_11;
+
+ EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_3, 1, 1000000))
+ .WillOnce(Return(3))
+ .WillRepeatedly(Return(17));
+ EXPECT_CALL(absl::MockUniform<int>(), Call(mocked_with_11, 1, 1000000))
+ .WillOnce(Return(11))
+ .WillRepeatedly(Return(17));
+
+ // Ensure that unmocked generator generates neither value.
+ int unmocked_value = get_value(unmocked_generator);
+ EXPECT_NE(unmocked_value, 3);
+ EXPECT_NE(unmocked_value, 11);
+ // Mocked generators should generate their mocked values.
+ EXPECT_EQ(get_value(mocked_with_3), 3);
+ EXPECT_EQ(get_value(mocked_with_11), 11);
+ // Ensure that the mocks have expired.
+ EXPECT_NE(get_value(mocked_with_3), 3);
+ EXPECT_NE(get_value(mocked_with_11), 11);
+}
+
+TEST(BasicMocking, MocksNotTrigeredForIncorrectTypes) {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
+
+ EXPECT_NE(absl::Uniform<uint16_t>(gen), 42); // Not mocked
+ EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42); // Mock triggered
+}
+
+TEST(BasicMocking, FailsOnUnsatisfiedMocks) {
+ EXPECT_NONFATAL_FAILURE(
+ []() {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockExponential<double>(), Call(gen, 1.0))
+ .WillOnce(Return(3.0));
+ // Does not call absl::Exponential().
+ }(),
+ "unsatisfied and active");
+}
+
+TEST(OnUniform, RespectsUniformIntervalSemantics) {
+ absl::MockingBitGen gen;
+
+ EXPECT_CALL(absl::MockUniform<int>(),
+ Call(absl::IntervalClosed, gen, 1, 1000000))
+ .WillOnce(Return(301));
+ EXPECT_NE(absl::Uniform(gen, 1, 1000000), 301); // Not mocked
+ EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 1, 1000000), 301);
+}
+
+TEST(OnUniform, RespectsNoArgUnsignedShorthand) {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockUniform<uint32_t>(), Call(gen)).WillOnce(Return(42));
+ EXPECT_EQ(absl::Uniform<uint32_t>(gen), 42);
+}
+
+TEST(RepeatedlyModifier, ForceSnakeEyesForManyDice) {
+ auto roll_some_dice = [](absl::BitGenRef gen_ref) {
+ std::vector<int> results(16);
+ for (auto& r : results) {
+ r = absl::Uniform(absl::IntervalClosed, gen_ref, 1, 6);
+ }
+ return results;
+ };
+ std::vector<int> results;
+ absl::MockingBitGen gen;
+
+ // Without any mocked calls, not all dice roll a "6".
+ results = roll_some_dice(gen);
+ EXPECT_LT(std::accumulate(std::begin(results), std::end(results), 0),
+ results.size() * 6);
+
+ // Verify that we can force all "6"-rolls, with mocking.
+ ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, 1, 6))
+ .WillByDefault(Return(6));
+ results = roll_some_dice(gen);
+ EXPECT_EQ(std::accumulate(std::begin(results), std::end(results), 0),
+ results.size() * 6);
+}
+
+TEST(WillOnce, DistinctCounters) {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+ .Times(3)
+ .WillRepeatedly(Return(0));
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1000001, 2000000))
+ .Times(3)
+ .WillRepeatedly(Return(1));
+ EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+ EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+ EXPECT_EQ(absl::Uniform(gen, 1000001, 2000000), 1);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 0);
+}
+
+TEST(TimesModifier, ModifierSaturatesAndExpires) {
+ EXPECT_NONFATAL_FAILURE(
+ []() {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, 1, 1000000))
+ .Times(3)
+ .WillRepeatedly(Return(15))
+ .RetiresOnSaturation();
+
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 15);
+ // Times(3) has expired - Should get a different value now.
+
+ EXPECT_NE(absl::Uniform(gen, 1, 1000000), 15);
+ }(),
+ "");
+}
+
+TEST(TimesModifier, Times0) {
+ absl::MockingBitGen gen;
+ EXPECT_CALL(absl::MockBernoulli(), Call(gen, 0.0)).Times(0);
+ EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).Times(0);
+}
+
+TEST(AnythingMatcher, MatchesAnyArgument) {
+ using testing::_;
+
+ {
+ absl::MockingBitGen gen;
+ ON_CALL(absl::MockUniform<int>(), Call(absl::IntervalClosed, gen, _, 1000))
+ .WillByDefault(Return(11));
+ ON_CALL(absl::MockUniform<int>(),
+ Call(absl::IntervalClosed, gen, _, Ne(1000)))
+ .WillByDefault(Return(99));
+
+ EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000000), 99);
+ EXPECT_EQ(absl::Uniform(absl::IntervalClosed, gen, 10, 1000), 11);
+ }
+
+ {
+ absl::MockingBitGen gen;
+ ON_CALL(absl::MockUniform<int>(), Call(gen, 1, _))
+ .WillByDefault(Return(25));
+ ON_CALL(absl::MockUniform<int>(), Call(gen, Ne(1), _))
+ .WillByDefault(Return(99));
+ EXPECT_EQ(absl::Uniform(gen, 3, 1000000), 99);
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000000), 25);
+ }
+
+ {
+ absl::MockingBitGen gen;
+ ON_CALL(absl::MockUniform<int>(), Call(gen, _, _))
+ .WillByDefault(Return(145));
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
+ EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);
+ EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);
+ }
+}
+
+TEST(AnythingMatcher, WithWillByDefault) {
+ using testing::_;
+ absl::MockingBitGen gen;
+ std::vector<int> values = {11, 22, 33, 44, 55, 66, 77, 88, 99, 1010};
+
+ ON_CALL(absl::MockUniform<size_t>(), Call(gen, 0, _))
+ .WillByDefault(Return(0));
+ for (int i = 0; i < 100; i++) {
+ auto& elem = values[absl::Uniform(gen, 0u, values.size())];
+ EXPECT_EQ(elem, 11);
+ }
+}
+
+TEST(BasicMocking, WillByDefaultWithArgs) {
+ using testing::_;
+
+ absl::MockingBitGen gen;
+ ON_CALL(absl::MockPoisson<int>(), Call(gen, _))
+ .WillByDefault(
+ [](double lambda) { return static_cast<int>(lambda * 10); });
+ EXPECT_EQ(absl::Poisson<int>(gen, 1.7), 17);
+ EXPECT_EQ(absl::Poisson<int>(gen, 0.03), 0);
+}
+
+TEST(MockingBitGen, InSequenceSucceedsInOrder) {
+ absl::MockingBitGen gen;
+
+ testing::InSequence seq;
+
+ EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 1.0)).WillOnce(Return(3));
+ EXPECT_CALL(absl::MockPoisson<int>(), Call(gen, 2.0)).WillOnce(Return(4));
+
+ EXPECT_EQ(absl::Poisson<int>(gen, 1.0), 3);
+ EXPECT_EQ(absl::Poisson<int>(gen, 2.0), 4);
+}
+
+TEST(MockingBitGen, NiceMock) {
+ ::testing::NiceMock<absl::MockingBitGen> gen;
+ ON_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillByDefault(Return(145));
+
+ ON_CALL(absl::MockPoisson<int>(), Call(gen, _)).WillByDefault(Return(3));
+
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
+ EXPECT_EQ(absl::Uniform(gen, 10, 1000), 145);
+ EXPECT_EQ(absl::Uniform(gen, 100, 1000), 145);
+}
+
+TEST(MockingBitGen, NaggyMock) {
+ // This is difficult to test, as only the output matters, so just verify
+ // that ON_CALL can be installed. Anything else requires log inspection.
+ ::testing::NaggyMock<absl::MockingBitGen> gen;
+
+ ON_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillByDefault(Return(145));
+ ON_CALL(absl::MockPoisson<int>(), Call(gen, _)).WillByDefault(Return(3));
+
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
+}
+
+TEST(MockingBitGen, StrictMock_NotEnough) {
+ EXPECT_NONFATAL_FAILURE(
+ []() {
+ ::testing::StrictMock<absl::MockingBitGen> gen;
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, _, _))
+ .WillOnce(Return(145));
+ }(),
+ "unsatisfied and active");
+}
+
+TEST(MockingBitGen, StrictMock_TooMany) {
+ ::testing::StrictMock<absl::MockingBitGen> gen;
+
+ EXPECT_CALL(absl::MockUniform<int>(), Call(gen, _, _)).WillOnce(Return(145));
+ EXPECT_EQ(absl::Uniform(gen, 1, 1000), 145);
+
+ EXPECT_NONFATAL_FAILURE(
+ [&]() { EXPECT_EQ(absl::Uniform(gen, 10, 1000), 0); }(),
+ "over-saturated and active");
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution.h
new file mode 100644
index 00000000000..cb5f5d5d0ff
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution.h
@@ -0,0 +1,258 @@
+// 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"
+
+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(std::is_integral<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 <= (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 > (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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution_test.cc
new file mode 100644
index 00000000000..8baabd11189
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/poisson_distribution_test.cc
@@ -0,0 +1,573 @@
+// 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.
+
+#include "absl/random/poisson_distribution.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+// Notes about generating poisson variates:
+//
+// It is unlikely that any implementation of std::poisson_distribution
+// will be stable over time and across library implementations. For instance
+// the three different poisson variate generators listed below all differ:
+//
+// https://github.com/ampl/gsl/tree/master/randist/poisson.c
+// * GSL uses a gamma + binomial + knuth method to compute poisson variates.
+//
+// https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/random.tcc
+// * GCC uses the Devroye rejection algorithm, based on
+// Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag,
+// New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!), ~p.511
+// http://www.nrbook.com/devroye/
+//
+// https://github.com/llvm-mirror/libcxx/blob/master/include/random
+// * CLANG uses a different rejection method, which appears to include a
+// normal-distribution approximation and an exponential distribution to
+// compute the threshold, including a similar factorial approximation to this
+// one, but it is unclear where the algorithm comes from, exactly.
+//
+
+namespace {
+
+using absl::random_internal::kChiSquared;
+
+// The PoissonDistributionInterfaceTest provides a basic test that
+// absl::poisson_distribution conforms to the interface and serialization
+// requirements imposed by [rand.req.dist] for the common integer types.
+
+template <typename IntType>
+class PoissonDistributionInterfaceTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t,
+ uint8_t, uint16_t, uint32_t, uint64_t>;
+TYPED_TEST_CASE(PoissonDistributionInterfaceTest, IntTypes);
+
+TYPED_TEST(PoissonDistributionInterfaceTest, SerializeTest) {
+ using param_type = typename absl::poisson_distribution<TypeParam>::param_type;
+ const double kMax =
+ std::min(1e10 /* assertion limit */,
+ static_cast<double>(std::numeric_limits<TypeParam>::max()));
+
+ const double kParams[] = {
+ // Cases around 1.
+ 1, //
+ std::nextafter(1.0, 0.0), // 1 - epsilon
+ std::nextafter(1.0, 2.0), // 1 + epsilon
+ // Arbitrary values.
+ 1e-8, 1e-4,
+ 0.0000005, // ~7.2e-7
+ 0.2, // ~0.2x
+ 0.5, // 0.72
+ 2, // ~2.8
+ 20, // 3x ~9.6
+ 100, 1e4, 1e8, 1.5e9, 1e20,
+ // Boundary cases.
+ std::numeric_limits<double>::max(),
+ std::numeric_limits<double>::epsilon(),
+ std::nextafter(std::numeric_limits<double>::min(),
+ 1.0), // min + epsilon
+ std::numeric_limits<double>::min(), // smallest normal
+ std::numeric_limits<double>::denorm_min(), // smallest denorm
+ std::numeric_limits<double>::min() / 2, // denorm
+ std::nextafter(std::numeric_limits<double>::min(),
+ 0.0), // denorm_max
+ };
+
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ for (const double m : kParams) {
+ const double mean = std::min(kMax, m);
+ const param_type param(mean);
+
+ // Validate parameters.
+ absl::poisson_distribution<TypeParam> before(mean);
+ EXPECT_EQ(before.mean(), param.mean());
+
+ {
+ absl::poisson_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ EXPECT_EQ(via_param.param(), before.param());
+ }
+
+ // Smoke test.
+ auto sample_min = before.max();
+ auto sample_max = before.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = before(gen);
+ EXPECT_GE(sample, before.min());
+ EXPECT_LE(sample, before.max());
+ if (sample > sample_max) sample_max = sample;
+ if (sample < sample_min) sample_min = sample;
+ }
+
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat("Range {", param.mean(), "}: ",
+ +sample_min, ", ", +sample_max));
+
+ // Validate stream serialization.
+ std::stringstream ss;
+ ss << before;
+
+ absl::poisson_distribution<TypeParam> after(3.8);
+
+ EXPECT_NE(before.mean(), after.mean());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.mean(), after.mean()) //
+ << ss.str() << " " //
+ << (ss.good() ? "good " : "") //
+ << (ss.bad() ? "bad " : "") //
+ << (ss.eof() ? "eof " : "") //
+ << (ss.fail() ? "fail " : "");
+ }
+}
+
+// See http://www.itl.nist.gov/div898/handbook/eda/section3/eda366j.htm
+
+class PoissonModel {
+ public:
+ explicit PoissonModel(double mean) : mean_(mean) {}
+
+ double mean() const { return mean_; }
+ double variance() const { return mean_; }
+ double stddev() const { return std::sqrt(variance()); }
+ double skew() const { return 1.0 / mean_; }
+ double kurtosis() const { return 3.0 + 1.0 / mean_; }
+
+ // InitCDF() initializes the CDF for the distribution parameters.
+ void InitCDF();
+
+ // The InverseCDF, or the Percent-point function returns x, P(x) < v.
+ struct CDF {
+ size_t index;
+ double pmf;
+ double cdf;
+ };
+ CDF InverseCDF(double p) {
+ CDF target{0, 0, p};
+ auto it = std::upper_bound(
+ std::begin(cdf_), std::end(cdf_), target,
+ [](const CDF& a, const CDF& b) { return a.cdf < b.cdf; });
+ return *it;
+ }
+
+ void LogCDF() {
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat("CDF (mean = ", mean_, ")"));
+ for (const auto c : cdf_) {
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat(c.index, ": pmf=", c.pmf, " cdf=", c.cdf));
+ }
+ }
+
+ private:
+ const double mean_;
+
+ std::vector<CDF> cdf_;
+};
+
+// The goal is to compute an InverseCDF function, or percent point function for
+// the poisson distribution, and use that to partition our output into equal
+// range buckets. However there is no closed form solution for the inverse cdf
+// for poisson distributions (the closest is the incomplete gamma function).
+// Instead, `InitCDF` iteratively computes the PMF and the CDF. This enables
+// searching for the bucket points.
+void PoissonModel::InitCDF() {
+ if (!cdf_.empty()) {
+ // State already initialized.
+ return;
+ }
+ ABSL_ASSERT(mean_ < 201.0);
+
+ const size_t max_i = 50 * stddev() + mean();
+ const double e_neg_mean = std::exp(-mean());
+ ABSL_ASSERT(e_neg_mean > 0);
+
+ double d = 1;
+ double last_result = e_neg_mean;
+ double cumulative = e_neg_mean;
+ if (e_neg_mean > 1e-10) {
+ cdf_.push_back({0, e_neg_mean, cumulative});
+ }
+ for (size_t i = 1; i < max_i; i++) {
+ d *= (mean() / i);
+ double result = e_neg_mean * d;
+ cumulative += result;
+ if (result < 1e-10 && result < last_result && cumulative > 0.999999) {
+ break;
+ }
+ if (result > 1e-7) {
+ cdf_.push_back({i, result, cumulative});
+ }
+ last_result = result;
+ }
+ ABSL_ASSERT(!cdf_.empty());
+}
+
+// PoissonDistributionZTest implements a z-test for the poisson distribution.
+
+struct ZParam {
+ double mean;
+ double p_fail; // Z-Test probability of failure.
+ int trials; // Z-Test trials.
+ size_t samples; // Z-Test samples.
+};
+
+class PoissonDistributionZTest : public testing::TestWithParam<ZParam>,
+ public PoissonModel {
+ public:
+ PoissonDistributionZTest() : PoissonModel(GetParam().mean) {}
+
+ // ZTestImpl provides a basic z-squared test of the mean vs. expected
+ // mean for data generated by the poisson distribution.
+ template <typename D>
+ bool SingleZTest(const double p, const size_t samples);
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+template <typename D>
+bool PoissonDistributionZTest::SingleZTest(const double p,
+ const size_t samples) {
+ D dis(mean());
+
+ absl::flat_hash_map<int32_t, int> buckets;
+ std::vector<double> data;
+ data.reserve(samples);
+ for (int j = 0; j < samples; j++) {
+ const auto x = dis(rng_);
+ buckets[x]++;
+ data.push_back(x);
+ }
+
+ // The null-hypothesis is that the distribution is a poisson distribution with
+ // the provided mean (not estimated from the data).
+ const auto m = absl::random_internal::ComputeDistributionMoments(data);
+ const double max_err = absl::random_internal::MaxErrorTolerance(p);
+ const double z = absl::random_internal::ZScore(mean(), m);
+ const bool pass = absl::random_internal::Near("z", z, 0.0, max_err);
+
+ if (!pass) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrFormat("p=%f max_err=%f\n"
+ " mean=%f vs. %f\n"
+ " stddev=%f vs. %f\n"
+ " skewness=%f vs. %f\n"
+ " kurtosis=%f vs. %f\n"
+ " z=%f",
+ p, max_err, m.mean, mean(), std::sqrt(m.variance),
+ stddev(), m.skewness, skew(), m.kurtosis,
+ kurtosis(), z));
+ }
+ return pass;
+}
+
+TEST_P(PoissonDistributionZTest, AbslPoissonDistribution) {
+ const auto& param = GetParam();
+ const int expected_failures =
+ std::max(1, static_cast<int>(std::ceil(param.trials * param.p_fail)));
+ const double p = absl::random_internal::RequiredSuccessProbability(
+ param.p_fail, param.trials);
+
+ int failures = 0;
+ for (int i = 0; i < param.trials; i++) {
+ failures +=
+ SingleZTest<absl::poisson_distribution<int32_t>>(p, param.samples) ? 0
+ : 1;
+ }
+ EXPECT_LE(failures, expected_failures);
+}
+
+std::vector<ZParam> GetZParams() {
+ // These values have been adjusted from the "exact" computed values to reduce
+ // failure rates.
+ //
+ // It turns out that the actual values are not as close to the expected values
+ // as would be ideal.
+ return std::vector<ZParam>({
+ // Knuth method.
+ ZParam{0.5, 0.01, 100, 1000},
+ ZParam{1.0, 0.01, 100, 1000},
+ ZParam{10.0, 0.01, 100, 5000},
+ // Split-knuth method.
+ ZParam{20.0, 0.01, 100, 10000},
+ ZParam{50.0, 0.01, 100, 10000},
+ // Ratio of gaussians method.
+ ZParam{51.0, 0.01, 100, 10000},
+ ZParam{200.0, 0.05, 10, 100000},
+ ZParam{100000.0, 0.05, 10, 1000000},
+ });
+}
+
+std::string ZParamName(const ::testing::TestParamInfo<ZParam>& info) {
+ const auto& p = info.param;
+ std::string name = absl::StrCat("mean_", absl::SixDigits(p.mean));
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionZTest,
+ ::testing::ValuesIn(GetZParams()), ZParamName);
+
+// The PoissonDistributionChiSquaredTest class provides a basic test framework
+// for variates generated by a conforming poisson_distribution.
+class PoissonDistributionChiSquaredTest : public testing::TestWithParam<double>,
+ public PoissonModel {
+ public:
+ PoissonDistributionChiSquaredTest() : PoissonModel(GetParam()) {}
+
+ // The ChiSquaredTestImpl provides a chi-squared goodness of fit test for data
+ // generated by the poisson distribution.
+ template <typename D>
+ double ChiSquaredTestImpl();
+
+ private:
+ void InitChiSquaredTest(const double buckets);
+
+ std::vector<size_t> cutoffs_;
+ std::vector<double> expected_;
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+void PoissonDistributionChiSquaredTest::InitChiSquaredTest(
+ const double buckets) {
+ if (!cutoffs_.empty() && !expected_.empty()) {
+ return;
+ }
+ InitCDF();
+
+ // The code below finds cuttoffs that yield approximately equally-sized
+ // buckets to the extent that it is possible. However for poisson
+ // distributions this is particularly challenging for small mean parameters.
+ // Track the expected proportion of items in each bucket.
+ double last_cdf = 0;
+ const double inc = 1.0 / buckets;
+ for (double p = inc; p <= 1.0; p += inc) {
+ auto result = InverseCDF(p);
+ if (!cutoffs_.empty() && cutoffs_.back() == result.index) {
+ continue;
+ }
+ double d = result.cdf - last_cdf;
+ cutoffs_.push_back(result.index);
+ expected_.push_back(d);
+ last_cdf = result.cdf;
+ }
+ cutoffs_.push_back(std::numeric_limits<size_t>::max());
+ expected_.push_back(std::max(0.0, 1.0 - last_cdf));
+}
+
+template <typename D>
+double PoissonDistributionChiSquaredTest::ChiSquaredTestImpl() {
+ const int kSamples = 2000;
+ const int kBuckets = 50;
+
+ // The poisson CDF fails for large mean values, since e^-mean exceeds the
+ // machine precision. For these cases, using a normal approximation would be
+ // appropriate.
+ ABSL_ASSERT(mean() <= 200);
+ InitChiSquaredTest(kBuckets);
+
+ D dis(mean());
+
+ std::vector<int32_t> counts(cutoffs_.size(), 0);
+ for (int j = 0; j < kSamples; j++) {
+ const size_t x = dis(rng_);
+ auto it = std::lower_bound(std::begin(cutoffs_), std::end(cutoffs_), x);
+ counts[std::distance(cutoffs_.begin(), it)]++;
+ }
+
+ // Normalize the counts.
+ std::vector<int32_t> e(expected_.size(), 0);
+ for (int i = 0; i < e.size(); i++) {
+ e[i] = kSamples * expected_[i];
+ }
+
+ // The null-hypothesis is that the distribution is a poisson distribution with
+ // the provided mean (not estimated from the data).
+ const int dof = static_cast<int>(counts.size()) - 1;
+
+ // The threshold for logging is 1-in-50.
+ const double threshold = absl::random_internal::ChiSquareValue(dof, 0.98);
+
+ const double chi_square = absl::random_internal::ChiSquare(
+ std::begin(counts), std::end(counts), std::begin(e), std::end(e));
+
+ const double p = absl::random_internal::ChiSquarePValue(chi_square, dof);
+
+ // Log if the chi_squared value is above the threshold.
+ if (chi_square > threshold) {
+ LogCDF();
+
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat("VALUES buckets=", counts.size(),
+ " samples=", kSamples));
+ for (size_t i = 0; i < counts.size(); i++) {
+ ABSL_INTERNAL_LOG(
+ INFO, absl::StrCat(cutoffs_[i], ": ", counts[i], " vs. E=", e[i]));
+ }
+
+ ABSL_INTERNAL_LOG(
+ INFO,
+ absl::StrCat(kChiSquared, "(data, dof=", dof, ") = ", chi_square, " (",
+ p, ")\n", " vs.\n", kChiSquared, " @ 0.98 = ", threshold));
+ }
+ return p;
+}
+
+TEST_P(PoissonDistributionChiSquaredTest, AbslPoissonDistribution) {
+ const int kTrials = 20;
+
+ // Large values are not yet supported -- this requires estimating the cdf
+ // using the normal distribution instead of the poisson in this case.
+ ASSERT_LE(mean(), 200.0);
+ if (mean() > 200.0) {
+ return;
+ }
+
+ int failures = 0;
+ for (int i = 0; i < kTrials; i++) {
+ double p_value = ChiSquaredTestImpl<absl::poisson_distribution<int32_t>>();
+ if (p_value < 0.005) {
+ failures++;
+ }
+ }
+ // There is a 0.10% chance of producing at least one failure, so raise the
+ // failure threshold high enough to allow for a flake rate < 10,000.
+ EXPECT_LE(failures, 4);
+}
+
+INSTANTIATE_TEST_SUITE_P(All, PoissonDistributionChiSquaredTest,
+ ::testing::Values(0.5, 1.0, 2.0, 10.0, 50.0, 51.0,
+ 200.0));
+
+// NOTE: absl::poisson_distribution is not guaranteed to be stable.
+TEST(PoissonDistributionTest, StabilityTest) {
+ using testing::ElementsAre;
+ // absl::poisson_distribution stability relies on stability of
+ // std::exp, std::log, std::sqrt, std::ceil, std::floor, and
+ // absl::FastUniformBits, absl::StirlingLogFactorial, absl::RandU64ToDouble.
+ absl::random_internal::sequence_urbg urbg({
+ 0x035b0dc7e0a18acfull, 0x06cebe0d2653682eull, 0x0061e9b23861596bull,
+ 0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull,
+ 0x4864f22c059bf29eull, 0x247856d8b862665cull, 0xe46e86e9a1337e10ull,
+ 0xd8c8541f3519b133ull, 0xe75b5162c567b9e4ull, 0xf732e5ded7009c5bull,
+ 0xb170b98353121eacull, 0x1ec2e8986d2362caull, 0x814c8e35fe9a961aull,
+ 0x0c3cd59c9b638a02ull, 0xcb3bb6478a07715cull, 0x1224e62c978bbc7full,
+ 0x671ef2cb04e81f6eull, 0x3c1cbd811eaf1808ull, 0x1bbc23cfa8fac721ull,
+ 0xa4c2cda65e596a51ull, 0xb77216fad37adf91ull, 0x836d794457c08849ull,
+ 0xe083df03475f49d7ull, 0xbc9feb512e6b0d6cull, 0xb12d74fdd718c8c5ull,
+ 0x12ff09653bfbe4caull, 0x8dd03a105bc4ee7eull, 0x5738341045ba0d85ull,
+ 0xf3fd722dc65ad09eull, 0xfa14fd21ea2a5705ull, 0xffe6ea4d6edb0c73ull,
+ 0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull, 0xEAAD8E716B93D5A0ull,
+ 0xD08ED1D0AFC725E0ull, 0x8E3C5B2F8E7594B7ull, 0x8FF6E2FBF2122B64ull,
+ 0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull, 0xD1CFF191B3A8C1ADull,
+ 0x2F2F2218BE0E1777ull, 0xEA752DFE8B021FA1ull, 0xE5A0CC0FB56F74E8ull,
+ 0x18ACF3D6CE89E299ull, 0xB4A84FE0FD13E0B7ull, 0x7CC43B81D2ADA8D9ull,
+ 0x165FA26680957705ull, 0x93CC7314211A1477ull, 0xE6AD206577B5FA86ull,
+ 0xC75442F5FB9D35CFull, 0xEBCDAF0C7B3E89A0ull, 0xD6411BD3AE1E7E49ull,
+ 0x00250E2D2071B35Eull, 0x226800BB57B8E0AFull, 0x2464369BF009B91Eull,
+ 0x5563911D59DFA6AAull, 0x78C14389D95A537Full, 0x207D5BA202E5B9C5ull,
+ 0x832603766295CFA9ull, 0x11C819684E734A41ull, 0xB3472DCA7B14A94Aull,
+ });
+
+ std::vector<int> output(10);
+
+ // Method 1.
+ {
+ absl::poisson_distribution<int> dist(5);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ }
+ EXPECT_THAT(output, // mean = 4.2
+ ElementsAre(1, 0, 0, 4, 2, 10, 3, 3, 7, 12));
+
+ // Method 2.
+ {
+ urbg.reset();
+ absl::poisson_distribution<int> dist(25);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ }
+ EXPECT_THAT(output, // mean = 19.8
+ ElementsAre(9, 35, 18, 10, 35, 18, 10, 35, 18, 10));
+
+ // Method 3.
+ {
+ urbg.reset();
+ absl::poisson_distribution<int> dist(121);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ }
+ EXPECT_THAT(output, // mean = 124.1
+ ElementsAre(161, 122, 129, 124, 112, 112, 117, 120, 130, 114));
+}
+
+TEST(PoissonDistributionTest, AlgorithmExpectedValue_1) {
+ // This tests small values of the Knuth method.
+ // The underlying uniform distribution will generate exactly 0.5.
+ absl::random_internal::sequence_urbg urbg({0x8000000000000001ull});
+ absl::poisson_distribution<int> dist(5);
+ EXPECT_EQ(7, dist(urbg));
+}
+
+TEST(PoissonDistributionTest, AlgorithmExpectedValue_2) {
+ // This tests larger values of the Knuth method.
+ // The underlying uniform distribution will generate exactly 0.5.
+ absl::random_internal::sequence_urbg urbg({0x8000000000000001ull});
+ absl::poisson_distribution<int> dist(25);
+ EXPECT_EQ(36, dist(urbg));
+}
+
+TEST(PoissonDistributionTest, AlgorithmExpectedValue_3) {
+ // This variant uses the ratio of uniforms method.
+ absl::random_internal::sequence_urbg urbg(
+ {0x7fffffffffffffffull, 0x8000000000000000ull});
+
+ absl::poisson_distribution<int> dist(121);
+ EXPECT_EQ(121, dist(urbg));
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/random.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/random.h
new file mode 100644
index 00000000000..71b6309288e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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.
+//
+// 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);
+//
+// `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.
+//
+// Constructing two `absl::BitGen`s with the same seed sequence in the same
+// binary will produce the same sequence of variates within the same binary, but
+// need not do so across multiple binary invocations.
+//
+// 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. (See std_seed_seq.h for more information.)
+//
+// `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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.cc
new file mode 100644
index 00000000000..fdcb54a86cd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.cc
@@ -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.
+
+#include "absl/random/seed_gen_exception.h"
+
+#include <iostream>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+static constexpr const char kExceptionMessage[] =
+ "Failed generating seed-material for URBG.";
+
+SeedGenException::~SeedGenException() = default;
+
+const char* SeedGenException::what() const noexcept {
+ return kExceptionMessage;
+}
+
+namespace random_internal {
+
+void ThrowSeedGenException() {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw absl::SeedGenException();
+#else
+ std::cerr << kExceptionMessage << std::endl;
+ std::terminate();
+#endif
+}
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.h
new file mode 100644
index 00000000000..53539005643
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_gen_exception.h
@@ -0,0 +1,55 @@
+// 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: seed_gen_exception.h
+// -----------------------------------------------------------------------------
+//
+// This header defines an exception class which may be thrown if unpredictable
+// events prevent the derivation of suitable seed-material for constructing a
+// bit generator conforming to [rand.req.urng] (eg. entropy cannot be read from
+// /dev/urandom on a Unix-based system).
+//
+// Note: if exceptions are disabled, `std::terminate()` is called instead.
+
+#ifndef ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
+#define ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
+
+#include <exception>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+//------------------------------------------------------------------------------
+// SeedGenException
+//------------------------------------------------------------------------------
+class SeedGenException : public std::exception {
+ public:
+ SeedGenException() = default;
+ ~SeedGenException() override;
+ const char* what() const noexcept override;
+};
+
+namespace random_internal {
+
+// throw delegator
+[[noreturn]] void ThrowSeedGenException();
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_SEED_GEN_EXCEPTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.cc
new file mode 100644
index 00000000000..426eafd3c8d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.cc
@@ -0,0 +1,29 @@
+// 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.
+
+#include "absl/random/seed_sequences.h"
+
+#include "absl/random/internal/pool_urbg.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+SeedSeq MakeSeedSeq() {
+ SeedSeq::result_type seed_material[8];
+ random_internal::RandenPool<uint32_t>::Fill(absl::MakeSpan(seed_material));
+ return SeedSeq(std::begin(seed_material), std::end(seed_material));
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.h
new file mode 100644
index 00000000000..ff1340cc8ee
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences.h
@@ -0,0 +1,110 @@
+// 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: seed_sequences.h
+// -----------------------------------------------------------------------------
+//
+// This header contains utilities for creating and working with seed sequences
+// conforming to [rand.req.seedseq]. In general, direct construction of seed
+// sequences is discouraged, but use-cases for construction of identical bit
+// generators (using the same seed sequence) may be helpful (e.g. replaying a
+// simulation whose state is derived from variates of a bit generator).
+
+#ifndef ABSL_RANDOM_SEED_SEQUENCES_H_
+#define ABSL_RANDOM_SEED_SEQUENCES_H_
+
+#include <iterator>
+#include <random>
+
+#include "absl/random/internal/salted_seed_seq.h"
+#include "absl/random/internal/seed_material.h"
+#include "absl/random/seed_gen_exception.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// -----------------------------------------------------------------------------
+// absl::SeedSeq
+// -----------------------------------------------------------------------------
+//
+// `absl::SeedSeq` constructs a seed sequence according to [rand.req.seedseq]
+// for use within bit generators. `absl::SeedSeq`, unlike `std::seed_seq`
+// additionally salts the generated seeds with extra implementation-defined
+// entropy. For that reason, you can use `absl::SeedSeq` in combination with
+// standard library bit generators (e.g. `std::mt19937`) to introduce
+// non-determinism in your seeds.
+//
+// Example:
+//
+// absl::SeedSeq my_seed_seq({a, b, c});
+// std::mt19937 my_bitgen(my_seed_seq);
+//
+using SeedSeq = random_internal::SaltedSeedSeq<std::seed_seq>;
+
+// -----------------------------------------------------------------------------
+// absl::CreateSeedSeqFrom(bitgen*)
+// -----------------------------------------------------------------------------
+//
+// Constructs a seed sequence conforming to [rand.req.seedseq] using variates
+// produced by a provided bit generator.
+//
+// You should generally avoid direct construction of seed sequences, but
+// use-cases for reuse of a seed sequence to construct identical bit generators
+// may be helpful (eg. replaying a simulation whose state is derived from bit
+// generator values).
+//
+// If bitgen == nullptr, then behavior is undefined.
+//
+// Example:
+//
+// absl::BitGen my_bitgen;
+// auto seed_seq = absl::CreateSeedSeqFrom(&my_bitgen);
+// absl::BitGen new_engine(seed_seq); // derived from my_bitgen, but not
+// // correlated.
+//
+template <typename URBG>
+SeedSeq CreateSeedSeqFrom(URBG* urbg) {
+ SeedSeq::result_type
+ seed_material[random_internal::kEntropyBlocksNeeded];
+
+ if (!random_internal::ReadSeedMaterialFromURBG(
+ urbg, absl::MakeSpan(seed_material))) {
+ random_internal::ThrowSeedGenException();
+ }
+ return SeedSeq(std::begin(seed_material), std::end(seed_material));
+}
+
+// -----------------------------------------------------------------------------
+// absl::MakeSeedSeq()
+// -----------------------------------------------------------------------------
+//
+// Constructs an `absl::SeedSeq` salting the generated values using
+// implementation-defined entropy. The returned sequence can be used to create
+// equivalent bit generators correlated using this sequence.
+//
+// Example:
+//
+// auto my_seed_seq = absl::MakeSeedSeq();
+// std::mt19937 rng1(my_seed_seq);
+// std::mt19937 rng2(my_seed_seq);
+// EXPECT_EQ(rng1(), rng2());
+//
+SeedSeq MakeSeedSeq();
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_SEED_SEQUENCES_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences_test.cc
new file mode 100644
index 00000000000..fe1100bda0d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/seed_sequences_test.cc
@@ -0,0 +1,126 @@
+// 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.
+
+#include "absl/random/seed_sequences.h"
+
+#include <iterator>
+#include <random>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/random/internal/nonsecure_base.h"
+#include "absl/random/random.h"
+namespace {
+
+TEST(SeedSequences, Examples) {
+ {
+ absl::SeedSeq seed_seq({1, 2, 3});
+ absl::BitGen bitgen(seed_seq);
+
+ EXPECT_NE(0, bitgen());
+ }
+ {
+ absl::BitGen engine;
+ auto seed_seq = absl::CreateSeedSeqFrom(&engine);
+ absl::BitGen bitgen(seed_seq);
+
+ EXPECT_NE(engine(), bitgen());
+ }
+ {
+ auto seed_seq = absl::MakeSeedSeq();
+ std::mt19937 random(seed_seq);
+
+ EXPECT_NE(0, random());
+ }
+}
+
+TEST(CreateSeedSeqFrom, CompatibleWithStdTypes) {
+ using ExampleNonsecureURBG =
+ absl::random_internal::NonsecureURBGBase<std::minstd_rand0>;
+
+ // Construct a URBG instance.
+ ExampleNonsecureURBG rng;
+
+ // Construct a Seed Sequence from its variates.
+ auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
+
+ // Ensure that another URBG can be validly constructed from the Seed Sequence.
+ std::mt19937_64{seq_from_rng};
+}
+
+TEST(CreateSeedSeqFrom, CompatibleWithBitGenerator) {
+ // Construct a URBG instance.
+ absl::BitGen rng;
+
+ // Construct a Seed Sequence from its variates.
+ auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
+
+ // Ensure that another URBG can be validly constructed from the Seed Sequence.
+ std::mt19937_64{seq_from_rng};
+}
+
+TEST(CreateSeedSeqFrom, CompatibleWithInsecureBitGen) {
+ // Construct a URBG instance.
+ absl::InsecureBitGen rng;
+
+ // Construct a Seed Sequence from its variates.
+ auto seq_from_rng = absl::CreateSeedSeqFrom(&rng);
+
+ // Ensure that another URBG can be validly constructed from the Seed Sequence.
+ std::mt19937_64{seq_from_rng};
+}
+
+TEST(CreateSeedSeqFrom, CompatibleWithRawURBG) {
+ // Construct a URBG instance.
+ std::random_device urandom;
+
+ // Construct a Seed Sequence from its variates, using 64b of seed-material.
+ auto seq_from_rng = absl::CreateSeedSeqFrom(&urandom);
+
+ // Ensure that another URBG can be validly constructed from the Seed Sequence.
+ std::mt19937_64{seq_from_rng};
+}
+
+template <typename URBG>
+void TestReproducibleVariateSequencesForNonsecureURBG() {
+ const size_t kNumVariates = 1000;
+
+ URBG rng;
+ // Reused for both RNG instances.
+ auto reusable_seed = absl::CreateSeedSeqFrom(&rng);
+
+ typename URBG::result_type variates[kNumVariates];
+ {
+ URBG child(reusable_seed);
+ for (auto& variate : variates) {
+ variate = child();
+ }
+ }
+ // Ensure that variate-sequence can be "replayed" by identical RNG.
+ {
+ URBG child(reusable_seed);
+ for (auto& variate : variates) {
+ ASSERT_EQ(variate, child());
+ }
+ }
+}
+
+TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForInsecureBitGen) {
+ TestReproducibleVariateSequencesForNonsecureURBG<absl::InsecureBitGen>();
+}
+
+TEST(CreateSeedSeqFrom, ReproducesVariateSequencesForBitGenerator) {
+ TestReproducibleVariateSequencesForNonsecureURBG<absl::BitGen>();
+}
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution.h
new file mode 100644
index 00000000000..c1f54ccebce
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution.h
@@ -0,0 +1,275 @@
+// 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_int_distribution.h
+// -----------------------------------------------------------------------------
+//
+// This header defines a class for representing a uniform integer distribution
+// over the closed (inclusive) 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_int_distribution` is a drop-in replacement for the C++11
+// `std::uniform_int_distribution` [rand.dist.uni.int] but is considerably
+// faster than the libstdc++ implementation.
+
+#ifndef ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
+#define ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
+
+#include <cassert>
+#include <istream>
+#include <limits>
+#include <type_traits>
+
+#include "absl/base/optimization.h"
+#include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/iostream_state_saver.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/internal/wide_multiply.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::uniform_int_distribution<T>
+//
+// This distribution produces random integer values uniformly distributed in the
+// closed (inclusive) interval [a, b].
+//
+// Example:
+//
+// absl::BitGen gen;
+//
+// // Use the distribution to produce a value between 1 and 6, inclusive.
+// int die_roll = absl::uniform_int_distribution<int>(1, 6)(gen);
+//
+template <typename IntType = int>
+class 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 = uniform_int_distribution;
+
+ explicit param_type(
+ result_type lo = 0,
+ result_type hi = (std::numeric_limits<result_type>::max)())
+ : lo_(lo),
+ range_(static_cast<unsigned_type>(hi) -
+ static_cast<unsigned_type>(lo)) {
+ // [rand.dist.uni.int] precondition 2
+ assert(lo <= hi);
+ }
+
+ result_type a() const { return lo_; }
+ result_type b() const {
+ return static_cast<result_type>(static_cast<unsigned_type>(lo_) + range_);
+ }
+
+ friend bool operator==(const param_type& a, const param_type& b) {
+ return a.lo_ == b.lo_ && a.range_ == b.range_;
+ }
+
+ friend bool operator!=(const param_type& a, const param_type& b) {
+ return !(a == b);
+ }
+
+ private:
+ friend class uniform_int_distribution;
+ unsigned_type range() const { return range_; }
+
+ result_type lo_;
+ unsigned_type range_;
+
+ static_assert(std::is_integral<result_type>::value,
+ "Class-template absl::uniform_int_distribution<> must be "
+ "parameterized using an integral type.");
+ }; // param_type
+
+ uniform_int_distribution() : uniform_int_distribution(0) {}
+
+ explicit uniform_int_distribution(
+ result_type lo,
+ result_type hi = (std::numeric_limits<result_type>::max)())
+ : param_(lo, hi) {}
+
+ explicit uniform_int_distribution(const param_type& param) : param_(param) {}
+
+ // uniform_int_distribution<T>::reset()
+ //
+ // Resets the uniform int 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 (*this)(gen, param());
+ }
+
+ template <typename URBG>
+ result_type operator()(
+ URBG& gen, const param_type& param) { // NOLINT(runtime/references)
+ return param.a() + Generate(gen, param.range());
+ }
+
+ 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_int_distribution& a,
+ const uniform_int_distribution& b) {
+ return a.param_ == b.param_;
+ }
+ friend bool operator!=(const uniform_int_distribution& a,
+ const uniform_int_distribution& b) {
+ return !(a == b);
+ }
+
+ private:
+ // Generates a value in the *closed* interval [0, R]
+ template <typename URBG>
+ unsigned_type Generate(URBG& g, // NOLINT(runtime/references)
+ unsigned_type R);
+ param_type param_;
+};
+
+// -----------------------------------------------------------------------------
+// Implementation details follow
+// -----------------------------------------------------------------------------
+template <typename CharT, typename Traits, typename IntType>
+std::basic_ostream<CharT, Traits>& operator<<(
+ std::basic_ostream<CharT, Traits>& os,
+ const 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.a()) << os.fill()
+ << static_cast<stream_type>(x.b());
+ return os;
+}
+
+template <typename CharT, typename Traits, typename IntType>
+std::basic_istream<CharT, Traits>& operator>>(
+ std::basic_istream<CharT, Traits>& is,
+ uniform_int_distribution<IntType>& x) {
+ using param_type = typename uniform_int_distribution<IntType>::param_type;
+ using result_type = typename uniform_int_distribution<IntType>::result_type;
+ using stream_type =
+ typename random_internal::stream_format_type<IntType>::type;
+
+ stream_type a;
+ stream_type b;
+
+ auto saver = random_internal::make_istream_state_saver(is);
+ is >> a >> b;
+ if (!is.fail()) {
+ x.param(
+ param_type(static_cast<result_type>(a), static_cast<result_type>(b)));
+ }
+ return is;
+}
+
+template <typename IntType>
+template <typename URBG>
+typename random_internal::make_unsigned_bits<IntType>::type
+uniform_int_distribution<IntType>::Generate(
+ URBG& g, // NOLINT(runtime/references)
+ typename random_internal::make_unsigned_bits<IntType>::type R) {
+ random_internal::FastUniformBits<unsigned_type> fast_bits;
+ unsigned_type bits = fast_bits(g);
+ const unsigned_type Lim = R + 1;
+ if ((R & Lim) == 0) {
+ // If the interval's length is a power of two range, just take the low bits.
+ return bits & R;
+ }
+
+ // Generates a uniform variate on [0, Lim) using fixed-point multiplication.
+ // The above fast-path guarantees that Lim is representable in unsigned_type.
+ //
+ // Algorithm adapted from
+ // http://lemire.me/blog/2016/06/30/fast-random-shuffling/, with added
+ // explanation.
+ //
+ // The algorithm creates a uniform variate `bits` in the interval [0, 2^N),
+ // and treats it as the fractional part of a fixed-point real value in [0, 1),
+ // multiplied by 2^N. For example, 0.25 would be represented as 2^(N - 2),
+ // because 2^N * 0.25 == 2^(N - 2).
+ //
+ // Next, `bits` and `Lim` are multiplied with a wide-multiply to bring the
+ // value into the range [0, Lim). The integral part (the high word of the
+ // multiplication result) is then very nearly the desired result. However,
+ // this is not quite accurate; viewing the multiplication result as one
+ // double-width integer, the resulting values for the sample are mapped as
+ // follows:
+ //
+ // If the result lies in this interval: Return this value:
+ // [0, 2^N) 0
+ // [2^N, 2 * 2^N) 1
+ // ... ...
+ // [K * 2^N, (K + 1) * 2^N) K
+ // ... ...
+ // [(Lim - 1) * 2^N, Lim * 2^N) Lim - 1
+ //
+ // While all of these intervals have the same size, the result of `bits * Lim`
+ // must be a multiple of `Lim`, and not all of these intervals contain the
+ // same number of multiples of `Lim`. In particular, some contain
+ // `F = floor(2^N / Lim)` and some contain `F + 1 = ceil(2^N / Lim)`. This
+ // difference produces a small nonuniformity, which is corrected by applying
+ // rejection sampling to one of the values in the "larger intervals" (i.e.,
+ // the intervals containing `F + 1` multiples of `Lim`.
+ //
+ // An interval contains `F + 1` multiples of `Lim` if and only if its smallest
+ // value modulo 2^N is less than `2^N % Lim`. The unique value satisfying
+ // this property is used as the one for rejection. That is, a value of
+ // `bits * Lim` is rejected if `(bit * Lim) % 2^N < (2^N % Lim)`.
+
+ using helper = random_internal::wide_multiply<unsigned_type>;
+ auto product = helper::multiply(bits, Lim);
+
+ // Two optimizations here:
+ // * Rejection occurs with some probability less than 1/2, and for reasonable
+ // ranges considerably less (in particular, less than 1/(F+1)), so
+ // ABSL_PREDICT_FALSE is apt.
+ // * `Lim` is an overestimate of `threshold`, and doesn't require a divide.
+ if (ABSL_PREDICT_FALSE(helper::lo(product) < Lim)) {
+ // This quantity is exactly equal to `2^N % Lim`, but does not require high
+ // precision calculations: `2^N % Lim` is congruent to `(2^N - Lim) % Lim`.
+ // Ideally this could be expressed simply as `-X` rather than `2^N - X`, but
+ // for types smaller than int, this calculation is incorrect due to integer
+ // promotion rules.
+ const unsigned_type threshold =
+ ((std::numeric_limits<unsigned_type>::max)() - Lim + 1) % Lim;
+ while (helper::lo(product) < threshold) {
+ bits = fast_bits(g);
+ product = helper::multiply(bits, Lim);
+ }
+ }
+
+ return helper::hi(product);
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_UNIFORM_INT_DISTRIBUTION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution_test.cc
new file mode 100644
index 00000000000..276d72ad204
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_int_distribution_test.cc
@@ -0,0 +1,259 @@
+// 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.
+
+#include "absl/random/uniform_int_distribution.h"
+
+#include <cmath>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <sstream>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+
+template <typename IntType>
+class UniformIntDistributionTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<int8_t, uint8_t, int16_t, uint16_t, int32_t,
+ uint32_t, int64_t, uint64_t>;
+TYPED_TEST_SUITE(UniformIntDistributionTest, IntTypes);
+
+TYPED_TEST(UniformIntDistributionTest, ParamSerializeTest) {
+ // This test essentially ensures that the parameters serialize,
+ // not that the values generated cover the full range.
+ using Limits = std::numeric_limits<TypeParam>;
+ using param_type =
+ typename absl::uniform_int_distribution<TypeParam>::param_type;
+ const TypeParam kMin = std::is_unsigned<TypeParam>::value ? 37 : -105;
+ const TypeParam kNegOneOrZero = std::is_unsigned<TypeParam>::value ? 0 : -1;
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ for (const auto& param : {
+ param_type(),
+ param_type(2, 2), // Same
+ param_type(9, 32),
+ param_type(kMin, 115),
+ param_type(kNegOneOrZero, Limits::max()),
+ param_type(Limits::min(), Limits::max()),
+ param_type(Limits::lowest(), Limits::max()),
+ param_type(Limits::min() + 1, Limits::max() - 1),
+ }) {
+ const auto a = param.a();
+ const auto b = param.b();
+ absl::uniform_int_distribution<TypeParam> before(a, b);
+ EXPECT_EQ(before.a(), param.a());
+ EXPECT_EQ(before.b(), param.b());
+
+ {
+ // Initialize via param_type
+ absl::uniform_int_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ }
+
+ // Initialize via iostreams
+ std::stringstream ss;
+ ss << before;
+
+ absl::uniform_int_distribution<TypeParam> after(Limits::min() + 3,
+ Limits::max() - 5);
+
+ EXPECT_NE(before.a(), after.a());
+ EXPECT_NE(before.b(), after.b());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.a(), after.a());
+ EXPECT_EQ(before.b(), after.b());
+ EXPECT_EQ(before.param(), after.param());
+ EXPECT_EQ(before, after);
+
+ // Smoke test.
+ auto sample_min = after.max();
+ auto sample_max = after.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = after(gen);
+ EXPECT_GE(sample, after.min());
+ EXPECT_LE(sample, after.max());
+ if (sample > sample_max) {
+ sample_max = sample;
+ }
+ if (sample < sample_min) {
+ sample_min = sample;
+ }
+ }
+ std::string msg = absl::StrCat("Range: ", +sample_min, ", ", +sample_max);
+ ABSL_RAW_LOG(INFO, "%s", msg.c_str());
+ }
+}
+
+TYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) {
+#if GTEST_HAS_DEATH_TEST
+ // Hi < Lo
+ EXPECT_DEBUG_DEATH({ absl::uniform_int_distribution<TypeParam> dist(10, 1); },
+ "");
+#endif // GTEST_HAS_DEATH_TEST
+#if defined(NDEBUG)
+ // opt-mode, for invalid parameters, will generate a garbage value,
+ // but should not enter an infinite loop.
+ absl::InsecureBitGen gen;
+ absl::uniform_int_distribution<TypeParam> dist(10, 1);
+ auto x = dist(gen);
+
+ // Any value will generate a non-empty string.
+ EXPECT_FALSE(absl::StrCat(+x).empty()) << x;
+#endif // NDEBUG
+}
+
+TYPED_TEST(UniformIntDistributionTest, TestMoments) {
+ constexpr int kSize = 100000;
+ using Limits = std::numeric_limits<TypeParam>;
+ using param_type =
+ typename absl::uniform_int_distribution<TypeParam>::param_type;
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
+ std::vector<double> values(kSize);
+ for (const auto& param :
+ {param_type(0, Limits::max()), param_type(13, 127)}) {
+ absl::uniform_int_distribution<TypeParam> dist(param);
+ for (int i = 0; i < kSize; i++) {
+ const auto sample = dist(rng);
+ ASSERT_LE(dist.param().a(), sample);
+ ASSERT_GE(dist.param().b(), sample);
+ values[i] = sample;
+ }
+
+ auto moments = absl::random_internal::ComputeDistributionMoments(values);
+ const double a = dist.param().a();
+ const double b = dist.param().b();
+ const double n = (b - a + 1);
+ const double mean = (a + b) / 2;
+ const double var = ((b - a + 1) * (b - a + 1) - 1) / 12;
+ const double kurtosis = 3 - 6 * (n * n + 1) / (5 * (n * n - 1));
+
+ // TODO(ahh): this is not the right bound
+ // empirically validated with --runs_per_test=10000.
+ EXPECT_NEAR(mean, moments.mean, 0.01 * var);
+ EXPECT_NEAR(var, moments.variance, 0.015 * var);
+ EXPECT_NEAR(0.0, moments.skewness, 0.025);
+ EXPECT_NEAR(kurtosis, moments.kurtosis, 0.02 * kurtosis);
+ }
+}
+
+TYPED_TEST(UniformIntDistributionTest, ChiSquaredTest50) {
+ using absl::random_internal::kChiSquared;
+
+ constexpr size_t kTrials = 1000;
+ constexpr int kBuckets = 50; // inclusive, so actally +1
+ constexpr double kExpected =
+ static_cast<double>(kTrials) / static_cast<double>(kBuckets);
+
+ // Empirically validated with --runs_per_test=10000.
+ const int kThreshold =
+ absl::random_internal::ChiSquareValue(kBuckets, 0.999999);
+
+ const TypeParam min = std::is_unsigned<TypeParam>::value ? 37 : -37;
+ const TypeParam max = min + kBuckets;
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
+ absl::uniform_int_distribution<TypeParam> dist(min, max);
+
+ std::vector<int32_t> counts(kBuckets + 1, 0);
+ for (size_t i = 0; i < kTrials; i++) {
+ auto x = dist(rng);
+ counts[x - min]++;
+ }
+ double chi_square = absl::random_internal::ChiSquareWithExpected(
+ std::begin(counts), std::end(counts), kExpected);
+ if (chi_square > kThreshold) {
+ double p_value =
+ absl::random_internal::ChiSquarePValue(chi_square, kBuckets);
+
+ // Chi-squared test failed. Output does not appear to be uniform.
+ std::string msg;
+ for (const auto& a : counts) {
+ absl::StrAppend(&msg, a, "\n");
+ }
+ absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n");
+ absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ",
+ kThreshold);
+ ABSL_RAW_LOG(INFO, "%s", msg.c_str());
+ FAIL() << msg;
+ }
+}
+
+TEST(UniformIntDistributionTest, StabilityTest) {
+ // absl::uniform_int_distribution stability relies only on integer operations.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(12);
+
+ {
+ absl::uniform_int_distribution<int32_t> dist(0, 4);
+ for (auto& v : output) {
+ v = dist(urbg);
+ }
+ }
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_THAT(output, testing::ElementsAre(4, 4, 3, 2, 1, 0, 1, 4, 3, 1, 3, 1));
+
+ {
+ urbg.reset();
+ absl::uniform_int_distribution<int32_t> dist(0, 100);
+ for (auto& v : output) {
+ v = dist(urbg);
+ }
+ }
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_THAT(output, testing::ElementsAre(97, 86, 75, 41, 36, 16, 38, 92, 67,
+ 30, 80, 38));
+
+ {
+ urbg.reset();
+ absl::uniform_int_distribution<int32_t> dist(0, 10000);
+ for (auto& v : output) {
+ v = dist(urbg);
+ }
+ }
+ EXPECT_EQ(12, urbg.invocations());
+ EXPECT_THAT(output, testing::ElementsAre(9648, 8562, 7439, 4089, 3571, 1602,
+ 3813, 9195, 6641, 2986, 7956, 3765));
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution.h
new file mode 100644
index 00000000000..5ba17b2341c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/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)());
+ assert(std::isfinite(range_));
+ }
+
+ 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution_test.cc
new file mode 100644
index 00000000000..18bcd3bce88
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/uniform_real_distribution_test.cc
@@ -0,0 +1,349 @@
+// 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.
+
+#include "absl/random/uniform_real_distribution.h"
+
+#include <cmath>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/numeric/internal/representation.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/distribution_test_util.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+
+// NOTES:
+// * Some documentation on generating random real values suggests that
+// it is possible to use std::nextafter(b, DBL_MAX) to generate a value on
+// the closed range [a, b]. Unfortunately, that technique is not universally
+// reliable due to floating point quantization.
+//
+// * absl::uniform_real_distribution<float> generates between 2^28 and 2^29
+// distinct floating point values in the range [0, 1).
+//
+// * absl::uniform_real_distribution<float> generates at least 2^23 distinct
+// floating point values in the range [1, 2). This should be the same as
+// any other range covered by a single exponent in IEEE 754.
+//
+// * absl::uniform_real_distribution<double> generates more than 2^52 distinct
+// values in the range [0, 1), and should generate at least 2^52 distinct
+// values in the range of [1, 2).
+//
+
+namespace {
+
+template <typename RealType>
+class UniformRealDistributionTest : public ::testing::Test {};
+
+// double-double arithmetic is not supported well by either GCC or Clang; see
+// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048,
+// https://bugs.llvm.org/show_bug.cgi?id=49131, and
+// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests
+// with double doubles until compiler support is better.
+using RealTypes =
+ std::conditional<absl::numeric_internal::IsDoubleDouble(),
+ ::testing::Types<float, double>,
+ ::testing::Types<float, double, long double>>::type;
+
+TYPED_TEST_SUITE(UniformRealDistributionTest, RealTypes);
+
+TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) {
+ using param_type =
+ typename absl::uniform_real_distribution<TypeParam>::param_type;
+
+ constexpr const TypeParam a{1152921504606846976};
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ for (const auto& param : {
+ param_type(),
+ param_type(TypeParam(2.0), TypeParam(2.0)), // Same
+ param_type(TypeParam(-0.1), TypeParam(0.1)),
+ param_type(TypeParam(0.05), TypeParam(0.12)),
+ param_type(TypeParam(-0.05), TypeParam(0.13)),
+ param_type(TypeParam(-0.05), TypeParam(-0.02)),
+ // double range = 0
+ // 2^60 , 2^60 + 2^6
+ param_type(a, TypeParam(1152921504606847040)),
+ // 2^60 , 2^60 + 2^7
+ param_type(a, TypeParam(1152921504606847104)),
+ // double range = 2^8
+ // 2^60 , 2^60 + 2^8
+ param_type(a, TypeParam(1152921504606847232)),
+ // float range = 0
+ // 2^60 , 2^60 + 2^36
+ param_type(a, TypeParam(1152921573326323712)),
+ // 2^60 , 2^60 + 2^37
+ param_type(a, TypeParam(1152921642045800448)),
+ // float range = 2^38
+ // 2^60 , 2^60 + 2^38
+ param_type(a, TypeParam(1152921779484753920)),
+ // Limits
+ param_type(0, std::numeric_limits<TypeParam>::max()),
+ param_type(std::numeric_limits<TypeParam>::lowest(), 0),
+ param_type(0, std::numeric_limits<TypeParam>::epsilon()),
+ param_type(-std::numeric_limits<TypeParam>::epsilon(),
+ std::numeric_limits<TypeParam>::epsilon()),
+ param_type(std::numeric_limits<TypeParam>::epsilon(),
+ 2 * std::numeric_limits<TypeParam>::epsilon()),
+ }) {
+ // Validate parameters.
+ const auto a = param.a();
+ const auto b = param.b();
+ absl::uniform_real_distribution<TypeParam> before(a, b);
+ EXPECT_EQ(before.a(), param.a());
+ EXPECT_EQ(before.b(), param.b());
+
+ {
+ absl::uniform_real_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ }
+
+ std::stringstream ss;
+ ss << before;
+ absl::uniform_real_distribution<TypeParam> after(TypeParam(1.0),
+ TypeParam(3.1));
+
+ EXPECT_NE(before.a(), after.a());
+ EXPECT_NE(before.b(), after.b());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.a(), after.a());
+ EXPECT_EQ(before.b(), after.b());
+ EXPECT_EQ(before.param(), after.param());
+ EXPECT_EQ(before, after);
+
+ // Smoke test.
+ auto sample_min = after.max();
+ auto sample_max = after.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = after(gen);
+ // Failure here indicates a bug in uniform_real_distribution::operator(),
+ // or bad parameters--range too large, etc.
+ if (after.min() == after.max()) {
+ EXPECT_EQ(sample, after.min());
+ } else {
+ EXPECT_GE(sample, after.min());
+ EXPECT_LT(sample, after.max());
+ }
+ if (sample > sample_max) {
+ sample_max = sample;
+ }
+ if (sample < sample_min) {
+ sample_min = sample;
+ }
+ }
+
+ if (!std::is_same<TypeParam, long double>::value) {
+ // static_cast<double>(long double) can overflow.
+ std::string msg = absl::StrCat("Range: ", static_cast<double>(sample_min),
+ ", ", static_cast<double>(sample_max));
+ ABSL_RAW_LOG(INFO, "%s", msg.c_str());
+ }
+ }
+}
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4756) // Constant arithmetic overflow.
+#endif
+TYPED_TEST(UniformRealDistributionTest, ViolatesPreconditionsDeathTest) {
+#if GTEST_HAS_DEATH_TEST
+ // Hi < Lo
+ EXPECT_DEBUG_DEATH(
+ { absl::uniform_real_distribution<TypeParam> dist(10.0, 1.0); }, "");
+
+ // Hi - Lo > numeric_limits<>::max()
+ EXPECT_DEBUG_DEATH(
+ {
+ absl::uniform_real_distribution<TypeParam> dist(
+ std::numeric_limits<TypeParam>::lowest(),
+ std::numeric_limits<TypeParam>::max());
+ },
+ "");
+#endif // GTEST_HAS_DEATH_TEST
+#if defined(NDEBUG)
+ // opt-mode, for invalid parameters, will generate a garbage value,
+ // but should not enter an infinite loop.
+ absl::InsecureBitGen gen;
+ {
+ absl::uniform_real_distribution<TypeParam> dist(10.0, 1.0);
+ auto x = dist(gen);
+ EXPECT_FALSE(std::isnan(x)) << x;
+ }
+ {
+ absl::uniform_real_distribution<TypeParam> dist(
+ std::numeric_limits<TypeParam>::lowest(),
+ std::numeric_limits<TypeParam>::max());
+ auto x = dist(gen);
+ // Infinite result.
+ EXPECT_FALSE(std::isfinite(x)) << x;
+ }
+#endif // NDEBUG
+}
+#ifdef _MSC_VER
+#pragma warning(pop) // warning(disable:4756)
+#endif
+
+TYPED_TEST(UniformRealDistributionTest, TestMoments) {
+ constexpr int kSize = 1000000;
+ std::vector<double> values(kSize);
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
+ absl::uniform_real_distribution<TypeParam> dist;
+ for (int i = 0; i < kSize; i++) {
+ values[i] = dist(rng);
+ }
+
+ const auto moments =
+ absl::random_internal::ComputeDistributionMoments(values);
+ EXPECT_NEAR(0.5, moments.mean, 0.01);
+ EXPECT_NEAR(1 / 12.0, moments.variance, 0.015);
+ EXPECT_NEAR(0.0, moments.skewness, 0.02);
+ EXPECT_NEAR(9 / 5.0, moments.kurtosis, 0.015);
+}
+
+TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) {
+ using absl::random_internal::kChiSquared;
+ using param_type =
+ typename absl::uniform_real_distribution<TypeParam>::param_type;
+
+ constexpr size_t kTrials = 100000;
+ constexpr int kBuckets = 50;
+ constexpr double kExpected =
+ static_cast<double>(kTrials) / static_cast<double>(kBuckets);
+
+ // 1-in-100000 threshold, but remember, there are about 8 tests
+ // in this file. And the test could fail for other reasons.
+ // Empirically validated with --runs_per_test=10000.
+ const int kThreshold =
+ absl::random_internal::ChiSquareValue(kBuckets - 1, 0.999999);
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng{0x2B7E151628AED2A6};
+
+ for (const auto& param : {param_type(0, 1), param_type(5, 12),
+ param_type(-5, 13), param_type(-5, -2)}) {
+ const double min_val = param.a();
+ const double max_val = param.b();
+ const double factor = kBuckets / (max_val - min_val);
+
+ std::vector<int32_t> counts(kBuckets, 0);
+ absl::uniform_real_distribution<TypeParam> dist(param);
+ for (size_t i = 0; i < kTrials; i++) {
+ auto x = dist(rng);
+ auto bucket = static_cast<size_t>((x - min_val) * factor);
+ counts[bucket]++;
+ }
+
+ double chi_square = absl::random_internal::ChiSquareWithExpected(
+ std::begin(counts), std::end(counts), kExpected);
+ if (chi_square > kThreshold) {
+ double p_value =
+ absl::random_internal::ChiSquarePValue(chi_square, kBuckets);
+
+ // Chi-squared test failed. Output does not appear to be uniform.
+ std::string msg;
+ for (const auto& a : counts) {
+ absl::StrAppend(&msg, a, "\n");
+ }
+ absl::StrAppend(&msg, kChiSquared, " p-value ", p_value, "\n");
+ absl::StrAppend(&msg, "High ", kChiSquared, " value: ", chi_square, " > ",
+ kThreshold);
+ ABSL_RAW_LOG(INFO, "%s", msg.c_str());
+ FAIL() << msg;
+ }
+ }
+}
+
+TYPED_TEST(UniformRealDistributionTest, StabilityTest) {
+ // absl::uniform_real_distribution stability relies only on
+ // random_internal::RandU64ToDouble and random_internal::RandU64ToFloat.
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(12);
+
+ absl::uniform_real_distribution<TypeParam> dist;
+ std::generate(std::begin(output), std::end(output), [&] {
+ return static_cast<int>(TypeParam(1000000) * dist(urbg));
+ });
+
+ EXPECT_THAT(
+ output, //
+ testing::ElementsAre(59, 999246, 762494, 395876, 167716, 82545, 925251,
+ 77341, 12527, 708791, 834451, 932808));
+}
+
+TEST(UniformRealDistributionTest, AlgorithmBounds) {
+ absl::uniform_real_distribution<double> dist;
+
+ {
+ // This returns the smallest value >0 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0x0000000000000001ull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 5.42101086242752217004e-20);
+ }
+
+ {
+ // This returns a value very near 0.5 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0x7fffffffffffffefull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 0.499999999999999944489);
+ }
+ {
+ // This returns a value very near 0.5 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0x8000000000000000ull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 0.5);
+ }
+
+ {
+ // This returns the largest value <1 from absl::uniform_real_distribution.
+ absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFEFull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 0.999999999999999888978);
+ }
+ {
+ // This *ALSO* returns the largest value <1.
+ absl::random_internal::sequence_urbg urbg({0xFFFFFFFFFFFFFFFFull});
+ double a = dist(urbg);
+ EXPECT_EQ(a, 0.999999999999999888978);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution.h
new file mode 100644
index 00000000000..22ebc756cfe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution.h
@@ -0,0 +1,271 @@
+// 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/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 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(std::is_integral<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 > 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution_test.cc
new file mode 100644
index 00000000000..f8cf70e0ddd
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/random/zipf_distribution_test.cc
@@ -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.
+
+#include "absl/random/zipf_distribution.h"
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <random>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/random/internal/chi_square.h"
+#include "absl/random/internal/pcg_engine.h"
+#include "absl/random/internal/sequence_urbg.h"
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/strip.h"
+
+namespace {
+
+using ::absl::random_internal::kChiSquared;
+using ::testing::ElementsAre;
+
+template <typename IntType>
+class ZipfDistributionTypedTest : public ::testing::Test {};
+
+using IntTypes = ::testing::Types<int, int8_t, int16_t, int32_t, int64_t,
+ uint8_t, uint16_t, uint32_t, uint64_t>;
+TYPED_TEST_CASE(ZipfDistributionTypedTest, IntTypes);
+
+TYPED_TEST(ZipfDistributionTypedTest, SerializeTest) {
+ using param_type = typename absl::zipf_distribution<TypeParam>::param_type;
+
+ constexpr int kCount = 1000;
+ absl::InsecureBitGen gen;
+ for (const auto& param : {
+ param_type(),
+ param_type(32),
+ param_type(100, 3, 2),
+ param_type(std::numeric_limits<TypeParam>::max(), 4, 3),
+ param_type(std::numeric_limits<TypeParam>::max() / 2),
+ }) {
+ // Validate parameters.
+ const auto k = param.k();
+ const auto q = param.q();
+ const auto v = param.v();
+
+ absl::zipf_distribution<TypeParam> before(k, q, v);
+ EXPECT_EQ(before.k(), param.k());
+ EXPECT_EQ(before.q(), param.q());
+ EXPECT_EQ(before.v(), param.v());
+
+ {
+ absl::zipf_distribution<TypeParam> via_param(param);
+ EXPECT_EQ(via_param, before);
+ }
+
+ // Validate stream serialization.
+ std::stringstream ss;
+ ss << before;
+ absl::zipf_distribution<TypeParam> after(4, 5.5, 4.4);
+
+ EXPECT_NE(before.k(), after.k());
+ EXPECT_NE(before.q(), after.q());
+ EXPECT_NE(before.v(), after.v());
+ EXPECT_NE(before.param(), after.param());
+ EXPECT_NE(before, after);
+
+ ss >> after;
+
+ EXPECT_EQ(before.k(), after.k());
+ EXPECT_EQ(before.q(), after.q());
+ EXPECT_EQ(before.v(), after.v());
+ EXPECT_EQ(before.param(), after.param());
+ EXPECT_EQ(before, after);
+
+ // Smoke test.
+ auto sample_min = after.max();
+ auto sample_max = after.min();
+ for (int i = 0; i < kCount; i++) {
+ auto sample = after(gen);
+ EXPECT_GE(sample, after.min());
+ EXPECT_LE(sample, after.max());
+ if (sample > sample_max) sample_max = sample;
+ if (sample < sample_min) sample_min = sample;
+ }
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("Range: ", +sample_min, ", ", +sample_max));
+ }
+}
+
+class ZipfModel {
+ public:
+ ZipfModel(size_t k, double q, double v) : k_(k), q_(q), v_(v) {}
+
+ double mean() const { return mean_; }
+
+ // For the other moments of the Zipf distribution, see, for example,
+ // http://mathworld.wolfram.com/ZipfDistribution.html
+
+ // PMF(k) = (1 / k^s) / H(N,s)
+ // Returns the probability that any single invocation returns k.
+ double PMF(size_t i) { return i >= hnq_.size() ? 0.0 : hnq_[i] / sum_hnq_; }
+
+ // CDF = H(k, s) / H(N,s)
+ double CDF(size_t i) {
+ if (i >= hnq_.size()) {
+ return 1.0;
+ }
+ auto it = std::begin(hnq_);
+ double h = 0.0;
+ for (const auto end = it; it != end; it++) {
+ h += *it;
+ }
+ return h / sum_hnq_;
+ }
+
+ // The InverseCDF returns the k values which bound p on the upper and lower
+ // bound. Since there is no closed-form solution, this is implemented as a
+ // bisction of the cdf.
+ std::pair<size_t, size_t> InverseCDF(double p) {
+ size_t min = 0;
+ size_t max = hnq_.size();
+ while (max > min + 1) {
+ size_t target = (max + min) >> 1;
+ double x = CDF(target);
+ if (x > p) {
+ max = target;
+ } else {
+ min = target;
+ }
+ }
+ return {min, max};
+ }
+
+ // Compute the probability totals, which are based on the generalized harmonic
+ // number, H(N,s).
+ // H(N,s) == SUM(k=1..N, 1 / k^s)
+ //
+ // In the limit, H(N,s) == zetac(s) + 1.
+ //
+ // NOTE: The mean of a zipf distribution could be computed here as well.
+ // Mean := H(N, s-1) / H(N,s).
+ // Given the parameter v = 1, this gives the following function:
+ // (Hn(100, 1) - Hn(1,1)) / (Hn(100,2) - Hn(1,2)) = 6.5944
+ //
+ void Init() {
+ if (!hnq_.empty()) {
+ return;
+ }
+ hnq_.clear();
+ hnq_.reserve(std::min(k_, size_t{1000}));
+
+ sum_hnq_ = 0;
+ double qm1 = q_ - 1.0;
+ double sum_hnq_m1 = 0;
+ for (size_t i = 0; i < k_; i++) {
+ // Partial n-th generalized harmonic number
+ const double x = v_ + i;
+
+ // H(n, q-1)
+ const double hnqm1 =
+ (q_ == 2.0) ? (1.0 / x)
+ : (q_ == 3.0) ? (1.0 / (x * x)) : std::pow(x, -qm1);
+ sum_hnq_m1 += hnqm1;
+
+ // H(n, q)
+ const double hnq =
+ (q_ == 2.0) ? (1.0 / (x * x))
+ : (q_ == 3.0) ? (1.0 / (x * x * x)) : std::pow(x, -q_);
+ sum_hnq_ += hnq;
+ hnq_.push_back(hnq);
+ if (i > 1000 && hnq <= 1e-10) {
+ // The harmonic number is too small.
+ break;
+ }
+ }
+ assert(sum_hnq_ > 0);
+ mean_ = sum_hnq_m1 / sum_hnq_;
+ }
+
+ private:
+ const size_t k_;
+ const double q_;
+ const double v_;
+
+ double mean_;
+ std::vector<double> hnq_;
+ double sum_hnq_;
+};
+
+using zipf_u64 = absl::zipf_distribution<uint64_t>;
+
+class ZipfTest : public testing::TestWithParam<zipf_u64::param_type>,
+ public ZipfModel {
+ public:
+ ZipfTest() : ZipfModel(GetParam().k(), GetParam().q(), GetParam().v()) {}
+
+ // We use a fixed bit generator for distribution accuracy tests. This allows
+ // these tests to be deterministic, while still testing the qualify of the
+ // implementation.
+ absl::random_internal::pcg64_2018_engine rng_{0x2B7E151628AED2A6};
+};
+
+TEST_P(ZipfTest, ChiSquaredTest) {
+ const auto& param = GetParam();
+ Init();
+
+ size_t trials = 10000;
+
+ // Find the split-points for the buckets.
+ std::vector<size_t> points;
+ std::vector<double> expected;
+ {
+ double last_cdf = 0.0;
+ double min_p = 1.0;
+ for (double p = 0.01; p < 1.0; p += 0.01) {
+ auto x = InverseCDF(p);
+ if (points.empty() || points.back() < x.second) {
+ const double p = CDF(x.second);
+ points.push_back(x.second);
+ double q = p - last_cdf;
+ expected.push_back(q);
+ last_cdf = p;
+ if (q < min_p) {
+ min_p = q;
+ }
+ }
+ }
+ if (last_cdf < 0.999) {
+ points.push_back(std::numeric_limits<size_t>::max());
+ double q = 1.0 - last_cdf;
+ expected.push_back(q);
+ if (q < min_p) {
+ min_p = q;
+ }
+ } else {
+ points.back() = std::numeric_limits<size_t>::max();
+ expected.back() += (1.0 - last_cdf);
+ }
+ // The Chi-Squared score is not completely scale-invariant; it works best
+ // when the small values are in the small digits.
+ trials = static_cast<size_t>(8.0 / min_p);
+ }
+ ASSERT_GT(points.size(), 0);
+
+ // Generate n variates and fill the counts vector with the count of their
+ // occurrences.
+ std::vector<int64_t> buckets(points.size(), 0);
+ double avg = 0;
+ {
+ zipf_u64 dis(param);
+ for (size_t i = 0; i < trials; i++) {
+ uint64_t x = dis(rng_);
+ ASSERT_LE(x, dis.max());
+ ASSERT_GE(x, dis.min());
+ avg += static_cast<double>(x);
+ auto it = std::upper_bound(std::begin(points), std::end(points),
+ static_cast<size_t>(x));
+ buckets[std::distance(std::begin(points), it)]++;
+ }
+ avg = avg / static_cast<double>(trials);
+ }
+
+ // Validate the output using the Chi-Squared test.
+ for (auto& e : expected) {
+ e *= trials;
+ }
+
+ // The null-hypothesis is that the distribution is a poisson distribution with
+ // the provided mean (not estimated from the data).
+ const int dof = static_cast<int>(expected.size()) - 1;
+
+ // NOTE: This test runs about 15x per invocation, so a value of 0.9995 is
+ // approximately correct for a test suite failure rate of 1 in 100. In
+ // practice we see failures slightly higher than that.
+ const double threshold = absl::random_internal::ChiSquareValue(dof, 0.9999);
+
+ const double chi_square = absl::random_internal::ChiSquare(
+ std::begin(buckets), std::end(buckets), std::begin(expected),
+ std::end(expected));
+
+ const double p_actual =
+ absl::random_internal::ChiSquarePValue(chi_square, dof);
+
+ // Log if the chi_squared value is above the threshold.
+ if (chi_square > threshold) {
+ ABSL_INTERNAL_LOG(INFO, "values");
+ for (size_t i = 0; i < expected.size(); i++) {
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat(points[i], ": ", buckets[i],
+ " vs. E=", expected[i]));
+ }
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat("trials ", trials));
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("mean ", avg, " vs. expected ", mean()));
+ ABSL_INTERNAL_LOG(INFO, absl::StrCat(kChiSquared, "(data, ", dof, ") = ",
+ chi_square, " (", p_actual, ")"));
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat(kChiSquared, " @ 0.9995 = ", threshold));
+ FAIL() << kChiSquared << " value of " << chi_square
+ << " is above the threshold.";
+ }
+}
+
+std::vector<zipf_u64::param_type> GenParams() {
+ using param = zipf_u64::param_type;
+ const auto k = param().k();
+ const auto q = param().q();
+ const auto v = param().v();
+ const uint64_t k2 = 1 << 10;
+ return std::vector<zipf_u64::param_type>{
+ // Default
+ param(k, q, v),
+ // vary K
+ param(4, q, v), param(1 << 4, q, v), param(k2, q, v),
+ // vary V
+ param(k2, q, 0.5), param(k2, q, 1.5), param(k2, q, 2.5), param(k2, q, 10),
+ // vary Q
+ param(k2, 1.5, v), param(k2, 3, v), param(k2, 5, v), param(k2, 10, v),
+ // Vary V & Q
+ param(k2, 1.5, 0.5), param(k2, 3, 1.5), param(k, 10, 10)};
+}
+
+std::string ParamName(
+ const ::testing::TestParamInfo<zipf_u64::param_type>& info) {
+ const auto& p = info.param;
+ std::string name = absl::StrCat("k_", p.k(), "__q_", absl::SixDigits(p.q()),
+ "__v_", absl::SixDigits(p.v()));
+ return absl::StrReplaceAll(name, {{"+", "_"}, {"-", "_"}, {".", "_"}});
+}
+
+INSTANTIATE_TEST_SUITE_P(All, ZipfTest, ::testing::ValuesIn(GenParams()),
+ ParamName);
+
+// NOTE: absl::zipf_distribution is not guaranteed to be stable.
+TEST(ZipfDistributionTest, StabilityTest) {
+ // absl::zipf_distribution stability relies on
+ // absl::uniform_real_distribution, std::log, std::exp, std::log1p
+ absl::random_internal::sequence_urbg urbg(
+ {0x0003eb76f6f7f755ull, 0xFFCEA50FDB2F953Bull, 0xC332DDEFBE6C5AA5ull,
+ 0x6558218568AB9702ull, 0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull,
+ 0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
+ 0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
+
+ std::vector<int> output(10);
+
+ {
+ absl::zipf_distribution<int32_t> dist;
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ EXPECT_THAT(output, ElementsAre(10031, 0, 0, 3, 6, 0, 7, 47, 0, 0));
+ }
+ urbg.reset();
+ {
+ absl::zipf_distribution<int32_t> dist(std::numeric_limits<int32_t>::max(),
+ 3.3);
+ std::generate(std::begin(output), std::end(output),
+ [&] { return dist(urbg); });
+ EXPECT_THAT(output, ElementsAre(44, 0, 0, 0, 0, 1, 0, 1, 3, 0));
+ }
+}
+
+TEST(ZipfDistributionTest, AlgorithmBounds) {
+ absl::zipf_distribution<int32_t> dist;
+
+ // Small values from absl::uniform_real_distribution map to larger Zipf
+ // distribution values.
+ const std::pair<uint64_t, int32_t> kInputs[] = {
+ {0xffffffffffffffff, 0x0}, {0x7fffffffffffffff, 0x0},
+ {0x3ffffffffffffffb, 0x1}, {0x1ffffffffffffffd, 0x4},
+ {0xffffffffffffffe, 0x9}, {0x7ffffffffffffff, 0x12},
+ {0x3ffffffffffffff, 0x25}, {0x1ffffffffffffff, 0x4c},
+ {0xffffffffffffff, 0x99}, {0x7fffffffffffff, 0x132},
+ {0x3fffffffffffff, 0x265}, {0x1fffffffffffff, 0x4cc},
+ {0xfffffffffffff, 0x999}, {0x7ffffffffffff, 0x1332},
+ {0x3ffffffffffff, 0x2665}, {0x1ffffffffffff, 0x4ccc},
+ {0xffffffffffff, 0x9998}, {0x7fffffffffff, 0x1332f},
+ {0x3fffffffffff, 0x2665a}, {0x1fffffffffff, 0x4cc9e},
+ {0xfffffffffff, 0x998e0}, {0x7ffffffffff, 0x133051},
+ {0x3ffffffffff, 0x265ae4}, {0x1ffffffffff, 0x4c9ed3},
+ {0xffffffffff, 0x98e223}, {0x7fffffffff, 0x13058c4},
+ {0x3fffffffff, 0x25b178e}, {0x1fffffffff, 0x4a062b2},
+ {0xfffffffff, 0x8ee23b8}, {0x7ffffffff, 0x10b21642},
+ {0x3ffffffff, 0x1d89d89d}, {0x1ffffffff, 0x2fffffff},
+ {0xffffffff, 0x45d1745d}, {0x7fffffff, 0x5a5a5a5a},
+ {0x3fffffff, 0x69ee5846}, {0x1fffffff, 0x73ecade3},
+ {0xfffffff, 0x79a9d260}, {0x7ffffff, 0x7cc0532b},
+ {0x3ffffff, 0x7e5ad146}, {0x1ffffff, 0x7f2c0bec},
+ {0xffffff, 0x7f95adef}, {0x7fffff, 0x7fcac0da},
+ {0x3fffff, 0x7fe55ae2}, {0x1fffff, 0x7ff2ac0e},
+ {0xfffff, 0x7ff955ae}, {0x7ffff, 0x7ffcaac1},
+ {0x3ffff, 0x7ffe555b}, {0x1ffff, 0x7fff2aac},
+ {0xffff, 0x7fff9556}, {0x7fff, 0x7fffcaab},
+ {0x3fff, 0x7fffe555}, {0x1fff, 0x7ffff2ab},
+ {0xfff, 0x7ffff955}, {0x7ff, 0x7ffffcab},
+ {0x3ff, 0x7ffffe55}, {0x1ff, 0x7fffff2b},
+ {0xff, 0x7fffff95}, {0x7f, 0x7fffffcb},
+ {0x3f, 0x7fffffe5}, {0x1f, 0x7ffffff3},
+ {0xf, 0x7ffffff9}, {0x7, 0x7ffffffd},
+ {0x3, 0x7ffffffe}, {0x1, 0x7fffffff},
+ };
+
+ for (const auto& instance : kInputs) {
+ absl::random_internal::sequence_urbg urbg({instance.first});
+ EXPECT_EQ(instance.second, dist(urbg));
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/BUILD.bazel
new file mode 100644
index 00000000000..189bd73d0e4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/BUILD.bazel
@@ -0,0 +1,103 @@
+#
+# 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 package contains `absl::Status`.
+# It will expand later to have utilities around `Status` like `StatusOr`,
+# `StatusBuilder` and macros.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load(
+ "//absl:copts/configure_copts.bzl",
+ "ABSL_DEFAULT_COPTS",
+ "ABSL_TEST_COPTS",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "status",
+ srcs = [
+ "internal/status_internal.h",
+ "status.cc",
+ "status_payload_printer.cc",
+ ],
+ hdrs = [
+ "status.h",
+ "status_payload_printer.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ "//absl/base:atomic_hook",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/container:inlined_vector",
+ "//absl/debugging:stacktrace",
+ "//absl/debugging:symbolize",
+ "//absl/strings",
+ "//absl/strings:cord",
+ "//absl/strings:str_format",
+ "//absl/types:optional",
+ ],
+)
+
+cc_test(
+ name = "status_test",
+ srcs = ["status_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":status",
+ "//absl/strings",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
+ name = "statusor",
+ srcs = [
+ "internal/statusor_internal.h",
+ "statusor.cc",
+ ],
+ hdrs = [
+ "statusor.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ ":status",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/meta:type_traits",
+ "//absl/strings",
+ "//absl/types:variant",
+ "//absl/utility",
+ ],
+)
+
+cc_test(
+ name = "statusor_test",
+ size = "small",
+ srcs = ["statusor_test.cc"],
+ deps = [
+ ":status",
+ ":statusor",
+ "//absl/base",
+ "//absl/memory",
+ "//absl/types:any",
+ "//absl/utility",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/status_internal.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/status_internal.h
new file mode 100644
index 00000000000..99a2d964f76
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/status_internal.h
@@ -0,0 +1,69 @@
+// 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_STATUS_INTERNAL_STATUS_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
+
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/cord.h"
+
+#ifndef SWIG
+// Disabled for SWIG as it doesn't parse attributes correctly.
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+// Returned Status objects may not be ignored. Codesearch doesn't handle ifdefs
+// as part of a class definitions (b/6995610), so we use a forward declaration.
+class ABSL_MUST_USE_RESULT Status;
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif // !SWIG
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class StatusCode : int;
+
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+ std::string type_url;
+ absl::Cord payload;
+};
+
+using Payloads = absl::InlinedVector<Payload, 1>;
+
+// Reference-counted representation of Status data.
+struct StatusRep {
+ StatusRep(absl::StatusCode code, std::string message,
+ std::unique_ptr<status_internal::Payloads> payloads)
+ : ref(int32_t{1}),
+ code(code),
+ message(std::move(message)),
+ payloads(std::move(payloads)) {}
+
+ std::atomic<int32_t> ref;
+ absl::StatusCode code;
+ std::string message;
+ std::unique_ptr<status_internal::Payloads> payloads;
+};
+
+absl::StatusCode MapToLocalCode(int value);
+} // namespace status_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STATUS_INTERNAL_STATUS_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/statusor_internal.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/statusor_internal.h
new file mode 100644
index 00000000000..eaac2c0b14c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/internal/statusor_internal.h
@@ -0,0 +1,396 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+#define ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/status.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+namespace internal_statusor {
+
+// Detects whether `U` has conversion operator to `StatusOr<T>`, i.e. `operator
+// StatusOr<T>()`.
+template <typename T, typename U, typename = void>
+struct HasConversionOperatorToStatusOr : std::false_type {};
+
+template <typename T, typename U>
+void test(char (*)[sizeof(std::declval<U>().operator absl::StatusOr<T>())]);
+
+template <typename T, typename U>
+struct HasConversionOperatorToStatusOr<T, U, decltype(test<T, U>(0))>
+ : std::true_type {};
+
+// Detects whether `T` is constructible or convertible from `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleFromStatusOr =
+ absl::disjunction<std::is_constructible<T, StatusOr<U>&>,
+ std::is_constructible<T, const StatusOr<U>&>,
+ std::is_constructible<T, StatusOr<U>&&>,
+ std::is_constructible<T, const StatusOr<U>&&>,
+ std::is_convertible<StatusOr<U>&, T>,
+ std::is_convertible<const StatusOr<U>&, T>,
+ std::is_convertible<StatusOr<U>&&, T>,
+ std::is_convertible<const StatusOr<U>&&, T>>;
+
+// Detects whether `T` is constructible or convertible or assignable from
+// `StatusOr<U>`.
+template <typename T, typename U>
+using IsConstructibleOrConvertibleOrAssignableFromStatusOr =
+ absl::disjunction<IsConstructibleOrConvertibleFromStatusOr<T, U>,
+ std::is_assignable<T&, StatusOr<U>&>,
+ std::is_assignable<T&, const StatusOr<U>&>,
+ std::is_assignable<T&, StatusOr<U>&&>,
+ std::is_assignable<T&, const StatusOr<U>&&>>;
+
+// Detects whether direct initializing `StatusOr<T>` from `U` is ambiguous, i.e.
+// when `U` is `StatusOr<V>` and `T` is constructible or convertible from `V`.
+template <typename T, typename U>
+struct IsDirectInitializationAmbiguous
+ : public absl::conditional_t<
+ std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+ U>::value,
+ std::false_type,
+ IsDirectInitializationAmbiguous<
+ T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename V>
+struct IsDirectInitializationAmbiguous<T, absl::StatusOr<V>>
+ : public IsConstructibleOrConvertibleFromStatusOr<T, V> {};
+
+// Checks against the constraints of the direction initialization, i.e. when
+// `StatusOr<T>::StatusOr(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsDirectInitializationValid = absl::disjunction<
+ // Short circuits if T is basically U.
+ std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ absl::negation<absl::disjunction<
+ std::is_same<absl::StatusOr<T>,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ std::is_same<absl::Status,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ std::is_same<absl::in_place_t,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ IsDirectInitializationAmbiguous<T, U>>>>;
+
+// This trait detects whether `StatusOr<T>::operator=(U&&)` is ambiguous, which
+// is equivalent to whether all the following conditions are met:
+// 1. `U` is `StatusOr<V>`.
+// 2. `T` is constructible and assignable from `V`.
+// 3. `T` is constructible and assignable from `U` (i.e. `StatusOr<V>`).
+// For example, the following code is considered ambiguous:
+// (`T` is `bool`, `U` is `StatusOr<bool>`, `V` is `bool`)
+// StatusOr<bool> s1 = true; // s1.ok() && s1.ValueOrDie() == true
+// StatusOr<bool> s2 = false; // s2.ok() && s2.ValueOrDie() == false
+// s1 = s2; // ambiguous, `s1 = s2.ValueOrDie()` or `s1 = bool(s2)`?
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous
+ : public absl::conditional_t<
+ std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+ U>::value,
+ std::false_type,
+ IsForwardingAssignmentAmbiguous<
+ T, absl::remove_cv_t<absl::remove_reference_t<U>>>> {};
+
+template <typename T, typename U>
+struct IsForwardingAssignmentAmbiguous<T, absl::StatusOr<U>>
+ : public IsConstructibleOrConvertibleOrAssignableFromStatusOr<T, U> {};
+
+// Checks against the constraints of the forwarding assignment, i.e. whether
+// `StatusOr<T>::operator(U&&)` should participate in overload resolution.
+template <typename T, typename U>
+using IsForwardingAssignmentValid = absl::disjunction<
+ // Short circuits if T is basically U.
+ std::is_same<T, absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ absl::negation<absl::disjunction<
+ std::is_same<absl::StatusOr<T>,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ std::is_same<absl::Status,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ std::is_same<absl::in_place_t,
+ absl::remove_cv_t<absl::remove_reference_t<U>>>,
+ IsForwardingAssignmentAmbiguous<T, U>>>>;
+
+class Helper {
+ public:
+ // Move type-agnostic error handling to the .cc.
+ static void HandleInvalidStatusCtorArg(Status*);
+ ABSL_ATTRIBUTE_NORETURN static void Crash(const absl::Status& status);
+};
+
+// Construct an instance of T in `p` through placement new, passing Args... to
+// the constructor.
+// This abstraction is here mostly for the gcc performance fix.
+template <typename T, typename... Args>
+ABSL_ATTRIBUTE_NONNULL(1) void PlacementNew(void* p, Args&&... args) {
+ new (p) T(std::forward<Args>(args)...);
+}
+
+// Helper base class to hold the data and all operations.
+// We move all this to a base class to allow mixing with the appropriate
+// TraitsBase specialization.
+template <typename T>
+class StatusOrData {
+ template <typename U>
+ friend class StatusOrData;
+
+ public:
+ StatusOrData() = delete;
+
+ StatusOrData(const StatusOrData& other) {
+ if (other.ok()) {
+ MakeValue(other.data_);
+ MakeStatus();
+ } else {
+ MakeStatus(other.status_);
+ }
+ }
+
+ StatusOrData(StatusOrData&& other) noexcept {
+ if (other.ok()) {
+ MakeValue(std::move(other.data_));
+ MakeStatus();
+ } else {
+ MakeStatus(std::move(other.status_));
+ }
+ }
+
+ template <typename U>
+ explicit StatusOrData(const StatusOrData<U>& other) {
+ if (other.ok()) {
+ MakeValue(other.data_);
+ MakeStatus();
+ } else {
+ MakeStatus(other.status_);
+ }
+ }
+
+ template <typename U>
+ explicit StatusOrData(StatusOrData<U>&& other) {
+ if (other.ok()) {
+ MakeValue(std::move(other.data_));
+ MakeStatus();
+ } else {
+ MakeStatus(std::move(other.status_));
+ }
+ }
+
+ template <typename... Args>
+ explicit StatusOrData(absl::in_place_t, Args&&... args)
+ : data_(std::forward<Args>(args)...) {
+ MakeStatus();
+ }
+
+ explicit StatusOrData(const T& value) : data_(value) {
+ MakeStatus();
+ }
+ explicit StatusOrData(T&& value) : data_(std::move(value)) {
+ MakeStatus();
+ }
+
+ template <typename U,
+ absl::enable_if_t<std::is_constructible<absl::Status, U&&>::value,
+ int> = 0>
+ explicit StatusOrData(U&& v) : status_(std::forward<U>(v)) {
+ EnsureNotOk();
+ }
+
+ StatusOrData& operator=(const StatusOrData& other) {
+ if (this == &other) return *this;
+ if (other.ok())
+ Assign(other.data_);
+ else
+ AssignStatus(other.status_);
+ return *this;
+ }
+
+ StatusOrData& operator=(StatusOrData&& other) {
+ if (this == &other) return *this;
+ if (other.ok())
+ Assign(std::move(other.data_));
+ else
+ AssignStatus(std::move(other.status_));
+ return *this;
+ }
+
+ ~StatusOrData() {
+ if (ok()) {
+ status_.~Status();
+ data_.~T();
+ } else {
+ status_.~Status();
+ }
+ }
+
+ template <typename U>
+ void Assign(U&& value) {
+ if (ok()) {
+ data_ = std::forward<U>(value);
+ } else {
+ MakeValue(std::forward<U>(value));
+ status_ = OkStatus();
+ }
+ }
+
+ template <typename U>
+ void AssignStatus(U&& v) {
+ Clear();
+ status_ = static_cast<absl::Status>(std::forward<U>(v));
+ EnsureNotOk();
+ }
+
+ bool ok() const { return status_.ok(); }
+
+ protected:
+ // status_ will always be active after the constructor.
+ // We make it a union to be able to initialize exactly how we need without
+ // waste.
+ // Eg. in the copy constructor we use the default constructor of Status in
+ // the ok() path to avoid an extra Ref call.
+ union {
+ Status status_;
+ };
+
+ // data_ is active iff status_.ok()==true
+ struct Dummy {};
+ union {
+ // When T is const, we need some non-const object we can cast to void* for
+ // the placement new. dummy_ is that object.
+ Dummy dummy_;
+ T data_;
+ };
+
+ void Clear() {
+ if (ok()) data_.~T();
+ }
+
+ void EnsureOk() const {
+ if (ABSL_PREDICT_FALSE(!ok())) Helper::Crash(status_);
+ }
+
+ void EnsureNotOk() {
+ if (ABSL_PREDICT_FALSE(ok())) Helper::HandleInvalidStatusCtorArg(&status_);
+ }
+
+ // Construct the value (ie. data_) through placement new with the passed
+ // argument.
+ template <typename... Arg>
+ void MakeValue(Arg&&... arg) {
+ internal_statusor::PlacementNew<T>(&dummy_, std::forward<Arg>(arg)...);
+ }
+
+ // Construct the status (ie. status_) through placement new with the passed
+ // argument.
+ template <typename... Args>
+ void MakeStatus(Args&&... args) {
+ internal_statusor::PlacementNew<Status>(&status_,
+ std::forward<Args>(args)...);
+ }
+};
+
+// Helper base classes to allow implicitly deleted constructors and assignment
+// operators in `StatusOr`. For example, `CopyCtorBase` will explicitly delete
+// the copy constructor when T is not copy constructible and `StatusOr` will
+// inherit that behavior implicitly.
+template <typename T, bool = std::is_copy_constructible<T>::value>
+struct CopyCtorBase {
+ CopyCtorBase() = default;
+ CopyCtorBase(const CopyCtorBase&) = default;
+ CopyCtorBase(CopyCtorBase&&) = default;
+ CopyCtorBase& operator=(const CopyCtorBase&) = default;
+ CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T>
+struct CopyCtorBase<T, false> {
+ CopyCtorBase() = default;
+ CopyCtorBase(const CopyCtorBase&) = delete;
+ CopyCtorBase(CopyCtorBase&&) = default;
+ CopyCtorBase& operator=(const CopyCtorBase&) = default;
+ CopyCtorBase& operator=(CopyCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value>
+struct MoveCtorBase {
+ MoveCtorBase() = default;
+ MoveCtorBase(const MoveCtorBase&) = default;
+ MoveCtorBase(MoveCtorBase&&) = default;
+ MoveCtorBase& operator=(const MoveCtorBase&) = default;
+ MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T>
+struct MoveCtorBase<T, false> {
+ MoveCtorBase() = default;
+ MoveCtorBase(const MoveCtorBase&) = default;
+ MoveCtorBase(MoveCtorBase&&) = delete;
+ MoveCtorBase& operator=(const MoveCtorBase&) = default;
+ MoveCtorBase& operator=(MoveCtorBase&&) = default;
+};
+
+template <typename T, bool = std::is_copy_constructible<T>::value&&
+ std::is_copy_assignable<T>::value>
+struct CopyAssignBase {
+ CopyAssignBase() = default;
+ CopyAssignBase(const CopyAssignBase&) = default;
+ CopyAssignBase(CopyAssignBase&&) = default;
+ CopyAssignBase& operator=(const CopyAssignBase&) = default;
+ CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T>
+struct CopyAssignBase<T, false> {
+ CopyAssignBase() = default;
+ CopyAssignBase(const CopyAssignBase&) = default;
+ CopyAssignBase(CopyAssignBase&&) = default;
+ CopyAssignBase& operator=(const CopyAssignBase&) = delete;
+ CopyAssignBase& operator=(CopyAssignBase&&) = default;
+};
+
+template <typename T, bool = std::is_move_constructible<T>::value&&
+ std::is_move_assignable<T>::value>
+struct MoveAssignBase {
+ MoveAssignBase() = default;
+ MoveAssignBase(const MoveAssignBase&) = default;
+ MoveAssignBase(MoveAssignBase&&) = default;
+ MoveAssignBase& operator=(const MoveAssignBase&) = default;
+ MoveAssignBase& operator=(MoveAssignBase&&) = default;
+};
+
+template <typename T>
+struct MoveAssignBase<T, false> {
+ MoveAssignBase() = default;
+ MoveAssignBase(const MoveAssignBase&) = default;
+ MoveAssignBase(MoveAssignBase&&) = default;
+ MoveAssignBase& operator=(const MoveAssignBase&) = default;
+ MoveAssignBase& operator=(MoveAssignBase&&) = delete;
+};
+
+ABSL_ATTRIBUTE_NORETURN void ThrowBadStatusOrAccess(absl::Status status);
+
+} // namespace internal_statusor
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STATUS_INTERNAL_STATUSOR_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.cc
new file mode 100644
index 00000000000..51a0d268973
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.cc
@@ -0,0 +1,452 @@
+// 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.
+#include "absl/status/status.h"
+
+#include <cassert>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/debugging/stacktrace.h"
+#include "absl/debugging/symbolize.h"
+#include "absl/status/status_payload_printer.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_split.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+std::string StatusCodeToString(StatusCode code) {
+ switch (code) {
+ case StatusCode::kOk:
+ return "OK";
+ case StatusCode::kCancelled:
+ return "CANCELLED";
+ case StatusCode::kUnknown:
+ return "UNKNOWN";
+ case StatusCode::kInvalidArgument:
+ return "INVALID_ARGUMENT";
+ case StatusCode::kDeadlineExceeded:
+ return "DEADLINE_EXCEEDED";
+ case StatusCode::kNotFound:
+ return "NOT_FOUND";
+ case StatusCode::kAlreadyExists:
+ return "ALREADY_EXISTS";
+ case StatusCode::kPermissionDenied:
+ return "PERMISSION_DENIED";
+ case StatusCode::kUnauthenticated:
+ return "UNAUTHENTICATED";
+ case StatusCode::kResourceExhausted:
+ return "RESOURCE_EXHAUSTED";
+ case StatusCode::kFailedPrecondition:
+ return "FAILED_PRECONDITION";
+ case StatusCode::kAborted:
+ return "ABORTED";
+ case StatusCode::kOutOfRange:
+ return "OUT_OF_RANGE";
+ case StatusCode::kUnimplemented:
+ return "UNIMPLEMENTED";
+ case StatusCode::kInternal:
+ return "INTERNAL";
+ case StatusCode::kUnavailable:
+ return "UNAVAILABLE";
+ case StatusCode::kDataLoss:
+ return "DATA_LOSS";
+ default:
+ return "";
+ }
+}
+
+std::ostream& operator<<(std::ostream& os, StatusCode code) {
+ return os << StatusCodeToString(code);
+}
+
+namespace status_internal {
+
+static int FindPayloadIndexByUrl(const Payloads* payloads,
+ absl::string_view type_url) {
+ if (payloads == nullptr) return -1;
+
+ for (size_t i = 0; i < payloads->size(); ++i) {
+ if ((*payloads)[i].type_url == type_url) return i;
+ }
+
+ return -1;
+}
+
+// Convert canonical code to a value known to this binary.
+absl::StatusCode MapToLocalCode(int value) {
+ absl::StatusCode code = static_cast<absl::StatusCode>(value);
+ switch (code) {
+ case absl::StatusCode::kOk:
+ case absl::StatusCode::kCancelled:
+ case absl::StatusCode::kUnknown:
+ case absl::StatusCode::kInvalidArgument:
+ case absl::StatusCode::kDeadlineExceeded:
+ case absl::StatusCode::kNotFound:
+ case absl::StatusCode::kAlreadyExists:
+ case absl::StatusCode::kPermissionDenied:
+ case absl::StatusCode::kResourceExhausted:
+ case absl::StatusCode::kFailedPrecondition:
+ case absl::StatusCode::kAborted:
+ case absl::StatusCode::kOutOfRange:
+ case absl::StatusCode::kUnimplemented:
+ case absl::StatusCode::kInternal:
+ case absl::StatusCode::kUnavailable:
+ case absl::StatusCode::kDataLoss:
+ case absl::StatusCode::kUnauthenticated:
+ return code;
+ default:
+ return absl::StatusCode::kUnknown;
+ }
+}
+} // namespace status_internal
+
+absl::optional<absl::Cord> Status::GetPayload(
+ absl::string_view type_url) const {
+ const auto* payloads = GetPayloads();
+ int index = status_internal::FindPayloadIndexByUrl(payloads, type_url);
+ if (index != -1) return (*payloads)[index].payload;
+
+ return absl::nullopt;
+}
+
+void Status::SetPayload(absl::string_view type_url, absl::Cord payload) {
+ if (ok()) return;
+
+ PrepareToModify();
+
+ status_internal::StatusRep* rep = RepToPointer(rep_);
+ if (!rep->payloads) {
+ rep->payloads = absl::make_unique<status_internal::Payloads>();
+ }
+
+ int index =
+ status_internal::FindPayloadIndexByUrl(rep->payloads.get(), type_url);
+ if (index != -1) {
+ (*rep->payloads)[index].payload = std::move(payload);
+ return;
+ }
+
+ rep->payloads->push_back({std::string(type_url), std::move(payload)});
+}
+
+bool Status::ErasePayload(absl::string_view type_url) {
+ int index = status_internal::FindPayloadIndexByUrl(GetPayloads(), type_url);
+ if (index != -1) {
+ PrepareToModify();
+ GetPayloads()->erase(GetPayloads()->begin() + index);
+ if (GetPayloads()->empty() && message().empty()) {
+ // Special case: If this can be represented inlined, it MUST be
+ // inlined (EqualsSlow depends on this behavior).
+ StatusCode c = static_cast<StatusCode>(raw_code());
+ Unref(rep_);
+ rep_ = CodeToInlinedRep(c);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void Status::ForEachPayload(
+ const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
+ const {
+ if (auto* payloads = GetPayloads()) {
+ bool in_reverse =
+ payloads->size() > 1 && reinterpret_cast<uintptr_t>(payloads) % 13 > 6;
+
+ for (size_t index = 0; index < payloads->size(); ++index) {
+ const auto& elem =
+ (*payloads)[in_reverse ? payloads->size() - 1 - index : index];
+
+#ifdef NDEBUG
+ visitor(elem.type_url, elem.payload);
+#else
+ // In debug mode invalidate the type url to prevent users from relying on
+ // this string lifetime.
+
+ // NOLINTNEXTLINE intentional extra conversion to force temporary.
+ visitor(std::string(elem.type_url), elem.payload);
+#endif // NDEBUG
+ }
+ }
+}
+
+const std::string* Status::EmptyString() {
+ static std::string* empty_string = new std::string();
+ return empty_string;
+}
+
+constexpr const char Status::kMovedFromString[];
+
+const std::string* Status::MovedFromString() {
+ static std::string* moved_from_string = new std::string(kMovedFromString);
+ return moved_from_string;
+}
+
+void Status::UnrefNonInlined(uintptr_t rep) {
+ status_internal::StatusRep* r = RepToPointer(rep);
+ // Fast path: if ref==1, there is no need for a RefCountDec (since
+ // this is the only reference and therefore no other thread is
+ // allowed to be mucking with r).
+ if (r->ref.load(std::memory_order_acquire) == 1 ||
+ r->ref.fetch_sub(1, std::memory_order_acq_rel) - 1 == 0) {
+ delete r;
+ }
+}
+
+uintptr_t Status::NewRep(
+ absl::StatusCode code, absl::string_view msg,
+ std::unique_ptr<status_internal::Payloads> payloads) {
+ status_internal::StatusRep* rep = new status_internal::StatusRep(
+ code, std::string(msg.data(), msg.size()),
+ std::move(payloads));
+ return PointerToRep(rep);
+}
+
+Status::Status(absl::StatusCode code, absl::string_view msg)
+ : rep_(CodeToInlinedRep(code)) {
+ if (code != absl::StatusCode::kOk && !msg.empty()) {
+ rep_ = NewRep(code, msg, nullptr);
+ }
+}
+
+int Status::raw_code() const {
+ if (IsInlined(rep_)) {
+ return static_cast<int>(InlinedRepToCode(rep_));
+ }
+ status_internal::StatusRep* rep = RepToPointer(rep_);
+ return static_cast<int>(rep->code);
+}
+
+absl::StatusCode Status::code() const {
+ return status_internal::MapToLocalCode(raw_code());
+}
+
+void Status::PrepareToModify() {
+ ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
+ if (IsInlined(rep_)) {
+ rep_ =
+ NewRep(static_cast<absl::StatusCode>(raw_code()), absl::string_view(),
+ nullptr);
+ return;
+ }
+
+ uintptr_t rep_i = rep_;
+ status_internal::StatusRep* rep = RepToPointer(rep_);
+ if (rep->ref.load(std::memory_order_acquire) != 1) {
+ std::unique_ptr<status_internal::Payloads> payloads;
+ if (rep->payloads) {
+ payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
+ }
+ rep_ = NewRep(rep->code, message(),
+ std::move(payloads));
+ UnrefNonInlined(rep_i);
+ }
+}
+
+bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
+ if (IsInlined(a.rep_) != IsInlined(b.rep_)) return false;
+ if (a.message() != b.message()) return false;
+ if (a.raw_code() != b.raw_code()) return false;
+ if (a.GetPayloads() == b.GetPayloads()) return true;
+
+ const status_internal::Payloads no_payloads;
+ const status_internal::Payloads* larger_payloads =
+ a.GetPayloads() ? a.GetPayloads() : &no_payloads;
+ const status_internal::Payloads* smaller_payloads =
+ b.GetPayloads() ? b.GetPayloads() : &no_payloads;
+ if (larger_payloads->size() < smaller_payloads->size()) {
+ std::swap(larger_payloads, smaller_payloads);
+ }
+ if ((larger_payloads->size() - smaller_payloads->size()) > 1) return false;
+ // Payloads can be ordered differently, so we can't just compare payload
+ // vectors.
+ for (const auto& payload : *larger_payloads) {
+
+ bool found = false;
+ for (const auto& other_payload : *smaller_payloads) {
+ if (payload.type_url == other_payload.type_url) {
+ if (payload.payload != other_payload.payload) {
+ return false;
+ }
+ found = true;
+ break;
+ }
+ }
+ if (!found) return false;
+ }
+ return true;
+}
+
+std::string Status::ToStringSlow(StatusToStringMode mode) const {
+ std::string text;
+ absl::StrAppend(&text, absl::StatusCodeToString(code()), ": ", message());
+
+ const bool with_payload = (mode & StatusToStringMode::kWithPayload) ==
+ StatusToStringMode::kWithPayload;
+
+ if (with_payload) {
+ status_internal::StatusPayloadPrinter printer =
+ status_internal::GetStatusPayloadPrinter();
+ this->ForEachPayload([&](absl::string_view type_url,
+ const absl::Cord& payload) {
+ absl::optional<std::string> result;
+ if (printer) result = printer(type_url, payload);
+ absl::StrAppend(
+ &text, " [", type_url, "='",
+ result.has_value() ? *result : absl::CHexEscape(std::string(payload)),
+ "']");
+ });
+ }
+
+ return text;
+}
+
+std::ostream& operator<<(std::ostream& os, const Status& x) {
+ os << x.ToString();
+ return os;
+}
+
+Status AbortedError(absl::string_view message) {
+ return Status(absl::StatusCode::kAborted, message);
+}
+
+Status AlreadyExistsError(absl::string_view message) {
+ return Status(absl::StatusCode::kAlreadyExists, message);
+}
+
+Status CancelledError(absl::string_view message) {
+ return Status(absl::StatusCode::kCancelled, message);
+}
+
+Status DataLossError(absl::string_view message) {
+ return Status(absl::StatusCode::kDataLoss, message);
+}
+
+Status DeadlineExceededError(absl::string_view message) {
+ return Status(absl::StatusCode::kDeadlineExceeded, message);
+}
+
+Status FailedPreconditionError(absl::string_view message) {
+ return Status(absl::StatusCode::kFailedPrecondition, message);
+}
+
+Status InternalError(absl::string_view message) {
+ return Status(absl::StatusCode::kInternal, message);
+}
+
+Status InvalidArgumentError(absl::string_view message) {
+ return Status(absl::StatusCode::kInvalidArgument, message);
+}
+
+Status NotFoundError(absl::string_view message) {
+ return Status(absl::StatusCode::kNotFound, message);
+}
+
+Status OutOfRangeError(absl::string_view message) {
+ return Status(absl::StatusCode::kOutOfRange, message);
+}
+
+Status PermissionDeniedError(absl::string_view message) {
+ return Status(absl::StatusCode::kPermissionDenied, message);
+}
+
+Status ResourceExhaustedError(absl::string_view message) {
+ return Status(absl::StatusCode::kResourceExhausted, message);
+}
+
+Status UnauthenticatedError(absl::string_view message) {
+ return Status(absl::StatusCode::kUnauthenticated, message);
+}
+
+Status UnavailableError(absl::string_view message) {
+ return Status(absl::StatusCode::kUnavailable, message);
+}
+
+Status UnimplementedError(absl::string_view message) {
+ return Status(absl::StatusCode::kUnimplemented, message);
+}
+
+Status UnknownError(absl::string_view message) {
+ return Status(absl::StatusCode::kUnknown, message);
+}
+
+bool IsAborted(const Status& status) {
+ return status.code() == absl::StatusCode::kAborted;
+}
+
+bool IsAlreadyExists(const Status& status) {
+ return status.code() == absl::StatusCode::kAlreadyExists;
+}
+
+bool IsCancelled(const Status& status) {
+ return status.code() == absl::StatusCode::kCancelled;
+}
+
+bool IsDataLoss(const Status& status) {
+ return status.code() == absl::StatusCode::kDataLoss;
+}
+
+bool IsDeadlineExceeded(const Status& status) {
+ return status.code() == absl::StatusCode::kDeadlineExceeded;
+}
+
+bool IsFailedPrecondition(const Status& status) {
+ return status.code() == absl::StatusCode::kFailedPrecondition;
+}
+
+bool IsInternal(const Status& status) {
+ return status.code() == absl::StatusCode::kInternal;
+}
+
+bool IsInvalidArgument(const Status& status) {
+ return status.code() == absl::StatusCode::kInvalidArgument;
+}
+
+bool IsNotFound(const Status& status) {
+ return status.code() == absl::StatusCode::kNotFound;
+}
+
+bool IsOutOfRange(const Status& status) {
+ return status.code() == absl::StatusCode::kOutOfRange;
+}
+
+bool IsPermissionDenied(const Status& status) {
+ return status.code() == absl::StatusCode::kPermissionDenied;
+}
+
+bool IsResourceExhausted(const Status& status) {
+ return status.code() == absl::StatusCode::kResourceExhausted;
+}
+
+bool IsUnauthenticated(const Status& status) {
+ return status.code() == absl::StatusCode::kUnauthenticated;
+}
+
+bool IsUnavailable(const Status& status) {
+ return status.code() == absl::StatusCode::kUnavailable;
+}
+
+bool IsUnimplemented(const Status& status) {
+ return status.code() == absl::StatusCode::kUnimplemented;
+}
+
+bool IsUnknown(const Status& status) {
+ return status.code() == absl::StatusCode::kUnknown;
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.h
new file mode 100644
index 00000000000..61486feedfe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status.h
@@ -0,0 +1,878 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// File: status.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the Abseil `status` library, consisting of:
+//
+// * An `absl::Status` class for holding error handling information
+// * A set of canonical `absl::StatusCode` error codes, and associated
+// utilities for generating and propagating status codes.
+// * A set of helper functions for creating status codes and checking their
+// values
+//
+// Within Google, `absl::Status` is the primary mechanism for gracefully
+// handling errors across API boundaries (and in particular across RPC
+// boundaries). Some of these errors may be recoverable, but others may not.
+// Most functions that can produce a recoverable error should be designed to
+// return an `absl::Status` (or `absl::StatusOr`).
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+// ...
+// // encounter error
+// if (error condition) {
+// return absl::InvalidArgumentError("bad mode");
+// }
+// // else, return OK
+// return absl::OkStatus();
+// }
+//
+// An `absl::Status` is designed to either return "OK" or one of a number of
+// different error codes, corresponding to typical error conditions.
+// In almost all cases, when using `absl::Status` you should use the canonical
+// error codes (of type `absl::StatusCode`) enumerated in this header file.
+// These canonical codes are understood across the codebase and will be
+// accepted across all API and RPC boundaries.
+#ifndef ABSL_STATUS_STATUS_H_
+#define ABSL_STATUS_STATUS_H_
+
+#include <iostream>
+#include <string>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/status/internal/status_internal.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// absl::StatusCode
+//
+// An `absl::StatusCode` is an enumerated type indicating either no error ("OK")
+// or an error condition. In most cases, an `absl::Status` indicates a
+// recoverable error, and the purpose of signalling an error is to indicate what
+// action to take in response to that error. These error codes map to the proto
+// RPC error codes indicated in https://cloud.google.com/apis/design/errors.
+//
+// The errors listed below are the canonical errors associated with
+// `absl::Status` and are used throughout the codebase. As a result, these
+// error codes are somewhat generic.
+//
+// In general, try to return the most specific error that applies if more than
+// one error may pertain. For example, prefer `kOutOfRange` over
+// `kFailedPrecondition` if both codes apply. Similarly prefer `kNotFound` or
+// `kAlreadyExists` over `kFailedPrecondition`.
+//
+// Because these errors may travel RPC boundaries, these codes are tied to the
+// `google.rpc.Code` definitions within
+// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
+// The string value of these RPC codes is denoted within each enum below.
+//
+// If your error handling code requires more context, you can attach payloads
+// to your status. See `absl::Status::SetPayload()` and
+// `absl::Status::GetPayload()` below.
+enum class StatusCode : int {
+ // StatusCode::kOk
+ //
+ // kOK (gRPC code "OK") does not indicate an error; this value is returned on
+ // success. It is typical to check for this value before proceeding on any
+ // given call across an API or RPC boundary. To check this value, use the
+ // `absl::Status::ok()` member function rather than inspecting the raw code.
+ kOk = 0,
+
+ // StatusCode::kCancelled
+ //
+ // kCancelled (gRPC code "CANCELLED") indicates the operation was cancelled,
+ // typically by the caller.
+ kCancelled = 1,
+
+ // StatusCode::kUnknown
+ //
+ // kUnknown (gRPC code "UNKNOWN") indicates an unknown error occurred. In
+ // general, more specific errors should be raised, if possible. Errors raised
+ // by APIs that do not return enough error information may be converted to
+ // this error.
+ kUnknown = 2,
+
+ // StatusCode::kInvalidArgument
+ //
+ // kInvalidArgument (gRPC code "INVALID_ARGUMENT") indicates the caller
+ // specified an invalid argument, such a malformed filename. Note that such
+ // errors should be narrowly limited to indicate to the invalid nature of the
+ // arguments themselves. Errors with validly formed arguments that may cause
+ // errors with the state of the receiving system should be denoted with
+ // `kFailedPrecondition` instead.
+ kInvalidArgument = 3,
+
+ // StatusCode::kDeadlineExceeded
+ //
+ // kDeadlineExceeded (gRPC code "DEADLINE_EXCEEDED") indicates a deadline
+ // expired before the operation could complete. For operations that may change
+ // state within a system, this error may be returned even if the operation has
+ // completed successfully. For example, a successful response from a server
+ // could have been delayed long enough for the deadline to expire.
+ kDeadlineExceeded = 4,
+
+ // StatusCode::kNotFound
+ //
+ // kNotFound (gRPC code "NOT_FOUND") indicates some requested entity (such as
+ // a file or directory) was not found.
+ //
+ // `kNotFound` is useful if a request should be denied for an entire class of
+ // users, such as during a gradual feature rollout or undocumented allow list.
+ // If, instead, a request should be denied for specific sets of users, such as
+ // through user-based access control, use `kPermissionDenied` instead.
+ kNotFound = 5,
+
+ // StatusCode::kAlreadyExists
+ //
+ // kAlreadyExists (gRPC code "ALREADY_EXISTS") indicates the entity that a
+ // caller attempted to create (such as file or directory) is already present.
+ kAlreadyExists = 6,
+
+ // StatusCode::kPermissionDenied
+ //
+ // kPermissionDenied (gRPC code "PERMISSION_DENIED") indicates that the caller
+ // does not have permission to execute the specified operation. Note that this
+ // error is different than an error due to an *un*authenticated user. This
+ // error code does not imply the request is valid or the requested entity
+ // exists or satisfies any other pre-conditions.
+ //
+ // `kPermissionDenied` must not be used for rejections caused by exhausting
+ // some resource. Instead, use `kResourceExhausted` for those errors.
+ // `kPermissionDenied` must not be used if the caller cannot be identified.
+ // Instead, use `kUnauthenticated` for those errors.
+ kPermissionDenied = 7,
+
+ // StatusCode::kResourceExhausted
+ //
+ // kResourceExhausted (gRPC code "RESOURCE_EXHAUSTED") indicates some resource
+ // has been exhausted, perhaps a per-user quota, or perhaps the entire file
+ // system is out of space.
+ kResourceExhausted = 8,
+
+ // StatusCode::kFailedPrecondition
+ //
+ // kFailedPrecondition (gRPC code "FAILED_PRECONDITION") indicates that the
+ // operation was rejected because the system is not in a state required for
+ // the operation's execution. For example, a directory to be deleted may be
+ // non-empty, an "rmdir" operation is applied to a non-directory, etc.
+ //
+ // Some guidelines that may help a service implementer in deciding between
+ // `kFailedPrecondition`, `kAborted`, and `kUnavailable`:
+ //
+ // (a) Use `kUnavailable` if the client can retry just the failing call.
+ // (b) Use `kAborted` if the client should retry at a higher transaction
+ // level (such as when a client-specified test-and-set fails, indicating
+ // the client should restart a read-modify-write sequence).
+ // (c) Use `kFailedPrecondition` if the client should not retry until
+ // the system state has been explicitly fixed. For example, if an "rmdir"
+ // fails because the directory is non-empty, `kFailedPrecondition`
+ // should be returned since the client should not retry unless
+ // the files are deleted from the directory.
+ kFailedPrecondition = 9,
+
+ // StatusCode::kAborted
+ //
+ // kAborted (gRPC code "ABORTED") indicates the operation was aborted,
+ // typically due to a concurrency issue such as a sequencer check failure or a
+ // failed transaction.
+ //
+ // See the guidelines above for deciding between `kFailedPrecondition`,
+ // `kAborted`, and `kUnavailable`.
+ kAborted = 10,
+
+ // StatusCode::kOutOfRange
+ //
+ // kOutOfRange (gRPC code "OUT_OF_RANGE") indicates the operation was
+ // attempted past the valid range, such as seeking or reading past an
+ // end-of-file.
+ //
+ // Unlike `kInvalidArgument`, this error indicates a problem that may
+ // be fixed if the system state changes. For example, a 32-bit file
+ // system will generate `kInvalidArgument` if asked to read at an
+ // offset that is not in the range [0,2^32-1], but it will generate
+ // `kOutOfRange` if asked to read from an offset past the current
+ // file size.
+ //
+ // There is a fair bit of overlap between `kFailedPrecondition` and
+ // `kOutOfRange`. We recommend using `kOutOfRange` (the more specific
+ // error) when it applies so that callers who are iterating through
+ // a space can easily look for an `kOutOfRange` error to detect when
+ // they are done.
+ kOutOfRange = 11,
+
+ // StatusCode::kUnimplemented
+ //
+ // kUnimplemented (gRPC code "UNIMPLEMENTED") indicates the operation is not
+ // implemented or supported in this service. In this case, the operation
+ // should not be re-attempted.
+ kUnimplemented = 12,
+
+ // StatusCode::kInternal
+ //
+ // kInternal (gRPC code "INTERNAL") indicates an internal error has occurred
+ // and some invariants expected by the underlying system have not been
+ // satisfied. This error code is reserved for serious errors.
+ kInternal = 13,
+
+ // StatusCode::kUnavailable
+ //
+ // kUnavailable (gRPC code "UNAVAILABLE") indicates the service is currently
+ // unavailable and that this is most likely a transient condition. An error
+ // such as this can be corrected by retrying with a backoff scheme. Note that
+ // it is not always safe to retry non-idempotent operations.
+ //
+ // See the guidelines above for deciding between `kFailedPrecondition`,
+ // `kAborted`, and `kUnavailable`.
+ kUnavailable = 14,
+
+ // StatusCode::kDataLoss
+ //
+ // kDataLoss (gRPC code "DATA_LOSS") indicates that unrecoverable data loss or
+ // corruption has occurred. As this error is serious, proper alerting should
+ // be attached to errors such as this.
+ kDataLoss = 15,
+
+ // StatusCode::kUnauthenticated
+ //
+ // kUnauthenticated (gRPC code "UNAUTHENTICATED") indicates that the request
+ // does not have valid authentication credentials for the operation. Correct
+ // the authentication and try again.
+ kUnauthenticated = 16,
+
+ // StatusCode::DoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_
+ //
+ // NOTE: this error code entry should not be used and you should not rely on
+ // its value, which may change.
+ //
+ // The purpose of this enumerated value is to force people who handle status
+ // codes with `switch()` statements to *not* simply enumerate all possible
+ // values, but instead provide a "default:" case. Providing such a default
+ // case ensures that code will compile when new codes are added.
+ kDoNotUseReservedForFutureExpansionUseDefaultInSwitchInstead_ = 20
+};
+
+// StatusCodeToString()
+//
+// Returns the name for the status code, or "" if it is an unknown value.
+std::string StatusCodeToString(StatusCode code);
+
+// operator<<
+//
+// Streams StatusCodeToString(code) to `os`.
+std::ostream& operator<<(std::ostream& os, StatusCode code);
+
+// absl::StatusToStringMode
+//
+// An `absl::StatusToStringMode` is an enumerated type indicating how
+// `absl::Status::ToString()` should construct the output string for an non-ok
+// status.
+enum class StatusToStringMode : int {
+ // ToString will not contain any extra data (such as payloads). It will only
+ // contain the error code and message, if any.
+ kWithNoExtraData = 0,
+ // ToString will contain the payloads.
+ kWithPayload = 1 << 0,
+ // ToString will include all the extra data this Status has.
+ kWithEverything = ~kWithNoExtraData,
+};
+
+// absl::StatusToStringMode is specified as a bitmask type, which means the
+// following operations must be provided:
+inline constexpr StatusToStringMode operator&(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) &
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator|(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) |
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator^(StatusToStringMode lhs,
+ StatusToStringMode rhs) {
+ return static_cast<StatusToStringMode>(static_cast<int>(lhs) ^
+ static_cast<int>(rhs));
+}
+inline constexpr StatusToStringMode operator~(StatusToStringMode arg) {
+ return static_cast<StatusToStringMode>(~static_cast<int>(arg));
+}
+inline StatusToStringMode& operator&=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs & rhs;
+ return lhs;
+}
+inline StatusToStringMode& operator|=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs | rhs;
+ return lhs;
+}
+inline StatusToStringMode& operator^=(StatusToStringMode& lhs,
+ StatusToStringMode rhs) {
+ lhs = lhs ^ rhs;
+ return lhs;
+}
+
+// absl::Status
+//
+// The `absl::Status` class is generally used to gracefully handle errors
+// across API boundaries (and in particular across RPC boundaries). Some of
+// these errors may be recoverable, but others may not. Most
+// functions which can produce a recoverable error should be designed to return
+// either an `absl::Status` (or the similar `absl::StatusOr<T>`, which holds
+// either an object of type `T` or an error).
+//
+// API developers should construct their functions to return `absl::OkStatus()`
+// upon success, or an `absl::StatusCode` upon another type of error (e.g
+// an `absl::StatusCode::kInvalidArgument` error). The API provides convenience
+// functions to constuct each status code.
+//
+// Example:
+//
+// absl::Status myFunction(absl::string_view fname, ...) {
+// ...
+// // encounter error
+// if (error condition) {
+// // Construct an absl::StatusCode::kInvalidArgument error
+// return absl::InvalidArgumentError("bad mode");
+// }
+// // else, return OK
+// return absl::OkStatus();
+// }
+//
+// Users handling status error codes should prefer checking for an OK status
+// using the `ok()` member function. Handling multiple error codes may justify
+// use of switch statement, but only check for error codes you know how to
+// handle; do not try to exhaustively match against all canonical error codes.
+// Errors that cannot be handled should be logged and/or propagated for higher
+// levels to deal with. If you do use a switch statement, make sure that you
+// also provide a `default:` switch case, so that code does not break as other
+// canonical codes are added to the API.
+//
+// Example:
+//
+// absl::Status result = DoSomething();
+// if (!result.ok()) {
+// LOG(ERROR) << result;
+// }
+//
+// // Provide a default if switching on multiple error codes
+// switch (result.code()) {
+// // The user hasn't authenticated. Ask them to reauth
+// case absl::StatusCode::kUnauthenticated:
+// DoReAuth();
+// break;
+// // The user does not have permission. Log an error.
+// case absl::StatusCode::kPermissionDenied:
+// LOG(ERROR) << result;
+// break;
+// // Propagate the error otherwise.
+// default:
+// return true;
+// }
+//
+// An `absl::Status` can optionally include a payload with more information
+// about the error. Typically, this payload serves one of several purposes:
+//
+// * It may provide more fine-grained semantic information about the error to
+// facilitate actionable remedies.
+// * It may provide human-readable contexual information that is more
+// appropriate to display to an end user.
+//
+// Example:
+//
+// absl::Status result = DoSomething();
+// // Inform user to retry after 30 seconds
+// // See more error details in googleapis/google/rpc/error_details.proto
+// if (absl::IsResourceExhausted(result)) {
+// google::rpc::RetryInfo info;
+// info.retry_delay().seconds() = 30;
+// // Payloads require a unique key (a URL to ensure no collisions with
+// // other payloads), and an `absl::Cord` to hold the encoded data.
+// absl::string_view url = "type.googleapis.com/google.rpc.RetryInfo";
+// result.SetPayload(url, info.SerializeAsCord());
+// return result;
+// }
+//
+// For documentation see https://abseil.io/docs/cpp/guides/status.
+//
+// Returned Status objects may not be ignored. status_internal.h has a forward
+// declaration of the form
+// class ABSL_MUST_USE_RESULT Status;
+class Status final {
+ public:
+ // Constructors
+
+ // This default constructor creates an OK status with no message or payload.
+ // Avoid this constructor and prefer explicit construction of an OK status
+ // with `absl::OkStatus()`.
+ Status();
+
+ // Creates a status in the canonical error space with the specified
+ // `absl::StatusCode` and error message. If `code == absl::StatusCode::kOk`, // NOLINT
+ // `msg` is ignored and an object identical to an OK status is constructed.
+ //
+ // The `msg` string must be in UTF-8. The implementation may complain (e.g., // NOLINT
+ // by printing a warning) if it is not.
+ Status(absl::StatusCode code, absl::string_view msg);
+
+ Status(const Status&);
+ Status& operator=(const Status& x);
+
+ // Move operators
+
+ // The moved-from state is valid but unspecified.
+ Status(Status&&) noexcept;
+ Status& operator=(Status&&);
+
+ ~Status();
+
+ // Status::Update()
+ //
+ // Updates the existing status with `new_status` provided that `this->ok()`.
+ // If the existing status already contains a non-OK error, this update has no
+ // effect and preserves the current data. Note that this behavior may change
+ // in the future to augment a current non-ok status with additional
+ // information about `new_status`.
+ //
+ // `Update()` provides a convenient way of keeping track of the first error
+ // encountered.
+ //
+ // Example:
+ // // Instead of "if (overall_status.ok()) overall_status = new_status"
+ // overall_status.Update(new_status);
+ //
+ void Update(const Status& new_status);
+ void Update(Status&& new_status);
+
+ // Status::ok()
+ //
+ // Returns `true` if `this->ok()`. Prefer checking for an OK status using this
+ // member function.
+ ABSL_MUST_USE_RESULT bool ok() const;
+
+ // Status::code()
+ //
+ // Returns the canonical error code of type `absl::StatusCode` of this status.
+ absl::StatusCode code() const;
+
+ // Status::raw_code()
+ //
+ // Returns a raw (canonical) error code corresponding to the enum value of
+ // `google.rpc.Code` definitions within
+ // https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto.
+ // These values could be out of the range of canonical `absl::StatusCode`
+ // enum values.
+ //
+ // NOTE: This function should only be called when converting to an associated
+ // wire format. Use `Status::code()` for error handling.
+ int raw_code() const;
+
+ // Status::message()
+ //
+ // Returns the error message associated with this error code, if available.
+ // Note that this message rarely describes the error code. It is not unusual
+ // for the error message to be the empty string. As a result, prefer
+ // `Status::ToString()` for debug logging.
+ absl::string_view message() const;
+
+ friend bool operator==(const Status&, const Status&);
+ friend bool operator!=(const Status&, const Status&);
+
+ // Status::ToString()
+ //
+ // Returns a string based on the `mode`. By default, it returns combination of
+ // the error code name, the message and any associated payload messages. This
+ // string is designed simply to be human readable and its exact format should
+ // not be load bearing. Do not depend on the exact format of the result of
+ // `ToString()` which is subject to change.
+ //
+ // The printed code name and the message are generally substrings of the
+ // result, and the payloads to be printed use the status payload printer
+ // mechanism (which is internal).
+ std::string ToString(
+ StatusToStringMode mode = StatusToStringMode::kWithPayload) const;
+
+ // Status::IgnoreError()
+ //
+ // Ignores any errors. This method does nothing except potentially suppress
+ // complaints from any tools that are checking that errors are not dropped on
+ // the floor.
+ void IgnoreError() const;
+
+ // swap()
+ //
+ // Swap the contents of one status with another.
+ friend void swap(Status& a, Status& b);
+
+ //----------------------------------------------------------------------------
+ // Payload Management APIs
+ //----------------------------------------------------------------------------
+
+ // A payload may be attached to a status to provide additional context to an
+ // error that may not be satisifed by an existing `absl::StatusCode`.
+ // Typically, this payload serves one of several purposes:
+ //
+ // * It may provide more fine-grained semantic information about the error
+ // to facilitate actionable remedies.
+ // * It may provide human-readable contexual information that is more
+ // appropriate to display to an end user.
+ //
+ // A payload consists of a [key,value] pair, where the key is a string
+ // referring to a unique "type URL" and the value is an object of type
+ // `absl::Cord` to hold the contextual data.
+ //
+ // The "type URL" should be unique and follow the format of a URL
+ // (https://en.wikipedia.org/wiki/URL) and, ideally, provide some
+ // documentation or schema on how to interpret its associated data. For
+ // example, the default type URL for a protobuf message type is
+ // "type.googleapis.com/packagename.messagename". Other custom wire formats
+ // should define the format of type URL in a similar practice so as to
+ // minimize the chance of conflict between type URLs.
+ // Users should ensure that the type URL can be mapped to a concrete
+ // C++ type if they want to deserialize the payload and read it effectively.
+ //
+ // To attach a payload to a status object, call `Status::SetPayload()`,
+ // passing it the type URL and an `absl::Cord` of associated data. Similarly,
+ // to extract the payload from a status, call `Status::GetPayload()`. You
+ // may attach multiple payloads (with differing type URLs) to any given
+ // status object, provided that the status is currently exhibiting an error
+ // code (i.e. is not OK).
+
+ // Status::GetPayload()
+ //
+ // Gets the payload of a status given its unique `type_url` key, if present.
+ absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
+
+ // Status::SetPayload()
+ //
+ // Sets the payload for a non-ok status using a `type_url` key, overwriting
+ // any existing payload for that `type_url`.
+ //
+ // NOTE: This function does nothing if the Status is ok.
+ void SetPayload(absl::string_view type_url, absl::Cord payload);
+
+ // Status::ErasePayload()
+ //
+ // Erases the payload corresponding to the `type_url` key. Returns `true` if
+ // the payload was present.
+ bool ErasePayload(absl::string_view type_url);
+
+ // Status::ForEachPayload()
+ //
+ // Iterates over the stored payloads and calls the
+ // `visitor(type_key, payload)` callable for each one.
+ //
+ // NOTE: The order of calls to `visitor()` is not specified and may change at
+ // any time.
+ //
+ // NOTE: Any mutation on the same 'absl::Status' object during visitation is
+ // forbidden and could result in undefined behavior.
+ void ForEachPayload(
+ const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
+ const;
+
+ private:
+ friend Status CancelledError();
+
+ // Creates a status in the canonical error space with the specified
+ // code, and an empty error message.
+ explicit Status(absl::StatusCode code);
+
+ static void UnrefNonInlined(uintptr_t rep);
+ static void Ref(uintptr_t rep);
+ static void Unref(uintptr_t rep);
+
+ // REQUIRES: !ok()
+ // Ensures rep_ is not shared with any other Status.
+ void PrepareToModify();
+
+ const status_internal::Payloads* GetPayloads() const;
+ status_internal::Payloads* GetPayloads();
+
+ // Takes ownership of payload.
+ static uintptr_t NewRep(
+ absl::StatusCode code, absl::string_view msg,
+ std::unique_ptr<status_internal::Payloads> payload);
+ static bool EqualsSlow(const absl::Status& a, const absl::Status& b);
+
+ // MSVC 14.0 limitation requires the const.
+ static constexpr const char kMovedFromString[] =
+ "Status accessed after move.";
+
+ static const std::string* EmptyString();
+ static const std::string* MovedFromString();
+
+ // Returns whether rep contains an inlined representation.
+ // See rep_ for details.
+ static bool IsInlined(uintptr_t rep);
+
+ // Indicates whether this Status was the rhs of a move operation. See rep_
+ // for details.
+ static bool IsMovedFrom(uintptr_t rep);
+ static uintptr_t MovedFromRep();
+
+ // Convert between error::Code and the inlined uintptr_t representation used
+ // by rep_. See rep_ for details.
+ static uintptr_t CodeToInlinedRep(absl::StatusCode code);
+ static absl::StatusCode InlinedRepToCode(uintptr_t rep);
+
+ // Converts between StatusRep* and the external uintptr_t representation used
+ // by rep_. See rep_ for details.
+ static uintptr_t PointerToRep(status_internal::StatusRep* r);
+ static status_internal::StatusRep* RepToPointer(uintptr_t r);
+
+ std::string ToStringSlow(StatusToStringMode mode) const;
+
+ // Status supports two different representations.
+ // - When the low bit is off it is an inlined representation.
+ // It uses the canonical error space, no message or payload.
+ // The error code is (rep_ >> 2).
+ // The (rep_ & 2) bit is the "moved from" indicator, used in IsMovedFrom().
+ // - When the low bit is on it is an external representation.
+ // In this case all the data comes from a heap allocated Rep object.
+ // (rep_ - 1) is a status_internal::StatusRep* pointer to that structure.
+ uintptr_t rep_;
+};
+
+// OkStatus()
+//
+// Returns an OK status, equivalent to a default constructed instance. Prefer
+// usage of `absl::OkStatus()` when constructing such an OK status.
+Status OkStatus();
+
+// operator<<()
+//
+// Prints a human-readable representation of `x` to `os`.
+std::ostream& operator<<(std::ostream& os, const Status& x);
+
+// IsAborted()
+// IsAlreadyExists()
+// IsCancelled()
+// IsDataLoss()
+// IsDeadlineExceeded()
+// IsFailedPrecondition()
+// IsInternal()
+// IsInvalidArgument()
+// IsNotFound()
+// IsOutOfRange()
+// IsPermissionDenied()
+// IsResourceExhausted()
+// IsUnauthenticated()
+// IsUnavailable()
+// IsUnimplemented()
+// IsUnknown()
+//
+// These convenience functions return `true` if a given status matches the
+// `absl::StatusCode` error code of its associated function.
+ABSL_MUST_USE_RESULT bool IsAborted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsAlreadyExists(const Status& status);
+ABSL_MUST_USE_RESULT bool IsCancelled(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDataLoss(const Status& status);
+ABSL_MUST_USE_RESULT bool IsDeadlineExceeded(const Status& status);
+ABSL_MUST_USE_RESULT bool IsFailedPrecondition(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInternal(const Status& status);
+ABSL_MUST_USE_RESULT bool IsInvalidArgument(const Status& status);
+ABSL_MUST_USE_RESULT bool IsNotFound(const Status& status);
+ABSL_MUST_USE_RESULT bool IsOutOfRange(const Status& status);
+ABSL_MUST_USE_RESULT bool IsPermissionDenied(const Status& status);
+ABSL_MUST_USE_RESULT bool IsResourceExhausted(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnauthenticated(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnavailable(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnimplemented(const Status& status);
+ABSL_MUST_USE_RESULT bool IsUnknown(const Status& status);
+
+// AbortedError()
+// AlreadyExistsError()
+// CancelledError()
+// DataLossError()
+// DeadlineExceededError()
+// FailedPreconditionError()
+// InternalError()
+// InvalidArgumentError()
+// NotFoundError()
+// OutOfRangeError()
+// PermissionDeniedError()
+// ResourceExhaustedError()
+// UnauthenticatedError()
+// UnavailableError()
+// UnimplementedError()
+// UnknownError()
+//
+// These convenience functions create an `absl::Status` object with an error
+// code as indicated by the associated function name, using the error message
+// passed in `message`.
+Status AbortedError(absl::string_view message);
+Status AlreadyExistsError(absl::string_view message);
+Status CancelledError(absl::string_view message);
+Status DataLossError(absl::string_view message);
+Status DeadlineExceededError(absl::string_view message);
+Status FailedPreconditionError(absl::string_view message);
+Status InternalError(absl::string_view message);
+Status InvalidArgumentError(absl::string_view message);
+Status NotFoundError(absl::string_view message);
+Status OutOfRangeError(absl::string_view message);
+Status PermissionDeniedError(absl::string_view message);
+Status ResourceExhaustedError(absl::string_view message);
+Status UnauthenticatedError(absl::string_view message);
+Status UnavailableError(absl::string_view message);
+Status UnimplementedError(absl::string_view message);
+Status UnknownError(absl::string_view message);
+
+//------------------------------------------------------------------------------
+// Implementation details follow
+//------------------------------------------------------------------------------
+
+inline Status::Status() : rep_(CodeToInlinedRep(absl::StatusCode::kOk)) {}
+
+inline Status::Status(absl::StatusCode code) : rep_(CodeToInlinedRep(code)) {}
+
+inline Status::Status(const Status& x) : rep_(x.rep_) { Ref(rep_); }
+
+inline Status& Status::operator=(const Status& x) {
+ uintptr_t old_rep = rep_;
+ if (x.rep_ != old_rep) {
+ Ref(x.rep_);
+ rep_ = x.rep_;
+ Unref(old_rep);
+ }
+ return *this;
+}
+
+inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
+ x.rep_ = MovedFromRep();
+}
+
+inline Status& Status::operator=(Status&& x) {
+ uintptr_t old_rep = rep_;
+ if (x.rep_ != old_rep) {
+ rep_ = x.rep_;
+ x.rep_ = MovedFromRep();
+ Unref(old_rep);
+ }
+ return *this;
+}
+
+inline void Status::Update(const Status& new_status) {
+ if (ok()) {
+ *this = new_status;
+ }
+}
+
+inline void Status::Update(Status&& new_status) {
+ if (ok()) {
+ *this = std::move(new_status);
+ }
+}
+
+inline Status::~Status() { Unref(rep_); }
+
+inline bool Status::ok() const {
+ return rep_ == CodeToInlinedRep(absl::StatusCode::kOk);
+}
+
+inline absl::string_view Status::message() const {
+ return !IsInlined(rep_)
+ ? RepToPointer(rep_)->message
+ : (IsMovedFrom(rep_) ? absl::string_view(kMovedFromString)
+ : absl::string_view());
+}
+
+inline bool operator==(const Status& lhs, const Status& rhs) {
+ return lhs.rep_ == rhs.rep_ || Status::EqualsSlow(lhs, rhs);
+}
+
+inline bool operator!=(const Status& lhs, const Status& rhs) {
+ return !(lhs == rhs);
+}
+
+inline std::string Status::ToString(StatusToStringMode mode) const {
+ return ok() ? "OK" : ToStringSlow(mode);
+}
+
+inline void Status::IgnoreError() const {
+ // no-op
+}
+
+inline void swap(absl::Status& a, absl::Status& b) {
+ using std::swap;
+ swap(a.rep_, b.rep_);
+}
+
+inline const status_internal::Payloads* Status::GetPayloads() const {
+ return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
+}
+
+inline status_internal::Payloads* Status::GetPayloads() {
+ return IsInlined(rep_) ? nullptr : RepToPointer(rep_)->payloads.get();
+}
+
+inline bool Status::IsInlined(uintptr_t rep) { return (rep & 1) == 0; }
+
+inline bool Status::IsMovedFrom(uintptr_t rep) {
+ return IsInlined(rep) && (rep & 2) != 0;
+}
+
+inline uintptr_t Status::MovedFromRep() {
+ return CodeToInlinedRep(absl::StatusCode::kInternal) | 2;
+}
+
+inline uintptr_t Status::CodeToInlinedRep(absl::StatusCode code) {
+ return static_cast<uintptr_t>(code) << 2;
+}
+
+inline absl::StatusCode Status::InlinedRepToCode(uintptr_t rep) {
+ assert(IsInlined(rep));
+ return static_cast<absl::StatusCode>(rep >> 2);
+}
+
+inline status_internal::StatusRep* Status::RepToPointer(uintptr_t rep) {
+ assert(!IsInlined(rep));
+ return reinterpret_cast<status_internal::StatusRep*>(rep - 1);
+}
+
+inline uintptr_t Status::PointerToRep(status_internal::StatusRep* rep) {
+ return reinterpret_cast<uintptr_t>(rep) + 1;
+}
+
+inline void Status::Ref(uintptr_t rep) {
+ if (!IsInlined(rep)) {
+ RepToPointer(rep)->ref.fetch_add(1, std::memory_order_relaxed);
+ }
+}
+
+inline void Status::Unref(uintptr_t rep) {
+ if (!IsInlined(rep)) {
+ UnrefNonInlined(rep);
+ }
+}
+
+inline Status OkStatus() { return Status(); }
+
+// Creates a `Status` object with the `absl::StatusCode::kCancelled` error code
+// and an empty message. It is provided only for efficiency, given that
+// message-less kCancelled errors are common in the infrastructure.
+inline Status CancelledError() { return Status(absl::StatusCode::kCancelled); }
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STATUS_STATUS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.cc
new file mode 100644
index 00000000000..a47aea11c2d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.cc
@@ -0,0 +1,38 @@
+// 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.
+#include "absl/status/status_payload_printer.h"
+
+#include <atomic>
+
+#include "absl/base/attributes.h"
+#include "absl/base/internal/atomic_hook.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace status_internal {
+
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+static absl::base_internal::AtomicHook<StatusPayloadPrinter> storage;
+
+void SetStatusPayloadPrinter(StatusPayloadPrinter printer) {
+ storage.Store(printer);
+}
+
+StatusPayloadPrinter GetStatusPayloadPrinter() {
+ return storage.Load();
+}
+
+} // namespace status_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.h
new file mode 100644
index 00000000000..5e0937f67da
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_payload_printer.h
@@ -0,0 +1,51 @@
+// 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_STATUS_STATUS_PAYLOAD_PRINTER_H_
+#define ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
+
+#include <string>
+
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace status_internal {
+
+// By default, `Status::ToString` and `operator<<(Status)` print a payload by
+// dumping the type URL and the raw bytes. To help debugging, we provide an
+// extension point, which is a global printer function that can be set by users
+// to specify how to print payloads. The function takes the type URL and the
+// payload as input, and should return a valid human-readable string on success
+// or `absl::nullopt` on failure (in which case it falls back to the default
+// approach of printing the raw bytes).
+// NOTE: This is an internal API and the design is subject to change in the
+// future in a non-backward-compatible way. Since it's only meant for debugging
+// purpose, you should not rely on it in any critical logic.
+using StatusPayloadPrinter = absl::optional<std::string> (*)(absl::string_view,
+ const absl::Cord&);
+
+// Sets the global payload printer. Only one printer should be set per process.
+// If multiple printers are set, it's undefined which one will be used.
+void SetStatusPayloadPrinter(StatusPayloadPrinter);
+
+// Returns the global payload printer if previously set, otherwise `nullptr`.
+StatusPayloadPrinter GetStatusPayloadPrinter();
+
+} // namespace status_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STATUS_STATUS_PAYLOAD_PRINTER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_test.cc
new file mode 100644
index 00000000000..0e1a43ce0ed
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/status_test.cc
@@ -0,0 +1,484 @@
+// 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.
+
+#include "absl/status/status.h"
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/strings/str_cat.h"
+
+namespace {
+
+using ::testing::Eq;
+using ::testing::HasSubstr;
+using ::testing::Optional;
+using ::testing::UnorderedElementsAreArray;
+
+TEST(StatusCode, InsertionOperator) {
+ const absl::StatusCode code = absl::StatusCode::kUnknown;
+ std::ostringstream oss;
+ oss << code;
+ EXPECT_EQ(oss.str(), absl::StatusCodeToString(code));
+}
+
+// This structure holds the details for testing a single error code,
+// its creator, and its classifier.
+struct ErrorTest {
+ absl::StatusCode code;
+ using Creator = absl::Status (*)(absl::string_view);
+ using Classifier = bool (*)(const absl::Status&);
+ Creator creator;
+ Classifier classifier;
+};
+
+constexpr ErrorTest kErrorTests[]{
+ {absl::StatusCode::kCancelled, absl::CancelledError, absl::IsCancelled},
+ {absl::StatusCode::kUnknown, absl::UnknownError, absl::IsUnknown},
+ {absl::StatusCode::kInvalidArgument, absl::InvalidArgumentError,
+ absl::IsInvalidArgument},
+ {absl::StatusCode::kDeadlineExceeded, absl::DeadlineExceededError,
+ absl::IsDeadlineExceeded},
+ {absl::StatusCode::kNotFound, absl::NotFoundError, absl::IsNotFound},
+ {absl::StatusCode::kAlreadyExists, absl::AlreadyExistsError,
+ absl::IsAlreadyExists},
+ {absl::StatusCode::kPermissionDenied, absl::PermissionDeniedError,
+ absl::IsPermissionDenied},
+ {absl::StatusCode::kResourceExhausted, absl::ResourceExhaustedError,
+ absl::IsResourceExhausted},
+ {absl::StatusCode::kFailedPrecondition, absl::FailedPreconditionError,
+ absl::IsFailedPrecondition},
+ {absl::StatusCode::kAborted, absl::AbortedError, absl::IsAborted},
+ {absl::StatusCode::kOutOfRange, absl::OutOfRangeError, absl::IsOutOfRange},
+ {absl::StatusCode::kUnimplemented, absl::UnimplementedError,
+ absl::IsUnimplemented},
+ {absl::StatusCode::kInternal, absl::InternalError, absl::IsInternal},
+ {absl::StatusCode::kUnavailable, absl::UnavailableError,
+ absl::IsUnavailable},
+ {absl::StatusCode::kDataLoss, absl::DataLossError, absl::IsDataLoss},
+ {absl::StatusCode::kUnauthenticated, absl::UnauthenticatedError,
+ absl::IsUnauthenticated},
+};
+
+TEST(Status, CreateAndClassify) {
+ for (const auto& test : kErrorTests) {
+ SCOPED_TRACE(absl::StatusCodeToString(test.code));
+
+ // Ensure that the creator does, in fact, create status objects with the
+ // expected error code and message.
+ std::string message =
+ absl::StrCat("error code ", test.code, " test message");
+ absl::Status status = test.creator(message);
+ EXPECT_EQ(test.code, status.code());
+ EXPECT_EQ(message, status.message());
+
+ // Ensure that the classifier returns true for a status produced by the
+ // creator.
+ EXPECT_TRUE(test.classifier(status));
+
+ // Ensure that the classifier returns false for status with a different
+ // code.
+ for (const auto& other : kErrorTests) {
+ if (other.code != test.code) {
+ EXPECT_FALSE(test.classifier(absl::Status(other.code, "")))
+ << " other.code = " << other.code;
+ }
+ }
+ }
+}
+
+TEST(Status, DefaultConstructor) {
+ absl::Status status;
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(absl::StatusCode::kOk, status.code());
+ EXPECT_EQ("", status.message());
+}
+
+TEST(Status, OkStatus) {
+ absl::Status status = absl::OkStatus();
+ EXPECT_TRUE(status.ok());
+ EXPECT_EQ(absl::StatusCode::kOk, status.code());
+ EXPECT_EQ("", status.message());
+}
+
+TEST(Status, ConstructorWithCodeMessage) {
+ {
+ absl::Status status(absl::StatusCode::kCancelled, "");
+ EXPECT_FALSE(status.ok());
+ EXPECT_EQ(absl::StatusCode::kCancelled, status.code());
+ EXPECT_EQ("", status.message());
+ }
+ {
+ absl::Status status(absl::StatusCode::kInternal, "message");
+ EXPECT_FALSE(status.ok());
+ EXPECT_EQ(absl::StatusCode::kInternal, status.code());
+ EXPECT_EQ("message", status.message());
+ }
+}
+
+TEST(Status, ConstructOutOfRangeCode) {
+ const int kRawCode = 9999;
+ absl::Status status(static_cast<absl::StatusCode>(kRawCode), "");
+ EXPECT_EQ(absl::StatusCode::kUnknown, status.code());
+ EXPECT_EQ(kRawCode, status.raw_code());
+}
+
+constexpr char kUrl1[] = "url.payload.1";
+constexpr char kUrl2[] = "url.payload.2";
+constexpr char kUrl3[] = "url.payload.3";
+constexpr char kUrl4[] = "url.payload.xx";
+
+constexpr char kPayload1[] = "aaaaa";
+constexpr char kPayload2[] = "bbbbb";
+constexpr char kPayload3[] = "ccccc";
+
+using PayloadsVec = std::vector<std::pair<std::string, absl::Cord>>;
+
+TEST(Status, TestGetSetPayload) {
+ absl::Status ok_status = absl::OkStatus();
+ ok_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ ok_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+ EXPECT_FALSE(ok_status.GetPayload(kUrl1));
+ EXPECT_FALSE(ok_status.GetPayload(kUrl2));
+
+ absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+ bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+ EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload1)));
+ EXPECT_THAT(bad_status.GetPayload(kUrl2), Optional(Eq(kPayload2)));
+
+ EXPECT_FALSE(bad_status.GetPayload(kUrl3));
+
+ bad_status.SetPayload(kUrl1, absl::Cord(kPayload3));
+ EXPECT_THAT(bad_status.GetPayload(kUrl1), Optional(Eq(kPayload3)));
+
+ // Testing dynamically generated type_url
+ bad_status.SetPayload(absl::StrCat(kUrl1, ".1"), absl::Cord(kPayload1));
+ EXPECT_THAT(bad_status.GetPayload(absl::StrCat(kUrl1, ".1")),
+ Optional(Eq(kPayload1)));
+}
+
+TEST(Status, TestErasePayload) {
+ absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+ bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+ bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+ EXPECT_FALSE(bad_status.ErasePayload(kUrl4));
+
+ EXPECT_TRUE(bad_status.GetPayload(kUrl2));
+ EXPECT_TRUE(bad_status.ErasePayload(kUrl2));
+ EXPECT_FALSE(bad_status.GetPayload(kUrl2));
+ EXPECT_FALSE(bad_status.ErasePayload(kUrl2));
+
+ EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
+ EXPECT_TRUE(bad_status.ErasePayload(kUrl3));
+
+ bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ EXPECT_TRUE(bad_status.ErasePayload(kUrl1));
+}
+
+TEST(Status, TestComparePayloads) {
+ absl::Status bad_status1(absl::StatusCode::kInternal, "fail");
+ bad_status1.SetPayload(kUrl1, absl::Cord(kPayload1));
+ bad_status1.SetPayload(kUrl2, absl::Cord(kPayload2));
+ bad_status1.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+ absl::Status bad_status2(absl::StatusCode::kInternal, "fail");
+ bad_status2.SetPayload(kUrl2, absl::Cord(kPayload2));
+ bad_status2.SetPayload(kUrl3, absl::Cord(kPayload3));
+ bad_status2.SetPayload(kUrl1, absl::Cord(kPayload1));
+
+ EXPECT_EQ(bad_status1, bad_status2);
+}
+
+TEST(Status, TestComparePayloadsAfterErase) {
+ absl::Status payload_status(absl::StatusCode::kInternal, "");
+ payload_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ payload_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+
+ absl::Status empty_status(absl::StatusCode::kInternal, "");
+
+ // Different payloads, not equal
+ EXPECT_NE(payload_status, empty_status);
+ EXPECT_TRUE(payload_status.ErasePayload(kUrl1));
+
+ // Still Different payloads, still not equal.
+ EXPECT_NE(payload_status, empty_status);
+ EXPECT_TRUE(payload_status.ErasePayload(kUrl2));
+
+ // Both empty payloads, should be equal
+ EXPECT_EQ(payload_status, empty_status);
+}
+
+PayloadsVec AllVisitedPayloads(const absl::Status& s) {
+ PayloadsVec result;
+
+ s.ForEachPayload([&](absl::string_view type_url, const absl::Cord& payload) {
+ result.push_back(std::make_pair(std::string(type_url), payload));
+ });
+
+ return result;
+}
+
+TEST(Status, TestForEachPayload) {
+ absl::Status bad_status(absl::StatusCode::kInternal, "fail");
+ bad_status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ bad_status.SetPayload(kUrl2, absl::Cord(kPayload2));
+ bad_status.SetPayload(kUrl3, absl::Cord(kPayload3));
+
+ int count = 0;
+
+ bad_status.ForEachPayload(
+ [&count](absl::string_view, const absl::Cord&) { ++count; });
+
+ EXPECT_EQ(count, 3);
+
+ PayloadsVec expected_payloads = {{kUrl1, absl::Cord(kPayload1)},
+ {kUrl2, absl::Cord(kPayload2)},
+ {kUrl3, absl::Cord(kPayload3)}};
+
+ // Test that we visit all the payloads in the status.
+ PayloadsVec visited_payloads = AllVisitedPayloads(bad_status);
+ EXPECT_THAT(visited_payloads, UnorderedElementsAreArray(expected_payloads));
+
+ // Test that visitation order is not consistent between run.
+ std::vector<absl::Status> scratch;
+ while (true) {
+ scratch.emplace_back(absl::StatusCode::kInternal, "fail");
+
+ scratch.back().SetPayload(kUrl1, absl::Cord(kPayload1));
+ scratch.back().SetPayload(kUrl2, absl::Cord(kPayload2));
+ scratch.back().SetPayload(kUrl3, absl::Cord(kPayload3));
+
+ if (AllVisitedPayloads(scratch.back()) != visited_payloads) {
+ break;
+ }
+ }
+}
+
+TEST(Status, ToString) {
+ absl::Status s(absl::StatusCode::kInternal, "fail");
+ EXPECT_EQ("INTERNAL: fail", s.ToString());
+ s.SetPayload("foo", absl::Cord("bar"));
+ EXPECT_EQ("INTERNAL: fail [foo='bar']", s.ToString());
+ s.SetPayload("bar", absl::Cord("\377"));
+ EXPECT_THAT(s.ToString(),
+ AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+ HasSubstr("[bar='\\xff']")));
+}
+
+TEST(Status, ToStringMode) {
+ absl::Status s(absl::StatusCode::kInternal, "fail");
+ s.SetPayload("foo", absl::Cord("bar"));
+ s.SetPayload("bar", absl::Cord("\377"));
+
+ EXPECT_EQ("INTERNAL: fail",
+ s.ToString(absl::StatusToStringMode::kWithNoExtraData));
+
+ EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithPayload),
+ AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+ HasSubstr("[bar='\\xff']")));
+
+ EXPECT_THAT(s.ToString(absl::StatusToStringMode::kWithEverything),
+ AllOf(HasSubstr("INTERNAL: fail"), HasSubstr("[foo='bar']"),
+ HasSubstr("[bar='\\xff']")));
+
+ EXPECT_THAT(s.ToString(~absl::StatusToStringMode::kWithPayload),
+ AllOf(HasSubstr("INTERNAL: fail"), Not(HasSubstr("[foo='bar']")),
+ Not(HasSubstr("[bar='\\xff']"))));
+}
+
+absl::Status EraseAndReturn(const absl::Status& base) {
+ absl::Status copy = base;
+ EXPECT_TRUE(copy.ErasePayload(kUrl1));
+ return copy;
+}
+
+TEST(Status, CopyOnWriteForErasePayload) {
+ {
+ absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
+ base.SetPayload(kUrl1, absl::Cord(kPayload1));
+ EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+ absl::Status copy = EraseAndReturn(base);
+ EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+ EXPECT_FALSE(copy.GetPayload(kUrl1).has_value());
+ }
+ {
+ absl::Status base(absl::StatusCode::kInvalidArgument, "fail");
+ base.SetPayload(kUrl1, absl::Cord(kPayload1));
+ absl::Status copy = base;
+
+ EXPECT_TRUE(base.GetPayload(kUrl1).has_value());
+ EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
+
+ EXPECT_TRUE(base.ErasePayload(kUrl1));
+
+ EXPECT_FALSE(base.GetPayload(kUrl1).has_value());
+ EXPECT_TRUE(copy.GetPayload(kUrl1).has_value());
+ }
+}
+
+TEST(Status, CopyConstructor) {
+ {
+ absl::Status status;
+ absl::Status copy(status);
+ EXPECT_EQ(copy, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ absl::Status copy(status);
+ EXPECT_EQ(copy, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ absl::Status copy(status);
+ EXPECT_EQ(copy, status);
+ }
+}
+
+TEST(Status, CopyAssignment) {
+ absl::Status assignee;
+ {
+ absl::Status status;
+ assignee = status;
+ EXPECT_EQ(assignee, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ assignee = status;
+ EXPECT_EQ(assignee, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ assignee = status;
+ EXPECT_EQ(assignee, status);
+ }
+}
+
+TEST(Status, CopyAssignmentIsNotRef) {
+ const absl::Status status_orig(absl::StatusCode::kInvalidArgument, "message");
+ absl::Status status_copy = status_orig;
+ EXPECT_EQ(status_orig, status_copy);
+ status_copy.SetPayload(kUrl1, absl::Cord(kPayload1));
+ EXPECT_NE(status_orig, status_copy);
+}
+
+TEST(Status, MoveConstructor) {
+ {
+ absl::Status status;
+ absl::Status copy(absl::Status{});
+ EXPECT_EQ(copy, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ absl::Status copy(
+ absl::Status(absl::StatusCode::kInvalidArgument, "message"));
+ EXPECT_EQ(copy, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ absl::Status copy1(status);
+ absl::Status copy2(std::move(status));
+ EXPECT_EQ(copy1, copy2);
+ }
+}
+
+TEST(Status, MoveAssignment) {
+ absl::Status assignee;
+ {
+ absl::Status status;
+ assignee = absl::Status();
+ EXPECT_EQ(assignee, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ assignee = absl::Status(absl::StatusCode::kInvalidArgument, "message");
+ EXPECT_EQ(assignee, status);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ status.SetPayload(kUrl1, absl::Cord(kPayload1));
+ absl::Status copy(status);
+ assignee = std::move(status);
+ EXPECT_EQ(assignee, copy);
+ }
+ {
+ absl::Status status(absl::StatusCode::kInvalidArgument, "message");
+ absl::Status copy(status);
+ status = static_cast<absl::Status&&>(status);
+ EXPECT_EQ(status, copy);
+ }
+}
+
+TEST(Status, Update) {
+ absl::Status s;
+ s.Update(absl::OkStatus());
+ EXPECT_TRUE(s.ok());
+ const absl::Status a(absl::StatusCode::kCancelled, "message");
+ s.Update(a);
+ EXPECT_EQ(s, a);
+ const absl::Status b(absl::StatusCode::kInternal, "other message");
+ s.Update(b);
+ EXPECT_EQ(s, a);
+ s.Update(absl::OkStatus());
+ EXPECT_EQ(s, a);
+ EXPECT_FALSE(s.ok());
+}
+
+TEST(Status, Equality) {
+ absl::Status ok;
+ absl::Status no_payload = absl::CancelledError("no payload");
+ absl::Status one_payload = absl::InvalidArgumentError("one payload");
+ one_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
+ absl::Status two_payloads = one_payload;
+ two_payloads.SetPayload(kUrl2, absl::Cord(kPayload2));
+ const std::array<absl::Status, 4> status_arr = {ok, no_payload, one_payload,
+ two_payloads};
+ for (int i = 0; i < status_arr.size(); i++) {
+ for (int j = 0; j < status_arr.size(); j++) {
+ if (i == j) {
+ EXPECT_TRUE(status_arr[i] == status_arr[j]);
+ EXPECT_FALSE(status_arr[i] != status_arr[j]);
+ } else {
+ EXPECT_TRUE(status_arr[i] != status_arr[j]);
+ EXPECT_FALSE(status_arr[i] == status_arr[j]);
+ }
+ }
+ }
+}
+
+TEST(Status, Swap) {
+ auto test_swap = [](const absl::Status& s1, const absl::Status& s2) {
+ absl::Status copy1 = s1, copy2 = s2;
+ swap(copy1, copy2);
+ EXPECT_EQ(copy1, s2);
+ EXPECT_EQ(copy2, s1);
+ };
+ const absl::Status ok;
+ const absl::Status no_payload(absl::StatusCode::kAlreadyExists, "no payload");
+ absl::Status with_payload(absl::StatusCode::kInternal, "with payload");
+ with_payload.SetPayload(kUrl1, absl::Cord(kPayload1));
+ test_swap(ok, no_payload);
+ test_swap(no_payload, ok);
+ test_swap(ok, with_payload);
+ test_swap(with_payload, ok);
+ test_swap(no_payload, with_payload);
+ test_swap(with_payload, no_payload);
+}
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.cc
new file mode 100644
index 00000000000..b954b45e32c
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/status/statusor.h"
+
+#include <cstdlib>
+#include <utility>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+BadStatusOrAccess::BadStatusOrAccess(absl::Status status)
+ : status_(std::move(status)) {}
+
+BadStatusOrAccess::~BadStatusOrAccess() = default;
+const char* BadStatusOrAccess::what() const noexcept {
+ return "Bad StatusOr access";
+}
+
+const absl::Status& BadStatusOrAccess::status() const { return status_; }
+
+namespace internal_statusor {
+
+void Helper::HandleInvalidStatusCtorArg(absl::Status* status) {
+ const char* kMessage =
+ "An OK status is not a valid constructor argument to StatusOr<T>";
+#ifdef NDEBUG
+ ABSL_INTERNAL_LOG(ERROR, kMessage);
+#else
+ ABSL_INTERNAL_LOG(FATAL, kMessage);
+#endif
+ // In optimized builds, we will fall back to InternalError.
+ *status = absl::InternalError(kMessage);
+}
+
+void Helper::Crash(const absl::Status& status) {
+ ABSL_INTERNAL_LOG(
+ FATAL,
+ absl::StrCat("Attempting to fetch value instead of handling error ",
+ status.ToString()));
+}
+
+void ThrowBadStatusOrAccess(absl::Status status) {
+#ifdef ABSL_HAVE_EXCEPTIONS
+ throw absl::BadStatusOrAccess(std::move(status));
+#else
+ ABSL_INTERNAL_LOG(
+ FATAL,
+ absl::StrCat("Attempting to fetch value instead of handling error ",
+ status.ToString()));
+ std::abort();
+#endif
+}
+
+} // namespace internal_statusor
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.h
new file mode 100644
index 00000000000..b7c55cc8acc
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor.h
@@ -0,0 +1,760 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: statusor.h
+// -----------------------------------------------------------------------------
+//
+// An `absl::StatusOr<T>` represents a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` will either contain an
+// object of type `T` (indicating a successful operation), or an error (of type
+// `absl::Status`) explaining why such a value is not present.
+//
+// In general, check the success of an operation returning an
+// `absl::StatusOr<T>` like you would an `absl::Status` by using the `ok()`
+// member function.
+//
+// Example:
+//
+// StatusOr<Foo> result = Calculation();
+// if (result.ok()) {
+// result->DoSomethingCool();
+// } else {
+// LOG(ERROR) << result.status();
+// }
+#ifndef ABSL_STATUS_STATUSOR_H_
+#define ABSL_STATUS_STATUSOR_H_
+
+#include <exception>
+#include <initializer_list>
+#include <new>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+#include "absl/status/internal/statusor_internal.h"
+#include "absl/status/status.h"
+#include "absl/types/variant.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// BadStatusOrAccess
+//
+// This class defines the type of object to throw (if exceptions are enabled),
+// when accessing the value of an `absl::StatusOr<T>` object that does not
+// contain a value. This behavior is analogous to that of
+// `std::bad_optional_access` in the case of accessing an invalid
+// `std::optional` value.
+//
+// Example:
+//
+// try {
+// absl::StatusOr<int> v = FetchInt();
+// DoWork(v.value()); // Accessing value() when not "OK" may throw
+// } catch (absl::BadStatusOrAccess& ex) {
+// LOG(ERROR) << ex.status();
+// }
+class BadStatusOrAccess : public std::exception {
+ public:
+ explicit BadStatusOrAccess(absl::Status status);
+ ~BadStatusOrAccess() override;
+
+ // BadStatusOrAccess::what()
+ //
+ // Returns the associated explanatory string of the `absl::StatusOr<T>`
+ // object's error code. This function only returns the string literal "Bad
+ // StatusOr Access" for cases when evaluating general exceptions.
+ //
+ // The pointer of this string is guaranteed to be valid until any non-const
+ // function is invoked on the exception object.
+ const char* what() const noexcept override;
+
+ // BadStatusOrAccess::status()
+ //
+ // Returns the associated `absl::Status` of the `absl::StatusOr<T>` object's
+ // error.
+ const absl::Status& status() const;
+
+ private:
+ absl::Status status_;
+};
+
+// Returned StatusOr objects may not be ignored.
+template <typename T>
+class ABSL_MUST_USE_RESULT StatusOr;
+
+// absl::StatusOr<T>
+//
+// The `absl::StatusOr<T>` class template is a union of an `absl::Status` object
+// and an object of type `T`. The `absl::StatusOr<T>` models an object that is
+// either a usable object, or an error (of type `absl::Status`) explaining why
+// such an object is not present. An `absl::StatusOr<T>` is typically the return
+// value of a function which may fail.
+//
+// An `absl::StatusOr<T>` can never hold an "OK" status (an
+// `absl::StatusCode::kOk` value); instead, the presence of an object of type
+// `T` indicates success. Instead of checking for a `kOk` value, use the
+// `absl::StatusOr<T>::ok()` member function. (It is for this reason, and code
+// readability, that using the `ok()` function is preferred for `absl::Status`
+// as well.)
+//
+// Example:
+//
+// StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+// if (result.ok()) {
+// result->DoSomethingCool();
+// } else {
+// LOG(ERROR) << result.status();
+// }
+//
+// Accessing the object held by an `absl::StatusOr<T>` should be performed via
+// `operator*` or `operator->`, after a call to `ok()` confirms that the
+// `absl::StatusOr<T>` holds an object of type `T`:
+//
+// Example:
+//
+// absl::StatusOr<int> i = GetCount();
+// if (i.ok()) {
+// updated_total += *i
+// }
+//
+// NOTE: using `absl::StatusOr<T>::value()` when no valid value is present will
+// throw an exception if exceptions are enabled or terminate the process when
+// exceptions are not enabled.
+//
+// Example:
+//
+// StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+// const Foo& foo = result.value(); // Crash/exception if no value present
+// foo.DoSomethingCool();
+//
+// A `absl::StatusOr<T*>` can be constructed from a null pointer like any other
+// pointer value, and the result will be that `ok()` returns `true` and
+// `value()` returns `nullptr`. Checking the value of pointer in an
+// `absl::StatusOr<T>` generally requires a bit more care, to ensure both that a
+// value is present and that value is not null:
+//
+// StatusOr<std::unique_ptr<Foo>> result = FooFactory::MakeNewFoo(arg);
+// if (!result.ok()) {
+// LOG(ERROR) << result.status();
+// } else if (*result == nullptr) {
+// LOG(ERROR) << "Unexpected null pointer";
+// } else {
+// (*result)->DoSomethingCool();
+// }
+//
+// Example factory implementation returning StatusOr<T>:
+//
+// StatusOr<Foo> FooFactory::MakeFoo(int arg) {
+// if (arg <= 0) {
+// return absl::Status(absl::StatusCode::kInvalidArgument,
+// "Arg must be positive");
+// }
+// return Foo(arg);
+// }
+template <typename T>
+class StatusOr : private internal_statusor::StatusOrData<T>,
+ private internal_statusor::CopyCtorBase<T>,
+ private internal_statusor::MoveCtorBase<T>,
+ private internal_statusor::CopyAssignBase<T>,
+ private internal_statusor::MoveAssignBase<T> {
+ template <typename U>
+ friend class StatusOr;
+
+ typedef internal_statusor::StatusOrData<T> Base;
+
+ public:
+ // StatusOr<T>::value_type
+ //
+ // This instance data provides a generic `value_type` member for use within
+ // generic programming. This usage is analogous to that of
+ // `optional::value_type` in the case of `std::optional`.
+ typedef T value_type;
+
+ // Constructors
+
+ // Constructs a new `absl::StatusOr` with an `absl::StatusCode::kUnknown`
+ // status. This constructor is marked 'explicit' to prevent usages in return
+ // values such as 'return {};', under the misconception that
+ // `absl::StatusOr<std::vector<int>>` will be initialized with an empty
+ // vector, instead of an `absl::StatusCode::kUnknown` error code.
+ explicit StatusOr();
+
+ // `StatusOr<T>` is copy constructible if `T` is copy constructible.
+ StatusOr(const StatusOr&) = default;
+ // `StatusOr<T>` is copy assignable if `T` is copy constructible and copy
+ // assignable.
+ StatusOr& operator=(const StatusOr&) = default;
+
+ // `StatusOr<T>` is move constructible if `T` is move constructible.
+ StatusOr(StatusOr&&) = default;
+ // `StatusOr<T>` is moveAssignable if `T` is move constructible and move
+ // assignable.
+ StatusOr& operator=(StatusOr&&) = default;
+
+ // Converting Constructors
+
+ // Constructs a new `absl::StatusOr<T>` from an `absl::StatusOr<U>`, when `T`
+ // is constructible from `U`. To avoid ambiguity, these constructors are
+ // disabled if `T` is also constructible from `StatusOr<U>.`. This constructor
+ // is explicit if and only if the corresponding construction of `T` from `U`
+ // is explicit. (This constructor inherits its explicitness from the
+ // underlying constructor.)
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>,
+ std::is_convertible<const U&, T>,
+ absl::negation<
+ internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ StatusOr(const StatusOr<U>& other) // NOLINT
+ : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>,
+ absl::negation<std::is_convertible<const U&, T>>,
+ absl::negation<
+ internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ explicit StatusOr(const StatusOr<U>& other)
+ : Base(static_cast<const typename StatusOr<U>::Base&>(other)) {}
+
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ std::is_convertible<U&&, T>,
+ absl::negation<
+ internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ StatusOr(StatusOr<U>&& other) // NOLINT
+ : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ absl::negation<std::is_convertible<U&&, T>>,
+ absl::negation<
+ internal_statusor::IsConstructibleOrConvertibleFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ explicit StatusOr(StatusOr<U>&& other)
+ : Base(static_cast<typename StatusOr<U>::Base&&>(other)) {}
+
+ // Converting Assignment Operators
+
+ // Creates an `absl::StatusOr<T>` through assignment from an
+ // `absl::StatusOr<U>` when:
+ //
+ // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` are OK by assigning
+ // `U` to `T` directly.
+ // * `absl::StatusOr<T>` is OK and `absl::StatusOr<U>` contains an error
+ // code by destroying `absl::StatusOr<T>`'s value and assigning from
+ // `absl::StatusOr<U>'
+ // * `absl::StatusOr<T>` contains an error code and `absl::StatusOr<U>` is
+ // OK by directly initializing `T` from `U`.
+ // * Both `absl::StatusOr<T>` and `absl::StatusOr<U>` contain an error
+ // code by assigning the `Status` in `absl::StatusOr<U>` to
+ // `absl::StatusOr<T>`
+ //
+ // These overloads only apply if `absl::StatusOr<T>` is constructible and
+ // assignable from `absl::StatusOr<U>` and `StatusOr<T>` cannot be directly
+ // assigned from `StatusOr<U>`.
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>,
+ std::is_constructible<T, const U&>,
+ std::is_assignable<T, const U&>,
+ absl::negation<
+ internal_statusor::
+ IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ StatusOr& operator=(const StatusOr<U>& other) {
+ this->Assign(other);
+ return *this;
+ }
+ template <
+ typename U,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_same<T, U>>, std::is_constructible<T, U&&>,
+ std::is_assignable<T, U&&>,
+ absl::negation<
+ internal_statusor::
+ IsConstructibleOrConvertibleOrAssignableFromStatusOr<
+ T, U>>>::value,
+ int> = 0>
+ StatusOr& operator=(StatusOr<U>&& other) {
+ this->Assign(std::move(other));
+ return *this;
+ }
+
+ // Constructs a new `absl::StatusOr<T>` with a non-ok status. After calling
+ // this constructor, `this->ok()` will be `false` and calls to `value()` will
+ // crash, or produce an exception if exceptions are enabled.
+ //
+ // The constructor also takes any type `U` that is convertible to
+ // `absl::Status`. This constructor is explicit if an only if `U` is not of
+ // type `absl::Status` and the conversion from `U` to `Status` is explicit.
+ //
+ // REQUIRES: !Status(std::forward<U>(v)).ok(). This requirement is DCHECKed.
+ // In optimized builds, passing absl::OkStatus() here will have the effect
+ // of passing absl::StatusCode::kInternal as a fallback.
+ template <
+ typename U = absl::Status,
+ absl::enable_if_t<
+ absl::conjunction<
+ std::is_convertible<U&&, absl::Status>,
+ std::is_constructible<absl::Status, U&&>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+ absl::negation<std::is_same<absl::decay_t<U>, T>>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+ absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+ T, U&&>>>::value,
+ int> = 0>
+ StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+ template <
+ typename U = absl::Status,
+ absl::enable_if_t<
+ absl::conjunction<
+ absl::negation<std::is_convertible<U&&, absl::Status>>,
+ std::is_constructible<absl::Status, U&&>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+ absl::negation<std::is_same<absl::decay_t<U>, T>>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+ absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+ T, U&&>>>::value,
+ int> = 0>
+ explicit StatusOr(U&& v) : Base(std::forward<U>(v)) {}
+
+ template <
+ typename U = absl::Status,
+ absl::enable_if_t<
+ absl::conjunction<
+ std::is_convertible<U&&, absl::Status>,
+ std::is_constructible<absl::Status, U&&>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::StatusOr<T>>>,
+ absl::negation<std::is_same<absl::decay_t<U>, T>>,
+ absl::negation<std::is_same<absl::decay_t<U>, absl::in_place_t>>,
+ absl::negation<internal_statusor::HasConversionOperatorToStatusOr<
+ T, U&&>>>::value,
+ int> = 0>
+ StatusOr& operator=(U&& v) {
+ this->AssignStatus(std::forward<U>(v));
+ return *this;
+ }
+
+ // Perfect-forwarding value assignment operator.
+
+ // If `*this` contains a `T` value before the call, the contained value is
+ // assigned from `std::forward<U>(v)`; Otherwise, it is directly-initialized
+ // from `std::forward<U>(v)`.
+ // This function does not participate in overload unless:
+ // 1. `std::is_constructible_v<T, U>` is true,
+ // 2. `std::is_assignable_v<T&, U>` is true.
+ // 3. `std::is_same_v<StatusOr<T>, std::remove_cvref_t<U>>` is false.
+ // 4. Assigning `U` to `T` is not ambiguous:
+ // If `U` is `StatusOr<V>` and `T` is constructible and assignable from
+ // both `StatusOr<V>` and `V`, the assignment is considered bug-prone and
+ // ambiguous thus will fail to compile. For example:
+ // StatusOr<bool> s1 = true; // s1.ok() && *s1 == true
+ // StatusOr<bool> s2 = false; // s2.ok() && *s2 == false
+ // s1 = s2; // ambiguous, `s1 = *s2` or `s1 = bool(s2)`?
+ template <
+ typename U = T,
+ typename = typename std::enable_if<absl::conjunction<
+ std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>,
+ absl::disjunction<
+ std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>, T>,
+ absl::conjunction<
+ absl::negation<std::is_convertible<U&&, absl::Status>>,
+ absl::negation<internal_statusor::
+ HasConversionOperatorToStatusOr<T, U&&>>>>,
+ internal_statusor::IsForwardingAssignmentValid<T, U&&>>::value>::type>
+ StatusOr& operator=(U&& v) {
+ this->Assign(std::forward<U>(v));
+ return *this;
+ }
+
+ // Constructs the inner value `T` in-place using the provided args, using the
+ // `T(args...)` constructor.
+ template <typename... Args>
+ explicit StatusOr(absl::in_place_t, Args&&... args);
+ template <typename U, typename... Args>
+ explicit StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+ Args&&... args);
+
+ // Constructs the inner value `T` in-place using the provided args, using the
+ // `T(U)` (direct-initialization) constructor. This constructor is only valid
+ // if `T` can be constructed from a `U`. Can accept move or copy constructors.
+ //
+ // This constructor is explicit if `U` is not convertible to `T`. To avoid
+ // ambiguity, this constuctor is disabled if `U` is a `StatusOr<J>`, where `J`
+ // is convertible to `T`.
+ template <
+ typename U = T,
+ absl::enable_if_t<
+ absl::conjunction<
+ internal_statusor::IsDirectInitializationValid<T, U&&>,
+ std::is_constructible<T, U&&>, std::is_convertible<U&&, T>,
+ absl::disjunction<
+ std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+ T>,
+ absl::conjunction<
+ absl::negation<std::is_convertible<U&&, absl::Status>>,
+ absl::negation<
+ internal_statusor::HasConversionOperatorToStatusOr<
+ T, U&&>>>>>::value,
+ int> = 0>
+ StatusOr(U&& u) // NOLINT
+ : StatusOr(absl::in_place, std::forward<U>(u)) {
+ }
+
+ template <
+ typename U = T,
+ absl::enable_if_t<
+ absl::conjunction<
+ internal_statusor::IsDirectInitializationValid<T, U&&>,
+ absl::disjunction<
+ std::is_same<absl::remove_cv_t<absl::remove_reference_t<U>>,
+ T>,
+ absl::conjunction<
+ absl::negation<std::is_constructible<absl::Status, U&&>>,
+ absl::negation<
+ internal_statusor::HasConversionOperatorToStatusOr<
+ T, U&&>>>>,
+ std::is_constructible<T, U&&>,
+ absl::negation<std::is_convertible<U&&, T>>>::value,
+ int> = 0>
+ explicit StatusOr(U&& u) // NOLINT
+ : StatusOr(absl::in_place, std::forward<U>(u)) {
+ }
+
+ // StatusOr<T>::ok()
+ //
+ // Returns whether or not this `absl::StatusOr<T>` holds a `T` value. This
+ // member function is analagous to `absl::Status::ok()` and should be used
+ // similarly to check the status of return values.
+ //
+ // Example:
+ //
+ // StatusOr<Foo> result = DoBigCalculationThatCouldFail();
+ // if (result.ok()) {
+ // // Handle result
+ // else {
+ // // Handle error
+ // }
+ ABSL_MUST_USE_RESULT bool ok() const { return this->status_.ok(); }
+
+ // StatusOr<T>::status()
+ //
+ // Returns a reference to the current `absl::Status` contained within the
+ // `absl::StatusOr<T>`. If `absl::StatusOr<T>` contains a `T`, then this
+ // function returns `absl::OkStatus()`.
+ const Status& status() const &;
+ Status status() &&;
+
+ // StatusOr<T>::value()
+ //
+ // Returns a reference to the held value if `this->ok()`. Otherwise, throws
+ // `absl::BadStatusOrAccess` if exceptions are enabled, or is guaranteed to
+ // terminate the process if exceptions are disabled.
+ //
+ // If you have already checked the status using `this->ok()`, you probably
+ // want to use `operator*()` or `operator->()` to access the value instead of
+ // `value`.
+ //
+ // Note: for value types that are cheap to copy, prefer simple code:
+ //
+ // T value = statusor.value();
+ //
+ // Otherwise, if the value type is expensive to copy, but can be left
+ // in the StatusOr, simply assign to a reference:
+ //
+ // T& value = statusor.value(); // or `const T&`
+ //
+ // Otherwise, if the value type supports an efficient move, it can be
+ // used as follows:
+ //
+ // T value = std::move(statusor).value();
+ //
+ // The `std::move` on statusor instead of on the whole expression enables
+ // warnings about possible uses of the statusor object after the move.
+ const T& value() const&;
+ T& value() &;
+ const T&& value() const&&;
+ T&& value() &&;
+
+ // StatusOr<T>:: operator*()
+ //
+ // Returns a reference to the current value.
+ //
+ // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+ //
+ // Use `this->ok()` to verify that there is a current value within the
+ // `absl::StatusOr<T>`. Alternatively, see the `value()` member function for a
+ // similar API that guarantees crashing or throwing an exception if there is
+ // no current value.
+ const T& operator*() const&;
+ T& operator*() &;
+ const T&& operator*() const&&;
+ T&& operator*() &&;
+
+ // StatusOr<T>::operator->()
+ //
+ // Returns a pointer to the current value.
+ //
+ // REQUIRES: `this->ok() == true`, otherwise the behavior is undefined.
+ //
+ // Use `this->ok()` to verify that there is a current value.
+ const T* operator->() const;
+ T* operator->();
+
+ // StatusOr<T>::value_or()
+ //
+ // Returns the current value if `this->ok() == true`. Otherwise constructs a
+ // value using the provided `default_value`.
+ //
+ // Unlike `value`, this function returns by value, copying the current value
+ // if necessary. If the value type supports an efficient move, it can be used
+ // as follows:
+ //
+ // T value = std::move(statusor).value_or(def);
+ //
+ // Unlike with `value`, calling `std::move()` on the result of `value_or` will
+ // still trigger a copy.
+ template <typename U>
+ T value_or(U&& default_value) const&;
+ template <typename U>
+ T value_or(U&& default_value) &&;
+
+ // StatusOr<T>::IgnoreError()
+ //
+ // Ignores any errors. This method does nothing except potentially suppress
+ // complaints from any tools that are checking that errors are not dropped on
+ // the floor.
+ void IgnoreError() const;
+
+ // StatusOr<T>::emplace()
+ //
+ // Reconstructs the inner value T in-place using the provided args, using the
+ // T(args...) constructor. Returns reference to the reconstructed `T`.
+ template <typename... Args>
+ T& emplace(Args&&... args) {
+ if (ok()) {
+ this->Clear();
+ this->MakeValue(std::forward<Args>(args)...);
+ } else {
+ this->MakeValue(std::forward<Args>(args)...);
+ this->status_ = absl::OkStatus();
+ }
+ return this->data_;
+ }
+
+ template <
+ typename U, typename... Args,
+ absl::enable_if_t<
+ std::is_constructible<T, std::initializer_list<U>&, Args&&...>::value,
+ int> = 0>
+ T& emplace(std::initializer_list<U> ilist, Args&&... args) {
+ if (ok()) {
+ this->Clear();
+ this->MakeValue(ilist, std::forward<Args>(args)...);
+ } else {
+ this->MakeValue(ilist, std::forward<Args>(args)...);
+ this->status_ = absl::OkStatus();
+ }
+ return this->data_;
+ }
+
+ private:
+ using internal_statusor::StatusOrData<T>::Assign;
+ template <typename U>
+ void Assign(const absl::StatusOr<U>& other);
+ template <typename U>
+ void Assign(absl::StatusOr<U>&& other);
+};
+
+// operator==()
+//
+// This operator checks the equality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator==(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+ if (lhs.ok() && rhs.ok()) return *lhs == *rhs;
+ return lhs.status() == rhs.status();
+}
+
+// operator!=()
+//
+// This operator checks the inequality of two `absl::StatusOr<T>` objects.
+template <typename T>
+bool operator!=(const StatusOr<T>& lhs, const StatusOr<T>& rhs) {
+ return !(lhs == rhs);
+}
+
+//------------------------------------------------------------------------------
+// Implementation details for StatusOr<T>
+//------------------------------------------------------------------------------
+
+// TODO(sbenza): avoid the string here completely.
+template <typename T>
+StatusOr<T>::StatusOr() : Base(Status(absl::StatusCode::kUnknown, "")) {}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(const StatusOr<U>& other) {
+ if (other.ok()) {
+ this->Assign(*other);
+ } else {
+ this->AssignStatus(other.status());
+ }
+}
+
+template <typename T>
+template <typename U>
+inline void StatusOr<T>::Assign(StatusOr<U>&& other) {
+ if (other.ok()) {
+ this->Assign(*std::move(other));
+ } else {
+ this->AssignStatus(std::move(other).status());
+ }
+}
+template <typename T>
+template <typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, Args&&... args)
+ : Base(absl::in_place, std::forward<Args>(args)...) {}
+
+template <typename T>
+template <typename U, typename... Args>
+StatusOr<T>::StatusOr(absl::in_place_t, std::initializer_list<U> ilist,
+ Args&&... args)
+ : Base(absl::in_place, ilist, std::forward<Args>(args)...) {}
+
+template <typename T>
+const Status& StatusOr<T>::status() const & { return this->status_; }
+template <typename T>
+Status StatusOr<T>::status() && {
+ return ok() ? OkStatus() : std::move(this->status_);
+}
+
+template <typename T>
+const T& StatusOr<T>::value() const& {
+ if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+ return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::value() & {
+ if (!this->ok()) internal_statusor::ThrowBadStatusOrAccess(this->status_);
+ return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::value() const&& {
+ if (!this->ok()) {
+ internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+ }
+ return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::value() && {
+ if (!this->ok()) {
+ internal_statusor::ThrowBadStatusOrAccess(std::move(this->status_));
+ }
+ return std::move(this->data_);
+}
+
+template <typename T>
+const T& StatusOr<T>::operator*() const& {
+ this->EnsureOk();
+ return this->data_;
+}
+
+template <typename T>
+T& StatusOr<T>::operator*() & {
+ this->EnsureOk();
+ return this->data_;
+}
+
+template <typename T>
+const T&& StatusOr<T>::operator*() const&& {
+ this->EnsureOk();
+ return std::move(this->data_);
+}
+
+template <typename T>
+T&& StatusOr<T>::operator*() && {
+ this->EnsureOk();
+ return std::move(this->data_);
+}
+
+template <typename T>
+const T* StatusOr<T>::operator->() const {
+ this->EnsureOk();
+ return &this->data_;
+}
+
+template <typename T>
+T* StatusOr<T>::operator->() {
+ this->EnsureOk();
+ return &this->data_;
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) const& {
+ if (ok()) {
+ return this->data_;
+ }
+ return std::forward<U>(default_value);
+}
+
+template <typename T>
+template <typename U>
+T StatusOr<T>::value_or(U&& default_value) && {
+ if (ok()) {
+ return std::move(this->data_);
+ }
+ return std::forward<U>(default_value);
+}
+
+template <typename T>
+void StatusOr<T>::IgnoreError() const {
+ // no-op
+}
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STATUS_STATUSOR_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor_test.cc
new file mode 100644
index 00000000000..c2e8fb7e359
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/status/statusor_test.cc
@@ -0,0 +1,1811 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/status/statusor.h"
+
+#include <array>
+#include <initializer_list>
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/memory/memory.h"
+#include "absl/status/status.h"
+#include "absl/types/any.h"
+#include "absl/utility/utility.h"
+
+namespace {
+
+using ::testing::AllOf;
+using ::testing::AnyWith;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::Ne;
+using ::testing::Not;
+using ::testing::Pointee;
+using ::testing::VariantWith;
+
+#ifdef GTEST_HAS_STATUS_MATCHERS
+using ::testing::status::IsOk;
+using ::testing::status::IsOkAndHolds;
+#else // GTEST_HAS_STATUS_MATCHERS
+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();
+}
+
+// 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 (!actual_value.ok()) {
+ *result_listener << "which has status " << actual_value.status();
+ return false;
+ }
+
+ ::testing::StringMatchResultListener inner_listener;
+ const bool matches =
+ inner_matcher_.MatchAndExplain(*actual_value, &inner_listener);
+ const std::string inner_explanation = inner_listener.str();
+ if (!inner_explanation.empty()) {
+ *result_listener << "which contains value "
+ << ::testing::PrintToString(*actual_value) << ", "
+ << inner_explanation;
+ }
+ return matches;
+ }
+
+ 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::move(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_;
+};
+
+// 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>
+ operator ::testing::Matcher<T>() const { // NOLINT
+ return ::testing::Matcher<T>(new MonoIsOkMatcherImpl<T>());
+ }
+};
+
+// Macros for testing the results of functions that return absl::Status or
+// absl::StatusOr<T> (for any type T).
+#define EXPECT_OK(expression) EXPECT_THAT(expression, IsOk())
+
+// Returns a gMock matcher that matches a StatusOr<> whose status is
+// OK and whose value matches the inner matcher.
+template <typename InnerMatcher>
+IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type> IsOkAndHolds(
+ InnerMatcher&& inner_matcher) {
+ return IsOkAndHoldsMatcher<typename std::decay<InnerMatcher>::type>(
+ std::forward<InnerMatcher>(inner_matcher));
+}
+
+// Returns a gMock matcher that matches a Status or StatusOr<> which is OK.
+inline IsOkMatcher IsOk() { return IsOkMatcher(); }
+#endif // GTEST_HAS_STATUS_MATCHERS
+
+struct CopyDetector {
+ CopyDetector() = default;
+ explicit CopyDetector(int xx) : x(xx) {}
+ CopyDetector(CopyDetector&& d) noexcept
+ : x(d.x), copied(false), moved(true) {}
+ CopyDetector(const CopyDetector& d) : x(d.x), copied(true), moved(false) {}
+ CopyDetector& operator=(const CopyDetector& c) {
+ x = c.x;
+ copied = true;
+ moved = false;
+ return *this;
+ }
+ CopyDetector& operator=(CopyDetector&& c) noexcept {
+ x = c.x;
+ copied = false;
+ moved = true;
+ return *this;
+ }
+ int x = 0;
+ bool copied = false;
+ bool moved = false;
+};
+
+testing::Matcher<const CopyDetector&> CopyDetectorHas(int a, bool b, bool c) {
+ return AllOf(Field(&CopyDetector::x, a), Field(&CopyDetector::moved, b),
+ Field(&CopyDetector::copied, c));
+}
+
+class Base1 {
+ public:
+ virtual ~Base1() {}
+ int pad;
+};
+
+class Base2 {
+ public:
+ virtual ~Base2() {}
+ int yetotherpad;
+};
+
+class Derived : public Base1, public Base2 {
+ public:
+ virtual ~Derived() {}
+ int evenmorepad;
+};
+
+class CopyNoAssign {
+ public:
+ explicit CopyNoAssign(int value) : foo(value) {}
+ CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
+ int foo;
+
+ private:
+ const CopyNoAssign& operator=(const CopyNoAssign&);
+};
+
+absl::StatusOr<std::unique_ptr<int>> ReturnUniquePtr() {
+ // Uses implicit constructor from T&&
+ return absl::make_unique<int>(0);
+}
+
+TEST(StatusOr, ElementType) {
+ static_assert(std::is_same<absl::StatusOr<int>::value_type, int>(), "");
+ static_assert(std::is_same<absl::StatusOr<char>::value_type, char>(), "");
+}
+
+TEST(StatusOr, TestMoveOnlyInitialization) {
+ absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+ ASSERT_TRUE(thing.ok());
+ EXPECT_EQ(0, **thing);
+ int* previous = thing->get();
+
+ thing = ReturnUniquePtr();
+ EXPECT_TRUE(thing.ok());
+ EXPECT_EQ(0, **thing);
+ EXPECT_NE(previous, thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyValueExtraction) {
+ absl::StatusOr<std::unique_ptr<int>> thing(ReturnUniquePtr());
+ ASSERT_TRUE(thing.ok());
+ std::unique_ptr<int> ptr = *std::move(thing);
+ EXPECT_EQ(0, *ptr);
+
+ thing = std::move(ptr);
+ ptr = std::move(*thing);
+ EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestMoveOnlyInitializationFromTemporaryByValueOrDie) {
+ std::unique_ptr<int> ptr(*ReturnUniquePtr());
+ EXPECT_EQ(0, *ptr);
+}
+
+TEST(StatusOr, TestValueOrDieOverloadForConstTemporary) {
+ static_assert(
+ std::is_same<const int&&,
+ decltype(
+ std::declval<const absl::StatusOr<int>&&>().value())>(),
+ "value() for const temporaries should return const T&&");
+}
+
+TEST(StatusOr, TestMoveOnlyConversion) {
+ absl::StatusOr<std::unique_ptr<const int>> const_thing(ReturnUniquePtr());
+ EXPECT_TRUE(const_thing.ok());
+ EXPECT_EQ(0, **const_thing);
+
+ // Test rvalue converting assignment
+ const int* const_previous = const_thing->get();
+ const_thing = ReturnUniquePtr();
+ EXPECT_TRUE(const_thing.ok());
+ EXPECT_EQ(0, **const_thing);
+ EXPECT_NE(const_previous, const_thing->get());
+}
+
+TEST(StatusOr, TestMoveOnlyVector) {
+ // Sanity check that absl::StatusOr<MoveOnly> works in vector.
+ std::vector<absl::StatusOr<std::unique_ptr<int>>> vec;
+ vec.push_back(ReturnUniquePtr());
+ vec.resize(2);
+ auto another_vec = std::move(vec);
+ EXPECT_EQ(0, **another_vec[0]);
+ EXPECT_EQ(absl::UnknownError(""), another_vec[1].status());
+}
+
+TEST(StatusOr, TestDefaultCtor) {
+ absl::StatusOr<int> thing;
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+TEST(StatusOr, StatusCtorForwards) {
+ absl::Status status(absl::StatusCode::kInternal, "Some error");
+
+ EXPECT_EQ(absl::StatusOr<int>(status).status().message(), "Some error");
+ EXPECT_EQ(status.message(), "Some error");
+
+ EXPECT_EQ(absl::StatusOr<int>(std::move(status)).status().message(),
+ "Some error");
+ EXPECT_NE(status.message(), "Some error");
+}
+
+// Define `EXPECT_DEATH_OR_THROW` to test the behavior of `StatusOr::value`,
+// which either throws `BadStatusOrAccess` or `LOG(FATAL)` based on whether
+// exceptions are enabled.
+#ifdef ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status_) \
+ EXPECT_THROW( \
+ { \
+ try { \
+ statement; \
+ } catch (const absl::BadStatusOrAccess& e) { \
+ EXPECT_EQ(e.status(), status_); \
+ throw; \
+ } \
+ }, \
+ absl::BadStatusOrAccess);
+#else // ABSL_HAVE_EXCEPTIONS
+#define EXPECT_DEATH_OR_THROW(statement, status) \
+ EXPECT_DEATH_IF_SUPPORTED(statement, status.ToString());
+#endif // ABSL_HAVE_EXCEPTIONS
+
+TEST(StatusOrDeathTest, TestDefaultCtorValue) {
+ absl::StatusOr<int> thing;
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+ const absl::StatusOr<int> thing2;
+ EXPECT_DEATH_OR_THROW(thing2.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestValueNotOk) {
+ absl::StatusOr<int> thing(absl::CancelledError());
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestValueNotOkConst) {
+ const absl::StatusOr<int> thing(absl::UnknownError(""));
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerDefaultCtorValue) {
+ absl::StatusOr<int*> thing;
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::UnknownError(""));
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOk) {
+ absl::StatusOr<int*> thing(absl::CancelledError());
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+TEST(StatusOrDeathTest, TestPointerValueNotOkConst) {
+ const absl::StatusOr<int*> thing(absl::CancelledError());
+ EXPECT_DEATH_OR_THROW(thing.value(), absl::CancelledError());
+}
+
+#if GTEST_HAS_DEATH_TEST
+TEST(StatusOrDeathTest, TestStatusCtorStatusOk) {
+ EXPECT_DEBUG_DEATH(
+ {
+ // This will DCHECK
+ absl::StatusOr<int> thing(absl::OkStatus());
+ // In optimized mode, we are actually going to get error::INTERNAL for
+ // status here, rather than crashing, so check that.
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+ },
+ "An OK status is not a valid constructor argument");
+}
+
+TEST(StatusOrDeathTest, TestPointerStatusCtorStatusOk) {
+ EXPECT_DEBUG_DEATH(
+ {
+ absl::StatusOr<int*> thing(absl::OkStatus());
+ // In optimized mode, we are actually going to get error::INTERNAL for
+ // status here, rather than crashing, so check that.
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kInternal);
+ },
+ "An OK status is not a valid constructor argument");
+}
+#endif
+
+TEST(StatusOr, ValueAccessor) {
+ const int kIntValue = 110;
+ {
+ absl::StatusOr<int> status_or(kIntValue);
+ EXPECT_EQ(kIntValue, status_or.value());
+ EXPECT_EQ(kIntValue, std::move(status_or).value());
+ }
+ {
+ absl::StatusOr<CopyDetector> status_or(kIntValue);
+ EXPECT_THAT(status_or,
+ IsOkAndHolds(CopyDetectorHas(kIntValue, false, false)));
+ CopyDetector copy_detector = status_or.value();
+ EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, false, true));
+ copy_detector = std::move(status_or).value();
+ EXPECT_THAT(copy_detector, CopyDetectorHas(kIntValue, true, false));
+ }
+}
+
+TEST(StatusOr, BadValueAccess) {
+ const absl::Status kError = absl::CancelledError("message");
+ absl::StatusOr<int> status_or(kError);
+ EXPECT_DEATH_OR_THROW(status_or.value(), kError);
+}
+
+TEST(StatusOr, TestStatusCtor) {
+ absl::StatusOr<int> thing(absl::CancelledError());
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+
+
+TEST(StatusOr, TestValueCtor) {
+ const int kI = 4;
+ const absl::StatusOr<int> thing(kI);
+ EXPECT_TRUE(thing.ok());
+ EXPECT_EQ(kI, *thing);
+}
+
+struct Foo {
+ const int x;
+ explicit Foo(int y) : x(y) {}
+};
+
+TEST(StatusOr, InPlaceConstruction) {
+ EXPECT_THAT(absl::StatusOr<Foo>(absl::in_place, 10),
+ IsOkAndHolds(Field(&Foo::x, 10)));
+}
+
+struct InPlaceHelper {
+ InPlaceHelper(std::initializer_list<int> xs, std::unique_ptr<int> yy)
+ : x(xs), y(std::move(yy)) {}
+ const std::vector<int> x;
+ std::unique_ptr<int> y;
+};
+
+TEST(StatusOr, InPlaceInitListConstruction) {
+ absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+ absl::make_unique<int>(13));
+ EXPECT_THAT(status_or, IsOkAndHolds(AllOf(
+ Field(&InPlaceHelper::x, ElementsAre(10, 11, 12)),
+ Field(&InPlaceHelper::y, Pointee(13)))));
+}
+
+TEST(StatusOr, Emplace) {
+ absl::StatusOr<Foo> status_or_foo(10);
+ status_or_foo.emplace(20);
+ EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+ status_or_foo = absl::InvalidArgumentError("msg");
+ EXPECT_FALSE(status_or_foo.ok());
+ EXPECT_EQ(status_or_foo.status().code(), absl::StatusCode::kInvalidArgument);
+ EXPECT_EQ(status_or_foo.status().message(), "msg");
+ status_or_foo.emplace(20);
+ EXPECT_THAT(status_or_foo, IsOkAndHolds(Field(&Foo::x, 20)));
+}
+
+TEST(StatusOr, EmplaceInitializerList) {
+ absl::StatusOr<InPlaceHelper> status_or(absl::in_place, {10, 11, 12},
+ absl::make_unique<int>(13));
+ status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+ EXPECT_THAT(status_or,
+ IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+ Field(&InPlaceHelper::y, Pointee(4)))));
+ status_or = absl::InvalidArgumentError("msg");
+ EXPECT_FALSE(status_or.ok());
+ EXPECT_EQ(status_or.status().code(), absl::StatusCode::kInvalidArgument);
+ EXPECT_EQ(status_or.status().message(), "msg");
+ status_or.emplace({1, 2, 3}, absl::make_unique<int>(4));
+ EXPECT_THAT(status_or,
+ IsOkAndHolds(AllOf(Field(&InPlaceHelper::x, ElementsAre(1, 2, 3)),
+ Field(&InPlaceHelper::y, Pointee(4)))));
+}
+
+TEST(StatusOr, TestCopyCtorStatusOk) {
+ const int kI = 4;
+ const absl::StatusOr<int> original(kI);
+ const absl::StatusOr<int> copy(original);
+ EXPECT_OK(copy.status());
+ EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOk) {
+ absl::StatusOr<int> original(absl::CancelledError());
+ absl::StatusOr<int> copy(original);
+ EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestCopyCtorNonAssignable) {
+ const int kI = 4;
+ CopyNoAssign value(kI);
+ absl::StatusOr<CopyNoAssign> original(value);
+ absl::StatusOr<CopyNoAssign> copy(original);
+ EXPECT_OK(copy.status());
+ EXPECT_EQ(original->foo, copy->foo);
+}
+
+TEST(StatusOr, TestCopyCtorStatusOKConverting) {
+ const int kI = 4;
+ absl::StatusOr<int> original(kI);
+ absl::StatusOr<double> copy(original);
+ EXPECT_OK(copy.status());
+ EXPECT_DOUBLE_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
+ absl::StatusOr<int> original(absl::CancelledError());
+ absl::StatusOr<double> copy(original);
+ EXPECT_EQ(copy.status(), original.status());
+}
+
+TEST(StatusOr, TestAssignmentStatusOk) {
+ // Copy assignmment
+ {
+ const auto p = std::make_shared<int>(17);
+ absl::StatusOr<std::shared_ptr<int>> source(p);
+
+ absl::StatusOr<std::shared_ptr<int>> target;
+ target = source;
+
+ ASSERT_TRUE(target.ok());
+ EXPECT_OK(target.status());
+ EXPECT_EQ(p, *target);
+
+ ASSERT_TRUE(source.ok());
+ EXPECT_OK(source.status());
+ EXPECT_EQ(p, *source);
+ }
+
+ // Move asssignment
+ {
+ const auto p = std::make_shared<int>(17);
+ absl::StatusOr<std::shared_ptr<int>> source(p);
+
+ absl::StatusOr<std::shared_ptr<int>> target;
+ target = std::move(source);
+
+ ASSERT_TRUE(target.ok());
+ EXPECT_OK(target.status());
+ EXPECT_EQ(p, *target);
+
+ ASSERT_TRUE(source.ok());
+ EXPECT_OK(source.status());
+ EXPECT_EQ(nullptr, *source);
+ }
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOk) {
+ // Copy assignment
+ {
+ const absl::Status expected = absl::CancelledError();
+ absl::StatusOr<int> source(expected);
+
+ absl::StatusOr<int> target;
+ target = source;
+
+ EXPECT_FALSE(target.ok());
+ EXPECT_EQ(expected, target.status());
+
+ EXPECT_FALSE(source.ok());
+ EXPECT_EQ(expected, source.status());
+ }
+
+ // Move assignment
+ {
+ const absl::Status expected = absl::CancelledError();
+ absl::StatusOr<int> source(expected);
+
+ absl::StatusOr<int> target;
+ target = std::move(source);
+
+ EXPECT_FALSE(target.ok());
+ EXPECT_EQ(expected, target.status());
+
+ EXPECT_FALSE(source.ok());
+ EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+ }
+}
+
+TEST(StatusOr, TestAssignmentStatusOKConverting) {
+ // Copy assignment
+ {
+ const int kI = 4;
+ absl::StatusOr<int> source(kI);
+
+ absl::StatusOr<double> target;
+ target = source;
+
+ ASSERT_TRUE(target.ok());
+ EXPECT_OK(target.status());
+ EXPECT_DOUBLE_EQ(kI, *target);
+
+ ASSERT_TRUE(source.ok());
+ EXPECT_OK(source.status());
+ EXPECT_DOUBLE_EQ(kI, *source);
+ }
+
+ // Move assignment
+ {
+ const auto p = new int(17);
+ absl::StatusOr<std::unique_ptr<int>> source(absl::WrapUnique(p));
+
+ absl::StatusOr<std::shared_ptr<int>> target;
+ target = std::move(source);
+
+ ASSERT_TRUE(target.ok());
+ EXPECT_OK(target.status());
+ EXPECT_EQ(p, target->get());
+
+ ASSERT_TRUE(source.ok());
+ EXPECT_OK(source.status());
+ EXPECT_EQ(nullptr, source->get());
+ }
+}
+
+struct A {
+ int x;
+};
+
+struct ImplicitConstructibleFromA {
+ int x;
+ bool moved;
+ ImplicitConstructibleFromA(const A& a) // NOLINT
+ : x(a.x), moved(false) {}
+ ImplicitConstructibleFromA(A&& a) // NOLINT
+ : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ImplicitConvertingConstructor) {
+ EXPECT_THAT(
+ absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(
+ absl::StatusOr<A>(A{11})),
+ IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 11),
+ Field(&ImplicitConstructibleFromA::moved, true))));
+ absl::StatusOr<A> a(A{12});
+ EXPECT_THAT(
+ absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromA>>(a),
+ IsOkAndHolds(AllOf(Field(&ImplicitConstructibleFromA::x, 12),
+ Field(&ImplicitConstructibleFromA::moved, false))));
+}
+
+struct ExplicitConstructibleFromA {
+ int x;
+ bool moved;
+ explicit ExplicitConstructibleFromA(const A& a) : x(a.x), moved(false) {}
+ explicit ExplicitConstructibleFromA(A&& a) : x(a.x), moved(true) {}
+};
+
+TEST(StatusOr, ExplicitConvertingConstructor) {
+ EXPECT_FALSE(
+ (std::is_convertible<const absl::StatusOr<A>&,
+ absl::StatusOr<ExplicitConstructibleFromA>>::value));
+ EXPECT_FALSE(
+ (std::is_convertible<absl::StatusOr<A>&&,
+ absl::StatusOr<ExplicitConstructibleFromA>>::value));
+ EXPECT_THAT(
+ absl::StatusOr<ExplicitConstructibleFromA>(absl::StatusOr<A>(A{11})),
+ IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 11),
+ Field(&ExplicitConstructibleFromA::moved, true))));
+ absl::StatusOr<A> a(A{12});
+ EXPECT_THAT(
+ absl::StatusOr<ExplicitConstructibleFromA>(a),
+ IsOkAndHolds(AllOf(Field(&ExplicitConstructibleFromA::x, 12),
+ Field(&ExplicitConstructibleFromA::moved, false))));
+}
+
+struct ImplicitConstructibleFromBool {
+ ImplicitConstructibleFromBool(bool y) : x(y) {} // NOLINT
+ bool x = false;
+};
+
+struct ConvertibleToBool {
+ explicit ConvertibleToBool(bool y) : x(y) {}
+ operator bool() const { return x; } // NOLINT
+ bool x = false;
+};
+
+TEST(StatusOr, ImplicitBooleanConstructionWithImplicitCasts) {
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+ IsOkAndHolds(false));
+ EXPECT_THAT(
+ absl::implicit_cast<absl::StatusOr<ImplicitConstructibleFromBool>>(
+ absl::StatusOr<bool>(false)),
+ IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+ EXPECT_FALSE((std::is_convertible<
+ absl::StatusOr<ConvertibleToBool>,
+ absl::StatusOr<ImplicitConstructibleFromBool>>::value));
+}
+
+TEST(StatusOr, BooleanConstructionWithImplicitCasts) {
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<ConvertibleToBool>(false)),
+ IsOkAndHolds(false));
+ EXPECT_THAT(
+ absl::StatusOr<ImplicitConstructibleFromBool>{
+ absl::StatusOr<bool>(false)},
+ IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+ EXPECT_THAT(
+ absl::StatusOr<ImplicitConstructibleFromBool>{
+ absl::StatusOr<bool>(absl::InvalidArgumentError(""))},
+ Not(IsOk()));
+
+ EXPECT_THAT(
+ absl::StatusOr<ImplicitConstructibleFromBool>{
+ absl::StatusOr<ConvertibleToBool>(ConvertibleToBool{false})},
+ IsOkAndHolds(Field(&ImplicitConstructibleFromBool::x, false)));
+ EXPECT_THAT(
+ absl::StatusOr<ImplicitConstructibleFromBool>{
+ absl::StatusOr<ConvertibleToBool>(absl::InvalidArgumentError(""))},
+ Not(IsOk()));
+}
+
+TEST(StatusOr, ConstImplicitCast) {
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+ absl::StatusOr<const bool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<bool>>(
+ absl::StatusOr<const bool>(false)),
+ IsOkAndHolds(false));
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+ absl::StatusOr<bool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const bool>>(
+ absl::StatusOr<bool>(false)),
+ IsOkAndHolds(false));
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<const std::string>>(
+ absl::StatusOr<std::string>("foo")),
+ IsOkAndHolds("foo"));
+ EXPECT_THAT(absl::implicit_cast<absl::StatusOr<std::string>>(
+ absl::StatusOr<const std::string>("foo")),
+ IsOkAndHolds("foo"));
+ EXPECT_THAT(
+ absl::implicit_cast<absl::StatusOr<std::shared_ptr<const std::string>>>(
+ absl::StatusOr<std::shared_ptr<std::string>>(
+ std::make_shared<std::string>("foo"))),
+ IsOkAndHolds(Pointee(std::string("foo"))));
+}
+
+TEST(StatusOr, ConstExplicitConstruction) {
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::StatusOr<bool>(absl::StatusOr<const bool>(false)),
+ IsOkAndHolds(false));
+ EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(true)),
+ IsOkAndHolds(true));
+ EXPECT_THAT(absl::StatusOr<const bool>(absl::StatusOr<bool>(false)),
+ IsOkAndHolds(false));
+}
+
+struct ExplicitConstructibleFromInt {
+ int x;
+ explicit ExplicitConstructibleFromInt(int y) : x(y) {}
+};
+
+TEST(StatusOr, ExplicitConstruction) {
+ EXPECT_THAT(absl::StatusOr<ExplicitConstructibleFromInt>(10),
+ IsOkAndHolds(Field(&ExplicitConstructibleFromInt::x, 10)));
+}
+
+TEST(StatusOr, ImplicitConstruction) {
+ // Check implicit casting works.
+ auto status_or =
+ absl::implicit_cast<absl::StatusOr<absl::variant<int, std::string>>>(10);
+ EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, ImplicitConstructionFromInitliazerList) {
+ // Note: dropping the explicit std::initializer_list<int> is not supported
+ // by absl::StatusOr or absl::optional.
+ auto status_or =
+ absl::implicit_cast<absl::StatusOr<std::vector<int>>>({{10, 20, 30}});
+ EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitConstruction) {
+ auto status_or = absl::implicit_cast<absl::StatusOr<std::unique_ptr<Base1>>>(
+ absl::make_unique<Derived>());
+ EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveConstructorTests) {
+ absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+ absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+ absl::InvalidArgumentError("foo");
+ EXPECT_THAT(status_or,
+ IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+ absl::StatusOr<absl::StatusOr<CopyDetector>> a = status_or;
+ EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+ absl::StatusOr<absl::StatusOr<CopyDetector>> a_err = status_error;
+ EXPECT_THAT(a_err, Not(IsOk()));
+
+ const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+ absl::StatusOr<absl::StatusOr<CopyDetector>> b = cref; // NOLINT
+ EXPECT_THAT(b, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+ const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+ absl::StatusOr<absl::StatusOr<CopyDetector>> b_err = cref_err; // NOLINT
+ EXPECT_THAT(b_err, Not(IsOk()));
+
+ absl::StatusOr<absl::StatusOr<CopyDetector>> c = std::move(status_or);
+ EXPECT_THAT(c, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+ absl::StatusOr<absl::StatusOr<CopyDetector>> c_err = std::move(status_error);
+ EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, NestedStatusOrCopyAndMoveAssignment) {
+ absl::StatusOr<absl::StatusOr<CopyDetector>> status_or = CopyDetector(10);
+ absl::StatusOr<absl::StatusOr<CopyDetector>> status_error =
+ absl::InvalidArgumentError("foo");
+ absl::StatusOr<absl::StatusOr<CopyDetector>> a;
+ a = status_or;
+ EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+ a = status_error;
+ EXPECT_THAT(a, Not(IsOk()));
+
+ const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref = status_or;
+ a = cref;
+ EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, false, true))));
+ const absl::StatusOr<absl::StatusOr<CopyDetector>>& cref_err = status_error;
+ a = cref_err;
+ EXPECT_THAT(a, Not(IsOk()));
+ a = std::move(status_or);
+ EXPECT_THAT(a, IsOkAndHolds(IsOkAndHolds(CopyDetectorHas(10, true, false))));
+ a = std::move(status_error);
+ EXPECT_THAT(a, Not(IsOk()));
+}
+
+struct Copyable {
+ Copyable() {}
+ Copyable(const Copyable&) {}
+ Copyable& operator=(const Copyable&) { return *this; }
+};
+
+struct MoveOnly {
+ MoveOnly() {}
+ MoveOnly(MoveOnly&&) {}
+ MoveOnly& operator=(MoveOnly&&) { return *this; }
+};
+
+struct NonMovable {
+ NonMovable() {}
+ NonMovable(const NonMovable&) = delete;
+ NonMovable(NonMovable&&) = delete;
+ NonMovable& operator=(const NonMovable&) = delete;
+ NonMovable& operator=(NonMovable&&) = delete;
+};
+
+TEST(StatusOr, CopyAndMoveAbility) {
+ EXPECT_TRUE(std::is_copy_constructible<Copyable>::value);
+ EXPECT_TRUE(std::is_copy_assignable<Copyable>::value);
+ EXPECT_TRUE(std::is_move_constructible<Copyable>::value);
+ EXPECT_TRUE(std::is_move_assignable<Copyable>::value);
+ EXPECT_FALSE(std::is_copy_constructible<MoveOnly>::value);
+ EXPECT_FALSE(std::is_copy_assignable<MoveOnly>::value);
+ EXPECT_TRUE(std::is_move_constructible<MoveOnly>::value);
+ EXPECT_TRUE(std::is_move_assignable<MoveOnly>::value);
+ EXPECT_FALSE(std::is_copy_constructible<NonMovable>::value);
+ EXPECT_FALSE(std::is_copy_assignable<NonMovable>::value);
+ EXPECT_FALSE(std::is_move_constructible<NonMovable>::value);
+ EXPECT_FALSE(std::is_move_assignable<NonMovable>::value);
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveConstructorTests) {
+ absl::StatusOr<absl::any> status_or = CopyDetector(10);
+ absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+ EXPECT_THAT(
+ status_or,
+ IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+ absl::StatusOr<absl::any> a = status_or;
+ EXPECT_THAT(
+ a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+ absl::StatusOr<absl::any> a_err = status_error;
+ EXPECT_THAT(a_err, Not(IsOk()));
+
+ const absl::StatusOr<absl::any>& cref = status_or;
+ // No lint for no-change copy.
+ absl::StatusOr<absl::any> b = cref; // NOLINT
+ EXPECT_THAT(
+ b, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+ const absl::StatusOr<absl::any>& cref_err = status_error;
+ // No lint for no-change copy.
+ absl::StatusOr<absl::any> b_err = cref_err; // NOLINT
+ EXPECT_THAT(b_err, Not(IsOk()));
+
+ absl::StatusOr<absl::any> c = std::move(status_or);
+ EXPECT_THAT(
+ c, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+ absl::StatusOr<absl::any> c_err = std::move(status_error);
+ EXPECT_THAT(c_err, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrAnyCopyAndMoveAssignment) {
+ absl::StatusOr<absl::any> status_or = CopyDetector(10);
+ absl::StatusOr<absl::any> status_error = absl::InvalidArgumentError("foo");
+ absl::StatusOr<absl::any> a;
+ a = status_or;
+ EXPECT_THAT(
+ a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+ a = status_error;
+ EXPECT_THAT(a, Not(IsOk()));
+
+ const absl::StatusOr<absl::any>& cref = status_or;
+ a = cref;
+ EXPECT_THAT(
+ a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, false, true))));
+ const absl::StatusOr<absl::any>& cref_err = status_error;
+ a = cref_err;
+ EXPECT_THAT(a, Not(IsOk()));
+ a = std::move(status_or);
+ EXPECT_THAT(
+ a, IsOkAndHolds(AnyWith<CopyDetector>(CopyDetectorHas(10, true, false))));
+ a = std::move(status_error);
+ EXPECT_THAT(a, Not(IsOk()));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsConstructor) {
+ absl::StatusOr<CopyDetector> status_or(10);
+ ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+ absl::StatusOr<CopyDetector> a(status_or);
+ EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+ const absl::StatusOr<CopyDetector>& cref = status_or;
+ absl::StatusOr<CopyDetector> b(cref); // NOLINT
+ EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+ absl::StatusOr<CopyDetector> c(std::move(status_or));
+ EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, StatusOrCopyAndMoveTestsAssignment) {
+ absl::StatusOr<CopyDetector> status_or(10);
+ ASSERT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(10, false, false)));
+ absl::StatusOr<CopyDetector> a;
+ a = status_or;
+ EXPECT_THAT(a, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+ const absl::StatusOr<CopyDetector>& cref = status_or;
+ absl::StatusOr<CopyDetector> b;
+ b = cref;
+ EXPECT_THAT(b, IsOkAndHolds(CopyDetectorHas(10, false, true)));
+ absl::StatusOr<CopyDetector> c;
+ c = std::move(status_or);
+ EXPECT_THAT(c, IsOkAndHolds(CopyDetectorHas(10, true, false)));
+}
+
+TEST(StatusOr, AbslAnyAssignment) {
+ EXPECT_FALSE((std::is_assignable<absl::StatusOr<absl::any>,
+ absl::StatusOr<int>>::value));
+ absl::StatusOr<absl::any> status_or;
+ status_or = absl::InvalidArgumentError("foo");
+ EXPECT_THAT(status_or, Not(IsOk()));
+}
+
+TEST(StatusOr, ImplicitAssignment) {
+ absl::StatusOr<absl::variant<int, std::string>> status_or;
+ status_or = 10;
+ EXPECT_THAT(status_or, IsOkAndHolds(VariantWith<int>(10)));
+}
+
+TEST(StatusOr, SelfDirectInitAssignment) {
+ absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+ status_or = *status_or;
+ EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, ImplicitCastFromInitializerList) {
+ absl::StatusOr<std::vector<int>> status_or = {{10, 20, 30}};
+ EXPECT_THAT(status_or, IsOkAndHolds(ElementsAre(10, 20, 30)));
+}
+
+TEST(StatusOr, UniquePtrImplicitAssignment) {
+ absl::StatusOr<std::unique_ptr<Base1>> status_or;
+ status_or = absl::make_unique<Derived>();
+ EXPECT_THAT(status_or, IsOkAndHolds(Ne(nullptr)));
+}
+
+TEST(StatusOr, Pointer) {
+ struct A {};
+ struct B : public A {};
+ struct C : private A {};
+
+ EXPECT_TRUE((std::is_constructible<absl::StatusOr<A*>, B*>::value));
+ EXPECT_TRUE((std::is_convertible<B*, absl::StatusOr<A*>>::value));
+ EXPECT_FALSE((std::is_constructible<absl::StatusOr<A*>, C*>::value));
+ EXPECT_FALSE((std::is_convertible<C*, absl::StatusOr<A*>>::value));
+}
+
+TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
+ // Copy assignment
+ {
+ const absl::Status expected = absl::CancelledError();
+ absl::StatusOr<int> source(expected);
+
+ absl::StatusOr<double> target;
+ target = source;
+
+ EXPECT_FALSE(target.ok());
+ EXPECT_EQ(expected, target.status());
+
+ EXPECT_FALSE(source.ok());
+ EXPECT_EQ(expected, source.status());
+ }
+
+ // Move assignment
+ {
+ const absl::Status expected = absl::CancelledError();
+ absl::StatusOr<int> source(expected);
+
+ absl::StatusOr<double> target;
+ target = std::move(source);
+
+ EXPECT_FALSE(target.ok());
+ EXPECT_EQ(expected, target.status());
+
+ EXPECT_FALSE(source.ok());
+ EXPECT_EQ(source.status().code(), absl::StatusCode::kInternal);
+ }
+}
+
+TEST(StatusOr, SelfAssignment) {
+ // Copy-assignment, status OK
+ {
+ // A string long enough that it's likely to defeat any inline representation
+ // optimization.
+ const std::string long_str(128, 'a');
+
+ absl::StatusOr<std::string> so = long_str;
+ so = *&so;
+
+ ASSERT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(long_str, *so);
+ }
+
+ // Copy-assignment, error status
+ {
+ absl::StatusOr<int> so = absl::NotFoundError("taco");
+ so = *&so;
+
+ EXPECT_FALSE(so.ok());
+ EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+ EXPECT_EQ(so.status().message(), "taco");
+ }
+
+ // Move-assignment with copyable type, status OK
+ {
+ absl::StatusOr<int> so = 17;
+
+ // Fool the compiler, which otherwise complains.
+ auto& same = so;
+ so = std::move(same);
+
+ ASSERT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(17, *so);
+ }
+
+ // Move-assignment with copyable type, error status
+ {
+ absl::StatusOr<int> so = absl::NotFoundError("taco");
+
+ // Fool the compiler, which otherwise complains.
+ auto& same = so;
+ so = std::move(same);
+
+ EXPECT_FALSE(so.ok());
+ EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+ EXPECT_EQ(so.status().message(), "taco");
+ }
+
+ // Move-assignment with non-copyable type, status OK
+ {
+ const auto raw = new int(17);
+ absl::StatusOr<std::unique_ptr<int>> so = absl::WrapUnique(raw);
+
+ // Fool the compiler, which otherwise complains.
+ auto& same = so;
+ so = std::move(same);
+
+ ASSERT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(raw, so->get());
+ }
+
+ // Move-assignment with non-copyable type, error status
+ {
+ absl::StatusOr<std::unique_ptr<int>> so = absl::NotFoundError("taco");
+
+ // Fool the compiler, which otherwise complains.
+ auto& same = so;
+ so = std::move(same);
+
+ EXPECT_FALSE(so.ok());
+ EXPECT_EQ(so.status().code(), absl::StatusCode::kNotFound);
+ EXPECT_EQ(so.status().message(), "taco");
+ }
+}
+
+// These types form the overload sets of the constructors and the assignment
+// operators of `MockValue`. They distinguish construction from assignment,
+// lvalue from rvalue.
+struct FromConstructibleAssignableLvalue {};
+struct FromConstructibleAssignableRvalue {};
+struct FromImplicitConstructibleOnly {};
+struct FromAssignableOnly {};
+
+// This class is for testing the forwarding value assignments of `StatusOr`.
+// `from_rvalue` indicates whether the constructor or the assignment taking
+// rvalue reference is called. `from_assignment` indicates whether any
+// assignment is called.
+struct MockValue {
+ // Constructs `MockValue` from `FromConstructibleAssignableLvalue`.
+ MockValue(const FromConstructibleAssignableLvalue&) // NOLINT
+ : from_rvalue(false), assigned(false) {}
+ // Constructs `MockValue` from `FromConstructibleAssignableRvalue`.
+ MockValue(FromConstructibleAssignableRvalue&&) // NOLINT
+ : from_rvalue(true), assigned(false) {}
+ // Constructs `MockValue` from `FromImplicitConstructibleOnly`.
+ // `MockValue` is not assignable from `FromImplicitConstructibleOnly`.
+ MockValue(const FromImplicitConstructibleOnly&) // NOLINT
+ : from_rvalue(false), assigned(false) {}
+ // Assigns `FromConstructibleAssignableLvalue`.
+ MockValue& operator=(const FromConstructibleAssignableLvalue&) {
+ from_rvalue = false;
+ assigned = true;
+ return *this;
+ }
+ // Assigns `FromConstructibleAssignableRvalue` (rvalue only).
+ MockValue& operator=(FromConstructibleAssignableRvalue&&) {
+ from_rvalue = true;
+ assigned = true;
+ return *this;
+ }
+ // Assigns `FromAssignableOnly`, but not constructible from
+ // `FromAssignableOnly`.
+ MockValue& operator=(const FromAssignableOnly&) {
+ from_rvalue = false;
+ assigned = true;
+ return *this;
+ }
+ bool from_rvalue;
+ bool assigned;
+};
+
+// operator=(U&&)
+TEST(StatusOr, PerfectForwardingAssignment) {
+ // U == T
+ constexpr int kValue1 = 10, kValue2 = 20;
+ absl::StatusOr<CopyDetector> status_or;
+ CopyDetector lvalue(kValue1);
+ status_or = lvalue;
+ EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue1, false, true)));
+ status_or = CopyDetector(kValue2);
+ EXPECT_THAT(status_or, IsOkAndHolds(CopyDetectorHas(kValue2, true, false)));
+
+ // U != T
+ EXPECT_TRUE(
+ (std::is_assignable<absl::StatusOr<MockValue>&,
+ const FromConstructibleAssignableLvalue&>::value));
+ EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+ FromConstructibleAssignableLvalue&&>::value));
+ EXPECT_FALSE(
+ (std::is_assignable<absl::StatusOr<MockValue>&,
+ const FromConstructibleAssignableRvalue&>::value));
+ EXPECT_TRUE((std::is_assignable<absl::StatusOr<MockValue>&,
+ FromConstructibleAssignableRvalue&&>::value));
+ EXPECT_TRUE(
+ (std::is_assignable<absl::StatusOr<MockValue>&,
+ const FromImplicitConstructibleOnly&>::value));
+ EXPECT_FALSE((std::is_assignable<absl::StatusOr<MockValue>&,
+ const FromAssignableOnly&>::value));
+
+ absl::StatusOr<MockValue> from_lvalue(FromConstructibleAssignableLvalue{});
+ EXPECT_FALSE(from_lvalue->from_rvalue);
+ EXPECT_FALSE(from_lvalue->assigned);
+ from_lvalue = FromConstructibleAssignableLvalue{};
+ EXPECT_FALSE(from_lvalue->from_rvalue);
+ EXPECT_TRUE(from_lvalue->assigned);
+
+ absl::StatusOr<MockValue> from_rvalue(FromConstructibleAssignableRvalue{});
+ EXPECT_TRUE(from_rvalue->from_rvalue);
+ EXPECT_FALSE(from_rvalue->assigned);
+ from_rvalue = FromConstructibleAssignableRvalue{};
+ EXPECT_TRUE(from_rvalue->from_rvalue);
+ EXPECT_TRUE(from_rvalue->assigned);
+
+ absl::StatusOr<MockValue> from_implicit_constructible(
+ FromImplicitConstructibleOnly{});
+ EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+ EXPECT_FALSE(from_implicit_constructible->assigned);
+ // construct a temporary `StatusOr` object and invoke the `StatusOr` move
+ // assignment operator.
+ from_implicit_constructible = FromImplicitConstructibleOnly{};
+ EXPECT_FALSE(from_implicit_constructible->from_rvalue);
+ EXPECT_FALSE(from_implicit_constructible->assigned);
+}
+
+TEST(StatusOr, TestStatus) {
+ absl::StatusOr<int> good(4);
+ EXPECT_TRUE(good.ok());
+ absl::StatusOr<int> bad(absl::CancelledError());
+ EXPECT_FALSE(bad.ok());
+ EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, OperatorStarRefQualifiers) {
+ static_assert(
+ std::is_same<const int&,
+ decltype(*std::declval<const absl::StatusOr<int>&>())>(),
+ "Unexpected ref-qualifiers");
+ static_assert(
+ std::is_same<int&, decltype(*std::declval<absl::StatusOr<int>&>())>(),
+ "Unexpected ref-qualifiers");
+ static_assert(
+ std::is_same<const int&&,
+ decltype(*std::declval<const absl::StatusOr<int>&&>())>(),
+ "Unexpected ref-qualifiers");
+ static_assert(
+ std::is_same<int&&, decltype(*std::declval<absl::StatusOr<int>&&>())>(),
+ "Unexpected ref-qualifiers");
+}
+
+TEST(StatusOr, OperatorStar) {
+ const absl::StatusOr<std::string> const_lvalue("hello");
+ EXPECT_EQ("hello", *const_lvalue);
+
+ absl::StatusOr<std::string> lvalue("hello");
+ EXPECT_EQ("hello", *lvalue);
+
+ // Note: Recall that std::move() is equivalent to a static_cast to an rvalue
+ // reference type.
+ const absl::StatusOr<std::string> const_rvalue("hello");
+ EXPECT_EQ("hello", *std::move(const_rvalue)); // NOLINT
+
+ absl::StatusOr<std::string> rvalue("hello");
+ EXPECT_EQ("hello", *std::move(rvalue));
+}
+
+TEST(StatusOr, OperatorArrowQualifiers) {
+ static_assert(
+ std::is_same<
+ const int*,
+ decltype(std::declval<const absl::StatusOr<int>&>().operator->())>(),
+ "Unexpected qualifiers");
+ static_assert(
+ std::is_same<
+ int*, decltype(std::declval<absl::StatusOr<int>&>().operator->())>(),
+ "Unexpected qualifiers");
+ static_assert(
+ std::is_same<
+ const int*,
+ decltype(std::declval<const absl::StatusOr<int>&&>().operator->())>(),
+ "Unexpected qualifiers");
+ static_assert(
+ std::is_same<
+ int*, decltype(std::declval<absl::StatusOr<int>&&>().operator->())>(),
+ "Unexpected qualifiers");
+}
+
+TEST(StatusOr, OperatorArrow) {
+ const absl::StatusOr<std::string> const_lvalue("hello");
+ EXPECT_EQ(std::string("hello"), const_lvalue->c_str());
+
+ absl::StatusOr<std::string> lvalue("hello");
+ EXPECT_EQ(std::string("hello"), lvalue->c_str());
+}
+
+TEST(StatusOr, RValueStatus) {
+ absl::StatusOr<int> so(absl::NotFoundError("taco"));
+ const absl::Status s = std::move(so).status();
+
+ EXPECT_EQ(s.code(), absl::StatusCode::kNotFound);
+ EXPECT_EQ(s.message(), "taco");
+
+ // Check that !ok() still implies !status().ok(), even after moving out of the
+ // object. See the note on the rvalue ref-qualified status method.
+ EXPECT_FALSE(so.ok()); // NOLINT
+ EXPECT_FALSE(so.status().ok());
+ EXPECT_EQ(so.status().code(), absl::StatusCode::kInternal);
+ EXPECT_EQ(so.status().message(), "Status accessed after move.");
+}
+
+TEST(StatusOr, TestValue) {
+ const int kI = 4;
+ absl::StatusOr<int> thing(kI);
+ EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestValueConst) {
+ const int kI = 4;
+ const absl::StatusOr<int> thing(kI);
+ EXPECT_EQ(kI, *thing);
+}
+
+TEST(StatusOr, TestPointerDefaultCtor) {
+ absl::StatusOr<int*> thing;
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kUnknown);
+}
+
+
+
+TEST(StatusOr, TestPointerStatusCtor) {
+ absl::StatusOr<int*> thing(absl::CancelledError());
+ EXPECT_FALSE(thing.ok());
+ EXPECT_EQ(thing.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValueCtor) {
+ const int kI = 4;
+
+ // Construction from a non-null pointer
+ {
+ absl::StatusOr<const int*> so(&kI);
+ EXPECT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(&kI, *so);
+ }
+
+ // Construction from a null pointer constant
+ {
+ absl::StatusOr<const int*> so(nullptr);
+ EXPECT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(nullptr, *so);
+ }
+
+ // Construction from a non-literal null pointer
+ {
+ const int* const p = nullptr;
+
+ absl::StatusOr<const int*> so(p);
+ EXPECT_TRUE(so.ok());
+ EXPECT_OK(so.status());
+ EXPECT_EQ(nullptr, *so);
+ }
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOk) {
+ const int kI = 0;
+ absl::StatusOr<const int*> original(&kI);
+ absl::StatusOr<const int*> copy(original);
+ EXPECT_OK(copy.status());
+ EXPECT_EQ(*original, *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
+ absl::StatusOr<int*> original(absl::CancelledError());
+ absl::StatusOr<int*> copy(original);
+ EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
+ Derived derived;
+ absl::StatusOr<Derived*> original(&derived);
+ absl::StatusOr<Base2*> copy(original);
+ EXPECT_OK(copy.status());
+ EXPECT_EQ(static_cast<const Base2*>(*original), *copy);
+}
+
+TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
+ absl::StatusOr<Derived*> original(absl::CancelledError());
+ absl::StatusOr<Base2*> copy(original);
+ EXPECT_EQ(copy.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOk) {
+ const int kI = 0;
+ absl::StatusOr<const int*> source(&kI);
+ absl::StatusOr<const int*> target;
+ target = source;
+ EXPECT_OK(target.status());
+ EXPECT_EQ(*source, *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
+ absl::StatusOr<int*> source(absl::CancelledError());
+ absl::StatusOr<int*> target;
+ target = source;
+ EXPECT_EQ(target.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
+ Derived derived;
+ absl::StatusOr<Derived*> source(&derived);
+ absl::StatusOr<Base2*> target;
+ target = source;
+ EXPECT_OK(target.status());
+ EXPECT_EQ(static_cast<const Base2*>(*source), *target);
+}
+
+TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
+ absl::StatusOr<Derived*> source(absl::CancelledError());
+ absl::StatusOr<Base2*> target;
+ target = source;
+ EXPECT_EQ(target.status(), source.status());
+}
+
+TEST(StatusOr, TestPointerStatus) {
+ const int kI = 0;
+ absl::StatusOr<const int*> good(&kI);
+ EXPECT_TRUE(good.ok());
+ absl::StatusOr<const int*> bad(absl::CancelledError());
+ EXPECT_EQ(bad.status().code(), absl::StatusCode::kCancelled);
+}
+
+TEST(StatusOr, TestPointerValue) {
+ const int kI = 0;
+ absl::StatusOr<const int*> thing(&kI);
+ EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, TestPointerValueConst) {
+ const int kI = 0;
+ const absl::StatusOr<const int*> thing(&kI);
+ EXPECT_EQ(&kI, *thing);
+}
+
+TEST(StatusOr, StatusOrVectorOfUniquePointerCanReserveAndResize) {
+ using EvilType = std::vector<std::unique_ptr<int>>;
+ static_assert(std::is_copy_constructible<EvilType>::value, "");
+ std::vector<::absl::StatusOr<EvilType>> v(5);
+ v.reserve(v.capacity() + 10);
+ v.resize(v.capacity() + 10);
+}
+
+TEST(StatusOr, ConstPayload) {
+ // A reduced version of a problematic type found in the wild. All of the
+ // operations below should compile.
+ absl::StatusOr<const int> a;
+
+ // Copy-construction
+ absl::StatusOr<const int> b(a);
+
+ // Copy-assignment
+ EXPECT_FALSE(std::is_copy_assignable<absl::StatusOr<const int>>::value);
+
+ // Move-construction
+ absl::StatusOr<const int> c(std::move(a));
+
+ // Move-assignment
+ EXPECT_FALSE(std::is_move_assignable<absl::StatusOr<const int>>::value);
+}
+
+TEST(StatusOr, MapToStatusOrUniquePtr) {
+ // A reduced version of a problematic type found in the wild. All of the
+ // operations below should compile.
+ using MapType = std::map<std::string, absl::StatusOr<std::unique_ptr<int>>>;
+
+ MapType a;
+
+ // Move-construction
+ MapType b(std::move(a));
+
+ // Move-assignment
+ a = std::move(b);
+}
+
+TEST(StatusOr, ValueOrOk) {
+ const absl::StatusOr<int> status_or = 0;
+ EXPECT_EQ(status_or.value_or(-1), 0);
+}
+
+TEST(StatusOr, ValueOrDefault) {
+ const absl::StatusOr<int> status_or = absl::CancelledError();
+ EXPECT_EQ(status_or.value_or(-1), -1);
+}
+
+TEST(StatusOr, MoveOnlyValueOrOk) {
+ EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::make_unique<int>(0))
+ .value_or(absl::make_unique<int>(-1)),
+ Pointee(0));
+}
+
+TEST(StatusOr, MoveOnlyValueOrDefault) {
+ EXPECT_THAT(absl::StatusOr<std::unique_ptr<int>>(absl::CancelledError())
+ .value_or(absl::make_unique<int>(-1)),
+ Pointee(-1));
+}
+
+static absl::StatusOr<int> MakeStatus() { return 100; }
+
+TEST(StatusOr, TestIgnoreError) { MakeStatus().IgnoreError(); }
+
+TEST(StatusOr, EqualityOperator) {
+ constexpr int kNumCases = 4;
+ std::array<absl::StatusOr<int>, kNumCases> group1 = {
+ absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+ absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+ absl::StatusOr<int>(absl::InternalError("msg"))};
+ std::array<absl::StatusOr<int>, kNumCases> group2 = {
+ absl::StatusOr<int>(1), absl::StatusOr<int>(2),
+ absl::StatusOr<int>(absl::InvalidArgumentError("msg")),
+ absl::StatusOr<int>(absl::InternalError("msg"))};
+ for (int i = 0; i < kNumCases; ++i) {
+ for (int j = 0; j < kNumCases; ++j) {
+ if (i == j) {
+ EXPECT_TRUE(group1[i] == group2[j]);
+ EXPECT_FALSE(group1[i] != group2[j]);
+ } else {
+ EXPECT_FALSE(group1[i] == group2[j]);
+ EXPECT_TRUE(group1[i] != group2[j]);
+ }
+ }
+ }
+}
+
+struct MyType {
+ bool operator==(const MyType&) const { return true; }
+};
+
+enum class ConvTraits { kNone = 0, kImplicit = 1, kExplicit = 2 };
+
+// This class has conversion operator to `StatusOr<T>` based on value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusOrConversionBase {};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kImplicit> {
+ operator absl::StatusOr<T>() const& { // NOLINT
+ return absl::InvalidArgumentError("conversion to absl::StatusOr");
+ }
+ operator absl::StatusOr<T>() && { // NOLINT
+ return absl::InvalidArgumentError("conversion to absl::StatusOr");
+ }
+};
+
+template <typename T>
+struct StatusOrConversionBase<T, ConvTraits::kExplicit> {
+ explicit operator absl::StatusOr<T>() const& {
+ return absl::InvalidArgumentError("conversion to absl::StatusOr");
+ }
+ explicit operator absl::StatusOr<T>() && {
+ return absl::InvalidArgumentError("conversion to absl::StatusOr");
+ }
+};
+
+// This class has conversion operator to `T` based on the value of
+// `conv_traits`.
+template <typename T, ConvTraits conv_traits = ConvTraits::kNone>
+struct ConversionBase {};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kImplicit> {
+ operator T() const& { return t; } // NOLINT
+ operator T() && { return std::move(t); } // NOLINT
+ T t;
+};
+
+template <typename T>
+struct ConversionBase<T, ConvTraits::kExplicit> {
+ explicit operator T() const& { return t; }
+ explicit operator T() && { return std::move(t); }
+ T t;
+};
+
+// This class has conversion operator to `absl::Status` based on the value of
+// `conv_traits`.
+template <ConvTraits conv_traits = ConvTraits::kNone>
+struct StatusConversionBase {};
+
+template <>
+struct StatusConversionBase<ConvTraits::kImplicit> {
+ operator absl::Status() const& { // NOLINT
+ return absl::InternalError("conversion to Status");
+ }
+ operator absl::Status() && { // NOLINT
+ return absl::InternalError("conversion to Status");
+ }
+};
+
+template <>
+struct StatusConversionBase<ConvTraits::kExplicit> {
+ explicit operator absl::Status() const& { // NOLINT
+ return absl::InternalError("conversion to Status");
+ }
+ explicit operator absl::Status() && { // NOLINT
+ return absl::InternalError("conversion to Status");
+ }
+};
+
+static constexpr int kConvToStatus = 1;
+static constexpr int kConvToStatusOr = 2;
+static constexpr int kConvToT = 4;
+static constexpr int kConvExplicit = 8;
+
+constexpr ConvTraits GetConvTraits(int bit, int config) {
+ return (config & bit) == 0
+ ? ConvTraits::kNone
+ : ((config & kConvExplicit) == 0 ? ConvTraits::kImplicit
+ : ConvTraits::kExplicit);
+}
+
+// This class conditionally has conversion operator to `absl::Status`, `T`,
+// `StatusOr<T>`, based on values of the template parameters.
+template <typename T, int config>
+struct CustomType
+ : StatusOrConversionBase<T, GetConvTraits(kConvToStatusOr, config)>,
+ ConversionBase<T, GetConvTraits(kConvToT, config)>,
+ StatusConversionBase<GetConvTraits(kConvToStatus, config)> {};
+
+struct ConvertibleToAnyStatusOr {
+ template <typename T>
+ operator absl::StatusOr<T>() const { // NOLINT
+ return absl::InvalidArgumentError("Conversion to absl::StatusOr");
+ }
+};
+
+// Test the rank of overload resolution for `StatusOr<T>` constructor and
+// assignment, from highest to lowest:
+// 1. T/Status
+// 2. U that has conversion operator to absl::StatusOr<T>
+// 3. U that is convertible to Status
+// 4. U that is convertible to T
+TEST(StatusOr, ConstructionFromT) {
+ // Construct absl::StatusOr<T> from T when T is convertible to
+ // absl::StatusOr<T>
+ {
+ ConvertibleToAnyStatusOr v;
+ absl::StatusOr<ConvertibleToAnyStatusOr> statusor(v);
+ EXPECT_TRUE(statusor.ok());
+ }
+ {
+ ConvertibleToAnyStatusOr v;
+ absl::StatusOr<ConvertibleToAnyStatusOr> statusor = v;
+ EXPECT_TRUE(statusor.ok());
+ }
+ // Construct absl::StatusOr<T> from T when T is explicitly convertible to
+ // Status
+ {
+ CustomType<MyType, kConvToStatus | kConvExplicit> v;
+ absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor(
+ v);
+ EXPECT_TRUE(statusor.ok());
+ }
+ {
+ CustomType<MyType, kConvToStatus | kConvExplicit> v;
+ absl::StatusOr<CustomType<MyType, kConvToStatus | kConvExplicit>> statusor =
+ v;
+ EXPECT_TRUE(statusor.ok());
+ }
+}
+
+// Construct absl::StatusOr<T> from U when U is explicitly convertible to T
+TEST(StatusOr, ConstructionFromTypeConvertibleToT) {
+ {
+ CustomType<MyType, kConvToT | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_TRUE(statusor.ok());
+ }
+ {
+ CustomType<MyType, kConvToT> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_TRUE(statusor.ok());
+ }
+}
+
+// Construct absl::StatusOr<T> from U when U has explicit conversion operator to
+// absl::StatusOr<T>
+TEST(StatusOr, ConstructionFromTypeWithConversionOperatorToStatusOrT) {
+ {
+ CustomType<MyType, kConvToStatusOr | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatusOr | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToStatusOr | kConvToStatus | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType,
+ kConvToT | kConvToStatusOr | kConvToStatus | kConvExplicit>
+ v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToStatusOr> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatusOr> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+}
+
+TEST(StatusOr, ConstructionFromTypeConvertibleToStatus) {
+ // Construction fails because conversion to `Status` is explicit.
+ {
+ CustomType<MyType, kConvToStatus | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatus | kConvExplicit> v;
+ absl::StatusOr<MyType> statusor(v);
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+ {
+ CustomType<MyType, kConvToStatus> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor = v;
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+}
+
+TEST(StatusOr, AssignmentFromT) {
+ // Assign to absl::StatusOr<T> from T when T is convertible to
+ // absl::StatusOr<T>
+ {
+ ConvertibleToAnyStatusOr v;
+ absl::StatusOr<ConvertibleToAnyStatusOr> statusor;
+ statusor = v;
+ EXPECT_TRUE(statusor.ok());
+ }
+ // Assign to absl::StatusOr<T> from T when T is convertible to Status
+ {
+ CustomType<MyType, kConvToStatus> v;
+ absl::StatusOr<CustomType<MyType, kConvToStatus>> statusor;
+ statusor = v;
+ EXPECT_TRUE(statusor.ok());
+ }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToT) {
+ // Assign to absl::StatusOr<T> from U when U is convertible to T
+ {
+ CustomType<MyType, kConvToT> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_TRUE(statusor.ok());
+ }
+}
+
+TEST(StatusOr, AssignmentFromTypeWithConversionOperatortoStatusOrT) {
+ // Assign to absl::StatusOr<T> from U when U has conversion operator to
+ // absl::StatusOr<T>
+ {
+ CustomType<MyType, kConvToStatusOr> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatusOr> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToStatusOr | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatusOr | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_EQ(statusor, v.operator absl::StatusOr<MyType>());
+ }
+}
+
+TEST(StatusOr, AssignmentFromTypeConvertibleToStatus) {
+ // Assign to absl::StatusOr<T> from U when U is convertible to Status
+ {
+ CustomType<MyType, kConvToStatus> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+ {
+ CustomType<MyType, kConvToT | kConvToStatus> v;
+ absl::StatusOr<MyType> statusor;
+ statusor = v;
+ EXPECT_FALSE(statusor.ok());
+ EXPECT_EQ(statusor.status(), static_cast<absl::Status>(v));
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/BUILD.bazel
index 7635a6198ab..123b5efbd86 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/BUILD.bazel
@@ -5,21 +5,19 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
"ABSL_TEST_COPTS",
- "ABSL_EXCEPTIONS_FLAG",
- "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
)
package(
@@ -27,7 +25,7 @@ package(
features = ["parse_headers"],
)
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "strings",
@@ -56,6 +54,7 @@ cc_library(
"ascii.h",
"charconv.h",
"escaping.h",
+ "internal/string_constant.h",
"match.h",
"numbers.h",
"str_cat.h",
@@ -70,13 +69,14 @@ cc_library(
deps = [
":internal",
"//absl/base",
- "//absl/base:bits",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
+ "//absl/base:raw_logging_internal",
"//absl/base:throw_delegate",
"//absl/memory",
"//absl/meta:type_traits",
+ "//absl/numeric:bits",
"//absl/numeric:int128",
],
)
@@ -84,19 +84,23 @@ cc_library(
cc_library(
name = "internal",
srcs = [
+ "internal/escaping.cc",
"internal/ostringstream.cc",
"internal/utf8.cc",
],
hdrs = [
"internal/char_map.h",
+ "internal/escaping.h",
"internal/ostringstream.h",
"internal/resize_uninitialized.h",
"internal/utf8.h",
],
copts = ABSL_DEFAULT_COPTS,
deps = [
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
+ "//absl/base:raw_logging_internal",
"//absl/meta:type_traits",
],
)
@@ -123,6 +127,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
+ ":cord",
":strings",
"//absl/base:core_headers",
"//absl/container:fixed_array",
@@ -141,7 +146,7 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -219,6 +224,19 @@ cc_test(
)
cc_test(
+ name = "string_constant_test",
+ size = "small",
+ srcs = ["internal/string_constant_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":strings",
+ "//absl/meta:type_traits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
name = "string_view_benchmark",
srcs = ["string_view_benchmark.cc"],
copts = ABSL_TEST_COPTS,
@@ -226,8 +244,8 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "//absl/base",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -236,8 +254,7 @@ cc_test(
name = "string_view_test",
size = "small",
srcs = ["string_view_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
":strings",
@@ -248,6 +265,128 @@ cc_test(
],
)
+cc_library(
+ name = "cord_internal",
+ srcs = [
+ "internal/cord_internal.cc",
+ "internal/cord_rep_ring.cc",
+ ],
+ hdrs = [
+ "internal/cord_internal.h",
+ "internal/cord_rep_flat.h",
+ "internal/cord_rep_ring.h",
+ "internal/cord_rep_ring_reader.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ visibility = [
+ "//visibility:private",
+ ],
+ deps = [
+ ":strings",
+ "//absl/base:base_internal",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:endian",
+ "//absl/base:raw_logging_internal",
+ "//absl/base:throw_delegate",
+ "//absl/container:compressed_tuple",
+ "//absl/container:inlined_vector",
+ "//absl/container:layout",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_library(
+ name = "cord",
+ srcs = [
+ "cord.cc",
+ ],
+ hdrs = [
+ "cord.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ ":cord_internal",
+ ":internal",
+ ":str_format",
+ ":strings",
+ "//absl/base",
+ "//absl/base:core_headers",
+ "//absl/base:endian",
+ "//absl/base:raw_logging_internal",
+ "//absl/container:fixed_array",
+ "//absl/container:inlined_vector",
+ "//absl/functional:function_ref",
+ "//absl/meta:type_traits",
+ "//absl/types:optional",
+ ],
+)
+
+cc_library(
+ name = "cord_test_helpers",
+ testonly = 1,
+ hdrs = [
+ "cord_test_helpers.h",
+ ],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ ":cord",
+ ],
+)
+
+cc_test(
+ name = "cord_test",
+ size = "medium",
+ srcs = ["cord_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":cord",
+ ":cord_test_helpers",
+ ":str_format",
+ ":strings",
+ "//absl/base",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:endian",
+ "//absl/base:raw_logging_internal",
+ "//absl/container:fixed_array",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "cord_ring_test",
+ size = "medium",
+ srcs = ["cord_ring_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":cord_internal",
+ ":strings",
+ "//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/debugging:leak_check",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_test(
+ name = "cord_ring_reader_test",
+ size = "medium",
+ srcs = ["cord_ring_reader_test.cc"],
+ copts = ABSL_TEST_COPTS,
+ visibility = ["//visibility:private"],
+ deps = [
+ ":cord_internal",
+ ":strings",
+ "//absl/base:core_headers",
+ "//absl/debugging:leak_check",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
cc_test(
name = "substitute_test",
size = "small",
@@ -269,7 +408,7 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -295,6 +434,8 @@ cc_test(
":strings",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
+ "//absl/container:flat_hash_map",
+ "//absl/container:node_hash_map",
"@com_google_googletest//:gtest_main",
],
)
@@ -307,7 +448,7 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -405,7 +546,7 @@ cc_test(
cc_test(
name = "numbers_test",
- size = "small",
+ size = "medium",
srcs = [
"internal/numbers_test_common.h",
"numbers_test.cc",
@@ -413,10 +554,13 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
+ ":internal",
":pow10_helper",
":strings",
- "//absl/base",
- "//absl/base:core_headers",
+ "//absl/base:config",
+ "//absl/base:raw_logging_internal",
+ "//absl/random",
+ "//absl/random:distributions",
"@com_google_googletest//:gtest_main",
],
)
@@ -429,7 +573,9 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":strings",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
+ "//absl/random",
+ "//absl/random:distributions",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -475,7 +621,6 @@ cc_test(
":pow10_helper",
":str_format",
":strings",
- "//absl/base",
"@com_google_googletest//:gtest_main",
],
)
@@ -489,7 +634,8 @@ cc_test(
copts = ABSL_TEST_COPTS,
deps = [
":strings",
- "//absl/base",
+ "//absl/base:config",
+ "//absl/base:raw_logging_internal",
"@com_google_googletest//:gtest_main",
],
)
@@ -504,7 +650,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
deps = [
":strings",
- "//absl/base",
+ "//absl/base:config",
"@com_google_googletest//:gtest_main",
],
)
@@ -519,7 +665,6 @@ cc_test(
],
deps = [
":strings",
- "//absl/base",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -558,10 +703,14 @@ cc_library(
visibility = ["//visibility:private"],
deps = [
":strings",
+ "//absl/base:config",
"//absl/base:core_headers",
- "//absl/container:inlined_vector",
+ "//absl/functional:function_ref",
"//absl/meta:type_traits",
+ "//absl/numeric:bits",
"//absl/numeric:int128",
+ "//absl/numeric:representation",
+ "//absl/types:optional",
"//absl/types:span",
],
)
@@ -572,6 +721,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
+ ":cord",
":str_format",
":strings",
"//absl/base:core_headers",
@@ -589,6 +739,7 @@ cc_test(
deps = [
":str_format",
":str_format_internal",
+ ":strings",
"@com_google_googletest//:gtest_main",
],
)
@@ -629,13 +780,15 @@ cc_test(
cc_test(
name = "str_format_convert_test",
- size = "small",
+ size = "medium",
srcs = ["internal/str_format/convert_test.cc"],
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
":str_format_internal",
- "//absl/numeric:int128",
+ ":strings",
+ "//absl/base:raw_logging_internal",
+ "//absl/types:optional",
"@com_google_googletest//:gtest_main",
],
)
@@ -646,6 +799,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
+ ":cord",
":str_format_internal",
"@com_google_googletest//:gtest_main",
],
@@ -669,6 +823,7 @@ cc_library(
srcs = ["internal/pow10_helper.cc"],
hdrs = ["internal/pow10_helper.h"],
visibility = ["//visibility:private"],
+ deps = ["//absl/base:config"],
)
cc_test(
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.cc
index c9481e88654..93bb03e9581 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/strings/ascii.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace ascii_internal {
// # Table generated by this Python code (bit 0x02 is currently unused):
@@ -56,7 +57,7 @@ namespace ascii_internal {
// of these bits is tightly coupled to this implementation, the individual bits
// are not named. Note that bitfields for all characters above ASCII 127 are
// zero-initialized.
-const unsigned char kPropertyBits[256] = {
+ABSL_DLL const unsigned char kPropertyBits[256] = {
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x00
0x40, 0x68, 0x48, 0x48, 0x48, 0x48, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x10
@@ -78,7 +79,7 @@ const unsigned char kPropertyBits[256] = {
// Array of characters for the ascii_tolower() function. For values 'A'
// through 'Z', return the lower-case character; otherwise, return the
// identity of the passed character.
-const char kToLower[256] = {
+ABSL_DLL const char kToLower[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -116,7 +117,7 @@ const char kToLower[256] = {
// Array of characters for the ascii_toupper() function. For values 'a'
// through 'z', return the upper-case character; otherwise, return the
// identity of the passed character.
-const char kToUpper[256] = {
+ABSL_DLL const char kToUpper[256] = {
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
@@ -195,4 +196,5 @@ void RemoveExtraAsciiWhitespace(std::string* str) {
str->erase(output_it - &(*str)[0]);
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.h
index 48a9da22e76..b46bc71f35b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -56,19 +56,21 @@
#include <string>
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace ascii_internal {
// Declaration for an array of bitfields holding character information.
-extern const unsigned char kPropertyBits[256];
+ABSL_DLL extern const unsigned char kPropertyBits[256];
// Declaration for the array of characters to upper-case characters.
-extern const char kToUpper[256];
+ABSL_DLL extern const char kToUpper[256];
// Declaration for the array of characters to lower-case characters.
-extern const char kToLower[256];
+ABSL_DLL extern const char kToLower[256];
} // namespace ascii_internal
@@ -234,6 +236,7 @@ inline void StripAsciiWhitespace(std::string* str) {
// Removes leading, trailing, and consecutive internal whitespace.
void RemoveExtraAsciiWhitespace(std::string*);
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_ASCII_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_benchmark.cc
index 8dea4b8cfbf..aca458c8042 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_test.cc
index 9903b0496b7..83af7825e19 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/ascii_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -197,11 +197,15 @@ TEST(AsciiStrTo, Lower) {
const std::string str("GHIJKL");
const std::string str2("MNOPQR");
const absl::string_view sp(str2);
+ std::string mutable_str("STUVWX");
EXPECT_EQ("abcdef", absl::AsciiStrToLower(buf));
EXPECT_EQ("ghijkl", absl::AsciiStrToLower(str));
EXPECT_EQ("mnopqr", absl::AsciiStrToLower(sp));
+ absl::AsciiStrToLower(&mutable_str);
+ EXPECT_EQ("stuvwx", mutable_str);
+
char mutable_buf[] = "Mutable";
std::transform(mutable_buf, mutable_buf + strlen(mutable_buf),
mutable_buf, absl::ascii_tolower);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.cc
index c7b8c98b1b4..b8674c28026 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,7 +20,7 @@
#include <cstring>
#include "absl/base/casts.h"
-#include "absl/base/internal/bits.h"
+#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/internal/charconv_bigint.h"
#include "absl/strings/internal/charconv_parse.h"
@@ -57,6 +57,7 @@
// narrower mantissas.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
template <typename FloatType>
@@ -241,11 +242,11 @@ struct CalculatedFloat {
// Returns the bit width of the given uint128. (Equivalently, returns 128
// minus the number of leading zero bits.)
-int BitWidth(uint128 value) {
+unsigned BitWidth(uint128 value) {
if (Uint128High64(value) == 0) {
- return 64 - base_internal::CountLeadingZeros64(Uint128Low64(value));
+ return static_cast<unsigned>(bit_width(Uint128Low64(value)));
}
- return 128 - base_internal::CountLeadingZeros64(Uint128High64(value));
+ return 128 - countl_zero(Uint128High64(value));
}
// Calculates how far to the right a mantissa needs to be shifted to create a
@@ -518,7 +519,7 @@ CalculatedFloat CalculateFromParsedHexadecimal(
const strings_internal::ParsedFloat& parsed_hex) {
uint64_t mantissa = parsed_hex.mantissa;
int exponent = parsed_hex.exponent;
- int mantissa_width = 64 - base_internal::CountLeadingZeros64(mantissa);
+ auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
bool result_exact;
exponent += shift;
@@ -551,9 +552,10 @@ CalculatedFloat CalculateFromParsedDecimal(
int binary_exponent = Power10Exponent(parsed_decimal.exponent);
// Discard bits that are inaccurate due to truncation error. The magic
- // `mantissa_width` constants below are justified in charconv_algorithm.md.
- // They represent the number of bits in `wide_binary_mantissa` that are
- // guaranteed to be unaffected by error propagation.
+ // `mantissa_width` constants below are justified in
+ // https://abseil.io/about/design/charconv. They represent the number of bits
+ // in `wide_binary_mantissa` that are guaranteed to be unaffected by error
+ // propagation.
bool mantissa_exact;
int mantissa_width;
if (parsed_decimal.subrange_begin) {
@@ -617,10 +619,10 @@ from_chars_result FromCharsImpl(const char* first, const char* last,
// Either we failed to parse a hex float after the "0x", or we read
// "0xinf" or "0xnan" which we don't want to match.
//
- // However, a std::string that begins with "0x" also begins with "0", which
+ // However, a string that begins with "0x" also begins with "0", which
// is normally a valid match for the number zero. So we want these
// strings to match zero unless fmt_flags is `scientific`. (This flag
- // means an exponent is required, which the std::string "0" does not have.)
+ // means an exponent is required, which the string "0" does not have.)
if (fmt_flags == chars_format::scientific) {
result.ec = std::errc::invalid_argument;
} else {
@@ -671,7 +673,6 @@ from_chars_result FromCharsImpl(const char* first, const char* last,
EncodeResult(calculated, negative, &result, &value);
return result;
}
- return result;
}
} // namespace
@@ -979,4 +980,5 @@ const int16_t kPower10ExponentTable[] = {
};
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.h
index 07353829623..e04be32f951 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,7 +17,10 @@
#include <system_error> // NOLINT(build/c++11)
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Workalike compatibilty version of std::chars_format from C++17.
//
@@ -49,9 +52,9 @@ struct from_chars_result {
// this only supports the `double` and `float` types.
//
// This interface incorporates the proposed resolutions for library issues
-// DR 3800 and DR 3801. If these are adopted with different wording,
+// DR 3080 and DR 3081. If these are adopted with different wording,
// Abseil's behavior will change to match the standard. (The behavior most
-// likely to change is for DR 3801, which says what `value` will be set to in
+// likely to change is for DR 3081, which says what `value` will be set to in
// the case of overflow and underflow. Code that wants to avoid possible
// breaking changes in this area should not depend on `value` when the returned
// from_chars_result indicates a range error.)
@@ -110,6 +113,7 @@ inline chars_format& operator^=(chars_format& lhs, chars_format rhs) {
return lhs;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_CHARCONV_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_benchmark.cc
index fd83f44e3d0..e8c7371d658 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -132,7 +132,7 @@ BENCHMARK(BM_Absl_HugeMantissa);
std::string MakeHardCase(int length) {
// The number 1.1521...e-297 is exactly halfway between 12345 * 2**-1000 and
// the next larger representable number. The digits of this number are in
- // the std::string below.
+ // the string below.
const std::string digits =
"1."
"152113937042223790993097181572444900347587985074226836242307364987727724"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_test.cc
index d07537eb590..b83de5a0ba2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/charconv_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -279,7 +279,8 @@ void TestHalfwayValue(const std::string& mantissa, int exponent,
absl::from_chars(low_rep.data(), low_rep.data() + low_rep.size(), actual_low);
EXPECT_EQ(expected_low, actual_low);
- std::string high_rep = absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
+ std::string high_rep =
+ absl::StrCat(mantissa, std::string(1000, '0'), "1e", exponent);
FloatType actual_high = 0;
absl::from_chars(high_rep.data(), high_rep.data() + high_rep.size(),
actual_high);
@@ -510,6 +511,13 @@ TEST(FromChars, Overflow) {
EXPECT_EQ(f, std::numeric_limits<float>::max());
}
+TEST(FromChars, RegressionTestsFromFuzzer) {
+ absl::string_view src = "0x21900000p00000000099";
+ float f;
+ auto result = absl::from_chars(src.data(), src.data() + src.size(), f);
+ EXPECT_EQ(result.ec, std::errc::result_out_of_range);
+}
+
TEST(FromChars, ReturnValuePtr) {
// Check that `ptr` points one past the number scanned, even if that number
// is not representable.
@@ -645,7 +653,9 @@ TEST(FromChars, NaNFloats) {
negative_from_chars_float);
EXPECT_TRUE(std::signbit(negative_from_chars_float));
EXPECT_FALSE(Identical(negative_from_chars_float, from_chars_float));
- from_chars_float = std::copysign(from_chars_float, -1.0);
+ // Use the (float, float) overload of std::copysign to prevent narrowing;
+ // see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98251.
+ from_chars_float = std::copysign(from_chars_float, -1.0f);
EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float));
}
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.cc
new file mode 100644
index 00000000000..93533757f59
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.cc
@@ -0,0 +1,1953 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/cord.h"
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <cstdio>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <sstream>
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include "absl/base/casts.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/fixed_array.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+using ::absl::cord_internal::CordRep;
+using ::absl::cord_internal::CordRepConcat;
+using ::absl::cord_internal::CordRepExternal;
+using ::absl::cord_internal::CordRepFlat;
+using ::absl::cord_internal::CordRepRing;
+using ::absl::cord_internal::CordRepSubstring;
+using ::absl::cord_internal::kMinFlatLength;
+using ::absl::cord_internal::kMaxFlatLength;
+
+using ::absl::cord_internal::CONCAT;
+using ::absl::cord_internal::EXTERNAL;
+using ::absl::cord_internal::FLAT;
+using ::absl::cord_internal::RING;
+using ::absl::cord_internal::SUBSTRING;
+
+using ::absl::cord_internal::kInlinedVectorSize;
+using ::absl::cord_internal::kMaxBytesToCopy;
+
+constexpr uint64_t Fibonacci(unsigned char n, uint64_t a = 0, uint64_t b = 1) {
+ return n == 0 ? a : Fibonacci(n - 1, b, a + b);
+}
+
+static_assert(Fibonacci(63) == 6557470319842,
+ "Fibonacci values computed incorrectly");
+
+// Minimum length required for a given depth tree -- a tree is considered
+// balanced if
+// length(t) >= min_length[depth(t)]
+// The root node depth is allowed to become twice as large to reduce rebalancing
+// for larger strings (see IsRootBalanced).
+static constexpr uint64_t min_length[] = {
+ Fibonacci(2), Fibonacci(3), Fibonacci(4), Fibonacci(5),
+ Fibonacci(6), Fibonacci(7), Fibonacci(8), Fibonacci(9),
+ Fibonacci(10), Fibonacci(11), Fibonacci(12), Fibonacci(13),
+ Fibonacci(14), Fibonacci(15), Fibonacci(16), Fibonacci(17),
+ Fibonacci(18), Fibonacci(19), Fibonacci(20), Fibonacci(21),
+ Fibonacci(22), Fibonacci(23), Fibonacci(24), Fibonacci(25),
+ Fibonacci(26), Fibonacci(27), Fibonacci(28), Fibonacci(29),
+ Fibonacci(30), Fibonacci(31), Fibonacci(32), Fibonacci(33),
+ Fibonacci(34), Fibonacci(35), Fibonacci(36), Fibonacci(37),
+ Fibonacci(38), Fibonacci(39), Fibonacci(40), Fibonacci(41),
+ Fibonacci(42), Fibonacci(43), Fibonacci(44), Fibonacci(45),
+ Fibonacci(46), Fibonacci(47),
+ 0xffffffffffffffffull, // Avoid overflow
+};
+
+static const int kMinLengthSize = ABSL_ARRAYSIZE(min_length);
+
+static inline bool cord_ring_enabled() {
+ return cord_internal::cord_ring_buffer_enabled.load(
+ std::memory_order_relaxed);
+}
+
+static inline bool IsRootBalanced(CordRep* node) {
+ if (node->tag != CONCAT) {
+ return true;
+ } else if (node->concat()->depth() <= 15) {
+ return true;
+ } else if (node->concat()->depth() > kMinLengthSize) {
+ return false;
+ } else {
+ // Allow depth to become twice as large as implied by fibonacci rule to
+ // reduce rebalancing for larger strings.
+ return (node->length >= min_length[node->concat()->depth() / 2]);
+ }
+}
+
+static CordRep* Rebalance(CordRep* node);
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
+ int indent = 0);
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+ bool full_validation);
+
+static inline CordRep* VerifyTree(CordRep* node) {
+ // Verification is expensive, so only do it in debug mode.
+ // Even in debug mode we normally do only light validation.
+ // If you are debugging Cord itself, you should define the
+ // macro EXTRA_CORD_VALIDATION, e.g. by adding
+ // --copt=-DEXTRA_CORD_VALIDATION to the blaze line.
+#ifdef EXTRA_CORD_VALIDATION
+ assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/true));
+#else // EXTRA_CORD_VALIDATION
+ assert(node == nullptr || VerifyNode(node, node, /*full_validation=*/false));
+#endif // EXTRA_CORD_VALIDATION
+ static_cast<void>(&VerifyNode);
+
+ return node;
+}
+
+// Return the depth of a node
+static int Depth(const CordRep* rep) {
+ if (rep->tag == CONCAT) {
+ return rep->concat()->depth();
+ } else {
+ return 0;
+ }
+}
+
+static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
+ CordRep* right) {
+ concat->left = left;
+ concat->right = right;
+
+ concat->length = left->length + right->length;
+ concat->set_depth(1 + std::max(Depth(left), Depth(right)));
+}
+
+// Create a concatenation of the specified nodes.
+// Does not change the refcounts of "left" and "right".
+// The returned node has a refcount of 1.
+static CordRep* RawConcat(CordRep* left, CordRep* right) {
+ // Avoid making degenerate concat nodes (one child is empty)
+ if (left == nullptr) return right;
+ if (right == nullptr) return left;
+ if (left->length == 0) {
+ CordRep::Unref(left);
+ return right;
+ }
+ if (right->length == 0) {
+ CordRep::Unref(right);
+ return left;
+ }
+
+ CordRepConcat* rep = new CordRepConcat();
+ rep->tag = CONCAT;
+ SetConcatChildren(rep, left, right);
+
+ return rep;
+}
+
+static CordRep* Concat(CordRep* left, CordRep* right) {
+ CordRep* rep = RawConcat(left, right);
+ if (rep != nullptr && !IsRootBalanced(rep)) {
+ rep = Rebalance(rep);
+ }
+ return VerifyTree(rep);
+}
+
+// Make a balanced tree out of an array of leaf nodes.
+static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
+ // Make repeated passes over the array, merging adjacent pairs
+ // until we are left with just a single node.
+ while (n > 1) {
+ size_t dst = 0;
+ for (size_t src = 0; src < n; src += 2) {
+ if (src + 1 < n) {
+ reps[dst] = Concat(reps[src], reps[src + 1]);
+ } else {
+ reps[dst] = reps[src];
+ }
+ dst++;
+ }
+ n = dst;
+ }
+
+ return reps[0];
+}
+
+static CordRepFlat* CreateFlat(const char* data, size_t length,
+ size_t alloc_hint) {
+ CordRepFlat* flat = CordRepFlat::New(length + alloc_hint);
+ flat->length = length;
+ memcpy(flat->Data(), data, length);
+ return flat;
+}
+
+// Creates a new flat or ringbuffer out of the specified array.
+// The returned node has a refcount of 1.
+static CordRep* RingNewTree(const char* data, size_t length,
+ size_t alloc_hint) {
+ if (length <= kMaxFlatLength) {
+ return CreateFlat(data, length, alloc_hint);
+ }
+ CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
+ data += kMaxFlatLength;
+ length -= kMaxFlatLength;
+ size_t extra = (length - 1) / kMaxFlatLength + 1;
+ auto* root = CordRepRing::Create(flat, extra);
+ return CordRepRing::Append(root, {data, length}, alloc_hint);
+}
+
+// Create a new tree out of the specified array.
+// The returned node has a refcount of 1.
+static CordRep* NewTree(const char* data,
+ size_t length,
+ size_t alloc_hint) {
+ if (length == 0) return nullptr;
+ if (cord_ring_enabled()) {
+ return RingNewTree(data, length, alloc_hint);
+ }
+ absl::FixedArray<CordRep*> reps((length - 1) / kMaxFlatLength + 1);
+ size_t n = 0;
+ do {
+ const size_t len = std::min(length, kMaxFlatLength);
+ CordRepFlat* rep = CordRepFlat::New(len + alloc_hint);
+ rep->length = len;
+ memcpy(rep->Data(), data, len);
+ reps[n++] = VerifyTree(rep);
+ data += len;
+ length -= len;
+ } while (length != 0);
+ return MakeBalancedTree(reps.data(), n);
+}
+
+namespace cord_internal {
+
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
+ assert(!data.empty());
+ rep->length = data.size();
+ rep->tag = EXTERNAL;
+ rep->base = data.data();
+ VerifyTree(rep);
+}
+
+} // namespace cord_internal
+
+static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
+ // Never create empty substring nodes
+ if (length == 0) {
+ CordRep::Unref(child);
+ return nullptr;
+ } else {
+ CordRepSubstring* rep = new CordRepSubstring();
+ assert((offset + length) <= child->length);
+ rep->length = length;
+ rep->tag = SUBSTRING;
+ rep->start = offset;
+ rep->child = child;
+ return VerifyTree(rep);
+ }
+}
+
+// --------------------------------------------------------------------
+// Cord::InlineRep functions
+
+constexpr unsigned char Cord::InlineRep::kMaxInline;
+
+inline void Cord::InlineRep::set_data(const char* data, size_t n,
+ bool nullify_tail) {
+ static_assert(kMaxInline == 15, "set_data is hard-coded for a length of 15");
+
+ cord_internal::SmallMemmove(data_.as_chars(), data, n, nullify_tail);
+ set_inline_size(n);
+}
+
+inline char* Cord::InlineRep::set_data(size_t n) {
+ assert(n <= kMaxInline);
+ ResetToEmpty();
+ set_inline_size(n);
+ return data_.as_chars();
+}
+
+inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
+ if (data_.is_tree()) {
+ return data_.as_tree();
+ }
+
+ size_t len = inline_size();
+ CordRepFlat* result = CordRepFlat::New(len + extra_hint);
+ result->length = len;
+ static_assert(kMinFlatLength >= sizeof(data_), "");
+ memcpy(result->Data(), data_.as_chars(), sizeof(data_));
+ set_tree(result);
+ return result;
+}
+
+inline void Cord::InlineRep::reduce_size(size_t n) {
+ size_t tag = inline_size();
+ assert(tag <= kMaxInline);
+ assert(tag >= n);
+ tag -= n;
+ memset(data_.as_chars() + tag, 0, n);
+ set_inline_size(static_cast<char>(tag));
+}
+
+inline void Cord::InlineRep::remove_prefix(size_t n) {
+ cord_internal::SmallMemmove(data_.as_chars(), data_.as_chars() + n,
+ inline_size() - n);
+ reduce_size(n);
+}
+
+// Returns `rep` converted into a CordRepRing.
+// Directly returns `rep` if `rep` is already a CordRepRing.
+static CordRepRing* ForceRing(CordRep* rep, size_t extra) {
+ return (rep->tag == RING) ? rep->ring() : CordRepRing::Create(rep, extra);
+}
+
+void Cord::InlineRep::AppendTree(CordRep* tree) {
+ if (tree == nullptr) return;
+ if (data_.is_empty()) {
+ set_tree(tree);
+ } else if (cord_ring_enabled()) {
+ set_tree(CordRepRing::Append(ForceRing(force_tree(0), 1), tree));
+ } else {
+ set_tree(Concat(force_tree(0), tree));
+ }
+}
+
+void Cord::InlineRep::PrependTree(CordRep* tree) {
+ assert(tree != nullptr);
+ if (data_.is_empty()) {
+ set_tree(tree);
+ } else if (cord_ring_enabled()) {
+ set_tree(CordRepRing::Prepend(ForceRing(force_tree(0), 1), tree));
+ } else {
+ set_tree(Concat(tree, force_tree(0)));
+ }
+}
+
+// Searches for a non-full flat node at the rightmost leaf of the tree. If a
+// suitable leaf is found, the function will update the length field for all
+// nodes to account for the size increase. The append region address will be
+// written to region and the actual size increase will be written to size.
+static inline bool PrepareAppendRegion(CordRep* root, char** region,
+ size_t* size, size_t max_length) {
+ if (root->tag == RING && root->refcount.IsOne()) {
+ Span<char> span = root->ring()->GetAppendBuffer(max_length);
+ if (!span.empty()) {
+ *region = span.data();
+ *size = span.size();
+ return true;
+ }
+ }
+
+ // Search down the right-hand path for a non-full FLAT node.
+ CordRep* dst = root;
+ while (dst->tag == CONCAT && dst->refcount.IsOne()) {
+ dst = dst->concat()->right;
+ }
+
+ if (dst->tag < FLAT || !dst->refcount.IsOne()) {
+ *region = nullptr;
+ *size = 0;
+ return false;
+ }
+
+ const size_t in_use = dst->length;
+ const size_t capacity = dst->flat()->Capacity();
+ if (in_use == capacity) {
+ *region = nullptr;
+ *size = 0;
+ return false;
+ }
+
+ size_t size_increase = std::min(capacity - in_use, max_length);
+
+ // We need to update the length fields for all nodes, including the leaf node.
+ for (CordRep* rep = root; rep != dst; rep = rep->concat()->right) {
+ rep->length += size_increase;
+ }
+ dst->length += size_increase;
+
+ *region = dst->flat()->Data() + in_use;
+ *size = size_increase;
+ return true;
+}
+
+void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
+ size_t max_length) {
+ if (max_length == 0) {
+ *region = nullptr;
+ *size = 0;
+ return;
+ }
+
+ // Try to fit in the inline buffer if possible.
+ if (!is_tree()) {
+ size_t inline_length = inline_size();
+ if (max_length <= kMaxInline - inline_length) {
+ *region = data_.as_chars() + inline_length;
+ *size = max_length;
+ set_inline_size(inline_length + max_length);
+ return;
+ }
+ }
+
+ CordRep* root = force_tree(max_length);
+
+ if (PrepareAppendRegion(root, region, size, max_length)) {
+ return;
+ }
+
+ // Allocate new node.
+ CordRepFlat* new_node =
+ CordRepFlat::New(std::max(static_cast<size_t>(root->length), max_length));
+ new_node->length = std::min(new_node->Capacity(), max_length);
+ *region = new_node->Data();
+ *size = new_node->length;
+
+ if (cord_ring_enabled()) {
+ replace_tree(CordRepRing::Append(ForceRing(root, 1), new_node));
+ return;
+ }
+ replace_tree(Concat(root, new_node));
+}
+
+void Cord::InlineRep::GetAppendRegion(char** region, size_t* size) {
+ const size_t max_length = std::numeric_limits<size_t>::max();
+
+ // Try to fit in the inline buffer if possible.
+ if (!data_.is_tree()) {
+ size_t inline_length = inline_size();
+ if (inline_length < kMaxInline) {
+ *region = data_.as_chars() + inline_length;
+ *size = kMaxInline - inline_length;
+ set_inline_size(kMaxInline);
+ return;
+ }
+ }
+
+ CordRep* root = force_tree(max_length);
+
+ if (PrepareAppendRegion(root, region, size, max_length)) {
+ return;
+ }
+
+ // Allocate new node.
+ CordRepFlat* new_node = CordRepFlat::New(root->length);
+ new_node->length = new_node->Capacity();
+ *region = new_node->Data();
+ *size = new_node->length;
+
+ if (cord_ring_enabled()) {
+ replace_tree(CordRepRing::Append(ForceRing(root, 1), new_node));
+ return;
+ }
+ replace_tree(Concat(root, new_node));
+}
+
+// If the rep is a leaf, this will increment the value at total_mem_usage and
+// will return true.
+static bool RepMemoryUsageLeaf(const CordRep* rep, size_t* total_mem_usage) {
+ if (rep->tag >= FLAT) {
+ *total_mem_usage += rep->flat()->AllocatedSize();
+ return true;
+ }
+ if (rep->tag == EXTERNAL) {
+ *total_mem_usage += sizeof(CordRepConcat) + rep->length;
+ return true;
+ }
+ return false;
+}
+
+void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
+ ClearSlow();
+
+ data_ = src.data_;
+ if (is_tree()) {
+ data_.set_profiled(false);
+ CordRep::Ref(tree());
+ clear_cordz_info();
+ }
+}
+
+void Cord::InlineRep::ClearSlow() {
+ if (is_tree()) {
+ CordRep::Unref(tree());
+ }
+ ResetToEmpty();
+}
+
+// --------------------------------------------------------------------
+// Constructors and destructors
+
+Cord::Cord(absl::string_view src) {
+ const size_t n = src.size();
+ if (n <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), n, false);
+ } else {
+ contents_.set_tree(NewTree(src.data(), n, 0));
+ }
+}
+
+template <typename T, Cord::EnableIfString<T>>
+Cord::Cord(T&& src) {
+ if (
+ // String is short: copy data to avoid external block overhead.
+ src.size() <= kMaxBytesToCopy ||
+ // String is wasteful: copy data to avoid pinning too much unused memory.
+ src.size() < src.capacity() / 2
+ ) {
+ if (src.size() <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), src.size(), false);
+ } else {
+ contents_.set_tree(NewTree(src.data(), src.size(), 0));
+ }
+ } else {
+ struct StringReleaser {
+ void operator()(absl::string_view /* data */) {}
+ std::string data;
+ };
+ const absl::string_view original_data = src;
+ auto* rep = static_cast<
+ ::absl::cord_internal::CordRepExternalImpl<StringReleaser>*>(
+ absl::cord_internal::NewExternalRep(
+ original_data, StringReleaser{std::forward<T>(src)}));
+ // Moving src may have invalidated its data pointer, so adjust it.
+ rep->base = rep->template get<0>().data.data();
+ contents_.set_tree(rep);
+ }
+}
+
+template Cord::Cord(std::string&& src);
+
+// The destruction code is separate so that the compiler can determine
+// that it does not need to call the destructor on a moved-from Cord.
+void Cord::DestroyCordSlow() {
+ if (CordRep* tree = contents_.tree()) {
+ CordRep::Unref(VerifyTree(tree));
+ }
+}
+
+// --------------------------------------------------------------------
+// Mutators
+
+void Cord::Clear() {
+ if (CordRep* tree = contents_.clear()) {
+ CordRep::Unref(tree);
+ }
+}
+
+Cord& Cord::operator=(absl::string_view src) {
+
+ const char* data = src.data();
+ size_t length = src.size();
+ CordRep* tree = contents_.tree();
+ if (length <= InlineRep::kMaxInline) {
+ // Embed into this->contents_
+ contents_.set_data(data, length, true);
+ if (tree) CordRep::Unref(tree);
+ return *this;
+ }
+ if (tree != nullptr && tree->tag >= FLAT &&
+ tree->flat()->Capacity() >= length &&
+ tree->refcount.IsOne()) {
+ // Copy in place if the existing FLAT node is reusable.
+ memmove(tree->flat()->Data(), data, length);
+ tree->length = length;
+ VerifyTree(tree);
+ return *this;
+ }
+ contents_.set_tree(NewTree(data, length, 0));
+ if (tree) CordRep::Unref(tree);
+ return *this;
+}
+
+template <typename T, Cord::EnableIfString<T>>
+Cord& Cord::operator=(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ *this = absl::string_view(src);
+ } else {
+ *this = Cord(std::forward<T>(src));
+ }
+ return *this;
+}
+
+template Cord& Cord::operator=(std::string&& src);
+
+// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
+// we keep it here to make diffs easier.
+void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
+ if (src_size == 0) return; // memcpy(_, nullptr, 0) is undefined.
+
+ size_t appended = 0;
+ CordRep* root = nullptr;
+ if (is_tree()) {
+ root = data_.as_tree();
+ char* region;
+ if (PrepareAppendRegion(root, &region, &appended, src_size)) {
+ memcpy(region, src_data, appended);
+ }
+ } else {
+ // Try to fit in the inline buffer if possible.
+ size_t inline_length = inline_size();
+ if (src_size <= kMaxInline - inline_length) {
+ // Append new data to embedded array
+ memcpy(data_.as_chars() + inline_length, src_data, src_size);
+ set_inline_size(inline_length + src_size);
+ return;
+ }
+
+ // It is possible that src_data == data_, but when we transition from an
+ // InlineRep to a tree we need to assign data_ = root via set_tree. To
+ // avoid corrupting the source data before we copy it, delay calling
+ // set_tree until after we've copied data.
+ // We are going from an inline size to beyond inline size. Make the new size
+ // either double the inlined size, or the added size + 10%.
+ const size_t size1 = inline_length * 2 + src_size;
+ const size_t size2 = inline_length + src_size / 10;
+ root = CordRepFlat::New(std::max<size_t>(size1, size2));
+ appended = std::min(
+ src_size, root->flat()->Capacity() - inline_length);
+ memcpy(root->flat()->Data(), data_.as_chars(), inline_length);
+ memcpy(root->flat()->Data() + inline_length, src_data, appended);
+ root->length = inline_length + appended;
+ set_tree(root);
+ }
+
+ src_data += appended;
+ src_size -= appended;
+ if (src_size == 0) {
+ return;
+ }
+
+ if (cord_ring_enabled()) {
+ absl::string_view data(src_data, src_size);
+ root = ForceRing(root, (data.size() - 1) / kMaxFlatLength + 1);
+ replace_tree(CordRepRing::Append(root->ring(), data));
+ return;
+ }
+
+ // Use new block(s) for any remaining bytes that were not handled above.
+ // Alloc extra memory only if the right child of the root of the new tree is
+ // going to be a FLAT node, which will permit further inplace appends.
+ size_t length = src_size;
+ if (src_size < kMaxFlatLength) {
+ // The new length is either
+ // - old size + 10%
+ // - old_size + src_size
+ // This will cause a reasonable conservative step-up in size that is still
+ // large enough to avoid excessive amounts of small fragments being added.
+ length = std::max<size_t>(root->length / 10, src_size);
+ }
+ set_tree(Concat(root, NewTree(src_data, src_size, length - src_size)));
+}
+
+inline CordRep* Cord::TakeRep() const& {
+ return CordRep::Ref(contents_.tree());
+}
+
+inline CordRep* Cord::TakeRep() && {
+ CordRep* rep = contents_.tree();
+ contents_.clear();
+ return rep;
+}
+
+template <typename C>
+inline void Cord::AppendImpl(C&& src) {
+ if (empty()) {
+ // In case of an empty destination avoid allocating a new node, do not copy
+ // data.
+ *this = std::forward<C>(src);
+ return;
+ }
+
+ // For short cords, it is faster to copy data if there is room in dst.
+ const size_t src_size = src.contents_.size();
+ if (src_size <= kMaxBytesToCopy) {
+ CordRep* src_tree = src.contents_.tree();
+ if (src_tree == nullptr) {
+ // src has embedded data.
+ contents_.AppendArray(src.contents_.data(), src_size);
+ return;
+ }
+ if (src_tree->tag >= FLAT) {
+ // src tree just has one flat node.
+ contents_.AppendArray(src_tree->flat()->Data(), src_size);
+ return;
+ }
+ if (&src == this) {
+ // ChunkIterator below assumes that src is not modified during traversal.
+ Append(Cord(src));
+ return;
+ }
+ // TODO(mec): Should we only do this if "dst" has space?
+ for (absl::string_view chunk : src.Chunks()) {
+ Append(chunk);
+ }
+ return;
+ }
+
+ // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
+ contents_.AppendTree(std::forward<C>(src).TakeRep());
+}
+
+void Cord::Append(const Cord& src) { AppendImpl(src); }
+
+void Cord::Append(Cord&& src) { AppendImpl(std::move(src)); }
+
+template <typename T, Cord::EnableIfString<T>>
+void Cord::Append(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Append(absl::string_view(src));
+ } else {
+ Append(Cord(std::forward<T>(src)));
+ }
+}
+
+template void Cord::Append(std::string&& src);
+
+void Cord::Prepend(const Cord& src) {
+ CordRep* src_tree = src.contents_.tree();
+ if (src_tree != nullptr) {
+ CordRep::Ref(src_tree);
+ contents_.PrependTree(src_tree);
+ return;
+ }
+
+ // `src` cord is inlined.
+ absl::string_view src_contents(src.contents_.data(), src.contents_.size());
+ return Prepend(src_contents);
+}
+
+void Cord::Prepend(absl::string_view src) {
+ if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
+ if (!contents_.is_tree()) {
+ size_t cur_size = contents_.inline_size();
+ if (cur_size + src.size() <= InlineRep::kMaxInline) {
+ // Use embedded storage.
+ char data[InlineRep::kMaxInline + 1] = {0};
+ memcpy(data, src.data(), src.size());
+ memcpy(data + src.size(), contents_.data(), cur_size);
+ memcpy(contents_.data_.as_chars(), data, InlineRep::kMaxInline + 1);
+ contents_.set_inline_size(cur_size + src.size());
+ return;
+ }
+ }
+ contents_.PrependTree(NewTree(src.data(), src.size(), 0));
+}
+
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ if (src.size() <= kMaxBytesToCopy) {
+ Prepend(absl::string_view(src));
+ } else {
+ Prepend(Cord(std::forward<T>(src)));
+ }
+}
+
+template void Cord::Prepend(std::string&& src);
+
+static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
+ if (n >= node->length) return nullptr;
+ if (n == 0) return CordRep::Ref(node);
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
+
+ while (node->tag == CONCAT) {
+ assert(n <= node->length);
+ if (n < node->concat()->left->length) {
+ // Push right to stack, descend left.
+ rhs_stack.push_back(node->concat()->right);
+ node = node->concat()->left;
+ } else {
+ // Drop left, descend right.
+ n -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+ assert(n <= node->length);
+
+ if (n == 0) {
+ CordRep::Ref(node);
+ } else {
+ size_t start = n;
+ size_t len = node->length - n;
+ if (node->tag == SUBSTRING) {
+ // Consider in-place update of node, similar to in RemoveSuffixFrom().
+ start += node->substring()->start;
+ node = node->substring()->child;
+ }
+ node = NewSubstring(CordRep::Ref(node), start, len);
+ }
+ while (!rhs_stack.empty()) {
+ node = Concat(node, CordRep::Ref(rhs_stack.back()));
+ rhs_stack.pop_back();
+ }
+ return node;
+}
+
+// RemoveSuffixFrom() is very similar to RemovePrefixFrom(), with the
+// exception that removing a suffix has an optimization where a node may be
+// edited in place iff that node and all its ancestors have a refcount of 1.
+static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
+ if (n >= node->length) return nullptr;
+ if (n == 0) return CordRep::Ref(node);
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
+ bool inplace_ok = node->refcount.IsOne();
+
+ while (node->tag == CONCAT) {
+ assert(n <= node->length);
+ if (n < node->concat()->right->length) {
+ // Push left to stack, descend right.
+ lhs_stack.push_back(node->concat()->left);
+ node = node->concat()->right;
+ } else {
+ // Drop right, descend left.
+ n -= node->concat()->right->length;
+ node = node->concat()->left;
+ }
+ inplace_ok = inplace_ok && node->refcount.IsOne();
+ }
+ assert(n <= node->length);
+
+ if (n == 0) {
+ CordRep::Ref(node);
+ } else if (inplace_ok && node->tag != EXTERNAL) {
+ // Consider making a new buffer if the current node capacity is much
+ // larger than the new length.
+ CordRep::Ref(node);
+ node->length -= n;
+ } else {
+ size_t start = 0;
+ size_t len = node->length - n;
+ if (node->tag == SUBSTRING) {
+ start = node->substring()->start;
+ node = node->substring()->child;
+ }
+ node = NewSubstring(CordRep::Ref(node), start, len);
+ }
+ while (!lhs_stack.empty()) {
+ node = Concat(CordRep::Ref(lhs_stack.back()), node);
+ lhs_stack.pop_back();
+ }
+ return node;
+}
+
+void Cord::RemovePrefix(size_t n) {
+ ABSL_INTERNAL_CHECK(n <= size(),
+ absl::StrCat("Requested prefix size ", n,
+ " exceeds Cord's size ", size()));
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ contents_.remove_prefix(n);
+ } else if (tree->tag == RING) {
+ contents_.replace_tree(CordRepRing::RemovePrefix(tree->ring(), n));
+ } else {
+ CordRep* newrep = RemovePrefixFrom(tree, n);
+ CordRep::Unref(tree);
+ contents_.replace_tree(VerifyTree(newrep));
+ }
+}
+
+void Cord::RemoveSuffix(size_t n) {
+ ABSL_INTERNAL_CHECK(n <= size(),
+ absl::StrCat("Requested suffix size ", n,
+ " exceeds Cord's size ", size()));
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ contents_.reduce_size(n);
+ } else if (tree->tag == RING) {
+ contents_.replace_tree(CordRepRing::RemoveSuffix(tree->ring(), n));
+ } else {
+ CordRep* newrep = RemoveSuffixFrom(tree, n);
+ CordRep::Unref(tree);
+ contents_.replace_tree(VerifyTree(newrep));
+ }
+}
+
+// Work item for NewSubRange().
+struct SubRange {
+ SubRange(CordRep* a_node, size_t a_pos, size_t a_n)
+ : node(a_node), pos(a_pos), n(a_n) {}
+ CordRep* node; // nullptr means concat last 2 results.
+ size_t pos;
+ size_t n;
+};
+
+static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> results;
+ absl::InlinedVector<SubRange, kInlinedVectorSize> todo;
+ todo.push_back(SubRange(node, pos, n));
+ do {
+ const SubRange& sr = todo.back();
+ node = sr.node;
+ pos = sr.pos;
+ n = sr.n;
+ todo.pop_back();
+
+ if (node == nullptr) {
+ assert(results.size() >= 2);
+ CordRep* right = results.back();
+ results.pop_back();
+ CordRep* left = results.back();
+ results.pop_back();
+ results.push_back(Concat(left, right));
+ } else if (pos == 0 && n == node->length) {
+ results.push_back(CordRep::Ref(node));
+ } else if (node->tag != CONCAT) {
+ if (node->tag == SUBSTRING) {
+ pos += node->substring()->start;
+ node = node->substring()->child;
+ }
+ results.push_back(NewSubstring(CordRep::Ref(node), pos, n));
+ } else if (pos + n <= node->concat()->left->length) {
+ todo.push_back(SubRange(node->concat()->left, pos, n));
+ } else if (pos >= node->concat()->left->length) {
+ pos -= node->concat()->left->length;
+ todo.push_back(SubRange(node->concat()->right, pos, n));
+ } else {
+ size_t left_n = node->concat()->left->length - pos;
+ todo.push_back(SubRange(nullptr, 0, 0)); // Concat()
+ todo.push_back(SubRange(node->concat()->right, 0, n - left_n));
+ todo.push_back(SubRange(node->concat()->left, pos, left_n));
+ }
+ } while (!todo.empty());
+ assert(results.size() == 1);
+ return results[0];
+}
+
+Cord Cord::Subcord(size_t pos, size_t new_size) const {
+ Cord sub_cord;
+ size_t length = size();
+ if (pos > length) pos = length;
+ if (new_size > length - pos) new_size = length - pos;
+ CordRep* tree = contents_.tree();
+ if (tree == nullptr) {
+ // sub_cord is newly constructed, no need to re-zero-out the tail of
+ // contents_ memory.
+ sub_cord.contents_.set_data(contents_.data() + pos, new_size, false);
+ } else if (new_size == 0) {
+ // We want to return empty subcord, so nothing to do.
+ } else if (new_size <= InlineRep::kMaxInline) {
+ Cord::ChunkIterator it = chunk_begin();
+ it.AdvanceBytes(pos);
+ char* dest = sub_cord.contents_.data_.as_chars();
+ size_t remaining_size = new_size;
+ while (remaining_size > it->size()) {
+ cord_internal::SmallMemmove(dest, it->data(), it->size());
+ remaining_size -= it->size();
+ dest += it->size();
+ ++it;
+ }
+ cord_internal::SmallMemmove(dest, it->data(), remaining_size);
+ sub_cord.contents_.set_inline_size(new_size);
+ } else if (tree->tag == RING) {
+ tree = CordRepRing::SubRing(CordRep::Ref(tree)->ring(), pos, new_size);
+ sub_cord.contents_.set_tree(tree);
+ } else {
+ sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
+ }
+ return sub_cord;
+}
+
+// --------------------------------------------------------------------
+// Balancing
+
+class CordForest {
+ public:
+ explicit CordForest(size_t length)
+ : root_length_(length), trees_(kMinLengthSize, nullptr) {}
+
+ void Build(CordRep* cord_root) {
+ std::vector<CordRep*> pending = {cord_root};
+
+ while (!pending.empty()) {
+ CordRep* node = pending.back();
+ pending.pop_back();
+ CheckNode(node);
+ if (ABSL_PREDICT_FALSE(node->tag != CONCAT)) {
+ AddNode(node);
+ continue;
+ }
+
+ CordRepConcat* concat_node = node->concat();
+ if (concat_node->depth() >= kMinLengthSize ||
+ concat_node->length < min_length[concat_node->depth()]) {
+ pending.push_back(concat_node->right);
+ pending.push_back(concat_node->left);
+
+ if (concat_node->refcount.IsOne()) {
+ concat_node->left = concat_freelist_;
+ concat_freelist_ = concat_node;
+ } else {
+ CordRep::Ref(concat_node->right);
+ CordRep::Ref(concat_node->left);
+ CordRep::Unref(concat_node);
+ }
+ } else {
+ AddNode(node);
+ }
+ }
+ }
+
+ CordRep* ConcatNodes() {
+ CordRep* sum = nullptr;
+ for (auto* node : trees_) {
+ if (node == nullptr) continue;
+
+ sum = PrependNode(node, sum);
+ root_length_ -= node->length;
+ if (root_length_ == 0) break;
+ }
+ ABSL_INTERNAL_CHECK(sum != nullptr, "Failed to locate sum node");
+ return VerifyTree(sum);
+ }
+
+ private:
+ CordRep* AppendNode(CordRep* node, CordRep* sum) {
+ return (sum == nullptr) ? node : MakeConcat(sum, node);
+ }
+
+ CordRep* PrependNode(CordRep* node, CordRep* sum) {
+ return (sum == nullptr) ? node : MakeConcat(node, sum);
+ }
+
+ void AddNode(CordRep* node) {
+ CordRep* sum = nullptr;
+
+ // Collect together everything with which we will merge with node
+ int i = 0;
+ for (; node->length > min_length[i + 1]; ++i) {
+ auto& tree_at_i = trees_[i];
+
+ if (tree_at_i == nullptr) continue;
+ sum = PrependNode(tree_at_i, sum);
+ tree_at_i = nullptr;
+ }
+
+ sum = AppendNode(node, sum);
+
+ // Insert sum into appropriate place in the forest
+ for (; sum->length >= min_length[i]; ++i) {
+ auto& tree_at_i = trees_[i];
+ if (tree_at_i == nullptr) continue;
+
+ sum = MakeConcat(tree_at_i, sum);
+ tree_at_i = nullptr;
+ }
+
+ // min_length[0] == 1, which means sum->length >= min_length[0]
+ assert(i > 0);
+ trees_[i - 1] = sum;
+ }
+
+ // Make concat node trying to resue existing CordRepConcat nodes we
+ // already collected in the concat_freelist_.
+ CordRep* MakeConcat(CordRep* left, CordRep* right) {
+ if (concat_freelist_ == nullptr) return RawConcat(left, right);
+
+ CordRepConcat* rep = concat_freelist_;
+ if (concat_freelist_->left == nullptr) {
+ concat_freelist_ = nullptr;
+ } else {
+ concat_freelist_ = concat_freelist_->left->concat();
+ }
+ SetConcatChildren(rep, left, right);
+
+ return rep;
+ }
+
+ static void CheckNode(CordRep* node) {
+ ABSL_INTERNAL_CHECK(node->length != 0u, "");
+ if (node->tag == CONCAT) {
+ ABSL_INTERNAL_CHECK(node->concat()->left != nullptr, "");
+ ABSL_INTERNAL_CHECK(node->concat()->right != nullptr, "");
+ ABSL_INTERNAL_CHECK(node->length == (node->concat()->left->length +
+ node->concat()->right->length),
+ "");
+ }
+ }
+
+ size_t root_length_;
+
+ // use an inlined vector instead of a flat array to get bounds checking
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> trees_;
+
+ // List of concat nodes we can re-use for Cord balancing.
+ CordRepConcat* concat_freelist_ = nullptr;
+};
+
+static CordRep* Rebalance(CordRep* node) {
+ VerifyTree(node);
+ assert(node->tag == CONCAT);
+
+ if (node->length == 0) {
+ return nullptr;
+ }
+
+ CordForest forest(node->length);
+ forest.Build(node);
+ return forest.ConcatNodes();
+}
+
+// --------------------------------------------------------------------
+// Comparators
+
+namespace {
+
+int ClampResult(int memcmp_res) {
+ return static_cast<int>(memcmp_res > 0) - static_cast<int>(memcmp_res < 0);
+}
+
+int CompareChunks(absl::string_view* lhs, absl::string_view* rhs,
+ size_t* size_to_compare) {
+ size_t compared_size = std::min(lhs->size(), rhs->size());
+ assert(*size_to_compare >= compared_size);
+ *size_to_compare -= compared_size;
+
+ int memcmp_res = ::memcmp(lhs->data(), rhs->data(), compared_size);
+ if (memcmp_res != 0) return memcmp_res;
+
+ lhs->remove_prefix(compared_size);
+ rhs->remove_prefix(compared_size);
+
+ return 0;
+}
+
+// This overload set computes comparison results from memcmp result. This
+// interface is used inside GenericCompare below. Differet implementations
+// are specialized for int and bool. For int we clamp result to {-1, 0, 1}
+// set. For bool we just interested in "value == 0".
+template <typename ResultType>
+ResultType ComputeCompareResult(int memcmp_res) {
+ return ClampResult(memcmp_res);
+}
+template <>
+bool ComputeCompareResult<bool>(int memcmp_res) {
+ return memcmp_res == 0;
+}
+
+} // namespace
+
+// Helper routine. Locates the first flat chunk of the Cord without
+// initializing the iterator.
+inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
+ if (!is_tree()) {
+ return absl::string_view(data_.as_chars(), data_.inline_size());
+ }
+
+ CordRep* node = tree();
+ if (node->tag >= FLAT) {
+ return absl::string_view(node->flat()->Data(), node->length);
+ }
+
+ if (node->tag == EXTERNAL) {
+ return absl::string_view(node->external()->base, node->length);
+ }
+
+ if (node->tag == RING) {
+ return node->ring()->entry_data(node->ring()->head());
+ }
+
+ // Walk down the left branches until we hit a non-CONCAT node.
+ while (node->tag == CONCAT) {
+ node = node->concat()->left;
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
+ assert(length != 0);
+
+ if (node->tag == SUBSTRING) {
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
+ if (node->tag >= FLAT) {
+ return absl::string_view(node->flat()->Data() + offset, length);
+ }
+
+ assert((node->tag == EXTERNAL) && "Expect FLAT or EXTERNAL node here");
+
+ return absl::string_view(node->external()->base + offset, length);
+}
+
+inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size,
+ size_t size_to_compare) const {
+ auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+ if (!chunk->empty()) return true;
+ ++*it;
+ if (it->bytes_remaining_ == 0) return false;
+ *chunk = **it;
+ return true;
+ };
+
+ Cord::ChunkIterator lhs_it = chunk_begin();
+
+ // compared_size is inside first chunk.
+ absl::string_view lhs_chunk =
+ (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+ assert(compared_size <= lhs_chunk.size());
+ assert(compared_size <= rhs.size());
+ lhs_chunk.remove_prefix(compared_size);
+ rhs.remove_prefix(compared_size);
+ size_to_compare -= compared_size; // skip already compared size.
+
+ while (advance(&lhs_it, &lhs_chunk) && !rhs.empty()) {
+ int comparison_result = CompareChunks(&lhs_chunk, &rhs, &size_to_compare);
+ if (comparison_result != 0) return comparison_result;
+ if (size_to_compare == 0) return 0;
+ }
+
+ return static_cast<int>(rhs.empty()) - static_cast<int>(lhs_chunk.empty());
+}
+
+inline int Cord::CompareSlowPath(const Cord& rhs, size_t compared_size,
+ size_t size_to_compare) const {
+ auto advance = [](Cord::ChunkIterator* it, absl::string_view* chunk) {
+ if (!chunk->empty()) return true;
+ ++*it;
+ if (it->bytes_remaining_ == 0) return false;
+ *chunk = **it;
+ return true;
+ };
+
+ Cord::ChunkIterator lhs_it = chunk_begin();
+ Cord::ChunkIterator rhs_it = rhs.chunk_begin();
+
+ // compared_size is inside both first chunks.
+ absl::string_view lhs_chunk =
+ (lhs_it.bytes_remaining_ != 0) ? *lhs_it : absl::string_view();
+ absl::string_view rhs_chunk =
+ (rhs_it.bytes_remaining_ != 0) ? *rhs_it : absl::string_view();
+ assert(compared_size <= lhs_chunk.size());
+ assert(compared_size <= rhs_chunk.size());
+ lhs_chunk.remove_prefix(compared_size);
+ rhs_chunk.remove_prefix(compared_size);
+ size_to_compare -= compared_size; // skip already compared size.
+
+ while (advance(&lhs_it, &lhs_chunk) && advance(&rhs_it, &rhs_chunk)) {
+ int memcmp_res = CompareChunks(&lhs_chunk, &rhs_chunk, &size_to_compare);
+ if (memcmp_res != 0) return memcmp_res;
+ if (size_to_compare == 0) return 0;
+ }
+
+ return static_cast<int>(rhs_chunk.empty()) -
+ static_cast<int>(lhs_chunk.empty());
+}
+
+inline absl::string_view Cord::GetFirstChunk(const Cord& c) {
+ return c.contents_.FindFlatStartPiece();
+}
+inline absl::string_view Cord::GetFirstChunk(absl::string_view sv) {
+ return sv;
+}
+
+// Compares up to 'size_to_compare' bytes of 'lhs' with 'rhs'. It is assumed
+// that 'size_to_compare' is greater that size of smallest of first chunks.
+template <typename ResultType, typename RHS>
+ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+ size_t size_to_compare) {
+ absl::string_view lhs_chunk = Cord::GetFirstChunk(lhs);
+ absl::string_view rhs_chunk = Cord::GetFirstChunk(rhs);
+
+ size_t compared_size = std::min(lhs_chunk.size(), rhs_chunk.size());
+ assert(size_to_compare >= compared_size);
+ int memcmp_res = ::memcmp(lhs_chunk.data(), rhs_chunk.data(), compared_size);
+ if (compared_size == size_to_compare || memcmp_res != 0) {
+ return ComputeCompareResult<ResultType>(memcmp_res);
+ }
+
+ return ComputeCompareResult<ResultType>(
+ lhs.CompareSlowPath(rhs, compared_size, size_to_compare));
+}
+
+bool Cord::EqualsImpl(absl::string_view rhs, size_t size_to_compare) const {
+ return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+bool Cord::EqualsImpl(const Cord& rhs, size_t size_to_compare) const {
+ return GenericCompare<bool>(*this, rhs, size_to_compare);
+}
+
+template <typename RHS>
+inline int SharedCompareImpl(const Cord& lhs, const RHS& rhs) {
+ size_t lhs_size = lhs.size();
+ size_t rhs_size = rhs.size();
+ if (lhs_size == rhs_size) {
+ return GenericCompare<int>(lhs, rhs, lhs_size);
+ }
+ if (lhs_size < rhs_size) {
+ auto data_comp_res = GenericCompare<int>(lhs, rhs, lhs_size);
+ return data_comp_res == 0 ? -1 : data_comp_res;
+ }
+
+ auto data_comp_res = GenericCompare<int>(lhs, rhs, rhs_size);
+ return data_comp_res == 0 ? +1 : data_comp_res;
+}
+
+int Cord::Compare(absl::string_view rhs) const {
+ return SharedCompareImpl(*this, rhs);
+}
+
+int Cord::CompareImpl(const Cord& rhs) const {
+ return SharedCompareImpl(*this, rhs);
+}
+
+bool Cord::EndsWith(absl::string_view rhs) const {
+ size_t my_size = size();
+ size_t rhs_size = rhs.size();
+
+ if (my_size < rhs_size) return false;
+
+ Cord tmp(*this);
+ tmp.RemovePrefix(my_size - rhs_size);
+ return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+bool Cord::EndsWith(const Cord& rhs) const {
+ size_t my_size = size();
+ size_t rhs_size = rhs.size();
+
+ if (my_size < rhs_size) return false;
+
+ Cord tmp(*this);
+ tmp.RemovePrefix(my_size - rhs_size);
+ return tmp.EqualsImpl(rhs, rhs_size);
+}
+
+// --------------------------------------------------------------------
+// Misc.
+
+Cord::operator std::string() const {
+ std::string s;
+ absl::CopyCordToString(*this, &s);
+ return s;
+}
+
+void CopyCordToString(const Cord& src, std::string* dst) {
+ if (!src.contents_.is_tree()) {
+ src.contents_.CopyTo(dst);
+ } else {
+ absl::strings_internal::STLStringResizeUninitialized(dst, src.size());
+ src.CopyToArraySlowPath(&(*dst)[0]);
+ }
+}
+
+void Cord::CopyToArraySlowPath(char* dst) const {
+ assert(contents_.is_tree());
+ absl::string_view fragment;
+ if (GetFlatAux(contents_.tree(), &fragment)) {
+ memcpy(dst, fragment.data(), fragment.size());
+ return;
+ }
+ for (absl::string_view chunk : Chunks()) {
+ memcpy(dst, chunk.data(), chunk.size());
+ dst += chunk.size();
+ }
+}
+
+Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
+ auto& stack_of_right_children = stack_of_right_children_;
+ if (stack_of_right_children.empty()) {
+ assert(!current_chunk_.empty()); // Called on invalid iterator.
+ // We have reached the end of the Cord.
+ return *this;
+ }
+
+ // Process the next node on the stack.
+ CordRep* node = stack_of_right_children.back();
+ stack_of_right_children.pop_back();
+
+ // Walk down the left branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
+ while (node->tag == CONCAT) {
+ stack_of_right_children.push_back(node->concat()->right);
+ node = node->concat()->left;
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
+ if (node->tag == SUBSTRING) {
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
+ assert(length != 0);
+ const char* data =
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
+ current_chunk_ = absl::string_view(data + offset, length);
+ current_leaf_ = node;
+ return *this;
+}
+
+Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ >= n &&
+ "Attempted to iterate past `end()`");
+ Cord subcord;
+
+ if (n <= InlineRep::kMaxInline) {
+ // Range to read fits in inline data. Flatten it.
+ char* data = subcord.contents_.set_data(n);
+ while (n > current_chunk_.size()) {
+ memcpy(data, current_chunk_.data(), current_chunk_.size());
+ data += current_chunk_.size();
+ n -= current_chunk_.size();
+ ++*this;
+ }
+ memcpy(data, current_chunk_.data(), n);
+ if (n < current_chunk_.size()) {
+ RemoveChunkPrefix(n);
+ } else if (n > 0) {
+ ++*this;
+ }
+ return subcord;
+ }
+
+ if (ring_reader_) {
+ size_t chunk_size = current_chunk_.size();
+ if (n <= chunk_size && n <= kMaxBytesToCopy) {
+ subcord = Cord(current_chunk_.substr(0, n));
+ } else {
+ auto* ring = CordRep::Ref(ring_reader_.ring())->ring();
+ size_t offset = ring_reader_.length() - bytes_remaining_;
+ subcord.contents_.set_tree(CordRepRing::SubRing(ring, offset, n));
+ }
+ if (n < chunk_size) {
+ bytes_remaining_ -= n;
+ current_chunk_.remove_prefix(n);
+ } else {
+ AdvanceBytesRing(n);
+ }
+ return subcord;
+ }
+
+ auto& stack_of_right_children = stack_of_right_children_;
+ if (n < current_chunk_.size()) {
+ // Range to read is a proper subrange of the current chunk.
+ assert(current_leaf_ != nullptr);
+ CordRep* subnode = CordRep::Ref(current_leaf_);
+ const char* data = subnode->tag == EXTERNAL ? subnode->external()->base
+ : subnode->flat()->Data();
+ subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
+ subcord.contents_.set_tree(VerifyTree(subnode));
+ RemoveChunkPrefix(n);
+ return subcord;
+ }
+
+ // Range to read begins with a proper subrange of the current chunk.
+ assert(!current_chunk_.empty());
+ assert(current_leaf_ != nullptr);
+ CordRep* subnode = CordRep::Ref(current_leaf_);
+ if (current_chunk_.size() < subnode->length) {
+ const char* data = subnode->tag == EXTERNAL ? subnode->external()->base
+ : subnode->flat()->Data();
+ subnode = NewSubstring(subnode, current_chunk_.data() - data,
+ current_chunk_.size());
+ }
+ n -= current_chunk_.size();
+ bytes_remaining_ -= current_chunk_.size();
+
+ // Process the next node(s) on the stack, reading whole subtrees depending on
+ // their length and how many bytes we are advancing.
+ CordRep* node = nullptr;
+ while (!stack_of_right_children.empty()) {
+ node = stack_of_right_children.back();
+ stack_of_right_children.pop_back();
+ if (node->length > n) break;
+ // TODO(qrczak): This might unnecessarily recreate existing concat nodes.
+ // Avoiding that would need pretty complicated logic (instead of
+ // current_leaf, keep current_subtree_ which points to the highest node
+ // such that the current leaf can be found on the path of left children
+ // starting from current_subtree_; delay creating subnode while node is
+ // below current_subtree_; find the proper node along the path of left
+ // children starting from current_subtree_ if this loop exits while staying
+ // below current_subtree_; etc.; alternatively, push parents instead of
+ // right children on the stack).
+ subnode = Concat(subnode, CordRep::Ref(node));
+ n -= node->length;
+ bytes_remaining_ -= node->length;
+ node = nullptr;
+ }
+
+ if (node == nullptr) {
+ // We have reached the end of the Cord.
+ assert(bytes_remaining_ == 0);
+ subcord.contents_.set_tree(VerifyTree(subnode));
+ return subcord;
+ }
+
+ // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
+ while (node->tag == CONCAT) {
+ if (node->concat()->left->length > n) {
+ // Push right, descend left.
+ stack_of_right_children.push_back(node->concat()->right);
+ node = node->concat()->left;
+ } else {
+ // Read left, descend right.
+ subnode = Concat(subnode, CordRep::Ref(node->concat()->left));
+ n -= node->concat()->left->length;
+ bytes_remaining_ -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
+ if (node->tag == SUBSTRING) {
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
+ // Range to read ends with a proper (possibly empty) subrange of the current
+ // chunk.
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
+ assert(length > n);
+ if (n > 0) {
+ subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
+ }
+ const char* data =
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
+ current_chunk_ = absl::string_view(data + offset + n, length - n);
+ current_leaf_ = node;
+ bytes_remaining_ -= n;
+ subcord.contents_.set_tree(VerifyTree(subnode));
+ return subcord;
+}
+
+void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
+ assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
+ assert(n >= current_chunk_.size()); // This should only be called when
+ // iterating to a new node.
+
+ n -= current_chunk_.size();
+ bytes_remaining_ -= current_chunk_.size();
+
+ if (stack_of_right_children_.empty()) {
+ // We have reached the end of the Cord.
+ assert(bytes_remaining_ == 0);
+ return;
+ }
+
+ // Process the next node(s) on the stack, skipping whole subtrees depending on
+ // their length and how many bytes we are advancing.
+ CordRep* node = nullptr;
+ auto& stack_of_right_children = stack_of_right_children_;
+ while (!stack_of_right_children.empty()) {
+ node = stack_of_right_children.back();
+ stack_of_right_children.pop_back();
+ if (node->length > n) break;
+ n -= node->length;
+ bytes_remaining_ -= node->length;
+ node = nullptr;
+ }
+
+ if (node == nullptr) {
+ // We have reached the end of the Cord.
+ assert(bytes_remaining_ == 0);
+ return;
+ }
+
+ // Walk down the appropriate branches until we hit a non-CONCAT node. Save the
+ // right children to the stack for subsequent traversal.
+ while (node->tag == CONCAT) {
+ if (node->concat()->left->length > n) {
+ // Push right, descend left.
+ stack_of_right_children.push_back(node->concat()->right);
+ node = node->concat()->left;
+ } else {
+ // Skip left, descend right.
+ n -= node->concat()->left->length;
+ bytes_remaining_ -= node->concat()->left->length;
+ node = node->concat()->right;
+ }
+ }
+
+ // Get the child node if we encounter a SUBSTRING.
+ size_t offset = 0;
+ size_t length = node->length;
+ if (node->tag == SUBSTRING) {
+ offset = node->substring()->start;
+ node = node->substring()->child;
+ }
+
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
+ assert(length > n);
+ const char* data =
+ node->tag == EXTERNAL ? node->external()->base : node->flat()->Data();
+ current_chunk_ = absl::string_view(data + offset + n, length - n);
+ current_leaf_ = node;
+ bytes_remaining_ -= n;
+}
+
+char Cord::operator[](size_t i) const {
+ ABSL_HARDENING_ASSERT(i < size());
+ size_t offset = i;
+ const CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return contents_.data()[i];
+ }
+ while (true) {
+ assert(rep != nullptr);
+ assert(offset < rep->length);
+ if (rep->tag >= FLAT) {
+ // Get the "i"th character directly from the flat array.
+ return rep->flat()->Data()[offset];
+ } else if (rep->tag == RING) {
+ return rep->ring()->GetCharacter(offset);
+ } else if (rep->tag == EXTERNAL) {
+ // Get the "i"th character from the external array.
+ return rep->external()->base[offset];
+ } else if (rep->tag == CONCAT) {
+ // Recursively branch to the side of the concatenation that the "i"th
+ // character is on.
+ size_t left_length = rep->concat()->left->length;
+ if (offset < left_length) {
+ rep = rep->concat()->left;
+ } else {
+ offset -= left_length;
+ rep = rep->concat()->right;
+ }
+ } else {
+ // This must be a substring a node, so bypass it to get to the child.
+ assert(rep->tag == SUBSTRING);
+ offset += rep->substring()->start;
+ rep = rep->substring()->child;
+ }
+ }
+}
+
+absl::string_view Cord::FlattenSlowPath() {
+ size_t total_size = size();
+ CordRep* new_rep;
+ char* new_buffer;
+
+ // Try to put the contents into a new flat rep. If they won't fit in the
+ // biggest possible flat node, use an external rep instead.
+ if (total_size <= kMaxFlatLength) {
+ new_rep = CordRepFlat::New(total_size);
+ new_rep->length = total_size;
+ new_buffer = new_rep->flat()->Data();
+ CopyToArraySlowPath(new_buffer);
+ } else {
+ new_buffer = std::allocator<char>().allocate(total_size);
+ CopyToArraySlowPath(new_buffer);
+ new_rep = absl::cord_internal::NewExternalRep(
+ absl::string_view(new_buffer, total_size), [](absl::string_view s) {
+ std::allocator<char>().deallocate(const_cast<char*>(s.data()),
+ s.size());
+ });
+ }
+ if (CordRep* tree = contents_.tree()) {
+ CordRep::Unref(tree);
+ }
+ contents_.set_tree(new_rep);
+ return absl::string_view(new_buffer, total_size);
+}
+
+/* static */ bool Cord::GetFlatAux(CordRep* rep, absl::string_view* fragment) {
+ assert(rep != nullptr);
+ if (rep->tag >= FLAT) {
+ *fragment = absl::string_view(rep->flat()->Data(), rep->length);
+ return true;
+ } else if (rep->tag == EXTERNAL) {
+ *fragment = absl::string_view(rep->external()->base, rep->length);
+ return true;
+ } else if (rep->tag == SUBSTRING) {
+ CordRep* child = rep->substring()->child;
+ if (child->tag >= FLAT) {
+ *fragment = absl::string_view(
+ child->flat()->Data() + rep->substring()->start, rep->length);
+ return true;
+ } else if (child->tag == EXTERNAL) {
+ *fragment = absl::string_view(
+ child->external()->base + rep->substring()->start, rep->length);
+ return true;
+ }
+ }
+ return false;
+}
+
+/* static */ void Cord::ForEachChunkAux(
+ absl::cord_internal::CordRep* rep,
+ absl::FunctionRef<void(absl::string_view)> callback) {
+ if (rep->tag == RING) {
+ ChunkIterator it(rep), end;
+ while (it != end) {
+ callback(*it);
+ ++it;
+ }
+ return;
+ }
+
+ assert(rep != nullptr);
+ int stack_pos = 0;
+ constexpr int stack_max = 128;
+ // Stack of right branches for tree traversal
+ absl::cord_internal::CordRep* stack[stack_max];
+ absl::cord_internal::CordRep* current_node = rep;
+ while (true) {
+ if (current_node->tag == CONCAT) {
+ if (stack_pos == stack_max) {
+ // There's no more room on our stack array to add another right branch,
+ // and the idea is to avoid allocations, so call this function
+ // recursively to navigate this subtree further. (This is not something
+ // we expect to happen in practice).
+ ForEachChunkAux(current_node, callback);
+
+ // Pop the next right branch and iterate.
+ current_node = stack[--stack_pos];
+ continue;
+ } else {
+ // Save the right branch for later traversal and continue down the left
+ // branch.
+ stack[stack_pos++] = current_node->concat()->right;
+ current_node = current_node->concat()->left;
+ continue;
+ }
+ }
+ // This is a leaf node, so invoke our callback.
+ absl::string_view chunk;
+ bool success = GetFlatAux(current_node, &chunk);
+ assert(success);
+ if (success) {
+ callback(chunk);
+ }
+ if (stack_pos == 0) {
+ // end of traversal
+ return;
+ }
+ current_node = stack[--stack_pos];
+ }
+}
+
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
+ int indent) {
+ const int kIndentStep = 1;
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
+ absl::InlinedVector<int, kInlinedVectorSize> indents;
+ for (;;) {
+ *os << std::setw(3) << rep->refcount.Get();
+ *os << " " << std::setw(7) << rep->length;
+ *os << " [";
+ if (include_data) *os << static_cast<void*>(rep);
+ *os << "]";
+ *os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
+ *os << " " << std::setw(indent) << "";
+ if (rep->tag == CONCAT) {
+ *os << "CONCAT depth=" << Depth(rep) << "\n";
+ indent += kIndentStep;
+ indents.push_back(indent);
+ stack.push_back(rep->concat()->right);
+ rep = rep->concat()->left;
+ } else if (rep->tag == SUBSTRING) {
+ *os << "SUBSTRING @ " << rep->substring()->start << "\n";
+ indent += kIndentStep;
+ rep = rep->substring()->child;
+ } else { // Leaf or ring
+ if (rep->tag == EXTERNAL) {
+ *os << "EXTERNAL [";
+ if (include_data)
+ *os << absl::CEscape(std::string(rep->external()->base, rep->length));
+ *os << "]\n";
+ } else if (rep->tag >= FLAT) {
+ *os << "FLAT cap=" << rep->flat()->Capacity()
+ << " [";
+ if (include_data)
+ *os << absl::CEscape(std::string(rep->flat()->Data(), rep->length));
+ *os << "]\n";
+ } else {
+ assert(rep->tag == RING);
+ auto* ring = rep->ring();
+ *os << "RING, entries = " << ring->entries() << "\n";
+ CordRepRing::index_type head = ring->head();
+ do {
+ DumpNode(ring->entry_child(head), include_data, os,
+ indent + kIndentStep);
+ head = ring->advance(head);;
+ } while (head != ring->tail());
+ }
+ if (stack.empty()) break;
+ rep = stack.back();
+ stack.pop_back();
+ indent = indents.back();
+ indents.pop_back();
+ }
+ }
+ ABSL_INTERNAL_CHECK(indents.empty(), "");
+}
+
+static std::string ReportError(CordRep* root, CordRep* node) {
+ std::ostringstream buf;
+ buf << "Error at node " << node << " in:";
+ DumpNode(root, true, &buf);
+ return buf.str();
+}
+
+static bool VerifyNode(CordRep* root, CordRep* start_node,
+ bool full_validation) {
+ absl::InlinedVector<CordRep*, 2> worklist;
+ worklist.push_back(start_node);
+ do {
+ CordRep* node = worklist.back();
+ worklist.pop_back();
+
+ ABSL_INTERNAL_CHECK(node != nullptr, ReportError(root, node));
+ if (node != root) {
+ ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
+ }
+
+ if (node->tag == CONCAT) {
+ ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK((node->length == node->concat()->left->length +
+ node->concat()->right->length),
+ ReportError(root, node));
+ if (full_validation) {
+ worklist.push_back(node->concat()->right);
+ worklist.push_back(node->concat()->left);
+ }
+ } else if (node->tag >= FLAT) {
+ ABSL_INTERNAL_CHECK(
+ node->length <= node->flat()->Capacity(),
+ ReportError(root, node));
+ } else if (node->tag == EXTERNAL) {
+ ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
+ ReportError(root, node));
+ } else if (node->tag == SUBSTRING) {
+ ABSL_INTERNAL_CHECK(
+ node->substring()->start < node->substring()->child->length,
+ ReportError(root, node));
+ ABSL_INTERNAL_CHECK(node->substring()->start + node->length <=
+ node->substring()->child->length,
+ ReportError(root, node));
+ }
+ } while (!worklist.empty());
+ return true;
+}
+
+// Traverses the tree and computes the total memory allocated.
+/* static */ size_t Cord::MemoryUsageAux(const CordRep* rep) {
+ size_t total_mem_usage = 0;
+
+ // Allow a quick exit for the common case that the root is a leaf.
+ if (RepMemoryUsageLeaf(rep, &total_mem_usage)) {
+ return total_mem_usage;
+ }
+
+ // Iterate over the tree. cur_node is never a leaf node and leaf nodes will
+ // never be appended to tree_stack. This reduces overhead from manipulating
+ // tree_stack.
+ absl::InlinedVector<const CordRep*, kInlinedVectorSize> tree_stack;
+ const CordRep* cur_node = rep;
+ while (true) {
+ const CordRep* next_node = nullptr;
+
+ if (cur_node->tag == CONCAT) {
+ total_mem_usage += sizeof(CordRepConcat);
+ const CordRep* left = cur_node->concat()->left;
+ if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
+ next_node = left;
+ }
+
+ const CordRep* right = cur_node->concat()->right;
+ if (!RepMemoryUsageLeaf(right, &total_mem_usage)) {
+ if (next_node) {
+ tree_stack.push_back(next_node);
+ }
+ next_node = right;
+ }
+ } else if (cur_node->tag == RING) {
+ total_mem_usage += CordRepRing::AllocSize(cur_node->ring()->capacity());
+ const CordRepRing* ring = cur_node->ring();
+ CordRepRing::index_type pos = ring->head(), tail = ring->tail();
+ do {
+ CordRep* node = ring->entry_child(pos);
+ assert(node->tag >= FLAT || node->tag == EXTERNAL);
+ RepMemoryUsageLeaf(node, &total_mem_usage);
+ } while ((pos = ring->advance(pos)) != tail);
+ } else {
+ // Since cur_node is not a leaf or a concat node it must be a substring.
+ assert(cur_node->tag == SUBSTRING);
+ total_mem_usage += sizeof(CordRepSubstring);
+ next_node = cur_node->substring()->child;
+ if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
+ next_node = nullptr;
+ }
+ }
+
+ if (!next_node) {
+ if (tree_stack.empty()) {
+ return total_mem_usage;
+ }
+ next_node = tree_stack.back();
+ tree_stack.pop_back();
+ }
+ cur_node = next_node;
+ }
+}
+
+std::ostream& operator<<(std::ostream& out, const Cord& cord) {
+ for (absl::string_view chunk : cord.Chunks()) {
+ out.write(chunk.data(), chunk.size());
+ }
+ return out;
+}
+
+namespace strings_internal {
+size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
+size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
+size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
+ return cord_internal::TagToLength(tag);
+}
+uint8_t CordTestAccess::LengthToTag(size_t s) {
+ ABSL_INTERNAL_CHECK(s <= kMaxFlatLength, absl::StrCat("Invalid length ", s));
+ return cord_internal::AllocatedSizeToTag(s + cord_internal::kFlatOverhead);
+}
+size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
+size_t CordTestAccess::SizeofCordRepExternal() {
+ return sizeof(CordRepExternal);
+}
+size_t CordTestAccess::SizeofCordRepSubstring() {
+ return sizeof(CordRepSubstring);
+}
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.h
new file mode 100644
index 00000000000..fa9cb913fd4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord.h
@@ -0,0 +1,1394 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// -----------------------------------------------------------------------------
+// File: cord.h
+// -----------------------------------------------------------------------------
+//
+// This file defines the `absl::Cord` data structure and operations on that data
+// structure. A Cord is a string-like sequence of characters optimized for
+// specific use cases. Unlike a `std::string`, which stores an array of
+// contiguous characters, Cord data is stored in a structure consisting of
+// separate, reference-counted "chunks." (Currently, this implementation is a
+// tree structure, though that implementation may change.)
+//
+// Because a Cord consists of these chunks, data can be added to or removed from
+// a Cord during its lifetime. Chunks may also be shared between Cords. Unlike a
+// `std::string`, a Cord can therefore accommodate data that changes over its
+// lifetime, though it's not quite "mutable"; it can change only in the
+// attachment, detachment, or rearrangement of chunks of its constituent data.
+//
+// A Cord provides some benefit over `std::string` under the following (albeit
+// narrow) circumstances:
+//
+// * Cord data is designed to grow and shrink over a Cord's lifetime. Cord
+// provides efficient insertions and deletions at the start and end of the
+// character sequences, avoiding copies in those cases. Static data should
+// generally be stored as strings.
+// * External memory consisting of string-like data can be directly added to
+// a Cord without requiring copies or allocations.
+// * Cord data may be shared and copied cheaply. Cord provides a copy-on-write
+// implementation and cheap sub-Cord operations. Copying a Cord is an O(1)
+// operation.
+//
+// As a consequence to the above, Cord data is generally large. Small data
+// should generally use strings, as construction of a Cord requires some
+// overhead. Small Cords (<= 15 bytes) are represented inline, but most small
+// Cords are expected to grow over their lifetimes.
+//
+// Note that because a Cord is made up of separate chunked data, random access
+// to character data within a Cord is slower than within a `std::string`.
+//
+// Thread Safety
+//
+// Cord has the same thread-safety properties as many other types like
+// std::string, std::vector<>, int, etc -- it is thread-compatible. In
+// particular, if threads do not call non-const methods, then it is safe to call
+// const methods without synchronization. Copying a Cord produces a new instance
+// that can be used concurrently with the original in arbitrary ways.
+
+#ifndef ABSL_STRINGS_CORD_H_
+#define ABSL_STRINGS_CORD_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <cstring>
+#include <iosfwd>
+#include <iterator>
+#include <string>
+#include <type_traits>
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/per_thread_tls.h"
+#include "absl/base/macros.h"
+#include "absl/base/port.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+#include "absl/strings/internal/cord_rep_ring_reader.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/internal/string_constant.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+class Cord;
+class CordTestPeer;
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view, Releaser&&);
+void CopyCordToString(const Cord& src, std::string* dst);
+
+// Cord
+//
+// A Cord is a sequence of characters, designed to be more efficient than a
+// `std::string` in certain circumstances: namely, large string data that needs
+// to change over its lifetime or shared, especially when such data is shared
+// across API boundaries.
+//
+// A Cord stores its character data in a structure that allows efficient prepend
+// and append operations. This makes a Cord useful for large string data sent
+// over in a wire format that may need to be prepended or appended at some point
+// during the data exchange (e.g. HTTP, protocol buffers). For example, a
+// Cord is useful for storing an HTTP request, and prepending an HTTP header to
+// such a request.
+//
+// Cords should not be used for storing general string data, however. They
+// require overhead to construct and are slower than strings for random access.
+//
+// The Cord API provides the following common API operations:
+//
+// * Create or assign Cords out of existing string data, memory, or other Cords
+// * Append and prepend data to an existing Cord
+// * Create new Sub-Cords from existing Cord data
+// * Swap Cord data and compare Cord equality
+// * Write out Cord data by constructing a `std::string`
+//
+// Additionally, the API provides iterator utilities to iterate through Cord
+// data via chunks or character bytes.
+//
+class Cord {
+ private:
+ template <typename T>
+ using EnableIfString =
+ absl::enable_if_t<std::is_same<T, std::string>::value, int>;
+
+ public:
+ // Cord::Cord() Constructors.
+
+ // Creates an empty Cord.
+ constexpr Cord() noexcept;
+
+ // Creates a Cord from an existing Cord. Cord is copyable and efficiently
+ // movable. The moved-from state is valid but unspecified.
+ Cord(const Cord& src);
+ Cord(Cord&& src) noexcept;
+ Cord& operator=(const Cord& x);
+ Cord& operator=(Cord&& x) noexcept;
+
+ // Creates a Cord from a `src` string. This constructor is marked explicit to
+ // prevent implicit Cord constructions from arguments convertible to an
+ // `absl::string_view`.
+ explicit Cord(absl::string_view src);
+ Cord& operator=(absl::string_view src);
+
+ // Creates a Cord from a `std::string&&` rvalue. These constructors are
+ // templated to avoid ambiguities for types that are convertible to both
+ // `absl::string_view` and `std::string`, such as `const char*`.
+ template <typename T, EnableIfString<T> = 0>
+ explicit Cord(T&& src);
+ template <typename T, EnableIfString<T> = 0>
+ Cord& operator=(T&& src);
+
+ // Cord::~Cord()
+ //
+ // Destructs the Cord.
+ ~Cord() {
+ if (contents_.is_tree()) DestroyCordSlow();
+ }
+
+ // MakeCordFromExternal()
+ //
+ // Creates a Cord that takes ownership of external string memory. The
+ // contents of `data` are not copied to the Cord; instead, the external
+ // memory is added to the Cord and reference-counted. This data may not be
+ // changed for the life of the Cord, though it may be prepended or appended
+ // to.
+ //
+ // `MakeCordFromExternal()` takes a callable "releaser" that is invoked when
+ // the reference count for `data` reaches zero. As noted above, this data must
+ // remain live until the releaser is invoked. The callable releaser also must:
+ //
+ // * be move constructible
+ // * support `void operator()(absl::string_view) const` or `void operator()`
+ //
+ // Example:
+ //
+ // Cord MakeCord(BlockPool* pool) {
+ // Block* block = pool->NewBlock();
+ // FillBlock(block);
+ // return absl::MakeCordFromExternal(
+ // block->ToStringView(),
+ // [pool, block](absl::string_view v) {
+ // pool->FreeBlock(block, v);
+ // });
+ // }
+ //
+ // WARNING: Because a Cord can be reference-counted, it's likely a bug if your
+ // releaser doesn't do anything. For example, consider the following:
+ //
+ // void Foo(const char* buffer, int len) {
+ // auto c = absl::MakeCordFromExternal(absl::string_view(buffer, len),
+ // [](absl::string_view) {});
+ //
+ // // BUG: If Bar() copies its cord for any reason, including keeping a
+ // // substring of it, the lifetime of buffer might be extended beyond
+ // // when Foo() returns.
+ // Bar(c);
+ // }
+ template <typename Releaser>
+ friend Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser);
+
+ // Cord::Clear()
+ //
+ // Releases the Cord data. Any nodes that share data with other Cords, if
+ // applicable, will have their reference counts reduced by 1.
+ void Clear();
+
+ // Cord::Append()
+ //
+ // Appends data to the Cord, which may come from another Cord or other string
+ // data.
+ void Append(const Cord& src);
+ void Append(Cord&& src);
+ void Append(absl::string_view src);
+ template <typename T, EnableIfString<T> = 0>
+ void Append(T&& src);
+
+ // Cord::Prepend()
+ //
+ // Prepends data to the Cord, which may come from another Cord or other string
+ // data.
+ void Prepend(const Cord& src);
+ void Prepend(absl::string_view src);
+ template <typename T, EnableIfString<T> = 0>
+ void Prepend(T&& src);
+
+ // Cord::RemovePrefix()
+ //
+ // Removes the first `n` bytes of a Cord.
+ void RemovePrefix(size_t n);
+ void RemoveSuffix(size_t n);
+
+ // Cord::Subcord()
+ //
+ // Returns a new Cord representing the subrange [pos, pos + new_size) of
+ // *this. If pos >= size(), the result is empty(). If
+ // (pos + new_size) >= size(), the result is the subrange [pos, size()).
+ Cord Subcord(size_t pos, size_t new_size) const;
+
+ // Cord::swap()
+ //
+ // Swaps the contents of the Cord with `other`.
+ void swap(Cord& other) noexcept;
+
+ // swap()
+ //
+ // Swaps the contents of two Cords.
+ friend void swap(Cord& x, Cord& y) noexcept {
+ x.swap(y);
+ }
+
+ // Cord::size()
+ //
+ // Returns the size of the Cord.
+ size_t size() const;
+
+ // Cord::empty()
+ //
+ // Determines whether the given Cord is empty, returning `true` is so.
+ bool empty() const;
+
+ // Cord::EstimatedMemoryUsage()
+ //
+ // Returns the *approximate* number of bytes held in full or in part by this
+ // Cord (which may not remain the same between invocations). Note that Cords
+ // that share memory could each be "charged" independently for the same shared
+ // memory.
+ size_t EstimatedMemoryUsage() const;
+
+ // Cord::Compare()
+ //
+ // Compares 'this' Cord with rhs. This function and its relatives treat Cords
+ // as sequences of unsigned bytes. The comparison is a straightforward
+ // lexicographic comparison. `Cord::Compare()` returns values as follows:
+ //
+ // -1 'this' Cord is smaller
+ // 0 two Cords are equal
+ // 1 'this' Cord is larger
+ int Compare(absl::string_view rhs) const;
+ int Compare(const Cord& rhs) const;
+
+ // Cord::StartsWith()
+ //
+ // Determines whether the Cord starts with the passed string data `rhs`.
+ bool StartsWith(const Cord& rhs) const;
+ bool StartsWith(absl::string_view rhs) const;
+
+ // Cord::EndsWith()
+ //
+ // Determines whether the Cord ends with the passed string data `rhs`.
+ bool EndsWith(absl::string_view rhs) const;
+ bool EndsWith(const Cord& rhs) const;
+
+ // Cord::operator std::string()
+ //
+ // Converts a Cord into a `std::string()`. This operator is marked explicit to
+ // prevent unintended Cord usage in functions that take a string.
+ explicit operator std::string() const;
+
+ // CopyCordToString()
+ //
+ // Copies the contents of a `src` Cord into a `*dst` string.
+ //
+ // This function optimizes the case of reusing the destination string since it
+ // can reuse previously allocated capacity. However, this function does not
+ // guarantee that pointers previously returned by `dst->data()` remain valid
+ // even if `*dst` had enough capacity to hold `src`. If `*dst` is a new
+ // object, prefer to simply use the conversion operator to `std::string`.
+ friend void CopyCordToString(const Cord& src, std::string* dst);
+
+ class CharIterator;
+
+ //----------------------------------------------------------------------------
+ // Cord::ChunkIterator
+ //----------------------------------------------------------------------------
+ //
+ // A `Cord::ChunkIterator` allows iteration over the constituent chunks of its
+ // Cord. Such iteration allows you to perform non-const operatons on the data
+ // of a Cord without modifying it.
+ //
+ // Generally, you do not instantiate a `Cord::ChunkIterator` directly;
+ // instead, you create one implicitly through use of the `Cord::Chunks()`
+ // member function.
+ //
+ // The `Cord::ChunkIterator` has the following properties:
+ //
+ // * The iterator is invalidated after any non-const operation on the
+ // Cord object over which it iterates.
+ // * The `string_view` returned by dereferencing a valid, non-`end()`
+ // iterator is guaranteed to be non-empty.
+ // * Two `ChunkIterator` objects can be compared equal if and only if they
+ // remain valid and iterate over the same Cord.
+ // * The iterator in this case is a proxy iterator; the `string_view`
+ // returned by the iterator does not live inside the Cord, and its
+ // lifetime is limited to the lifetime of the iterator itself. To help
+ // prevent lifetime issues, `ChunkIterator::reference` is not a true
+ // reference type and is equivalent to `value_type`.
+ // * The iterator keeps state that can grow for Cords that contain many
+ // nodes and are imbalanced due to sharing. Prefer to pass this type by
+ // const reference instead of by value.
+ class ChunkIterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = absl::string_view;
+ using difference_type = ptrdiff_t;
+ using pointer = const value_type*;
+ using reference = value_type;
+
+ ChunkIterator() = default;
+
+ ChunkIterator& operator++();
+ ChunkIterator operator++(int);
+ bool operator==(const ChunkIterator& other) const;
+ bool operator!=(const ChunkIterator& other) const;
+ reference operator*() const;
+ pointer operator->() const;
+
+ friend class Cord;
+ friend class CharIterator;
+
+ private:
+ using CordRep = absl::cord_internal::CordRep;
+ using CordRepRing = absl::cord_internal::CordRepRing;
+ using CordRepRingReader = absl::cord_internal::CordRepRingReader;
+
+ // Stack of right children of concat nodes that we have to visit.
+ // Keep this at the end of the structure to avoid cache-thrashing.
+ // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+ // the inlined vector size (47 exists for backward compatibility).
+ using Stack = absl::InlinedVector<absl::cord_internal::CordRep*, 47>;
+
+ // Constructs a `begin()` iterator from `tree`. `tree` must not be null.
+ explicit ChunkIterator(cord_internal::CordRep* tree);
+
+ // Constructs a `begin()` iterator from `cord`.
+ explicit ChunkIterator(const Cord* cord);
+
+ // Initializes this instance from a tree. Invoked by constructors.
+ void InitTree(cord_internal::CordRep* tree);
+
+ // Removes `n` bytes from `current_chunk_`. Expects `n` to be smaller than
+ // `current_chunk_.size()`.
+ void RemoveChunkPrefix(size_t n);
+ Cord AdvanceAndReadBytes(size_t n);
+ void AdvanceBytes(size_t n);
+
+ // Stack specific operator++
+ ChunkIterator& AdvanceStack();
+
+ // Ring buffer specific operator++
+ ChunkIterator& AdvanceRing();
+ void AdvanceBytesRing(size_t n);
+
+ // Iterates `n` bytes, where `n` is expected to be greater than or equal to
+ // `current_chunk_.size()`.
+ void AdvanceBytesSlowPath(size_t n);
+
+ // A view into bytes of the current `CordRep`. It may only be a view to a
+ // suffix of bytes if this is being used by `CharIterator`.
+ absl::string_view current_chunk_;
+ // The current leaf, or `nullptr` if the iterator points to short data.
+ // If the current chunk is a substring node, current_leaf_ points to the
+ // underlying flat or external node.
+ absl::cord_internal::CordRep* current_leaf_ = nullptr;
+ // The number of bytes left in the `Cord` over which we are iterating.
+ size_t bytes_remaining_ = 0;
+
+ // Cord reader for ring buffers. Empty if not traversing a ring buffer.
+ CordRepRingReader ring_reader_;
+
+ // See 'Stack' alias definition.
+ Stack stack_of_right_children_;
+ };
+
+ // Cord::ChunkIterator::chunk_begin()
+ //
+ // Returns an iterator to the first chunk of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `ChunkIterator` where range-based for-loops are not useful.
+ //
+ // Example:
+ //
+ // absl::Cord::ChunkIterator FindAsChunk(const absl::Cord& c,
+ // absl::string_view s) {
+ // return std::find(c.chunk_begin(), c.chunk_end(), s);
+ // }
+ ChunkIterator chunk_begin() const;
+
+ // Cord::ChunkItertator::chunk_end()
+ //
+ // Returns an iterator one increment past the last chunk of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chunks()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `ChunkIterator` where range-based for-loops may not be available.
+ ChunkIterator chunk_end() const;
+
+ //----------------------------------------------------------------------------
+ // Cord::ChunkIterator::ChunkRange
+ //----------------------------------------------------------------------------
+ //
+ // `ChunkRange` is a helper class for iterating over the chunks of the `Cord`,
+ // producing an iterator which can be used within a range-based for loop.
+ // Construction of a `ChunkRange` will return an iterator pointing to the
+ // first chunk of the Cord. Generally, do not construct a `ChunkRange`
+ // directly; instead, prefer to use the `Cord::Chunks()` method.
+ //
+ // Implementation note: `ChunkRange` is simply a convenience wrapper over
+ // `Cord::chunk_begin()` and `Cord::chunk_end()`.
+ class ChunkRange {
+ public:
+ explicit ChunkRange(const Cord* cord) : cord_(cord) {}
+
+ ChunkIterator begin() const;
+ ChunkIterator end() const;
+
+ private:
+ const Cord* cord_;
+ };
+
+ // Cord::Chunks()
+ //
+ // Returns a `Cord::ChunkIterator::ChunkRange` for iterating over the chunks
+ // of a `Cord` with a range-based for-loop. For most iteration tasks on a
+ // Cord, use `Cord::Chunks()` to retrieve this iterator.
+ //
+ // Example:
+ //
+ // void ProcessChunks(const Cord& cord) {
+ // for (absl::string_view chunk : cord.Chunks()) { ... }
+ // }
+ //
+ // Note that the ordinary caveats of temporary lifetime extension apply:
+ //
+ // void Process() {
+ // for (absl::string_view chunk : CordFactory().Chunks()) {
+ // // The temporary Cord returned by CordFactory has been destroyed!
+ // }
+ // }
+ ChunkRange Chunks() const;
+
+ //----------------------------------------------------------------------------
+ // Cord::CharIterator
+ //----------------------------------------------------------------------------
+ //
+ // A `Cord::CharIterator` allows iteration over the constituent characters of
+ // a `Cord`.
+ //
+ // Generally, you do not instantiate a `Cord::CharIterator` directly; instead,
+ // you create one implicitly through use of the `Cord::Chars()` member
+ // function.
+ //
+ // A `Cord::CharIterator` has the following properties:
+ //
+ // * The iterator is invalidated after any non-const operation on the
+ // Cord object over which it iterates.
+ // * Two `CharIterator` objects can be compared equal if and only if they
+ // remain valid and iterate over the same Cord.
+ // * The iterator keeps state that can grow for Cords that contain many
+ // nodes and are imbalanced due to sharing. Prefer to pass this type by
+ // const reference instead of by value.
+ // * This type cannot act as a forward iterator because a `Cord` can reuse
+ // sections of memory. This fact violates the requirement for forward
+ // iterators to compare equal if dereferencing them returns the same
+ // object.
+ class CharIterator {
+ public:
+ using iterator_category = std::input_iterator_tag;
+ using value_type = char;
+ using difference_type = ptrdiff_t;
+ using pointer = const char*;
+ using reference = const char&;
+
+ CharIterator() = default;
+
+ CharIterator& operator++();
+ CharIterator operator++(int);
+ bool operator==(const CharIterator& other) const;
+ bool operator!=(const CharIterator& other) const;
+ reference operator*() const;
+ pointer operator->() const;
+
+ friend Cord;
+
+ private:
+ explicit CharIterator(const Cord* cord) : chunk_iterator_(cord) {}
+
+ ChunkIterator chunk_iterator_;
+ };
+
+ // Cord::CharIterator::AdvanceAndRead()
+ //
+ // Advances the `Cord::CharIterator` by `n_bytes` and returns the bytes
+ // advanced as a separate `Cord`. `n_bytes` must be less than or equal to the
+ // number of bytes within the Cord; otherwise, behavior is undefined. It is
+ // valid to pass `char_end()` and `0`.
+ static Cord AdvanceAndRead(CharIterator* it, size_t n_bytes);
+
+ // Cord::CharIterator::Advance()
+ //
+ // Advances the `Cord::CharIterator` by `n_bytes`. `n_bytes` must be less than
+ // or equal to the number of bytes remaining within the Cord; otherwise,
+ // behavior is undefined. It is valid to pass `char_end()` and `0`.
+ static void Advance(CharIterator* it, size_t n_bytes);
+
+ // Cord::CharIterator::ChunkRemaining()
+ //
+ // Returns the longest contiguous view starting at the iterator's position.
+ //
+ // `it` must be dereferenceable.
+ static absl::string_view ChunkRemaining(const CharIterator& it);
+
+ // Cord::CharIterator::char_begin()
+ //
+ // Returns an iterator to the first character of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `CharIterator` where range-based for-loops may not be available.
+ CharIterator char_begin() const;
+
+ // Cord::CharIterator::char_end()
+ //
+ // Returns an iterator to one past the last character of the `Cord`.
+ //
+ // Generally, prefer using `Cord::Chars()` within a range-based for loop for
+ // iterating over the chunks of a Cord. This method may be useful for getting
+ // a `CharIterator` where range-based for-loops are not useful.
+ CharIterator char_end() const;
+
+ // Cord::CharIterator::CharRange
+ //
+ // `CharRange` is a helper class for iterating over the characters of a
+ // producing an iterator which can be used within a range-based for loop.
+ // Construction of a `CharRange` will return an iterator pointing to the first
+ // character of the Cord. Generally, do not construct a `CharRange` directly;
+ // instead, prefer to use the `Cord::Chars()` method show below.
+ //
+ // Implementation note: `CharRange` is simply a convenience wrapper over
+ // `Cord::char_begin()` and `Cord::char_end()`.
+ class CharRange {
+ public:
+ explicit CharRange(const Cord* cord) : cord_(cord) {}
+
+ CharIterator begin() const;
+ CharIterator end() const;
+
+ private:
+ const Cord* cord_;
+ };
+
+ // Cord::CharIterator::Chars()
+ //
+ // Returns a `Cord::CharIterator` for iterating over the characters of a
+ // `Cord` with a range-based for-loop. For most character-based iteration
+ // tasks on a Cord, use `Cord::Chars()` to retrieve this iterator.
+ //
+ // Example:
+ //
+ // void ProcessCord(const Cord& cord) {
+ // for (char c : cord.Chars()) { ... }
+ // }
+ //
+ // Note that the ordinary caveats of temporary lifetime extension apply:
+ //
+ // void Process() {
+ // for (char c : CordFactory().Chars()) {
+ // // The temporary Cord returned by CordFactory has been destroyed!
+ // }
+ // }
+ CharRange Chars() const;
+
+ // Cord::operator[]
+ //
+ // Gets the "i"th character of the Cord and returns it, provided that
+ // 0 <= i < Cord.size().
+ //
+ // NOTE: This routine is reasonably efficient. It is roughly
+ // logarithmic based on the number of chunks that make up the cord. Still,
+ // if you need to iterate over the contents of a cord, you should
+ // use a CharIterator/ChunkIterator rather than call operator[] or Get()
+ // repeatedly in a loop.
+ char operator[](size_t i) const;
+
+ // Cord::TryFlat()
+ //
+ // If this cord's representation is a single flat array, returns a
+ // string_view referencing that array. Otherwise returns nullopt.
+ absl::optional<absl::string_view> TryFlat() const;
+
+ // Cord::Flatten()
+ //
+ // Flattens the cord into a single array and returns a view of the data.
+ //
+ // If the cord was already flat, the contents are not modified.
+ absl::string_view Flatten();
+
+ // Supports absl::Cord as a sink object for absl::Format().
+ friend void AbslFormatFlush(absl::Cord* cord, absl::string_view part) {
+ cord->Append(part);
+ }
+
+ template <typename H>
+ friend H AbslHashValue(H hash_state, const absl::Cord& c) {
+ absl::optional<absl::string_view> maybe_flat = c.TryFlat();
+ if (maybe_flat.has_value()) {
+ return H::combine(std::move(hash_state), *maybe_flat);
+ }
+ return c.HashFragmented(std::move(hash_state));
+ }
+
+ // Create a Cord with the contents of StringConstant<T>::value.
+ // No allocations will be done and no data will be copied.
+ // This is an INTERNAL API and subject to change or removal. This API can only
+ // be used by spelling absl::strings_internal::MakeStringConstant, which is
+ // also an internal API.
+ template <typename T>
+ explicit constexpr Cord(strings_internal::StringConstant<T>);
+
+ private:
+ friend class CordTestPeer;
+ friend bool operator==(const Cord& lhs, const Cord& rhs);
+ friend bool operator==(const Cord& lhs, absl::string_view rhs);
+
+ // Calls the provided function once for each cord chunk, in order. Unlike
+ // Chunks(), this API will not allocate memory.
+ void ForEachChunk(absl::FunctionRef<void(absl::string_view)>) const;
+
+ // Allocates new contiguous storage for the contents of the cord. This is
+ // called by Flatten() when the cord was not already flat.
+ absl::string_view FlattenSlowPath();
+
+ // Actual cord contents are hidden inside the following simple
+ // class so that we can isolate the bulk of cord.cc from changes
+ // to the representation.
+ //
+ // InlineRep holds either a tree pointer, or an array of kMaxInline bytes.
+ class InlineRep {
+ public:
+ static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
+ static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
+
+ constexpr InlineRep() : data_() {}
+ InlineRep(const InlineRep& src);
+ InlineRep(InlineRep&& src);
+ InlineRep& operator=(const InlineRep& src);
+ InlineRep& operator=(InlineRep&& src) noexcept;
+
+ explicit constexpr InlineRep(cord_internal::InlineData data);
+
+ void Swap(InlineRep* rhs);
+ bool empty() const;
+ size_t size() const;
+ const char* data() const; // Returns nullptr if holding pointer
+ void set_data(const char* data, size_t n,
+ bool nullify_tail); // Discards pointer, if any
+ char* set_data(size_t n); // Write data to the result
+ // Returns nullptr if holding bytes
+ absl::cord_internal::CordRep* tree() const;
+ absl::cord_internal::CordRep* as_tree() const;
+ // Discards old pointer, if any
+ void set_tree(absl::cord_internal::CordRep* rep);
+ // Replaces a tree with a new root. This is faster than set_tree, but it
+ // should only be used when it's clear that the old rep was a tree.
+ void replace_tree(absl::cord_internal::CordRep* rep);
+ // Returns non-null iff was holding a pointer
+ absl::cord_internal::CordRep* clear();
+ // Converts to pointer if necessary.
+ absl::cord_internal::CordRep* force_tree(size_t extra_hint);
+ void reduce_size(size_t n); // REQUIRES: holding data
+ void remove_prefix(size_t n); // REQUIRES: holding data
+ void AppendArray(const char* src_data, size_t src_size);
+ absl::string_view FindFlatStartPiece() const;
+ void AppendTree(absl::cord_internal::CordRep* tree);
+ void PrependTree(absl::cord_internal::CordRep* tree);
+ void GetAppendRegion(char** region, size_t* size, size_t max_length);
+ void GetAppendRegion(char** region, size_t* size);
+ bool IsSame(const InlineRep& other) const {
+ return memcmp(&data_, &other.data_, sizeof(data_)) == 0;
+ }
+ int BitwiseCompare(const InlineRep& other) const {
+ uint64_t x, y;
+ // Use memcpy to avoid aliasing issues.
+ memcpy(&x, &data_, sizeof(x));
+ memcpy(&y, &other.data_, sizeof(y));
+ if (x == y) {
+ memcpy(&x, reinterpret_cast<const char*>(&data_) + 8, sizeof(x));
+ memcpy(&y, reinterpret_cast<const char*>(&other.data_) + 8, sizeof(y));
+ if (x == y) return 0;
+ }
+ return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
+ ? -1
+ : 1;
+ }
+ void CopyTo(std::string* dst) const {
+ // memcpy is much faster when operating on a known size. On most supported
+ // platforms, the small string optimization is large enough that resizing
+ // to 15 bytes does not cause a memory allocation.
+ absl::strings_internal::STLStringResizeUninitialized(dst,
+ sizeof(data_) - 1);
+ memcpy(&(*dst)[0], &data_, sizeof(data_) - 1);
+ // erase is faster than resize because the logic for memory allocation is
+ // not needed.
+ dst->erase(inline_size());
+ }
+
+ // Copies the inline contents into `dst`. Assumes the cord is not empty.
+ void CopyToArray(char* dst) const;
+
+ bool is_tree() const { return data_.is_tree(); }
+
+ // Returns true if the Cord is being profiled by cordz.
+ bool is_profiled() const { return data_.is_tree() && data_.is_profiled(); }
+
+ // Returns the profiled CordzInfo, or nullptr if not sampled.
+ absl::cord_internal::CordzInfo* cordz_info() const {
+ return data_.cordz_info();
+ }
+
+ // Sets the profiled CordzInfo. `cordz_info` must not be null.
+ void set_cordz_info(cord_internal::CordzInfo* cordz_info) {
+ assert(cordz_info != nullptr);
+ data_.set_cordz_info(cordz_info);
+ }
+
+ // Resets the current cordz_info to null / empty.
+ void clear_cordz_info() { data_.clear_cordz_info(); }
+
+ private:
+ friend class Cord;
+
+ void AssignSlow(const InlineRep& src);
+ // Unrefs the tree, stops profiling, and zeroes the contents
+ void ClearSlow();
+
+ void ResetToEmpty() { data_ = {}; }
+
+ void set_inline_size(size_t size) { data_.set_inline_size(size); }
+ size_t inline_size() const { return data_.inline_size(); }
+
+ cord_internal::InlineData data_;
+ };
+ InlineRep contents_;
+
+ // Helper for MemoryUsage().
+ static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
+
+ // Helper for GetFlat() and TryFlat().
+ static bool GetFlatAux(absl::cord_internal::CordRep* rep,
+ absl::string_view* fragment);
+
+ // Helper for ForEachChunk().
+ static void ForEachChunkAux(
+ absl::cord_internal::CordRep* rep,
+ absl::FunctionRef<void(absl::string_view)> callback);
+
+ // The destructor for non-empty Cords.
+ void DestroyCordSlow();
+
+ // Out-of-line implementation of slower parts of logic.
+ void CopyToArraySlowPath(char* dst) const;
+ int CompareSlowPath(absl::string_view rhs, size_t compared_size,
+ size_t size_to_compare) const;
+ int CompareSlowPath(const Cord& rhs, size_t compared_size,
+ size_t size_to_compare) const;
+ bool EqualsImpl(absl::string_view rhs, size_t size_to_compare) const;
+ bool EqualsImpl(const Cord& rhs, size_t size_to_compare) const;
+ int CompareImpl(const Cord& rhs) const;
+
+ template <typename ResultType, typename RHS>
+ friend ResultType GenericCompare(const Cord& lhs, const RHS& rhs,
+ size_t size_to_compare);
+ static absl::string_view GetFirstChunk(const Cord& c);
+ static absl::string_view GetFirstChunk(absl::string_view sv);
+
+ // Returns a new reference to contents_.tree(), or steals an existing
+ // reference if called on an rvalue.
+ absl::cord_internal::CordRep* TakeRep() const&;
+ absl::cord_internal::CordRep* TakeRep() &&;
+
+ // Helper for Append().
+ template <typename C>
+ void AppendImpl(C&& src);
+
+ // Helper for AbslHashValue().
+ template <typename H>
+ H HashFragmented(H hash_state) const {
+ typename H::AbslInternalPiecewiseCombiner combiner;
+ ForEachChunk([&combiner, &hash_state](absl::string_view chunk) {
+ hash_state = combiner.add_buffer(std::move(hash_state), chunk.data(),
+ chunk.size());
+ });
+ return H::combine(combiner.finalize(std::move(hash_state)), size());
+ }
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// allow a Cord to be logged
+extern std::ostream& operator<<(std::ostream& out, const Cord& cord);
+
+// ------------------------------------------------------------------
+// Internal details follow. Clients should ignore.
+
+namespace cord_internal {
+
+// Fast implementation of memmove for up to 15 bytes. This implementation is
+// safe for overlapping regions. If nullify_tail is true, the destination is
+// padded with '\0' up to 16 bytes.
+inline void SmallMemmove(char* dst, const char* src, size_t n,
+ bool nullify_tail = false) {
+ if (n >= 8) {
+ assert(n <= 16);
+ uint64_t buf1;
+ uint64_t buf2;
+ memcpy(&buf1, src, 8);
+ memcpy(&buf2, src + n - 8, 8);
+ if (nullify_tail) {
+ memset(dst + 8, 0, 8);
+ }
+ memcpy(dst, &buf1, 8);
+ memcpy(dst + n - 8, &buf2, 8);
+ } else if (n >= 4) {
+ uint32_t buf1;
+ uint32_t buf2;
+ memcpy(&buf1, src, 4);
+ memcpy(&buf2, src + n - 4, 4);
+ if (nullify_tail) {
+ memset(dst + 4, 0, 4);
+ memset(dst + 8, 0, 8);
+ }
+ memcpy(dst, &buf1, 4);
+ memcpy(dst + n - 4, &buf2, 4);
+ } else {
+ if (n != 0) {
+ dst[0] = src[0];
+ dst[n / 2] = src[n / 2];
+ dst[n - 1] = src[n - 1];
+ }
+ if (nullify_tail) {
+ memset(dst + 8, 0, 8);
+ memset(dst + n, 0, 8);
+ }
+ }
+}
+
+// Does non-template-specific `CordRepExternal` initialization.
+// Expects `data` to be non-empty.
+void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
+
+// Creates a new `CordRep` that owns `data` and `releaser` and returns a pointer
+// to it, or `nullptr` if `data` was empty.
+template <typename Releaser>
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+CordRep* NewExternalRep(absl::string_view data, Releaser&& releaser) {
+ using ReleaserType = absl::decay_t<Releaser>;
+ if (data.empty()) {
+ // Never create empty external nodes.
+ InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
+ data);
+ return nullptr;
+ }
+
+ CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
+ std::forward<Releaser>(releaser), 0);
+ InitializeCordRepExternal(data, rep);
+ return rep;
+}
+
+// Overload for function reference types that dispatches using a function
+// pointer because there are no `alignof()` or `sizeof()` a function reference.
+// NOLINTNEXTLINE - suppress clang-tidy raw pointer return.
+inline CordRep* NewExternalRep(absl::string_view data,
+ void (&releaser)(absl::string_view)) {
+ return NewExternalRep(data, &releaser);
+}
+
+} // namespace cord_internal
+
+template <typename Releaser>
+Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
+ Cord cord;
+ cord.contents_.set_tree(::absl::cord_internal::NewExternalRep(
+ data, std::forward<Releaser>(releaser)));
+ return cord;
+}
+
+constexpr Cord::InlineRep::InlineRep(cord_internal::InlineData data)
+ : data_(data) {}
+
+inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src)
+ : data_(src.data_) {
+ if (is_tree()) {
+ data_.clear_cordz_info();
+ absl::cord_internal::CordRep::Ref(as_tree());
+ }
+}
+
+inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) {
+ data_ = src.data_;
+ src.ResetToEmpty();
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
+ if (this == &src) {
+ return *this;
+ }
+ if (!is_tree() && !src.is_tree()) {
+ data_ = src.data_;
+ return *this;
+ }
+ AssignSlow(src);
+ return *this;
+}
+
+inline Cord::InlineRep& Cord::InlineRep::operator=(
+ Cord::InlineRep&& src) noexcept {
+ if (is_tree()) {
+ ClearSlow();
+ }
+ data_ = src.data_;
+ src.ResetToEmpty();
+ return *this;
+}
+
+inline void Cord::InlineRep::Swap(Cord::InlineRep* rhs) {
+ if (rhs == this) {
+ return;
+ }
+ std::swap(data_, rhs->data_);
+}
+
+inline const char* Cord::InlineRep::data() const {
+ return is_tree() ? nullptr : data_.as_chars();
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
+ assert(data_.is_tree());
+ return data_.as_tree();
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
+ if (is_tree()) {
+ return as_tree();
+ } else {
+ return nullptr;
+ }
+}
+
+inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
+
+inline size_t Cord::InlineRep::size() const {
+ return is_tree() ? as_tree()->length : inline_size();
+}
+
+inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) {
+ if (rep == nullptr) {
+ ResetToEmpty();
+ } else {
+ if (data_.is_tree()) {
+ // `data_` already holds a 'tree' value and an optional cordz_info value.
+ // Replace the tree value only, leaving the cordz_info value unchanged.
+ data_.set_tree(rep);
+ } else {
+ // `data_` contains inlined data: initialize data_ to tree value `rep`.
+ data_.make_tree(rep);
+ }
+ }
+}
+
+inline void Cord::InlineRep::replace_tree(absl::cord_internal::CordRep* rep) {
+ ABSL_ASSERT(is_tree());
+ if (ABSL_PREDICT_FALSE(rep == nullptr)) {
+ set_tree(rep);
+ return;
+ }
+ data_.set_tree(rep);
+}
+
+inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
+ absl::cord_internal::CordRep* result = tree();
+ ResetToEmpty();
+ return result;
+}
+
+inline void Cord::InlineRep::CopyToArray(char* dst) const {
+ assert(!is_tree());
+ size_t n = inline_size();
+ assert(n != 0);
+ cord_internal::SmallMemmove(dst, data_.as_chars(), n);
+}
+
+constexpr inline Cord::Cord() noexcept {}
+
+template <typename T>
+constexpr Cord::Cord(strings_internal::StringConstant<T>)
+ : contents_(strings_internal::StringConstant<T>::value.size() <=
+ cord_internal::kMaxInline
+ ? cord_internal::InlineData(
+ strings_internal::StringConstant<T>::value)
+ : cord_internal::InlineData(
+ &cord_internal::ConstInitExternalStorage<
+ strings_internal::StringConstant<T>>::value)) {}
+
+inline Cord& Cord::operator=(const Cord& x) {
+ contents_ = x.contents_;
+ return *this;
+}
+
+inline Cord::Cord(const Cord& src) : contents_(src.contents_) {}
+
+inline Cord::Cord(Cord&& src) noexcept : contents_(std::move(src.contents_)) {}
+
+inline void Cord::swap(Cord& other) noexcept {
+ contents_.Swap(&other.contents_);
+}
+
+inline Cord& Cord::operator=(Cord&& x) noexcept {
+ contents_ = std::move(x.contents_);
+ return *this;
+}
+
+extern template Cord::Cord(std::string&& src);
+extern template Cord& Cord::operator=(std::string&& src);
+
+inline size_t Cord::size() const {
+ // Length is 1st field in str.rep_
+ return contents_.size();
+}
+
+inline bool Cord::empty() const { return contents_.empty(); }
+
+inline size_t Cord::EstimatedMemoryUsage() const {
+ size_t result = sizeof(Cord);
+ if (const absl::cord_internal::CordRep* rep = contents_.tree()) {
+ result += MemoryUsageAux(rep);
+ }
+ return result;
+}
+
+inline absl::optional<absl::string_view> Cord::TryFlat() const {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return absl::string_view(contents_.data(), contents_.size());
+ }
+ absl::string_view fragment;
+ if (GetFlatAux(rep, &fragment)) {
+ return fragment;
+ }
+ return absl::nullopt;
+}
+
+inline absl::string_view Cord::Flatten() {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ return absl::string_view(contents_.data(), contents_.size());
+ } else {
+ absl::string_view already_flat_contents;
+ if (GetFlatAux(rep, &already_flat_contents)) {
+ return already_flat_contents;
+ }
+ }
+ return FlattenSlowPath();
+}
+
+inline void Cord::Append(absl::string_view src) {
+ contents_.AppendArray(src.data(), src.size());
+}
+
+extern template void Cord::Append(std::string&& src);
+extern template void Cord::Prepend(std::string&& src);
+
+inline int Cord::Compare(const Cord& rhs) const {
+ if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
+ return contents_.BitwiseCompare(rhs.contents_);
+ }
+
+ return CompareImpl(rhs);
+}
+
+// Does 'this' cord start/end with rhs
+inline bool Cord::StartsWith(const Cord& rhs) const {
+ if (contents_.IsSame(rhs.contents_)) return true;
+ size_t rhs_size = rhs.size();
+ if (size() < rhs_size) return false;
+ return EqualsImpl(rhs, rhs_size);
+}
+
+inline bool Cord::StartsWith(absl::string_view rhs) const {
+ size_t rhs_size = rhs.size();
+ if (size() < rhs_size) return false;
+ return EqualsImpl(rhs, rhs_size);
+}
+
+inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
+ if (tree->tag == cord_internal::RING) {
+ current_chunk_ = ring_reader_.Reset(tree->ring());
+ return;
+ }
+
+ stack_of_right_children_.push_back(tree);
+ operator++();
+}
+
+inline Cord::ChunkIterator::ChunkIterator(cord_internal::CordRep* tree)
+ : bytes_remaining_(tree->length) {
+ InitTree(tree);
+}
+
+inline Cord::ChunkIterator::ChunkIterator(const Cord* cord)
+ : bytes_remaining_(cord->size()) {
+ if (cord->contents_.is_tree()) {
+ InitTree(cord->contents_.as_tree());
+ } else {
+ current_chunk_ =
+ absl::string_view(cord->contents_.data(), bytes_remaining_);
+ }
+}
+
+inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceRing() {
+ current_chunk_ = ring_reader_.Next();
+ return *this;
+}
+
+inline void Cord::ChunkIterator::AdvanceBytesRing(size_t n) {
+ assert(n >= current_chunk_.size());
+ bytes_remaining_ -= n;
+ if (bytes_remaining_) {
+ if (n == current_chunk_.size()) {
+ current_chunk_ = ring_reader_.Next();
+ } else {
+ size_t offset = ring_reader_.length() - bytes_remaining_;
+ current_chunk_ = ring_reader_.Seek(offset);
+ }
+ } else {
+ current_chunk_ = {};
+ }
+}
+
+inline Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ > 0 &&
+ "Attempted to iterate past `end()`");
+ assert(bytes_remaining_ >= current_chunk_.size());
+ bytes_remaining_ -= current_chunk_.size();
+ if (bytes_remaining_ > 0) {
+ return ring_reader_ ? AdvanceRing() : AdvanceStack();
+ } else {
+ current_chunk_ = {};
+ }
+ return *this;
+}
+
+inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
+ ChunkIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+inline bool Cord::ChunkIterator::operator==(const ChunkIterator& other) const {
+ return bytes_remaining_ == other.bytes_remaining_;
+}
+
+inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
+ return !(*this == other);
+}
+
+inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ return current_chunk_;
+}
+
+inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
+ ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ return &current_chunk_;
+}
+
+inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t n) {
+ assert(n < current_chunk_.size());
+ current_chunk_.remove_prefix(n);
+ bytes_remaining_ -= n;
+}
+
+inline void Cord::ChunkIterator::AdvanceBytes(size_t n) {
+ assert(bytes_remaining_ >= n);
+ if (ABSL_PREDICT_TRUE(n < current_chunk_.size())) {
+ RemoveChunkPrefix(n);
+ } else if (n != 0) {
+ ring_reader_ ? AdvanceBytesRing(n) : AdvanceBytesSlowPath(n);
+ }
+}
+
+inline Cord::ChunkIterator Cord::chunk_begin() const {
+ return ChunkIterator(this);
+}
+
+inline Cord::ChunkIterator Cord::chunk_end() const { return ChunkIterator(); }
+
+inline Cord::ChunkIterator Cord::ChunkRange::begin() const {
+ return cord_->chunk_begin();
+}
+
+inline Cord::ChunkIterator Cord::ChunkRange::end() const {
+ return cord_->chunk_end();
+}
+
+inline Cord::ChunkRange Cord::Chunks() const { return ChunkRange(this); }
+
+inline Cord::CharIterator& Cord::CharIterator::operator++() {
+ if (ABSL_PREDICT_TRUE(chunk_iterator_->size() > 1)) {
+ chunk_iterator_.RemoveChunkPrefix(1);
+ } else {
+ ++chunk_iterator_;
+ }
+ return *this;
+}
+
+inline Cord::CharIterator Cord::CharIterator::operator++(int) {
+ CharIterator tmp(*this);
+ operator++();
+ return tmp;
+}
+
+inline bool Cord::CharIterator::operator==(const CharIterator& other) const {
+ return chunk_iterator_ == other.chunk_iterator_;
+}
+
+inline bool Cord::CharIterator::operator!=(const CharIterator& other) const {
+ return !(*this == other);
+}
+
+inline Cord::CharIterator::reference Cord::CharIterator::operator*() const {
+ return *chunk_iterator_->data();
+}
+
+inline Cord::CharIterator::pointer Cord::CharIterator::operator->() const {
+ return chunk_iterator_->data();
+}
+
+inline Cord Cord::AdvanceAndRead(CharIterator* it, size_t n_bytes) {
+ assert(it != nullptr);
+ return it->chunk_iterator_.AdvanceAndReadBytes(n_bytes);
+}
+
+inline void Cord::Advance(CharIterator* it, size_t n_bytes) {
+ assert(it != nullptr);
+ it->chunk_iterator_.AdvanceBytes(n_bytes);
+}
+
+inline absl::string_view Cord::ChunkRemaining(const CharIterator& it) {
+ return *it.chunk_iterator_;
+}
+
+inline Cord::CharIterator Cord::char_begin() const {
+ return CharIterator(this);
+}
+
+inline Cord::CharIterator Cord::char_end() const { return CharIterator(); }
+
+inline Cord::CharIterator Cord::CharRange::begin() const {
+ return cord_->char_begin();
+}
+
+inline Cord::CharIterator Cord::CharRange::end() const {
+ return cord_->char_end();
+}
+
+inline Cord::CharRange Cord::Chars() const { return CharRange(this); }
+
+inline void Cord::ForEachChunk(
+ absl::FunctionRef<void(absl::string_view)> callback) const {
+ absl::cord_internal::CordRep* rep = contents_.tree();
+ if (rep == nullptr) {
+ callback(absl::string_view(contents_.data(), contents_.size()));
+ } else {
+ return ForEachChunkAux(rep, callback);
+ }
+}
+
+// Nonmember Cord-to-Cord relational operarators.
+inline bool operator==(const Cord& lhs, const Cord& rhs) {
+ if (lhs.contents_.IsSame(rhs.contents_)) return true;
+ size_t rhs_size = rhs.size();
+ if (lhs.size() != rhs_size) return false;
+ return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator!=(const Cord& x, const Cord& y) { return !(x == y); }
+inline bool operator<(const Cord& x, const Cord& y) {
+ return x.Compare(y) < 0;
+}
+inline bool operator>(const Cord& x, const Cord& y) {
+ return x.Compare(y) > 0;
+}
+inline bool operator<=(const Cord& x, const Cord& y) {
+ return x.Compare(y) <= 0;
+}
+inline bool operator>=(const Cord& x, const Cord& y) {
+ return x.Compare(y) >= 0;
+}
+
+// Nonmember Cord-to-absl::string_view relational operators.
+//
+// Due to implicit conversions, these also enable comparisons of Cord with
+// with std::string, ::string, and const char*.
+inline bool operator==(const Cord& lhs, absl::string_view rhs) {
+ size_t lhs_size = lhs.size();
+ size_t rhs_size = rhs.size();
+ if (lhs_size != rhs_size) return false;
+ return lhs.EqualsImpl(rhs, rhs_size);
+}
+
+inline bool operator==(absl::string_view x, const Cord& y) { return y == x; }
+inline bool operator!=(const Cord& x, absl::string_view y) { return !(x == y); }
+inline bool operator!=(absl::string_view x, const Cord& y) { return !(x == y); }
+inline bool operator<(const Cord& x, absl::string_view y) {
+ return x.Compare(y) < 0;
+}
+inline bool operator<(absl::string_view x, const Cord& y) {
+ return y.Compare(x) > 0;
+}
+inline bool operator>(const Cord& x, absl::string_view y) { return y < x; }
+inline bool operator>(absl::string_view x, const Cord& y) { return y < x; }
+inline bool operator<=(const Cord& x, absl::string_view y) { return !(y < x); }
+inline bool operator<=(absl::string_view x, const Cord& y) { return !(y < x); }
+inline bool operator>=(const Cord& x, absl::string_view y) { return !(x < y); }
+inline bool operator>=(absl::string_view x, const Cord& y) { return !(x < y); }
+
+// Some internals exposed to test code.
+namespace strings_internal {
+class CordTestAccess {
+ public:
+ static size_t FlatOverhead();
+ static size_t MaxFlatLength();
+ static size_t SizeofCordRepConcat();
+ static size_t SizeofCordRepExternal();
+ static size_t SizeofCordRepSubstring();
+ static size_t FlatTagToLength(uint8_t tag);
+ static uint8_t LengthToTag(size_t s);
+};
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_CORD_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_reader_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_reader_test.cc
new file mode 100644
index 00000000000..585616f3c00
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_reader_test.cc
@@ -0,0 +1,173 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstdlib>
+#include <ctime>
+#include <memory>
+#include <random>
+#include <sstream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/debugging/leak_check.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+#include "absl/strings/internal/cord_rep_ring_reader.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+namespace {
+
+using testing::Eq;
+
+// Creates a flat for testing
+CordRep* MakeFlat(absl::string_view s) {
+ CordRepFlat* flat = CordRepFlat::New(s.length());
+ memcpy(flat->Data(), s.data(), s.length());
+ flat->length = s.length();
+ return flat;
+}
+
+CordRepRing* FromFlats(Span<absl::string_view const> flats) {
+ CordRepRing* ring = CordRepRing::Create(MakeFlat(flats[0]), flats.size() - 1);
+ for (int i = 1; i < flats.size(); ++i) {
+ ring = CordRepRing::Append(ring, MakeFlat(flats[i]));
+ }
+ return ring;
+}
+
+std::array<absl::string_view, 12> TestFlats() {
+ return {"abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+}
+
+TEST(CordRingReaderTest, DefaultInstance) {
+ CordRepRingReader reader;
+ EXPECT_FALSE(static_cast<bool>(reader));
+ EXPECT_THAT(reader.ring(), Eq(nullptr));
+#ifndef NDEBUG
+ EXPECT_DEATH_IF_SUPPORTED(reader.length(), ".*");
+ EXPECT_DEATH_IF_SUPPORTED(reader.consumed(), ".*");
+ EXPECT_DEATH_IF_SUPPORTED(reader.remaining(), ".*");
+ EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
+ EXPECT_DEATH_IF_SUPPORTED(reader.Seek(0), ".*");
+#endif
+}
+
+TEST(CordRingReaderTest, Reset) {
+ CordRepRingReader reader;
+ auto flats = TestFlats();
+ CordRepRing* ring = FromFlats(flats);
+
+ absl::string_view first = reader.Reset(ring);
+ EXPECT_THAT(first, Eq(flats[0]));
+ EXPECT_TRUE(static_cast<bool>(reader));
+ EXPECT_THAT(reader.ring(), Eq(ring));
+ EXPECT_THAT(reader.index(), Eq(ring->head()));
+ EXPECT_THAT(reader.length(), Eq(ring->length));
+ EXPECT_THAT(reader.consumed(), Eq(flats[0].length()));
+ EXPECT_THAT(reader.remaining(), Eq(ring->length - reader.consumed()));
+
+ reader.Reset();
+ EXPECT_FALSE(static_cast<bool>(reader));
+ EXPECT_THAT(reader.ring(), Eq(nullptr));
+
+ CordRep::Unref(ring);
+}
+
+TEST(CordRingReaderTest, Next) {
+ CordRepRingReader reader;
+ auto flats = TestFlats();
+ CordRepRing* ring = FromFlats(flats);
+ CordRepRing::index_type head = ring->head();
+
+ reader.Reset(ring);
+ size_t consumed = reader.consumed();
+ size_t remaining = reader.remaining();
+ for (int i = 1; i < flats.size(); ++i) {
+ consumed += flats[i].length();
+ remaining -= flats[i].length();
+ absl::string_view next = reader.Next();
+ ASSERT_THAT(next, Eq(flats[i]));
+ ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
+ ASSERT_THAT(reader.consumed(), Eq(consumed));
+ ASSERT_THAT(reader.remaining(), Eq(remaining));
+ }
+
+#ifndef NDEBUG
+ EXPECT_DEATH_IF_SUPPORTED(reader.Next(), ".*");
+#endif
+
+ CordRep::Unref(ring);
+}
+
+TEST(CordRingReaderTest, SeekForward) {
+ CordRepRingReader reader;
+ auto flats = TestFlats();
+ CordRepRing* ring = FromFlats(flats);
+ CordRepRing::index_type head = ring->head();
+
+ reader.Reset(ring);
+ size_t consumed = 0;
+ size_t remaining = ring->length;;
+ for (int i = 0; i < flats.size(); ++i) {
+ size_t offset = consumed;
+ consumed += flats[i].length();
+ remaining -= flats[i].length();
+ for (int off = 0; off < flats[i].length(); ++off) {
+ absl::string_view chunk = reader.Seek(offset + off);
+ ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
+ ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
+ ASSERT_THAT(reader.consumed(), Eq(consumed));
+ ASSERT_THAT(reader.remaining(), Eq(remaining));
+ }
+ }
+
+ CordRep::Unref(ring);
+}
+
+TEST(CordRingReaderTest, SeekBackward) {
+ CordRepRingReader reader;
+ auto flats = TestFlats();
+ CordRepRing* ring = FromFlats(flats);
+ CordRepRing::index_type head = ring->head();
+
+ reader.Reset(ring);
+ size_t consumed = ring->length;
+ size_t remaining = 0;
+ for (int i = flats.size() - 1; i >= 0; --i) {
+ size_t offset = consumed - flats[i].length();
+ for (int off = 0; off < flats[i].length(); ++off) {
+ absl::string_view chunk = reader.Seek(offset + off);
+ ASSERT_THAT(chunk, Eq(flats[i].substr(off)));
+ ASSERT_THAT(reader.index(), Eq(ring->advance(head, i)));
+ ASSERT_THAT(reader.consumed(), Eq(consumed));
+ ASSERT_THAT(reader.remaining(), Eq(remaining));
+ }
+ consumed -= flats[i].length();
+ remaining += flats[i].length();
+ }
+#ifndef NDEBUG
+ EXPECT_DEATH_IF_SUPPORTED(reader.Seek(ring->length), ".*");
+#endif
+ CordRep::Unref(ring);
+}
+
+} // namespace
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_test.cc
new file mode 100644
index 00000000000..7d75e106e7a
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_ring_test.cc
@@ -0,0 +1,1572 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <cstdlib>
+#include <ctime>
+#include <memory>
+#include <random>
+#include <sstream>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/debugging/leak_check.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+extern thread_local bool cord_ring;
+
+// TOOD(b/177688959): weird things happened with the original test
+#define ASAN_BUG_177688959_FIXED false
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+using RandomEngine = std::mt19937_64;
+
+using ::absl::cord_internal::CordRep;
+using ::absl::cord_internal::CordRepConcat;
+using ::absl::cord_internal::CordRepExternal;
+using ::absl::cord_internal::CordRepFlat;
+using ::absl::cord_internal::CordRepRing;
+using ::absl::cord_internal::CordRepSubstring;
+
+using ::absl::cord_internal::CONCAT;
+using ::absl::cord_internal::EXTERNAL;
+using ::absl::cord_internal::SUBSTRING;
+
+using testing::ElementsAre;
+using testing::ElementsAreArray;
+using testing::Eq;
+using testing::Ge;
+using testing::Le;
+using testing::Lt;
+using testing::Ne;
+using testing::SizeIs;
+
+using index_type = CordRepRing::index_type;
+
+enum InputShareMode { kPrivate, kShared, kSharedIndirect };
+
+// TestParam class used by all test fixtures.
+// Not all fixtures use all possible input combinations
+struct TestParam {
+ TestParam() = default;
+ explicit TestParam(InputShareMode input_share_mode)
+ : input_share_mode(input_share_mode) {}
+
+ // Run the test with the 'rep under test' to be privately owned.
+ // Otherwise, the rep has a shared ref count of 2 or higher.
+ bool refcount_is_one = true;
+
+ // Run the test with the 'rep under test' being allocated with enough capacity
+ // to accommodate any modifications made to it. Otherwise, the rep has zero
+ // extra (reserve) capacity.
+ bool with_capacity = true;
+
+ // For test providing possibly shared input such as Append(.., CordpRep*),
+ // this field defines if that input is adopted with a refcount of one
+ // (privately owned / donated), or shared. For composite inputs such as
+ // 'substring of flat', we also have the 'shared indirect' value which means
+ // the top level node is not shared, but the contained child node is shared.
+ InputShareMode input_share_mode = kPrivate;
+
+ std::string ToString() const {
+ return absl::StrCat(refcount_is_one ? "Private" : "Shared",
+ with_capacity ? "" : "_NoCapacity",
+ (input_share_mode == kPrivate) ? ""
+ : (input_share_mode == kShared)
+ ? "_SharedInput"
+ : "_IndirectSharedInput");
+ }
+};
+using TestParams = std::vector<TestParam>;
+
+// Matcher validating when mutable copies are required / performed.
+MATCHER_P2(EqIfPrivate, param, rep,
+ absl::StrCat("Equal 0x", absl::Hex(rep), " if private")) {
+ return param.refcount_is_one ? arg == rep : arg != rep;
+}
+
+// Matcher validating when mutable copies are required / performed.
+MATCHER_P2(EqIfPrivateAndCapacity, param, rep,
+ absl::StrCat("Equal 0x", absl::Hex(rep),
+ " if private and capacity")) {
+ return (param.refcount_is_one && param.with_capacity) ? arg == rep
+ : arg != rep;
+}
+
+MATCHER_P2(EqIfInputPrivate, param, rep, "Equal if input is private") {
+ return param.input_share_mode == kPrivate ? arg == rep : arg != rep;
+}
+
+// Matcher validating the core in-variants of the CordRepRing instance.
+MATCHER(IsValidRingBuffer, "RingBuffer is valid") {
+ std::stringstream ss;
+ if (!arg->IsValid(ss)) {
+ *result_listener << "\nERROR: " << ss.str() << "\nRING = " << *arg;
+ return false;
+ }
+ return true;
+}
+
+// Returns the flats contained in the provided CordRepRing
+std::vector<string_view> ToFlats(const CordRepRing* r) {
+ std::vector<string_view> flats;
+ flats.reserve(r->entries());
+ index_type pos = r->head();
+ do {
+ flats.push_back(r->entry_data(pos));
+ } while ((pos = r->advance(pos)) != r->tail());
+ return flats;
+}
+
+class not_a_string_view {
+ public:
+ explicit not_a_string_view(absl::string_view s)
+ : data_(s.data()), size_(s.size()) {}
+ explicit not_a_string_view(const void* data, size_t size)
+ : data_(data), size_(size) {}
+
+ not_a_string_view remove_prefix(size_t n) const {
+ return not_a_string_view(static_cast<const char*>(data_) + n, size_ - n);
+ }
+
+ not_a_string_view remove_suffix(size_t n) const {
+ return not_a_string_view(data_, size_ - n);
+ }
+
+ const void* data() const { return data_; }
+ size_t size() const { return size_; }
+
+ private:
+ const void* data_;
+ size_t size_;
+};
+
+bool operator==(not_a_string_view lhs, not_a_string_view rhs) {
+ return lhs.data() == rhs.data() && lhs.size() == rhs.size();
+}
+
+std::ostream& operator<<(std::ostream& s, not_a_string_view rhs) {
+ return s << "{ data: " << rhs.data() << " size: " << rhs.size() << "}";
+}
+
+std::vector<not_a_string_view> ToRawFlats(const CordRepRing* r) {
+ std::vector<not_a_string_view> flats;
+ flats.reserve(r->entries());
+ index_type pos = r->head();
+ do {
+ flats.emplace_back(r->entry_data(pos));
+ } while ((pos = r->advance(pos)) != r->tail());
+ return flats;
+}
+
+// Returns the value contained in the provided CordRepRing
+std::string ToString(const CordRepRing* r) {
+ std::string value;
+ value.reserve(r->length);
+ index_type pos = r->head();
+ do {
+ absl::string_view sv = r->entry_data(pos);
+ value.append(sv.data(), sv.size());
+ } while ((pos = r->advance(pos)) != r->tail());
+ return value;
+}
+
+// Creates a flat for testing
+CordRep* MakeFlat(absl::string_view s, size_t extra = 0) {
+ CordRepFlat* flat = CordRepFlat::New(s.length() + extra);
+ memcpy(flat->Data(), s.data(), s.length());
+ flat->length = s.length();
+ return flat;
+}
+
+// Creates an external node for testing
+CordRepExternal* MakeExternal(absl::string_view s) {
+ struct Rep : public CordRepExternal {
+ std::string s;
+ explicit Rep(absl::string_view s) : s(s) {
+ this->tag = EXTERNAL;
+ this->base = s.data();
+ this->length = s.length();
+ this->releaser_invoker = [](CordRepExternal* self) {
+ delete static_cast<Rep*>(self);
+ };
+ }
+ };
+ return new Rep(s);
+}
+
+CordRepExternal* MakeFakeExternal(size_t length) {
+ struct Rep : public CordRepExternal {
+ std::string s;
+ explicit Rep(size_t len) {
+ this->tag = EXTERNAL;
+ this->base = this->storage;
+ this->length = len;
+ this->releaser_invoker = [](CordRepExternal* self) {
+ delete static_cast<Rep*>(self);
+ };
+ }
+ };
+ return new Rep(length);
+}
+
+// Creates a flat or an external node for testing depending on the size.
+CordRep* MakeLeaf(absl::string_view s, size_t extra = 0) {
+ if (s.size() <= absl::cord_internal::kMaxFlatLength) {
+ return MakeFlat(s, extra);
+ } else {
+ return MakeExternal(s);
+ }
+}
+
+// Creates a substring node
+CordRepSubstring* MakeSubstring(size_t start, size_t len, CordRep* rep) {
+ auto* sub = new CordRepSubstring;
+ sub->tag = SUBSTRING;
+ sub->start = start;
+ sub->length = (len <= 0) ? rep->length - start + len : len;
+ sub->child = rep;
+ return sub;
+}
+
+// Creates a substring node removing the specified prefix
+CordRepSubstring* RemovePrefix(size_t start, CordRep* rep) {
+ return MakeSubstring(start, rep->length - start, rep);
+}
+
+// Creates a substring node removing the specified suffix
+CordRepSubstring* RemoveSuffix(size_t length, CordRep* rep) {
+ return MakeSubstring(0, rep->length - length, rep);
+}
+
+CordRepConcat* MakeConcat(CordRep* left, CordRep* right, int depth = 0) {
+ auto* concat = new CordRepConcat;
+ concat->tag = CONCAT;
+ concat->length = left->length + right->length;
+ concat->left = left;
+ concat->right = right;
+ concat->set_depth(depth);
+ return concat;
+}
+
+enum Composition { kMix, kAppend, kPrepend };
+
+Composition RandomComposition() {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ return (rng() & 1) ? kMix : ((rng() & 1) ? kAppend : kPrepend);
+}
+
+absl::string_view ToString(Composition composition) {
+ switch (composition) {
+ case kAppend:
+ return "Append";
+ case kPrepend:
+ return "Prepend";
+ case kMix:
+ return "Mix";
+ }
+ assert(false);
+ return "???";
+}
+
+constexpr const char* kFox = "The quick brown fox jumps over the lazy dog";
+constexpr const char* kFoxFlats[] = {"The ", "quick ", "brown ",
+ "fox ", "jumps ", "over ",
+ "the ", "lazy ", "dog"};
+constexpr const char* kAlphabet = "abcdefghijklmnopqrstuvwxyz";
+
+CordRepRing* FromFlats(Span<const char* const> flats,
+ Composition composition = kAppend) {
+ if (flats.empty()) return nullptr;
+ CordRepRing* ring = nullptr;
+ switch (composition) {
+ case kAppend:
+ ring = CordRepRing::Create(MakeLeaf(flats.front()), flats.size() - 1);
+ for (int i = 1; i < flats.size(); ++i) {
+ ring = CordRepRing::Append(ring, MakeLeaf(flats[i]));
+ }
+ break;
+ case kPrepend:
+ ring = CordRepRing::Create(MakeLeaf(flats.back()), flats.size() - 1);
+ for (int i = static_cast<int>(flats.size() - 2); i >= 0; --i) {
+ ring = CordRepRing::Prepend(ring, MakeLeaf(flats[i]));
+ }
+ break;
+ case kMix:
+ size_t middle1 = flats.size() / 2, middle2 = middle1;
+ ring = CordRepRing::Create(MakeLeaf(flats[middle1]), flats.size() - 1);
+ if (!flats.empty()) {
+ if ((flats.size() & 1) == 0) {
+ ring = CordRepRing::Prepend(ring, MakeLeaf(flats[--middle1]));
+ }
+ for (int i = 1; i <= middle1; ++i) {
+ ring = CordRepRing::Prepend(ring, MakeLeaf(flats[middle1 - i]));
+ ring = CordRepRing::Append(ring, MakeLeaf(flats[middle2 + i]));
+ }
+ }
+ break;
+ }
+ EXPECT_THAT(ToFlats(ring), ElementsAreArray(flats));
+ return ring;
+}
+
+std::ostream& operator<<(std::ostream& s, const TestParam& param) {
+ return s << param.ToString();
+}
+
+std::string TestParamToString(const testing::TestParamInfo<TestParam>& info) {
+ return info.param.ToString();
+}
+
+class CordRingTest : public testing::Test {
+ public:
+ ~CordRingTest() override {
+#if ASAN_BUG_177688959_FIXED
+ for (CordRep* rep : unrefs_) {
+ CordRep::Unref(rep);
+ }
+#endif
+ }
+
+ template <typename CordRepType>
+ CordRepType* NeedsUnref(CordRepType* rep) {
+ assert(rep);
+#if ASAN_BUG_177688959_FIXED
+ unrefs_.push_back(rep);
+#endif
+ return rep;
+ }
+
+ template <typename CordRepType>
+ CordRepType* Ref(CordRepType* rep) {
+ CordRep::Ref(rep);
+ return NeedsUnref(rep);
+ }
+
+ void Unref(CordRep* rep) {
+#if !ASAN_BUG_177688959_FIXED
+ CordRep::Unref(rep);
+#endif
+ }
+
+ private:
+#if ASAN_BUG_177688959_FIXED
+ std::vector<CordRep*> unrefs_;
+#endif
+};
+
+class CordRingTestWithParam : public testing::TestWithParam<TestParam> {
+ public:
+ ~CordRingTestWithParam() override {
+#if ASAN_BUG_177688959_FIXED
+ for (CordRep* rep : unrefs_) {
+ CordRep::Unref(rep);
+ }
+#endif
+ }
+
+ CordRepRing* CreateWithCapacity(CordRep* child, size_t extra_capacity) {
+ if (!GetParam().with_capacity) extra_capacity = 0;
+ CordRepRing* ring = CordRepRing::Create(child, extra_capacity);
+ ring->SetCapacityForTesting(1 + extra_capacity);
+ return RefIfShared(ring);
+ }
+
+ bool Shared() const { return !GetParam().refcount_is_one; }
+ bool InputShared() const { return GetParam().input_share_mode == kShared; }
+ bool InputSharedIndirect() const {
+ return GetParam().input_share_mode == kSharedIndirect;
+ }
+
+ template <typename CordRepType>
+ CordRepType* NeedsUnref(CordRepType* rep) {
+ assert(rep);
+#if ASAN_BUG_177688959_FIXED
+ unrefs_.push_back(rep);
+#endif
+ return rep;
+ }
+
+ template <typename CordRepType>
+ CordRepType* Ref(CordRepType* rep) {
+ CordRep::Ref(rep);
+ return NeedsUnref(rep);
+ }
+
+ void Unref(CordRep* rep) {
+#if !ASAN_BUG_177688959_FIXED
+ CordRep::Unref(rep);
+#endif
+ }
+
+ template <typename CordRepType>
+ CordRepType* RefIfShared(CordRepType* rep) {
+ return Shared() ? Ref(rep) : rep;
+ }
+
+ void UnrefIfShared(CordRep* rep) {
+ if (Shared()) Unref(rep);
+ }
+
+ template <typename CordRepType>
+ CordRepType* RefIfInputShared(CordRepType* rep) {
+ return InputShared() ? Ref(rep) : rep;
+ }
+
+ void UnrefIfInputShared(CordRep* rep) {
+ if (InputShared()) Unref(rep);
+ }
+
+ template <typename CordRepType>
+ CordRepType* RefIfInputSharedIndirect(CordRepType* rep) {
+ return InputSharedIndirect() ? Ref(rep) : rep;
+ }
+
+ void UnrefIfInputSharedIndirect(CordRep* rep) {
+ if (InputSharedIndirect()) Unref(rep);
+ }
+
+ private:
+#if ASAN_BUG_177688959_FIXED
+ std::vector<CordRep*> unrefs_;
+#endif
+};
+
+class CordRingCreateTest : public CordRingTestWithParam {
+ public:
+ static TestParams CreateTestParams() {
+ TestParams params;
+ params.emplace_back(InputShareMode::kPrivate);
+ params.emplace_back(InputShareMode::kShared);
+ return params;
+ }
+};
+
+class CordRingSubTest : public CordRingTestWithParam {
+ public:
+ static TestParams CreateTestParams() {
+ TestParams params;
+ for (bool refcount_is_one : {true, false}) {
+ TestParam param;
+ param.refcount_is_one = refcount_is_one;
+ params.push_back(param);
+ }
+ return params;
+ }
+};
+
+class CordRingBuildTest : public CordRingTestWithParam {
+ public:
+ static TestParams CreateTestParams() {
+ TestParams params;
+ for (bool refcount_is_one : {true, false}) {
+ for (bool with_capacity : {true, false}) {
+ TestParam param;
+ param.refcount_is_one = refcount_is_one;
+ param.with_capacity = with_capacity;
+ params.push_back(param);
+ }
+ }
+ return params;
+ }
+};
+
+class CordRingCreateFromTreeTest : public CordRingTestWithParam {
+ public:
+ static TestParams CreateTestParams() {
+ TestParams params;
+ params.emplace_back(InputShareMode::kPrivate);
+ params.emplace_back(InputShareMode::kShared);
+ params.emplace_back(InputShareMode::kSharedIndirect);
+ return params;
+ }
+};
+
+class CordRingBuildInputTest : public CordRingTestWithParam {
+ public:
+ static TestParams CreateTestParams() {
+ TestParams params;
+ for (bool refcount_is_one : {true, false}) {
+ for (bool with_capacity : {true, false}) {
+ for (InputShareMode share_mode : {kPrivate, kShared, kSharedIndirect}) {
+ TestParam param;
+ param.refcount_is_one = refcount_is_one;
+ param.with_capacity = with_capacity;
+ param.input_share_mode = share_mode;
+ params.push_back(param);
+ }
+ }
+ }
+ return params;
+ }
+};
+
+INSTANTIATE_TEST_CASE_P(WithParam, CordRingSubTest,
+ testing::ValuesIn(CordRingSubTest::CreateTestParams()),
+ TestParamToString);
+
+INSTANTIATE_TEST_CASE_P(
+ WithParam, CordRingCreateTest,
+ testing::ValuesIn(CordRingCreateTest::CreateTestParams()),
+ TestParamToString);
+
+INSTANTIATE_TEST_CASE_P(
+ WithParam, CordRingCreateFromTreeTest,
+ testing::ValuesIn(CordRingCreateFromTreeTest::CreateTestParams()),
+ TestParamToString);
+
+INSTANTIATE_TEST_CASE_P(
+ WithParam, CordRingBuildTest,
+ testing::ValuesIn(CordRingBuildTest::CreateTestParams()),
+ TestParamToString);
+
+INSTANTIATE_TEST_CASE_P(
+ WithParam, CordRingBuildInputTest,
+ testing::ValuesIn(CordRingBuildInputTest::CreateTestParams()),
+ TestParamToString);
+
+TEST_P(CordRingCreateTest, CreateFromFlat) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(MakeFlat(str1)));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1));
+ Unref(result);
+}
+
+TEST_P(CordRingCreateTest, CreateFromRing) {
+ CordRepRing* ring = RefIfShared(FromFlats(kFoxFlats));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(ring));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringRing) {
+ CordRepRing* ring = RefIfInputSharedIndirect(FromFlats(kFoxFlats));
+ CordRep* sub = RefIfInputShared(MakeSubstring(2, 11, ring));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(sub));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfInputPrivate(GetParam(), ring));
+ EXPECT_THAT(ToString(result), string_view(kFox).substr(2, 11));
+ UnrefIfInputSharedIndirect(ring);
+ UnrefIfInputShared(sub);
+ Unref(result);
+}
+
+TEST_F(CordRingTest, CreateWithIllegalExtraCapacity) {
+ CordRep* flat = NeedsUnref(MakeFlat("Hello world"));
+#if defined(ABSL_HAVE_EXCEPTIONS)
+ try {
+ CordRepRing::Create(flat, CordRepRing::kMaxCapacity);
+ GTEST_FAIL() << "expected std::length_error exception";
+ } catch (const std::length_error&) {
+ }
+#elif defined(GTEST_HAS_DEATH_TEST)
+ EXPECT_DEATH(CordRepRing::Create(flat, CordRepRing::kMaxCapacity), ".*");
+#endif
+ Unref(flat);
+}
+
+TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringOfFlat) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ auto* flat = RefIfInputShared(MakeFlat(str1));
+ auto* child = RefIfInputSharedIndirect(MakeSubstring(4, 20, flat));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(20));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1.substr(4, 20)));
+ Unref(result);
+ UnrefIfInputShared(flat);
+ UnrefIfInputSharedIndirect(child);
+}
+
+TEST_P(CordRingCreateTest, CreateFromExternal) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ auto* child = RefIfInputShared(MakeExternal(str1));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1));
+ Unref(result);
+ UnrefIfInputShared(child);
+}
+
+TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringOfExternal) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ auto* external = RefIfInputShared(MakeExternal(str1));
+ auto* child = RefIfInputSharedIndirect(MakeSubstring(1, 24, external));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(24));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1.substr(1, 24)));
+ Unref(result);
+ UnrefIfInputShared(external);
+ UnrefIfInputSharedIndirect(child);
+}
+
+TEST_P(CordRingCreateFromTreeTest, CreateFromSubstringOfLargeExternal) {
+ auto* external = RefIfInputShared(MakeFakeExternal(1 << 20));
+ auto str = not_a_string_view(external->base, 1 << 20)
+ .remove_prefix(1 << 19)
+ .remove_suffix(6);
+ auto* child =
+ RefIfInputSharedIndirect(MakeSubstring(1 << 19, (1 << 19) - 6, external));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str.size()));
+ EXPECT_THAT(ToRawFlats(result), ElementsAre(str));
+ Unref(result);
+ UnrefIfInputShared(external);
+ UnrefIfInputSharedIndirect(child);
+}
+
+TEST_P(CordRingBuildInputTest, CreateFromConcat) {
+ CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
+ MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
+ auto* left = MakeConcat(RefIfInputSharedIndirect(flats[0]), flats[1]);
+ auto* right = MakeConcat(flats[2], RefIfInputSharedIndirect(flats[3]));
+ auto* concat = RefIfInputShared(MakeConcat(left, right));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(concat));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(26));
+ EXPECT_THAT(ToString(result), Eq(kAlphabet));
+ UnrefIfInputSharedIndirect(flats[0]);
+ UnrefIfInputSharedIndirect(flats[3]);
+ UnrefIfInputShared(concat);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, CreateFromSubstringConcat) {
+ for (size_t off = 0; off < 26; ++off) {
+ for (size_t len = 1; len < 26 - off; ++len) {
+ CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
+ MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
+ auto* left = MakeConcat(RefIfInputSharedIndirect(flats[0]), flats[1]);
+ auto* right = MakeConcat(flats[2], RefIfInputSharedIndirect(flats[3]));
+ auto* concat = MakeConcat(left, right);
+ auto* child = RefIfInputShared(MakeSubstring(off, len, concat));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ ASSERT_THAT(result->length, Eq(len));
+ ASSERT_THAT(ToString(result), string_view(kAlphabet).substr(off, len));
+ UnrefIfInputSharedIndirect(flats[0]);
+ UnrefIfInputSharedIndirect(flats[3]);
+ UnrefIfInputShared(child);
+ Unref(result);
+ }
+ }
+}
+
+TEST_P(CordRingCreateTest, Properties) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(MakeFlat(str1), 120));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->head(), Eq(0));
+ EXPECT_THAT(result->tail(), Eq(1));
+ EXPECT_THAT(result->capacity(), Ge(120 + 1));
+ EXPECT_THAT(result->capacity(), Le(2 * 120 + 1));
+ EXPECT_THAT(result->entries(), Eq(1));
+ EXPECT_THAT(result->begin_pos(), Eq(0));
+ Unref(result);
+}
+
+TEST_P(CordRingCreateTest, EntryForNewFlat) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ CordRep* child = MakeFlat(str1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child, 120));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->entry_child(0), Eq(child));
+ EXPECT_THAT(result->entry_end_pos(0), Eq(str1.length()));
+ EXPECT_THAT(result->entry_data_offset(0), Eq(0));
+ Unref(result);
+}
+
+TEST_P(CordRingCreateTest, EntryForNewFlatSubstring) {
+ absl::string_view str1 = "1234567890abcdefghijklmnopqrstuvwxyz";
+ CordRep* child = MakeFlat(str1);
+ CordRep* substring = MakeSubstring(10, 26, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(substring, 1));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->entry_child(0), Eq(child));
+ EXPECT_THAT(result->entry_end_pos(0), Eq(26));
+ EXPECT_THAT(result->entry_data_offset(0), Eq(10));
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendFlat) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, MakeFlat(str2)));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, PrependFlat) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, MakeFlat(str2)));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str2, str1));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendString) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendStringHavingExtra) {
+ absl::string_view str1 = "1234";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeFlat(str1, 26), 0);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendStringHavingPartialExtra) {
+ absl::string_view str1 = "1234";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ // Create flat with at least one extra byte. We don't expect to have sized
+ // alloc and capacity rounding to grant us enough to not make it partial.
+ auto* flat = MakeFlat(str1, 1);
+ size_t avail = flat->flat()->Capacity() - flat->length;
+ ASSERT_THAT(avail, Lt(str2.size())) << " adjust test for larger flats!";
+
+ // Construct the flats we do expect using all of `avail`.
+ absl::string_view str1a = str2.substr(0, avail);
+ absl::string_view str2a = str2.substr(avail);
+
+ CordRepRing* ring = CreateWithCapacity(flat, 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ if (GetParam().refcount_is_one) {
+ EXPECT_THAT(ToFlats(result), ElementsAre(StrCat(str1, str1a), str2a));
+ } else {
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
+ }
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendStringHavingExtraInSubstring) {
+ absl::string_view str1 = "123456789_1234";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRep* flat = RemovePrefix(10, MakeFlat(str1, 26));
+ CordRepRing* ring = CreateWithCapacity(flat, 0);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(4 + str2.size()));
+ if (GetParam().refcount_is_one) {
+ EXPECT_THAT(ToFlats(result), ElementsAre(StrCat("1234", str2)));
+ } else {
+ EXPECT_THAT(ToFlats(result), ElementsAre("1234", str2));
+ }
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendStringHavingSharedExtra) {
+ absl::string_view str1 = "123456789_1234";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ for (int shared_type = 0; shared_type < 2; ++shared_type) {
+ SCOPED_TRACE(absl::StrCat("Shared extra type ", shared_type));
+
+ // Create a flat that is shared in some way.
+ CordRep* flat = nullptr;
+ CordRep* flat1 = nullptr;
+ if (shared_type == 0) {
+ // Shared flat
+ flat = CordRep::Ref(MakeFlat(str1.substr(10), 100));
+ } else if (shared_type == 1) {
+ // Shared flat inside private substring
+ flat1 = CordRep::Ref(MakeFlat(str1));
+ flat = RemovePrefix(10, flat1);
+ } else {
+ // Private flat inside shared substring
+ flat = CordRep::Ref(RemovePrefix(10, MakeFlat(str1, 100)));
+ }
+
+ CordRepRing* ring = CreateWithCapacity(flat, 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(4 + str2.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre("1234", str2));
+ UnrefIfShared(ring);
+ Unref(result);
+
+ CordRep::Unref(shared_type == 1 ? flat1 : flat);
+ }
+}
+
+TEST_P(CordRingBuildTest, AppendStringWithExtra) {
+ absl::string_view str1 = "1234";
+ absl::string_view str2 = "1234567890";
+ absl::string_view str3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, str2, 26));
+ result = CordRepRing::Append(result, str3);
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size() + str3.size()));
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str1, StrCat(str2, str3)));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, PrependString) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ // Use external rep to avoid appending to first flat
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ if (GetParam().with_capacity && GetParam().refcount_is_one) {
+ EXPECT_THAT(result, Eq(ring));
+ } else {
+ EXPECT_THAT(result, Ne(ring));
+ }
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str2, str1));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, PrependStringHavingExtra) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz1234";
+ absl::string_view str2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRep* flat = RemovePrefix(26, MakeFlat(str1));
+ CordRepRing* ring = CreateWithCapacity(flat, 0);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(result->length, Eq(4 + str2.size()));
+ if (GetParam().refcount_is_one) {
+ EXPECT_THAT(ToFlats(result), ElementsAre(StrCat(str2, "1234")));
+ } else {
+ EXPECT_THAT(ToFlats(result), ElementsAre(str2, "1234"));
+ }
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, PrependStringHavingSharedExtra) {
+ absl::string_view str1 = "123456789_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ absl::string_view str2 = "abcdefghij";
+ absl::string_view str1a = str1.substr(10);
+ for (int shared_type = 1; shared_type < 2; ++shared_type) {
+ SCOPED_TRACE(absl::StrCat("Shared extra type ", shared_type));
+
+ // Create a flat that is shared in some way.
+ CordRep* flat = nullptr;
+ CordRep* flat1 = nullptr;
+ if (shared_type == 1) {
+ // Shared flat inside private substring
+ flat = RemovePrefix(10, flat1 = CordRep::Ref(MakeFlat(str1)));
+ } else {
+ // Private flat inside shared substring
+ flat = CordRep::Ref(RemovePrefix(10, MakeFlat(str1, 100)));
+ }
+
+ CordRepRing* ring = CreateWithCapacity(flat, 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, str2));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result->length, Eq(str1a.size() + str2.size()));
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre(str2, str1a));
+ UnrefIfShared(ring);
+ Unref(result);
+ CordRep::Unref(shared_type == 1 ? flat1 : flat);
+ }
+}
+
+TEST_P(CordRingBuildTest, PrependStringWithExtra) {
+ absl::string_view str1 = "1234";
+ absl::string_view str2 = "1234567890";
+ absl::string_view str3 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ CordRepRing* ring = CreateWithCapacity(MakeExternal(str1), 1);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, str2, 26));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ result = CordRepRing::Prepend(result, str3);
+ EXPECT_THAT(result->length, Eq(str1.size() + str2.size() + str3.size()));
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre(StrCat(str3, str2), str1));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendPrependStringMix) {
+ const auto& flats = kFoxFlats;
+ CordRepRing* ring = CreateWithCapacity(MakeFlat(flats[4]), 8);
+ CordRepRing* result = ring;
+ for (int i = 1; i <= 4; ++i) {
+ result = CordRepRing::Prepend(result, flats[4 - i]);
+ result = CordRepRing::Append(result, flats[4 + i]);
+ }
+ UnrefIfShared(ring);
+ NeedsUnref(result);
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToString(result), kFox);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendPrependStringMixWithExtra) {
+ const auto& flats = kFoxFlats;
+ CordRepRing* ring = CreateWithCapacity(MakeFlat(flats[4], 100), 8);
+ CordRepRing* result = ring;
+ for (int i = 1; i <= 4; ++i) {
+ result = CordRepRing::Prepend(result, flats[4 - i], 100);
+ result = CordRepRing::Append(result, flats[4 + i], 100);
+ }
+ NeedsUnref(result);
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ if (GetParam().refcount_is_one) {
+ EXPECT_THAT(ToFlats(result),
+ ElementsAre("The quick brown fox ", "jumps over the lazy dog"));
+ } else {
+ EXPECT_THAT(ToFlats(result), ElementsAre("The quick brown fox ", "jumps ",
+ "over the lazy dog"));
+ }
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendPrependStringMixWithPrependedExtra) {
+ const auto& flats = kFoxFlats;
+ CordRep* flat = MakeFlat(StrCat(std::string(50, '.'), flats[4]), 50);
+ CordRepRing* ring = CreateWithCapacity(RemovePrefix(50, flat), 0);
+ CordRepRing* result = ring;
+ for (int i = 1; i <= 4; ++i) {
+ result = CordRepRing::Prepend(result, flats[4 - i], 100);
+ result = CordRepRing::Append(result, flats[4 + i], 100);
+ }
+ result = NeedsUnref(result);
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ if (GetParam().refcount_is_one) {
+ EXPECT_THAT(ToFlats(result), ElementsAre(kFox));
+ } else {
+ EXPECT_THAT(ToFlats(result), ElementsAre("The quick brown fox ", "jumps ",
+ "over the lazy dog"));
+ }
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingSubTest, SubRing) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ string_view all = kFox;
+ for (size_t offset = 0; offset < all.size() - 1; ++offset) {
+ CordRepRing* ring = RefIfShared(FromFlats(flats, composition));
+ CordRepRing* result = CordRepRing::SubRing(ring, offset, 0);
+ EXPECT_THAT(result, nullptr);
+ UnrefIfShared(ring);
+
+ for (size_t len = 1; len < all.size() - offset; ++len) {
+ ring = RefIfShared(FromFlats(flats, composition));
+ result = NeedsUnref(CordRepRing::SubRing(ring, offset, len));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ ASSERT_THAT(result, EqIfPrivate(GetParam(), ring));
+ ASSERT_THAT(ToString(result), Eq(all.substr(offset, len)));
+ UnrefIfShared(ring);
+ Unref(result);
+ }
+ }
+}
+
+TEST_P(CordRingSubTest, SubRingFromLargeExternal) {
+ auto composition = RandomComposition();
+ std::string large_string(1 << 20, '.');
+ const char* flats[] = {
+ "abcdefghijklmnopqrstuvwxyz",
+ large_string.c_str(),
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ };
+ std::string buffer = absl::StrCat(flats[0], flats[1], flats[2]);
+ absl::string_view all = buffer;
+ for (size_t offset = 0; offset < 30; ++offset) {
+ CordRepRing* ring = RefIfShared(FromFlats(flats, composition));
+ CordRepRing* result = CordRepRing::SubRing(ring, offset, 0);
+ EXPECT_THAT(result, nullptr);
+ UnrefIfShared(ring);
+
+ for (size_t len = all.size() - 30; len < all.size() - offset; ++len) {
+ ring = RefIfShared(FromFlats(flats, composition));
+ result = NeedsUnref(CordRepRing::SubRing(ring, offset, len));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ ASSERT_THAT(result, EqIfPrivate(GetParam(), ring));
+ auto str = ToString(result);
+ ASSERT_THAT(str, SizeIs(len));
+ ASSERT_THAT(str, Eq(all.substr(offset, len)));
+ UnrefIfShared(ring);
+ Unref(result);
+ }
+ }
+}
+
+TEST_P(CordRingSubTest, RemovePrefix) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ string_view all = kFox;
+ CordRepRing* ring = RefIfShared(FromFlats(flats, composition));
+ CordRepRing* result = CordRepRing::RemovePrefix(ring, all.size());
+ EXPECT_THAT(result, nullptr);
+ UnrefIfShared(ring);
+
+ for (size_t len = 1; len < all.size(); ++len) {
+ ring = RefIfShared(FromFlats(flats, composition));
+ result = NeedsUnref(CordRepRing::RemovePrefix(ring, len));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(ToString(result), Eq(all.substr(len)));
+ UnrefIfShared(ring);
+ Unref(result);
+ }
+}
+
+TEST_P(CordRingSubTest, RemovePrefixFromLargeExternal) {
+ CordRepExternal* external1 = MakeFakeExternal(1 << 20);
+ CordRepExternal* external2 = MakeFakeExternal(1 << 20);
+ CordRepRing* ring = CordRepRing::Create(external1, 1);
+ ring = CordRepRing::Append(ring, external2);
+ CordRepRing* result = NeedsUnref(CordRepRing::RemovePrefix(ring, 1 << 16));
+ EXPECT_THAT(
+ ToRawFlats(result),
+ ElementsAre(
+ not_a_string_view(external1->base, 1 << 20).remove_prefix(1 << 16),
+ not_a_string_view(external2->base, 1 << 20)));
+ Unref(result);
+}
+
+TEST_P(CordRingSubTest, RemoveSuffix) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ string_view all = kFox;
+ CordRepRing* ring = RefIfShared(FromFlats(flats, composition));
+ CordRepRing* result = CordRepRing::RemoveSuffix(ring, all.size());
+ EXPECT_THAT(result, nullptr);
+ UnrefIfShared(ring);
+
+ for (size_t len = 1; len < all.size(); ++len) {
+ ring = RefIfShared(FromFlats(flats, composition));
+ result = NeedsUnref(CordRepRing::RemoveSuffix(ring, len));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(ToString(result), Eq(all.substr(0, all.size() - len)));
+ UnrefIfShared(ring);
+ Unref(result);
+ }
+}
+
+TEST_P(CordRingSubTest, AppendRing) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats).subspan(1);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat(kFoxFlats[0]), flats.size());
+ CordRepRing* child = FromFlats(flats, composition);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivate(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, AppendRingWithFlatOffset) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RemovePrefix(10, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("Head", "brown ", "fox ", "jumps ",
+ "over ", "the ", "lazy ", "dog"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, AppendRingWithBrokenOffset) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RemovePrefix(21, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result),
+ ElementsAre("Head", "umps ", "over ", "the ", "lazy ", "dog"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, AppendRingWithFlatLength) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RemoveSuffix(8, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("Head", "The ", "quick ", "brown ",
+ "fox ", "jumps ", "over ", "the "));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendRingWithBrokenFlatLength) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RemoveSuffix(15, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("Head", "The ", "quick ", "brown ",
+ "fox ", "jumps ", "ov"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendRingMiddlePiece) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = MakeSubstring(7, child->length - 27, child);
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result),
+ ElementsAre("Head", "ck ", "brown ", "fox ", "jum"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildTest, AppendRingSinglePiece) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Head"), flats.size());
+ CordRep* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputShared(MakeSubstring(11, 3, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("Head", "row"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfInputShared(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, AppendRingSinglePieceWithPrefix) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ size_t extra_capacity = 1 + (GetParam().with_capacity ? flats.size() : 0);
+ CordRepRing* ring = CordRepRing::Create(MakeFlat("Head"), extra_capacity);
+ ring->SetCapacityForTesting(1 + extra_capacity);
+ ring = RefIfShared(CordRepRing::Prepend(ring, MakeFlat("Prepend")));
+ assert(ring->IsValid(std::cout));
+ CordRepRing* child = RefIfInputSharedIndirect(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputShared(MakeSubstring(11, 3, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Append(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("Prepend", "Head", "row"));
+ UnrefIfInputSharedIndirect(child);
+ UnrefIfInputShared(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRing) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto fox = MakeSpan(kFoxFlats);
+ auto flats = MakeSpan(fox).subspan(0, fox.size() - 1);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat(fox.back()), flats.size());
+ CordRepRing* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
+ UnrefIfInputShared(child);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingWithFlatOffset) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(RemovePrefix(10, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("brown ", "fox ", "jumps ", "over ",
+ "the ", "lazy ", "dog", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingWithBrokenOffset) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(RemovePrefix(21, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result),
+ ElementsAre("umps ", "over ", "the ", "lazy ", "dog", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingWithFlatLength) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(RemoveSuffix(8, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("The ", "quick ", "brown ", "fox ",
+ "jumps ", "over ", "the ", "Tail"));
+ UnrefIfShared(ring);
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingWithBrokenFlatLength) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(RemoveSuffix(15, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("The ", "quick ", "brown ", "fox ",
+ "jumps ", "ov", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingMiddlePiece) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped =
+ RefIfInputSharedIndirect(MakeSubstring(7, child->length - 27, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result),
+ ElementsAre("ck ", "brown ", "fox ", "jum", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingSinglePiece) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CreateWithCapacity(MakeFlat("Tail"), flats.size());
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(MakeSubstring(11, 3, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("row", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_P(CordRingBuildInputTest, PrependRingSinglePieceWithPrefix) {
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ auto flats = MakeSpan(kFoxFlats);
+ size_t extra_capacity = 1 + (GetParam().with_capacity ? flats.size() : 0);
+ CordRepRing* ring = CordRepRing::Create(MakeFlat("Tail"), extra_capacity);
+ ring->SetCapacityForTesting(1 + extra_capacity);
+ ring = RefIfShared(CordRepRing::Prepend(ring, MakeFlat("Prepend")));
+ CordRep* child = RefIfInputShared(FromFlats(flats, composition));
+ CordRep* stripped = RefIfInputSharedIndirect(MakeSubstring(11, 3, child));
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, stripped));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
+ EXPECT_THAT(ToFlats(result), ElementsAre("row", "Prepend", "Tail"));
+ UnrefIfInputShared(child);
+ UnrefIfInputSharedIndirect(stripped);
+ UnrefIfShared(ring);
+ Unref(result);
+}
+
+TEST_F(CordRingTest, Find) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = NeedsUnref(FromFlats(flats, composition));
+ std::string value = ToString(ring);
+ for (int i = 0; i < value.length(); ++i) {
+ CordRepRing::Position found = ring->Find(i);
+ auto data = ring->entry_data(found.index);
+ ASSERT_THAT(found.offset, Lt(data.length()));
+ ASSERT_THAT(data[found.offset], Eq(value[i]));
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, FindWithHint) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = NeedsUnref(FromFlats(flats, composition));
+ std::string value = ToString(ring);
+
+#if defined(GTEST_HAS_DEATH_TEST)
+ // Test hint beyond valid position
+ index_type head = ring->head();
+ EXPECT_DEBUG_DEATH(ring->Find(ring->advance(head), 0), ".*");
+ EXPECT_DEBUG_DEATH(ring->Find(ring->advance(head), 9), ".*");
+ EXPECT_DEBUG_DEATH(ring->Find(ring->advance(head, 3), 24), ".*");
+#endif
+
+ int flat_pos = 0;
+ size_t flat_offset = 0;
+ for (auto sflat : flats) {
+ string_view flat(sflat);
+ for (int offset = 0; offset < flat.length(); ++offset) {
+ for (int start = 0; start <= flat_pos; ++start) {
+ index_type hint = ring->advance(ring->head(), start);
+ CordRepRing::Position found = ring->Find(hint, flat_offset + offset);
+ ASSERT_THAT(found.index, Eq(ring->advance(ring->head(), flat_pos)));
+ ASSERT_THAT(found.offset, Eq(offset));
+ }
+ }
+ ++flat_pos;
+ flat_offset += flat.length();
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, FindInLargeRing) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = FromFlats(flats, composition);
+ for (int i = 0; i < 13; ++i) {
+ ring = CordRepRing::Append(ring, FromFlats(flats, composition));
+ }
+ NeedsUnref(ring);
+ std::string value = ToString(ring);
+ for (int i = 0; i < value.length(); ++i) {
+ CordRepRing::Position pos = ring->Find(i);
+ auto data = ring->entry_data(pos.index);
+ ASSERT_THAT(pos.offset, Lt(data.length()));
+ ASSERT_THAT(data[pos.offset], Eq(value[i]));
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, FindTail) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = NeedsUnref(FromFlats(flats, composition));
+ std::string value = ToString(ring);
+
+ for (int i = 0; i < value.length(); ++i) {
+ CordRepRing::Position pos = ring->FindTail(i + 1);
+ auto data = ring->entry_data(ring->retreat(pos.index));
+ ASSERT_THAT(pos.offset, Lt(data.length()));
+ ASSERT_THAT(data[data.length() - pos.offset - 1], Eq(value[i]));
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, FindTailWithHint) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = NeedsUnref(FromFlats(flats, composition));
+ std::string value = ToString(ring);
+
+ // Test hint beyond valid position
+#if defined(GTEST_HAS_DEATH_TEST)
+ index_type head = ring->head();
+ EXPECT_DEBUG_DEATH(ring->FindTail(ring->advance(head), 1), ".*");
+ EXPECT_DEBUG_DEATH(ring->FindTail(ring->advance(head), 10), ".*");
+ EXPECT_DEBUG_DEATH(ring->FindTail(ring->advance(head, 3), 26), ".*");
+#endif
+
+ for (int i = 0; i < value.length(); ++i) {
+ CordRepRing::Position pos = ring->FindTail(i + 1);
+ auto data = ring->entry_data(ring->retreat(pos.index));
+ ASSERT_THAT(pos.offset, Lt(data.length()));
+ ASSERT_THAT(data[data.length() - pos.offset - 1], Eq(value[i]));
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, FindTailInLargeRing) {
+ constexpr const char* flats[] = {
+ "abcdefghij", "klmnopqrst", "uvwxyz", "ABCDEFGHIJ",
+ "KLMNOPQRST", "UVWXYZ", "1234567890", "~!@#$%^&*()_",
+ "+-=", "[]\\{}|;':", ",/<>?", "."};
+ auto composition = RandomComposition();
+ SCOPED_TRACE(ToString(composition));
+ CordRepRing* ring = FromFlats(flats, composition);
+ for (int i = 0; i < 13; ++i) {
+ ring = CordRepRing::Append(ring, FromFlats(flats, composition));
+ }
+ NeedsUnref(ring);
+ std::string value = ToString(ring);
+ for (int i = 0; i < value.length(); ++i) {
+ CordRepRing::Position pos = ring->FindTail(i + 1);
+ auto data = ring->entry_data(ring->retreat(pos.index));
+ ASSERT_THAT(pos.offset, Lt(data.length()));
+ ASSERT_THAT(data[data.length() - pos.offset - 1], Eq(value[i]));
+ }
+ Unref(ring);
+}
+
+TEST_F(CordRingTest, GetCharacter) {
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = CordRepRing::Create(MakeFlat("Tail"), flats.size());
+ CordRep* child = FromFlats(flats, kAppend);
+ CordRepRing* result = NeedsUnref(CordRepRing::Prepend(ring, child));
+ std::string value = ToString(result);
+ for (int i = 0; i < value.length(); ++i) {
+ ASSERT_THAT(result->GetCharacter(i), Eq(value[i]));
+ }
+ Unref(result);
+}
+
+TEST_F(CordRingTest, GetCharacterWithSubstring) {
+ absl::string_view str1 = "abcdefghijklmnopqrstuvwxyz";
+ auto* child = MakeSubstring(4, 20, MakeFlat(str1));
+ CordRepRing* result = NeedsUnref(CordRepRing::Create(child));
+ ASSERT_THAT(result, IsValidRingBuffer());
+ std::string value = ToString(result);
+ for (int i = 0; i < value.length(); ++i) {
+ ASSERT_THAT(result->GetCharacter(i), Eq(value[i]));
+ }
+ Unref(result);
+}
+
+TEST_F(CordRingTest, Dump) {
+ std::stringstream ss;
+ auto flats = MakeSpan(kFoxFlats);
+ CordRepRing* ring = NeedsUnref(FromFlats(flats, kPrepend));
+ ss << *ring;
+ Unref(ring);
+}
+
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test.cc
new file mode 100644
index 00000000000..f9982428b31
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test.cc
@@ -0,0 +1,1715 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/cord.h"
+
+#include <algorithm>
+#include <climits>
+#include <cstdio>
+#include <iterator>
+#include <map>
+#include <numeric>
+#include <random>
+#include <sstream>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
+#include "absl/container/fixed_array.h"
+#include "absl/strings/cord_test_helpers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+typedef std::mt19937_64 RandomEngine;
+
+static std::string RandomLowercaseString(RandomEngine* rng);
+static std::string RandomLowercaseString(RandomEngine* rng, size_t length);
+
+static int GetUniformRandomUpTo(RandomEngine* rng, int upper_bound) {
+ if (upper_bound > 0) {
+ std::uniform_int_distribution<int> uniform(0, upper_bound - 1);
+ return uniform(*rng);
+ } else {
+ return 0;
+ }
+}
+
+static size_t GetUniformRandomUpTo(RandomEngine* rng, size_t upper_bound) {
+ if (upper_bound > 0) {
+ std::uniform_int_distribution<size_t> uniform(0, upper_bound - 1);
+ return uniform(*rng);
+ } else {
+ return 0;
+ }
+}
+
+static int32_t GenerateSkewedRandom(RandomEngine* rng, int max_log) {
+ const uint32_t base = (*rng)() % (max_log + 1);
+ const uint32_t mask = ((base < 32) ? (1u << base) : 0u) - 1u;
+ return (*rng)() & mask;
+}
+
+static std::string RandomLowercaseString(RandomEngine* rng) {
+ int length;
+ std::bernoulli_distribution one_in_1k(0.001);
+ std::bernoulli_distribution one_in_10k(0.0001);
+ // With low probability, make a large fragment
+ if (one_in_10k(*rng)) {
+ length = GetUniformRandomUpTo(rng, 1048576);
+ } else if (one_in_1k(*rng)) {
+ length = GetUniformRandomUpTo(rng, 10000);
+ } else {
+ length = GenerateSkewedRandom(rng, 10);
+ }
+ return RandomLowercaseString(rng, length);
+}
+
+static std::string RandomLowercaseString(RandomEngine* rng, size_t length) {
+ std::string result(length, '\0');
+ std::uniform_int_distribution<int> chars('a', 'z');
+ std::generate(result.begin(), result.end(),
+ [&]() { return static_cast<char>(chars(*rng)); });
+ return result;
+}
+
+static void DoNothing(absl::string_view /* data */, void* /* arg */) {}
+
+static void DeleteExternalString(absl::string_view data, void* arg) {
+ std::string* s = reinterpret_cast<std::string*>(arg);
+ EXPECT_EQ(data, *s);
+ delete s;
+}
+
+// Add "s" to *dst via `MakeCordFromExternal`
+static void AddExternalMemory(absl::string_view s, absl::Cord* dst) {
+ std::string* str = new std::string(s.data(), s.size());
+ dst->Append(absl::MakeCordFromExternal(*str, [str](absl::string_view data) {
+ DeleteExternalString(data, str);
+ }));
+}
+
+static void DumpGrowth() {
+ absl::Cord str;
+ for (int i = 0; i < 1000; i++) {
+ char c = 'a' + i % 26;
+ str.Append(absl::string_view(&c, 1));
+ }
+}
+
+// Make a Cord with some number of fragments. Return the size (in bytes)
+// of the smallest fragment.
+static size_t AppendWithFragments(const std::string& s, RandomEngine* rng,
+ absl::Cord* cord) {
+ size_t j = 0;
+ const size_t max_size = s.size() / 5; // Make approx. 10 fragments
+ size_t min_size = max_size; // size of smallest fragment
+ while (j < s.size()) {
+ size_t N = 1 + GetUniformRandomUpTo(rng, max_size);
+ if (N > (s.size() - j)) {
+ N = s.size() - j;
+ }
+ if (N < min_size) {
+ min_size = N;
+ }
+
+ std::bernoulli_distribution coin_flip(0.5);
+ if (coin_flip(*rng)) {
+ // Grow by adding an external-memory.
+ AddExternalMemory(absl::string_view(s.data() + j, N), cord);
+ } else {
+ cord->Append(absl::string_view(s.data() + j, N));
+ }
+ j += N;
+ }
+ return min_size;
+}
+
+// Add an external memory that contains the specified std::string to cord
+static void AddNewStringBlock(const std::string& str, absl::Cord* dst) {
+ char* data = new char[str.size()];
+ memcpy(data, str.data(), str.size());
+ dst->Append(absl::MakeCordFromExternal(
+ absl::string_view(data, str.size()),
+ [](absl::string_view s) { delete[] s.data(); }));
+}
+
+// Make a Cord out of many different types of nodes.
+static absl::Cord MakeComposite() {
+ absl::Cord cord;
+ cord.Append("the");
+ AddExternalMemory(" quick brown", &cord);
+ AddExternalMemory(" fox jumped", &cord);
+
+ absl::Cord full(" over");
+ AddExternalMemory(" the lazy", &full);
+ AddNewStringBlock(" dog slept the whole day away", &full);
+ absl::Cord substring = full.Subcord(0, 18);
+
+ // Make substring long enough to defeat the copying fast path in Append.
+ substring.Append(std::string(1000, '.'));
+ cord.Append(substring);
+ cord = cord.Subcord(0, cord.size() - 998); // Remove most of extra junk
+
+ return cord;
+}
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+class CordTestPeer {
+ public:
+ static void ForEachChunk(
+ const Cord& c, absl::FunctionRef<void(absl::string_view)> callback) {
+ c.ForEachChunk(callback);
+ }
+
+ static bool IsTree(const Cord& c) { return c.contents_.is_tree(); }
+
+ static cord_internal::CordzInfo* GetCordzInfo(const Cord& c) {
+ return c.contents_.cordz_info();
+ }
+};
+
+ABSL_NAMESPACE_END
+} // namespace absl
+
+TEST(Cord, AllFlatSizes) {
+ using absl::strings_internal::CordTestAccess;
+
+ for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
+ // Make a string of length s.
+ std::string src;
+ while (src.size() < s) {
+ src.push_back('a' + (src.size() % 26));
+ }
+
+ absl::Cord dst(src);
+ EXPECT_EQ(std::string(dst), src) << s;
+ }
+}
+
+// We create a Cord at least 128GB in size using the fact that Cords can
+// internally reference-count; thus the Cord is enormous without actually
+// consuming very much memory.
+TEST(GigabyteCord, FromExternal) {
+ const size_t one_gig = 1024U * 1024U * 1024U;
+ size_t max_size = 2 * one_gig;
+ if (sizeof(max_size) > 4) max_size = 128 * one_gig;
+
+ size_t length = 128 * 1024;
+ char* data = new char[length];
+ absl::Cord from = absl::MakeCordFromExternal(
+ absl::string_view(data, length),
+ [](absl::string_view sv) { delete[] sv.data(); });
+
+ // This loop may seem odd due to its combination of exponential doubling of
+ // size and incremental size increases. We do it incrementally to be sure the
+ // Cord will need rebalancing and will exercise code that, in the past, has
+ // caused crashes in production. We grow exponentially so that the code will
+ // execute in a reasonable amount of time.
+ absl::Cord c;
+ ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
+ c.Append(from);
+ while (c.size() < max_size) {
+ c.Append(c);
+ c.Append(from);
+ c.Append(from);
+ c.Append(from);
+ c.Append(from);
+ }
+
+ for (int i = 0; i < 1024; ++i) {
+ c.Append(from);
+ }
+ ABSL_RAW_LOG(INFO, "Made a Cord with %zu bytes!", c.size());
+ // Note: on a 32-bit build, this comes out to 2,818,048,000 bytes.
+ // Note: on a 64-bit build, this comes out to 171,932,385,280 bytes.
+}
+
+static absl::Cord MakeExternalCord(int size) {
+ char* buffer = new char[size];
+ memset(buffer, 'x', size);
+ absl::Cord cord;
+ cord.Append(absl::MakeCordFromExternal(
+ absl::string_view(buffer, size),
+ [](absl::string_view s) { delete[] s.data(); }));
+ return cord;
+}
+
+// Extern to fool clang that this is not constant. Needed to suppress
+// a warning of unsafe code we want to test.
+extern bool my_unique_true_boolean;
+bool my_unique_true_boolean = true;
+
+TEST(Cord, Assignment) {
+ absl::Cord x(absl::string_view("hi there"));
+ absl::Cord y(x);
+ ASSERT_EQ(std::string(x), "hi there");
+ ASSERT_EQ(std::string(y), "hi there");
+ ASSERT_TRUE(x == y);
+ ASSERT_TRUE(x <= y);
+ ASSERT_TRUE(y <= x);
+
+ x = absl::string_view("foo");
+ ASSERT_EQ(std::string(x), "foo");
+ ASSERT_EQ(std::string(y), "hi there");
+ ASSERT_TRUE(x < y);
+ ASSERT_TRUE(y > x);
+ ASSERT_TRUE(x != y);
+ ASSERT_TRUE(x <= y);
+ ASSERT_TRUE(y >= x);
+
+ x = "foo";
+ ASSERT_EQ(x, "foo");
+
+ // Test that going from inline rep to tree we don't leak memory.
+ std::vector<std::pair<absl::string_view, absl::string_view>>
+ test_string_pairs = {{"hi there", "foo"},
+ {"loooooong coooooord", "short cord"},
+ {"short cord", "loooooong coooooord"},
+ {"loooooong coooooord1", "loooooong coooooord2"}};
+ for (std::pair<absl::string_view, absl::string_view> test_strings :
+ test_string_pairs) {
+ absl::Cord tmp(test_strings.first);
+ absl::Cord z(std::move(tmp));
+ ASSERT_EQ(std::string(z), test_strings.first);
+ tmp = test_strings.second;
+ z = std::move(tmp);
+ ASSERT_EQ(std::string(z), test_strings.second);
+ }
+ {
+ // Test that self-move assignment doesn't crash/leak.
+ // Do not write such code!
+ absl::Cord my_small_cord("foo");
+ absl::Cord my_big_cord("loooooong coooooord");
+ // Bypass clang's warning on self move-assignment.
+ absl::Cord* my_small_alias =
+ my_unique_true_boolean ? &my_small_cord : &my_big_cord;
+ absl::Cord* my_big_alias =
+ !my_unique_true_boolean ? &my_small_cord : &my_big_cord;
+
+ *my_small_alias = std::move(my_small_cord);
+ *my_big_alias = std::move(my_big_cord);
+ // my_small_cord and my_big_cord are in an unspecified but valid
+ // state, and will be correctly destroyed here.
+ }
+}
+
+TEST(Cord, StartsEndsWith) {
+ absl::Cord x(absl::string_view("abcde"));
+ absl::Cord empty("");
+
+ ASSERT_TRUE(x.StartsWith(absl::Cord("abcde")));
+ ASSERT_TRUE(x.StartsWith(absl::Cord("abc")));
+ ASSERT_TRUE(x.StartsWith(absl::Cord("")));
+ ASSERT_TRUE(empty.StartsWith(absl::Cord("")));
+ ASSERT_TRUE(x.EndsWith(absl::Cord("abcde")));
+ ASSERT_TRUE(x.EndsWith(absl::Cord("cde")));
+ ASSERT_TRUE(x.EndsWith(absl::Cord("")));
+ ASSERT_TRUE(empty.EndsWith(absl::Cord("")));
+
+ ASSERT_TRUE(!x.StartsWith(absl::Cord("xyz")));
+ ASSERT_TRUE(!empty.StartsWith(absl::Cord("xyz")));
+ ASSERT_TRUE(!x.EndsWith(absl::Cord("xyz")));
+ ASSERT_TRUE(!empty.EndsWith(absl::Cord("xyz")));
+
+ ASSERT_TRUE(x.StartsWith("abcde"));
+ ASSERT_TRUE(x.StartsWith("abc"));
+ ASSERT_TRUE(x.StartsWith(""));
+ ASSERT_TRUE(empty.StartsWith(""));
+ ASSERT_TRUE(x.EndsWith("abcde"));
+ ASSERT_TRUE(x.EndsWith("cde"));
+ ASSERT_TRUE(x.EndsWith(""));
+ ASSERT_TRUE(empty.EndsWith(""));
+
+ ASSERT_TRUE(!x.StartsWith("xyz"));
+ ASSERT_TRUE(!empty.StartsWith("xyz"));
+ ASSERT_TRUE(!x.EndsWith("xyz"));
+ ASSERT_TRUE(!empty.EndsWith("xyz"));
+}
+
+TEST(Cord, Subcord) {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ const std::string s = RandomLowercaseString(&rng, 1024);
+
+ absl::Cord a;
+ AppendWithFragments(s, &rng, &a);
+ ASSERT_EQ(s.size(), a.size());
+
+ // Check subcords of a, from a variety of interesting points.
+ std::set<size_t> positions;
+ for (int i = 0; i <= 32; ++i) {
+ positions.insert(i);
+ positions.insert(i * 32 - 1);
+ positions.insert(i * 32);
+ positions.insert(i * 32 + 1);
+ positions.insert(a.size() - i);
+ }
+ positions.insert(237);
+ positions.insert(732);
+ for (size_t pos : positions) {
+ if (pos > a.size()) continue;
+ for (size_t end_pos : positions) {
+ if (end_pos < pos || end_pos > a.size()) continue;
+ absl::Cord sa = a.Subcord(pos, end_pos - pos);
+ ASSERT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
+ std::string(sa))
+ << a;
+ }
+ }
+
+ // Do the same thing for an inline cord.
+ const std::string sh = "short";
+ absl::Cord c(sh);
+ for (size_t pos = 0; pos <= sh.size(); ++pos) {
+ for (size_t n = 0; n <= sh.size() - pos; ++n) {
+ absl::Cord sc = c.Subcord(pos, n);
+ ASSERT_EQ(sh.substr(pos, n), std::string(sc)) << c;
+ }
+ }
+
+ // Check subcords of subcords.
+ absl::Cord sa = a.Subcord(0, a.size());
+ std::string ss = s.substr(0, s.size());
+ while (sa.size() > 1) {
+ sa = sa.Subcord(1, sa.size() - 2);
+ ss = ss.substr(1, ss.size() - 2);
+ ASSERT_EQ(ss, std::string(sa)) << a;
+ if (HasFailure()) break; // halt cascade
+ }
+
+ // It is OK to ask for too much.
+ sa = a.Subcord(0, a.size() + 1);
+ EXPECT_EQ(s, std::string(sa));
+
+ // It is OK to ask for something beyond the end.
+ sa = a.Subcord(a.size() + 1, 0);
+ EXPECT_TRUE(sa.empty());
+ sa = a.Subcord(a.size() + 1, 1);
+ EXPECT_TRUE(sa.empty());
+}
+
+TEST(Cord, Swap) {
+ absl::string_view a("Dexter");
+ absl::string_view b("Mandark");
+ absl::Cord x(a);
+ absl::Cord y(b);
+ swap(x, y);
+ ASSERT_EQ(x, absl::Cord(b));
+ ASSERT_EQ(y, absl::Cord(a));
+ x.swap(y);
+ ASSERT_EQ(x, absl::Cord(a));
+ ASSERT_EQ(y, absl::Cord(b));
+}
+
+static void VerifyCopyToString(const absl::Cord& cord) {
+ std::string initially_empty;
+ absl::CopyCordToString(cord, &initially_empty);
+ EXPECT_EQ(initially_empty, cord);
+
+ constexpr size_t kInitialLength = 1024;
+ std::string has_initial_contents(kInitialLength, 'x');
+ const char* address_before_copy = has_initial_contents.data();
+ absl::CopyCordToString(cord, &has_initial_contents);
+ EXPECT_EQ(has_initial_contents, cord);
+
+ if (cord.size() <= kInitialLength) {
+ EXPECT_EQ(has_initial_contents.data(), address_before_copy)
+ << "CopyCordToString allocated new string storage; "
+ "has_initial_contents = \""
+ << has_initial_contents << "\"";
+ }
+}
+
+TEST(Cord, CopyToString) {
+ VerifyCopyToString(absl::Cord());
+ VerifyCopyToString(absl::Cord("small cord"));
+ VerifyCopyToString(
+ absl::MakeFragmentedCord({"fragmented ", "cord ", "to ", "test ",
+ "copying ", "to ", "a ", "string."}));
+}
+
+TEST(TryFlat, Empty) {
+ absl::Cord c;
+ EXPECT_EQ(c.TryFlat(), "");
+}
+
+TEST(TryFlat, Flat) {
+ absl::Cord c("hello");
+ EXPECT_EQ(c.TryFlat(), "hello");
+}
+
+TEST(TryFlat, SubstrInlined) {
+ absl::Cord c("hello");
+ c.RemovePrefix(1);
+ EXPECT_EQ(c.TryFlat(), "ello");
+}
+
+TEST(TryFlat, SubstrFlat) {
+ absl::Cord c("longer than 15 bytes");
+ c.RemovePrefix(1);
+ EXPECT_EQ(c.TryFlat(), "onger than 15 bytes");
+}
+
+TEST(TryFlat, Concat) {
+ absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
+ EXPECT_EQ(c.TryFlat(), absl::nullopt);
+}
+
+TEST(TryFlat, External) {
+ absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
+ EXPECT_EQ(c.TryFlat(), "hell");
+}
+
+TEST(TryFlat, SubstrExternal) {
+ absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
+ c.RemovePrefix(1);
+ EXPECT_EQ(c.TryFlat(), "ell");
+}
+
+TEST(TryFlat, SubstrConcat) {
+ absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
+ c.RemovePrefix(1);
+ EXPECT_EQ(c.TryFlat(), absl::nullopt);
+}
+
+static bool IsFlat(const absl::Cord& c) {
+ return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
+}
+
+static void VerifyFlatten(absl::Cord c) {
+ std::string old_contents(c);
+ absl::string_view old_flat;
+ bool already_flat_and_non_empty = IsFlat(c) && !c.empty();
+ if (already_flat_and_non_empty) {
+ old_flat = *c.chunk_begin();
+ }
+ absl::string_view new_flat = c.Flatten();
+
+ // Verify that the contents of the flattened Cord are correct.
+ EXPECT_EQ(new_flat, old_contents);
+ EXPECT_EQ(std::string(c), old_contents);
+
+ // If the Cord contained data and was already flat, verify that the data
+ // wasn't copied.
+ if (already_flat_and_non_empty) {
+ EXPECT_EQ(old_flat.data(), new_flat.data())
+ << "Allocated new memory even though the Cord was already flat.";
+ }
+
+ // Verify that the flattened Cord is in fact flat.
+ EXPECT_TRUE(IsFlat(c));
+}
+
+TEST(Cord, Flatten) {
+ VerifyFlatten(absl::Cord());
+ VerifyFlatten(absl::Cord("small cord"));
+ VerifyFlatten(absl::Cord("larger than small buffer optimization"));
+ VerifyFlatten(absl::MakeFragmentedCord({"small ", "fragmented ", "cord"}));
+
+ // Test with a cord that is longer than the largest flat buffer
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ VerifyFlatten(absl::Cord(RandomLowercaseString(&rng, 8192)));
+}
+
+// Test data
+namespace {
+class TestData {
+ private:
+ std::vector<std::string> data_;
+
+ // Return a std::string of the specified length.
+ static std::string MakeString(int length) {
+ std::string result;
+ char buf[30];
+ snprintf(buf, sizeof(buf), "(%d)", length);
+ while (result.size() < length) {
+ result += buf;
+ }
+ result.resize(length);
+ return result;
+ }
+
+ public:
+ TestData() {
+ // short strings increasing in length by one
+ for (int i = 0; i < 30; i++) {
+ data_.push_back(MakeString(i));
+ }
+
+ // strings around half kMaxFlatLength
+ static const int kMaxFlatLength = 4096 - 9;
+ static const int kHalf = kMaxFlatLength / 2;
+
+ for (int i = -10; i <= +10; i++) {
+ data_.push_back(MakeString(kHalf + i));
+ }
+
+ for (int i = -10; i <= +10; i++) {
+ data_.push_back(MakeString(kMaxFlatLength + i));
+ }
+ }
+
+ size_t size() const { return data_.size(); }
+ const std::string& data(size_t i) const { return data_[i]; }
+};
+} // namespace
+
+TEST(Cord, MultipleLengths) {
+ TestData d;
+ for (size_t i = 0; i < d.size(); i++) {
+ std::string a = d.data(i);
+
+ { // Construct from Cord
+ absl::Cord tmp(a);
+ absl::Cord x(tmp);
+ EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
+ }
+
+ { // Construct from absl::string_view
+ absl::Cord x(a);
+ EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
+ }
+
+ { // Append cord to self
+ absl::Cord self(a);
+ self.Append(self);
+ EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
+ }
+
+ { // Prepend cord to self
+ absl::Cord self(a);
+ self.Prepend(self);
+ EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
+ }
+
+ // Try to append/prepend others
+ for (size_t j = 0; j < d.size(); j++) {
+ std::string b = d.data(j);
+
+ { // CopyFrom Cord
+ absl::Cord x(a);
+ absl::Cord y(b);
+ x = y;
+ EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
+ }
+
+ { // CopyFrom absl::string_view
+ absl::Cord x(a);
+ x = b;
+ EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
+ }
+
+ { // Cord::Append(Cord)
+ absl::Cord x(a);
+ absl::Cord y(b);
+ x.Append(y);
+ EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
+ }
+
+ { // Cord::Append(absl::string_view)
+ absl::Cord x(a);
+ x.Append(b);
+ EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
+ }
+
+ { // Cord::Prepend(Cord)
+ absl::Cord x(a);
+ absl::Cord y(b);
+ x.Prepend(y);
+ EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
+ }
+
+ { // Cord::Prepend(absl::string_view)
+ absl::Cord x(a);
+ x.Prepend(b);
+ EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
+ }
+ }
+ }
+}
+
+namespace {
+
+TEST(Cord, RemoveSuffixWithExternalOrSubstring) {
+ absl::Cord cord = absl::MakeCordFromExternal(
+ "foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
+
+ EXPECT_EQ("foo bar baz", std::string(cord));
+
+ // This RemoveSuffix() will wrap the EXTERNAL node in a SUBSTRING node.
+ cord.RemoveSuffix(4);
+ EXPECT_EQ("foo bar", std::string(cord));
+
+ // This RemoveSuffix() will adjust the SUBSTRING node in-place.
+ cord.RemoveSuffix(4);
+ EXPECT_EQ("foo", std::string(cord));
+}
+
+TEST(Cord, RemoveSuffixMakesZeroLengthNode) {
+ absl::Cord c;
+ c.Append(absl::Cord(std::string(100, 'x')));
+ absl::Cord other_ref = c; // Prevent inplace appends
+ c.Append(absl::Cord(std::string(200, 'y')));
+ c.RemoveSuffix(200);
+ EXPECT_EQ(std::string(100, 'x'), std::string(c));
+}
+
+} // namespace
+
+// CordSpliceTest contributed by hendrie.
+namespace {
+
+// Create a cord with an external memory block filled with 'z'
+absl::Cord CordWithZedBlock(size_t size) {
+ char* data = new char[size];
+ if (size > 0) {
+ memset(data, 'z', size);
+ }
+ absl::Cord cord = absl::MakeCordFromExternal(
+ absl::string_view(data, size),
+ [](absl::string_view s) { delete[] s.data(); });
+ return cord;
+}
+
+// Establish that ZedBlock does what we think it does.
+TEST(CordSpliceTest, ZedBlock) {
+ absl::Cord blob = CordWithZedBlock(10);
+ EXPECT_EQ(10, blob.size());
+ std::string s;
+ absl::CopyCordToString(blob, &s);
+ EXPECT_EQ("zzzzzzzzzz", s);
+}
+
+TEST(CordSpliceTest, ZedBlock0) {
+ absl::Cord blob = CordWithZedBlock(0);
+ EXPECT_EQ(0, blob.size());
+ std::string s;
+ absl::CopyCordToString(blob, &s);
+ EXPECT_EQ("", s);
+}
+
+TEST(CordSpliceTest, ZedBlockSuffix1) {
+ absl::Cord blob = CordWithZedBlock(10);
+ EXPECT_EQ(10, blob.size());
+ absl::Cord suffix(blob);
+ suffix.RemovePrefix(9);
+ EXPECT_EQ(1, suffix.size());
+ std::string s;
+ absl::CopyCordToString(suffix, &s);
+ EXPECT_EQ("z", s);
+}
+
+// Remove all of a prefix block
+TEST(CordSpliceTest, ZedBlockSuffix0) {
+ absl::Cord blob = CordWithZedBlock(10);
+ EXPECT_EQ(10, blob.size());
+ absl::Cord suffix(blob);
+ suffix.RemovePrefix(10);
+ EXPECT_EQ(0, suffix.size());
+ std::string s;
+ absl::CopyCordToString(suffix, &s);
+ EXPECT_EQ("", s);
+}
+
+absl::Cord BigCord(size_t len, char v) {
+ std::string s(len, v);
+ return absl::Cord(s);
+}
+
+// Splice block into cord.
+absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
+ const absl::Cord& block) {
+ ABSL_RAW_CHECK(offset >= 0, "");
+ ABSL_RAW_CHECK(offset + block.size() <= blob.size(), "");
+ absl::Cord result(blob);
+ result.RemoveSuffix(blob.size() - offset);
+ result.Append(block);
+ absl::Cord suffix(blob);
+ suffix.RemovePrefix(offset + block.size());
+ result.Append(suffix);
+ ABSL_RAW_CHECK(blob.size() == result.size(), "");
+ return result;
+}
+
+// Taking an empty suffix of a block breaks appending.
+TEST(CordSpliceTest, RemoveEntireBlock1) {
+ absl::Cord zero = CordWithZedBlock(10);
+ absl::Cord suffix(zero);
+ suffix.RemovePrefix(10);
+ absl::Cord result;
+ result.Append(suffix);
+}
+
+TEST(CordSpliceTest, RemoveEntireBlock2) {
+ absl::Cord zero = CordWithZedBlock(10);
+ absl::Cord prefix(zero);
+ prefix.RemoveSuffix(10);
+ absl::Cord suffix(zero);
+ suffix.RemovePrefix(10);
+ absl::Cord result(prefix);
+ result.Append(suffix);
+}
+
+TEST(CordSpliceTest, RemoveEntireBlock3) {
+ absl::Cord blob = CordWithZedBlock(10);
+ absl::Cord block = BigCord(10, 'b');
+ blob = SpliceCord(blob, 0, block);
+}
+
+struct CordCompareTestCase {
+ template <typename LHS, typename RHS>
+ CordCompareTestCase(const LHS& lhs, const RHS& rhs)
+ : lhs_cord(lhs), rhs_cord(rhs) {}
+
+ absl::Cord lhs_cord;
+ absl::Cord rhs_cord;
+};
+
+const auto sign = [](int x) { return x == 0 ? 0 : (x > 0 ? 1 : -1); };
+
+void VerifyComparison(const CordCompareTestCase& test_case) {
+ std::string lhs_string(test_case.lhs_cord);
+ std::string rhs_string(test_case.rhs_cord);
+ int expected = sign(lhs_string.compare(rhs_string));
+ EXPECT_EQ(expected, test_case.lhs_cord.Compare(test_case.rhs_cord))
+ << "LHS=" << lhs_string << "; RHS=" << rhs_string;
+ EXPECT_EQ(expected, test_case.lhs_cord.Compare(rhs_string))
+ << "LHS=" << lhs_string << "; RHS=" << rhs_string;
+ EXPECT_EQ(-expected, test_case.rhs_cord.Compare(test_case.lhs_cord))
+ << "LHS=" << rhs_string << "; RHS=" << lhs_string;
+ EXPECT_EQ(-expected, test_case.rhs_cord.Compare(lhs_string))
+ << "LHS=" << rhs_string << "; RHS=" << lhs_string;
+}
+
+TEST(Cord, Compare) {
+ absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
+ subcord = subcord.Subcord(3, 10);
+
+ absl::Cord tmp("aaaaaaaaaaaaaaaa");
+ tmp.Append("BBBBBBBBBBBBBBBB");
+ absl::Cord concat = absl::Cord("cccccccccccccccc");
+ concat.Append("DDDDDDDDDDDDDDDD");
+ concat.Prepend(tmp);
+
+ absl::Cord concat2("aaaaaaaaaaaaa");
+ concat2.Append("aaaBBBBBBBBBBBBBBBBccccc");
+ concat2.Append("cccccccccccDDDDDDDDDDDDDD");
+ concat2.Append("DD");
+
+ std::vector<CordCompareTestCase> test_cases = {{
+ // Inline cords
+ {"abcdef", "abcdef"},
+ {"abcdef", "abcdee"},
+ {"abcdef", "abcdeg"},
+ {"bbcdef", "abcdef"},
+ {"bbcdef", "abcdeg"},
+ {"abcdefa", "abcdef"},
+ {"abcdef", "abcdefa"},
+
+ // Small flat cords
+ {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDD"},
+ {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBxccccDDDDD"},
+ {"aaaaaBBBBBcxcccDDDDD", "aaaaaBBBBBcccccDDDDD"},
+ {"aaaaaBBBBBxccccDDDDD", "aaaaaBBBBBcccccDDDDX"},
+ {"aaaaaBBBBBcccccDDDDDa", "aaaaaBBBBBcccccDDDDD"},
+ {"aaaaaBBBBBcccccDDDDD", "aaaaaBBBBBcccccDDDDDa"},
+
+ // Subcords
+ {subcord, subcord},
+ {subcord, "aaBBBBBccc"},
+ {subcord, "aaBBBBBccd"},
+ {subcord, "aaBBBBBccb"},
+ {subcord, "aaBBBBBxcb"},
+ {subcord, "aaBBBBBccca"},
+ {subcord, "aaBBBBBcc"},
+
+ // Concats
+ {concat, concat},
+ {concat,
+ "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDD"},
+ {concat,
+ "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBcccccccccccccccxDDDDDDDDDDDDDDDD"},
+ {concat,
+ "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBacccccccccccccccDDDDDDDDDDDDDDDD"},
+ {concat,
+ "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDD"},
+ {concat,
+ "aaaaaaaaaaaaaaaaBBBBBBBBBBBBBBBBccccccccccccccccDDDDDDDDDDDDDDDDe"},
+
+ {concat, concat2},
+ }};
+
+ for (const auto& tc : test_cases) {
+ VerifyComparison(tc);
+ }
+}
+
+TEST(Cord, CompareAfterAssign) {
+ absl::Cord a("aaaaaa1111111");
+ absl::Cord b("aaaaaa2222222");
+ a = "cccccc";
+ b = "cccccc";
+ EXPECT_EQ(a, b);
+ EXPECT_FALSE(a < b);
+
+ a = "aaaa";
+ b = "bbbbb";
+ a = "";
+ b = "";
+ EXPECT_EQ(a, b);
+ EXPECT_FALSE(a < b);
+}
+
+// Test CompareTo() and ComparePrefix() against string and substring
+// comparison methods from basic_string.
+static void TestCompare(const absl::Cord& c, const absl::Cord& d,
+ RandomEngine* rng) {
+ typedef std::basic_string<uint8_t> ustring;
+ ustring cs(reinterpret_cast<const uint8_t*>(std::string(c).data()), c.size());
+ ustring ds(reinterpret_cast<const uint8_t*>(std::string(d).data()), d.size());
+ // ustring comparison is ideal because we expect Cord comparisons to be
+ // based on unsigned byte comparisons regardless of whether char is signed.
+ int expected = sign(cs.compare(ds));
+ EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
+}
+
+TEST(Compare, ComparisonIsUnsigned) {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ std::uniform_int_distribution<uint32_t> uniform_uint8(0, 255);
+ char x = static_cast<char>(uniform_uint8(rng));
+ TestCompare(
+ absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x)),
+ absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
+}
+
+TEST(Compare, RandomComparisons) {
+ const int kIters = 5000;
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+
+ int n = GetUniformRandomUpTo(&rng, 5000);
+ absl::Cord a[] = {MakeExternalCord(n),
+ absl::Cord("ant"),
+ absl::Cord("elephant"),
+ absl::Cord("giraffe"),
+ absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100),
+ GetUniformRandomUpTo(&rng, 100))),
+ absl::Cord(""),
+ absl::Cord("x"),
+ absl::Cord("A"),
+ absl::Cord("B"),
+ absl::Cord("C")};
+ for (int i = 0; i < kIters; i++) {
+ absl::Cord c, d;
+ for (int j = 0; j < (i % 7) + 1; j++) {
+ c.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
+ d.Append(a[GetUniformRandomUpTo(&rng, ABSL_ARRAYSIZE(a))]);
+ }
+ std::bernoulli_distribution coin_flip(0.5);
+ TestCompare(coin_flip(rng) ? c : absl::Cord(std::string(c)),
+ coin_flip(rng) ? d : absl::Cord(std::string(d)), &rng);
+ }
+}
+
+template <typename T1, typename T2>
+void CompareOperators() {
+ const T1 a("a");
+ const T2 b("b");
+
+ EXPECT_TRUE(a == a);
+ // For pointer type (i.e. `const char*`), operator== compares the address
+ // instead of the string, so `a == const char*("a")` isn't necessarily true.
+ EXPECT_TRUE(std::is_pointer<T1>::value || a == T1("a"));
+ EXPECT_TRUE(std::is_pointer<T2>::value || a == T2("a"));
+ EXPECT_FALSE(a == b);
+
+ EXPECT_TRUE(a != b);
+ EXPECT_FALSE(a != a);
+
+ EXPECT_TRUE(a < b);
+ EXPECT_FALSE(b < a);
+
+ EXPECT_TRUE(b > a);
+ EXPECT_FALSE(a > b);
+
+ EXPECT_TRUE(a >= a);
+ EXPECT_TRUE(b >= a);
+ EXPECT_FALSE(a >= b);
+
+ EXPECT_TRUE(a <= a);
+ EXPECT_TRUE(a <= b);
+ EXPECT_FALSE(b <= a);
+}
+
+TEST(ComparisonOperators, Cord_Cord) {
+ CompareOperators<absl::Cord, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_StringPiece) {
+ CompareOperators<absl::Cord, absl::string_view>();
+}
+
+TEST(ComparisonOperators, StringPiece_Cord) {
+ CompareOperators<absl::string_view, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_string) {
+ CompareOperators<absl::Cord, std::string>();
+}
+
+TEST(ComparisonOperators, string_Cord) {
+ CompareOperators<std::string, absl::Cord>();
+}
+
+TEST(ComparisonOperators, stdstring_Cord) {
+ CompareOperators<std::string, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_stdstring) {
+ CompareOperators<absl::Cord, std::string>();
+}
+
+TEST(ComparisonOperators, charstar_Cord) {
+ CompareOperators<const char*, absl::Cord>();
+}
+
+TEST(ComparisonOperators, Cord_charstar) {
+ CompareOperators<absl::Cord, const char*>();
+}
+
+TEST(ConstructFromExternal, ReleaserInvoked) {
+ // Empty external memory means the releaser should be called immediately.
+ {
+ bool invoked = false;
+ auto releaser = [&invoked](absl::string_view) { invoked = true; };
+ {
+ auto c = absl::MakeCordFromExternal("", releaser);
+ EXPECT_TRUE(invoked);
+ }
+ }
+
+ // If the size of the data is small enough, a future constructor
+ // implementation may copy the bytes and immediately invoke the releaser
+ // instead of creating an external node. We make a large dummy std::string to
+ // make this test independent of such an optimization.
+ std::string large_dummy(2048, 'c');
+ {
+ bool invoked = false;
+ auto releaser = [&invoked](absl::string_view) { invoked = true; };
+ {
+ auto c = absl::MakeCordFromExternal(large_dummy, releaser);
+ EXPECT_FALSE(invoked);
+ }
+ EXPECT_TRUE(invoked);
+ }
+
+ {
+ bool invoked = false;
+ auto releaser = [&invoked](absl::string_view) { invoked = true; };
+ {
+ absl::Cord copy;
+ {
+ auto c = absl::MakeCordFromExternal(large_dummy, releaser);
+ copy = c;
+ EXPECT_FALSE(invoked);
+ }
+ EXPECT_FALSE(invoked);
+ }
+ EXPECT_TRUE(invoked);
+ }
+}
+
+TEST(ConstructFromExternal, CompareContents) {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+
+ for (int length = 1; length <= 2048; length *= 2) {
+ std::string data = RandomLowercaseString(&rng, length);
+ auto* external = new std::string(data);
+ auto cord =
+ absl::MakeCordFromExternal(*external, [external](absl::string_view sv) {
+ EXPECT_EQ(external->data(), sv.data());
+ EXPECT_EQ(external->size(), sv.size());
+ delete external;
+ });
+ EXPECT_EQ(data, cord);
+ }
+}
+
+TEST(ConstructFromExternal, LargeReleaser) {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ constexpr size_t kLength = 256;
+ std::string data = RandomLowercaseString(&rng, kLength);
+ std::array<char, kLength> data_array;
+ for (size_t i = 0; i < kLength; ++i) data_array[i] = data[i];
+ bool invoked = false;
+ auto releaser = [data_array, &invoked](absl::string_view data) {
+ EXPECT_EQ(data, absl::string_view(data_array.data(), data_array.size()));
+ invoked = true;
+ };
+ (void)absl::MakeCordFromExternal(data, releaser);
+ EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, FunctionPointerReleaser) {
+ static absl::string_view data("hello world");
+ static bool invoked;
+ auto* releaser =
+ static_cast<void (*)(absl::string_view)>([](absl::string_view sv) {
+ EXPECT_EQ(data, sv);
+ invoked = true;
+ });
+ invoked = false;
+ (void)absl::MakeCordFromExternal(data, releaser);
+ EXPECT_TRUE(invoked);
+
+ invoked = false;
+ (void)absl::MakeCordFromExternal(data, *releaser);
+ EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, MoveOnlyReleaser) {
+ struct Releaser {
+ explicit Releaser(bool* invoked) : invoked(invoked) {}
+ Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
+ void operator()(absl::string_view) const { *invoked = true; }
+
+ bool* invoked;
+ };
+
+ bool invoked = false;
+ (void)absl::MakeCordFromExternal("dummy", Releaser(&invoked));
+ EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, NoArgLambda) {
+ bool invoked = false;
+ (void)absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; });
+ EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, StringViewArgLambda) {
+ bool invoked = false;
+ (void)absl::MakeCordFromExternal(
+ "dummy", [&invoked](absl::string_view) { invoked = true; });
+ EXPECT_TRUE(invoked);
+}
+
+TEST(ConstructFromExternal, NonTrivialReleaserDestructor) {
+ struct Releaser {
+ explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
+ ~Releaser() { *destroyed = true; }
+ void operator()(absl::string_view) const {}
+
+ bool* destroyed;
+ };
+
+ bool destroyed = false;
+ Releaser releaser(&destroyed);
+ (void)absl::MakeCordFromExternal("dummy", releaser);
+ EXPECT_TRUE(destroyed);
+}
+
+TEST(ConstructFromExternal, ReferenceQualifierOverloads) {
+ struct Releaser {
+ void operator()(absl::string_view) & { *lvalue_invoked = true; }
+ void operator()(absl::string_view) && { *rvalue_invoked = true; }
+
+ bool* lvalue_invoked;
+ bool* rvalue_invoked;
+ };
+
+ bool lvalue_invoked = false;
+ bool rvalue_invoked = false;
+ Releaser releaser = {&lvalue_invoked, &rvalue_invoked};
+ (void)absl::MakeCordFromExternal("", releaser);
+ EXPECT_FALSE(lvalue_invoked);
+ EXPECT_TRUE(rvalue_invoked);
+ rvalue_invoked = false;
+
+ (void)absl::MakeCordFromExternal("dummy", releaser);
+ EXPECT_FALSE(lvalue_invoked);
+ EXPECT_TRUE(rvalue_invoked);
+ rvalue_invoked = false;
+
+ // NOLINTNEXTLINE: suppress clang-tidy std::move on trivially copyable type.
+ (void)absl::MakeCordFromExternal("dummy", std::move(releaser));
+ EXPECT_FALSE(lvalue_invoked);
+ EXPECT_TRUE(rvalue_invoked);
+}
+
+TEST(ExternalMemory, BasicUsage) {
+ static const char* strings[] = {"", "hello", "there"};
+ for (const char* str : strings) {
+ absl::Cord dst("(prefix)");
+ AddExternalMemory(str, &dst);
+ dst.Append("(suffix)");
+ EXPECT_EQ((std::string("(prefix)") + str + std::string("(suffix)")),
+ std::string(dst));
+ }
+}
+
+TEST(ExternalMemory, RemovePrefixSuffix) {
+ // Exhaustively try all sub-strings.
+ absl::Cord cord = MakeComposite();
+ std::string s = std::string(cord);
+ for (int offset = 0; offset <= s.size(); offset++) {
+ for (int length = 0; length <= s.size() - offset; length++) {
+ absl::Cord result(cord);
+ result.RemovePrefix(offset);
+ result.RemoveSuffix(result.size() - length);
+ EXPECT_EQ(s.substr(offset, length), std::string(result))
+ << offset << " " << length;
+ }
+ }
+}
+
+TEST(ExternalMemory, Get) {
+ absl::Cord cord("hello");
+ AddExternalMemory(" world!", &cord);
+ AddExternalMemory(" how are ", &cord);
+ cord.Append(" you?");
+ std::string s = std::string(cord);
+ for (int i = 0; i < s.size(); i++) {
+ EXPECT_EQ(s[i], cord[i]);
+ }
+}
+
+// CordMemoryUsage tests verify the correctness of the EstimatedMemoryUsage()
+// These tests take into account that the reported memory usage is approximate
+// and non-deterministic. For all tests, We verify that the reported memory
+// usage is larger than `size()`, and less than `size() * 1.5` as a cord should
+// never reserve more 'extra' capacity than half of its size as it grows.
+// Additionally we have some whiteboxed expectations based on our knowledge of
+// the layout and size of empty and inlined cords, and flat nodes.
+
+TEST(CordMemoryUsage, Empty) {
+ EXPECT_EQ(sizeof(absl::Cord), absl::Cord().EstimatedMemoryUsage());
+}
+
+TEST(CordMemoryUsage, Embedded) {
+ absl::Cord a("hello");
+ EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
+}
+
+TEST(CordMemoryUsage, EmbeddedAppend) {
+ absl::Cord a("a");
+ absl::Cord b("bcd");
+ EXPECT_EQ(b.EstimatedMemoryUsage(), sizeof(absl::Cord));
+ a.Append(b);
+ EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
+}
+
+TEST(CordMemoryUsage, ExternalMemory) {
+ static const int kLength = 1000;
+ absl::Cord cord;
+ AddExternalMemory(std::string(kLength, 'x'), &cord);
+ EXPECT_GT(cord.EstimatedMemoryUsage(), kLength);
+ EXPECT_LE(cord.EstimatedMemoryUsage(), kLength * 1.5);
+}
+
+TEST(CordMemoryUsage, Flat) {
+ static const int kLength = 125;
+ absl::Cord a(std::string(kLength, 'a'));
+ EXPECT_GT(a.EstimatedMemoryUsage(), kLength);
+ EXPECT_LE(a.EstimatedMemoryUsage(), kLength * 1.5);
+}
+
+TEST(CordMemoryUsage, AppendFlat) {
+ using absl::strings_internal::CordTestAccess;
+ absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
+ size_t length = a.EstimatedMemoryUsage();
+ a.Append(std::string(CordTestAccess::MaxFlatLength(), 'b'));
+ size_t delta = a.EstimatedMemoryUsage() - length;
+ EXPECT_GT(delta, CordTestAccess::MaxFlatLength());
+ EXPECT_LE(delta, CordTestAccess::MaxFlatLength() * 1.5);
+}
+
+// Regtest for a change that had to be rolled back because it expanded out
+// of the InlineRep too soon, which was observable through MemoryUsage().
+TEST(CordMemoryUsage, InlineRep) {
+ constexpr size_t kMaxInline = 15; // Cord::InlineRep::N
+ const std::string small_string(kMaxInline, 'x');
+ absl::Cord c1(small_string);
+
+ absl::Cord c2;
+ c2.Append(small_string);
+ EXPECT_EQ(c1, c2);
+ EXPECT_EQ(c1.EstimatedMemoryUsage(), c2.EstimatedMemoryUsage());
+}
+
+} // namespace
+
+// Regtest for 7510292 (fix a bug introduced by 7465150)
+TEST(Cord, Concat_Append) {
+ // Create a rep of type CONCAT
+ absl::Cord s1("foobarbarbarbarbar");
+ s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
+ size_t size = s1.size();
+
+ // Create a copy of s1 and append to it.
+ absl::Cord s2 = s1;
+ s2.Append("x");
+
+ // 7465150 modifies s1 when it shouldn't.
+ EXPECT_EQ(s1.size(), size);
+ EXPECT_EQ(s2.size(), size + 1);
+}
+
+TEST(MakeFragmentedCord, MakeFragmentedCordFromInitializerList) {
+ absl::Cord fragmented =
+ absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
+
+ EXPECT_EQ("A fragmented Cord", fragmented);
+
+ auto chunk_it = fragmented.chunk_begin();
+
+ ASSERT_TRUE(chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("A ", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("fragmented ", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("Cord", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
+}
+
+TEST(MakeFragmentedCord, MakeFragmentedCordFromVector) {
+ std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
+ absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
+
+ EXPECT_EQ("A fragmented Cord", fragmented);
+
+ auto chunk_it = fragmented.chunk_begin();
+
+ ASSERT_TRUE(chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("A ", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("fragmented ", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it != fragmented.chunk_end());
+ EXPECT_EQ("Cord", *chunk_it);
+
+ ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
+}
+
+TEST(CordChunkIterator, Traits) {
+ static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,
+ "");
+ static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, "");
+
+ // Move semantics to satisfy swappable via std::swap
+ static_assert(std::is_move_constructible<absl::Cord::ChunkIterator>::value,
+ "");
+ static_assert(std::is_move_assignable<absl::Cord::ChunkIterator>::value, "");
+
+ static_assert(
+ std::is_same<
+ std::iterator_traits<absl::Cord::ChunkIterator>::iterator_category,
+ std::input_iterator_tag>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::value_type,
+ absl::string_view>::value,
+ "");
+ static_assert(
+ std::is_same<
+ std::iterator_traits<absl::Cord::ChunkIterator>::difference_type,
+ ptrdiff_t>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::pointer,
+ const absl::string_view*>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::ChunkIterator>::reference,
+ absl::string_view>::value,
+ "");
+}
+
+static void VerifyChunkIterator(const absl::Cord& cord,
+ size_t expected_chunks) {
+ EXPECT_EQ(cord.chunk_begin() == cord.chunk_end(), cord.empty()) << cord;
+ EXPECT_EQ(cord.chunk_begin() != cord.chunk_end(), !cord.empty());
+
+ absl::Cord::ChunkRange range = cord.Chunks();
+ EXPECT_EQ(range.begin() == range.end(), cord.empty());
+ EXPECT_EQ(range.begin() != range.end(), !cord.empty());
+
+ std::string content(cord);
+ size_t pos = 0;
+ auto pre_iter = cord.chunk_begin(), post_iter = cord.chunk_begin();
+ size_t n_chunks = 0;
+ while (pre_iter != cord.chunk_end() && post_iter != cord.chunk_end()) {
+ EXPECT_FALSE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test ==
+ EXPECT_FALSE(post_iter == cord.chunk_end()); // NOLINT
+
+ EXPECT_EQ(pre_iter, post_iter);
+ EXPECT_EQ(*pre_iter, *post_iter);
+
+ EXPECT_EQ(pre_iter->data(), (*pre_iter).data());
+ EXPECT_EQ(pre_iter->size(), (*pre_iter).size());
+
+ absl::string_view chunk = *pre_iter;
+ EXPECT_FALSE(chunk.empty());
+ EXPECT_LE(pos + chunk.size(), content.size());
+ EXPECT_EQ(absl::string_view(content.c_str() + pos, chunk.size()), chunk);
+
+ int n_equal_iterators = 0;
+ for (absl::Cord::ChunkIterator it = range.begin(); it != range.end();
+ ++it) {
+ n_equal_iterators += static_cast<int>(it == pre_iter);
+ }
+ EXPECT_EQ(n_equal_iterators, 1);
+
+ ++pre_iter;
+ EXPECT_EQ(*post_iter++, chunk);
+
+ pos += chunk.size();
+ ++n_chunks;
+ }
+ EXPECT_EQ(expected_chunks, n_chunks);
+ EXPECT_EQ(pos, content.size());
+ EXPECT_TRUE(pre_iter == cord.chunk_end()); // NOLINT: explicitly test ==
+ EXPECT_TRUE(post_iter == cord.chunk_end()); // NOLINT
+}
+
+TEST(CordChunkIterator, Operations) {
+ absl::Cord empty_cord;
+ VerifyChunkIterator(empty_cord, 0);
+
+ absl::Cord small_buffer_cord("small cord");
+ VerifyChunkIterator(small_buffer_cord, 1);
+
+ absl::Cord flat_node_cord("larger than small buffer optimization");
+ VerifyChunkIterator(flat_node_cord, 1);
+
+ VerifyChunkIterator(
+ absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
+ "testing ", "chunk ", "iterations."}),
+ 8);
+
+ absl::Cord reused_nodes_cord(std::string(40, 'c'));
+ reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'b')));
+ reused_nodes_cord.Prepend(absl::Cord(std::string(40, 'a')));
+ size_t expected_chunks = 3;
+ for (int i = 0; i < 8; ++i) {
+ reused_nodes_cord.Prepend(reused_nodes_cord);
+ expected_chunks *= 2;
+ VerifyChunkIterator(reused_nodes_cord, expected_chunks);
+ }
+
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
+ absl::Cord subcords;
+ for (int i = 0; i < 128; ++i) subcords.Prepend(flat_cord.Subcord(i, 128));
+ VerifyChunkIterator(subcords, 128);
+}
+
+TEST(CordCharIterator, Traits) {
+ static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,
+ "");
+ static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, "");
+
+ // Move semantics to satisfy swappable via std::swap
+ static_assert(std::is_move_constructible<absl::Cord::CharIterator>::value,
+ "");
+ static_assert(std::is_move_assignable<absl::Cord::CharIterator>::value, "");
+
+ static_assert(
+ std::is_same<
+ std::iterator_traits<absl::Cord::CharIterator>::iterator_category,
+ std::input_iterator_tag>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::CharIterator>::value_type,
+ char>::value,
+ "");
+ static_assert(
+ std::is_same<
+ std::iterator_traits<absl::Cord::CharIterator>::difference_type,
+ ptrdiff_t>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::CharIterator>::pointer,
+ const char*>::value,
+ "");
+ static_assert(
+ std::is_same<std::iterator_traits<absl::Cord::CharIterator>::reference,
+ const char&>::value,
+ "");
+}
+
+static void VerifyCharIterator(const absl::Cord& cord) {
+ EXPECT_EQ(cord.char_begin() == cord.char_end(), cord.empty());
+ EXPECT_EQ(cord.char_begin() != cord.char_end(), !cord.empty());
+
+ absl::Cord::CharRange range = cord.Chars();
+ EXPECT_EQ(range.begin() == range.end(), cord.empty());
+ EXPECT_EQ(range.begin() != range.end(), !cord.empty());
+
+ size_t i = 0;
+ absl::Cord::CharIterator pre_iter = cord.char_begin();
+ absl::Cord::CharIterator post_iter = cord.char_begin();
+ std::string content(cord);
+ while (pre_iter != cord.char_end() && post_iter != cord.char_end()) {
+ EXPECT_FALSE(pre_iter == cord.char_end()); // NOLINT: explicitly test ==
+ EXPECT_FALSE(post_iter == cord.char_end()); // NOLINT
+
+ EXPECT_LT(i, cord.size());
+ EXPECT_EQ(content[i], *pre_iter);
+
+ EXPECT_EQ(pre_iter, post_iter);
+ EXPECT_EQ(*pre_iter, *post_iter);
+ EXPECT_EQ(&*pre_iter, &*post_iter);
+
+ EXPECT_EQ(&*pre_iter, pre_iter.operator->());
+
+ const char* character_address = &*pre_iter;
+ absl::Cord::CharIterator copy = pre_iter;
+ ++copy;
+ EXPECT_EQ(character_address, &*pre_iter);
+
+ int n_equal_iterators = 0;
+ for (absl::Cord::CharIterator it = range.begin(); it != range.end(); ++it) {
+ n_equal_iterators += static_cast<int>(it == pre_iter);
+ }
+ EXPECT_EQ(n_equal_iterators, 1);
+
+ absl::Cord::CharIterator advance_iter = range.begin();
+ absl::Cord::Advance(&advance_iter, i);
+ EXPECT_EQ(pre_iter, advance_iter);
+
+ advance_iter = range.begin();
+ EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, i), cord.Subcord(0, i));
+ EXPECT_EQ(pre_iter, advance_iter);
+
+ advance_iter = pre_iter;
+ absl::Cord::Advance(&advance_iter, cord.size() - i);
+ EXPECT_EQ(range.end(), advance_iter);
+
+ advance_iter = pre_iter;
+ EXPECT_EQ(absl::Cord::AdvanceAndRead(&advance_iter, cord.size() - i),
+ cord.Subcord(i, cord.size() - i));
+ EXPECT_EQ(range.end(), advance_iter);
+
+ ++i;
+ ++pre_iter;
+ post_iter++;
+ }
+ EXPECT_EQ(i, cord.size());
+ EXPECT_TRUE(pre_iter == cord.char_end()); // NOLINT: explicitly test ==
+ EXPECT_TRUE(post_iter == cord.char_end()); // NOLINT
+
+ absl::Cord::CharIterator zero_advanced_end = cord.char_end();
+ absl::Cord::Advance(&zero_advanced_end, 0);
+ EXPECT_EQ(zero_advanced_end, cord.char_end());
+
+ absl::Cord::CharIterator it = cord.char_begin();
+ for (absl::string_view chunk : cord.Chunks()) {
+ while (!chunk.empty()) {
+ EXPECT_EQ(absl::Cord::ChunkRemaining(it), chunk);
+ chunk.remove_prefix(1);
+ ++it;
+ }
+ }
+}
+
+TEST(CordCharIterator, Operations) {
+ absl::Cord empty_cord;
+ VerifyCharIterator(empty_cord);
+
+ absl::Cord small_buffer_cord("small cord");
+ VerifyCharIterator(small_buffer_cord);
+
+ absl::Cord flat_node_cord("larger than small buffer optimization");
+ VerifyCharIterator(flat_node_cord);
+
+ VerifyCharIterator(
+ absl::MakeFragmentedCord({"a ", "small ", "fragmented ", "cord ", "for ",
+ "testing ", "character ", "iteration."}));
+
+ absl::Cord reused_nodes_cord("ghi");
+ reused_nodes_cord.Prepend(absl::Cord("def"));
+ reused_nodes_cord.Prepend(absl::Cord("abc"));
+ for (int i = 0; i < 4; ++i) {
+ reused_nodes_cord.Prepend(reused_nodes_cord);
+ VerifyCharIterator(reused_nodes_cord);
+ }
+
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
+ absl::Cord flat_cord(RandomLowercaseString(&rng, 256));
+ absl::Cord subcords;
+ for (int i = 0; i < 4; ++i) subcords.Prepend(flat_cord.Subcord(16 * i, 128));
+ VerifyCharIterator(subcords);
+}
+
+TEST(Cord, StreamingOutput) {
+ absl::Cord c =
+ absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
+ std::stringstream output;
+ output << c;
+ EXPECT_EQ("A small fragmented Cord.", output.str());
+}
+
+TEST(Cord, ForEachChunk) {
+ for (int num_elements : {1, 10, 200}) {
+ SCOPED_TRACE(num_elements);
+ std::vector<std::string> cord_chunks;
+ for (int i = 0; i < num_elements; ++i) {
+ cord_chunks.push_back(absl::StrCat("[", i, "]"));
+ }
+ absl::Cord c = absl::MakeFragmentedCord(cord_chunks);
+
+ std::vector<std::string> iterated_chunks;
+ absl::CordTestPeer::ForEachChunk(c,
+ [&iterated_chunks](absl::string_view sv) {
+ iterated_chunks.emplace_back(sv);
+ });
+ EXPECT_EQ(iterated_chunks, cord_chunks);
+ }
+}
+
+TEST(Cord, SmallBufferAssignFromOwnData) {
+ constexpr size_t kMaxInline = 15;
+ std::string contents = "small buff cord";
+ EXPECT_EQ(contents.size(), kMaxInline);
+ for (size_t pos = 0; pos < contents.size(); ++pos) {
+ for (size_t count = contents.size() - pos; count > 0; --count) {
+ absl::Cord c(contents);
+ absl::string_view flat = c.Flatten();
+ c = flat.substr(pos, count);
+ EXPECT_EQ(c, contents.substr(pos, count))
+ << "pos = " << pos << "; count = " << count;
+ }
+ }
+}
+
+TEST(Cord, Format) {
+ absl::Cord c;
+ absl::Format(&c, "There were %04d little %s.", 3, "pigs");
+ EXPECT_EQ(c, "There were 0003 little pigs.");
+ absl::Format(&c, "And %-3llx bad wolf!", 1);
+ EXPECT_EQ(c, "There were 0003 little pigs.And 1 bad wolf!");
+}
+
+TEST(CordDeathTest, Hardening) {
+ absl::Cord cord("hello");
+ // These statement should abort the program in all builds modes.
+ EXPECT_DEATH_IF_SUPPORTED(cord.RemovePrefix(6), "");
+ EXPECT_DEATH_IF_SUPPORTED(cord.RemoveSuffix(6), "");
+
+ bool test_hardening = false;
+ ABSL_HARDENING_ASSERT([&]() {
+ // This only runs when ABSL_HARDENING_ASSERT is active.
+ test_hardening = true;
+ return true;
+ }());
+ if (!test_hardening) return;
+
+ EXPECT_DEATH_IF_SUPPORTED(cord[5], "");
+ EXPECT_DEATH_IF_SUPPORTED(*cord.chunk_end(), "");
+ EXPECT_DEATH_IF_SUPPORTED(static_cast<void>(cord.chunk_end()->empty()), "");
+ EXPECT_DEATH_IF_SUPPORTED(++cord.chunk_end(), "");
+}
+
+class AfterExitCordTester {
+ public:
+ bool Set(absl::Cord* cord, absl::string_view expected) {
+ cord_ = cord;
+ expected_ = expected;
+ return true;
+ }
+
+ ~AfterExitCordTester() {
+ EXPECT_EQ(*cord_, expected_);
+ }
+ private:
+ absl::Cord* cord_;
+ absl::string_view expected_;
+};
+
+template <typename Str>
+void TestConstinitConstructor(Str) {
+ const auto expected = Str::value;
+ // Defined before `cord` to be destroyed after it.
+ static AfterExitCordTester exit_tester; // NOLINT
+ ABSL_CONST_INIT static absl::Cord cord(Str{}); // NOLINT
+ static bool init_exit_tester = exit_tester.Set(&cord, expected);
+ (void)init_exit_tester;
+
+ EXPECT_EQ(cord, expected);
+ // Copy the object and test the copy, and the original.
+ {
+ absl::Cord copy = cord;
+ EXPECT_EQ(copy, expected);
+ }
+ // The original still works
+ EXPECT_EQ(cord, expected);
+
+ // Try making adding more structure to the tree.
+ {
+ absl::Cord copy = cord;
+ std::string expected_copy(expected);
+ for (int i = 0; i < 10; ++i) {
+ copy.Append(cord);
+ absl::StrAppend(&expected_copy, expected);
+ EXPECT_EQ(copy, expected_copy);
+ }
+ }
+
+ // Make sure we are using the right branch during constant evaluation.
+ EXPECT_EQ(absl::CordTestPeer::IsTree(cord), cord.size() >= 16);
+
+ for (int i = 0; i < 10; ++i) {
+ // Make a few more Cords from the same global rep.
+ // This tests what happens when the refcount for it gets below 1.
+ EXPECT_EQ(expected, absl::Cord(Str{}));
+ }
+}
+
+constexpr int SimpleStrlen(const char* p) {
+ return *p ? 1 + SimpleStrlen(p + 1) : 0;
+}
+
+struct ShortView {
+ constexpr absl::string_view operator()() const {
+ return absl::string_view("SSO string", SimpleStrlen("SSO string"));
+ }
+};
+
+struct LongView {
+ constexpr absl::string_view operator()() const {
+ return absl::string_view("String that does not fit SSO.",
+ SimpleStrlen("String that does not fit SSO."));
+ }
+};
+
+
+TEST(Cord, ConstinitConstructor) {
+ TestConstinitConstructor(
+ absl::strings_internal::MakeStringConstant(ShortView{}));
+ TestConstinitConstructor(
+ absl::strings_internal::MakeStringConstant(LongView{}));
+}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test_helpers.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test_helpers.h
new file mode 100644
index 00000000000..f1036e3b138
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/cord_test_helpers.h
@@ -0,0 +1,60 @@
+//
+// 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 "absl/strings/cord.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// 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/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.cc
index 8d8b00b2001..18b20b83fd3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,6 +26,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/unaligned_access.h"
#include "absl/strings/internal/char_map.h"
+#include "absl/strings/internal/escaping.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/internal/utf8.h"
#include "absl/strings/str_cat.h"
@@ -33,29 +34,9 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
-// Digit conversion.
-constexpr char kHexChar[] = "0123456789abcdef";
-
-constexpr char kHexTable[513] =
- "000102030405060708090a0b0c0d0e0f"
- "101112131415161718191a1b1c1d1e1f"
- "202122232425262728292a2b2c2d2e2f"
- "303132333435363738393a3b3c3d3e3f"
- "404142434445464748494a4b4c4d4e4f"
- "505152535455565758595a5b5c5d5e5f"
- "606162636465666768696a6b6c6d6e6f"
- "707172737475767778797a7b7c7d7e7f"
- "808182838485868788898a8b8c8d8e8f"
- "909192939495969798999a9b9c9d9e9f"
- "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
- "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
- "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
- "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
- "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
- "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
-
// These are used for the leave_nulls_escaped argument to CUnescapeInternal().
constexpr bool kUnescapeNulls = false;
@@ -156,7 +137,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
// Copy the escape sequence for the null character
const ptrdiff_t octal_size = p + 1 - octal_start;
*d++ = '\\';
- memcpy(d, octal_start, octal_size);
+ memmove(d, octal_start, octal_size);
d += octal_size;
break;
}
@@ -179,7 +160,8 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
ch = (ch << 4) + hex_digit_to_int(*++p);
if (ch > 0xFF) {
if (error) {
- *error = "Value of \\" + std::string(hex_start, p + 1 - hex_start) +
+ *error = "Value of \\" +
+ std::string(hex_start, p + 1 - hex_start) +
" exceeds 0xff";
}
return false;
@@ -188,7 +170,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
// Copy the escape sequence for the null character
const ptrdiff_t hex_size = p + 1 - hex_start;
*d++ = '\\';
- memcpy(d, hex_start, hex_size);
+ memmove(d, hex_start, hex_size);
d += hex_size;
break;
}
@@ -221,7 +203,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
if ((rune == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
*d++ = '\\';
- memcpy(d, hex_start, 5); // u0000
+ memmove(d, hex_start, 5); // u0000
d += 5;
break;
}
@@ -269,7 +251,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
if ((rune == 0) && leave_nulls_escaped) {
// Copy the escape sequence for the null character
*d++ = '\\';
- memcpy(d, hex_start, 9); // U00000000
+ memmove(d, hex_start, 9); // U00000000
d += 9;
break;
}
@@ -294,7 +276,7 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
// ----------------------------------------------------------------------
// CUnescapeInternal()
//
-// Same as above but uses a C++ string for output. 'source' and 'dest'
+// Same as above but uses a std::string for output. 'source' and 'dest'
// may be the same.
// ----------------------------------------------------------------------
bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
@@ -324,7 +306,8 @@ bool CUnescapeInternal(absl::string_view source, bool leave_nulls_escaped,
//
// Escaped chars: \n, \r, \t, ", ', \, and !absl::ascii_isprint().
// ----------------------------------------------------------------------
-std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe) {
+std::string CEscapeInternal(absl::string_view src, bool use_hex,
+ bool utf8_safe) {
std::string dest;
bool last_hex_escape = false; // true if last output char was \xNN.
@@ -346,14 +329,14 @@ std::string CEscapeInternal(absl::string_view src, bool use_hex, bool utf8_safe)
(last_hex_escape && absl::ascii_isxdigit(c)))) {
if (use_hex) {
dest.append("\\" "x");
- dest.push_back(kHexChar[c / 16]);
- dest.push_back(kHexChar[c % 16]);
+ dest.push_back(numbers_internal::kHexChar[c / 16]);
+ dest.push_back(numbers_internal::kHexChar[c % 16]);
is_hex_escape = true;
} else {
dest.append("\\");
- dest.push_back(kHexChar[c / 64]);
- dest.push_back(kHexChar[(c % 64) / 8]);
- dest.push_back(kHexChar[c % 8]);
+ dest.push_back(numbers_internal::kHexChar[c / 64]);
+ dest.push_back(numbers_internal::kHexChar[(c % 64) / 8]);
+ dest.push_back(numbers_internal::kHexChar[c % 8]);
}
} else {
dest.push_back(c);
@@ -467,7 +450,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
// The GET_INPUT macro gets the next input character, skipping
// over any whitespace, and stopping when we reach the end of the
- // std::string or when we read any non-data character. The arguments are
+ // string or when we read any non-data character. The arguments are
// an arbitrary identifier (used as a label for goto) and the number
// of data bytes that must remain in the input to avoid aborting the
// loop.
@@ -490,18 +473,18 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
if (dest) {
// This loop consumes 4 input bytes and produces 3 output bytes
// per iteration. We can't know at the start that there is enough
- // data left in the std::string for a full iteration, so the loop may
+ // data left in the string for a full iteration, so the loop may
// break out in the middle; if so 'state' will be set to the
// number of input bytes read.
while (szsrc >= 4) {
// We'll start by optimistically assuming that the next four
- // bytes of the std::string (src[0..3]) are four good data bytes
+ // bytes of the string (src[0..3]) are four good data bytes
// (that is, no nulls, whitespace, padding chars, or illegal
// chars). We need to test src[0..2] for nulls individually
// before constructing temp to preserve the property that we
- // never read past a null in the std::string (no matter how long
- // szsrc claims the std::string is).
+ // never read past a null in the string (no matter how long
+ // szsrc claims the string is).
if (!src[0] || !src[1] || !src[2] ||
((temp = ((unsigned(unbase64[src[0]]) << 18) |
@@ -526,7 +509,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
temp = (temp << 6) | decode;
} else {
// We really did have four good data bytes, so advance four
- // characters in the std::string.
+ // characters in the string.
szsrc -= 4;
src += 4;
@@ -661,7 +644,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
state);
}
- // The remainder of the std::string should be all whitespace, mixed with
+ // The remainder of the string should be all whitespace, mixed with
// exactly 0 equals signs, or exactly 'expected_equals' equals
// signs. (Always accepting 0 equals signs is an Abseil extension
// not covered in the RFC, as is accepting dot as the pad character.)
@@ -782,180 +765,13 @@ constexpr signed char kUnWebSafeBase64[] = {
};
/* clang-format on */
-size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
- // Base64 encodes three bytes of input at a time. If the input is not
- // divisible by three, we pad as appropriate.
- //
- // (from http://tools.ietf.org/html/rfc3548)
- // Special processing is performed if fewer than 24 bits are available
- // at the end of the data being encoded. A full encoding quantum is
- // always completed at the end of a quantity. When fewer than 24 input
- // bits are available in an input group, zero bits are added (on the
- // right) to form an integral number of 6-bit groups. Padding at the
- // end of the data is performed using the '=' character. Since all base
- // 64 input is an integral number of octets, only the following cases
- // can arise:
-
- // Base64 encodes each three bytes of input into four bytes of output.
- size_t len = (input_len / 3) * 4;
-
- if (input_len % 3 == 0) {
- // (from http://tools.ietf.org/html/rfc3548)
- // (1) the final quantum of encoding input is an integral multiple of 24
- // bits; here, the final unit of encoded output will be an integral
- // multiple of 4 characters with no "=" padding,
- } else if (input_len % 3 == 1) {
- // (from http://tools.ietf.org/html/rfc3548)
- // (2) the final quantum of encoding input is exactly 8 bits; here, the
- // final unit of encoded output will be two characters followed by two
- // "=" padding characters, or
- len += 2;
- if (do_padding) {
- len += 2;
- }
- } else { // (input_len % 3 == 2)
- // (from http://tools.ietf.org/html/rfc3548)
- // (3) the final quantum of encoding input is exactly 16 bits; here, the
- // final unit of encoded output will be three characters followed by one
- // "=" padding character.
- len += 3;
- if (do_padding) {
- len += 1;
- }
- }
-
- assert(len >= input_len); // make sure we didn't overflow
- return len;
-}
-
-size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
- size_t szdest, const char* base64,
- bool do_padding) {
- static const char kPad64 = '=';
-
- if (szsrc * 4 > szdest * 3) return 0;
-
- char* cur_dest = dest;
- const unsigned char* cur_src = src;
-
- char* const limit_dest = dest + szdest;
- const unsigned char* const limit_src = src + szsrc;
-
- // Three bytes of data encodes to four characters of cyphertext.
- // So we can pump through three-byte chunks atomically.
- if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3
- while (cur_src < limit_src - 3) { // as long as we have >= 32 bits
- uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
-
- cur_dest[0] = base64[in >> 18];
- in &= 0x3FFFF;
- cur_dest[1] = base64[in >> 12];
- in &= 0xFFF;
- cur_dest[2] = base64[in >> 6];
- in &= 0x3F;
- cur_dest[3] = base64[in];
-
- cur_dest += 4;
- cur_src += 3;
- }
- }
- // To save time, we didn't update szdest or szsrc in the loop. So do it now.
- szdest = limit_dest - cur_dest;
- szsrc = limit_src - cur_src;
-
- /* now deal with the tail (<=3 bytes) */
- switch (szsrc) {
- case 0:
- // Nothing left; nothing more to do.
- break;
- case 1: {
- // One byte left: this encodes to two characters, and (optionally)
- // two pad characters to round out the four-character cypherblock.
- if (szdest < 2) return 0;
- uint32_t in = cur_src[0];
- cur_dest[0] = base64[in >> 2];
- in &= 0x3;
- cur_dest[1] = base64[in << 4];
- cur_dest += 2;
- szdest -= 2;
- if (do_padding) {
- if (szdest < 2) return 0;
- cur_dest[0] = kPad64;
- cur_dest[1] = kPad64;
- cur_dest += 2;
- szdest -= 2;
- }
- break;
- }
- case 2: {
- // Two bytes left: this encodes to three characters, and (optionally)
- // one pad character to round out the four-character cypherblock.
- if (szdest < 3) return 0;
- uint32_t in = absl::big_endian::Load16(cur_src);
- cur_dest[0] = base64[in >> 10];
- in &= 0x3FF;
- cur_dest[1] = base64[in >> 4];
- in &= 0x00F;
- cur_dest[2] = base64[in << 2];
- cur_dest += 3;
- szdest -= 3;
- if (do_padding) {
- if (szdest < 1) return 0;
- cur_dest[0] = kPad64;
- cur_dest += 1;
- szdest -= 1;
- }
- break;
- }
- case 3: {
- // Three bytes left: same as in the big loop above. We can't do this in
- // the loop because the loop above always reads 4 bytes, and the fourth
- // byte is past the end of the input.
- if (szdest < 4) return 0;
- uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
- cur_dest[0] = base64[in >> 18];
- in &= 0x3FFFF;
- cur_dest[1] = base64[in >> 12];
- in &= 0xFFF;
- cur_dest[2] = base64[in >> 6];
- in &= 0x3F;
- cur_dest[3] = base64[in];
- cur_dest += 4;
- szdest -= 4;
- break;
- }
- default:
- // Should not be reached: blocks of 4 bytes are handled
- // in the while loop before this switch statement.
- ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
- break;
- }
- return (cur_dest - dest);
-}
-
-constexpr char kBase64Chars[] =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
constexpr char kWebSafeBase64Chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
template <typename String>
-void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
- bool do_padding, const char* base64_chars) {
- const size_t calc_escaped_size =
- CalculateBase64EscapedLenInternal(szsrc, do_padding);
- strings_internal::STLStringResizeUninitialized(dest, calc_escaped_size);
-
- const size_t escaped_len = Base64EscapeInternal(
- src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
- assert(calc_escaped_size == escaped_len);
- dest->erase(escaped_len);
-}
-
-template <typename String>
bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
const signed char* unbase64) {
- // Determine the size of the output std::string. Base64 encodes every 3 bytes into
+ // Determine the size of the output string. Base64 encodes every 3 bytes into
// 4 characters. any leftover chars are added directly for good measure.
// This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548
const size_t dest_len = 3 * (slen / 4) + (slen % 4);
@@ -963,7 +779,7 @@ bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
strings_internal::STLStringResizeUninitialized(dest, dest_len);
// We are getting the destination buffer by getting the beginning of the
- // std::string and converting it into a char *.
+ // string and converting it into a char *.
size_t len;
const bool ok =
Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
@@ -980,7 +796,7 @@ bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
}
/* clang-format off */
-constexpr char kHexValue[256] = {
+constexpr char kHexValueLenient[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -996,8 +812,9 @@ constexpr char kHexValue[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
+
/* clang-format on */
// This is a templated function so that T can be either a char*
@@ -1006,17 +823,18 @@ constexpr char kHexValue[256] = {
template <typename T>
void HexStringToBytesInternal(const char* from, T to, ptrdiff_t num) {
for (int i = 0; i < num; i++) {
- to[i] = (kHexValue[from[i * 2] & 0xFF] << 4) +
- (kHexValue[from[i * 2 + 1] & 0xFF]);
+ to[i] = (kHexValueLenient[from[i * 2] & 0xFF] << 4) +
+ (kHexValueLenient[from[i * 2 + 1] & 0xFF]);
}
}
-// This is a templated function so that T can be either a char* or a string.
+// This is a templated function so that T can be either a char* or a
+// std::string.
template <typename T>
void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
auto dest_ptr = &dest[0];
for (auto src_ptr = src; src_ptr != (src + num); ++src_ptr, dest_ptr += 2) {
- const char* hex_p = &kHexTable[*src_ptr * 2];
+ const char* hex_p = &numbers_internal::kHexTable[*src_ptr * 2];
std::copy(hex_p, hex_p + 2, dest_ptr);
}
}
@@ -1028,7 +846,8 @@ void BytesToHexStringInternal(const unsigned char* src, T dest, ptrdiff_t num) {
//
// See CUnescapeInternal() for implementation details.
// ----------------------------------------------------------------------
-bool CUnescape(absl::string_view source, std::string* dest, std::string* error) {
+bool CUnescape(absl::string_view source, std::string* dest,
+ std::string* error) {
return CUnescapeInternal(source, kUnescapeNulls, dest, error);
}
@@ -1051,10 +870,10 @@ std::string Utf8SafeCHexEscape(absl::string_view src) {
}
// ----------------------------------------------------------------------
-// ptrdiff_t Base64Unescape() - base64 decoder
-// ptrdiff_t Base64Escape() - base64 encoder
-// ptrdiff_t WebSafeBase64Unescape() - Google's variation of base64 decoder
-// ptrdiff_t WebSafeBase64Escape() - Google's variation of base64 encoder
+// Base64Unescape() - base64 decoder
+// Base64Escape() - base64 encoder
+// WebSafeBase64Unescape() - Google's variation of base64 decoder
+// WebSafeBase64Escape() - Google's variation of base64 encoder
//
// Check out
// http://tools.ietf.org/html/rfc2045 for formal description, but what we
@@ -1083,13 +902,31 @@ bool WebSafeBase64Unescape(absl::string_view src, std::string* dest) {
}
void Base64Escape(absl::string_view src, std::string* dest) {
- Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
- src.size(), dest, true, kBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+ true, strings_internal::kBase64Chars);
}
void WebSafeBase64Escape(absl::string_view src, std::string* dest) {
- Base64EscapeInternal(reinterpret_cast<const unsigned char*>(src.data()),
- src.size(), dest, false, kWebSafeBase64Chars);
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), dest,
+ false, kWebSafeBase64Chars);
+}
+
+std::string Base64Escape(absl::string_view src) {
+ std::string dest;
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+ true, strings_internal::kBase64Chars);
+ return dest;
+}
+
+std::string WebSafeBase64Escape(absl::string_view src) {
+ std::string dest;
+ strings_internal::Base64EscapeInternal(
+ reinterpret_cast<const unsigned char*>(src.data()), src.size(), &dest,
+ false, kWebSafeBase64Chars);
+ return dest;
}
std::string HexStringToBytes(absl::string_view from) {
@@ -1108,4 +945,5 @@ std::string BytesToHexString(absl::string_view from) {
return result;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.h
index 296597304e6..f5ca26c5dad 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,7 +19,6 @@
//
// This header file contains string utilities involved in escaping and
// unescaping strings in various ways.
-//
#ifndef ABSL_STRINGS_ESCAPING_H_
#define ABSL_STRINGS_ESCAPING_H_
@@ -34,11 +33,12 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// CUnescape()
//
// Unescapes a `source` string and copies it into `dest`, rewriting C-style
-// escape sequences (http://en.cppreference.com/w/cpp/language/escape) into
+// escape sequences (https://en.cppreference.com/w/cpp/language/escape) into
// their proper code point equivalents, returning `true` if successful.
//
// The following unescape sequences can be handled:
@@ -56,7 +56,6 @@ namespace absl {
// UTF-8. (E.g., `\u2019` unescapes to the three bytes 0xE2, 0x80, and
// 0x99).
//
-//
// If any errors are encountered, this function returns `false`, leaving the
// `dest` output parameter in an unspecified state, and stores the first
// encountered error in `error`. To disable error reporting, set `error` to
@@ -80,7 +79,7 @@ inline bool CUnescape(absl::string_view source, std::string* dest) {
// CEscape()
//
// Escapes a 'src' string using C-style escapes sequences
-// (http://en.cppreference.com/w/cpp/language/escape), escaping other
+// (https://en.cppreference.com/w/cpp/language/escape), escaping other
// non-printable/non-whitespace bytes as octal sequences (e.g. "\377").
//
// Example:
@@ -134,16 +133,18 @@ bool WebSafeBase64Unescape(absl::string_view src, std::string* dest);
// Base64Escape()
//
-// Encodes a `src` string into a `dest` buffer using base64 encoding, with
-// padding characters. This function conforms with RFC 4648 section 4 (base64).
+// Encodes a `src` string into a base64-encoded string, with padding characters.
+// This function conforms with RFC 4648 section 4 (base64).
void Base64Escape(absl::string_view src, std::string* dest);
+std::string Base64Escape(absl::string_view src);
// WebSafeBase64Escape()
//
-// Encodes a `src` string into a `dest` buffer using '-' instead of '+' and
-// '_' instead of '/', and without padding. This function conforms with RFC 4648
-// section 5 (base64url).
+// Encodes a `src` string into a base64-like string, using '-' instead of '+'
+// and '_' instead of '/', and without padding. This function conforms with RFC
+// 4648 section 5 (base64url).
void WebSafeBase64Escape(absl::string_view src, std::string* dest);
+std::string WebSafeBase64Escape(absl::string_view src);
// HexStringToBytes()
//
@@ -157,6 +158,7 @@ std::string HexStringToBytes(absl::string_view from);
// `2*from.size()`.
std::string BytesToHexString(absl::string_view from);
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_ESCAPING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_benchmark.cc
index 0f791f4e875..10d5b033c52 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_test.cc
index 9dc27f3f8fa..45671a0ed59 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/escaping_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -36,18 +36,19 @@ struct epair {
TEST(CEscape, EscapeAndUnescape) {
const std::string inputs[] = {
- std::string("foo\nxx\r\b\0023"),
- std::string(""),
- std::string("abc"),
- std::string("\1chad_rules"),
- std::string("\1arnar_drools"),
- std::string("xxxx\r\t'\"\\"),
- std::string("\0xx\0", 4),
- std::string("\x01\x31"),
- std::string("abc\xb\x42\141bc"),
- std::string("123\1\x31\x32\x33"),
- std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
- std::string("\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
+ std::string("foo\nxx\r\b\0023"),
+ std::string(""),
+ std::string("abc"),
+ std::string("\1chad_rules"),
+ std::string("\1arnar_drools"),
+ std::string("xxxx\r\t'\"\\"),
+ std::string("\0xx\0", 4),
+ std::string("\x01\x31"),
+ std::string("abc\xb\x42\141bc"),
+ std::string("123\1\x31\x32\x33"),
+ std::string("\xc1\xca\x1b\x62\x19o\xcc\x04"),
+ std::string(
+ "\\\"\xe8\xb0\xb7\xe6\xad\x8c\\\" is Google\\\'s Chinese name"),
};
// Do this twice, once for octal escapes and once for hex escapes.
for (int kind = 0; kind < 4; kind++) {
@@ -71,6 +72,11 @@ TEST(CEscape, EscapeAndUnescape) {
EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str));
EXPECT_EQ(unescaped_str, original);
+ unescaped_str.erase();
+ std::string error;
+ EXPECT_TRUE(absl::CUnescape(escaped, &unescaped_str, &error));
+ EXPECT_EQ(error, "");
+
// Check in-place unescaping
std::string s = escaped;
EXPECT_TRUE(absl::CUnescape(s, &s));
@@ -149,7 +155,8 @@ TEST(CEscape, BasicEscaping) {
TEST(Unescape, BasicFunction) {
epair tests[] =
- {{"\\u0030", "0"},
+ {{"", ""},
+ {"\\u0030", "0"},
{"\\u00A3", "\xC2\xA3"},
{"\\u22FD", "\xE2\x8B\xBD"},
{"\\U00010000", "\xF0\x90\x80\x80"},
@@ -159,20 +166,22 @@ TEST(Unescape, BasicFunction) {
EXPECT_TRUE(absl::CUnescape(val.escaped, &out));
EXPECT_EQ(out, val.unescaped);
}
- std::string bad[] =
- {"\\u1", // too short
- "\\U1", // too short
- "\\Uffffff", // exceeds 0x10ffff (largest Unicode)
- "\\U00110000", // exceeds 0x10ffff (largest Unicode)
- "\\uD835", // surrogate character (D800-DFFF)
- "\\U0000DD04", // surrogate character (D800-DFFF)
- "\\777", // exceeds 0xff
- "\\xABCD"}; // exceeds 0xff
+ std::string bad[] = {"\\u1", // too short
+ "\\U1", // too short
+ "\\Uffffff", // exceeds 0x10ffff (largest Unicode)
+ "\\U00110000", // exceeds 0x10ffff (largest Unicode)
+ "\\uD835", // surrogate character (D800-DFFF)
+ "\\U0000DD04", // surrogate character (D800-DFFF)
+ "\\777", // exceeds 0xff
+ "\\xABCD"}; // exceeds 0xff
for (const std::string& e : bad) {
std::string error;
std::string out;
EXPECT_FALSE(absl::CUnescape(e, &out, &error));
EXPECT_FALSE(error.empty());
+
+ out.erase();
+ EXPECT_FALSE(absl::CUnescape(e, &out));
}
}
@@ -258,9 +267,11 @@ TEST_F(CUnescapeTest, UnescapesMultipleOctalNulls) {
// All escapes, including newlines and null escapes, should have been
// converted to the equivalent characters.
EXPECT_EQ(std::string("\0\n"
- "0\n"
- "\0\n"
- "\0", 7), result_string_);
+ "0\n"
+ "\0\n"
+ "\0",
+ 7),
+ result_string_);
}
@@ -268,24 +279,28 @@ TEST_F(CUnescapeTest, UnescapesMultipleHexNulls) {
std::string original_string(kStringWithMultipleHexNulls);
EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
EXPECT_EQ(std::string("\0\n"
- "0\n"
- "\0\n"
- "\0", 7), result_string_);
+ "0\n"
+ "\0\n"
+ "\0",
+ 7),
+ result_string_);
}
TEST_F(CUnescapeTest, UnescapesMultipleUnicodeNulls) {
std::string original_string(kStringWithMultipleUnicodeNulls);
EXPECT_TRUE(absl::CUnescape(original_string, &result_string_));
EXPECT_EQ(std::string("\0\n"
- "0\n"
- "\0", 5), result_string_);
+ "0\n"
+ "\0",
+ 5),
+ result_string_);
}
static struct {
absl::string_view plaintext;
absl::string_view cyphertext;
} const base64_tests[] = {
- // Empty std::string.
+ // Empty string.
{{"", 0}, {"", 0}},
{{nullptr, 0},
{"", 0}}, // if length is zero, plaintext ptr must be ignored!
@@ -550,6 +565,7 @@ void TestEscapeAndUnescape() {
StringType encoded("this junk should be ignored");
absl::Base64Escape(tc.plaintext, &encoded);
EXPECT_EQ(encoded, tc.cyphertext);
+ EXPECT_EQ(absl::Base64Escape(tc.plaintext), tc.cyphertext);
StringType decoded("this junk should be ignored");
EXPECT_TRUE(absl::Base64Unescape(encoded, &decoded));
@@ -568,8 +584,9 @@ void TestEscapeAndUnescape() {
encoded = "this junk should be ignored";
absl::WebSafeBase64Escape(tc.plaintext, &encoded);
EXPECT_EQ(encoded, websafe);
+ EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe);
- // Let's try the std::string version of the decoder
+ // Let's try the string version of the decoder
decoded = "this junk should be ignored";
EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded));
EXPECT_EQ(decoded, tc.plaintext);
@@ -580,6 +597,7 @@ void TestEscapeAndUnescape() {
StringType buffer;
absl::WebSafeBase64Escape(tc.plaintext, &buffer);
EXPECT_EQ(tc.cyphertext, buffer);
+ EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), tc.cyphertext);
}
// Verify the behavior when decoding bad data
@@ -607,7 +625,7 @@ TEST(Base64, DISABLED_HugeData) {
std::string escaped;
absl::Base64Escape(huge, &escaped);
- // Generates the std::string that should match a base64 encoded "xxx..." std::string.
+ // Generates the string that should match a base64 encoded "xxx..." string.
// "xxx" in base64 is "eHh4".
std::string expected_encoding;
expected_encoding.reserve(kSize / 3 * 4);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map.h
index 8d92963a4de..61484de0b79 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,6 +28,7 @@
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
class Charmap {
@@ -71,7 +72,7 @@ class Charmap {
CharMaskForWord(x, 2), CharMaskForWord(x, 3));
}
- // Containing all the chars in the C-std::string 's'.
+ // Containing all the chars in the C-string 's'.
// Note that this is expensively recursive because of the C++11 constexpr
// formulation. Use only in constexpr initializers.
static constexpr Charmap FromString(const char* s) {
@@ -149,6 +150,7 @@ constexpr Charmap GraphCharmap() { return PrintCharmap() & ~SpaceCharmap(); }
constexpr Charmap PunctCharmap() { return GraphCharmap() & ~AlnumCharmap(); }
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHAR_MAP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_benchmark.cc
index c45f3157c29..5cef967b308 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_test.cc
index c3601e101e2..d3306241a40 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/char_map_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.cc
index 3e7296e7068..ebf8c0791af 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,6 +19,7 @@
#include <string>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
namespace {
@@ -157,12 +158,12 @@ const uint32_t* LargePowerOfFiveData(int i) {
int LargePowerOfFiveSize(int i) { return 2 * i; }
} // namespace
-const uint32_t kFiveToNth[14] = {
+ABSL_DLL const uint32_t kFiveToNth[14] = {
1, 5, 25, 125, 625, 3125, 15625,
78125, 390625, 1953125, 9765625, 48828125, 244140625, 1220703125,
};
-const uint32_t kTenToNth[10] = {
+ABSL_DLL const uint32_t kTenToNth[10] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000,
};
@@ -207,7 +208,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
++dropped_digits;
}
if (begin < end && *std::prev(end) == '.') {
- // If the std::string ends in '.', either before or after dropping zeroes, then
+ // If the string ends in '.', either before or after dropping zeroes, then
// drop the decimal point and look for more digits to drop.
dropped_digits = 0;
--end;
@@ -354,4 +355,5 @@ template class BigUnsigned<4>;
template class BigUnsigned<84>;
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.h
index 9d1a1bffe17..8f702976a80 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,11 +20,13 @@
#include <iostream>
#include <string>
+#include "absl/base/config.h"
#include "absl/strings/ascii.h"
#include "absl/strings/internal/charconv_parse.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// The largest power that 5 that can be raised to, and still fit in a uint32_t.
@@ -32,8 +34,9 @@ constexpr int kMaxSmallPowerOfFive = 13;
// The largest power that 10 that can be raised to, and still fit in a uint32_t.
constexpr int kMaxSmallPowerOfTen = 9;
-extern const uint32_t kFiveToNth[kMaxSmallPowerOfFive + 1];
-extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
+ABSL_DLL extern const uint32_t
+ kFiveToNth[kMaxSmallPowerOfFive + 1];
+ABSL_DLL extern const uint32_t kTenToNth[kMaxSmallPowerOfTen + 1];
// Large, fixed-width unsigned integer.
//
@@ -63,7 +66,7 @@ class BigUnsigned {
static_cast<uint32_t>(v >> 32)} {}
// Constructs a BigUnsigned from the given string_view containing a decimal
- // value. If the input std::string is not a decimal integer, constructs a 0
+ // value. If the input string is not a decimal integer, constructs a 0
// instead.
explicit BigUnsigned(absl::string_view sv) : size_(0), words_{} {
// Check for valid input, returning a 0 otherwise. This is reasonable
@@ -207,7 +210,7 @@ class BigUnsigned {
return words_[index];
}
- // Returns this integer as a decimal std::string. This is not used in the decimal-
+ // Returns this integer as a decimal string. This is not used in the decimal-
// to-binary conversion; it is intended to aid in testing.
std::string ToString() const;
@@ -414,6 +417,7 @@ extern template class BigUnsigned<4>;
extern template class BigUnsigned<84>;
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_BIGINT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
index 9b6357888fb..a8b9945829e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,6 +19,7 @@
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
TEST(BigUnsigned, ShiftLeft) {
@@ -68,6 +69,61 @@ TEST(BigUnsigned, ShiftLeft) {
// And we should have fully rotated all bits off by now:
EXPECT_EQ(a, BigUnsigned<84>(0u));
}
+ {
+ // Bit shifting large and small numbers by large and small offsets.
+ // Intended to exercise bounds-checking corner on ShiftLeft() (directly
+ // and under asan).
+
+ // 2**(32*84)-1
+ const BigUnsigned<84> all_bits_one(
+ "1474444211396924248063325089479706787923460402125687709454567433186613"
+ "6228083464060749874845919674257665016359189106695900028098437021384227"
+ "3285029708032466536084583113729486015826557532750465299832071590813090"
+ "2011853039837649252477307070509704043541368002938784757296893793903797"
+ "8180292336310543540677175225040919704702800559606097685920595947397024"
+ "8303316808753252115729411497720357971050627997031988036134171378490368"
+ "6008000778741115399296162550786288457245180872759047016734959330367829"
+ "5235612397427686310674725251378116268607113017720538636924549612987647"
+ "5767411074510311386444547332882472126067840027882117834454260409440463"
+ "9345147252664893456053258463203120637089916304618696601333953616715125"
+ "2115882482473279040772264257431663818610405673876655957323083702713344"
+ "4201105427930770976052393421467136557055");
+ const BigUnsigned<84> zero(0u);
+ const BigUnsigned<84> one(1u);
+ // in bounds shifts
+ for (int i = 1; i < 84*32; ++i) {
+ // shifting all_bits_one to the left should result in a smaller number,
+ // since the high bits rotate off and the low bits are replaced with
+ // zeroes.
+ BigUnsigned<84> big_shifted = all_bits_one;
+ big_shifted.ShiftLeft(i);
+ EXPECT_GT(all_bits_one, big_shifted);
+ // Shifting 1 to the left should instead result in a larger number.
+ BigUnsigned<84> small_shifted = one;
+ small_shifted.ShiftLeft(i);
+ EXPECT_LT(one, small_shifted);
+ }
+ // Shifting by zero or a negative number has no effect
+ for (int no_op_shift : {0, -1, -84 * 32, std::numeric_limits<int>::min()}) {
+ BigUnsigned<84> big_shifted = all_bits_one;
+ big_shifted.ShiftLeft(no_op_shift);
+ EXPECT_EQ(all_bits_one, big_shifted);
+ BigUnsigned<84> small_shifted = one;
+ big_shifted.ShiftLeft(no_op_shift);
+ EXPECT_EQ(one, small_shifted);
+ }
+ // Shifting by an amount greater than the number of bits should result in
+ // zero.
+ for (int out_of_bounds_shift :
+ {84 * 32, 84 * 32 + 1, std::numeric_limits<int>::max()}) {
+ BigUnsigned<84> big_shifted = all_bits_one;
+ big_shifted.ShiftLeft(out_of_bounds_shift);
+ EXPECT_EQ(zero, big_shifted);
+ BigUnsigned<84> small_shifted = one;
+ small_shifted.ShiftLeft(out_of_bounds_shift);
+ EXPECT_EQ(zero, small_shifted);
+ }
+ }
}
TEST(BigUnsigned, MultiplyByUint32) {
@@ -200,4 +256,5 @@ TEST(BigUnsigned, TenToTheNth) {
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.cc
index 7e4dabc2262..8b11868c887 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
// ParseFloat<10> will read the first 19 significant digits of the mantissa.
@@ -245,14 +246,20 @@ constexpr int DigitMagnitude<16>() {
// ConsumeDigits does not protect against overflow on *out; max_digits must
// be chosen with respect to type T to avoid the possibility of overflow.
template <int base, typename T>
-std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
- T* out, bool* dropped_nonzero_digit) {
+int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
+ bool* dropped_nonzero_digit) {
if (base == 10) {
assert(max_digits <= std::numeric_limits<T>::digits10);
} else if (base == 16) {
assert(max_digits * 4 <= std::numeric_limits<T>::digits);
}
const char* const original_begin = begin;
+
+ // Skip leading zeros, but only if *out is zero.
+ // They don't cause an overflow so we don't have to count them for
+ // `max_digits`.
+ while (!*out && end != begin && *begin == '0') ++begin;
+
T accumulator = *out;
const char* significant_digits_end =
(end - begin > max_digits) ? begin + max_digits : end;
@@ -275,7 +282,7 @@ std::size_t ConsumeDigits(const char* begin, const char* end, int max_digits,
*dropped_nonzero_digit = true;
}
*out = accumulator;
- return begin - original_begin;
+ return static_cast<int>(begin - original_begin);
}
// Returns true if `v` is one of the chars allowed inside parentheses following
@@ -295,7 +302,7 @@ bool ParseInfinityOrNan(const char* begin, const char* end,
switch (*begin) {
case 'i':
case 'I': {
- // An infinity std::string consists of the characters "inf" or "infinity",
+ // An infinity string consists of the characters "inf" or "infinity",
// case insensitive.
if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
return false;
@@ -319,7 +326,7 @@ bool ParseInfinityOrNan(const char* begin, const char* end,
}
out->type = strings_internal::FloatType::kNan;
out->end = begin + 3;
- // NaN is allowed to be followed by a parenthesized std::string, consisting of
+ // NaN is allowed to be followed by a parenthesized string, consisting of
// only the characters [a-zA-Z0-9_]. Match that if it's present.
begin += 3;
if (begin < end && *begin == '(') {
@@ -365,7 +372,7 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
int exponent_adjustment = 0;
bool mantissa_is_inexact = false;
- std::size_t pre_decimal_digits = ConsumeDigits<base>(
+ int pre_decimal_digits = ConsumeDigits<base>(
begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
begin += pre_decimal_digits;
int digits_left;
@@ -391,14 +398,14 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
while (begin < end && *begin == '0') {
++begin;
}
- std::size_t zeros_skipped = begin - begin_zeros;
+ int zeros_skipped = static_cast<int>(begin - begin_zeros);
if (zeros_skipped >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
}
exponent_adjustment -= static_cast<int>(zeros_skipped);
}
- std::size_t post_decimal_digits = ConsumeDigits<base>(
+ int post_decimal_digits = ConsumeDigits<base>(
begin, end, digits_left, &mantissa, &mantissa_is_inexact);
begin += post_decimal_digits;
@@ -493,4 +500,5 @@ template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
chars_format format_flags);
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.h
index 7a5c0874b80..505998b5394 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,9 +17,11 @@
#include <cstdint>
+#include "absl/base/config.h"
#include "absl/strings/charconv.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// Enum indicating whether a parsed float is a number or special value.
@@ -92,5 +94,6 @@ extern template ParsedFloat ParseFloat<16>(const char* begin, const char* end,
absl::chars_format format_flags);
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CHARCONV_PARSE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
index f48b9aee1a5..bc2d1118765 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -63,7 +63,7 @@ void ExpectParsedFloat(std::string s, absl::chars_format format_flags,
}
const std::string::size_type expected_characters_matched = s.find('$');
ABSL_RAW_CHECK(expected_characters_matched != std::string::npos,
- "Input std::string must contain $");
+ "Input string must contain $");
s.replace(expected_characters_matched, 1, "");
ParsedFloat parsed =
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.cc
new file mode 100644
index 00000000000..905ffd0cc16
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.cc
@@ -0,0 +1,83 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/strings/internal/cord_internal.h"
+
+#include <atomic>
+#include <cassert>
+#include <memory>
+
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled(
+ kCordEnableRingBufferDefault);
+ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(
+ kCordShallowSubcordsDefault);
+
+void CordRep::Destroy(CordRep* rep) {
+ assert(rep != nullptr);
+
+ absl::InlinedVector<CordRep*, Constants::kInlinedVectorSize> pending;
+ while (true) {
+ assert(!rep->refcount.IsImmortal());
+ if (rep->tag == CONCAT) {
+ CordRepConcat* rep_concat = rep->concat();
+ CordRep* right = rep_concat->right;
+ if (!right->refcount.Decrement()) {
+ pending.push_back(right);
+ }
+ CordRep* left = rep_concat->left;
+ delete rep_concat;
+ rep = nullptr;
+ if (!left->refcount.Decrement()) {
+ rep = left;
+ continue;
+ }
+ } else if (rep->tag == RING) {
+ CordRepRing::Destroy(rep->ring());
+ rep = nullptr;
+ } else if (rep->tag == EXTERNAL) {
+ CordRepExternal::Delete(rep);
+ rep = nullptr;
+ } else if (rep->tag == SUBSTRING) {
+ CordRepSubstring* rep_substring = rep->substring();
+ CordRep* child = rep_substring->child;
+ delete rep_substring;
+ rep = nullptr;
+ if (!child->refcount.Decrement()) {
+ rep = child;
+ continue;
+ }
+ } else {
+ CordRepFlat::Delete(rep);
+ rep = nullptr;
+ }
+
+ if (!pending.empty()) {
+ rep = pending.back();
+ pending.pop_back();
+ } else {
+ break;
+ }
+ }
+}
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.h
new file mode 100644
index 00000000000..a1ba67fec32
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_internal.h
@@ -0,0 +1,543 @@
+// 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_INTERNAL_H_
+#define ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
+
+#include <atomic>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <type_traits>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/invoke.h"
+#include "absl/base/optimization.h"
+#include "absl/container/internal/compressed_tuple.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+class CordzInfo;
+
+// Default feature enable states for cord ring buffers
+enum CordFeatureDefaults {
+ kCordEnableRingBufferDefault = false,
+ kCordShallowSubcordsDefault = false
+};
+
+extern std::atomic<bool> cord_ring_buffer_enabled;
+extern std::atomic<bool> shallow_subcords_enabled;
+
+inline void enable_cord_ring_buffer(bool enable) {
+ cord_ring_buffer_enabled.store(enable, std::memory_order_relaxed);
+}
+
+inline void enable_shallow_subcords(bool enable) {
+ shallow_subcords_enabled.store(enable, std::memory_order_relaxed);
+}
+
+enum Constants {
+ // The inlined size to use with absl::InlinedVector.
+ //
+ // Note: The InlinedVectors in this file (and in cord.h) do not need to use
+ // the same value for their inlined size. The fact that they do is historical.
+ // It may be desirable for each to use a different inlined size optimized for
+ // that InlinedVector's usage.
+ //
+ // TODO(jgm): Benchmark to see if there's a more optimal value than 47 for
+ // the inlined vector size (47 exists for backward compatibility).
+ kInlinedVectorSize = 47,
+
+ // Prefer copying blocks of at most this size, otherwise reference count.
+ kMaxBytesToCopy = 511
+};
+
+// Wraps std::atomic for reference counting.
+class Refcount {
+ public:
+ constexpr Refcount() : count_{kRefIncrement} {}
+ struct Immortal {};
+ explicit constexpr Refcount(Immortal) : count_(kImmortalTag) {}
+
+ // Increments the reference count. Imposes no memory ordering.
+ inline void Increment() {
+ count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
+ }
+
+ // Asserts that the current refcount is greater than 0. If the refcount is
+ // greater than 1, decrements the reference count.
+ //
+ // Returns false if there are no references outstanding; true otherwise.
+ // Inserts barriers to ensure that state written before this method returns
+ // false will be visible to a thread that just observed this method returning
+ // false.
+ inline bool Decrement() {
+ int32_t refcount = count_.load(std::memory_order_acquire);
+ assert(refcount > 0 || refcount & kImmortalTag);
+ return refcount != kRefIncrement &&
+ count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) !=
+ kRefIncrement;
+ }
+
+ // Same as Decrement but expect that refcount is greater than 1.
+ inline bool DecrementExpectHighRefcount() {
+ int32_t refcount =
+ count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel);
+ assert(refcount > 0 || refcount & kImmortalTag);
+ return refcount != kRefIncrement;
+ }
+
+ // Returns the current reference count using acquire semantics.
+ inline int32_t Get() const {
+ return count_.load(std::memory_order_acquire) >> kImmortalShift;
+ }
+
+ // Returns whether the atomic integer is 1.
+ // If the reference count is used in the conventional way, a
+ // reference count of 1 implies that the current thread owns the
+ // reference and no other thread shares it.
+ // This call performs the test for a reference count of one, and
+ // performs the memory barrier needed for the owning thread
+ // to act on the object, knowing that it has exclusive access to the
+ // object.
+ inline bool IsOne() {
+ return count_.load(std::memory_order_acquire) == kRefIncrement;
+ }
+
+ bool IsImmortal() const {
+ return (count_.load(std::memory_order_relaxed) & kImmortalTag) != 0;
+ }
+
+ private:
+ // We reserve the bottom bit to tag a reference count as immortal.
+ // By making it `1` we ensure that we never reach `0` when adding/subtracting
+ // `2`, thus it never looks as if it should be destroyed.
+ // These are used for the StringConstant constructor where we do not increase
+ // the refcount at construction time (due to constinit requirements) but we
+ // will still decrease it at destruction time to avoid branching on Unref.
+ enum {
+ kImmortalShift = 1,
+ kRefIncrement = 1 << kImmortalShift,
+ kImmortalTag = kRefIncrement - 1
+ };
+
+ std::atomic<int32_t> count_;
+};
+
+// The overhead of a vtable is too much for Cord, so we roll our own subclasses
+// using only a single byte to differentiate classes from each other - the "tag"
+// byte. Define the subclasses first so we can provide downcasting helper
+// functions in the base class.
+
+struct CordRepConcat;
+struct CordRepExternal;
+struct CordRepFlat;
+struct CordRepSubstring;
+class CordRepRing;
+
+// Various representations that we allow
+enum CordRepKind {
+ CONCAT = 0,
+ EXTERNAL = 1,
+ SUBSTRING = 2,
+ RING = 3,
+
+ // We have different tags for different sized flat arrays,
+ // starting with FLAT, and limited to MAX_FLAT_TAG. The 224 value is based on
+ // the current 'size to tag' encoding of 8 / 32 bytes. If a new tag is needed
+ // in the future, then 'FLAT' and 'MAX_FLAT_TAG' should be adjusted as well
+ // as the Tag <---> Size logic so that FLAT stil represents the minimum flat
+ // allocation size. (32 bytes as of now).
+ FLAT = 4,
+ MAX_FLAT_TAG = 224
+};
+
+struct CordRep {
+ CordRep() = default;
+ constexpr CordRep(Refcount::Immortal immortal, size_t l)
+ : length(l), refcount(immortal), tag(EXTERNAL), storage{} {}
+
+ // The following three fields have to be less than 32 bytes since
+ // that is the smallest supported flat node size.
+ size_t length;
+ Refcount refcount;
+ // If tag < FLAT, it represents CordRepKind and indicates the type of node.
+ // Otherwise, the node type is CordRepFlat and the tag is the encoded size.
+ uint8_t tag;
+ char storage[1]; // Starting point for flat array: MUST BE LAST FIELD
+
+ inline CordRepRing* ring();
+ inline const CordRepRing* ring() const;
+ inline CordRepConcat* concat();
+ inline const CordRepConcat* concat() const;
+ inline CordRepSubstring* substring();
+ inline const CordRepSubstring* substring() const;
+ inline CordRepExternal* external();
+ inline const CordRepExternal* external() const;
+ inline CordRepFlat* flat();
+ inline const CordRepFlat* flat() const;
+
+ // --------------------------------------------------------------------
+ // Memory management
+
+ // Destroys the provided `rep`.
+ static void Destroy(CordRep* rep);
+
+ // Increments the reference count of `rep`.
+ // Requires `rep` to be a non-null pointer value.
+ static inline CordRep* Ref(CordRep* rep);
+
+ // Decrements the reference count of `rep`. Destroys rep if count reaches
+ // zero. Requires `rep` to be a non-null pointer value.
+ static inline void Unref(CordRep* rep);
+};
+
+struct CordRepConcat : public CordRep {
+ CordRep* left;
+ CordRep* right;
+
+ uint8_t depth() const { return static_cast<uint8_t>(storage[0]); }
+ void set_depth(uint8_t depth) { storage[0] = static_cast<char>(depth); }
+};
+
+struct CordRepSubstring : public CordRep {
+ size_t start; // Starting offset of substring in child
+ CordRep* child;
+};
+
+// Type for function pointer that will invoke the releaser function and also
+// delete the `CordRepExternalImpl` corresponding to the passed in
+// `CordRepExternal`.
+using ExternalReleaserInvoker = void (*)(CordRepExternal*);
+
+// External CordReps are allocated together with a type erased releaser. The
+// releaser is stored in the memory directly following the CordRepExternal.
+struct CordRepExternal : public CordRep {
+ CordRepExternal() = default;
+ explicit constexpr CordRepExternal(absl::string_view str)
+ : CordRep(Refcount::Immortal{}, str.size()),
+ base(str.data()),
+ releaser_invoker(nullptr) {}
+
+ const char* base;
+ // Pointer to function that knows how to call and destroy the releaser.
+ ExternalReleaserInvoker releaser_invoker;
+
+ // Deletes (releases) the external rep.
+ // Requires rep != nullptr and rep->tag == EXTERNAL
+ static void Delete(CordRep* rep);
+};
+
+struct Rank1 {};
+struct Rank0 : Rank1 {};
+
+template <typename Releaser, typename = ::absl::base_internal::invoke_result_t<
+ Releaser, absl::string_view>>
+void InvokeReleaser(Rank0, Releaser&& releaser, absl::string_view data) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser), data);
+}
+
+template <typename Releaser,
+ typename = ::absl::base_internal::invoke_result_t<Releaser>>
+void InvokeReleaser(Rank1, Releaser&& releaser, absl::string_view) {
+ ::absl::base_internal::invoke(std::forward<Releaser>(releaser));
+}
+
+// We use CompressedTuple so that we can benefit from EBCO.
+template <typename Releaser>
+struct CordRepExternalImpl
+ : public CordRepExternal,
+ public ::absl::container_internal::CompressedTuple<Releaser> {
+ // The extra int arg is so that we can avoid interfering with copy/move
+ // constructors while still benefitting from perfect forwarding.
+ template <typename T>
+ CordRepExternalImpl(T&& releaser, int)
+ : CordRepExternalImpl::CompressedTuple(std::forward<T>(releaser)) {
+ this->releaser_invoker = &Release;
+ }
+
+ ~CordRepExternalImpl() {
+ InvokeReleaser(Rank0{}, std::move(this->template get<0>()),
+ absl::string_view(base, length));
+ }
+
+ static void Release(CordRepExternal* rep) {
+ delete static_cast<CordRepExternalImpl*>(rep);
+ }
+};
+
+inline void CordRepExternal::Delete(CordRep* rep) {
+ assert(rep != nullptr && rep->tag == EXTERNAL);
+ auto* rep_external = static_cast<CordRepExternal*>(rep);
+ assert(rep_external->releaser_invoker != nullptr);
+ rep_external->releaser_invoker(rep_external);
+}
+
+template <typename Str>
+struct ConstInitExternalStorage {
+ ABSL_CONST_INIT static CordRepExternal value;
+};
+
+template <typename Str>
+CordRepExternal ConstInitExternalStorage<Str>::value(Str::value);
+
+enum {
+ kMaxInline = 15,
+};
+
+constexpr char GetOrNull(absl::string_view data, size_t pos) {
+ return pos < data.size() ? data[pos] : '\0';
+}
+
+// We store cordz_info as 64 bit pointer value in big endian format. This
+// guarantees that the least significant byte of cordz_info matches the last
+// byte of the inline data representation in as_chars_, which holds the inlined
+// size or the 'is_tree' bit.
+using cordz_info_t = int64_t;
+
+// Assert that the `cordz_info` pointer value perfectly overlaps the last half
+// of `as_chars_` and can hold a pointer value.
+static_assert(sizeof(cordz_info_t) * 2 == kMaxInline + 1, "");
+static_assert(sizeof(cordz_info_t) >= sizeof(intptr_t), "");
+
+// BigEndianByte() creates a big endian representation of 'value', i.e.: a big
+// endian value where the last byte in the host's representation holds 'value`,
+// with all other bytes being 0.
+static constexpr cordz_info_t BigEndianByte(unsigned char value) {
+#if defined(ABSL_IS_BIG_ENDIAN)
+ return value;
+#else
+ return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
+#endif
+}
+
+class InlineData {
+ public:
+ // kNullCordzInfo holds the big endian representation of intptr_t(1)
+ // This is the 'null' / initial value of 'cordz_info'. The null value
+ // is specifically big endian 1 as with 64-bit pointers, the last
+ // byte of cordz_info overlaps with the last byte holding the tag.
+ static constexpr cordz_info_t kNullCordzInfo = BigEndianByte(1);
+
+ // kFakeCordzInfo holds a 'fake', non-null cordz-info value we use to
+ // emulate the previous 'kProfiled' tag logic in 'set_profiled' until
+ // cord code is changed to store cordz_info values in InlineData.
+ static constexpr cordz_info_t kFakeCordzInfo = BigEndianByte(9);
+
+ constexpr InlineData() : as_chars_{0} {}
+ explicit constexpr InlineData(CordRep* rep) : as_tree_(rep) {}
+ explicit constexpr InlineData(absl::string_view chars)
+ : as_chars_{
+ GetOrNull(chars, 0), GetOrNull(chars, 1),
+ GetOrNull(chars, 2), GetOrNull(chars, 3),
+ GetOrNull(chars, 4), GetOrNull(chars, 5),
+ GetOrNull(chars, 6), GetOrNull(chars, 7),
+ GetOrNull(chars, 8), GetOrNull(chars, 9),
+ GetOrNull(chars, 10), GetOrNull(chars, 11),
+ GetOrNull(chars, 12), GetOrNull(chars, 13),
+ GetOrNull(chars, 14), static_cast<char>((chars.size() << 1))} {}
+
+ // Returns true if the current instance is empty.
+ // The 'empty value' is an inlined data value of zero length.
+ bool is_empty() const { return tag() == 0; }
+
+ // Returns true if the current instance holds a tree value.
+ bool is_tree() const { return (tag() & 1) != 0; }
+
+ // Returns true if the current instance holds a cordz_info value.
+ // Requires the current instance to hold a tree value.
+ bool is_profiled() const {
+ assert(is_tree());
+ return as_tree_.cordz_info != kNullCordzInfo;
+ }
+
+ // Returns the cordz_info sampling instance for this instance, or nullptr
+ // if the current instance is not sampled and does not have CordzInfo data.
+ // Requires the current instance to hold a tree value.
+ CordzInfo* cordz_info() const {
+ assert(is_tree());
+ intptr_t info =
+ static_cast<intptr_t>(absl::big_endian::ToHost64(as_tree_.cordz_info));
+ assert(info & 1);
+ return reinterpret_cast<CordzInfo*>(info - 1);
+ }
+
+ // Sets the current cordz_info sampling instance for this instance, or nullptr
+ // if the current instance is not sampled and does not have CordzInfo data.
+ // Requires the current instance to hold a tree value.
+ void set_cordz_info(CordzInfo* cordz_info) {
+ assert(is_tree());
+ intptr_t info = reinterpret_cast<intptr_t>(cordz_info) | 1;
+ as_tree_.cordz_info = absl::big_endian::FromHost64(info);
+ }
+
+ // Resets the current cordz_info to null / empty.
+ void clear_cordz_info() {
+ assert(is_tree());
+ as_tree_.cordz_info = kNullCordzInfo;
+ }
+
+ // Returns a read only pointer to the character data inside this instance.
+ // Requires the current instance to hold inline data.
+ const char* as_chars() const {
+ assert(!is_tree());
+ return as_chars_;
+ }
+
+ // Returns a mutable pointer to the character data inside this instance.
+ // Should be used for 'write only' operations setting an inlined value.
+ // Applications can set the value of inlined data either before or after
+ // setting the inlined size, i.e., both of the below are valid:
+ //
+ // // Set inlined data and inline size
+ // memcpy(data_.as_chars(), data, size);
+ // data_.set_inline_size(size);
+ //
+ // // Set inlined size and inline data
+ // data_.set_inline_size(size);
+ // memcpy(data_.as_chars(), data, size);
+ //
+ // It's an error to read from the returned pointer without a preceding write
+ // if the current instance does not hold inline data, i.e.: is_tree() == true.
+ char* as_chars() { return as_chars_; }
+
+ // Returns the tree value of this value.
+ // Requires the current instance to hold a tree value.
+ CordRep* as_tree() const {
+ assert(is_tree());
+ return as_tree_.rep;
+ }
+
+ // Initialize this instance to holding the tree value `rep`,
+ // initializing the cordz_info to null, i.e.: 'not profiled'.
+ void make_tree(CordRep* rep) {
+ as_tree_.rep = rep;
+ as_tree_.cordz_info = kNullCordzInfo;
+ }
+
+ // Set the tree value of this instance to 'rep`.
+ // Requires the current instance to already hold a tree value.
+ // Does not affect the value of cordz_info.
+ void set_tree(CordRep* rep) {
+ assert(is_tree());
+ as_tree_.rep = rep;
+ }
+
+ // Returns the size of the inlined character data inside this instance.
+ // Requires the current instance to hold inline data.
+ size_t inline_size() const {
+ assert(!is_tree());
+ return tag() >> 1;
+ }
+
+ // Sets the size of the inlined character data inside this instance.
+ // Requires `size` to be <= kMaxInline.
+ // See the documentation on 'as_chars()' for more information and examples.
+ void set_inline_size(size_t size) {
+ ABSL_ASSERT(size <= kMaxInline);
+ tag() = static_cast<char>(size << 1);
+ }
+
+ // Sets or unsets the 'is_profiled' state of this instance.
+ // Requires the current instance to hold a tree value.
+ void set_profiled(bool profiled) {
+ assert(is_tree());
+ as_tree_.cordz_info = profiled ? kFakeCordzInfo : kNullCordzInfo;
+ }
+
+ private:
+ // See cordz_info_t for forced alignment and size of `cordz_info` details.
+ struct AsTree {
+ explicit constexpr AsTree(absl::cord_internal::CordRep* tree)
+ : rep(tree), cordz_info(kNullCordzInfo) {}
+ // This union uses up extra space so that whether rep is 32 or 64 bits,
+ // cordz_info will still start at the eighth byte, and the last
+ // byte of cordz_info will still be the last byte of InlineData.
+ union {
+ absl::cord_internal::CordRep* rep;
+ cordz_info_t unused_aligner;
+ };
+ cordz_info_t cordz_info;
+ };
+
+ char& tag() { return reinterpret_cast<char*>(this)[kMaxInline]; }
+ char tag() const { return reinterpret_cast<const char*>(this)[kMaxInline]; }
+
+ // If the data has length <= kMaxInline, we store it in `as_chars_`, and
+ // store the size in the last char of `as_chars_` shifted left + 1.
+ // Else we store it in a tree and store a pointer to that tree in
+ // `as_tree_.rep` and store a tag in `tagged_size`.
+ union {
+ char as_chars_[kMaxInline + 1];
+ AsTree as_tree_;
+ };
+};
+
+static_assert(sizeof(InlineData) == kMaxInline + 1, "");
+
+inline CordRepConcat* CordRep::concat() {
+ assert(tag == CONCAT);
+ return static_cast<CordRepConcat*>(this);
+}
+
+inline const CordRepConcat* CordRep::concat() const {
+ assert(tag == CONCAT);
+ return static_cast<const CordRepConcat*>(this);
+}
+
+inline CordRepSubstring* CordRep::substring() {
+ assert(tag == SUBSTRING);
+ return static_cast<CordRepSubstring*>(this);
+}
+
+inline const CordRepSubstring* CordRep::substring() const {
+ assert(tag == SUBSTRING);
+ return static_cast<const CordRepSubstring*>(this);
+}
+
+inline CordRepExternal* CordRep::external() {
+ assert(tag == EXTERNAL);
+ return static_cast<CordRepExternal*>(this);
+}
+
+inline const CordRepExternal* CordRep::external() const {
+ assert(tag == EXTERNAL);
+ return static_cast<const CordRepExternal*>(this);
+}
+
+inline CordRep* CordRep::Ref(CordRep* rep) {
+ assert(rep != nullptr);
+ rep->refcount.Increment();
+ return rep;
+}
+
+inline void CordRep::Unref(CordRep* rep) {
+ assert(rep != nullptr);
+ // Expect refcount to be 0. Avoiding the cost of an atomic decrement should
+ // typically outweigh the cost of an extra branch checking for ref == 1.
+ if (ABSL_PREDICT_FALSE(!rep->refcount.DecrementExpectHighRefcount())) {
+ Destroy(rep);
+ }
+}
+
+} // namespace cord_internal
+
+ABSL_NAMESPACE_END
+} // namespace absl
+#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_flat.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_flat.h
new file mode 100644
index 00000000000..a98aa9df5fe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_flat.h
@@ -0,0 +1,146 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+
+#include "absl/strings/internal/cord_internal.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// Note: all constants below are never ODR used and internal to cord, we define
+// these as static constexpr to avoid 'in struct' definition and usage clutter.
+
+// Largest and smallest flat node lengths we are willing to allocate
+// Flat allocation size is stored in tag, which currently can encode sizes up
+// to 4K, encoded as multiple of either 8 or 32 bytes.
+// If we allow for larger sizes, we need to change this to 8/64, 16/128, etc.
+// kMinFlatSize is bounded by tag needing to be at least FLAT * 8 bytes, and
+// ideally a 'nice' size aligning with allocation and cacheline sizes like 32.
+// kMaxFlatSize is bounded by the size resulting in a computed tag no greater
+// than MAX_FLAT_TAG. MAX_FLAT_TAG provides for additional 'high' tag values.
+static constexpr size_t kFlatOverhead = offsetof(CordRep, storage);
+static constexpr size_t kMinFlatSize = 32;
+static constexpr size_t kMaxFlatSize = 4096;
+static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
+static constexpr size_t kMinFlatLength = kMinFlatSize - kFlatOverhead;
+
+constexpr uint8_t AllocatedSizeToTagUnchecked(size_t size) {
+ return static_cast<uint8_t>((size <= 1024) ? size / 8
+ : 128 + size / 32 - 1024 / 32);
+}
+
+static_assert(kMinFlatSize / 8 >= FLAT, "");
+static_assert(AllocatedSizeToTagUnchecked(kMaxFlatSize) <= MAX_FLAT_TAG, "");
+
+// Helper functions for rounded div, and rounding to exact sizes.
+constexpr size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
+constexpr size_t RoundUp(size_t n, size_t m) { return DivUp(n, m) * m; }
+
+// Returns the size to the nearest equal or larger value that can be
+// expressed exactly as a tag value.
+inline size_t RoundUpForTag(size_t size) {
+ return RoundUp(size, (size <= 1024) ? 8 : 32);
+}
+
+// Converts the allocated size to a tag, rounding down if the size
+// does not exactly match a 'tag expressible' size value. The result is
+// undefined if the size exceeds the maximum size that can be encoded in
+// a tag, i.e., if size is larger than TagToAllocatedSize(<max tag>).
+inline uint8_t AllocatedSizeToTag(size_t size) {
+ const uint8_t tag = AllocatedSizeToTagUnchecked(size);
+ assert(tag <= MAX_FLAT_TAG);
+ return tag;
+}
+
+// Converts the provided tag to the corresponding allocated size
+constexpr size_t TagToAllocatedSize(uint8_t tag) {
+ return (tag <= 128) ? (tag * 8) : (1024 + (tag - 128) * 32);
+}
+
+// Converts the provided tag to the corresponding available data length
+constexpr size_t TagToLength(uint8_t tag) {
+ return TagToAllocatedSize(tag) - kFlatOverhead;
+}
+
+// Enforce that kMaxFlatSize maps to a well-known exact tag value.
+static_assert(TagToAllocatedSize(224) == kMaxFlatSize, "Bad tag logic");
+
+struct CordRepFlat : public CordRep {
+ // Creates a new flat node.
+ static CordRepFlat* New(size_t len) {
+ if (len <= kMinFlatLength) {
+ len = kMinFlatLength;
+ } else if (len > kMaxFlatLength) {
+ len = kMaxFlatLength;
+ }
+
+ // Round size up so it matches a size we can exactly express in a tag.
+ const size_t size = RoundUpForTag(len + kFlatOverhead);
+ void* const raw_rep = ::operator new(size);
+ CordRepFlat* rep = new (raw_rep) CordRepFlat();
+ rep->tag = AllocatedSizeToTag(size);
+ return rep;
+ }
+
+ // Deletes a CordRepFlat instance created previously through a call to New().
+ // Flat CordReps are allocated and constructed with raw ::operator new and
+ // placement new, and must be destructed and deallocated accordingly.
+ static void Delete(CordRep*rep) {
+ assert(rep->tag >= FLAT && rep->tag <= MAX_FLAT_TAG);
+
+#if defined(__cpp_sized_deallocation)
+ size_t size = TagToAllocatedSize(rep->tag);
+ rep->~CordRep();
+ ::operator delete(rep, size);
+#else
+ rep->~CordRep();
+ ::operator delete(rep);
+#endif
+ }
+
+ // Returns a pointer to the data inside this flat rep.
+ char* Data() { return storage; }
+ const char* Data() const { return storage; }
+
+ // Returns the maximum capacity (payload size) of this instance.
+ size_t Capacity() const { return TagToLength(tag); }
+
+ // Returns the allocated size (payload + overhead) of this instance.
+ size_t AllocatedSize() const { return TagToAllocatedSize(tag); }
+};
+
+// Now that CordRepFlat is defined, we can define CordRep's helper casts:
+inline CordRepFlat* CordRep::flat() {
+ assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+ return reinterpret_cast<CordRepFlat*>(this);
+}
+
+inline const CordRepFlat* CordRep::flat() const {
+ assert(tag >= FLAT && tag <= MAX_FLAT_TAG);
+ return reinterpret_cast<const CordRepFlat*>(this);
+}
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_FLAT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.cc
new file mode 100644
index 00000000000..4d31d1d97c7
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.cc
@@ -0,0 +1,897 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include "absl/strings/internal/cord_rep_ring.h"
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <memory>
+#include <string>
+
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/base/macros.h"
+#include "absl/container/inlined_vector.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// See https://bugs.llvm.org/show_bug.cgi?id=48477
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wshadow"
+#if __has_warning("-Wshadow-field")
+#pragma clang diagnostic ignored "-Wshadow-field"
+#endif
+#endif
+
+namespace {
+
+using index_type = CordRepRing::index_type;
+
+enum class Direction { kForward, kReversed };
+
+inline bool IsFlatOrExternal(CordRep* rep) {
+ return rep->tag >= FLAT || rep->tag == EXTERNAL;
+}
+
+// Verifies that n + extra <= kMaxCapacity: throws std::length_error otherwise.
+inline void CheckCapacity(size_t n, size_t extra) {
+ if (ABSL_PREDICT_FALSE(extra > CordRepRing::kMaxCapacity - n)) {
+ base_internal::ThrowStdLengthError("Maximum capacity exceeded");
+ }
+}
+
+// Removes a reference from `rep` only.
+// Asserts that the refcount after decrement is not zero.
+inline bool UnrefNeverOne(CordRep* rep) {
+ bool result = rep->refcount.Decrement();
+ assert(result);
+ return result;
+}
+
+// Creates a flat from the provided string data, allocating up to `extra`
+// capacity in the returned flat depending on kMaxFlatLength limitations.
+// Requires `len` to be less or equal to `kMaxFlatLength`
+CordRepFlat* CreateFlat(const char* s, size_t n, size_t extra = 0) { // NOLINT
+ assert(n <= kMaxFlatLength);
+ auto* rep = CordRepFlat::New(n + extra);
+ rep->length = n;
+ memcpy(rep->Data(), s, n);
+ return rep;
+}
+
+// Unrefs the provided `substring`, and returns `substring->child`
+// Adds or assumes a reference on `substring->child`
+CordRep* ClipSubstring(CordRepSubstring* substring) {
+ CordRep* child = substring->child;
+ if (substring->refcount.IsOne()) {
+ delete substring;
+ } else {
+ CordRep::Ref(child);
+ if (ABSL_PREDICT_FALSE(!substring->refcount.Decrement())) {
+ UnrefNeverOne(child);
+ delete substring;
+ }
+ }
+ return child;
+}
+
+// Unrefs the provided `concat`, and returns `{concat->left, concat->right}`
+// Adds or assumes a reference on `concat->left` and `concat->right`.
+std::pair<CordRep*, CordRep*> ClipConcat(CordRepConcat* concat) {
+ auto result = std::make_pair(concat->left, concat->right);
+ if (concat->refcount.IsOne()) {
+ delete concat;
+ } else {
+ CordRep::Ref(result.first);
+ CordRep::Ref(result.second);
+ if (ABSL_PREDICT_FALSE(!concat->refcount.Decrement())) {
+ UnrefNeverOne(result.first);
+ UnrefNeverOne(result.second);
+ delete concat;
+ }
+ }
+ return result;
+}
+
+// Unrefs the entries in `[head, tail)`.
+// Requires all entries to be a FLAT or EXTERNAL node.
+void UnrefEntries(const CordRepRing* rep, index_type head, index_type tail) {
+ rep->ForEach(head, tail, [rep](index_type ix) {
+ CordRep* child = rep->entry_child(ix);
+ if (!child->refcount.Decrement()) {
+ if (child->tag >= FLAT) {
+ CordRepFlat::Delete(child->flat());
+ } else {
+ CordRepExternal::Delete(child->external());
+ }
+ }
+ });
+}
+
+template <typename F>
+void Consume(Direction direction, CordRep* rep, F&& fn) {
+ size_t offset = 0;
+ size_t length = rep->length;
+ struct Entry {
+ CordRep* rep;
+ size_t offset;
+ size_t length;
+ };
+ absl::InlinedVector<Entry, 40> stack;
+
+ for (;;) {
+ if (rep->tag >= FLAT || rep->tag == EXTERNAL || rep->tag == RING) {
+ fn(rep, offset, length);
+ if (stack.empty()) return;
+
+ rep = stack.back().rep;
+ offset = stack.back().offset;
+ length = stack.back().length;
+ stack.pop_back();
+ } else if (rep->tag == SUBSTRING) {
+ offset += rep->substring()->start;
+ rep = ClipSubstring(rep->substring());
+ } else if (rep->tag == CONCAT) {
+ auto res = ClipConcat(rep->concat());
+ CordRep* left = res.first;
+ CordRep* right = res.second;
+
+ if (left->length <= offset) {
+ // Don't need left node
+ offset -= left->length;
+ CordRep::Unref(left);
+ rep = right;
+ continue;
+ }
+
+ size_t length_left = left->length - offset;
+ if (length_left >= length) {
+ // Don't need right node
+ CordRep::Unref(right);
+ rep = left;
+ continue;
+ }
+
+ // Need both nodes
+ size_t length_right = length - length_left;
+ if (direction == Direction::kReversed) {
+ stack.push_back({left, offset, length_left});
+ rep = right;
+ offset = 0;
+ length = length_right;
+ } else {
+ stack.push_back({right, 0, length_right});
+ rep = left;
+ length = length_left;
+ }
+ } else {
+ assert("Valid tag" == nullptr);
+ return;
+ }
+ }
+}
+
+template <typename F>
+void Consume(CordRep* rep, F&& fn) {
+ return Consume(Direction::kForward, rep, std::forward<F>(fn));
+}
+
+template <typename F>
+void RConsume(CordRep* rep, F&& fn) {
+ return Consume(Direction::kReversed, rep, std::forward<F>(fn));
+}
+
+} // namespace
+
+std::ostream& operator<<(std::ostream& s, const CordRepRing& rep) {
+ // Note: 'pos' values are defined as size_t (for overflow reasons), but that
+ // prints really awkward for small prepended values such as -5. ssize_t is not
+ // portable (POSIX), so we use ptrdiff_t instead to cast to signed values.
+ s << " CordRepRing(" << &rep << ", length = " << rep.length
+ << ", head = " << rep.head_ << ", tail = " << rep.tail_
+ << ", cap = " << rep.capacity_ << ", rc = " << rep.refcount.Get()
+ << ", begin_pos_ = " << static_cast<ptrdiff_t>(rep.begin_pos_) << ") {\n";
+ CordRepRing::index_type head = rep.head();
+ do {
+ CordRep* child = rep.entry_child(head);
+ s << " entry[" << head << "] length = " << rep.entry_length(head)
+ << ", child " << child << ", clen = " << child->length
+ << ", tag = " << static_cast<int>(child->tag)
+ << ", rc = " << child->refcount.Get()
+ << ", offset = " << rep.entry_data_offset(head)
+ << ", end_pos = " << static_cast<ptrdiff_t>(rep.entry_end_pos(head))
+ << "\n";
+ head = rep.advance(head);
+ } while (head != rep.tail());
+ return s << "}\n";
+}
+
+void CordRepRing::AddDataOffset(index_type index, size_t n) {
+ entry_data_offset()[index] += static_cast<offset_type>(n);
+}
+
+void CordRepRing::SubLength(index_type index, size_t n) {
+ entry_end_pos()[index] -= n;
+}
+
+class CordRepRing::Filler {
+ public:
+ Filler(CordRepRing* rep, index_type pos) : rep_(rep), head_(pos), pos_(pos) {}
+
+ index_type head() const { return head_; }
+ index_type pos() const { return pos_; }
+
+ void Add(CordRep* child, size_t offset, pos_type end_pos) {
+ rep_->entry_end_pos()[pos_] = end_pos;
+ rep_->entry_child()[pos_] = child;
+ rep_->entry_data_offset()[pos_] = static_cast<offset_type>(offset);
+ pos_ = rep_->advance(pos_);
+ }
+
+ private:
+ CordRepRing* rep_;
+ index_type head_;
+ index_type pos_;
+};
+
+constexpr size_t CordRepRing::kMaxCapacity; // NOLINT: needed for c++11
+
+bool CordRepRing::IsValid(std::ostream& output) const {
+ if (capacity_ == 0) {
+ output << "capacity == 0";
+ return false;
+ }
+
+ if (head_ >= capacity_ || tail_ >= capacity_) {
+ output << "head " << head_ << " and/or tail " << tail_ << "exceed capacity "
+ << capacity_;
+ return false;
+ }
+
+ const index_type back = retreat(tail_);
+ size_t pos_length = Distance(begin_pos_, entry_end_pos(back));
+ if (pos_length != length) {
+ output << "length " << length << " does not match positional length "
+ << pos_length << " from begin_pos " << begin_pos_ << " and entry["
+ << back << "].end_pos " << entry_end_pos(back);
+ return false;
+ }
+
+ index_type head = head_;
+ pos_type begin_pos = begin_pos_;
+ do {
+ pos_type end_pos = entry_end_pos(head);
+ size_t entry_length = Distance(begin_pos, end_pos);
+ if (entry_length == 0) {
+ output << "entry[" << head << "] has an invalid length " << entry_length
+ << " from begin_pos " << begin_pos << " and end_pos " << end_pos;
+ return false;
+ }
+
+ CordRep* child = entry_child(head);
+ if (child == nullptr) {
+ output << "entry[" << head << "].child == nullptr";
+ return false;
+ }
+ if (child->tag < FLAT && child->tag != EXTERNAL) {
+ output << "entry[" << head << "].child has an invalid tag "
+ << static_cast<int>(child->tag);
+ return false;
+ }
+
+ size_t offset = entry_data_offset(head);
+ if (offset >= child->length || entry_length > child->length - offset) {
+ output << "entry[" << head << "] has offset " << offset
+ << " and entry length " << entry_length
+ << " which are outside of the childs length of " << child->length;
+ return false;
+ }
+
+ begin_pos = end_pos;
+ head = advance(head);
+ } while (head != tail_);
+
+ return true;
+}
+
+#ifdef EXTRA_CORD_RING_VALIDATION
+CordRepRing* CordRepRing::Validate(CordRepRing* rep, const char* file,
+ int line) {
+ if (!rep->IsValid(std::cerr)) {
+ std::cerr << "\nERROR: CordRepRing corrupted";
+ if (line) std::cerr << " at line " << line;
+ if (file) std::cerr << " in file " << file;
+ std::cerr << "\nContent = " << *rep;
+ abort();
+ }
+ return rep;
+}
+#endif // EXTRA_CORD_RING_VALIDATION
+
+CordRepRing* CordRepRing::New(size_t capacity, size_t extra) {
+ CheckCapacity(capacity, extra);
+
+ size_t size = AllocSize(capacity += extra);
+ void* mem = ::operator new(size);
+ auto* rep = new (mem) CordRepRing(static_cast<index_type>(capacity));
+ rep->tag = RING;
+ rep->capacity_ = static_cast<index_type>(capacity);
+ rep->begin_pos_ = 0;
+ return rep;
+}
+
+void CordRepRing::SetCapacityForTesting(size_t capacity) {
+ // Adjust for the changed layout
+ assert(capacity <= capacity_);
+ assert(head() == 0 || head() < tail());
+ memmove(Layout::Partial(capacity).Pointer<1>(data_) + head(),
+ Layout::Partial(capacity_).Pointer<1>(data_) + head(),
+ entries() * sizeof(Layout::ElementType<1>));
+ memmove(Layout::Partial(capacity, capacity).Pointer<2>(data_) + head(),
+ Layout::Partial(capacity_, capacity_).Pointer<2>(data_) + head(),
+ entries() * sizeof(Layout::ElementType<2>));
+ capacity_ = static_cast<index_type>(capacity);
+}
+
+void CordRepRing::Delete(CordRepRing* rep) {
+ assert(rep != nullptr && rep->tag == RING);
+#if defined(__cpp_sized_deallocation)
+ size_t size = AllocSize(rep->capacity_);
+ rep->~CordRepRing();
+ ::operator delete(rep, size);
+#else
+ rep->~CordRepRing();
+ ::operator delete(rep);
+#endif
+}
+
+void CordRepRing::Destroy(CordRepRing* rep) {
+ UnrefEntries(rep, rep->head(), rep->tail());
+ Delete(rep);
+}
+
+template <bool ref>
+void CordRepRing::Fill(const CordRepRing* src, index_type head,
+ index_type tail) {
+ this->length = src->length;
+ head_ = 0;
+ tail_ = advance(0, src->entries(head, tail));
+ begin_pos_ = src->begin_pos_;
+
+ // TODO(mvels): there may be opportunities here for large buffers.
+ auto* dst_pos = entry_end_pos();
+ auto* dst_child = entry_child();
+ auto* dst_offset = entry_data_offset();
+ src->ForEach(head, tail, [&](index_type index) {
+ *dst_pos++ = src->entry_end_pos(index);
+ CordRep* child = src->entry_child(index);
+ *dst_child++ = ref ? CordRep::Ref(child) : child;
+ *dst_offset++ = src->entry_data_offset(index);
+ });
+}
+
+CordRepRing* CordRepRing::Copy(CordRepRing* rep, index_type head,
+ index_type tail, size_t extra) {
+ CordRepRing* newrep = CordRepRing::New(rep->entries(head, tail), extra);
+ newrep->Fill<true>(rep, head, tail);
+ CordRep::Unref(rep);
+ return newrep;
+}
+
+CordRepRing* CordRepRing::Mutable(CordRepRing* rep, size_t extra) {
+ // Get current number of entries, and check for max capacity.
+ size_t entries = rep->entries();
+
+ size_t min_extra = (std::max)(extra, rep->capacity() * 2 - entries);
+ if (!rep->refcount.IsOne()) {
+ return Copy(rep, rep->head(), rep->tail(), min_extra);
+ } else if (entries + extra > rep->capacity()) {
+ CordRepRing* newrep = CordRepRing::New(entries, min_extra);
+ newrep->Fill<false>(rep, rep->head(), rep->tail());
+ CordRepRing::Delete(rep);
+ return newrep;
+ } else {
+ return rep;
+ }
+}
+
+Span<char> CordRepRing::GetAppendBuffer(size_t size) {
+ assert(refcount.IsOne());
+ index_type back = retreat(tail_);
+ CordRep* child = entry_child(back);
+ if (child->tag >= FLAT && child->refcount.IsOne()) {
+ size_t capacity = child->flat()->Capacity();
+ pos_type end_pos = entry_end_pos(back);
+ size_t data_offset = entry_data_offset(back);
+ size_t entry_length = Distance(entry_begin_pos(back), end_pos);
+ size_t used = data_offset + entry_length;
+ if (size_t n = (std::min)(capacity - used, size)) {
+ child->length = data_offset + entry_length + n;
+ entry_end_pos()[back] = end_pos + n;
+ this->length += n;
+ return {child->flat()->Data() + used, n};
+ }
+ }
+ return {nullptr, 0};
+}
+
+Span<char> CordRepRing::GetPrependBuffer(size_t size) {
+ assert(refcount.IsOne());
+ CordRep* child = entry_child(head_);
+ size_t data_offset = entry_data_offset(head_);
+ if (data_offset && child->refcount.IsOne() && child->tag >= FLAT) {
+ size_t n = (std::min)(data_offset, size);
+ this->length += n;
+ begin_pos_ -= n;
+ data_offset -= n;
+ entry_data_offset()[head_] = static_cast<offset_type>(data_offset);
+ return {child->flat()->Data() + data_offset, n};
+ }
+ return {nullptr, 0};
+}
+
+CordRepRing* CordRepRing::CreateFromLeaf(CordRep* child, size_t offset,
+ size_t length, size_t extra) {
+ CordRepRing* rep = CordRepRing::New(1, extra);
+ rep->head_ = 0;
+ rep->tail_ = rep->advance(0);
+ rep->length = length;
+ rep->entry_end_pos()[0] = length;
+ rep->entry_child()[0] = child;
+ rep->entry_data_offset()[0] = static_cast<offset_type>(offset);
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::CreateSlow(CordRep* child, size_t extra) {
+ CordRepRing* rep = nullptr;
+ Consume(child, [&](CordRep* child, size_t offset, size_t length) {
+ if (IsFlatOrExternal(child)) {
+ rep = rep ? AppendLeaf(rep, child, offset, length)
+ : CreateFromLeaf(child, offset, length, extra);
+ } else if (rep) {
+ rep = AddRing<AddMode::kAppend>(rep, child->ring(), offset, length);
+ } else if (offset == 0 && child->length == length) {
+ rep = Mutable(child->ring(), extra);
+ } else {
+ rep = SubRing(child->ring(), offset, length, extra);
+ }
+ });
+ return Validate(rep, nullptr, __LINE__);
+}
+
+CordRepRing* CordRepRing::Create(CordRep* child, size_t extra) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return CreateFromLeaf(child, 0, length, extra);
+ }
+ if (child->tag == RING) {
+ return Mutable(child->ring(), extra);
+ }
+ return CreateSlow(child, extra);
+}
+
+template <CordRepRing::AddMode mode>
+CordRepRing* CordRepRing::AddRing(CordRepRing* rep, CordRepRing* ring,
+ size_t offset, size_t length) {
+ assert(offset < ring->length);
+ constexpr bool append = mode == AddMode::kAppend;
+ Position head = ring->Find(offset);
+ Position tail = ring->FindTail(head.index, offset + length);
+ const index_type entries = ring->entries(head.index, tail.index);
+
+ rep = Mutable(rep, entries);
+
+ // The delta for making ring[head].end_pos into 'len - offset'
+ const pos_type delta_length =
+ (append ? rep->begin_pos_ + rep->length : rep->begin_pos_ - length) -
+ ring->entry_begin_pos(head.index) - head.offset;
+
+ // Start filling at `tail`, or `entries` before `head`
+ Filler filler(rep, append ? rep->tail_ : rep->retreat(rep->head_, entries));
+
+ if (ring->refcount.IsOne()) {
+ // Copy entries from source stealing the ref and adjusting the end position.
+ // Commit the filler as this is no-op.
+ ring->ForEach(head.index, tail.index, [&](index_type ix) {
+ filler.Add(ring->entry_child(ix), ring->entry_data_offset(ix),
+ ring->entry_end_pos(ix) + delta_length);
+ });
+
+ // Unref entries we did not copy over, and delete source.
+ if (head.index != ring->head_) UnrefEntries(ring, ring->head_, head.index);
+ if (tail.index != ring->tail_) UnrefEntries(ring, tail.index, ring->tail_);
+ CordRepRing::Delete(ring);
+ } else {
+ ring->ForEach(head.index, tail.index, [&](index_type ix) {
+ CordRep* child = ring->entry_child(ix);
+ filler.Add(child, ring->entry_data_offset(ix),
+ ring->entry_end_pos(ix) + delta_length);
+ CordRep::Ref(child);
+ });
+ CordRepRing::Unref(ring);
+ }
+
+ if (head.offset) {
+ // Increase offset of first 'source' entry appended or prepended.
+ // This is always the entry in `filler.head()`
+ rep->AddDataOffset(filler.head(), head.offset);
+ }
+
+ if (tail.offset) {
+ // Reduce length of last 'source' entry appended or prepended.
+ // This is always the entry tailed by `filler.pos()`
+ rep->SubLength(rep->retreat(filler.pos()), tail.offset);
+ }
+
+ // Commit changes
+ rep->length += length;
+ if (append) {
+ rep->tail_ = filler.pos();
+ } else {
+ rep->head_ = filler.head();
+ rep->begin_pos_ -= length;
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::AppendSlow(CordRepRing* rep, CordRep* child) {
+ Consume(child, [&rep](CordRep* child, size_t offset, size_t length) {
+ if (child->tag == RING) {
+ rep = AddRing<AddMode::kAppend>(rep, child->ring(), offset, length);
+ } else {
+ rep = AppendLeaf(rep, child, offset, length);
+ }
+ });
+ return rep;
+}
+
+CordRepRing* CordRepRing::AppendLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length) {
+ rep = Mutable(rep, 1);
+ index_type back = rep->tail_;
+ const pos_type begin_pos = rep->begin_pos_ + rep->length;
+ rep->tail_ = rep->advance(rep->tail_);
+ rep->length += length;
+ rep->entry_end_pos()[back] = begin_pos + length;
+ rep->entry_child()[back] = child;
+ rep->entry_data_offset()[back] = static_cast<offset_type>(offset);
+ return Validate(rep, nullptr, __LINE__);
+}
+
+CordRepRing* CordRepRing::Append(CordRepRing* rep, CordRep* child) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return AppendLeaf(rep, child, 0, length);
+ }
+ if (child->tag == RING) {
+ return AddRing<AddMode::kAppend>(rep, child->ring(), 0, length);
+ }
+ return AppendSlow(rep, child);
+}
+
+CordRepRing* CordRepRing::PrependSlow(CordRepRing* rep, CordRep* child) {
+ RConsume(child, [&](CordRep* child, size_t offset, size_t length) {
+ if (IsFlatOrExternal(child)) {
+ rep = PrependLeaf(rep, child, offset, length);
+ } else {
+ rep = AddRing<AddMode::kPrepend>(rep, child->ring(), offset, length);
+ }
+ });
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::PrependLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length) {
+ rep = Mutable(rep, 1);
+ index_type head = rep->retreat(rep->head_);
+ pos_type end_pos = rep->begin_pos_;
+ rep->head_ = head;
+ rep->length += length;
+ rep->begin_pos_ -= length;
+ rep->entry_end_pos()[head] = end_pos;
+ rep->entry_child()[head] = child;
+ rep->entry_data_offset()[head] = static_cast<offset_type>(offset);
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::Prepend(CordRepRing* rep, CordRep* child) {
+ size_t length = child->length;
+ if (IsFlatOrExternal(child)) {
+ return PrependLeaf(rep, child, 0, length);
+ }
+ if (child->tag == RING) {
+ return AddRing<AddMode::kPrepend>(rep, child->ring(), 0, length);
+ }
+ return PrependSlow(rep, child);
+}
+
+CordRepRing* CordRepRing::Append(CordRepRing* rep, absl::string_view data,
+ size_t extra) {
+ if (rep->refcount.IsOne()) {
+ Span<char> avail = rep->GetAppendBuffer(data.length());
+ if (!avail.empty()) {
+ memcpy(avail.data(), data.data(), avail.length());
+ data.remove_prefix(avail.length());
+ }
+ }
+ if (data.empty()) return Validate(rep);
+
+ const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
+ rep = Mutable(rep, flats);
+
+ Filler filler(rep, rep->tail_);
+ pos_type pos = rep->begin_pos_ + rep->length;
+
+ while (data.length() >= kMaxFlatLength) {
+ auto* flat = CreateFlat(data.data(), kMaxFlatLength);
+ filler.Add(flat, 0, pos += kMaxFlatLength);
+ data.remove_prefix(kMaxFlatLength);
+ }
+
+ if (data.length()) {
+ auto* flat = CreateFlat(data.data(), data.length(), extra);
+ filler.Add(flat, 0, pos += data.length());
+ }
+
+ rep->length = pos - rep->begin_pos_;
+ rep->tail_ = filler.pos();
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::Prepend(CordRepRing* rep, absl::string_view data,
+ size_t extra) {
+ if (rep->refcount.IsOne()) {
+ Span<char> avail = rep->GetPrependBuffer(data.length());
+ if (!avail.empty()) {
+ const char* tail = data.data() + data.length() - avail.length();
+ memcpy(avail.data(), tail, avail.length());
+ data.remove_suffix(avail.length());
+ }
+ }
+ if (data.empty()) return rep;
+
+ const size_t flats = (data.length() - 1) / kMaxFlatLength + 1;
+ rep = Mutable(rep, flats);
+ pos_type pos = rep->begin_pos_;
+ Filler filler(rep, rep->retreat(rep->head_, static_cast<index_type>(flats)));
+
+ size_t first_size = data.size() - (flats - 1) * kMaxFlatLength;
+ CordRepFlat* flat = CordRepFlat::New(first_size + extra);
+ flat->length = first_size + extra;
+ memcpy(flat->Data() + extra, data.data(), first_size);
+ data.remove_prefix(first_size);
+ filler.Add(flat, extra, pos);
+ pos -= first_size;
+
+ while (!data.empty()) {
+ assert(data.size() >= kMaxFlatLength);
+ flat = CreateFlat(data.data(), kMaxFlatLength);
+ filler.Add(flat, 0, pos);
+ pos -= kMaxFlatLength;
+ data.remove_prefix(kMaxFlatLength);
+ }
+
+ rep->head_ = filler.head();
+ rep->length += rep->begin_pos_ - pos;
+ rep->begin_pos_ = pos;
+
+ return Validate(rep);
+}
+
+// 32 entries is 32 * sizeof(pos_type) = 4 cache lines on x86
+static constexpr index_type kBinarySearchThreshold = 32;
+static constexpr index_type kBinarySearchEndCount = 8;
+
+template <bool wrap>
+CordRepRing::index_type CordRepRing::FindBinary(index_type head,
+ index_type tail,
+ size_t offset) const {
+ index_type count = tail + (wrap ? capacity_ : 0) - head;
+ do {
+ count = (count - 1) / 2;
+ assert(count < entries(head, tail_));
+ index_type mid = wrap ? advance(head, count) : head + count;
+ index_type after_mid = wrap ? advance(mid) : mid + 1;
+ bool larger = (offset >= entry_end_offset(mid));
+ head = larger ? after_mid : head;
+ tail = larger ? tail : mid;
+ assert(head != tail);
+ } while (ABSL_PREDICT_TRUE(count > kBinarySearchEndCount));
+ return head;
+}
+
+CordRepRing::Position CordRepRing::FindSlow(index_type head,
+ size_t offset) const {
+ index_type tail = tail_;
+
+ // Binary search until we are good for linear search
+ // Optimize for branchless / non wrapping ops
+ if (tail > head) {
+ index_type count = tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<false>(head, tail, offset);
+ }
+ } else {
+ index_type count = capacity_ + tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<true>(head, tail, offset);
+ }
+ }
+
+ pos_type pos = entry_begin_pos(head);
+ pos_type end_pos = entry_end_pos(head);
+ while (offset >= Distance(begin_pos_, end_pos)) {
+ head = advance(head);
+ pos = end_pos;
+ end_pos = entry_end_pos(head);
+ }
+
+ return {head, offset - Distance(begin_pos_, pos)};
+}
+
+CordRepRing::Position CordRepRing::FindTailSlow(index_type head,
+ size_t offset) const {
+ index_type tail = tail_;
+ const size_t tail_offset = offset - 1;
+
+ // Binary search until we are good for linear search
+ // Optimize for branchless / non wrapping ops
+ if (tail > head) {
+ index_type count = tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<false>(head, tail, tail_offset);
+ }
+ } else {
+ index_type count = capacity_ + tail - head;
+ if (count > kBinarySearchThreshold) {
+ head = FindBinary<true>(head, tail, tail_offset);
+ }
+ }
+
+ size_t end_offset = entry_end_offset(head);
+ while (tail_offset >= end_offset) {
+ head = advance(head);
+ end_offset = entry_end_offset(head);
+ }
+
+ return {advance(head), end_offset - offset};
+}
+
+char CordRepRing::GetCharacter(size_t offset) const {
+ assert(offset < length);
+
+ Position pos = Find(offset);
+ size_t data_offset = entry_data_offset(pos.index) + pos.offset;
+ return GetRepData(entry_child(pos.index))[data_offset];
+}
+
+CordRepRing* CordRepRing::SubRing(CordRepRing* rep, size_t offset,
+ size_t length, size_t extra) {
+ assert(offset <= rep->length);
+ assert(offset <= rep->length - length);
+
+ if (length == 0) {
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ // Find position of first byte
+ Position head = rep->Find(offset);
+ Position tail = rep->FindTail(head.index, offset + length);
+ const size_t new_entries = rep->entries(head.index, tail.index);
+
+ if (rep->refcount.IsOne() && extra <= (rep->capacity() - new_entries)) {
+ // We adopt a privately owned rep and no extra entries needed.
+ if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
+ if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
+ rep->head_ = head.index;
+ rep->tail_ = tail.index;
+ } else {
+ // Copy subset to new rep
+ rep = Copy(rep, head.index, tail.index, extra);
+ head.index = rep->head_;
+ tail.index = rep->tail_;
+ }
+
+ // Adjust begin_pos and length
+ rep->length = length;
+ rep->begin_pos_ += offset;
+
+ // Adjust head and tail blocks
+ if (head.offset) {
+ rep->AddDataOffset(head.index, head.offset);
+ }
+ if (tail.offset) {
+ rep->SubLength(rep->retreat(tail.index), tail.offset);
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::RemovePrefix(CordRepRing* rep, size_t len,
+ size_t extra) {
+ assert(len <= rep->length);
+ if (len == rep->length) {
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ Position head = rep->Find(len);
+ if (rep->refcount.IsOne()) {
+ if (head.index != rep->head_) UnrefEntries(rep, rep->head_, head.index);
+ rep->head_ = head.index;
+ } else {
+ rep = Copy(rep, head.index, rep->tail_, extra);
+ head.index = rep->head_;
+ }
+
+ // Adjust begin_pos and length
+ rep->length -= len;
+ rep->begin_pos_ += len;
+
+ // Adjust head block
+ if (head.offset) {
+ rep->AddDataOffset(head.index, head.offset);
+ }
+
+ return Validate(rep);
+}
+
+CordRepRing* CordRepRing::RemoveSuffix(CordRepRing* rep, size_t len,
+ size_t extra) {
+ assert(len <= rep->length);
+
+ if (len == rep->length) {
+ CordRep::Unref(rep);
+ return nullptr;
+ }
+
+ Position tail = rep->FindTail(rep->length - len);
+ if (rep->refcount.IsOne()) {
+ // We adopt a privately owned rep, scrub.
+ if (tail.index != rep->tail_) UnrefEntries(rep, tail.index, rep->tail_);
+ rep->tail_ = tail.index;
+ } else {
+ // Copy subset to new rep
+ rep = Copy(rep, rep->head_, tail.index, extra);
+ tail.index = rep->tail_;
+ }
+
+ // Adjust length
+ rep->length -= len;
+
+ // Adjust tail block
+ if (tail.offset) {
+ rep->SubLength(rep->retreat(tail.index), tail.offset);
+ }
+
+ return Validate(rep);
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.h
new file mode 100644
index 00000000000..c74d3353fff
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring.h
@@ -0,0 +1,589 @@
+// Copyright 2020 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <iosfwd>
+#include <limits>
+#include <memory>
+
+#include "absl/container/internal/layout.h"
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_flat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// See https://bugs.llvm.org/show_bug.cgi?id=48477
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wshadow"
+#if __has_warning("-Wshadow-field")
+#pragma clang diagnostic ignored "-Wshadow-field"
+#endif
+#endif
+
+// All operations modifying a ring buffer are implemented as static methods
+// requiring a CordRepRing instance with a reference adopted by the method.
+//
+// The methods return the modified ring buffer, which may be equal to the input
+// if the input was not shared, and having large enough capacity to accommodate
+// any newly added node(s). Otherwise, a copy of the input rep with the new
+// node(s) added is returned.
+//
+// Any modification on non shared ring buffers with enough capacity will then
+// require minimum atomic operations. Caller should where possible provide
+// reasonable `extra` hints for both anticipated extra `flat` byte space, as
+// well as anticipated extra nodes required for complex operations.
+//
+// Example of code creating a ring buffer, adding some data to it,
+// and discarding the buffer when done:
+//
+// void FunWithRings() {
+// // Create ring with 3 flats
+// CordRep* flat = CreateFlat("Hello");
+// CordRepRing* ring = CordRepRing::Create(flat, 2);
+// ring = CordRepRing::Append(ring, CreateFlat(" "));
+// ring = CordRepRing::Append(ring, CreateFlat("world"));
+// DoSomethingWithRing(ring);
+// CordRep::Unref(ring);
+// }
+//
+// Example of code Copying an existing ring buffer and modifying it:
+//
+// void MoreFunWithRings(CordRepRing* src) {
+// CordRepRing* ring = CordRep::Ref(src)->ring();
+// ring = CordRepRing::Append(ring, CreateFlat("Hello"));
+// ring = CordRepRing::Append(ring, CreateFlat(" "));
+// ring = CordRepRing::Append(ring, CreateFlat("world"));
+// DoSomethingWithRing(ring);
+// CordRep::Unref(ring);
+// }
+//
+class CordRepRing : public CordRep {
+ public:
+ // `pos_type` represents a 'logical position'. A CordRepRing instance has a
+ // `begin_pos` (default 0), and each node inside the buffer will have an
+ // `end_pos` which is the `end_pos` of the previous node (or `begin_pos`) plus
+ // this node's length. The purpose is to allow for a binary search on this
+ // position, while allowing O(1) prepend and append operations.
+ using pos_type = size_t;
+
+ // `index_type` is the type for the `head`, `tail` and `capacity` indexes.
+ // Ring buffers are limited to having no more than four billion entries.
+ using index_type = uint32_t;
+
+ // `offset_type` is the type for the data offset inside a child rep's data.
+ using offset_type = uint32_t;
+
+ // Position holds the node index and relative offset into the node for
+ // some physical offset in the contained data as returned by the Find()
+ // and FindTail() methods.
+ struct Position {
+ index_type index;
+ size_t offset;
+ };
+
+ // The maximum # of child nodes that can be hosted inside a CordRepRing.
+ static constexpr size_t kMaxCapacity = (std::numeric_limits<uint32_t>::max)();
+
+ // CordRepring can not be default constructed, moved, copied or assigned.
+ CordRepRing() = delete;
+ CordRepRing(const CordRepRing&) = delete;
+ CordRepRing& operator=(const CordRepRing&) = delete;
+
+ // Returns true if this instance is valid, false if some or all of the
+ // invariants are broken. Intended for debug purposes only.
+ // `output` receives an explanation of the broken invariants.
+ bool IsValid(std::ostream& output) const;
+
+ // Returns the size in bytes for a CordRepRing with `capacity' entries.
+ static constexpr size_t AllocSize(size_t capacity);
+
+ // Returns the distance in bytes from `pos` to `end_pos`.
+ static constexpr size_t Distance(pos_type pos, pos_type end_pos);
+
+ // Creates a new ring buffer from the provided `rep`. Adopts a reference
+ // on `rep`. The returned ring buffer has a capacity of at least `extra + 1`
+ static CordRepRing* Create(CordRep* child, size_t extra = 0);
+
+ // `head`, `tail` and `capacity` indexes defining the ring buffer boundaries.
+ index_type head() const { return head_; }
+ index_type tail() const { return tail_; }
+ index_type capacity() const { return capacity_; }
+
+ // Returns the number of entries in this instance.
+ index_type entries() const { return entries(head_, tail_); }
+
+ // Returns the logical begin position of this instance.
+ pos_type begin_pos() const { return begin_pos_; }
+
+ // Returns the number of entries for a given head-tail range.
+ // Requires `head` and `tail` values to be less than `capacity()`.
+ index_type entries(index_type head, index_type tail) const {
+ assert(head < capacity_ && tail < capacity_);
+ return tail - head + ((tail > head) ? 0 : capacity_);
+ }
+
+ // Returns the logical end position of entry `index`.
+ pos_type const& entry_end_pos(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial().Pointer<0>(data_)[index];
+ }
+
+ // Returns the child pointer of entry `index`.
+ CordRep* const& entry_child(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial(capacity()).Pointer<1>(data_)[index];
+ }
+
+ // Returns the data offset of entry `index`
+ offset_type const& entry_data_offset(index_type index) const {
+ assert(IsValidIndex(index));
+ return Layout::Partial(capacity(), capacity()).Pointer<2>(data_)[index];
+ }
+
+ // Appends the provided child node to the `rep` instance.
+ // Adopts a reference from `rep` and `child` which may not be null.
+ // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
+ // containing a FLAT or EXTERNAL node, then flat or external the node is added
+ // 'as is', with an offset added for the SUBSTRING case.
+ // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING or
+ // CONCAT tree, then all child nodes not excluded by any start offset or
+ // length values are added recursively.
+ static CordRepRing* Append(CordRepRing* rep, CordRep* child);
+
+ // Appends the provided string data to the `rep` instance.
+ // This function will attempt to utilize any remaining capacity in the last
+ // node of the input if that node is not shared (directly or indirectly), and
+ // of type FLAT. Remaining data will be added as one or more FLAT nodes.
+ // Any last node added to the ring buffer will be allocated with up to
+ // `extra` bytes of capacity for (anticipated) subsequent append actions.
+ static CordRepRing* Append(CordRepRing* rep, string_view data,
+ size_t extra = 0);
+
+ // Prepends the provided child node to the `rep` instance.
+ // Adopts a reference from `rep` and `child` which may not be null.
+ // If the provided child is a FLAT or EXTERNAL node, or a SUBSTRING node
+ // containing a FLAT or EXTERNAL node, then flat or external the node is
+ // prepended 'as is', with an optional offset added for the SUBSTRING case.
+ // If the provided child is a RING or CONCAT tree, or a SUBSTRING of a RING
+ // or CONCAT tree, then all child nodes not excluded by any start offset or
+ // length values are added recursively.
+ static CordRepRing* Prepend(CordRepRing* rep, CordRep* child);
+
+ // Prepends the provided string data to the `rep` instance.
+ // This function will attempt to utilize any remaining capacity in the first
+ // node of the input if that node is not shared (directly or indirectly), and
+ // of type FLAT. Remaining data will be added as one or more FLAT nodes.
+ // Any first node prepnded to the ring buffer will be allocated with up to
+ // `extra` bytes of capacity for (anticipated) subsequent prepend actions.
+ static CordRepRing* Prepend(CordRepRing* rep, string_view data,
+ size_t extra = 0);
+
+ // Returns a span referencing potentially unused capacity in the last node.
+ // The returned span may be empty if no such capacity is available, or if the
+ // current instance is shared. Else, a span of size `n <= size` is returned.
+ // If non empty, the ring buffer is adjusted to the new length, with the newly
+ // added capacity left uninitialized. Callers should assign a value to the
+ // entire span before any other operations on this instance.
+ Span<char> GetAppendBuffer(size_t size);
+
+ // Returns a span referencing potentially unused capacity in the first node.
+ // This function is identical to GetAppendBuffer except that it returns a span
+ // referencing up to `size` capacity directly before the existing data.
+ Span<char> GetPrependBuffer(size_t size);
+
+ // Returns a cord ring buffer containing `length` bytes of data starting at
+ // `offset`. If the input is not shared, this function will remove all head
+ // and tail child nodes outside of the requested range, and adjust the new
+ // head and tail nodes as required. If the input is shared, this function
+ // returns a new instance sharing some or all of the nodes from the input.
+ static CordRepRing* SubRing(CordRepRing* r, size_t offset, size_t length,
+ size_t extra = 0);
+
+ // Returns a cord ring buffer with the first `length` bytes removed.
+ // If the input is not shared, this function will remove all head child nodes
+ // fully inside the first `length` bytes, and adjust the new head as required.
+ // If the input is shared, this function returns a new instance sharing some
+ // or all of the nodes from the input.
+ static CordRepRing* RemoveSuffix(CordRepRing* r, size_t length,
+ size_t extra = 0);
+
+ // Returns a cord ring buffer with the last `length` bytes removed.
+ // If the input is not shared, this function will remove all head child nodes
+ // fully inside the first `length` bytes, and adjust the new head as required.
+ // If the input is shared, this function returns a new instance sharing some
+ // or all of the nodes from the input.
+ static CordRepRing* RemovePrefix(CordRepRing* r, size_t len,
+ size_t extra = 0);
+
+ // Returns the character at `offset`. Requires that `offset < length`.
+ char GetCharacter(size_t offset) const;
+
+ // Testing only: set capacity to requested capacity.
+ void SetCapacityForTesting(size_t capacity);
+
+ // Returns the CordRep data pointer for the provided CordRep.
+ // Requires that the provided `rep` is either a FLAT or EXTERNAL CordRep.
+ static const char* GetLeafData(const CordRep* rep);
+
+ // Returns the CordRep data pointer for the provided CordRep.
+ // Requires that `rep` is either a FLAT, EXTERNAL, or SUBSTRING CordRep.
+ static const char* GetRepData(const CordRep* rep);
+
+ // Advances the provided position, wrapping around capacity as needed.
+ // Requires `index` < capacity()
+ inline index_type advance(index_type index) const;
+
+ // Advances the provided position by 'n`, wrapping around capacity as needed.
+ // Requires `index` < capacity() and `n` <= capacity.
+ inline index_type advance(index_type index, index_type n) const;
+
+ // Retreats the provided position, wrapping around 0 as needed.
+ // Requires `index` < capacity()
+ inline index_type retreat(index_type index) const;
+
+ // Retreats the provided position by 'n', wrapping around 0 as needed.
+ // Requires `index` < capacity()
+ inline index_type retreat(index_type index, index_type n) const;
+
+ // Returns the logical begin position of entry `index`
+ pos_type const& entry_begin_pos(index_type index) const {
+ return (index == head_) ? begin_pos_ : entry_end_pos(retreat(index));
+ }
+
+ // Returns the physical start offset of entry `index`
+ size_t entry_start_offset(index_type index) const {
+ return Distance(begin_pos_, entry_begin_pos(index));
+ }
+
+ // Returns the physical end offset of entry `index`
+ size_t entry_end_offset(index_type index) const {
+ return Distance(begin_pos_, entry_end_pos(index));
+ }
+
+ // Returns the data length for entry `index`
+ size_t entry_length(index_type index) const {
+ return Distance(entry_begin_pos(index), entry_end_pos(index));
+ }
+
+ // Returns the data for entry `index`
+ absl::string_view entry_data(index_type index) const;
+
+ // Returns the position for `offset` as {index, prefix}. `index` holds the
+ // index of the entry at the specified offset and `prefix` holds the relative
+ // offset inside that entry.
+ // Requires `offset` < length.
+ //
+ // For example we can implement GetCharacter(offset) as:
+ // char GetCharacter(size_t offset) {
+ // Position pos = this->Find(offset);
+ // return this->entry_data(pos.pos)[pos.offset];
+ // }
+ inline Position Find(size_t offset) const;
+
+ // Find starting at `head`
+ inline Position Find(index_type head, size_t offset) const;
+
+ // Returns the tail position for `offset` as {tail index, suffix}.
+ // `tail index` holds holds the index of the entry holding the offset directly
+ // before 'offset` advanced by one. 'suffix` holds the relative offset from
+ // that relative offset in the entry to the end of the entry.
+ // For example, FindTail(length) will return {tail(), 0}, FindTail(length - 5)
+ // will return {retreat(tail), 5)} provided the preceding entry contains at
+ // least 5 bytes of data.
+ // Requires offset >= 1 && offset <= length.
+ //
+ // This function is very useful in functions that need to clip the end of some
+ // ring buffer such as 'RemovePrefix'.
+ // For example, we could implement RemovePrefix for non shared instances as:
+ // void RemoveSuffix(size_t n) {
+ // Position pos = FindTail(length - n);
+ // UnrefEntries(pos.pos, this->tail_);
+ // this->tail_ = pos.pos;
+ // entry(retreat(pos.pos)).end_pos -= pos.offset;
+ // }
+ inline Position FindTail(size_t offset) const;
+
+ // Find tail starting at `head`
+ inline Position FindTail(index_type head, size_t offset) const;
+
+ // Invokes f(index_type index) for each entry inside the range [head, tail>
+ template <typename F>
+ void ForEach(index_type head, index_type tail, F&& f) const {
+ index_type n1 = (tail > head) ? tail : capacity_;
+ for (index_type i = head; i < n1; ++i) f(i);
+ if (tail <= head) {
+ for (index_type i = 0; i < tail; ++i) f(i);
+ }
+ }
+
+ // Invokes f(index_type index) for each entry inside this instance.
+ template <typename F>
+ void ForEach(F&& f) const {
+ ForEach(head_, tail_, std::forward<F>(f));
+ }
+
+ // Dump this instance's data tp stream `s` in human readable format, excluding
+ // the actual data content itself. Intended for debug purposes only.
+ friend std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
+
+ private:
+ enum class AddMode { kAppend, kPrepend };
+
+ using Layout = container_internal::Layout<pos_type, CordRep*, offset_type>;
+
+ class Filler;
+ class Transaction;
+ class CreateTransaction;
+
+ static constexpr size_t kLayoutAlignment = Layout::Partial().Alignment();
+
+ // Creates a new CordRepRing.
+ explicit CordRepRing(index_type capacity) : capacity_(capacity) {}
+
+ // Returns true if `index` is a valid index into this instance.
+ bool IsValidIndex(index_type index) const;
+
+ // Debug use only: validates the provided CordRepRing invariants.
+ // Verification of all CordRepRing methods can be enabled by defining
+ // EXTRA_CORD_RING_VALIDATION, i.e.: `--copts=-DEXTRA_CORD_RING_VALIDATION`
+ // Verification is VERY expensive, so only do it for debugging purposes.
+ static CordRepRing* Validate(CordRepRing* rep, const char* file = nullptr,
+ int line = 0);
+
+ // Allocates a CordRepRing large enough to hold `capacity + extra' entries.
+ // The returned capacity may be larger if the allocated memory allows for it.
+ // The maximum capacity of a CordRepRing is capped at kMaxCapacity.
+ // Throws `std::length_error` if `capacity + extra' exceeds kMaxCapacity.
+ static CordRepRing* New(size_t capacity, size_t extra);
+
+ // Deallocates (but does not destroy) the provided ring buffer.
+ static void Delete(CordRepRing* rep);
+
+ // Destroys the provided ring buffer, decrementing the reference count of all
+ // contained child CordReps. The provided 1\`rep` should have a ref count of
+ // one (pre decrement destroy call observing `refcount.IsOne()`) or zero (post
+ // decrement destroy call observing `!refcount.Decrement()`).
+ static void Destroy(CordRepRing* rep);
+
+ // Returns a mutable reference to the logical end position array.
+ pos_type* entry_end_pos() {
+ return Layout::Partial().Pointer<0>(data_);
+ }
+
+ // Returns a mutable reference to the child pointer array.
+ CordRep** entry_child() {
+ return Layout::Partial(capacity()).Pointer<1>(data_);
+ }
+
+ // Returns a mutable reference to the data offset array.
+ offset_type* entry_data_offset() {
+ return Layout::Partial(capacity(), capacity()).Pointer<2>(data_);
+ }
+
+ // Find implementations for the non fast path 0 / length cases.
+ Position FindSlow(index_type head, size_t offset) const;
+ Position FindTailSlow(index_type head, size_t offset) const;
+
+ // Finds the index of the first node that is inside a reasonable distance
+ // of the node at `offset` from which we can continue with a linear search.
+ template <bool wrap>
+ index_type FindBinary(index_type head, index_type tail, size_t offset) const;
+
+ // Fills the current (initialized) instance from the provided source, copying
+ // entries [head, tail). Adds a reference to copied entries if `ref` is true.
+ template <bool ref>
+ void Fill(const CordRepRing* src, index_type head, index_type tail);
+
+ // Create a copy of 'rep', copying all entries [head, tail), allocating room
+ // for `extra` entries. Adds a reference on all copied entries.
+ static CordRepRing* Copy(CordRepRing* rep, index_type head, index_type tail,
+ size_t extra = 0);
+
+ // Returns a Mutable CordRepRing reference from `rep` with room for at least
+ // `extra` additional nodes. Adopts a reference count from `rep`.
+ // This function will return `rep` if, and only if:
+ // - rep.entries + extra <= rep.capacity
+ // - rep.refcount == 1
+ // Otherwise, this function will create a new copy of `rep` with additional
+ // capacity to satisfy `extra` extra nodes, and unref the old `rep` instance.
+ //
+ // If a new CordRepRing can not be allocated, or the new capacity would exceed
+ // the maxmimum capacity, then the input is consumed only, and an exception is
+ // thrown.
+ static CordRepRing* Mutable(CordRepRing* rep, size_t extra);
+
+ // Slow path for Append(CordRepRing* rep, CordRep* child). This function is
+ // exercised if the provided `child` in Append() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* AppendSlow(CordRepRing* rep, CordRep* child);
+
+ // Appends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
+ static CordRepRing* AppendLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length);
+
+ // Prepends the provided leaf node. Requires `child` to be FLAT or EXTERNAL.
+ static CordRepRing* PrependLeaf(CordRepRing* rep, CordRep* child,
+ size_t offset, size_t length);
+
+ // Slow path for Prepend(CordRepRing* rep, CordRep* child). This function is
+ // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* PrependSlow(CordRepRing* rep, CordRep* child);
+
+ // Slow path for Create(CordRep* child, size_t extra). This function is
+ // exercised if the provided `child` in Prepend() is not a leaf node, i.e., a
+ // ring buffer or old (concat) cord tree.
+ static CordRepRing* CreateSlow(CordRep* child, size_t extra);
+
+ // Creates a new ring buffer from the provided `child` leaf node. Requires
+ // `child` to be FLAT or EXTERNAL. on `rep`.
+ // The returned ring buffer has a capacity of at least `1 + extra`
+ static CordRepRing* CreateFromLeaf(CordRep* child, size_t offset,
+ size_t length, size_t extra);
+
+ // Appends or prepends (depending on AddMode) the ring buffer in `ring' to
+ // `rep` starting at `offset` with length `length`.
+ template <AddMode mode>
+ static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring,
+ size_t offset, size_t length);
+
+ // Increases the data offset for entry `index` by `n`.
+ void AddDataOffset(index_type index, size_t n);
+
+ // Descreases the length for entry `index` by `n`.
+ void SubLength(index_type index, size_t n);
+
+ index_type head_;
+ index_type tail_;
+ index_type capacity_;
+ pos_type begin_pos_;
+
+ alignas(kLayoutAlignment) char data_[kLayoutAlignment];
+
+ friend struct CordRep;
+};
+
+constexpr size_t CordRepRing::AllocSize(size_t capacity) {
+ return sizeof(CordRepRing) - sizeof(data_) +
+ Layout(capacity, capacity, capacity).AllocSize();
+}
+
+inline constexpr size_t CordRepRing::Distance(pos_type pos, pos_type end_pos) {
+ return (end_pos - pos);
+}
+
+inline const char* CordRepRing::GetLeafData(const CordRep* rep) {
+ return rep->tag != EXTERNAL ? rep->flat()->Data() : rep->external()->base;
+}
+
+inline const char* CordRepRing::GetRepData(const CordRep* rep) {
+ if (rep->tag >= FLAT) return rep->flat()->Data();
+ if (rep->tag == EXTERNAL) return rep->external()->base;
+ return GetLeafData(rep->substring()->child) + rep->substring()->start;
+}
+
+inline CordRepRing::index_type CordRepRing::advance(index_type index) const {
+ assert(index < capacity_);
+ return ++index == capacity_ ? 0 : index;
+}
+
+inline CordRepRing::index_type CordRepRing::advance(index_type index,
+ index_type n) const {
+ assert(index < capacity_ && n <= capacity_);
+ return (index += n) >= capacity_ ? index - capacity_ : index;
+}
+
+inline CordRepRing::index_type CordRepRing::retreat(index_type index) const {
+ assert(index < capacity_);
+ return (index > 0 ? index : capacity_) - 1;
+}
+
+inline CordRepRing::index_type CordRepRing::retreat(index_type index,
+ index_type n) const {
+ assert(index < capacity_ && n <= capacity_);
+ return index >= n ? index - n : capacity_ - n + index;
+}
+
+inline absl::string_view CordRepRing::entry_data(index_type index) const {
+ size_t data_offset = entry_data_offset(index);
+ return {GetRepData(entry_child(index)) + data_offset, entry_length(index)};
+}
+
+inline bool CordRepRing::IsValidIndex(index_type index) const {
+ if (index >= capacity_) return false;
+ return (tail_ > head_) ? (index >= head_ && index < tail_)
+ : (index >= head_ || index < tail_);
+}
+
+#ifndef EXTRA_CORD_RING_VALIDATION
+inline CordRepRing* CordRepRing::Validate(CordRepRing* rep,
+ const char* /*file*/, int /*line*/) {
+ return rep;
+}
+#endif
+
+inline CordRepRing::Position CordRepRing::Find(size_t offset) const {
+ assert(offset < length);
+ return (offset == 0) ? Position{head_, 0} : FindSlow(head_, offset);
+}
+
+inline CordRepRing::Position CordRepRing::Find(index_type head,
+ size_t offset) const {
+ assert(offset < length);
+ assert(IsValidIndex(head) && offset >= entry_start_offset(head));
+ return (offset == 0) ? Position{head_, 0} : FindSlow(head, offset);
+}
+
+inline CordRepRing::Position CordRepRing::FindTail(size_t offset) const {
+ assert(offset > 0 && offset <= length);
+ return (offset == length) ? Position{tail_, 0} : FindTailSlow(head_, offset);
+}
+
+inline CordRepRing::Position CordRepRing::FindTail(index_type head,
+ size_t offset) const {
+ assert(offset > 0 && offset <= length);
+ assert(IsValidIndex(head) && offset >= entry_start_offset(head) + 1);
+ return (offset == length) ? Position{tail_, 0} : FindTailSlow(head, offset);
+}
+
+// Now that CordRepRing is defined, we can define CordRep's helper casts:
+inline CordRepRing* CordRep::ring() {
+ assert(tag == RING);
+ return static_cast<CordRepRing*>(this);
+}
+
+inline const CordRepRing* CordRep::ring() const {
+ assert(tag == RING);
+ return static_cast<const CordRepRing*>(this);
+}
+
+std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h
new file mode 100644
index 00000000000..396c0e2cd83
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h
@@ -0,0 +1,114 @@
+// 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_RING_READER_H_
+#define ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
+
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+
+#include "absl/strings/internal/cord_internal.h"
+#include "absl/strings/internal/cord_rep_ring.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace cord_internal {
+
+// CordRepRingReader provides basic navigation over CordRepRing data.
+class CordRepRingReader {
+ public:
+ // Returns true if this instance is not empty.
+ explicit operator bool() const { return ring_ != nullptr; }
+
+ // Returns the ring buffer reference for this instance, or nullptr if empty.
+ CordRepRing* ring() const { return ring_; }
+
+ // Returns the current node index inside the ring buffer for this instance.
+ // The returned value is undefined if this instance is empty.
+ CordRepRing::index_type index() const { return index_; }
+
+ // Returns the length of the referenced ring buffer.
+ // Requires the current instance to be non empty.
+ size_t length() const {
+ assert(ring_);
+ return ring_->length;
+ }
+
+ // Returns the end offset of the last navigated-to chunk, which represents the
+ // total bytes 'consumed' relative to the start of the ring. The returned
+ // value is never zero. For example, initializing a reader with a ring buffer
+ // with a first chunk of 19 bytes will return consumed() = 19.
+ // Requires the current instance to be non empty.
+ size_t consumed() const {
+ assert(ring_);
+ return ring_->entry_end_offset(index_);
+ }
+
+ // Returns the number of bytes remaining beyond the last navigated-to chunk.
+ // Requires the current instance to be non empty.
+ size_t remaining() const {
+ assert(ring_);
+ return length() - consumed();
+ }
+
+ // Resets this instance to an empty value
+ void Reset() { ring_ = nullptr; }
+
+ // Resets this instance to the start of `ring`. `ring` must not be null.
+ // Returns a reference into the first chunk of the provided ring.
+ absl::string_view Reset(CordRepRing* ring) {
+ assert(ring);
+ ring_ = ring;
+ index_ = ring_->head();
+ return ring_->entry_data(index_);
+ }
+
+ // Navigates to the next chunk inside the reference ring buffer.
+ // Returns a reference into the navigated-to chunk.
+ // Requires remaining() to be non zero.
+ absl::string_view Next() {
+ assert(remaining());
+ index_ = ring_->advance(index_);
+ return ring_->entry_data(index_);
+ }
+
+ // Navigates to the chunk at offset `offset`.
+ // Returns a reference into the navigated-to chunk, adjusted for the relative
+ // position of `offset` into that chunk. For example, calling Seek(13) on a
+ // ring buffer containing 2 chunks of 10 and 20 bytes respectively will return
+ // a string view into the second chunk starting at offset 3 with a size of 17.
+ // Requires `offset` to be less than `length()`
+ absl::string_view Seek(size_t offset) {
+ assert(offset < length());
+ size_t current = ring_->entry_end_offset(index_);
+ CordRepRing::index_type hint = (offset >= current) ? index_ : ring_->head();
+ const CordRepRing::Position head = ring_->Find(hint, offset);
+ index_ = head.index;
+ auto data = ring_->entry_data(head.index);
+ data.remove_prefix(head.offset);
+ return data;
+ }
+
+ private:
+ CordRepRing* ring_ = nullptr;
+ CordRepRing::index_type index_;
+};
+
+} // namespace cord_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_READER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.cc
new file mode 100644
index 00000000000..c5271286ad0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.cc
@@ -0,0 +1,180 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/escaping.h"
+
+#include "absl/base/internal/endian.h"
+#include "absl/base/internal/raw_logging.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+const char kBase64Chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding) {
+ // Base64 encodes three bytes of input at a time. If the input is not
+ // divisible by three, we pad as appropriate.
+ //
+ // (from https://tools.ietf.org/html/rfc3548)
+ // Special processing is performed if fewer than 24 bits are available
+ // at the end of the data being encoded. A full encoding quantum is
+ // always completed at the end of a quantity. When fewer than 24 input
+ // bits are available in an input group, zero bits are added (on the
+ // right) to form an integral number of 6-bit groups. Padding at the
+ // end of the data is performed using the '=' character. Since all base
+ // 64 input is an integral number of octets, only the following cases
+ // can arise:
+
+ // Base64 encodes each three bytes of input into four bytes of output.
+ size_t len = (input_len / 3) * 4;
+
+ if (input_len % 3 == 0) {
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (1) the final quantum of encoding input is an integral multiple of 24
+ // bits; here, the final unit of encoded output will be an integral
+ // multiple of 4 characters with no "=" padding,
+ } else if (input_len % 3 == 1) {
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (2) the final quantum of encoding input is exactly 8 bits; here, the
+ // final unit of encoded output will be two characters followed by two
+ // "=" padding characters, or
+ len += 2;
+ if (do_padding) {
+ len += 2;
+ }
+ } else { // (input_len % 3 == 2)
+ // (from https://tools.ietf.org/html/rfc3548)
+ // (3) the final quantum of encoding input is exactly 16 bits; here, the
+ // final unit of encoded output will be three characters followed by one
+ // "=" padding character.
+ len += 3;
+ if (do_padding) {
+ len += 1;
+ }
+ }
+
+ assert(len >= input_len); // make sure we didn't overflow
+ return len;
+}
+
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+ size_t szdest, const char* base64,
+ bool do_padding) {
+ static const char kPad64 = '=';
+
+ if (szsrc * 4 > szdest * 3) return 0;
+
+ char* cur_dest = dest;
+ const unsigned char* cur_src = src;
+
+ char* const limit_dest = dest + szdest;
+ const unsigned char* const limit_src = src + szsrc;
+
+ // Three bytes of data encodes to four characters of cyphertext.
+ // So we can pump through three-byte chunks atomically.
+ if (szsrc >= 3) { // "limit_src - 3" is UB if szsrc < 3.
+ while (cur_src < limit_src - 3) { // While we have >= 32 bits.
+ uint32_t in = absl::big_endian::Load32(cur_src) >> 8;
+
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+
+ cur_dest += 4;
+ cur_src += 3;
+ }
+ }
+ // To save time, we didn't update szdest or szsrc in the loop. So do it now.
+ szdest = limit_dest - cur_dest;
+ szsrc = limit_src - cur_src;
+
+ /* now deal with the tail (<=3 bytes) */
+ switch (szsrc) {
+ case 0:
+ // Nothing left; nothing more to do.
+ break;
+ case 1: {
+ // One byte left: this encodes to two characters, and (optionally)
+ // two pad characters to round out the four-character cypherblock.
+ if (szdest < 2) return 0;
+ uint32_t in = cur_src[0];
+ cur_dest[0] = base64[in >> 2];
+ in &= 0x3;
+ cur_dest[1] = base64[in << 4];
+ cur_dest += 2;
+ szdest -= 2;
+ if (do_padding) {
+ if (szdest < 2) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest[1] = kPad64;
+ cur_dest += 2;
+ szdest -= 2;
+ }
+ break;
+ }
+ case 2: {
+ // Two bytes left: this encodes to three characters, and (optionally)
+ // one pad character to round out the four-character cypherblock.
+ if (szdest < 3) return 0;
+ uint32_t in = absl::big_endian::Load16(cur_src);
+ cur_dest[0] = base64[in >> 10];
+ in &= 0x3FF;
+ cur_dest[1] = base64[in >> 4];
+ in &= 0x00F;
+ cur_dest[2] = base64[in << 2];
+ cur_dest += 3;
+ szdest -= 3;
+ if (do_padding) {
+ if (szdest < 1) return 0;
+ cur_dest[0] = kPad64;
+ cur_dest += 1;
+ szdest -= 1;
+ }
+ break;
+ }
+ case 3: {
+ // Three bytes left: same as in the big loop above. We can't do this in
+ // the loop because the loop above always reads 4 bytes, and the fourth
+ // byte is past the end of the input.
+ if (szdest < 4) return 0;
+ uint32_t in = (cur_src[0] << 16) + absl::big_endian::Load16(cur_src + 1);
+ cur_dest[0] = base64[in >> 18];
+ in &= 0x3FFFF;
+ cur_dest[1] = base64[in >> 12];
+ in &= 0xFFF;
+ cur_dest[2] = base64[in >> 6];
+ in &= 0x3F;
+ cur_dest[3] = base64[in];
+ cur_dest += 4;
+ szdest -= 4;
+ break;
+ }
+ default:
+ // Should not be reached: blocks of 4 bytes are handled
+ // in the while loop before this switch statement.
+ ABSL_RAW_LOG(FATAL, "Logic problem? szsrc = %zu", szsrc);
+ break;
+ }
+ return (cur_dest - dest);
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.h
new file mode 100644
index 00000000000..6a9ce602d9e
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping.h
@@ -0,0 +1,58 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_ESCAPING_H_
+#define ABSL_STRINGS_INTERNAL_ESCAPING_H_
+
+#include <cassert>
+
+#include "absl/strings/internal/resize_uninitialized.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+ABSL_CONST_INIT extern const char kBase64Chars[];
+
+// Calculates how long a string will be when it is base64 encoded given its
+// length and whether or not the result should be padded.
+size_t CalculateBase64EscapedLenInternal(size_t input_len, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3. Returns the length of `dest`.
+size_t Base64EscapeInternal(const unsigned char* src, size_t szsrc, char* dest,
+ size_t szdest, const char* base64, bool do_padding);
+
+// Base64-encodes `src` using the alphabet provided in `base64` and writes the
+// result to `dest`. If `do_padding` is true, `dest` is padded with '=' chars
+// until its length is a multiple of 3.
+template <typename String>
+void Base64EscapeInternal(const unsigned char* src, size_t szsrc, String* dest,
+ bool do_padding, const char* base64_chars) {
+ const size_t calc_escaped_size =
+ CalculateBase64EscapedLenInternal(szsrc, do_padding);
+ STLStringResizeUninitialized(dest, calc_escaped_size);
+
+ const size_t escaped_len = Base64EscapeInternal(
+ src, szsrc, &(*dest)[0], dest->size(), base64_chars, do_padding);
+ assert(calc_escaped_size == escaped_len);
+ dest->erase(escaped_len);
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_ESCAPING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping_test_common.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping_test_common.h
index cc41f4312c7..7b18017a089 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping_test_common.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/escaping_test_common.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
struct base64_testcase {
@@ -126,6 +127,7 @@ inline const std::array<base64_testcase, 5>& base64_strings() {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_ESCAPING_TEST_COMMON_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.cc
index a0de70dffdb..2519c6881e3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include <cstdlib>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
int memcasecmp(const char* s1, const char* s2, size_t len) {
@@ -107,4 +108,5 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.h
index 7de383b19ec..9ad05358086 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -69,6 +69,7 @@
#include "absl/strings/ascii.h" // for absl::ascii_tolower
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
inline char* memcat(char* dest, size_t destlen, const char* src,
@@ -141,6 +142,7 @@ const char* memmatch(const char* phaystack, size_t haylen, const char* pneedle,
size_t neelen);
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_MEMUTIL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_benchmark.cc
index 77915adb958..dc95c3e5e55 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_test.cc
index 09424de9a47..d8681ddf4e3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/memutil_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/numbers_test_common.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/numbers_test_common.h
index f6241ff3d8e..eaa88a88975 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/numbers_test_common.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/numbers_test_common.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,7 +23,10 @@
#include <limits>
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
template <typename IntType>
@@ -42,8 +45,9 @@ inline bool Itoa(IntType value, int base, std::string* destination) {
while (value != 0) {
const IntType next_value = value / base;
// Can't use std::abs here because of problems when IntType is unsigned.
- int remainder = value > next_value * base ? value - next_value * base
- : next_value * base - value;
+ 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;
@@ -166,7 +170,7 @@ inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
{"0x1234", true, 16, 0x1234},
- // Base-10 std::string version.
+ // Base-10 string version.
{"1234", true, 0, 1234},
{nullptr, false, 0, 0},
}};
@@ -174,6 +178,7 @@ inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_NUMBERS_TEST_COMMON_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.cc
index 6ee2b109088..05324c780c6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/strings/internal/ostringstream.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
OStringStream::Buf::int_type OStringStream::overflow(int c) {
@@ -31,4 +32,5 @@ std::streamsize OStringStream::xsputn(const char* s, std::streamsize n) {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.h
index e81a89affea..d25d60473f6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,20 +23,21 @@
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
-// The same as std::ostringstream but appends to a user-specified string,
+// The same as std::ostringstream but appends to a user-specified std::string,
// and is faster. It is ~70% faster to create, ~50% faster to write to, and
-// completely free to extract the result string.
+// completely free to extract the result std::string.
//
-// string s;
+// std::string s;
// OStringStream strm(&s);
// strm << 42 << ' ' << 3.14; // appends to `s`
//
// The stream object doesn't have to be named. Starting from C++11 operator<<
// works with rvalues of std::ostream.
//
-// string s;
+// std::string s;
// OStringStream(&s) << 42 << ' ' << 3.14; // appends to `s`
//
// OStringStream is faster to create than std::ostringstream but it's still
@@ -45,14 +46,14 @@ namespace strings_internal {
//
// Creates unnecessary instances of OStringStream: slow.
//
-// string s;
+// std::string s;
// OStringStream(&s) << 42;
// OStringStream(&s) << ' ';
// OStringStream(&s) << 3.14;
//
// Creates a single instance of OStringStream and reuses it: fast.
//
-// string s;
+// std::string s;
// OStringStream strm(&s);
// strm << 42;
// strm << ' ';
@@ -64,8 +65,8 @@ class OStringStream : private std::basic_streambuf<char>, public std::ostream {
// The argument can be null, in which case you'll need to call str(p) with a
// non-null argument before you can write to the stream.
//
- // The destructor of OStringStream doesn't use the std::string. It's OK to destroy
- // the std::string before the stream.
+ // The destructor of OStringStream doesn't use the std::string. It's OK to
+ // destroy the std::string before the stream.
explicit OStringStream(std::string* s) : std::ostream(this), s_(s) {}
std::string* str() { return s_; }
@@ -82,6 +83,7 @@ class OStringStream : private std::basic_streambuf<char>, public std::ostream {
};
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_OSTRINGSTREAM_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc
index c93f96909d8..5979f18236e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_test.cc
index 069a0e1fbbb..2879e50eb38 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/ostringstream_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.cc
index 66be163f43f..42e96c3425d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include <cmath>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
namespace {
@@ -117,4 +118,5 @@ double Pow10(int exp) {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.h
index fe7e735a30b..c37c2c3ffee 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,7 +22,10 @@
#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
@@ -31,6 +34,7 @@ namespace strings_internal {
double Pow10(int exp);
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_POW10_HELPER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper_test.cc
index 9a13d5240da..a4ff76d31e1 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/pow10_helper_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,7 @@
#include "absl/strings/str_format.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
namespace {
@@ -117,4 +118,5 @@ TEST(Pow10HelperTest, Works) {
} // namespace
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized.h
index c2da0da9e4a..e42628e3949 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
#include "absl/meta/type_traits.h" // for void_t
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// Is a subclass of true_type or false_type, depending on whether or not
@@ -35,8 +36,7 @@ struct ResizeUninitializedTraits {
static void Resize(string_type* s, size_t new_size) { s->resize(new_size); }
};
-// __resize_default_init is provided by libc++ >= 8.0 and by Google's internal
-// ::string implementation.
+// __resize_default_init is provided by libc++ >= 8.0
template <typename string_type>
struct ResizeUninitializedTraits<
string_type, absl::void_t<decltype(std::declval<string_type&>()
@@ -47,8 +47,8 @@ struct ResizeUninitializedTraits<
}
};
-// Returns true if the string implementation supports a resize where
-// the new characters added to the string are left untouched.
+// Returns true if the std::string implementation supports a resize where
+// the new characters added to the std::string are left untouched.
//
// (A better name might be "STLStringSupportsUninitializedResize", alluding to
// the previous function.)
@@ -60,13 +60,14 @@ inline constexpr bool STLStringSupportsNontrashingResize(string_type*) {
// Like str->resize(new_size), except any new characters added to "*str" as a
// result of resizing may be left uninitialized, rather than being filled with
// '0' bytes. Typically used when code is then going to overwrite the backing
-// store of the string with known data. Uses a Google extension to ::string.
+// store of the std::string with known data.
template <typename string_type, typename = void>
inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
ResizeUninitializedTraits<string_type>::Resize(s, new_size);
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
index 43aece8db10..0f8b3c2a95b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,13 +20,27 @@ namespace {
int resize_call_count = 0;
+// A mock string class whose only purpose is to track how many times its
+// resize() method has been called.
struct resizable_string {
+ size_t size() const { return 0; }
+ char& operator[](size_t) {
+ static char c = '\0';
+ return c;
+ }
void resize(size_t) { resize_call_count += 1; }
};
int resize_default_init_call_count = 0;
+// A mock string class whose only purpose is to track how many times its
+// resize() and __resize_default_init() methods have been called.
struct resize_default_init_string {
+ size_t size() const { return 0; }
+ char& operator[](size_t) {
+ static char c = '\0';
+ return c;
+ }
void resize(size_t) { resize_call_count += 1; }
void __resize_default_init(size_t) { resize_default_init_call_count += 1; }
};
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/stl_type_traits.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/stl_type_traits.h
index 04c4a5323b8..6035ca45cbd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/stl_type_traits.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/stl_type_traits.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -40,6 +40,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
template <typename C, template <typename...> class T>
@@ -242,5 +243,6 @@ struct IsStrictlyBaseOfAndConvertibleToSTLContainer
IsConvertibleToSTLContainer<C>> {};
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STL_TYPE_TRAITS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.cc
index b40be8ff382..e28a29b1716 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
//
// POSIX spec:
// http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
@@ -12,13 +26,13 @@
#include "absl/base/port.h"
#include "absl/strings/internal/str_format/float_conversion.h"
+#include "absl/strings/numbers.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
-const char kDigit[2][32] = { "0123456789abcdef", "0123456789ABCDEF" };
-
// Reduce *capacity by s.size(), clipped to a 0 minimum.
void ReducePadding(string_view s, size_t *capacity) {
*capacity = Excess(s.size(), *capacity);
@@ -32,6 +46,10 @@ void ReducePadding(size_t n, size_t *capacity) {
template <typename T>
struct MakeUnsigned : std::make_unsigned<T> {};
template <>
+struct MakeUnsigned<absl::int128> {
+ using type = absl::uint128;
+};
+template <>
struct MakeUnsigned<absl::uint128> {
using type = absl::uint128;
};
@@ -39,128 +57,183 @@ struct MakeUnsigned<absl::uint128> {
template <typename T>
struct IsSigned : std::is_signed<T> {};
template <>
+struct IsSigned<absl::int128> : std::true_type {};
+template <>
struct IsSigned<absl::uint128> : std::false_type {};
-class ConvertedIntInfo {
+// Integral digit printer.
+// Call one of the PrintAs* routines after construction once.
+// Use with_neg_and_zero/without_neg_or_zero/is_negative to access the results.
+class IntDigits {
public:
+ // Print the unsigned integer as octal.
+ // Supports unsigned integral types and uint128.
template <typename T>
- ConvertedIntInfo(T v, ConversionChar conv) {
- using Unsigned = typename MakeUnsigned<T>::type;
- auto u = static_cast<Unsigned>(v);
- if (IsNeg(v)) {
- is_neg_ = true;
- u = Unsigned{} - u;
- } else {
- is_neg_ = false;
+ void PrintAsOct(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+ do {
+ *--p = static_cast<char>('0' + (static_cast<size_t>(v) & 7));
+ v >>= 3;
+ } while (v);
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
+ }
+
+ // Print the signed or unsigned integer as decimal.
+ // Supports all integral types.
+ template <typename T>
+ void PrintAsDec(T v) {
+ static_assert(std::is_integral<T>::value, "");
+ start_ = storage_;
+ size_ = numbers_internal::FastIntToBuffer(v, storage_) - storage_;
+ }
+
+ void PrintAsDec(int128 v) {
+ auto u = static_cast<uint128>(v);
+ bool add_neg = false;
+ if (v < 0) {
+ add_neg = true;
+ u = uint128{} - u;
}
- UnsignedToStringRight(u, conv);
+ PrintAsDec(u, add_neg);
}
- string_view digits() const {
- return {end() - size_, static_cast<size_t>(size_)};
+ void PrintAsDec(uint128 v, bool add_neg = false) {
+ // This function can be sped up if needed. We can call FastIntToBuffer
+ // twice, or fix FastIntToBuffer to support uint128.
+ char *p = storage_ + sizeof(storage_);
+ do {
+ p -= 2;
+ numbers_internal::PutTwoDigits(static_cast<size_t>(v % 100), p);
+ v /= 100;
+ } while (v);
+ if (p[0] == '0') {
+ // We printed one too many hexits.
+ ++p;
+ }
+ if (add_neg) {
+ *--p = '-';
+ }
+ size_ = storage_ + sizeof(storage_) - p;
+ start_ = p;
}
- bool is_neg() const { return is_neg_; }
- private:
- template <typename T, bool IsSigned>
- struct IsNegImpl {
- static bool Eval(T v) { return v < 0; }
- };
+ // Print the unsigned integer as hex using lowercase.
+ // Supports unsigned integral types and uint128.
template <typename T>
- struct IsNegImpl<T, false> {
- static bool Eval(T) {
- return false;
+ void PrintAsHexLower(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+
+ do {
+ p -= 2;
+ constexpr const char* table = numbers_internal::kHexTable;
+ std::memcpy(p, table + 2 * (static_cast<size_t>(v) & 0xFF), 2);
+ if (sizeof(T) == 1) break;
+ v >>= 8;
+ } while (v);
+ if (p[0] == '0') {
+ // We printed one too many digits.
+ ++p;
}
- };
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
+ }
+ // Print the unsigned integer as hex using uppercase.
+ // Supports unsigned integral types and uint128.
template <typename T>
- bool IsNeg(T v) {
- return IsNegImpl<T, IsSigned<T>::value>::Eval(v);
+ void PrintAsHexUpper(T v) {
+ static_assert(!IsSigned<T>::value, "");
+ char *p = storage_ + sizeof(storage_);
+
+ // kHexTable is only lowercase, so do it manually for uppercase.
+ do {
+ *--p = "0123456789ABCDEF"[static_cast<size_t>(v) & 15];
+ v >>= 4;
+ } while (v);
+ start_ = p;
+ size_ = storage_ + sizeof(storage_) - p;
}
- template <typename T>
- void UnsignedToStringRight(T u, ConversionChar conv) {
- char *p = end();
- switch (conv.radix()) {
- default:
- case 10:
- for (; u; u /= 10)
- *--p = static_cast<char>('0' + static_cast<size_t>(u % 10));
- break;
- case 8:
- for (; u; u /= 8)
- *--p = static_cast<char>('0' + static_cast<size_t>(u % 8));
- break;
- case 16: {
- const char *digits = kDigit[conv.upper() ? 1 : 0];
- for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
- break;
- }
- }
- size_ = static_cast<int>(end() - p);
+ // The printed value including the '-' sign if available.
+ // For inputs of value `0`, this will return "0"
+ string_view with_neg_and_zero() const { return {start_, size_}; }
+
+ // The printed value not including the '-' sign.
+ // For inputs of value `0`, this will return "".
+ string_view without_neg_or_zero() const {
+ static_assert('-' < '0', "The check below verifies both.");
+ size_t advance = start_[0] <= '0' ? 1 : 0;
+ return {start_ + advance, size_ - advance};
}
- const char *end() const { return storage_ + sizeof(storage_); }
- char *end() { return storage_ + sizeof(storage_); }
+ bool is_negative() const { return start_[0] == '-'; }
- bool is_neg_;
- int size_;
- // Max size: 128 bit value as octal -> 43 digits
- char storage_[128 / 3 + 1];
+ private:
+ const char *start_;
+ size_t size_;
+ // Max size: 128 bit value as octal -> 43 digits, plus sign char
+ char storage_[128 / 3 + 1 + 1];
};
// Note: 'o' conversions do not have a base indicator, it's just that
// the '#' flag is specified to modify the precision for 'o' conversions.
-string_view BaseIndicator(const ConvertedIntInfo &info,
- const ConversionSpec conv) {
- bool alt = conv.flags().alt;
- int radix = conv.conv().radix();
- if (conv.conv().id() == ConversionChar::p)
- alt = true; // always show 0x for %p.
+string_view BaseIndicator(const IntDigits &as_digits,
+ const FormatConversionSpecImpl conv) {
+ // always show 0x for %p.
+ bool alt = conv.has_alt_flag() ||
+ conv.conversion_char() == FormatConversionCharInternal::p;
+ bool hex = (conv.conversion_char() == FormatConversionCharInternal::x ||
+ conv.conversion_char() == FormatConversionCharInternal::X ||
+ conv.conversion_char() == FormatConversionCharInternal::p);
// From the POSIX description of '#' flag:
// "For x or X conversion specifiers, a non-zero result shall have
// 0x (or 0X) prefixed to it."
- if (alt && radix == 16 && !info.digits().empty()) {
- if (conv.conv().upper()) return "0X";
- return "0x";
+ if (alt && hex && !as_digits.without_neg_or_zero().empty()) {
+ return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
+ : "0x";
}
return {};
}
-string_view SignColumn(bool neg, const ConversionSpec conv) {
- if (conv.conv().is_signed()) {
+string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
+ if (conv.conversion_char() == FormatConversionCharInternal::d ||
+ conv.conversion_char() == FormatConversionCharInternal::i) {
if (neg) return "-";
- if (conv.flags().show_pos) return "+";
- if (conv.flags().sign_col) return " ";
+ if (conv.has_show_pos_flag()) return "+";
+ if (conv.has_sign_col_flag()) return " ";
}
return {};
}
-bool ConvertCharImpl(unsigned char v, const ConversionSpec conv,
+bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
ReducePadding(1, &fill);
- if (!conv.flags().left) sink->Append(fill, ' ');
+ if (!conv.has_left_flag()) sink->Append(fill, ' ');
sink->Append(1, v);
- if (conv.flags().left) sink->Append(fill, ' ');
+ if (conv.has_left_flag()) sink->Append(fill, ' ');
return true;
}
-bool ConvertIntImplInner(const ConvertedIntInfo &info,
- const ConversionSpec conv, FormatSinkImpl *sink) {
+bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
// Print as a sequence of Substrings:
// [left_spaces][sign][base_indicator][zeroes][formatted][right_spaces]
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
- string_view formatted = info.digits();
+ string_view formatted = as_digits.without_neg_or_zero();
ReducePadding(formatted, &fill);
- string_view sign = SignColumn(info.is_neg(), conv);
+ string_view sign = SignColumn(as_digits.is_negative(), conv);
ReducePadding(sign, &fill);
- string_view base_indicator = BaseIndicator(info, conv);
+ string_view base_indicator = BaseIndicator(as_digits, conv);
ReducePadding(base_indicator, &fill);
int precision = conv.precision();
@@ -168,7 +241,8 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info,
if (!precision_specified)
precision = 1;
- if (conv.flags().alt && conv.conv().id() == ConversionChar::o) {
+ if (conv.has_alt_flag() &&
+ conv.conversion_char() == FormatConversionCharInternal::o) {
// From POSIX description of the '#' (alt) flag:
// "For o conversion, it increases the precision (if necessary) to
// force the first digit of the result to be zero."
@@ -181,13 +255,13 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info,
size_t num_zeroes = Excess(formatted.size(), precision);
ReducePadding(num_zeroes, &fill);
- size_t num_left_spaces = !conv.flags().left ? fill : 0;
- size_t num_right_spaces = conv.flags().left ? fill : 0;
+ size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
+ size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
// From POSIX description of the '0' (zero) flag:
// "For d, i, o, u, x, and X conversion specifiers, if a precision
// is specified, the '0' flag is ignored."
- if (!precision_specified && conv.flags().zero) {
+ if (!precision_specified && conv.has_zero_flag()) {
num_zeroes += num_left_spaces;
num_left_spaces = 0;
}
@@ -202,72 +276,97 @@ bool ConvertIntImplInner(const ConvertedIntInfo &info,
}
template <typename T>
-bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
- ConvertedIntInfo info(v, conv.conv());
- if (conv.flags().basic && conv.conv().id() != ConversionChar::p) {
- if (info.is_neg()) sink->Append(1, '-');
- if (info.digits().empty()) {
- sink->Append(1, '0');
- } else {
- sink->Append(info.digits());
- }
- return true;
+bool ConvertIntArg(T v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ using U = typename MakeUnsigned<T>::type;
+ IntDigits as_digits;
+
+ // This odd casting is due to a bug in -Wswitch behavior in gcc49 which causes
+ // it to complain about a switch/case type mismatch, even though both are
+ // FormatConverionChar. Likely this is because at this point
+ // FormatConversionChar is declared, but not defined.
+ switch (static_cast<uint8_t>(conv.conversion_char())) {
+ case static_cast<uint8_t>(FormatConversionCharInternal::c):
+ return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::o):
+ as_digits.PrintAsOct(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::x):
+ as_digits.PrintAsHexLower(static_cast<U>(v));
+ break;
+ case static_cast<uint8_t>(FormatConversionCharInternal::X):
+ as_digits.PrintAsHexUpper(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::u):
+ as_digits.PrintAsDec(static_cast<U>(v));
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::d):
+ case static_cast<uint8_t>(FormatConversionCharInternal::i):
+ as_digits.PrintAsDec(v);
+ break;
+
+ case static_cast<uint8_t>(FormatConversionCharInternal::a):
+ case static_cast<uint8_t>(FormatConversionCharInternal::e):
+ case static_cast<uint8_t>(FormatConversionCharInternal::f):
+ case static_cast<uint8_t>(FormatConversionCharInternal::g):
+ case static_cast<uint8_t>(FormatConversionCharInternal::A):
+ case static_cast<uint8_t>(FormatConversionCharInternal::E):
+ case static_cast<uint8_t>(FormatConversionCharInternal::F):
+ case static_cast<uint8_t>(FormatConversionCharInternal::G):
+ return ConvertFloatImpl(static_cast<double>(v), conv, sink);
+
+ default:
+ ABSL_INTERNAL_ASSUME(false);
}
- return ConvertIntImplInner(info, conv, sink);
-}
-template <typename T>
-bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
- if (conv.conv().is_float()) {
- return FormatConvertImpl(static_cast<double>(v), conv, sink).value;
- }
- if (conv.conv().id() == ConversionChar::c)
- return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
- if (!conv.conv().is_integral())
- return false;
- if (!conv.conv().is_signed() && IsSigned<T>::value) {
- using U = typename MakeUnsigned<T>::type;
- return FormatConvertImpl(static_cast<U>(v), conv, sink).value;
+ if (conv.is_basic()) {
+ sink->Append(as_digits.with_neg_and_zero());
+ return true;
}
- return ConvertIntImplInner(v, conv, sink);
+ return ConvertIntImplInnerSlow(as_digits, conv, sink);
}
template <typename T>
-bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
- return conv.conv().is_float() && ConvertFloatImpl(v, conv, sink);
+bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ return FormatConversionCharIsFloat(conv.conversion_char()) &&
+ ConvertFloatImpl(v, conv, sink);
}
-inline bool ConvertStringArg(string_view v, const ConversionSpec conv,
+inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
- if (conv.conv().id() != ConversionChar::s)
- return false;
- if (conv.flags().basic) {
+ if (conv.is_basic()) {
sink->Append(v);
return true;
}
return sink->PutPaddedString(v, conv.width(), conv.precision(),
- conv.flags().left);
+ conv.has_left_flag());
}
} // namespace
// ==================== Strings ====================
-ConvertResult<Conv::s> FormatConvertImpl(const std::string &v,
- const ConversionSpec conv,
- FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(const std::string &v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-ConvertResult<Conv::s> FormatConvertImpl(string_view v,
- const ConversionSpec conv,
- FormatSinkImpl *sink) {
+StringConvertResult FormatConvertImpl(string_view v,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v,
- const ConversionSpec conv,
- FormatSinkImpl *sink) {
- if (conv.conv().id() == ConversionChar::p)
+ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ if (conv.conversion_char() == FormatConversionCharInternal::p)
return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
size_t len;
if (v == nullptr) {
@@ -275,96 +374,106 @@ ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v,
} else if (conv.precision() < 0) {
len = std::strlen(v);
} else {
- // If precision is set, we look for the null terminator on the valid range.
+ // If precision is set, we look for the NUL-terminator on the valid range.
len = std::find(v, v + conv.precision(), '\0') - v;
}
return {ConvertStringArg(string_view(v, len), conv, sink)};
}
// ==================== Raw pointers ====================
-ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv,
- FormatSinkImpl *sink) {
- if (conv.conv().id() != ConversionChar::p)
- return {false};
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+ VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
if (!v.value) {
sink->Append("(nil)");
return {true};
}
- return {ConvertIntImplInner(v.value, conv, sink)};
+ IntDigits as_digits;
+ as_digits.PrintAsHexLower(v.value);
+ return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
}
// ==================== Floats ====================
-FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(float v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
-FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(double v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
FloatingConvertResult FormatConvertImpl(long double v,
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
// ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(char v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(signed char v,
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned char v,
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
// ==================== Ints ====================
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(int v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
+ FormatSinkImpl *sink) {
+ return {ConvertIntArg(v, conv, sink)};
+}
+IntegralConvertResult FormatConvertImpl(absl::int128 v,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(absl::uint128 v,
- const ConversionSpec conv,
+ const FormatConversionSpecImpl conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
@@ -372,6 +481,8 @@ IntegralConvertResult FormatConvertImpl(absl::uint128 v,
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_();
+
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.h
index ebd40adcd98..7040c866778 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
@@ -7,6 +21,7 @@
#include <cstdio>
#include <iomanip>
#include <limits>
+#include <memory>
#include <sstream>
#include <string>
#include <type_traits>
@@ -17,30 +32,59 @@
#include "absl/strings/internal/str_format/extension.h"
#include "absl/strings/string_view.h"
-class Cord;
-class CordReader;
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
+class Cord;
class FormatCountCapture;
class FormatSink;
+template <absl::FormatConversionCharSet C>
+struct FormatConvertResult;
+class FormatConversionSpec;
+
namespace str_format_internal {
template <typename T, typename = void>
struct HasUserDefinedConvert : std::false_type {};
template <typename T>
-struct HasUserDefinedConvert<
- T, void_t<decltype(AbslFormatConvert(
- std::declval<const T&>(), std::declval<ConversionSpec>(),
- std::declval<FormatSink*>()))>> : std::true_type {};
+struct HasUserDefinedConvert<T, void_t<decltype(AbslFormatConvert(
+ std::declval<const T&>(),
+ std::declval<const FormatConversionSpec&>(),
+ std::declval<FormatSink*>()))>>
+ : std::true_type {};
+
+void AbslFormatConvert(); // Stops the lexical name lookup
+template <typename T>
+auto FormatConvertImpl(const T& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink)
+ -> decltype(AbslFormatConvert(v,
+ std::declval<const FormatConversionSpec&>(),
+ std::declval<FormatSink*>())) {
+ using FormatConversionSpecT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatConversionSpec>;
+ using FormatSinkT =
+ absl::enable_if_t<sizeof(const T& (*)()) != 0, FormatSink>;
+ auto fcs = conv.Wrap<FormatConversionSpecT>();
+ auto fs = sink->Wrap<FormatSinkT>();
+ return AbslFormatConvert(v, fcs, &fs);
+}
+
template <typename T>
class StreamedWrapper;
// If 'v' can be converted (in the printf sense) according to 'conv',
// then convert it, appending to `sink` and return `true`.
// Otherwise fail and return `false`.
+
+// AbslFormatConvert(v, conv, sink) is intended to be found by ADL on 'v'
+// as an extension mechanism. These FormatConvertImpl functions are the default
+// implementations.
+// The ADL search is augmented via the 'Sink*' parameter, which also
+// serves as a disambiguator to reject possible unintended 'AbslFormatConvert'
+// functions in the namespaces associated with 'v'.
+
// Raw pointers.
struct VoidPtr {
VoidPtr() = default;
@@ -50,27 +94,45 @@ struct VoidPtr {
: value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
uintptr_t value;
};
-ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
- FormatSinkImpl* sink);
+
+template <FormatConversionCharSet C>
+struct ArgConvertResult {
+ bool value;
+};
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(FormatConvertResult<C>) {
+ return C;
+}
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet ExtractCharSet(ArgConvertResult<C>) {
+ return C;
+}
+
+using StringConvertResult =
+ ArgConvertResult<FormatConversionCharSetInternal::s>;
+ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
+ VoidPtr v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
// Strings.
-ConvertResult<Conv::s> FormatConvertImpl(const std::string& v, ConversionSpec conv,
- FormatSinkImpl* sink);
-ConvertResult<Conv::s> FormatConvertImpl(string_view v, ConversionSpec conv,
- FormatSinkImpl* sink);
-ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char* v,
- ConversionSpec conv,
- FormatSinkImpl* sink);
-template <class AbslCord,
- typename std::enable_if<
- std::is_same<AbslCord, ::Cord>::value>::type* = nullptr,
- class AbslCordReader = ::CordReader>
-ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
- ConversionSpec conv,
- FormatSinkImpl* sink) {
- if (conv.conv().id() != ConversionChar::s) return {false};
-
- bool is_left = conv.flags().left;
+StringConvertResult FormatConvertImpl(const std::string& v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+StringConvertResult FormatConvertImpl(string_view v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
+FormatConvertImpl(const char* v, const FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+
+template <class AbslCord, typename std::enable_if<std::is_same<
+ AbslCord, absl::Cord>::value>::type* = nullptr>
+StringConvertResult FormatConvertImpl(const AbslCord& value,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
+ bool is_left = conv.has_left_flag();
size_t space_remaining = 0;
int width = conv.width();
@@ -86,64 +148,80 @@ ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
if (space_remaining > 0 && !is_left) sink->Append(space_remaining, ' ');
- string_view piece;
- for (AbslCordReader reader(value);
- to_write > 0 && reader.ReadFragment(&piece); to_write -= piece.size()) {
- if (piece.size() > to_write) piece.remove_suffix(piece.size() - to_write);
+ for (string_view piece : value.Chunks()) {
+ if (piece.size() > to_write) {
+ piece.remove_suffix(piece.size() - to_write);
+ to_write = 0;
+ } else {
+ to_write -= piece.size();
+ }
sink->Append(piece);
+ if (to_write == 0) {
+ break;
+ }
}
if (space_remaining > 0 && is_left) sink->Append(space_remaining, ' ');
return {true};
}
-using IntegralConvertResult =
- ConvertResult<Conv::c | Conv::numeric | Conv::star>;
-using FloatingConvertResult = ConvertResult<Conv::floating>;
+using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
+ FormatConversionCharSetInternal::c,
+ FormatConversionCharSetInternal::kNumeric,
+ FormatConversionCharSetInternal::kStar)>;
+using FloatingConvertResult =
+ ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
// Floats.
-FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
+FloatingConvertResult FormatConvertImpl(long double v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Chars.
-IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(signed char v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned char v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(unsigned v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- ConversionSpec conv,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink);
+IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(uint128 v,
+ FormatConversionSpecImpl conv,
FormatSinkImpl* sink);
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
-IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
+IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
FormatSinkImpl* sink) {
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
@@ -154,12 +232,12 @@ template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
!HasUserDefinedConvert<T>::value,
IntegralConvertResult>::type
-FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
+FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
template <typename T>
-ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
- ConversionSpec conv,
- FormatSinkImpl* out) {
+StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
+ FormatConversionSpecImpl conv,
+ FormatSinkImpl* out) {
std::ostringstream oss;
oss << v.v_;
if (!oss) return {false};
@@ -170,22 +248,24 @@ ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
// until after FormatCountCapture is fully defined.
struct FormatCountCaptureHelper {
template <class T = int>
- static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
- ConversionSpec conv,
- FormatSinkImpl* sink) {
+ static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
+ const FormatCountCapture& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
- if (conv.conv().id() != str_format_internal::ConversionChar::n)
+ if (conv.conversion_char() !=
+ str_format_internal::FormatConversionCharInternal::n) {
return {false};
+ }
*v2.p_ = static_cast<int>(sink->size());
return {true};
}
};
template <class T = int>
-ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
- ConversionSpec conv,
- FormatSinkImpl* sink) {
+ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
+ const FormatCountCapture& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* sink) {
return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
}
@@ -194,13 +274,13 @@ ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
struct FormatArgImplFriend {
template <typename Arg>
static bool ToInt(Arg arg, int* out) {
- // A value initialized ConversionSpec has a `none` conv, which tells the
- // dispatcher to run the `int` conversion.
+ // A value initialized FormatConversionSpecImpl has a `none` conv, which
+ // tells the dispatcher to run the `int` conversion.
return arg.dispatcher_(arg.data_, {}, out);
}
template <typename Arg>
- static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
+ static bool Convert(Arg arg, FormatConversionSpecImpl conv,
FormatSinkImpl* out) {
return arg.dispatcher_(arg.data_, conv, out);
}
@@ -211,6 +291,15 @@ struct FormatArgImplFriend {
}
};
+template <typename Arg>
+constexpr FormatConversionCharSet ArgumentToConv() {
+ return absl::str_format_internal::ExtractCharSet(
+ decltype(str_format_internal::FormatConvertImpl(
+ std::declval<const Arg&>(),
+ std::declval<const FormatConversionSpecImpl&>(),
+ std::declval<FormatSinkImpl*>())){});
+}
+
// A type-erased handle to a format argument.
class FormatArgImpl {
private:
@@ -224,7 +313,7 @@ class FormatArgImpl {
char buf[kInlinedSpace];
};
- using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
+ using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
template <typename T>
struct store_by_value
@@ -289,7 +378,7 @@ class FormatArgImpl {
struct Manager<T, ByPointer> {
static Data SetValue(const T& value) {
Data data;
- data.ptr = &value;
+ data.ptr = std::addressof(value);
return data;
}
@@ -366,15 +455,20 @@ class FormatArgImpl {
}
template <typename T>
- static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
+ static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
// A `none` conv indicates that we want the `int` conversion.
- if (ABSL_PREDICT_FALSE(spec.conv().id() == ConversionChar::none)) {
+ if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
+ FormatConversionCharInternal::kNone)) {
return ToInt<T>(arg, static_cast<int*>(out), std::is_integral<T>(),
std::is_enum<T>());
}
-
+ if (ABSL_PREDICT_FALSE(!Contains(ArgumentToConv<T>(),
+ spec.conversion_char()))) {
+ return false;
+ }
return str_format_internal::FormatConvertImpl(
- Manager<T>::Value(arg), spec, static_cast<FormatSinkImpl*>(out))
+ Manager<T>::Value(arg), spec,
+ static_cast<FormatSinkImpl*>(out))
.value;
}
@@ -382,8 +476,9 @@ class FormatArgImpl {
Dispatcher dispatcher_;
};
-#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
- E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
+#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
+ E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
+ void*)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
@@ -404,17 +499,20 @@ class FormatArgImpl {
__VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(unsigned long long, /* NOLINT */ \
__VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(int128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(uint128, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(float, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(long double, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(const char*, __VA_ARGS__); \
- ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
+ ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(std::string, __VA_ARGS__); \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(string_view, __VA_ARGS__)
ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(extern);
+
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_ARG_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
index 83d59048ea2..1261937c309 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
@@ -4,8 +4,14 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// https://www.apache.org/licenses/LICENSE-2.0
//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/arg.h"
#include <ostream>
@@ -14,6 +20,7 @@
#include "absl/strings/str_format.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -22,8 +29,17 @@ class FormatArgImplTest : public ::testing::Test {
enum Color { kRed, kGreen, kBlue };
static const char *hi() { return "hi"; }
+
+ struct X {};
+
+ X x_;
};
+inline FormatConvertResult<FormatConversionCharSet{}> AbslFormatConvert(
+ const FormatArgImplTest::X &, const FormatConversionSpec &, FormatSink *) {
+ return {false};
+}
+
TEST_F(FormatArgImplTest, ToInt) {
int out = 0;
EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(1), &out));
@@ -58,6 +74,7 @@ TEST_F(FormatArgImplTest, ToInt) {
FormatArgImpl(static_cast<int *>(nullptr)), &out));
EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(hi()), &out));
EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl("hi"), &out));
+ EXPECT_FALSE(FormatArgImplFriend::ToInt(FormatArgImpl(x_), &out));
EXPECT_TRUE(FormatArgImplFriend::ToInt(FormatArgImpl(kBlue), &out));
EXPECT_EQ(2, out);
}
@@ -94,11 +111,12 @@ TEST_F(FormatArgImplTest, OtherPtrDecayToVoidPtr) {
TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
std::string s;
FormatSinkImpl sink(&s);
- ConversionSpec conv;
- conv.set_conv(ConversionChar::FromChar('s'));
- conv.set_flags(Flags());
- conv.set_width(-1);
- conv.set_precision(-1);
+ FormatConversionSpecImpl conv;
+ FormatConversionSpecImplFriend::SetConversionChar(
+ FormatConversionCharInternal::s, &conv);
+ FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
+ FormatConversionSpecImplFriend::SetWidth(-1, &conv);
+ FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
EXPECT_TRUE(
FormatArgImplFriend::Convert(FormatArgImpl(kMyArray), conv, &sink));
sink.Flush();
@@ -108,4 +126,5 @@ const char kMyArray[] = "ABCDE";
} // namespace
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.cc
index c4eddd17ddb..4e68b90b5ce 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/bind.h"
#include <cerrno>
@@ -6,6 +20,7 @@
#include <string>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -25,12 +40,12 @@ class ArgContext {
explicit ArgContext(absl::Span<const FormatArgImpl> pack) : pack_(pack) {}
// Fill 'bound' with the results of applying the context's argument pack
- // to the specified 'props'. We synthesize a BoundConversion by
+ // to the specified 'unbound'. We synthesize a BoundConversion by
// lining up a UnboundConversion with a user argument. We also
// resolve any '*' specifiers for width and precision, so after
// this call, 'bound' has all the information it needs to be formatted.
// Returns false on failure.
- bool Bind(const UnboundConversion *props, BoundConversion *bound);
+ bool Bind(const UnboundConversion* unbound, BoundConversion* bound);
private:
absl::Span<const FormatArgImpl> pack_;
@@ -53,7 +68,8 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
// "A negative field width is taken as a '-' flag followed by a
// positive field width."
force_left = true;
- width = -width;
+ // Make sure we don't overflow the width when negating it.
+ width = -std::max(width, -std::numeric_limits<int>::max());
}
}
@@ -64,19 +80,22 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
return false;
}
- bound->set_width(width);
- bound->set_precision(precision);
- bound->set_flags(unbound->flags);
- if (force_left)
- bound->set_left(true);
+ FormatConversionSpecImplFriend::SetWidth(width, bound);
+ FormatConversionSpecImplFriend::SetPrecision(precision, bound);
+
+ if (force_left) {
+ Flags flags = unbound->flags;
+ flags.left = true;
+ FormatConversionSpecImplFriend::SetFlags(flags, bound);
+ } else {
+ FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+ }
} else {
- bound->set_flags(unbound->flags);
- bound->set_width(-1);
- bound->set_precision(-1);
+ FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
+ FormatConversionSpecImplFriend::SetWidth(-1, bound);
+ FormatConversionSpecImplFriend::SetPrecision(-1, bound);
}
-
- bound->set_length_mod(unbound->length_mod);
- bound->set_conv(unbound->conv);
+ FormatConversionSpecImplFriend::SetConversionChar(unbound->conv, bound);
bound->set_arg(arg);
return true;
}
@@ -138,10 +157,11 @@ class SummarizingConverter {
UntypedFormatSpecImpl spec("%d");
std::ostringstream ss;
- ss << "{" << Streamable(spec, {*bound.arg()}) << ":" << bound.flags();
+ ss << "{" << Streamable(spec, {*bound.arg()}) << ":"
+ << FormatConversionSpecImplFriend::FlagsToString(bound);
if (bound.width() >= 0) ss << bound.width();
if (bound.precision() >= 0) ss << "." << bound.precision();
- ss << bound.length_mod() << bound.conv() << "}";
+ ss << bound.conversion_char() << "}";
Append(ss.str());
return true;
}
@@ -159,7 +179,7 @@ bool BindWithPack(const UnboundConversion* props,
}
std::string Summarize(const UntypedFormatSpecImpl format,
- absl::Span<const FormatArgImpl> args) {
+ absl::Span<const FormatArgImpl> args) {
typedef SummarizingConverter Converter;
std::string out;
{
@@ -187,7 +207,7 @@ std::ostream& Streamable::Print(std::ostream& os) const {
}
std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
- absl::Span<const FormatArgImpl> args) {
+ absl::Span<const FormatArgImpl> args) {
size_t orig = out->size();
if (ABSL_PREDICT_FALSE(!FormatUntyped(out, format, args))) {
out->erase(orig);
@@ -195,6 +215,15 @@ std::string& AppendPack(std::string* out, const UntypedFormatSpecImpl format,
return *out;
}
+std::string FormatPack(const UntypedFormatSpecImpl format,
+ absl::Span<const FormatArgImpl> args) {
+ std::string out;
+ if (ABSL_PREDICT_FALSE(!FormatUntyped(&out, format, args))) {
+ out.clear();
+ }
+ return out;
+}
+
int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args) {
FILERawSink sink(output);
@@ -206,7 +235,7 @@ int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
errno = sink.error();
return -1;
}
- if (sink.count() > std::numeric_limits<int>::max()) {
+ if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
errno = EFBIG;
return -1;
}
@@ -226,4 +255,5 @@ int SnprintF(char* output, size_t size, const UntypedFormatSpecImpl format,
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.h
index 1b52df9c7f5..267cc0ef692 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
@@ -7,19 +21,19 @@
#include <string>
#include "absl/base/port.h"
-#include "absl/container/inlined_vector.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/parser.h"
#include "absl/types/span.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
class UntypedFormatSpec;
namespace str_format_internal {
-class BoundConversion : public ConversionSpec {
+class BoundConversion : public FormatConversionSpecImpl {
public:
const FormatArgImpl* arg() const { return arg_; }
void set_arg(const FormatArgImpl* a) { arg_ = a; }
@@ -60,7 +74,7 @@ class UntypedFormatSpecImpl {
size_t size_;
};
-template <typename T, typename...>
+template <typename T, FormatConversionCharSet...>
struct MakeDependent {
using type = T;
};
@@ -68,19 +82,19 @@ struct MakeDependent {
// Implicitly convertible from `const char*`, `string_view`, and the
// `ExtendedParsedFormat` type. This abstraction allows all format functions to
// operate on any without providing too many overloads.
-template <typename... Args>
+template <FormatConversionCharSet... Args>
class FormatSpecTemplate
: public MakeDependent<UntypedFormatSpec, Args...>::type {
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
public:
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- // Honeypot overload for when the std::string is not constexpr.
+ // Honeypot overload for when the string is not constexpr.
// We use the 'unavailable' attribute to give a better compiler error than
// just 'method is deleted'.
FormatSpecTemplate(...) // NOLINT
- __attribute__((unavailable("Format std::string is not constexpr.")));
+ __attribute__((unavailable("Format string is not constexpr.")));
// Honeypot overload for when the format is constexpr and invalid.
// We use the 'unavailable' attribute to give a better compiler error than
@@ -105,13 +119,11 @@ class FormatSpecTemplate
// Good format overload.
FormatSpecTemplate(const char* s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
- "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
FormatSpecTemplate(string_view s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
- "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
: Base(s) {}
#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -121,24 +133,30 @@ class FormatSpecTemplate
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- template <Conv... C, typename = typename std::enable_if<
- sizeof...(C) == sizeof...(Args) &&
- AllOf(Contains(ArgumentToConv<Args>(),
- C)...)>::type>
+ template <
+ FormatConversionCharSet... C,
+ typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
+ typename = typename std::enable_if<AllOf(Contains(Args,
+ C)...)>::type>
FormatSpecTemplate(const ExtendedParsedFormat<C...>& pc) // NOLINT
: Base(&pc) {}
};
-template <typename... Args>
-struct FormatSpecDeductionBarrier {
- using type = FormatSpecTemplate<Args...>;
-};
-
class Streamable {
public:
Streamable(const UntypedFormatSpecImpl& format,
absl::Span<const FormatArgImpl> args)
- : format_(format), args_(args.begin(), args.end()) {}
+ : format_(format) {
+ if (args.size() <= ABSL_ARRAYSIZE(few_args_)) {
+ for (size_t i = 0; i < args.size(); ++i) {
+ few_args_[i] = args[i];
+ }
+ args_ = absl::MakeSpan(few_args_, args.size());
+ } else {
+ many_args_.assign(args.begin(), args.end());
+ args_ = many_args_;
+ }
+ }
std::ostream& Print(std::ostream& os) const;
@@ -148,12 +166,17 @@ class Streamable {
private:
const UntypedFormatSpecImpl& format_;
- absl::InlinedVector<FormatArgImpl, 4> args_;
+ absl::Span<const FormatArgImpl> args_;
+ // if args_.size() is 4 or less:
+ FormatArgImpl few_args_[4] = {FormatArgImpl(0), FormatArgImpl(0),
+ FormatArgImpl(0), FormatArgImpl(0)};
+ // if args_.size() is more than 4:
+ std::vector<FormatArgImpl> many_args_;
};
// for testing
std::string Summarize(UntypedFormatSpecImpl format,
- absl::Span<const FormatArgImpl> args);
+ absl::Span<const FormatArgImpl> args);
bool BindWithPack(const UnboundConversion* props,
absl::Span<const FormatArgImpl> pack, BoundConversion* bound);
@@ -162,21 +185,17 @@ bool FormatUntyped(FormatRawSinkImpl raw_sink,
absl::Span<const FormatArgImpl> args);
std::string& AppendPack(std::string* out, UntypedFormatSpecImpl format,
- absl::Span<const FormatArgImpl> args);
+ absl::Span<const FormatArgImpl> args);
-inline std::string FormatPack(const UntypedFormatSpecImpl format,
- absl::Span<const FormatArgImpl> args) {
- std::string out;
- AppendPack(&out, format, args);
- return out;
-}
+std::string FormatPack(const UntypedFormatSpecImpl format,
+ absl::Span<const FormatArgImpl> args);
int FprintF(std::FILE* output, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
int SnprintF(char* output, size_t size, UntypedFormatSpecImpl format,
absl::Span<const FormatArgImpl> args);
-// Returned by Streamed(v). Converts via '%s' to the string created
+// Returned by Streamed(v). Converts via '%s' to the std::string created
// by std::ostream << v.
template <typename T>
class StreamedWrapper {
@@ -185,13 +204,14 @@ class StreamedWrapper {
private:
template <typename S>
- friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v,
- ConversionSpec conv,
- FormatSinkImpl* out);
+ friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
+ const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
+ FormatSinkImpl* out);
const T& v_;
};
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_BIND_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
index 47575739ba1..1eef9c4326e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
@@ -1,23 +1,34 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/bind.h"
#include <string.h>
+#include <limits>
#include "gtest/gtest.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
-template <typename T, size_t N>
-size_t ArraySize(T (&)[N]) {
- return N;
-}
-
class FormatBindTest : public ::testing::Test {
public:
bool Extract(const char *s, UnboundConversion *props, int *next) const {
- absl::string_view src = s;
- return ConsumeUnboundConversion(&src, props, next) && src.empty();
+ return ConsumeUnboundConversion(s, s + strlen(s), props, next) ==
+ s + strlen(s);
}
};
@@ -91,6 +102,20 @@ TEST_F(FormatBindTest, BindSingle) {
}
}
+TEST_F(FormatBindTest, WidthUnderflowRegression) {
+ UnboundConversion props;
+ BoundConversion bound;
+ int next = 0;
+ const int args_i[] = {std::numeric_limits<int>::min(), 17};
+ const FormatArgImpl args[] = {FormatArgImpl(args_i[0]),
+ FormatArgImpl(args_i[1])};
+ ASSERT_TRUE(Extract("*d", &props, &next));
+ ASSERT_TRUE(BindWithPack(&props, args, &bound));
+
+ EXPECT_EQ(bound.width(), std::numeric_limits<int>::max());
+ EXPECT_EQ(bound.arg(), args + 1);
+}
+
TEST_F(FormatBindTest, FormatPack) {
struct Expectation {
int line;
@@ -102,18 +127,18 @@ TEST_F(FormatBindTest, FormatPack) {
FormatArgImpl(ia[2]), FormatArgImpl(ia[3]),
FormatArgImpl(ia[4])};
const Expectation kExpect[] = {
- {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"},
- {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"},
- {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"},
- {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"},
- {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"},
- {__LINE__, "a%.*fb", "a{20:.10f}b"},
- {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"},
- {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"},
- {__LINE__, "a%04ldb", "a{10:04ld}b"},
- {__LINE__, "a%-#04lldb", "a{10:-#04lld}b"},
- {__LINE__, "a%1$*5$db", "a{10:-10d}b"},
- {__LINE__, "a%1$.*5$db", "a{10:d}b"},
+ {__LINE__, "a%4db%dc", "a{10:4d}b{20:d}c"},
+ {__LINE__, "a%.4db%dc", "a{10:.4d}b{20:d}c"},
+ {__LINE__, "a%4.5db%dc", "a{10:4.5d}b{20:d}c"},
+ {__LINE__, "a%db%4.5dc", "a{10:d}b{20:4.5d}c"},
+ {__LINE__, "a%db%*.*dc", "a{10:d}b{40:20.30d}c"},
+ {__LINE__, "a%.*fb", "a{20:.10f}b"},
+ {__LINE__, "a%1$db%2$*3$.*4$dc", "a{10:d}b{20:30.40d}c"},
+ {__LINE__, "a%4$db%3$*2$.*1$dc", "a{40:d}b{30:20.10d}c"},
+ {__LINE__, "a%04ldb", "a{10:04d}b"},
+ {__LINE__, "a%-#04lldb", "a{10:-#04d}b"},
+ {__LINE__, "a%1$*5$db", "a{10:-10d}b"},
+ {__LINE__, "a%1$.*5$db", "a{10:d}b"},
};
for (const Expectation &e : kExpect) {
absl::string_view fmt = e.fmt;
@@ -128,4 +153,5 @@ TEST_F(FormatBindTest, FormatPack) {
} // namespace
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker.h
index 8b594f2d5cc..2a2601eccfd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker.h
@@ -1,20 +1,34 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
+#include "absl/base/attributes.h"
#include "absl/strings/internal/str_format/arg.h"
#include "absl/strings/internal/str_format/extension.h"
// Compile time check support for entry points.
#ifndef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
-#if defined(__clang__) && !defined(__native_client__)
-#if __has_attribute(enable_if)
+#if ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
#define ABSL_INTERNAL_ENABLE_FORMAT_CHECKER 1
-#endif // __has_attribute(enable_if)
-#endif // defined(__clang__) && !defined(__native_client__)
+#endif // ABSL_HAVE_ATTRIBUTE(enable_if) && !defined(__native_client__)
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
constexpr bool AllOf() { return true; }
@@ -24,14 +38,7 @@ constexpr bool AllOf(bool b, T... t) {
return b && AllOf(t...);
}
-template <typename Arg>
-constexpr Conv ArgumentToConv() {
- return decltype(str_format_internal::FormatConvertImpl(
- std::declval<const Arg&>(), std::declval<const ConversionSpec&>(),
- std::declval<FormatSinkImpl*>()))::kConv;
-}
-
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
constexpr bool ContainsChar(const char* chars, char c) {
return *chars == c || (*chars && ContainsChar(chars + 1, c));
@@ -39,14 +46,14 @@ constexpr bool ContainsChar(const char* chars, char c) {
// A constexpr compatible list of Convs.
struct ConvList {
- const Conv* array;
+ const FormatConversionCharSet* array;
int count;
// We do the bound check here to avoid having to do it on the callers.
- // Returning an empty Conv has the same effect as short circuiting because it
- // will never match any conversion.
- constexpr Conv operator[](int i) const {
- return i < count ? array[i] : Conv{};
+ // Returning an empty FormatConversionCharSet has the same effect as
+ // short circuiting because it will never match any conversion.
+ constexpr FormatConversionCharSet operator[](int i) const {
+ return i < count ? array[i] : FormatConversionCharSet{};
}
constexpr ConvList without_front() const {
@@ -57,7 +64,7 @@ struct ConvList {
template <size_t count>
struct ConvListT {
// Make sure the array has size > 0.
- Conv list[count ? count : 1];
+ FormatConversionCharSet list[count ? count : 1];
};
constexpr char GetChar(string_view str, size_t index) {
@@ -310,7 +317,7 @@ class FormatParser {
ConvList args_;
};
-template <Conv... C>
+template <FormatConversionCharSet... C>
constexpr bool ValidFormatImpl(string_view format) {
return FormatParser(format,
{ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
@@ -320,6 +327,7 @@ constexpr bool ValidFormatImpl(string_view format) {
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_CHECKER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
index 14d11ea8bd3..7c70f47d682 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include <string>
#include "gmock/gmock.h"
@@ -5,21 +19,26 @@
#include "absl/strings/str_format.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
-std::string ConvToString(Conv conv) {
+std::string ConvToString(FormatConversionCharSet conv) {
std::string out;
-#define CONV_SET_CASE(c) \
- if (Contains(conv, Conv::c)) out += #c;
- ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
+#define CONV_SET_CASE(c) \
+ if (Contains(conv, FormatConversionCharSetInternal::c)) { \
+ out += #c; \
+ }
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
- if (Contains(conv, Conv::star)) out += "*";
+ if (Contains(conv, FormatConversionCharSetInternal::kStar)) {
+ out += "*";
+ }
return out;
}
TEST(StrFormatChecker, ArgumentToConv) {
- Conv conv = ArgumentToConv<std::string>();
+ FormatConversionCharSet conv = ArgumentToConv<std::string>();
EXPECT_EQ(ConvToString(conv), "s");
conv = ArgumentToConv<const char*>();
@@ -35,7 +54,7 @@ TEST(StrFormatChecker, ArgumentToConv) {
EXPECT_EQ(ConvToString(conv), "p");
}
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
struct Case {
bool result;
@@ -62,32 +81,32 @@ TEST(StrFormatChecker, ValidFormat) {
ValidFormat<int>("%% %d"), //
ValidFormat<int>("%ld"), //
ValidFormat<int>("%lld"), //
- ValidFormat<std::string>("%s"), //
- ValidFormat<std::string>("%10s"), //
+ ValidFormat<std::string>("%s"), //
+ ValidFormat<std::string>("%10s"), //
ValidFormat<int>("%.10x"), //
ValidFormat<int, int>("%*.3x"), //
ValidFormat<int>("%1.d"), //
ValidFormat<int>("%.d"), //
ValidFormat<int, double>("%d %g"), //
- ValidFormat<int, std::string>("%*s"), //
+ ValidFormat<int, std::string>("%*s"), //
ValidFormat<int, double>("%.*f"), //
ValidFormat<void (*)(), volatile int*>("%p %p"), //
ValidFormat<string_view, const char*, double, void*>(
"string_view=%s const char*=%s double=%f void*=%p)"),
- ValidFormat<int>("%% %1$d"), //
- ValidFormat<int>("%1$ld"), //
- ValidFormat<int>("%1$lld"), //
- ValidFormat<std::string>("%1$s"), //
- ValidFormat<std::string>("%1$10s"), //
- ValidFormat<int>("%1$.10x"), //
- ValidFormat<int>("%1$*1$.*1$d"), //
- ValidFormat<int, int>("%1$*2$.3x"), //
- ValidFormat<int>("%1$1.d"), //
- ValidFormat<int>("%1$.d"), //
- ValidFormat<double, int>("%2$d %1$g"), //
- ValidFormat<int, std::string>("%2$*1$s"), //
- ValidFormat<int, double>("%2$.*1$f"), //
+ ValidFormat<int>("%% %1$d"), //
+ ValidFormat<int>("%1$ld"), //
+ ValidFormat<int>("%1$lld"), //
+ ValidFormat<std::string>("%1$s"), //
+ ValidFormat<std::string>("%1$10s"), //
+ ValidFormat<int>("%1$.10x"), //
+ ValidFormat<int>("%1$*1$.*1$d"), //
+ ValidFormat<int, int>("%1$*2$.3x"), //
+ ValidFormat<int>("%1$1.d"), //
+ ValidFormat<int>("%1$.d"), //
+ ValidFormat<double, int>("%2$d %1$g"), //
+ ValidFormat<int, std::string>("%2$*1$s"), //
+ ValidFormat<int, double>("%2$.*1$f"), //
ValidFormat<void*, string_view, const char*, double>(
"string_view=%2$s const char*=%3$s double=%4$f void*=%1$p "
"repeat=%3$s)")};
@@ -99,25 +118,25 @@ TEST(StrFormatChecker, ValidFormat) {
constexpr Case falses[] = {
ValidFormat<int>(""), //
- ValidFormat<e>("%s"), //
- ValidFormat<e2>("%s"), //
- ValidFormat<>("%s"), //
- ValidFormat<>("%r"), //
- ValidFormat<int>("%s"), //
- ValidFormat<int>("%.1.d"), //
- ValidFormat<int>("%*1d"), //
- ValidFormat<int>("%1-d"), //
+ ValidFormat<e>("%s"), //
+ ValidFormat<e2>("%s"), //
+ ValidFormat<>("%s"), //
+ ValidFormat<>("%r"), //
+ ValidFormat<int>("%s"), //
+ ValidFormat<int>("%.1.d"), //
+ ValidFormat<int>("%*1d"), //
+ ValidFormat<int>("%1-d"), //
ValidFormat<std::string, int>("%*s"), //
- ValidFormat<int>("%*d"), //
+ ValidFormat<int>("%*d"), //
ValidFormat<std::string>("%p"), //
- ValidFormat<int (*)(int)>("%d"), //
-
- ValidFormat<>("%3$d"), //
- ValidFormat<>("%1$r"), //
- ValidFormat<int>("%1$s"), //
- ValidFormat<int>("%1$.1.d"), //
- ValidFormat<int>("%1$*2$1d"), //
- ValidFormat<int>("%1$1-d"), //
+ ValidFormat<int (*)(int)>("%d"), //
+
+ ValidFormat<>("%3$d"), //
+ ValidFormat<>("%1$r"), //
+ ValidFormat<int>("%1$s"), //
+ ValidFormat<int>("%1$.1.d"), //
+ ValidFormat<int>("%1$*2$1d"), //
+ ValidFormat<int>("%1$1-d"), //
ValidFormat<std::string, int>("%2$*1$s"), //
ValidFormat<std::string>("%1$p"),
@@ -147,4 +166,5 @@ TEST(StrFormatChecker, LongFormat) {
} // namespace
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/convert_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
index 32f8a0f9ad1..926283cfac1 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
@@ -1,16 +1,46 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
+
+#include <cctype>
#include <cmath>
+#include <limits>
#include <string>
+#include <thread> // NOLINT
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/internal/raw_logging.h"
#include "absl/strings/internal/str_format/bind.h"
+#include "absl/strings/match.h"
+#include "absl/types/optional.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
+struct NativePrintfTraits {
+ bool hex_float_has_glibc_rounding;
+ bool hex_float_prefers_denormal_repr;
+ bool hex_float_uses_minimal_precision_when_not_specified;
+ bool hex_float_optimizes_leading_digit_bit_count;
+};
+
template <typename T, size_t N>
size_t ArraySize(T (&)[N]) {
return N;
@@ -32,7 +62,9 @@ std::string LengthModFor(long long) { return "ll"; } // NOLINT
std::string LengthModFor(unsigned long long) { return "ll"; } // NOLINT
std::string EscCharImpl(int v) {
- if (isprint(v)) return std::string(1, static_cast<char>(v));
+ if (std::isprint(static_cast<unsigned char>(v))) {
+ return std::string(1, static_cast<char>(v));
+ }
char buf[64];
int n = snprintf(buf, sizeof(buf), "\\%#.2x",
static_cast<unsigned>(v & 0xff));
@@ -51,7 +83,7 @@ std::string Esc(const T &v) {
return oss.str();
}
-void StrAppend(std::string *dst, const char *format, va_list ap) {
+void StrAppendV(std::string *dst, const char *format, va_list ap) {
// First try with a small fixed size buffer
static const int kSpaceLength = 1024;
char space[kSpaceLength];
@@ -92,15 +124,79 @@ void StrAppend(std::string *dst, const char *format, va_list ap) {
delete[] buf;
}
+void StrAppend(std::string *out, const char *format, ...) {
+ va_list ap;
+ va_start(ap, format);
+ StrAppendV(out, format, ap);
+ va_end(ap);
+}
+
std::string StrPrint(const char *format, ...) {
va_list ap;
va_start(ap, format);
std::string result;
- StrAppend(&result, format, ap);
+ StrAppendV(&result, format, ap);
va_end(ap);
return result;
}
+NativePrintfTraits VerifyNativeImplementationImpl() {
+ NativePrintfTraits result;
+
+ // >>> hex_float_has_glibc_rounding. To have glibc's rounding behavior we need
+ // to meet three requirements:
+ //
+ // - The threshold for rounding up is 8 (for e.g. MSVC uses 9).
+ // - If the digits lower than than the 8 are non-zero then we round up.
+ // - If the digits lower than the 8 are all zero then we round toward even.
+ //
+ // The numbers below represent all the cases covering {below,at,above} the
+ // threshold (8) with both {zero,non-zero} lower bits and both {even,odd}
+ // preceding digits.
+ const double d0079 = 65657.0; // 0x1.0079p+16
+ const double d0179 = 65913.0; // 0x1.0179p+16
+ const double d0080 = 65664.0; // 0x1.0080p+16
+ const double d0180 = 65920.0; // 0x1.0180p+16
+ const double d0081 = 65665.0; // 0x1.0081p+16
+ const double d0181 = 65921.0; // 0x1.0181p+16
+ result.hex_float_has_glibc_rounding =
+ StartsWith(StrPrint("%.2a", d0079), "0x1.00") &&
+ StartsWith(StrPrint("%.2a", d0179), "0x1.01") &&
+ StartsWith(StrPrint("%.2a", d0080), "0x1.00") &&
+ StartsWith(StrPrint("%.2a", d0180), "0x1.02") &&
+ StartsWith(StrPrint("%.2a", d0081), "0x1.01") &&
+ StartsWith(StrPrint("%.2a", d0181), "0x1.02");
+
+ // >>> hex_float_prefers_denormal_repr. Formatting `denormal` on glibc yields
+ // "0x0.0000000000001p-1022", whereas on std libs that don't use denormal
+ // representation it would either be 0x1p-1074 or 0x1.0000000000000-1074.
+ const double denormal = std::numeric_limits<double>::denorm_min();
+ result.hex_float_prefers_denormal_repr =
+ StartsWith(StrPrint("%a", denormal), "0x0.0000000000001");
+
+ // >>> hex_float_uses_minimal_precision_when_not_specified. Some (non-glibc)
+ // libs will format the following as "0x1.0079000000000p+16".
+ result.hex_float_uses_minimal_precision_when_not_specified =
+ (StrPrint("%a", d0079) == "0x1.0079p+16");
+
+ // >>> hex_float_optimizes_leading_digit_bit_count. The number 1.5, when
+ // formatted by glibc should yield "0x1.8p+0" for `double` and "0xcp-3" for
+ // `long double`, i.e., number of bits in the leading digit is adapted to the
+ // number of bits in the mantissa.
+ const double d_15 = 1.5;
+ const long double ld_15 = 1.5;
+ result.hex_float_optimizes_leading_digit_bit_count =
+ StartsWith(StrPrint("%a", d_15), "0x1.8") &&
+ StartsWith(StrPrint("%La", ld_15), "0xc");
+
+ return result;
+}
+
+const NativePrintfTraits &VerifyNativeImplementation() {
+ static NativePrintfTraits native_traits = VerifyNativeImplementationImpl();
+ return native_traits;
+}
+
class FormatConvertTest : public ::testing::Test { };
template <typename T>
@@ -148,18 +244,26 @@ TEST_F(FormatConvertTest, StringPrecision) {
UntypedFormatSpecImpl format("%.1s");
EXPECT_EQ("a", FormatPack(format, {FormatArgImpl(p)}));
- // We cap at the nul terminator.
+ // We cap at the NUL-terminator.
p = "ABC";
UntypedFormatSpecImpl format2("%.10s");
EXPECT_EQ("ABC", FormatPack(format2, {FormatArgImpl(p)}));
}
+// Pointer formatting is implementation defined. This checks that the argument
+// can be matched to `ptr`.
+MATCHER_P(MatchesPointerString, ptr, "") {
+ if (ptr == nullptr && arg == "(nil)") {
+ return true;
+ }
+ void* parsed = nullptr;
+ if (sscanf(arg.c_str(), "%p", &parsed) != 1) {
+ ABSL_RAW_LOG(FATAL, "Could not parse %s", arg.c_str());
+ }
+ return ptr == parsed;
+}
+
TEST_F(FormatConvertTest, Pointer) {
-#if _MSC_VER
- // MSVC's printf implementation prints pointers differently. We can't easily
- // compare our implementation to theirs.
- return;
-#endif
static int x = 0;
const int *xp = &x;
char c = 'h';
@@ -170,48 +274,62 @@ TEST_F(FormatConvertTest, Pointer) {
using VoidF = void (*)();
VoidF fp = [] {}, fnil = nullptr;
volatile char vc;
- volatile char* vcp = &vc;
- volatile char* vcnil = nullptr;
- const FormatArgImpl args[] = {
+ volatile char *vcp = &vc;
+ volatile char *vcnil = nullptr;
+ const FormatArgImpl args_array[] = {
FormatArgImpl(xp), FormatArgImpl(cp), FormatArgImpl(inil),
FormatArgImpl(cnil), FormatArgImpl(mcp), FormatArgImpl(fp),
FormatArgImpl(fnil), FormatArgImpl(vcp), FormatArgImpl(vcnil),
};
- struct Expectation {
- std::string out;
- const char *fmt;
- };
- const Expectation kExpect[] = {
- {StrPrint("%p", &x), "%p"},
- {StrPrint("%20p", &x), "%20p"},
- {StrPrint("%.1p", &x), "%.1p"},
- {StrPrint("%.20p", &x), "%.20p"},
- {StrPrint("%30.20p", &x), "%30.20p"},
-
- {StrPrint("%-p", &x), "%-p"},
- {StrPrint("%-20p", &x), "%-20p"},
- {StrPrint("%-.1p", &x), "%-.1p"},
- {StrPrint("%.20p", &x), "%.20p"},
- {StrPrint("%-30.20p", &x), "%-30.20p"},
-
- {StrPrint("%p", cp), "%2$p"}, // const char*
- {"(nil)", "%3$p"}, // null const char *
- {"(nil)", "%4$p"}, // null const int *
- {StrPrint("%p", mcp), "%5$p"}, // nonconst char*
-
- {StrPrint("%p", fp), "%6$p"}, // function pointer
- {StrPrint("%p", vcp), "%8$p"}, // function pointer
-
-#ifndef __APPLE__
- // Apple's printf differs here (0x0 vs. nil)
- {StrPrint("%p", fnil), "%7$p"}, // null function pointer
- {StrPrint("%p", vcnil), "%9$p"}, // null function pointer
-#endif
- };
- for (const Expectation &e : kExpect) {
- UntypedFormatSpecImpl format(e.fmt);
- EXPECT_EQ(e.out, FormatPack(format, absl::MakeSpan(args))) << e.fmt;
- }
+ auto args = absl::MakeConstSpan(args_array);
+
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.1p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%30.20p"), args),
+ MatchesPointerString(&x));
+
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-.1p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%.20p"), args),
+ MatchesPointerString(&x));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%-30.20p"), args),
+ MatchesPointerString(&x));
+
+ // const char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%2$p"), args),
+ MatchesPointerString(cp));
+ // null const int*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%3$p"), args),
+ MatchesPointerString(nullptr));
+ // null const char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%4$p"), args),
+ MatchesPointerString(nullptr));
+ // nonconst char*
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%5$p"), args),
+ MatchesPointerString(mcp));
+
+ // function pointers
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%6$p"), args),
+ MatchesPointerString(reinterpret_cast<const void*>(fp)));
+ EXPECT_THAT(
+ FormatPack(UntypedFormatSpecImpl("%8$p"), args),
+ MatchesPointerString(reinterpret_cast<volatile const void *>(vcp)));
+
+ // null function pointers
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%7$p"), args),
+ MatchesPointerString(nullptr));
+ EXPECT_THAT(FormatPack(UntypedFormatSpecImpl("%9$p"), args),
+ MatchesPointerString(nullptr));
}
struct Cardinal {
@@ -232,7 +350,7 @@ TEST_F(FormatConvertTest, Enum) {
template <typename T>
class TypedFormatConvertTest : public FormatConvertTest { };
-TYPED_TEST_CASE_P(TypedFormatConvertTest);
+TYPED_TEST_SUITE_P(TypedFormatConvertTest);
std::vector<std::string> AllFlagCombinations() {
const char kFlags[] = {'-', '#', '0', '+', ' '};
@@ -363,6 +481,53 @@ typedef ::testing::Types<
AllIntTypes;
INSTANTIATE_TYPED_TEST_CASE_P(TypedFormatConvertTestWithAllIntTypes,
TypedFormatConvertTest, AllIntTypes);
+TEST_F(FormatConvertTest, VectorBool) {
+ // Make sure vector<bool>'s values behave as bools.
+ std::vector<bool> v = {true, false};
+ const std::vector<bool> cv = {true, false};
+ EXPECT_EQ("1,0,1,0",
+ FormatPack(UntypedFormatSpecImpl("%d,%d,%d,%d"),
+ absl::Span<const FormatArgImpl>(
+ {FormatArgImpl(v[0]), FormatArgImpl(v[1]),
+ FormatArgImpl(cv[0]), FormatArgImpl(cv[1])})));
+}
+
+
+TEST_F(FormatConvertTest, Int128) {
+ absl::int128 positive = static_cast<absl::int128>(0x1234567890abcdef) * 1979;
+ absl::int128 negative = -positive;
+ absl::int128 max = absl::Int128Max(), min = absl::Int128Min();
+ const FormatArgImpl args[] = {FormatArgImpl(positive),
+ FormatArgImpl(negative), FormatArgImpl(max),
+ FormatArgImpl(min)};
+
+ struct Case {
+ const char* format;
+ const char* expected;
+ } cases[] = {
+ {"%1$d", "2595989796776606496405"},
+ {"%1$30d", " 2595989796776606496405"},
+ {"%1$-30d", "2595989796776606496405 "},
+ {"%1$u", "2595989796776606496405"},
+ {"%1$x", "8cba9876066020f695"},
+ {"%2$d", "-2595989796776606496405"},
+ {"%2$30d", " -2595989796776606496405"},
+ {"%2$-30d", "-2595989796776606496405 "},
+ {"%2$u", "340282366920938460867384810655161715051"},
+ {"%2$x", "ffffffffffffff73456789f99fdf096b"},
+ {"%3$d", "170141183460469231731687303715884105727"},
+ {"%3$u", "170141183460469231731687303715884105727"},
+ {"%3$x", "7fffffffffffffffffffffffffffffff"},
+ {"%4$d", "-170141183460469231731687303715884105728"},
+ {"%4$x", "80000000000000000000000000000000"},
+ };
+
+ for (auto c : cases) {
+ UntypedFormatSpecImpl format(c.format);
+ EXPECT_EQ(c.expected, FormatPack(format, absl::MakeSpan(args)));
+ }
+}
+
TEST_F(FormatConvertTest, Uint128) {
absl::uint128 v = static_cast<absl::uint128>(0x1234567890abcdef) * 1979;
absl::uint128 max = absl::Uint128Max();
@@ -388,17 +553,130 @@ TEST_F(FormatConvertTest, Uint128) {
}
}
-TEST_F(FormatConvertTest, Float) {
-#if _MSC_VER
- // MSVC has a different rounding policy than us so we can't test our
- // implementation against the native one there.
- return;
-#endif // _MSC_VER
+template <typename Floating>
+void TestWithMultipleFormatsHelper(const std::vector<Floating> &floats,
+ const std::set<Floating> &skip_verify) {
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+ // Reserve the space to ensure we don't allocate memory in the output itself.
+ std::string str_format_result;
+ str_format_result.reserve(1 << 20);
+ std::string string_printf_result;
+ string_printf_result.reserve(1 << 20);
const char *const kFormats[] = {
- "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+",
- "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
+ "%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03",
+ "%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
+
+ for (const char *fmt : kFormats) {
+ for (char f : {'f', 'F', //
+ 'g', 'G', //
+ 'a', 'A', //
+ 'e', 'E'}) {
+ std::string fmt_str = std::string(fmt) + f;
+
+ if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' &&
+ f != 'a' && f != 'A') {
+ // This particular test takes way too long with snprintf.
+ // Disable for the case we are not implementing natively.
+ continue;
+ }
+
+ if ((f == 'a' || f == 'A') &&
+ !native_traits.hex_float_has_glibc_rounding) {
+ continue;
+ }
+
+ for (Floating d : floats) {
+ if (!native_traits.hex_float_prefers_denormal_repr &&
+ (f == 'a' || f == 'A') && std::fpclassify(d) == FP_SUBNORMAL) {
+ continue;
+ }
+ int i = -10;
+ FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
+ UntypedFormatSpecImpl format(fmt_str);
+
+ string_printf_result.clear();
+ StrAppend(&string_printf_result, fmt_str.c_str(), d, i);
+ str_format_result.clear();
+
+ {
+ AppendPack(&str_format_result, format, absl::MakeSpan(args));
+ }
+
+#ifdef _MSC_VER
+ // MSVC has a different rounding policy than us so we can't test our
+ // implementation against the native one there.
+ continue;
+#elif defined(__APPLE__)
+ // Apple formats NaN differently (+nan) vs. (nan)
+ if (std::isnan(d)) continue;
+#endif
+ if (string_printf_result != str_format_result &&
+ skip_verify.find(d) == skip_verify.end()) {
+ // We use ASSERT_EQ here because failures are usually correlated and a
+ // bug would print way too many failed expectations causing the test
+ // to time out.
+ ASSERT_EQ(string_printf_result, str_format_result)
+ << fmt_str << " " << StrPrint("%.18g", d) << " "
+ << StrPrint("%a", d) << " " << StrPrint("%.50f", d);
+ }
+ }
+ }
+ }
+}
+
+TEST_F(FormatConvertTest, Float) {
+ std::vector<float> floats = {0.0f,
+ -0.0f,
+ .9999999f,
+ 9999999.f,
+ std::numeric_limits<float>::max(),
+ -std::numeric_limits<float>::max(),
+ std::numeric_limits<float>::min(),
+ -std::numeric_limits<float>::min(),
+ std::numeric_limits<float>::lowest(),
+ -std::numeric_limits<float>::lowest(),
+ std::numeric_limits<float>::epsilon(),
+ std::numeric_limits<float>::epsilon() + 1.0f,
+ std::numeric_limits<float>::infinity(),
+ -std::numeric_limits<float>::infinity(),
+ std::nanf("")};
+
+ // Some regression tests.
+ floats.push_back(0.999999989f);
+
+ if (std::numeric_limits<float>::has_denorm != std::denorm_absent) {
+ floats.push_back(std::numeric_limits<float>::denorm_min());
+ floats.push_back(-std::numeric_limits<float>::denorm_min());
+ }
+
+ for (float base :
+ {1.f, 12.f, 123.f, 1234.f, 12345.f, 123456.f, 1234567.f, 12345678.f,
+ 123456789.f, 1234567890.f, 12345678901.f, 12345678.f, 12345678.f}) {
+ for (int exp = -123; exp <= 123; ++exp) {
+ for (int sign : {1, -1}) {
+ floats.push_back(sign * std::ldexp(base, exp));
+ }
+ }
+ }
+
+ for (int exp = -300; exp <= 300; ++exp) {
+ const float all_ones_mantissa = 0xffffff;
+ floats.push_back(std::ldexp(all_ones_mantissa, exp));
+ }
+
+ // Remove duplicates to speed up the logic below.
+ std::sort(floats.begin(), floats.end());
+ floats.erase(std::unique(floats.begin(), floats.end()), floats.end());
+ TestWithMultipleFormatsHelper(floats, {});
+}
+
+TEST_F(FormatConvertTest, Double) {
+ // For values that we know won't match the standard library implementation we
+ // skip verification, but still run the algorithm to catch asserts/sanitizer
+ // bugs.
+ std::set<double> skip_verify;
std::vector<double> doubles = {0.0,
-0.0,
.99999999999999,
@@ -412,12 +690,8 @@ TEST_F(FormatConvertTest, Float) {
std::numeric_limits<double>::epsilon(),
std::numeric_limits<double>::epsilon() + 1,
std::numeric_limits<double>::infinity(),
- -std::numeric_limits<double>::infinity()};
-
-#ifndef __APPLE__
- // Apple formats NaN differently (+nan) vs. (nan)
- doubles.push_back(std::nan(""));
-#endif
+ -std::numeric_limits<double>::infinity(),
+ std::nan("")};
// Some regression tests.
doubles.push_back(0.99999999999999989);
@@ -437,43 +711,366 @@ TEST_F(FormatConvertTest, Float) {
}
}
- for (const char *fmt : kFormats) {
- for (char f : {'f', 'F', //
- 'g', 'G', //
- 'a', 'A', //
- 'e', 'E'}) {
- std::string fmt_str = std::string(fmt) + f;
- for (double d : doubles) {
- int i = -10;
- FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
- UntypedFormatSpecImpl format(fmt_str);
- // We use ASSERT_EQ here because failures are usually correlated and a
- // bug would print way too many failed expectations causing the test to
- // time out.
- ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i),
- FormatPack(format, absl::MakeSpan(args)))
- << fmt_str << " " << StrPrint("%.18g", d) << " "
- << StrPrint("%.999f", d);
- }
+ // Workaround libc bug.
+ // https://sourceware.org/bugzilla/show_bug.cgi?id=22142
+ const bool gcc_bug_22142 =
+ StrPrint("%f", std::numeric_limits<double>::max()) !=
+ "1797693134862315708145274237317043567980705675258449965989174768031"
+ "5726078002853876058955863276687817154045895351438246423432132688946"
+ "4182768467546703537516986049910576551282076245490090389328944075868"
+ "5084551339423045832369032229481658085593321233482747978262041447231"
+ "68738177180919299881250404026184124858368.000000";
+
+ for (int exp = -300; exp <= 300; ++exp) {
+ const double all_ones_mantissa = 0x1fffffffffffff;
+ doubles.push_back(std::ldexp(all_ones_mantissa, exp));
+ if (gcc_bug_22142) {
+ skip_verify.insert(doubles.back());
+ }
+ }
+
+ if (gcc_bug_22142) {
+ using L = std::numeric_limits<double>;
+ skip_verify.insert(L::max());
+ skip_verify.insert(L::min()); // NOLINT
+ skip_verify.insert(L::denorm_min());
+ skip_verify.insert(-L::max());
+ skip_verify.insert(-L::min()); // NOLINT
+ skip_verify.insert(-L::denorm_min());
+ }
+
+ // Remove duplicates to speed up the logic below.
+ std::sort(doubles.begin(), doubles.end());
+ doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end());
+
+ TestWithMultipleFormatsHelper(doubles, skip_verify);
+}
+
+TEST_F(FormatConvertTest, DoubleRound) {
+ std::string s;
+ const auto format = [&](const char *fmt, double d) -> std::string & {
+ s.clear();
+ FormatArgImpl args[1] = {FormatArgImpl(d)};
+ AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+#if !defined(_MSC_VER)
+ // MSVC has a different rounding policy than us so we can't test our
+ // implementation against the native one there.
+ EXPECT_EQ(StrPrint(fmt, d), s);
+#endif // _MSC_VER
+
+ return s;
+ };
+ // All of these values have to be exactly represented.
+ // Otherwise we might not be testing what we think we are testing.
+
+ // These values can fit in a 64bit "fast" representation.
+ const double exact_value = 0.00000000000005684341886080801486968994140625;
+ assert(exact_value == std::pow(2, -44));
+ // Round up at a 5xx.
+ EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001");
+ // Round up at a >5
+ EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006");
+ // Round down at a <5
+ EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568");
+ // Nine handling
+ EXPECT_EQ(format("%.35f", exact_value),
+ "0.00000000000005684341886080801486969");
+ EXPECT_EQ(format("%.36f", exact_value),
+ "0.000000000000056843418860808014869690");
+ // Round down the last nine.
+ EXPECT_EQ(format("%.37f", exact_value),
+ "0.0000000000000568434188608080148696899");
+ EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147");
+ // Round up the last nine
+ EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470");
+ EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697");
+
+ // Round to even (down)
+ EXPECT_EQ(format("%.43f", exact_value),
+ "0.0000000000000568434188608080148696899414062");
+ // Exact
+ EXPECT_EQ(format("%.44f", exact_value),
+ "0.00000000000005684341886080801486968994140625");
+ // Round to even (up), let make the last digits 75 instead of 25
+ EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)),
+ "0.0000000000001705302565824240446090698242188");
+ // Exact, just to check.
+ EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)),
+ "0.00000000000017053025658242404460906982421875");
+
+ // This value has to be small enough that it won't fit in the uint128
+ // representation for printing.
+ const double small_exact_value =
+ 0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625; // NOLINT
+ assert(small_exact_value == std::pow(2, -120));
+ // Round up at a 5xx.
+ EXPECT_EQ(format("%.37f", small_exact_value),
+ "0.0000000000000000000000000000000000008");
+ // Round down at a <5
+ EXPECT_EQ(format("%.38f", small_exact_value),
+ "0.00000000000000000000000000000000000075");
+ // Round up at a >5
+ EXPECT_EQ(format("%.41f", small_exact_value),
+ "0.00000000000000000000000000000000000075232");
+ // Nine handling
+ EXPECT_EQ(format("%.55f", small_exact_value),
+ "0.0000000000000000000000000000000000007523163845262640051");
+ EXPECT_EQ(format("%.56f", small_exact_value),
+ "0.00000000000000000000000000000000000075231638452626400510");
+ EXPECT_EQ(format("%.57f", small_exact_value),
+ "0.000000000000000000000000000000000000752316384526264005100");
+ EXPECT_EQ(format("%.58f", small_exact_value),
+ "0.0000000000000000000000000000000000007523163845262640051000");
+ // Round down the last nine
+ EXPECT_EQ(format("%.59f", small_exact_value),
+ "0.00000000000000000000000000000000000075231638452626400509999");
+ // Round up the last nine
+ EXPECT_EQ(format("%.79f", small_exact_value),
+ "0.000000000000000000000000000000000000"
+ "7523163845262640050999913838222372338039460");
+
+ // Round to even (down)
+ EXPECT_EQ(format("%.119f", small_exact_value),
+ "0.000000000000000000000000000000000000"
+ "75231638452626400509999138382223723380"
+ "394595633413601376560109201818704605102539062");
+ // Exact
+ EXPECT_EQ(format("%.120f", small_exact_value),
+ "0.000000000000000000000000000000000000"
+ "75231638452626400509999138382223723380"
+ "3945956334136013765601092018187046051025390625");
+ // Round to even (up), let make the last digits 75 instead of 25
+ EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)),
+ "0.000000000000000000000000000000000002"
+ "25694915357879201529997415146671170141"
+ "183786900240804129680327605456113815307617188");
+ // Exact, just to check.
+ EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)),
+ "0.000000000000000000000000000000000002"
+ "25694915357879201529997415146671170141"
+ "1837869002408041296803276054561138153076171875");
+}
+
+TEST_F(FormatConvertTest, DoubleRoundA) {
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+ std::string s;
+ const auto format = [&](const char *fmt, double d) -> std::string & {
+ s.clear();
+ FormatArgImpl args[1] = {FormatArgImpl(d)};
+ AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+ if (native_traits.hex_float_has_glibc_rounding) {
+ EXPECT_EQ(StrPrint(fmt, d), s);
+ }
+ return s;
+ };
+
+ // 0x1.00018000p+100
+ const double on_boundary_odd = 1267679614447900152596896153600.0;
+ EXPECT_EQ(format("%.0a", on_boundary_odd), "0x1p+100");
+ EXPECT_EQ(format("%.1a", on_boundary_odd), "0x1.0p+100");
+ EXPECT_EQ(format("%.2a", on_boundary_odd), "0x1.00p+100");
+ EXPECT_EQ(format("%.3a", on_boundary_odd), "0x1.000p+100");
+ EXPECT_EQ(format("%.4a", on_boundary_odd), "0x1.0002p+100"); // round
+ EXPECT_EQ(format("%.5a", on_boundary_odd), "0x1.00018p+100");
+ EXPECT_EQ(format("%.6a", on_boundary_odd), "0x1.000180p+100");
+
+ // 0x1.00028000p-2
+ const double on_boundary_even = 0.250009536743164062500;
+ EXPECT_EQ(format("%.0a", on_boundary_even), "0x1p-2");
+ EXPECT_EQ(format("%.1a", on_boundary_even), "0x1.0p-2");
+ EXPECT_EQ(format("%.2a", on_boundary_even), "0x1.00p-2");
+ EXPECT_EQ(format("%.3a", on_boundary_even), "0x1.000p-2");
+ EXPECT_EQ(format("%.4a", on_boundary_even), "0x1.0002p-2"); // no round
+ EXPECT_EQ(format("%.5a", on_boundary_even), "0x1.00028p-2");
+ EXPECT_EQ(format("%.6a", on_boundary_even), "0x1.000280p-2");
+
+ // 0x1.00018001p+1
+ const double slightly_over = 2.00004577683284878730773925781250;
+ EXPECT_EQ(format("%.0a", slightly_over), "0x1p+1");
+ EXPECT_EQ(format("%.1a", slightly_over), "0x1.0p+1");
+ EXPECT_EQ(format("%.2a", slightly_over), "0x1.00p+1");
+ EXPECT_EQ(format("%.3a", slightly_over), "0x1.000p+1");
+ EXPECT_EQ(format("%.4a", slightly_over), "0x1.0002p+1");
+ EXPECT_EQ(format("%.5a", slightly_over), "0x1.00018p+1");
+ EXPECT_EQ(format("%.6a", slightly_over), "0x1.000180p+1");
+
+ // 0x1.00017fffp+0
+ const double slightly_under = 1.000022887950763106346130371093750;
+ EXPECT_EQ(format("%.0a", slightly_under), "0x1p+0");
+ EXPECT_EQ(format("%.1a", slightly_under), "0x1.0p+0");
+ EXPECT_EQ(format("%.2a", slightly_under), "0x1.00p+0");
+ EXPECT_EQ(format("%.3a", slightly_under), "0x1.000p+0");
+ EXPECT_EQ(format("%.4a", slightly_under), "0x1.0001p+0");
+ EXPECT_EQ(format("%.5a", slightly_under), "0x1.00018p+0");
+ EXPECT_EQ(format("%.6a", slightly_under), "0x1.000180p+0");
+ EXPECT_EQ(format("%.7a", slightly_under), "0x1.0001800p+0");
+
+ // 0x1.1b3829ac28058p+3
+ const double hex_value = 8.85060580848964661981881363317370414733886718750;
+ EXPECT_EQ(format("%.0a", hex_value), "0x1p+3");
+ EXPECT_EQ(format("%.1a", hex_value), "0x1.2p+3");
+ EXPECT_EQ(format("%.2a", hex_value), "0x1.1bp+3");
+ EXPECT_EQ(format("%.3a", hex_value), "0x1.1b4p+3");
+ EXPECT_EQ(format("%.4a", hex_value), "0x1.1b38p+3");
+ EXPECT_EQ(format("%.5a", hex_value), "0x1.1b383p+3");
+ EXPECT_EQ(format("%.6a", hex_value), "0x1.1b382ap+3");
+ EXPECT_EQ(format("%.7a", hex_value), "0x1.1b3829bp+3");
+ EXPECT_EQ(format("%.8a", hex_value), "0x1.1b3829acp+3");
+ EXPECT_EQ(format("%.9a", hex_value), "0x1.1b3829ac3p+3");
+ EXPECT_EQ(format("%.10a", hex_value), "0x1.1b3829ac28p+3");
+ EXPECT_EQ(format("%.11a", hex_value), "0x1.1b3829ac280p+3");
+ EXPECT_EQ(format("%.12a", hex_value), "0x1.1b3829ac2806p+3");
+ EXPECT_EQ(format("%.13a", hex_value), "0x1.1b3829ac28058p+3");
+ EXPECT_EQ(format("%.14a", hex_value), "0x1.1b3829ac280580p+3");
+ EXPECT_EQ(format("%.15a", hex_value), "0x1.1b3829ac2805800p+3");
+ EXPECT_EQ(format("%.16a", hex_value), "0x1.1b3829ac28058000p+3");
+ EXPECT_EQ(format("%.17a", hex_value), "0x1.1b3829ac280580000p+3");
+ EXPECT_EQ(format("%.18a", hex_value), "0x1.1b3829ac2805800000p+3");
+ EXPECT_EQ(format("%.19a", hex_value), "0x1.1b3829ac28058000000p+3");
+ EXPECT_EQ(format("%.20a", hex_value), "0x1.1b3829ac280580000000p+3");
+ EXPECT_EQ(format("%.21a", hex_value), "0x1.1b3829ac2805800000000p+3");
+
+ // 0x1.0818283848586p+3
+ const double hex_value2 = 8.2529488658208371987257123691961169242858886718750;
+ EXPECT_EQ(format("%.0a", hex_value2), "0x1p+3");
+ EXPECT_EQ(format("%.1a", hex_value2), "0x1.1p+3");
+ EXPECT_EQ(format("%.2a", hex_value2), "0x1.08p+3");
+ EXPECT_EQ(format("%.3a", hex_value2), "0x1.082p+3");
+ EXPECT_EQ(format("%.4a", hex_value2), "0x1.0818p+3");
+ EXPECT_EQ(format("%.5a", hex_value2), "0x1.08183p+3");
+ EXPECT_EQ(format("%.6a", hex_value2), "0x1.081828p+3");
+ EXPECT_EQ(format("%.7a", hex_value2), "0x1.0818284p+3");
+ EXPECT_EQ(format("%.8a", hex_value2), "0x1.08182838p+3");
+ EXPECT_EQ(format("%.9a", hex_value2), "0x1.081828385p+3");
+ EXPECT_EQ(format("%.10a", hex_value2), "0x1.0818283848p+3");
+ EXPECT_EQ(format("%.11a", hex_value2), "0x1.08182838486p+3");
+ EXPECT_EQ(format("%.12a", hex_value2), "0x1.081828384858p+3");
+ EXPECT_EQ(format("%.13a", hex_value2), "0x1.0818283848586p+3");
+ EXPECT_EQ(format("%.14a", hex_value2), "0x1.08182838485860p+3");
+ EXPECT_EQ(format("%.15a", hex_value2), "0x1.081828384858600p+3");
+ EXPECT_EQ(format("%.16a", hex_value2), "0x1.0818283848586000p+3");
+ EXPECT_EQ(format("%.17a", hex_value2), "0x1.08182838485860000p+3");
+ EXPECT_EQ(format("%.18a", hex_value2), "0x1.081828384858600000p+3");
+ EXPECT_EQ(format("%.19a", hex_value2), "0x1.0818283848586000000p+3");
+ EXPECT_EQ(format("%.20a", hex_value2), "0x1.08182838485860000000p+3");
+ EXPECT_EQ(format("%.21a", hex_value2), "0x1.081828384858600000000p+3");
+}
+
+TEST_F(FormatConvertTest, LongDoubleRoundA) {
+ if (std::numeric_limits<long double>::digits % 4 != 0) {
+ // This test doesn't really make sense to run on platforms where a long
+ // double has a different mantissa size (mod 4) than Prod, since then the
+ // leading digit will be formatted differently.
+ return;
+ }
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+ std::string s;
+ const auto format = [&](const char *fmt, long double d) -> std::string & {
+ s.clear();
+ FormatArgImpl args[1] = {FormatArgImpl(d)};
+ AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+ if (native_traits.hex_float_has_glibc_rounding &&
+ native_traits.hex_float_optimizes_leading_digit_bit_count) {
+ EXPECT_EQ(StrPrint(fmt, d), s);
+ }
+ return s;
+ };
+
+ // 0x8.8p+4
+ const long double on_boundary_even = 136.0;
+ EXPECT_EQ(format("%.0La", on_boundary_even), "0x8p+4");
+ EXPECT_EQ(format("%.1La", on_boundary_even), "0x8.8p+4");
+ EXPECT_EQ(format("%.2La", on_boundary_even), "0x8.80p+4");
+ EXPECT_EQ(format("%.3La", on_boundary_even), "0x8.800p+4");
+ EXPECT_EQ(format("%.4La", on_boundary_even), "0x8.8000p+4");
+ EXPECT_EQ(format("%.5La", on_boundary_even), "0x8.80000p+4");
+ EXPECT_EQ(format("%.6La", on_boundary_even), "0x8.800000p+4");
+
+ // 0x9.8p+4
+ const long double on_boundary_odd = 152.0;
+ EXPECT_EQ(format("%.0La", on_boundary_odd), "0xap+4");
+ EXPECT_EQ(format("%.1La", on_boundary_odd), "0x9.8p+4");
+ EXPECT_EQ(format("%.2La", on_boundary_odd), "0x9.80p+4");
+ EXPECT_EQ(format("%.3La", on_boundary_odd), "0x9.800p+4");
+ EXPECT_EQ(format("%.4La", on_boundary_odd), "0x9.8000p+4");
+ EXPECT_EQ(format("%.5La", on_boundary_odd), "0x9.80000p+4");
+ EXPECT_EQ(format("%.6La", on_boundary_odd), "0x9.800000p+4");
+
+ // 0x8.80001p+24
+ const long double slightly_over = 142606352.0;
+ EXPECT_EQ(format("%.0La", slightly_over), "0x9p+24");
+ EXPECT_EQ(format("%.1La", slightly_over), "0x8.8p+24");
+ EXPECT_EQ(format("%.2La", slightly_over), "0x8.80p+24");
+ EXPECT_EQ(format("%.3La", slightly_over), "0x8.800p+24");
+ EXPECT_EQ(format("%.4La", slightly_over), "0x8.8000p+24");
+ EXPECT_EQ(format("%.5La", slightly_over), "0x8.80001p+24");
+ EXPECT_EQ(format("%.6La", slightly_over), "0x8.800010p+24");
+
+ // 0x8.7ffffp+24
+ const long double slightly_under = 142606320.0;
+ EXPECT_EQ(format("%.0La", slightly_under), "0x8p+24");
+ EXPECT_EQ(format("%.1La", slightly_under), "0x8.8p+24");
+ EXPECT_EQ(format("%.2La", slightly_under), "0x8.80p+24");
+ EXPECT_EQ(format("%.3La", slightly_under), "0x8.800p+24");
+ EXPECT_EQ(format("%.4La", slightly_under), "0x8.8000p+24");
+ EXPECT_EQ(format("%.5La", slightly_under), "0x8.7ffffp+24");
+ EXPECT_EQ(format("%.6La", slightly_under), "0x8.7ffff0p+24");
+ EXPECT_EQ(format("%.7La", slightly_under), "0x8.7ffff00p+24");
+
+ // 0xc.0828384858688000p+128
+ const long double eights = 4094231060438608800781871108094404067328.0;
+ EXPECT_EQ(format("%.0La", eights), "0xcp+128");
+ EXPECT_EQ(format("%.1La", eights), "0xc.1p+128");
+ EXPECT_EQ(format("%.2La", eights), "0xc.08p+128");
+ EXPECT_EQ(format("%.3La", eights), "0xc.083p+128");
+ EXPECT_EQ(format("%.4La", eights), "0xc.0828p+128");
+ EXPECT_EQ(format("%.5La", eights), "0xc.08284p+128");
+ EXPECT_EQ(format("%.6La", eights), "0xc.082838p+128");
+ EXPECT_EQ(format("%.7La", eights), "0xc.0828385p+128");
+ EXPECT_EQ(format("%.8La", eights), "0xc.08283848p+128");
+ EXPECT_EQ(format("%.9La", eights), "0xc.082838486p+128");
+ EXPECT_EQ(format("%.10La", eights), "0xc.0828384858p+128");
+ EXPECT_EQ(format("%.11La", eights), "0xc.08283848587p+128");
+ EXPECT_EQ(format("%.12La", eights), "0xc.082838485868p+128");
+ EXPECT_EQ(format("%.13La", eights), "0xc.0828384858688p+128");
+ EXPECT_EQ(format("%.14La", eights), "0xc.08283848586880p+128");
+ EXPECT_EQ(format("%.15La", eights), "0xc.082838485868800p+128");
+ EXPECT_EQ(format("%.16La", eights), "0xc.0828384858688000p+128");
+}
+
+// We don't actually store the results. This is just to exercise the rest of the
+// machinery.
+struct NullSink {
+ friend void AbslFormatFlush(NullSink *sink, string_view str) {}
+};
+
+template <typename... T>
+bool FormatWithNullSink(absl::string_view fmt, const T &... a) {
+ NullSink sink;
+ FormatArgImpl args[] = {FormatArgImpl(a)...};
+ return FormatUntyped(&sink, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
+}
+
+TEST_F(FormatConvertTest, ExtremeWidthPrecision) {
+ for (const char *fmt : {"f"}) {
+ for (double d : {1e-100, 1.0, 1e100}) {
+ constexpr int max = std::numeric_limits<int>::max();
+ EXPECT_TRUE(FormatWithNullSink(std::string("%.*") + fmt, max, d));
+ EXPECT_TRUE(FormatWithNullSink(std::string("%1.*") + fmt, max, d));
+ EXPECT_TRUE(FormatWithNullSink(std::string("%*") + fmt, max, d));
+ EXPECT_TRUE(FormatWithNullSink(std::string("%*.*") + fmt, max, max, d));
}
}
}
TEST_F(FormatConvertTest, LongDouble) {
- const char *const kFormats[] = {"%", "%.3", "%8.5", "%9",
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+ const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000",
"%.60", "%+", "% ", "%-10"};
- // This value is not representable in double, but it is in long double that
- // uses the extended format.
- // This is to verify that we are not truncating the value mistakenly through a
- // double.
- long double very_precise = 10000000000000000.25L;
-
std::vector<long double> doubles = {
0.0,
-0.0,
- very_precise,
- 1 / very_precise,
std::numeric_limits<long double>::max(),
-std::numeric_limits<long double>::max(),
std::numeric_limits<long double>::min(),
@@ -481,28 +1078,73 @@ TEST_F(FormatConvertTest, LongDouble) {
std::numeric_limits<long double>::infinity(),
-std::numeric_limits<long double>::infinity()};
+ for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L,
+ 1234567.L, 12345678.L, 123456789.L, 1234567890.L,
+ 12345678901.L, 123456789012.L, 1234567890123.L,
+ // This value is not representable in double, but it
+ // is in long double that uses the extended format.
+ // This is to verify that we are not truncating the
+ // value mistakenly through a double.
+ 10000000000000000.25L}) {
+ for (int exp : {-1000, -500, 0, 500, 1000}) {
+ for (int sign : {1, -1}) {
+ doubles.push_back(sign * std::ldexp(base, exp));
+ doubles.push_back(sign / std::ldexp(base, exp));
+ }
+ }
+ }
+
+ // Regression tests
+ //
+ // Using a string literal because not all platforms support hex literals or it
+ // might be out of range.
+ doubles.push_back(std::strtold("-0xf.ffffffb5feafffbp-16324L", nullptr));
+
for (const char *fmt : kFormats) {
for (char f : {'f', 'F', //
'g', 'G', //
'a', 'A', //
'e', 'E'}) {
std::string fmt_str = std::string(fmt) + 'L' + f;
+
+ if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F' &&
+ f != 'a' && f != 'A') {
+ // This particular test takes way too long with snprintf.
+ // Disable for the case we are not implementing natively.
+ continue;
+ }
+
+ if (f == 'a' || f == 'A') {
+ if (!native_traits.hex_float_has_glibc_rounding ||
+ !native_traits.hex_float_optimizes_leading_digit_bit_count) {
+ continue;
+ }
+ }
+
for (auto d : doubles) {
FormatArgImpl arg(d);
UntypedFormatSpecImpl format(fmt_str);
+ std::string result = FormatPack(format, {&arg, 1});
+
+#ifdef _MSC_VER
+ // MSVC has a different rounding policy than us so we can't test our
+ // implementation against the native one there.
+ continue;
+#endif // _MSC_VER
+
// We use ASSERT_EQ here because failures are usually correlated and a
// bug would print way too many failed expectations causing the test to
// time out.
- ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
- FormatPack(format, {&arg, 1}))
+ ASSERT_EQ(StrPrint(fmt_str.c_str(), d), result)
<< fmt_str << " " << StrPrint("%.18Lg", d) << " "
- << StrPrint("%.999Lf", d);
+ << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d);
}
}
}
}
-TEST_F(FormatConvertTest, IntAsFloat) {
+TEST_F(FormatConvertTest, IntAsDouble) {
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
const int kMin = std::numeric_limits<int>::min();
const int kMax = std::numeric_limits<int>::max();
const int ia[] = {
@@ -518,14 +1160,17 @@ TEST_F(FormatConvertTest, IntAsFloat) {
const char *fmt;
};
const double dx = static_cast<double>(fx);
- const Expectation kExpect[] = {
- { __LINE__, StrPrint("%f", dx), "%f" },
- { __LINE__, StrPrint("%12f", dx), "%12f" },
- { __LINE__, StrPrint("%.12f", dx), "%.12f" },
- { __LINE__, StrPrint("%12a", dx), "%12a" },
- { __LINE__, StrPrint("%.12a", dx), "%.12a" },
+ std::vector<Expectation> expect = {
+ {__LINE__, StrPrint("%f", dx), "%f"},
+ {__LINE__, StrPrint("%12f", dx), "%12f"},
+ {__LINE__, StrPrint("%.12f", dx), "%.12f"},
+ {__LINE__, StrPrint("%.12a", dx), "%.12a"},
};
- for (const Expectation &e : kExpect) {
+ if (native_traits.hex_float_uses_minimal_precision_when_not_specified) {
+ Expectation ex = {__LINE__, StrPrint("%12a", dx), "%12a"};
+ expect.push_back(ex);
+ }
+ for (const Expectation &e : expect) {
SCOPED_TRACE(e.line);
SCOPED_TRACE(e.fmt);
UntypedFormatSpecImpl format(e.fmt);
@@ -570,6 +1215,26 @@ TEST_F(FormatConvertTest, ExpectedFailures) {
EXPECT_TRUE(FormatFails("%*d", ""));
}
+// Sanity check to make sure that we are testing what we think we're testing on
+// e.g. the x86_64+glibc platform.
+TEST_F(FormatConvertTest, GlibcHasCorrectTraits) {
+#if !defined(__GLIBC__) || !defined(__x86_64__)
+ return;
+#endif
+ const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+ // If one of the following tests break then it is either because the above PP
+ // macro guards failed to exclude a new platform (likely) or because something
+ // has changed in the implemention of glibc sprintf float formatting behavior.
+ // If the latter, then the code that computes these flags needs to be
+ // revisited and/or possibly the StrFormat implementation.
+ EXPECT_TRUE(native_traits.hex_float_has_glibc_rounding);
+ EXPECT_TRUE(native_traits.hex_float_prefers_denormal_repr);
+ EXPECT_TRUE(
+ native_traits.hex_float_uses_minimal_precision_when_not_specified);
+ EXPECT_TRUE(native_traits.hex_float_optimizes_leading_digit_bit_count);
+}
+
} // namespace
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.cc
index c2174703c3e..bb0d96cf321 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,38 +20,8 @@
#include <string>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-namespace {
-// clang-format off
-#define ABSL_LENGTH_MODS_EXPAND_ \
- X_VAL(h) X_SEP \
- X_VAL(hh) X_SEP \
- X_VAL(l) X_SEP \
- X_VAL(ll) X_SEP \
- X_VAL(L) X_SEP \
- X_VAL(j) X_SEP \
- X_VAL(z) X_SEP \
- X_VAL(t) X_SEP \
- X_VAL(q)
-// clang-format on
-} // namespace
-
-const LengthMod::Spec LengthMod::kSpecs[] = {
-#define X_VAL(id) { LengthMod::id, #id, strlen(#id) }
-#define X_SEP ,
- ABSL_LENGTH_MODS_EXPAND_, {LengthMod::none, "", 0}
-#undef X_VAL
-#undef X_SEP
-};
-
-const ConversionChar::Spec ConversionChar::kSpecs[] = {
-#define X_VAL(id) { ConversionChar::id, #id[0] }
-#define X_SEP ,
- ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP),
- {ConversionChar::none, '\0'},
-#undef X_VAL
-#undef X_SEP
-};
std::string Flags::ToString() const {
std::string s;
@@ -63,22 +33,43 @@ std::string Flags::ToString() const {
return s;
}
-const size_t LengthMod::kNumValues;
+#define ABSL_INTERNAL_X_VAL(id) \
+ constexpr absl::FormatConversionChar FormatConversionCharInternal::id;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr absl::FormatConversionChar FormatConversionCharInternal::kNone;
+
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ constexpr FormatConversionCharSet FormatConversionCharSetInternal::c;
+ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
-const size_t ConversionChar::kNumValues;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kStar;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kIntegral;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kFloating;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kNumeric;
+// NOLINTNEXTLINE(readability-redundant-declaration)
+constexpr FormatConversionCharSet FormatConversionCharSetInternal::kPointer;
-bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) {
+bool FormatSinkImpl::PutPaddedString(string_view value, int width,
+ int precision, bool left) {
size_t space_remaining = 0;
- if (w >= 0) space_remaining = w;
- size_t n = v.size();
- if (p >= 0) n = std::min(n, static_cast<size_t>(p));
- string_view shown(v.data(), n);
+ if (width >= 0) space_remaining = width;
+ size_t n = value.size();
+ if (precision >= 0) n = std::min(n, static_cast<size_t>(precision));
+ string_view shown(value.data(), n);
space_remaining = Excess(shown.size(), space_remaining);
- if (!l) Append(space_remaining, ' ');
+ if (!left) Append(space_remaining, ' ');
Append(shown);
- if (l) Append(space_remaining, ' ');
+ if (left) Append(space_remaining, ' ');
return true;
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.h
index 7ce80d42547..a9b9e137deb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -13,22 +13,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-//
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
#include <limits.h>
+
#include <cstddef>
#include <cstring>
#include <ostream>
+#include "absl/base/config.h"
#include "absl/base/port.h"
+#include "absl/meta/type_traits.h"
#include "absl/strings/internal/str_format/output.h"
#include "absl/strings/string_view.h"
-class Cord;
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+enum class FormatConversionChar : uint8_t;
+enum class FormatConversionCharSet : uint64_t;
namespace str_format_internal {
@@ -103,7 +107,7 @@ class FormatSinkImpl {
size_t size() const { return size_; }
// Put 'v' to 'sink' with specified width, precision, and left flag.
- bool PutPaddedString(string_view v, int w, int p, bool l);
+ bool PutPaddedString(string_view v, int width, int precision, bool left);
template <typename T>
T Wrap() {
@@ -137,58 +141,10 @@ struct Flags {
}
};
-struct LengthMod {
- public:
- enum Id : uint8_t {
- h, hh, l, ll, L, j, z, t, q, none
- };
- static const size_t kNumValues = none + 1;
-
- LengthMod() : id_(none) {}
-
- // Index into the opaque array of LengthMod enums.
- // Requires: i < kNumValues
- static LengthMod FromIndex(size_t i) {
- return LengthMod(kSpecs[i].value);
- }
-
- static LengthMod FromId(Id id) { return LengthMod(id); }
-
- // The length modifier std::string associated with a specified LengthMod.
- string_view name() const {
- const Spec& spec = kSpecs[id_];
- return {spec.name, spec.name_length};
- }
-
- Id id() const { return id_; }
-
- friend bool operator==(const LengthMod& a, const LengthMod& b) {
- return a.id() == b.id();
- }
- friend bool operator!=(const LengthMod& a, const LengthMod& b) {
- return !(a == b);
- }
- friend std::ostream& operator<<(std::ostream& os, const LengthMod& v) {
- return os << v.name();
- }
-
- private:
- struct Spec {
- Id value;
- const char *name;
- size_t name_length;
- };
- static const Spec kSpecs[];
-
- explicit LengthMod(Id id) : id_(id) {}
-
- Id id_;
-};
-
// clang-format off
-#define ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
+#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
/* text */ \
- X_VAL(c) X_SEP X_VAL(C) X_SEP X_VAL(s) X_SEP X_VAL(S) X_SEP \
+ X_VAL(c) X_SEP X_VAL(s) X_SEP \
/* ints */ \
X_VAL(d) X_SEP X_VAL(i) X_SEP X_VAL(o) X_SEP \
X_VAL(u) X_SEP X_VAL(x) X_SEP X_VAL(X) X_SEP \
@@ -199,119 +155,119 @@ struct LengthMod {
X_VAL(n) X_SEP X_VAL(p)
// clang-format on
-struct ConversionChar {
- public:
- enum Id : uint8_t {
- c, C, s, S, // text
+// This type should not be referenced, it exists only to provide labels
+// internally that match the values declared in FormatConversionChar in
+// str_format.h. This is meant to allow internal libraries to use the same
+// declared interface type as the public interface
+// (absl::StrFormatConversionChar) while keeping the definition in a public
+// header.
+// Internal libraries should use the form
+// `FormatConversionCharInternal::c`, `FormatConversionCharInternal::kNone` for
+// comparisons. Use in switch statements is not recommended due to a bug in how
+// gcc 4.9 -Wswitch handles declared but undefined enums.
+struct FormatConversionCharInternal {
+ FormatConversionCharInternal() = delete;
+
+ private:
+ // clang-format off
+ enum class Enum : uint8_t {
+ c, s, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
n, p, // misc
- none
+ kNone
};
- static const size_t kNumValues = none + 1;
-
- ConversionChar() : id_(none) {}
-
+ // clang-format on
public:
- // Index into the opaque array of ConversionChar enums.
- // Requires: i < kNumValues
- static ConversionChar FromIndex(size_t i) {
- return ConversionChar(kSpecs[i].value);
- }
-
- static ConversionChar FromChar(char c) {
- ConversionChar::Id out_id = ConversionChar::none;
- switch (c) {
-#define X_VAL(id) \
- case #id[0]: \
- out_id = ConversionChar::id; \
- break;
- ABSL_CONVERSION_CHARS_EXPAND_(X_VAL, )
-#undef X_VAL
- default:
- break;
- }
- return ConversionChar(out_id);
- }
-
- static ConversionChar FromId(Id id) { return ConversionChar(id); }
- Id id() const { return id_; }
+#define ABSL_INTERNAL_X_VAL(id) \
+ static constexpr FormatConversionChar id = \
+ static_cast<FormatConversionChar>(Enum::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
+ static constexpr FormatConversionChar kNone =
+ static_cast<FormatConversionChar>(Enum::kNone);
+};
+// clang-format on
- int radix() const {
- switch (id()) {
- case x: case X: case a: case A: case p: return 16;
- case o: return 8;
- default: return 10;
- }
- }
-
- bool upper() const {
- switch (id()) {
- case X: case F: case E: case G: case A: return true;
- default: return false;
- }
+inline FormatConversionChar FormatConversionCharFromChar(char c) {
+ switch (c) {
+#define ABSL_INTERNAL_X_VAL(id) \
+ case #id[0]: \
+ return FormatConversionCharInternal::id;
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
+#undef ABSL_INTERNAL_X_VAL
}
+ return FormatConversionCharInternal::kNone;
+}
- bool is_signed() const {
- switch (id()) {
- case d: case i: return true;
- default: return false;
- }
- }
-
- bool is_integral() const {
- switch (id()) {
- case d: case i: case u: case o: case x: case X:
- return true;
- default: return false;
- }
+inline bool FormatConversionCharIsUpper(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::X ||
+ c == FormatConversionCharInternal::F ||
+ c == FormatConversionCharInternal::E ||
+ c == FormatConversionCharInternal::G ||
+ c == FormatConversionCharInternal::A) {
+ return true;
+ } else {
+ return false;
}
+}
- bool is_float() const {
- switch (id()) {
- case a: case e: case f: case g: case A: case E: case F: case G:
- return true;
- default: return false;
- }
+inline bool FormatConversionCharIsFloat(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::a ||
+ c == FormatConversionCharInternal::e ||
+ c == FormatConversionCharInternal::f ||
+ c == FormatConversionCharInternal::g ||
+ c == FormatConversionCharInternal::A ||
+ c == FormatConversionCharInternal::E ||
+ c == FormatConversionCharInternal::F ||
+ c == FormatConversionCharInternal::G) {
+ return true;
+ } else {
+ return false;
}
+}
- bool IsValid() const { return id() != none; }
-
- // The associated char.
- char Char() const { return kSpecs[id_].name; }
-
- friend bool operator==(const ConversionChar& a, const ConversionChar& b) {
- return a.id() == b.id();
- }
- friend bool operator!=(const ConversionChar& a, const ConversionChar& b) {
- return !(a == b);
- }
- friend std::ostream& operator<<(std::ostream& os, const ConversionChar& v) {
- char c = v.Char();
- if (!c) c = '?';
- return os << c;
+inline char FormatConversionCharToChar(FormatConversionChar c) {
+ if (c == FormatConversionCharInternal::kNone) {
+ return '\0';
+
+#define ABSL_INTERNAL_X_VAL(e) \
+ } else if (c == FormatConversionCharInternal::e) { \
+ return #e[0];
+#define ABSL_INTERNAL_X_SEP
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
+ ABSL_INTERNAL_X_SEP)
+ } else {
+ return '\0';
}
- private:
- struct Spec {
- Id value;
- char name;
- };
- static const Spec kSpecs[];
+#undef ABSL_INTERNAL_X_VAL
+#undef ABSL_INTERNAL_X_SEP
+}
- explicit ConversionChar(Id id) : id_(id) {}
+// The associated char.
+inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
+ char c = FormatConversionCharToChar(v);
+ if (!c) c = '?';
+ return os << c;
+}
- Id id_;
-};
+struct FormatConversionSpecImplFriend;
-class ConversionSpec {
+class FormatConversionSpecImpl {
public:
- Flags flags() const { return flags_; }
- LengthMod length_mod() const { return length_mod_; }
- ConversionChar conv() const {
+ // Width and precison are not specified, no flags are set.
+ bool is_basic() const { return flags_.basic; }
+ bool has_left_flag() const { return flags_.left; }
+ bool has_show_pos_flag() const { return flags_.show_pos; }
+ bool has_sign_col_flag() const { return flags_.sign_col; }
+ bool has_alt_flag() const { return flags_.alt; }
+ bool has_zero_flag() const { return flags_.zero; }
+
+ FormatConversionChar conversion_char() const {
// Keep this field first in the struct . It generates better code when
// accessing it when ConversionSpec is passed by value in registers.
- static_assert(offsetof(ConversionSpec, conv_) == 0, "");
+ static_assert(offsetof(FormatConversionSpecImpl, conv_) == 0, "");
return conv_;
}
@@ -322,46 +278,96 @@ class ConversionSpec {
// negative value.
int precision() const { return precision_; }
- void set_flags(Flags f) { flags_ = f; }
- void set_length_mod(LengthMod lm) { length_mod_ = lm; }
- void set_conv(ConversionChar c) { conv_ = c; }
- void set_width(int w) { width_ = w; }
- void set_precision(int p) { precision_ = p; }
- void set_left(bool b) { flags_.left = b; }
+ template <typename T>
+ T Wrap() {
+ return T(*this);
+ }
private:
- ConversionChar conv_;
+ friend struct str_format_internal::FormatConversionSpecImplFriend;
+ FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
Flags flags_;
- LengthMod length_mod_;
int width_;
int precision_;
};
-constexpr uint64_t ConversionCharToConvValue(char conv) {
+struct FormatConversionSpecImplFriend final {
+ static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
+ conv->flags_ = f;
+ }
+ static void SetConversionChar(FormatConversionChar c,
+ FormatConversionSpecImpl* conv) {
+ conv->conv_ = c;
+ }
+ static void SetWidth(int w, FormatConversionSpecImpl* conv) {
+ conv->width_ = w;
+ }
+ static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
+ conv->precision_ = p;
+ }
+ static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
+ return spec.flags_.ToString();
+ }
+};
+
+// Type safe OR operator.
+// We need this for two reasons:
+// 1. operator| on enums makes them decay to integers and the result is an
+// integer. We need the result to stay as an enum.
+// 2. We use "enum class" which would not work even if we accepted the decay.
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+ FormatConversionCharSet a) {
+ return a;
+}
+
+template <typename... CharSet>
+constexpr FormatConversionCharSet FormatConversionCharSetUnion(
+ FormatConversionCharSet a, CharSet... rest) {
+ return static_cast<FormatConversionCharSet>(
+ static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(FormatConversionCharSetUnion(rest...)));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(FormatConversionChar c) {
+ return uint64_t{1} << (1 + static_cast<uint8_t>(c));
+}
+
+constexpr uint64_t FormatConversionCharToConvInt(char conv) {
return
-#define CONV_SET_CASE(c) \
- conv == #c[0] ? (uint64_t{1} << (1 + ConversionChar::Id::c)):
- ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
-#undef CONV_SET_CASE
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ conv == #c[0] \
+ ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
+ :
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
conv == '*'
? 1
: 0;
}
-enum class Conv : uint64_t {
-#define CONV_SET_CASE(c) c = ConversionCharToConvValue(#c[0]),
- ABSL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
-#undef CONV_SET_CASE
+constexpr FormatConversionCharSet FormatConversionCharToConvValue(char conv) {
+ return static_cast<FormatConversionCharSet>(
+ FormatConversionCharToConvInt(conv));
+}
+
+struct FormatConversionCharSetInternal {
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ static constexpr FormatConversionCharSet c = \
+ FormatConversionCharToConvValue(#c[0]);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
+#undef ABSL_INTERNAL_CHAR_SET_CASE
// Used for width/precision '*' specification.
- star = ConversionCharToConvValue('*'),
-
- // Some predefined values:
- integral = d | i | u | o | x | X,
- floating = a | e | f | g | A | E | F | G,
- numeric = integral | floating,
- string = s, // absl:ignore(std::string)
- pointer = p
+ static constexpr FormatConversionCharSet kStar =
+ FormatConversionCharToConvValue('*');
+
+ static constexpr FormatConversionCharSet kIntegral =
+ FormatConversionCharSetUnion(d, i, u, o, x, X);
+ static constexpr FormatConversionCharSet kFloating =
+ FormatConversionCharSetUnion(a, e, f, g, A, E, F, G);
+ static constexpr FormatConversionCharSet kNumeric =
+ FormatConversionCharSetUnion(kIntegral, kFloating);
+ static constexpr FormatConversionCharSet kPointer = p;
};
// Type safe OR operator.
@@ -369,36 +375,44 @@ enum class Conv : uint64_t {
// 1. operator| on enums makes them decay to integers and the result is an
// integer. We need the result to stay as an enum.
// 2. We use "enum class" which would not work even if we accepted the decay.
-constexpr Conv operator|(Conv a, Conv b) {
- return Conv(static_cast<uint64_t>(a) | static_cast<uint64_t>(b));
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+ FormatConversionCharSet b) {
+ return FormatConversionCharSetUnion(a, b);
+}
+
+// Overloaded conversion functions to support absl::ParsedFormat.
+// Get a conversion with a single character in it.
+constexpr FormatConversionCharSet ToFormatConversionCharSet(char c) {
+ return static_cast<FormatConversionCharSet>(
+ FormatConversionCharToConvValue(c));
}
// Get a conversion with a single character in it.
-constexpr Conv ConversionCharToConv(char c) {
- return Conv(ConversionCharToConvValue(c));
+constexpr FormatConversionCharSet ToFormatConversionCharSet(
+ FormatConversionCharSet c) {
+ return c;
}
+template <typename T>
+void ToFormatConversionCharSet(T) = delete;
+
// Checks whether `c` exists in `set`.
-constexpr bool Contains(Conv set, char c) {
- return (static_cast<uint64_t>(set) & ConversionCharToConvValue(c)) != 0;
+constexpr bool Contains(FormatConversionCharSet set, char c) {
+ return (static_cast<uint64_t>(set) &
+ static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
-constexpr bool Contains(Conv set, Conv c) {
+constexpr bool Contains(FormatConversionCharSet set,
+ FormatConversionCharSet c) {
return (static_cast<uint64_t>(set) & static_cast<uint64_t>(c)) ==
static_cast<uint64_t>(c);
}
-// Return type of the AbslFormatConvert() functions.
-// The Conv template parameter is used to inform the framework of what
-// conversion characters are supported by that AbslFormatConvert routine.
-template <Conv C>
-struct ConvertResult {
- static constexpr Conv kConv = C;
- bool value;
-};
-template <Conv C>
-constexpr Conv ConvertResult<C>::kConv;
+// Checks whether all the characters in `c` are contained in `set`
+constexpr bool Contains(FormatConversionCharSet set, FormatConversionChar c) {
+ return (static_cast<uint64_t>(set) & FormatConversionCharToConvInt(c)) != 0;
+}
// Return capacity - used, clipped to a minimum of 0.
inline size_t Excess(size_t used, size_t capacity) {
@@ -407,6 +421,7 @@ inline size_t Excess(size_t used, size_t capacity) {
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_EXTENSION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
index 224fc923d3e..1c93fdb1c75 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,9 +18,27 @@
#include <random>
#include <string>
-#include "absl/strings/str_format.h"
#include "gtest/gtest.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+
+namespace my_namespace {
+class UserDefinedType {
+ public:
+ UserDefinedType() = default;
+
+ void Append(absl::string_view str) { value_.append(str.data(), str.size()); }
+ const std::string& Value() const { return value_; }
+
+ friend void AbslFormatFlush(UserDefinedType* x, absl::string_view str) {
+ x->Append(str);
+ }
+
+ private:
+ std::string value_;
+};
+} // namespace my_namespace
namespace {
@@ -62,4 +80,19 @@ TEST(FormatExtensionTest, SinkAppendChars) {
EXPECT_EQ(actual, expected);
}
}
+
+TEST(FormatExtensionTest, VerifyEnumEquality) {
+#define X_VAL(id) \
+ EXPECT_EQ(absl::FormatConversionChar::id, \
+ absl::str_format_internal::FormatConversionCharInternal::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+
+#define X_VAL(id) \
+ EXPECT_EQ(absl::FormatConversionCharSet::id, \
+ absl::str_format_internal::FormatConversionCharSetInternal::id);
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, );
+#undef X_VAL
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
index 6176db9cb5a..b1c40684756 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -1,23 +1,944 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/float_conversion.h"
#include <string.h>
+
#include <algorithm>
#include <cassert>
#include <cmath>
+#include <limits>
#include <string>
+#include "absl/base/attributes.h"
+#include "absl/base/config.h"
+#include "absl/base/optimization.h"
+#include "absl/functional/function_ref.h"
+#include "absl/meta/type_traits.h"
+#include "absl/numeric/bits.h"
+#include "absl/numeric/int128.h"
+#include "absl/numeric/internal/representation.h"
+#include "absl/strings/numbers.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
-char *CopyStringTo(string_view v, char *out) {
+using ::absl::numeric_internal::IsDoubleDouble;
+
+// The code below wants to avoid heap allocations.
+// To do so it needs to allocate memory on the stack.
+// `StackArray` will allocate memory on the stack in the form of a uint32_t
+// array and call the provided callback with said memory.
+// It will allocate memory in increments of 512 bytes. We could allocate the
+// largest needed unconditionally, but that is more than we need in most of
+// cases. This way we use less stack in the common cases.
+class StackArray {
+ using Func = absl::FunctionRef<void(absl::Span<uint32_t>)>;
+ static constexpr size_t kStep = 512 / sizeof(uint32_t);
+ // 5 steps is 2560 bytes, which is enough to hold a long double with the
+ // largest/smallest exponents.
+ // The operations below will static_assert their particular maximum.
+ static constexpr size_t kNumSteps = 5;
+
+ // We do not want this function to be inlined.
+ // Otherwise the caller will allocate the stack space unnecessarily for all
+ // the variants even though it only calls one.
+ template <size_t steps>
+ ABSL_ATTRIBUTE_NOINLINE static void RunWithCapacityImpl(Func f) {
+ uint32_t values[steps * kStep]{};
+ f(absl::MakeSpan(values));
+ }
+
+ public:
+ static constexpr size_t kMaxCapacity = kStep * kNumSteps;
+
+ static void RunWithCapacity(size_t capacity, Func f) {
+ assert(capacity <= kMaxCapacity);
+ const size_t step = (capacity + kStep - 1) / kStep;
+ assert(step <= kNumSteps);
+ switch (step) {
+ case 1:
+ return RunWithCapacityImpl<1>(f);
+ case 2:
+ return RunWithCapacityImpl<2>(f);
+ case 3:
+ return RunWithCapacityImpl<3>(f);
+ case 4:
+ return RunWithCapacityImpl<4>(f);
+ case 5:
+ return RunWithCapacityImpl<5>(f);
+ }
+
+ assert(false && "Invalid capacity");
+ }
+};
+
+// Calculates `10 * (*v) + carry` and stores the result in `*v` and returns
+// the carry.
+template <typename Int>
+inline Int MultiplyBy10WithCarry(Int *v, Int carry) {
+ using BiggerInt = absl::conditional_t<sizeof(Int) == 4, uint64_t, uint128>;
+ BiggerInt tmp = 10 * static_cast<BiggerInt>(*v) + carry;
+ *v = static_cast<Int>(tmp);
+ return static_cast<Int>(tmp >> (sizeof(Int) * 8));
+}
+
+// Calculates `(2^64 * carry + *v) / 10`.
+// Stores the quotient in `*v` and returns the remainder.
+// Requires: `0 <= carry <= 9`
+inline uint64_t DivideBy10WithCarry(uint64_t *v, uint64_t carry) {
+ constexpr uint64_t divisor = 10;
+ // 2^64 / divisor = chunk_quotient + chunk_remainder / divisor
+ constexpr uint64_t chunk_quotient = (uint64_t{1} << 63) / (divisor / 2);
+ constexpr uint64_t chunk_remainder = uint64_t{} - chunk_quotient * divisor;
+
+ const uint64_t mod = *v % divisor;
+ const uint64_t next_carry = chunk_remainder * carry + mod;
+ *v = *v / divisor + carry * chunk_quotient + next_carry / divisor;
+ return next_carry % divisor;
+}
+
+using MaxFloatType =
+ typename std::conditional<IsDoubleDouble(), double, long double>::type;
+
+// Generates the decimal representation for an integer of the form `v * 2^exp`,
+// where `v` and `exp` are both positive integers.
+// It generates the digits from the left (ie the most significant digit first)
+// to allow for direct printing into the sink.
+//
+// Requires `0 <= exp` and `exp <= numeric_limits<MaxFloatType>::max_exponent`.
+class BinaryToDecimal {
+ static constexpr int ChunksNeeded(int exp) {
+ // We will left shift a uint128 by `exp` bits, so we need `128+exp` total
+ // bits. Round up to 32.
+ // See constructor for details about adding `10%` to the value.
+ return (128 + exp + 31) / 32 * 11 / 10;
+ }
+
+ public:
+ // Run the conversion for `v * 2^exp` and call `f(binary_to_decimal)`.
+ // This function will allocate enough stack space to perform the conversion.
+ static void RunConversion(uint128 v, int exp,
+ absl::FunctionRef<void(BinaryToDecimal)> f) {
+ assert(exp > 0);
+ assert(exp <= std::numeric_limits<MaxFloatType>::max_exponent);
+ static_assert(
+ static_cast<int>(StackArray::kMaxCapacity) >=
+ ChunksNeeded(std::numeric_limits<MaxFloatType>::max_exponent),
+ "");
+
+ StackArray::RunWithCapacity(
+ ChunksNeeded(exp),
+ [=](absl::Span<uint32_t> input) { f(BinaryToDecimal(input, v, exp)); });
+ }
+
+ int TotalDigits() const {
+ return static_cast<int>((decimal_end_ - decimal_start_) * kDigitsPerChunk +
+ CurrentDigits().size());
+ }
+
+ // See the current block of digits.
+ absl::string_view CurrentDigits() const {
+ return absl::string_view(digits_ + kDigitsPerChunk - size_, size_);
+ }
+
+ // Advance the current view of digits.
+ // Returns `false` when no more digits are available.
+ bool AdvanceDigits() {
+ if (decimal_start_ >= decimal_end_) return false;
+
+ uint32_t w = data_[decimal_start_++];
+ for (size_ = 0; size_ < kDigitsPerChunk; w /= 10) {
+ digits_[kDigitsPerChunk - ++size_] = w % 10 + '0';
+ }
+ return true;
+ }
+
+ private:
+ BinaryToDecimal(absl::Span<uint32_t> data, uint128 v, int exp) : data_(data) {
+ // We need to print the digits directly into the sink object without
+ // buffering them all first. To do this we need two things:
+ // - to know the total number of digits to do padding when necessary
+ // - to generate the decimal digits from the left.
+ //
+ // In order to do this, we do a two pass conversion.
+ // On the first pass we convert the binary representation of the value into
+ // a decimal representation in which each uint32_t chunk holds up to 9
+ // decimal digits. In the second pass we take each decimal-holding-uint32_t
+ // value and generate the ascii decimal digits into `digits_`.
+ //
+ // The binary and decimal representations actually share the same memory
+ // region. As we go converting the chunks from binary to decimal we free
+ // them up and reuse them for the decimal representation. One caveat is that
+ // the decimal representation is around 7% less efficient in space than the
+ // binary one. We allocate an extra 10% memory to account for this. See
+ // ChunksNeeded for this calculation.
+ int chunk_index = exp / 32;
+ decimal_start_ = decimal_end_ = ChunksNeeded(exp);
+ const int offset = exp % 32;
+ // Left shift v by exp bits.
+ data_[chunk_index] = static_cast<uint32_t>(v << offset);
+ for (v >>= (32 - offset); v; v >>= 32)
+ data_[++chunk_index] = static_cast<uint32_t>(v);
+
+ while (chunk_index >= 0) {
+ // While we have more than one chunk available, go in steps of 1e9.
+ // `data_[chunk_index]` holds the highest non-zero binary chunk, so keep
+ // the variable updated.
+ uint32_t carry = 0;
+ for (int i = chunk_index; i >= 0; --i) {
+ uint64_t tmp = uint64_t{data_[i]} + (uint64_t{carry} << 32);
+ data_[i] = static_cast<uint32_t>(tmp / uint64_t{1000000000});
+ carry = static_cast<uint32_t>(tmp % uint64_t{1000000000});
+ }
+
+ // If the highest chunk is now empty, remove it from view.
+ if (data_[chunk_index] == 0) --chunk_index;
+
+ --decimal_start_;
+ assert(decimal_start_ != chunk_index);
+ data_[decimal_start_] = carry;
+ }
+
+ // Fill the first set of digits. The first chunk might not be complete, so
+ // handle differently.
+ for (uint32_t first = data_[decimal_start_++]; first != 0; first /= 10) {
+ digits_[kDigitsPerChunk - ++size_] = first % 10 + '0';
+ }
+ }
+
+ private:
+ static constexpr int kDigitsPerChunk = 9;
+
+ int decimal_start_;
+ int decimal_end_;
+
+ char digits_[kDigitsPerChunk];
+ int size_ = 0;
+
+ absl::Span<uint32_t> data_;
+};
+
+// Converts a value of the form `x * 2^-exp` into a sequence of decimal digits.
+// Requires `-exp < 0` and
+// `-exp >= limits<MaxFloatType>::min_exponent - limits<MaxFloatType>::digits`.
+class FractionalDigitGenerator {
+ public:
+ // Run the conversion for `v * 2^exp` and call `f(generator)`.
+ // This function will allocate enough stack space to perform the conversion.
+ static void RunConversion(
+ uint128 v, int exp, absl::FunctionRef<void(FractionalDigitGenerator)> f) {
+ using Limits = std::numeric_limits<MaxFloatType>;
+ assert(-exp < 0);
+ assert(-exp >= Limits::min_exponent - 128);
+ static_assert(StackArray::kMaxCapacity >=
+ (Limits::digits + 128 - Limits::min_exponent + 31) / 32,
+ "");
+ StackArray::RunWithCapacity((Limits::digits + exp + 31) / 32,
+ [=](absl::Span<uint32_t> input) {
+ f(FractionalDigitGenerator(input, v, exp));
+ });
+ }
+
+ // Returns true if there are any more non-zero digits left.
+ bool HasMoreDigits() const { return next_digit_ != 0 || chunk_index_ >= 0; }
+
+ // Returns true if the remainder digits are greater than 5000...
+ bool IsGreaterThanHalf() const {
+ return next_digit_ > 5 || (next_digit_ == 5 && chunk_index_ >= 0);
+ }
+ // Returns true if the remainder digits are exactly 5000...
+ bool IsExactlyHalf() const { return next_digit_ == 5 && chunk_index_ < 0; }
+
+ struct Digits {
+ int digit_before_nine;
+ int num_nines;
+ };
+
+ // Get the next set of digits.
+ // They are composed by a non-9 digit followed by a runs of zero or more 9s.
+ Digits GetDigits() {
+ Digits digits{next_digit_, 0};
+
+ next_digit_ = GetOneDigit();
+ while (next_digit_ == 9) {
+ ++digits.num_nines;
+ next_digit_ = GetOneDigit();
+ }
+
+ return digits;
+ }
+
+ private:
+ // Return the next digit.
+ int GetOneDigit() {
+ if (chunk_index_ < 0) return 0;
+
+ uint32_t carry = 0;
+ for (int i = chunk_index_; i >= 0; --i) {
+ carry = MultiplyBy10WithCarry(&data_[i], carry);
+ }
+ // If the lowest chunk is now empty, remove it from view.
+ if (data_[chunk_index_] == 0) --chunk_index_;
+ return carry;
+ }
+
+ FractionalDigitGenerator(absl::Span<uint32_t> data, uint128 v, int exp)
+ : chunk_index_(exp / 32), data_(data) {
+ const int offset = exp % 32;
+ // Right shift `v` by `exp` bits.
+ data_[chunk_index_] = static_cast<uint32_t>(v << (32 - offset));
+ v >>= offset;
+ // Make sure we don't overflow the data. We already calculated that
+ // non-zero bits fit, so we might not have space for leading zero bits.
+ for (int pos = chunk_index_; v; v >>= 32)
+ data_[--pos] = static_cast<uint32_t>(v);
+
+ // Fill next_digit_, as GetDigits expects it to be populated always.
+ next_digit_ = GetOneDigit();
+ }
+
+ int next_digit_;
+ int chunk_index_;
+ absl::Span<uint32_t> data_;
+};
+
+// Count the number of leading zero bits.
+int LeadingZeros(uint64_t v) { return countl_zero(v); }
+int LeadingZeros(uint128 v) {
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
+ return high != 0 ? countl_zero(high) : 64 + countl_zero(low);
+}
+
+// Round up the text digits starting at `p`.
+// The buffer must have an extra digit that is known to not need rounding.
+// This is done below by having an extra '0' digit on the left.
+void RoundUp(char *p) {
+ while (*p == '9' || *p == '.') {
+ if (*p == '9') *p = '0';
+ --p;
+ }
+ ++*p;
+}
+
+// Check the previous digit and round up or down to follow the round-to-even
+// policy.
+void RoundToEven(char *p) {
+ if (*p == '.') --p;
+ if (*p % 2 == 1) RoundUp(p);
+}
+
+// Simple integral decimal digit printing for values that fit in 64-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint64_t v, char *p) {
+ do {
+ *--p = DivideBy10WithCarry(&v, 0) + '0';
+ } while (v != 0);
+ return p;
+}
+
+// Simple integral decimal digit printing for values that fit in 128-bits.
+// Returns the pointer to the last written digit.
+char *PrintIntegralDigitsFromRightFast(uint128 v, char *p) {
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
+
+ while (high != 0) {
+ uint64_t carry = DivideBy10WithCarry(&high, 0);
+ carry = DivideBy10WithCarry(&low, carry);
+ *--p = carry + '0';
+ }
+ return PrintIntegralDigitsFromRightFast(low, p);
+}
+
+// Simple fractional decimal digit printing for values that fir in 64-bits after
+// shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint64_t v, char *start, int exp,
+ int precision) {
+ char *p = start;
+ v <<= (64 - exp);
+ while (precision > 0) {
+ if (!v) return p;
+ *p++ = MultiplyBy10WithCarry(&v, uint64_t{0}) + '0';
+ --precision;
+ }
+
+ // We need to round.
+ if (v < 0x8000000000000000) {
+ // We round down, so nothing to do.
+ } else if (v > 0x8000000000000000) {
+ // We round up.
+ RoundUp(p - 1);
+ } else {
+ RoundToEven(p - 1);
+ }
+
+ assert(precision == 0);
+ // Precision can only be zero here.
+ return p;
+}
+
+// Simple fractional decimal digit printing for values that fir in 128-bits
+// after shifting.
+// Performs rounding if necessary to fit within `precision`.
+// Returns the pointer to one after the last character written.
+char *PrintFractionalDigitsFast(uint128 v, char *start, int exp,
+ int precision) {
+ char *p = start;
+ v <<= (128 - exp);
+ auto high = static_cast<uint64_t>(v >> 64);
+ auto low = static_cast<uint64_t>(v);
+
+ // While we have digits to print and `low` is not empty, do the long
+ // multiplication.
+ while (precision > 0 && low != 0) {
+ uint64_t carry = MultiplyBy10WithCarry(&low, uint64_t{0});
+ carry = MultiplyBy10WithCarry(&high, carry);
+
+ *p++ = carry + '0';
+ --precision;
+ }
+
+ // Now `low` is empty, so use a faster approach for the rest of the digits.
+ // This block is pretty much the same as the main loop for the 64-bit case
+ // above.
+ while (precision > 0) {
+ if (!high) return p;
+ *p++ = MultiplyBy10WithCarry(&high, uint64_t{0}) + '0';
+ --precision;
+ }
+
+ // We need to round.
+ if (high < 0x8000000000000000) {
+ // We round down, so nothing to do.
+ } else if (high > 0x8000000000000000 || low != 0) {
+ // We round up.
+ RoundUp(p - 1);
+ } else {
+ RoundToEven(p - 1);
+ }
+
+ assert(precision == 0);
+ // Precision can only be zero here.
+ return p;
+}
+
+struct FormatState {
+ char sign_char;
+ int precision;
+ const FormatConversionSpecImpl &conv;
+ FormatSinkImpl *sink;
+
+ // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+ // digits. In non-alt mode, we strip it.
+ bool ShouldPrintDot() const { return precision != 0 || conv.has_alt_flag(); }
+};
+
+struct Padding {
+ int left_spaces;
+ int zeros;
+ int right_spaces;
+};
+
+Padding ExtraWidthToPadding(size_t total_size, const FormatState &state) {
+ if (state.conv.width() < 0 ||
+ static_cast<size_t>(state.conv.width()) <= total_size) {
+ return {0, 0, 0};
+ }
+ int missing_chars = state.conv.width() - total_size;
+ if (state.conv.has_left_flag()) {
+ return {0, 0, missing_chars};
+ } else if (state.conv.has_zero_flag()) {
+ return {0, missing_chars, 0};
+ } else {
+ return {missing_chars, 0, 0};
+ }
+}
+
+void FinalPrint(const FormatState &state, absl::string_view data,
+ int padding_offset, int trailing_zeros,
+ absl::string_view data_postfix) {
+ if (state.conv.width() < 0) {
+ // No width specified. Fast-path.
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(data);
+ state.sink->Append(trailing_zeros, '0');
+ state.sink->Append(data_postfix);
+ return;
+ }
+
+ auto padding = ExtraWidthToPadding((state.sign_char != '\0' ? 1 : 0) +
+ data.size() + data_postfix.size() +
+ static_cast<size_t>(trailing_zeros),
+ state);
+
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ // Padding in general needs to be inserted somewhere in the middle of `data`.
+ state.sink->Append(data.substr(0, padding_offset));
+ state.sink->Append(padding.zeros, '0');
+ state.sink->Append(data.substr(padding_offset));
+ state.sink->Append(trailing_zeros, '0');
+ state.sink->Append(data_postfix);
+ state.sink->Append(padding.right_spaces, ' ');
+}
+
+// Fastpath %f formatter for when the shifted value fits in a simple integral
+// type.
+// Prints `v*2^exp` with the options from `state`.
+template <typename Int>
+void FormatFFast(Int v, int exp, const FormatState &state) {
+ constexpr int input_bits = sizeof(Int) * 8;
+
+ static constexpr size_t integral_size =
+ /* in case we need to round up an extra digit */ 1 +
+ /* decimal digits for uint128 */ 40 + 1;
+ char buffer[integral_size + /* . */ 1 + /* max digits uint128 */ 128];
+ buffer[integral_size] = '.';
+ char *const integral_digits_end = buffer + integral_size;
+ char *integral_digits_start;
+ char *const fractional_digits_start = buffer + integral_size + 1;
+ char *fractional_digits_end = fractional_digits_start;
+
+ if (exp >= 0) {
+ const int total_bits = input_bits - LeadingZeros(v) + exp;
+ integral_digits_start =
+ total_bits <= 64
+ ? PrintIntegralDigitsFromRightFast(static_cast<uint64_t>(v) << exp,
+ integral_digits_end)
+ : PrintIntegralDigitsFromRightFast(static_cast<uint128>(v) << exp,
+ integral_digits_end);
+ } else {
+ exp = -exp;
+
+ integral_digits_start = PrintIntegralDigitsFromRightFast(
+ exp < input_bits ? v >> exp : 0, integral_digits_end);
+ // PrintFractionalDigits may pull a carried 1 all the way up through the
+ // integral portion.
+ integral_digits_start[-1] = '0';
+
+ fractional_digits_end =
+ exp <= 64 ? PrintFractionalDigitsFast(v, fractional_digits_start, exp,
+ state.precision)
+ : PrintFractionalDigitsFast(static_cast<uint128>(v),
+ fractional_digits_start, exp,
+ state.precision);
+ // There was a carry, so include the first digit too.
+ if (integral_digits_start[-1] != '0') --integral_digits_start;
+ }
+
+ size_t size = fractional_digits_end - integral_digits_start;
+
+ // In `alt` mode (flag #) we keep the `.` even if there are no fractional
+ // digits. In non-alt mode, we strip it.
+ if (!state.ShouldPrintDot()) --size;
+ FinalPrint(state, absl::string_view(integral_digits_start, size),
+ /*padding_offset=*/0,
+ static_cast<int>(state.precision - (fractional_digits_end -
+ fractional_digits_start)),
+ /*data_postfix=*/"");
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp > 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to not have fractional digits, so we don't have to
+// worry about anything after the `.`.
+void FormatFPositiveExpSlow(uint128 v, int exp, const FormatState &state) {
+ BinaryToDecimal::RunConversion(v, exp, [&](BinaryToDecimal btd) {
+ const size_t total_digits =
+ btd.TotalDigits() +
+ (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+
+ const auto padding = ExtraWidthToPadding(
+ total_digits + (state.sign_char != '\0' ? 1 : 0), state);
+
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(padding.zeros, '0');
+
+ do {
+ state.sink->Append(btd.CurrentDigits());
+ } while (btd.AdvanceDigits());
+
+ if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+ state.sink->Append(state.precision, '0');
+ state.sink->Append(padding.right_spaces, ' ');
+ });
+}
+
+// Slow %f formatter for when the shifted value does not fit in a uint128, and
+// `exp < 0`.
+// Prints `v*2^exp` with the options from `state`.
+// This one is guaranteed to be < 1.0, so we don't have to worry about integral
+// digits.
+void FormatFNegativeExpSlow(uint128 v, int exp, const FormatState &state) {
+ const size_t total_digits =
+ /* 0 */ 1 +
+ (state.ShouldPrintDot() ? static_cast<size_t>(state.precision) + 1 : 0);
+ auto padding =
+ ExtraWidthToPadding(total_digits + (state.sign_char ? 1 : 0), state);
+ padding.zeros += 1;
+ state.sink->Append(padding.left_spaces, ' ');
+ if (state.sign_char != '\0') state.sink->Append(1, state.sign_char);
+ state.sink->Append(padding.zeros, '0');
+
+ if (state.ShouldPrintDot()) state.sink->Append(1, '.');
+
+ // Print digits
+ int digits_to_go = state.precision;
+
+ FractionalDigitGenerator::RunConversion(
+ v, exp, [&](FractionalDigitGenerator digit_gen) {
+ // There are no digits to print here.
+ if (state.precision == 0) return;
+
+ // We go one digit at a time, while keeping track of runs of nines.
+ // The runs of nines are used to perform rounding when necessary.
+
+ while (digits_to_go > 0 && digit_gen.HasMoreDigits()) {
+ auto digits = digit_gen.GetDigits();
+
+ // Now we have a digit and a run of nines.
+ // See if we can print them all.
+ if (digits.num_nines + 1 < digits_to_go) {
+ // We don't have to round yet, so print them.
+ state.sink->Append(1, digits.digit_before_nine + '0');
+ state.sink->Append(digits.num_nines, '9');
+ digits_to_go -= digits.num_nines + 1;
+
+ } else {
+ // We can't print all the nines, see where we have to truncate.
+
+ bool round_up = false;
+ if (digits.num_nines + 1 > digits_to_go) {
+ // We round up at a nine. No need to print them.
+ round_up = true;
+ } else {
+ // We can fit all the nines, but truncate just after it.
+ if (digit_gen.IsGreaterThanHalf()) {
+ round_up = true;
+ } else if (digit_gen.IsExactlyHalf()) {
+ // Round to even
+ round_up =
+ digits.num_nines != 0 || digits.digit_before_nine % 2 == 1;
+ }
+ }
+
+ if (round_up) {
+ state.sink->Append(1, digits.digit_before_nine + '1');
+ --digits_to_go;
+ // The rest will be zeros.
+ } else {
+ state.sink->Append(1, digits.digit_before_nine + '0');
+ state.sink->Append(digits_to_go - 1, '9');
+ digits_to_go = 0;
+ }
+ return;
+ }
+ }
+ });
+
+ state.sink->Append(digits_to_go, '0');
+ state.sink->Append(padding.right_spaces, ' ');
+}
+
+template <typename Int>
+void FormatF(Int mantissa, int exp, const FormatState &state) {
+ if (exp >= 0) {
+ const int total_bits = sizeof(Int) * 8 - LeadingZeros(mantissa) + exp;
+
+ // Fallback to the slow stack-based approach if we can't do it in a 64 or
+ // 128 bit state.
+ if (ABSL_PREDICT_FALSE(total_bits > 128)) {
+ return FormatFPositiveExpSlow(mantissa, exp, state);
+ }
+ } else {
+ // Fallback to the slow stack-based approach if we can't do it in a 64 or
+ // 128 bit state.
+ if (ABSL_PREDICT_FALSE(exp < -128)) {
+ return FormatFNegativeExpSlow(mantissa, -exp, state);
+ }
+ }
+ return FormatFFast(mantissa, exp, state);
+}
+
+// Grab the group of four bits (nibble) from `n`. E.g., nibble 1 corresponds to
+// bits 4-7.
+template <typename Int>
+uint8_t GetNibble(Int n, int nibble_index) {
+ constexpr Int mask_low_nibble = Int{0xf};
+ int shift = nibble_index * 4;
+ n &= mask_low_nibble << shift;
+ return static_cast<uint8_t>((n >> shift) & 0xf);
+}
+
+// Add one to the given nibble, applying carry to higher nibbles. Returns true
+// if overflow, false otherwise.
+template <typename Int>
+bool IncrementNibble(int nibble_index, Int *n) {
+ constexpr int kShift = sizeof(Int) * 8 - 1;
+ constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+ Int before = *n >> kShift;
+ // Here we essentially want to take the number 1 and move it into the requsted
+ // nibble, then add it to *n to effectively increment the nibble. However,
+ // ASan will complain if we try to shift the 1 beyond the limits of the Int,
+ // i.e., if the nibble_index is out of range. So therefore we check for this
+ // and if we are out of range we just add 0 which leaves *n unchanged, which
+ // seems like the reasonable thing to do in that case.
+ *n += ((nibble_index >= kNumNibbles) ? 0 : (Int{1} << (nibble_index * 4)));
+ Int after = *n >> kShift;
+ return (before && !after) || (nibble_index >= kNumNibbles);
+}
+
+// Return a mask with 1's in the given nibble and all lower nibbles.
+template <typename Int>
+Int MaskUpToNibbleInclusive(int nibble_index) {
+ constexpr int kNumNibbles = sizeof(Int) * 8 / 4;
+ static const Int ones = ~Int{0};
+ return ones >> std::max(0, 4 * (kNumNibbles - nibble_index - 1));
+}
+
+// Return a mask with 1's below the given nibble.
+template <typename Int>
+Int MaskUpToNibbleExclusive(int nibble_index) {
+ return nibble_index <= 0 ? 0 : MaskUpToNibbleInclusive<Int>(nibble_index - 1);
+}
+
+template <typename Int>
+Int MoveToNibble(uint8_t nibble, int nibble_index) {
+ return Int{nibble} << (4 * nibble_index);
+}
+
+// Given mantissa size, find optimal # of mantissa bits to put in initial digit.
+//
+// In the hex representation we keep a single hex digit to the left of the dot.
+// However, the question as to how many bits of the mantissa should be put into
+// that hex digit in theory is arbitrary, but in practice it is optimal to
+// choose based on the size of the mantissa. E.g., for a `double`, there are 53
+// mantissa bits, so that means that we should put 1 bit to the left of the dot,
+// thereby leaving 52 bits to the right, which is evenly divisible by four and
+// thus all fractional digits represent actual precision. For a `long double`,
+// on the other hand, there are 64 bits of mantissa, thus we can use all four
+// bits for the initial hex digit and still have a number left over (60) that is
+// a multiple of four. Once again, the goal is to have all fractional digits
+// represent real precision.
+template <typename Float>
+constexpr int HexFloatLeadingDigitSizeInBits() {
+ return std::numeric_limits<Float>::digits % 4 > 0
+ ? std::numeric_limits<Float>::digits % 4
+ : 4;
+}
+
+// This function captures the rounding behavior of glibc for hex float
+// representations. E.g. when rounding 0x1.ab800000 to a precision of .2
+// ("%.2a") glibc will round up because it rounds toward the even number (since
+// 0xb is an odd number, it will round up to 0xc). However, when rounding at a
+// point that is not followed by 800000..., it disregards the parity and rounds
+// up if > 8 and rounds down if < 8.
+template <typename Int>
+bool HexFloatNeedsRoundUp(Int mantissa, int final_nibble_displayed,
+ uint8_t leading) {
+ // If the last nibble (hex digit) to be displayed is the lowest on in the
+ // mantissa then that means that we don't have any further nibbles to inform
+ // rounding, so don't round.
+ if (final_nibble_displayed <= 0) {
+ return false;
+ }
+ int rounding_nibble_idx = final_nibble_displayed - 1;
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ assert(final_nibble_displayed <= kTotalNibbles);
+ Int mantissa_up_to_rounding_nibble_inclusive =
+ mantissa & MaskUpToNibbleInclusive<Int>(rounding_nibble_idx);
+ Int eight = MoveToNibble<Int>(8, rounding_nibble_idx);
+ if (mantissa_up_to_rounding_nibble_inclusive != eight) {
+ return mantissa_up_to_rounding_nibble_inclusive > eight;
+ }
+ // Nibble in question == 8.
+ uint8_t round_if_odd = (final_nibble_displayed == kTotalNibbles)
+ ? leading
+ : GetNibble(mantissa, final_nibble_displayed);
+ return round_if_odd % 2 == 1;
+}
+
+// Stores values associated with a Float type needed by the FormatA
+// implementation in order to avoid templatizing that function by the Float
+// type.
+struct HexFloatTypeParams {
+ template <typename Float>
+ explicit HexFloatTypeParams(Float)
+ : min_exponent(std::numeric_limits<Float>::min_exponent - 1),
+ leading_digit_size_bits(HexFloatLeadingDigitSizeInBits<Float>()) {
+ assert(leading_digit_size_bits >= 1 && leading_digit_size_bits <= 4);
+ }
+
+ int min_exponent;
+ int leading_digit_size_bits;
+};
+
+// Hex Float Rounding. First check if we need to round; if so, then we do that
+// by manipulating (incrementing) the mantissa, that way we can later print the
+// mantissa digits by iterating through them in the same way regardless of
+// whether a rounding happened.
+template <typename Int>
+void FormatARound(bool precision_specified, const FormatState &state,
+ uint8_t *leading, Int *mantissa, int *exp) {
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ // Index of the last nibble that we could display given precision.
+ int final_nibble_displayed =
+ precision_specified ? std::max(0, (kTotalNibbles - state.precision)) : 0;
+ if (HexFloatNeedsRoundUp(*mantissa, final_nibble_displayed, *leading)) {
+ // Need to round up.
+ bool overflow = IncrementNibble(final_nibble_displayed, mantissa);
+ *leading += (overflow ? 1 : 0);
+ if (ABSL_PREDICT_FALSE(*leading > 15)) {
+ // We have overflowed the leading digit. This would mean that we would
+ // need two hex digits to the left of the dot, which is not allowed. So
+ // adjust the mantissa and exponent so that the result is always 1.0eXXX.
+ *leading = 1;
+ *mantissa = 0;
+ *exp += 4;
+ }
+ }
+ // Now that we have handled a possible round-up we can go ahead and zero out
+ // all the nibbles of the mantissa that we won't need.
+ if (precision_specified) {
+ *mantissa &= ~MaskUpToNibbleExclusive<Int>(final_nibble_displayed);
+ }
+}
+
+template <typename Int>
+void FormatANormalize(const HexFloatTypeParams float_traits, uint8_t *leading,
+ Int *mantissa, int *exp) {
+ constexpr int kIntBits = sizeof(Int) * 8;
+ static const Int kHighIntBit = Int{1} << (kIntBits - 1);
+ const int kLeadDigitBitsCount = float_traits.leading_digit_size_bits;
+ // Normalize mantissa so that highest bit set is in MSB position, unless we
+ // get interrupted by the exponent threshold.
+ while (*mantissa && !(*mantissa & kHighIntBit)) {
+ if (ABSL_PREDICT_FALSE(*exp - 1 < float_traits.min_exponent)) {
+ *mantissa >>= (float_traits.min_exponent - *exp);
+ *exp = float_traits.min_exponent;
+ return;
+ }
+ *mantissa <<= 1;
+ --*exp;
+ }
+ // Extract bits for leading digit then shift them away leaving the
+ // fractional part.
+ *leading =
+ static_cast<uint8_t>(*mantissa >> (kIntBits - kLeadDigitBitsCount));
+ *exp -= (*mantissa != 0) ? kLeadDigitBitsCount : *exp;
+ *mantissa <<= kLeadDigitBitsCount;
+}
+
+template <typename Int>
+void FormatA(const HexFloatTypeParams float_traits, Int mantissa, int exp,
+ bool uppercase, const FormatState &state) {
+ // Int properties.
+ constexpr int kIntBits = sizeof(Int) * 8;
+ constexpr int kTotalNibbles = sizeof(Int) * 8 / 4;
+ // Did the user specify a precision explicitly?
+ const bool precision_specified = state.conv.precision() >= 0;
+
+ // ========== Normalize/Denormalize ==========
+ exp += kIntBits; // make all digits fractional digits.
+ // This holds the (up to four) bits of leading digit, i.e., the '1' in the
+ // number 0x1.e6fp+2. It's always > 0 unless number is zero or denormal.
+ uint8_t leading = 0;
+ FormatANormalize(float_traits, &leading, &mantissa, &exp);
+
+ // =============== Rounding ==================
+ // Check if we need to round; if so, then we do that by manipulating
+ // (incrementing) the mantissa before beginning to print characters.
+ FormatARound(precision_specified, state, &leading, &mantissa, &exp);
+
+ // ============= Format Result ===============
+ // This buffer holds the "0x1.ab1de3" portion of "0x1.ab1de3pe+2". Compute the
+ // size with long double which is the largest of the floats.
+ constexpr size_t kBufSizeForHexFloatRepr =
+ 2 // 0x
+ + std::numeric_limits<MaxFloatType>::digits / 4 // number of hex digits
+ + 1 // round up
+ + 1; // "." (dot)
+ char digits_buffer[kBufSizeForHexFloatRepr];
+ char *digits_iter = digits_buffer;
+ const char *const digits =
+ static_cast<const char *>("0123456789ABCDEF0123456789abcdef") +
+ (uppercase ? 0 : 16);
+
+ // =============== Hex Prefix ================
+ *digits_iter++ = '0';
+ *digits_iter++ = uppercase ? 'X' : 'x';
+
+ // ========== Non-Fractional Digit ===========
+ *digits_iter++ = digits[leading];
+
+ // ================== Dot ====================
+ // There are three reasons we might need a dot. Keep in mind that, at this
+ // point, the mantissa holds only the fractional part.
+ if ((precision_specified && state.precision > 0) ||
+ (!precision_specified && mantissa > 0) || state.conv.has_alt_flag()) {
+ *digits_iter++ = '.';
+ }
+
+ // ============ Fractional Digits ============
+ int digits_emitted = 0;
+ while (mantissa > 0) {
+ *digits_iter++ = digits[GetNibble(mantissa, kTotalNibbles - 1)];
+ mantissa <<= 4;
+ ++digits_emitted;
+ }
+ int trailing_zeros =
+ precision_specified ? state.precision - digits_emitted : 0;
+ assert(trailing_zeros >= 0);
+ auto digits_result = string_view(digits_buffer, digits_iter - digits_buffer);
+
+ // =============== Exponent ==================
+ constexpr size_t kBufSizeForExpDecRepr =
+ numbers_internal::kFastToBufferSize // requred for FastIntToBuffer
+ + 1 // 'p' or 'P'
+ + 1; // '+' or '-'
+ char exp_buffer[kBufSizeForExpDecRepr];
+ exp_buffer[0] = uppercase ? 'P' : 'p';
+ exp_buffer[1] = exp >= 0 ? '+' : '-';
+ numbers_internal::FastIntToBuffer(exp < 0 ? -exp : exp, exp_buffer + 2);
+
+ // ============ Assemble Result ==============
+ FinalPrint(state, //
+ digits_result, // 0xN.NNN...
+ 2, // offset in `data` to start padding if needed.
+ trailing_zeros, // num remaining mantissa padding zeros
+ exp_buffer); // exponent
+}
+
+char *CopyStringTo(absl::string_view v, char *out) {
std::memcpy(out, v.data(), v.size());
return out + v.size();
}
template <typename Float>
-bool FallbackToSnprintf(const Float v, const ConversionSpec &conv,
+bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
int w = conv.width() >= 0 ? conv.width() : 0;
int p = conv.precision() >= 0 ? conv.precision() : -1;
@@ -25,22 +946,22 @@ bool FallbackToSnprintf(const Float v, const ConversionSpec &conv,
{
char *fp = fmt;
*fp++ = '%';
- fp = CopyStringTo(conv.flags().ToString(), fp);
+ fp = CopyStringTo(FormatConversionSpecImplFriend::FlagsToString(conv), fp);
fp = CopyStringTo("*.*", fp);
if (std::is_same<long double, Float>()) {
*fp++ = 'L';
}
- *fp++ = conv.conv().Char();
+ *fp++ = FormatConversionCharToChar(conv.conversion_char());
*fp = 0;
assert(fp < fmt + sizeof(fmt));
}
std::string space(512, '\0');
- string_view result;
+ absl::string_view result;
while (true) {
int n = snprintf(&space[0], space.size(), fmt, w, p, v);
if (n < 0) return false;
if (static_cast<size_t>(n) < space.size()) {
- result = string_view(space.data(), n);
+ result = absl::string_view(space.data(), n);
break;
}
space.resize(n + 1);
@@ -93,19 +1014,24 @@ enum class FormatStyle { Fixed, Precision };
// Otherwise, return false.
template <typename Float>
bool ConvertNonNumericFloats(char sign_char, Float v,
- const ConversionSpec &conv, FormatSinkImpl *sink) {
+ const FormatConversionSpecImpl &conv,
+ FormatSinkImpl *sink) {
char text[4], *ptr = text;
- if (sign_char) *ptr++ = sign_char;
+ if (sign_char != '\0') *ptr++ = sign_char;
if (std::isnan(v)) {
- ptr = std::copy_n(conv.conv().upper() ? "NAN" : "nan", 3, ptr);
+ ptr = std::copy_n(
+ FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
+ ptr);
} else if (std::isinf(v)) {
- ptr = std::copy_n(conv.conv().upper() ? "INF" : "inf", 3, ptr);
+ ptr = std::copy_n(
+ FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
+ ptr);
} else {
return false;
}
return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
- conv.flags().left);
+ conv.has_left_flag());
}
// Round up the last digit of the value.
@@ -165,7 +1091,12 @@ constexpr bool CanFitMantissa() {
template <typename Float>
struct Decomposed {
- Float mantissa;
+ using MantissaType =
+ absl::conditional_t<std::is_same<long double, Float>::value, uint128,
+ uint64_t>;
+ static_assert(std::numeric_limits<Float>::digits <= sizeof(MantissaType) * 8,
+ "");
+ MantissaType mantissa;
int exponent;
};
@@ -176,7 +1107,8 @@ Decomposed<Float> Decompose(Float v) {
Float m = std::frexp(v, &exp);
m = std::ldexp(m, std::numeric_limits<Float>::digits);
exp -= std::numeric_limits<Float>::digits;
- return {m, exp};
+
+ return {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
}
// Print 'digits' as decimal.
@@ -334,7 +1266,7 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
static_cast<std::uint64_t>(decomposed.exponent), precision, out, exp))
return true;
-#if defined(__SIZEOF_INT128__)
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
// If that is not enough, try with __uint128_t.
return CanFitMantissa<Float, __uint128_t>() &&
FloatToBufferImpl<__uint128_t, Float, mode>(
@@ -345,31 +1277,32 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
return false;
}
-void WriteBufferToSink(char sign_char, string_view str,
- const ConversionSpec &conv, FormatSinkImpl *sink) {
+void WriteBufferToSink(char sign_char, absl::string_view str,
+ const FormatConversionSpecImpl &conv,
+ FormatSinkImpl *sink) {
int left_spaces = 0, zeros = 0, right_spaces = 0;
int missing_chars =
conv.width() >= 0 ? std::max(conv.width() - static_cast<int>(str.size()) -
static_cast<int>(sign_char != 0),
0)
: 0;
- if (conv.flags().left) {
+ if (conv.has_left_flag()) {
right_spaces = missing_chars;
- } else if (conv.flags().zero) {
+ } else if (conv.has_zero_flag()) {
zeros = missing_chars;
} else {
left_spaces = missing_chars;
}
sink->Append(left_spaces, ' ');
- if (sign_char) sink->Append(1, sign_char);
+ if (sign_char != '\0') sink->Append(1, sign_char);
sink->Append(zeros, '0');
sink->Append(str);
sink->Append(right_spaces, ' ');
}
template <typename Float>
-bool FloatToSink(const Float v, const ConversionSpec &conv,
+bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
// Print the sign or the sign column.
Float abs_v = v;
@@ -377,9 +1310,9 @@ bool FloatToSink(const Float v, const ConversionSpec &conv,
if (std::signbit(abs_v)) {
sign_char = '-';
abs_v = -abs_v;
- } else if (conv.flags().show_pos) {
+ } else if (conv.has_show_pos_flag()) {
sign_char = '+';
- } else if (conv.flags().sign_col) {
+ } else if (conv.has_sign_col_flag()) {
sign_char = ' ';
}
@@ -396,88 +1329,95 @@ bool FloatToSink(const Float v, const ConversionSpec &conv,
Buffer buffer;
- switch (conv.conv().id()) {
- case ConversionChar::f:
- case ConversionChar::F:
- if (!FloatToBuffer<FormatStyle::Fixed>(decomposed, precision, &buffer,
- nullptr)) {
- return FallbackToSnprintf(v, conv, sink);
- }
- if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back();
- break;
-
- case ConversionChar::e:
- case ConversionChar::E:
- if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
- &exp)) {
- return FallbackToSnprintf(v, conv, sink);
- }
- if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back();
- PrintExponent(exp, conv.conv().upper() ? 'E' : 'e', &buffer);
- break;
-
- case ConversionChar::g:
- case ConversionChar::G:
- precision = std::max(0, precision - 1);
- if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
- &exp)) {
- return FallbackToSnprintf(v, conv, sink);
- }
- if (precision + 1 > exp && exp >= -4) {
- if (exp < 0) {
- // Have 1.23456, needs 0.00123456
- // Move the first digit
- buffer.begin[1] = *buffer.begin;
- // Add some zeros
- for (; exp < -1; ++exp) *buffer.begin-- = '0';
- *buffer.begin-- = '.';
- *buffer.begin = '0';
- } else if (exp > 0) {
- // Have 1.23456, needs 1234.56
- // Move the '.' exp positions to the right.
- std::rotate(buffer.begin + 1, buffer.begin + 2,
- buffer.begin + exp + 2);
- }
- exp = 0;
- }
- if (!conv.flags().alt) {
- while (buffer.back() == '0') buffer.pop_back();
- if (buffer.back() == '.') buffer.pop_back();
- }
- if (exp) PrintExponent(exp, conv.conv().upper() ? 'E' : 'e', &buffer);
- break;
+ FormatConversionChar c = conv.conversion_char();
- case ConversionChar::a:
- case ConversionChar::A:
+ if (c == FormatConversionCharInternal::f ||
+ c == FormatConversionCharInternal::F) {
+ FormatF(decomposed.mantissa, decomposed.exponent,
+ {sign_char, precision, conv, sink});
+ return true;
+ } else if (c == FormatConversionCharInternal::e ||
+ c == FormatConversionCharInternal::E) {
+ if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+ &exp)) {
return FallbackToSnprintf(v, conv, sink);
-
- default:
- return false;
+ }
+ if (!conv.has_alt_flag() && buffer.back() == '.') buffer.pop_back();
+ PrintExponent(
+ exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+ &buffer);
+ } else if (c == FormatConversionCharInternal::g ||
+ c == FormatConversionCharInternal::G) {
+ precision = std::max(0, precision - 1);
+ if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+ &exp)) {
+ return FallbackToSnprintf(v, conv, sink);
+ }
+ if (precision + 1 > exp && exp >= -4) {
+ if (exp < 0) {
+ // Have 1.23456, needs 0.00123456
+ // Move the first digit
+ buffer.begin[1] = *buffer.begin;
+ // Add some zeros
+ for (; exp < -1; ++exp) *buffer.begin-- = '0';
+ *buffer.begin-- = '.';
+ *buffer.begin = '0';
+ } else if (exp > 0) {
+ // Have 1.23456, needs 1234.56
+ // Move the '.' exp positions to the right.
+ std::rotate(buffer.begin + 1, buffer.begin + 2, buffer.begin + exp + 2);
+ }
+ exp = 0;
+ }
+ if (!conv.has_alt_flag()) {
+ while (buffer.back() == '0') buffer.pop_back();
+ if (buffer.back() == '.') buffer.pop_back();
+ }
+ if (exp) {
+ PrintExponent(
+ exp, FormatConversionCharIsUpper(conv.conversion_char()) ? 'E' : 'e',
+ &buffer);
+ }
+ } else if (c == FormatConversionCharInternal::a ||
+ c == FormatConversionCharInternal::A) {
+ bool uppercase = (c == FormatConversionCharInternal::A);
+ FormatA(HexFloatTypeParams(Float{}), decomposed.mantissa,
+ decomposed.exponent, uppercase, {sign_char, precision, conv, sink});
+ return true;
+ } else {
+ return false;
}
WriteBufferToSink(sign_char,
- string_view(buffer.begin, buffer.end - buffer.begin), conv,
- sink);
+ absl::string_view(buffer.begin, buffer.end - buffer.begin),
+ conv, sink);
return true;
}
} // namespace
-bool ConvertFloatImpl(long double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
+ if (IsDoubleDouble()) {
+ // This is the `double-double` representation of `long double`. We do not
+ // handle it natively. Fallback to snprintf.
+ return FallbackToSnprintf(v, conv, sink);
+ }
+
return FloatToSink(v, conv, sink);
}
-bool ConvertFloatImpl(float v, const ConversionSpec &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
- return FloatToSink(v, conv, sink);
+ return FloatToSink(static_cast<double>(v), conv, sink);
}
-bool ConvertFloatImpl(double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink) {
return FloatToSink(v, conv, sink);
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
index 8ba5566d3ee..71100e71425 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
@@ -1,21 +1,37 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-bool ConvertFloatImpl(float v, const ConversionSpec &conv,
+bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(long double v, const ConversionSpec &conv,
+bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
FormatSinkImpl *sink);
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_FLOAT_CONVERSION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.cc
index d7fef69b4cf..c4b24706132 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#include <cstring>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
@@ -67,4 +68,5 @@ void FILERawSink::Write(string_view v) {
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.h
index 12ecd99e680..8030dae00f4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,9 +28,8 @@
#include "absl/base/port.h"
#include "absl/strings/string_view.h"
-class Cord;
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
// RawSink implementation that writes into a char* buffer.
@@ -75,12 +74,6 @@ inline void AbslFormatFlush(std::ostream* out, string_view s) {
out->write(s.data(), s.size());
}
-template <class AbslCord, typename = typename std::enable_if<
- std::is_same<AbslCord, ::Cord>::value>::type>
-inline void AbslFormatFlush(AbslCord* out, string_view s) {
- out->Append(s);
-}
-
inline void AbslFormatFlush(FILERawSink* sink, string_view v) {
sink->Write(v);
}
@@ -89,13 +82,15 @@ inline void AbslFormatFlush(BufferRawSink* sink, string_view v) {
sink->Write(v);
}
+// This is a SFINAE to get a better compiler error message when the type
+// is not supported.
template <typename T>
-auto InvokeFlush(T* out, string_view s)
- -> decltype(str_format_internal::AbslFormatFlush(out, s)) {
- str_format_internal::AbslFormatFlush(out, s);
+auto InvokeFlush(T* out, string_view s) -> decltype(AbslFormatFlush(out, s)) {
+ AbslFormatFlush(out, s);
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_OUTPUT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output_test.cc
index cc3c615557f..ce2e91a0bbe 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/output_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,23 +17,18 @@
#include <sstream>
#include <string>
-
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/strings/cord.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
TEST(InvokeFlush, String) {
std::string str = "ABC";
str_format_internal::InvokeFlush(&str, "DEF");
EXPECT_EQ(str, "ABCDEF");
-
-#if UTIL_FORMAT_HAS_GLOBAL_STRING
- std::string str2 = "ABC";
- str_format_internal::InvokeFlush(&str2, "DEF");
- EXPECT_EQ(str2, "ABCDEF");
-#endif // UTIL_FORMAT_HAS_GLOBAL_STRING
}
TEST(InvokeFlush, Stream) {
@@ -43,6 +38,12 @@ TEST(InvokeFlush, Stream) {
EXPECT_EQ(str.str(), "ABCDEF");
}
+TEST(InvokeFlush, Cord) {
+ absl::Cord str("ABC");
+ str_format_internal::InvokeFlush(&str, "DEF");
+ EXPECT_EQ(str, "ABCDEF");
+}
+
TEST(BufferRawSink, Limits) {
char buf[16];
{
@@ -74,5 +75,5 @@ TEST(BufferRawSink, Limits) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
-
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.cc
index 5e3d0d0547d..f308d023512 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.cc
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/parser.h"
#include <assert.h>
@@ -14,7 +28,47 @@
#include <unordered_set>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
+
+using CC = FormatConversionCharInternal;
+using LM = LengthMod;
+
+ABSL_CONST_INIT const ConvTag kTags[256] = {
+ {}, {}, {}, {}, {}, {}, {}, {}, // 00-07
+ {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 10-17
+ {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 20-27
+ {}, {}, {}, {}, {}, {}, {}, {}, // 28-2f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 30-37
+ {}, {}, {}, {}, {}, {}, {}, {}, // 38-3f
+ {}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG
+ {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
+ {}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW
+ CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
+ {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
+ LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
+ CC::p, LM::q, {}, CC::s, LM::t, CC::u, {}, {}, // pqrstuvw
+ CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
+ {}, {}, {}, {}, {}, {}, {}, {}, // 80-87
+ {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 90-97
+ {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
+ {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
+ {}, {}, {}, {}, {}, {}, {}, {}, // a8-af
+ {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
+ {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
+ {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
+ {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
+ {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
+ {}, {}, {}, {}, {}, {}, {}, {}, // d8-df
+ {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
+ {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
+ {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
+ {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
+};
+
namespace {
bool CheckFastPathSetting(const UnboundConversion& conv) {
@@ -36,60 +90,17 @@ bool CheckFastPathSetting(const UnboundConversion& conv) {
return should_be_basic == conv.flags.basic;
}
-// Keep a single table for all the conversion chars and length modifiers.
-// We invert the length modifiers to make them negative so that we can easily
-// test for them.
-// Everything else is `none`, which is a negative constant.
-using CC = ConversionChar::Id;
-using LM = LengthMod::Id;
-static constexpr std::int8_t none = -128;
-static constexpr std::int8_t kIds[] = {
- none, none, none, none, none, none, none, none, // 00-07
- none, none, none, none, none, none, none, none, // 08-0f
- none, none, none, none, none, none, none, none, // 10-17
- none, none, none, none, none, none, none, none, // 18-1f
- none, none, none, none, none, none, none, none, // 20-27
- none, none, none, none, none, none, none, none, // 28-2f
- none, none, none, none, none, none, none, none, // 30-37
- none, none, none, none, none, none, none, none, // 38-3f
- none, CC::A, none, CC::C, none, CC::E, CC::F, CC::G, // @ABCDEFG
- none, none, none, none, ~LM::L, none, none, none, // HIJKLMNO
- none, none, none, CC::S, none, none, none, none, // PQRSTUVW
- CC::X, none, none, none, none, none, none, none, // XYZ[\]^_
- none, CC::a, none, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
- ~LM::h, CC::i, ~LM::j, none, ~LM::l, none, CC::n, CC::o, // hijklmno
- CC::p, ~LM::q, none, CC::s, ~LM::t, CC::u, none, none, // pqrstuvw
- CC::x, none, ~LM::z, none, none, none, none, none, // xyz{|}~!
- none, none, none, none, none, none, none, none, // 80-87
- none, none, none, none, none, none, none, none, // 88-8f
- none, none, none, none, none, none, none, none, // 90-97
- none, none, none, none, none, none, none, none, // 98-9f
- none, none, none, none, none, none, none, none, // a0-a7
- none, none, none, none, none, none, none, none, // a8-af
- none, none, none, none, none, none, none, none, // b0-b7
- none, none, none, none, none, none, none, none, // b8-bf
- none, none, none, none, none, none, none, none, // c0-c7
- none, none, none, none, none, none, none, none, // c8-cf
- none, none, none, none, none, none, none, none, // d0-d7
- none, none, none, none, none, none, none, none, // d8-df
- none, none, none, none, none, none, none, none, // e0-e7
- none, none, none, none, none, none, none, none, // e8-ef
- none, none, none, none, none, none, none, none, // f0-f7
- none, none, none, none, none, none, none, none, // f8-ff
-};
-
template <bool is_positional>
-bool ConsumeConversion(string_view *src, UnboundConversion *conv,
- int *next_arg) {
- const char *pos = src->data();
- const char *const end = pos + src->size();
+const char *ConsumeConversion(const char *pos, const char *const end,
+ UnboundConversion *conv, int *next_arg) {
+ const char* const original_pos = pos;
char c;
// Read the next char into `c` and update `pos`. Returns false if there are
// no more chars to read.
-#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
- do { \
- if (ABSL_PREDICT_FALSE(pos == end)) return false; \
- c = *pos++; \
+#define ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR() \
+ do { \
+ if (ABSL_PREDICT_FALSE(pos == end)) return nullptr; \
+ c = *pos++; \
} while (0)
const auto parse_digits = [&] {
@@ -99,10 +110,11 @@ bool ConsumeConversion(string_view *src, UnboundConversion *conv,
// digit doesn't match the expected characters.
int num_digits = std::numeric_limits<int>::digits10;
for (;;) {
- if (ABSL_PREDICT_FALSE(pos == end || !num_digits)) break;
+ if (ABSL_PREDICT_FALSE(pos == end)) break;
c = *pos++;
if (!std::isdigit(c)) break;
--num_digits;
+ if (ABSL_PREDICT_FALSE(!num_digits)) break;
digits = 10 * digits + c - '0';
}
return digits;
@@ -110,10 +122,10 @@ bool ConsumeConversion(string_view *src, UnboundConversion *conv,
if (is_positional) {
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return false;
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->arg_position = parse_digits();
assert(conv->arg_position > 0);
- if (ABSL_PREDICT_FALSE(c != '$')) return false;
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
}
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
@@ -128,10 +140,9 @@ bool ConsumeConversion(string_view *src, UnboundConversion *conv,
conv->flags.basic = false;
for (; c <= '0';) {
- // FIXME: We might be able to speed this up reusing the kIds lookup table
- // from above.
- // It might require changing Flags to be a plain integer where we can |= a
- // value.
+ // FIXME: We might be able to speed this up reusing the lookup table from
+ // above. It might require changing Flags to be a plain integer where we
+ // can |= a value.
switch (c) {
case '-':
conv->flags.left = true;
@@ -159,20 +170,20 @@ flags_done:
if (c >= '0') {
int maybe_width = parse_digits();
if (!is_positional && c == '$') {
- if (ABSL_PREDICT_FALSE(*next_arg != 0)) return false;
+ if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
// Positional conversion.
*next_arg = -1;
conv->flags = Flags();
conv->flags.basic = true;
- return ConsumeConversion<true>(src, conv, next_arg);
+ return ConsumeConversion<true>(original_pos, end, conv, next_arg);
}
conv->width.set_value(maybe_width);
} else if (c == '*') {
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return false;
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->width.set_from_arg(parse_digits());
- if (ABSL_PREDICT_FALSE(c != '$')) return false;
+ if (ABSL_PREDICT_FALSE(c != '$')) return nullptr;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->width.set_from_arg(++*next_arg);
@@ -187,9 +198,9 @@ flags_done:
} else if (c == '*') {
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (is_positional) {
- if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return false;
+ if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
conv->precision.set_from_arg(parse_digits());
- if (c != '$') return false;
+ if (c != '$') return nullptr;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->precision.set_from_arg(++*next_arg);
@@ -200,43 +211,68 @@ flags_done:
}
}
- std::int8_t id = kIds[static_cast<unsigned char>(c)];
+ auto tag = GetTagForChar(c);
- if (id < 0) {
- if (ABSL_PREDICT_FALSE(id == none)) return false;
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) {
+ if (ABSL_PREDICT_FALSE(!tag.is_length())) return nullptr;
// It is a length modifier.
using str_format_internal::LengthMod;
- LengthMod length_mod = LengthMod::FromId(static_cast<LM>(~id));
+ LengthMod length_mod = tag.as_length();
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- if (c == 'h' && length_mod.id() == LengthMod::h) {
- conv->length_mod = LengthMod::FromId(LengthMod::hh);
+ if (c == 'h' && length_mod == LengthMod::h) {
+ conv->length_mod = LengthMod::hh;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else if (c == 'l' && length_mod.id() == LengthMod::l) {
- conv->length_mod = LengthMod::FromId(LengthMod::ll);
+ } else if (c == 'l' && length_mod == LengthMod::l) {
+ conv->length_mod = LengthMod::ll;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
} else {
conv->length_mod = length_mod;
}
- id = kIds[static_cast<unsigned char>(c)];
- if (ABSL_PREDICT_FALSE(id < 0)) return false;
+ tag = GetTagForChar(c);
+ if (ABSL_PREDICT_FALSE(!tag.is_conv())) return nullptr;
}
assert(CheckFastPathSetting(*conv));
(void)(&CheckFastPathSetting);
- conv->conv = ConversionChar::FromId(static_cast<CC>(id));
+ conv->conv = tag.as_conv();
if (!is_positional) conv->arg_position = ++*next_arg;
- *src = string_view(pos, end - pos);
- return true;
+ return pos;
}
} // namespace
-bool ConsumeUnboundConversion(string_view *src, UnboundConversion *conv,
- int *next_arg) {
- if (*next_arg < 0) return ConsumeConversion<true>(src, conv, next_arg);
- return ConsumeConversion<false>(src, conv, next_arg);
+std::string LengthModToString(LengthMod v) {
+ switch (v) {
+ case LengthMod::h:
+ return "h";
+ case LengthMod::hh:
+ return "hh";
+ case LengthMod::l:
+ return "l";
+ case LengthMod::ll:
+ return "ll";
+ case LengthMod::L:
+ return "L";
+ case LengthMod::j:
+ return "j";
+ case LengthMod::z:
+ return "z";
+ case LengthMod::t:
+ return "t";
+ case LengthMod::q:
+ return "q";
+ case LengthMod::none:
+ return "";
+ }
+ return "";
+}
+
+const char *ConsumeUnboundConversion(const char *p, const char *end,
+ UnboundConversion *conv, int *next_arg) {
+ if (*next_arg < 0) return ConsumeConversion<true>(p, end, conv, next_arg);
+ return ConsumeConversion<false>(p, end, conv, next_arg);
}
struct ParsedFormatBase::ParsedFormatConsumer {
@@ -274,15 +310,17 @@ struct ParsedFormatBase::ParsedFormatConsumer {
char* data_pos;
};
-ParsedFormatBase::ParsedFormatBase(string_view format, bool allow_ignored,
- std::initializer_list<Conv> convs)
+ParsedFormatBase::ParsedFormatBase(
+ string_view format, bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs)
: data_(format.empty() ? nullptr : new char[format.size()]) {
has_error_ = !ParseFormatString(format, ParsedFormatConsumer(this)) ||
!MatchesConversions(allow_ignored, convs);
}
bool ParsedFormatBase::MatchesConversions(
- bool allow_ignored, std::initializer_list<Conv> convs) const {
+ bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs) const {
std::unordered_set<int> used;
auto add_if_valid_conv = [&](int pos, char c) {
if (static_cast<size_t>(pos) > convs.size() ||
@@ -300,10 +338,13 @@ bool ParsedFormatBase::MatchesConversions(
if (conv.width.is_from_arg() &&
!add_if_valid_conv(conv.width.get_from_arg(), '*'))
return false;
- if (!add_if_valid_conv(conv.arg_position, conv.conv.Char())) return false;
+ if (!add_if_valid_conv(conv.arg_position,
+ FormatConversionCharToChar(conv.conv)))
+ return false;
}
return used.size() == convs.size() || allow_ignored;
}
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.h
index 1022f06297a..6504dd3ddc2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser.h
@@ -1,3 +1,17 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#ifndef ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
#define ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
@@ -6,18 +20,25 @@
#include <stdlib.h>
#include <cassert>
+#include <cstdint>
#include <initializer_list>
#include <iosfwd>
#include <iterator>
#include <memory>
+#include <string>
#include <vector>
#include "absl/strings/internal/str_format/checker.h"
#include "absl/strings/internal/str_format/extension.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
+enum class LengthMod : std::uint8_t { h, hh, l, ll, L, j, z, t, q, none };
+
+std::string LengthModToString(LengthMod v);
+
// The analyzed properties of a single specified conversion.
struct UnboundConversion {
UnboundConversion()
@@ -59,21 +80,52 @@ struct UnboundConversion {
InputValue precision;
Flags flags;
- LengthMod length_mod;
- ConversionChar conv;
+ LengthMod length_mod = LengthMod::none;
+ FormatConversionChar conv = FormatConversionCharInternal::kNone;
};
-// Consume conversion spec prefix (not including '%') of '*src' if valid.
+// Consume conversion spec prefix (not including '%') of [p, end) if valid.
// Examples of valid specs would be e.g.: "s", "d", "-12.6f".
-// If valid, the front of src is advanced such that src becomes the
-// part following the conversion spec, and the spec part is broken down and
-// returned in 'conv'.
-// If invalid, returns false and leaves 'src' unmodified.
-// For example:
-// Given "d9", returns "d", and leaves src="9",
-// Given "!", returns "" and leaves src="!".
-bool ConsumeUnboundConversion(string_view* src, UnboundConversion* conv,
- int* next_arg);
+// If valid, it returns the first character following the conversion spec,
+// and the spec part is broken down and returned in 'conv'.
+// If invalid, returns nullptr.
+const char* ConsumeUnboundConversion(const char* p, const char* end,
+ UnboundConversion* conv, int* next_arg);
+
+// Helper tag class for the table below.
+// It allows fast `char -> ConversionChar/LengthMod` checking and
+// conversions.
+class ConvTag {
+ public:
+ constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
+ : tag_(static_cast<int8_t>(conversion_char)) {}
+ // We invert the length modifiers to make them negative so that we can easily
+ // test for them.
+ constexpr ConvTag(LengthMod length_mod) // NOLINT
+ : tag_(~static_cast<std::int8_t>(length_mod)) {}
+ // Everything else is -128, which is negative to make is_conv() simpler.
+ constexpr ConvTag() : tag_(-128) {}
+
+ bool is_conv() const { return tag_ >= 0; }
+ bool is_length() const { return tag_ < 0 && tag_ != -128; }
+ FormatConversionChar as_conv() const {
+ assert(is_conv());
+ return static_cast<FormatConversionChar>(tag_);
+ }
+ LengthMod as_length() const {
+ assert(is_length());
+ return static_cast<LengthMod>(~tag_);
+ }
+
+ private:
+ std::int8_t tag_;
+};
+
+extern const ConvTag kTags[256];
+// Keep a single table for all the conversion chars and length modifiers.
+inline ConvTag GetTagForChar(char c) {
+ return kTags[static_cast<unsigned char>(c)];
+}
// Parse the format string provided in 'src' and pass the identified items into
// 'consumer'.
@@ -88,51 +140,53 @@ bool ConsumeUnboundConversion(string_view* src, UnboundConversion* conv,
template <typename Consumer>
bool ParseFormatString(string_view src, Consumer consumer) {
int next_arg = 0;
- while (!src.empty()) {
- const char* percent =
- static_cast<const char*>(memchr(src.data(), '%', src.size()));
+ const char* p = src.data();
+ const char* const end = p + src.size();
+ while (p != end) {
+ const char* percent = static_cast<const char*>(memchr(p, '%', end - p));
if (!percent) {
// We found the last substring.
- return consumer.Append(src);
+ return consumer.Append(string_view(p, end - p));
}
// We found a percent, so push the text run then process the percent.
- size_t percent_loc = percent - src.data();
- if (!consumer.Append(string_view(src.data(), percent_loc))) return false;
- if (percent + 1 >= src.data() + src.size()) return false;
-
- UnboundConversion conv;
-
- switch (percent[1]) {
- case '%':
- if (!consumer.Append("%")) return false;
- src.remove_prefix(percent_loc + 2);
- continue;
-
-#define PARSER_CASE(ch) \
- case #ch[0]: \
- src.remove_prefix(percent_loc + 2); \
- conv.conv = ConversionChar::FromId(ConversionChar::ch); \
- conv.arg_position = ++next_arg; \
- break;
- ABSL_CONVERSION_CHARS_EXPAND_(PARSER_CASE, );
-#undef PARSER_CASE
-
- default:
- src.remove_prefix(percent_loc + 1);
- if (!ConsumeUnboundConversion(&src, &conv, &next_arg)) return false;
- break;
- }
- if (next_arg == 0) {
- // This indicates an error in the format std::string.
- // The only way to get next_arg == 0 is to have a positional argument
- // first which sets next_arg to -1 and then a non-positional argument
- // which does ++next_arg.
- // Checking here seems to be the cheapeast place to do it.
+ if (ABSL_PREDICT_FALSE(!consumer.Append(string_view(p, percent - p)))) {
return false;
}
- if (!consumer.ConvertOne(
- conv, string_view(percent + 1, src.data() - (percent + 1)))) {
- return false;
+ if (ABSL_PREDICT_FALSE(percent + 1 >= end)) return false;
+
+ auto tag = GetTagForChar(percent[1]);
+ if (tag.is_conv()) {
+ if (ABSL_PREDICT_FALSE(next_arg < 0)) {
+ // This indicates an error in the format string.
+ // The only way to get `next_arg < 0` here is to have a positional
+ // argument first which sets next_arg to -1 and then a non-positional
+ // argument.
+ return false;
+ }
+ p = percent + 2;
+
+ // Keep this case separate from the one below.
+ // ConvertOne is more efficient when the compiler can see that the `basic`
+ // flag is set.
+ UnboundConversion conv;
+ conv.conv = tag.as_conv();
+ conv.arg_position = ++next_arg;
+ if (ABSL_PREDICT_FALSE(
+ !consumer.ConvertOne(conv, string_view(percent + 1, 1)))) {
+ return false;
+ }
+ } else if (percent[1] != '%') {
+ UnboundConversion conv;
+ p = ConsumeUnboundConversion(percent + 1, end, &conv, &next_arg);
+ if (ABSL_PREDICT_FALSE(p == nullptr)) return false;
+ if (ABSL_PREDICT_FALSE(!consumer.ConvertOne(
+ conv, string_view(percent + 1, p - (percent + 1))))) {
+ return false;
+ }
+ } else {
+ if (ABSL_PREDICT_FALSE(!consumer.Append("%"))) return false;
+ p = percent + 2;
+ continue;
}
}
return true;
@@ -146,8 +200,9 @@ constexpr bool EnsureConstexpr(string_view s) {
class ParsedFormatBase {
public:
- explicit ParsedFormatBase(string_view format, bool allow_ignored,
- std::initializer_list<Conv> convs);
+ explicit ParsedFormatBase(
+ string_view format, bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs);
ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
@@ -194,8 +249,9 @@ class ParsedFormatBase {
private:
// Returns whether the conversions match and if !allow_ignored it verifies
// that all conversions are used by the format.
- bool MatchesConversions(bool allow_ignored,
- std::initializer_list<Conv> convs) const;
+ bool MatchesConversions(
+ bool allow_ignored,
+ std::initializer_list<FormatConversionCharSet> convs) const;
struct ParsedFormatConsumer;
@@ -240,14 +296,14 @@ class ParsedFormatBase {
// This is the only API that allows the user to pass a runtime specified format
// string. These factory functions will return NULL if the format does not match
// the conversions requested by the user.
-template <str_format_internal::Conv... C>
+template <FormatConversionCharSet... C>
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
public:
explicit ExtendedParsedFormat(string_view format)
-#if ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
+#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
__attribute__((
enable_if(str_format_internal::EnsureConstexpr(format),
- "Format std::string is not constexpr."),
+ "Format string is not constexpr."),
enable_if(str_format_internal::ValidFormatImpl<C...>(format),
"Format specified does not match the template arguments.")))
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -287,6 +343,7 @@ class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
: ParsedFormatBase(s, allow_ignored, {C...}) {}
};
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_FORMAT_PARSER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
index ae40203191b..a5fa1c79aaf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
@@ -1,18 +1,37 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
#include "absl/strings/internal/str_format/parser.h"
#include <string.h>
+
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/macros.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
+using testing::Pair;
+
TEST(LengthModTest, Names) {
struct Expectation {
int line;
- LengthMod::Id id;
+ LengthMod mod;
const char *name;
};
const Expectation kExpect[] = {
@@ -27,56 +46,53 @@ TEST(LengthModTest, Names) {
{__LINE__, LengthMod::t, "t" },
{__LINE__, LengthMod::q, "q" },
};
- EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), LengthMod::kNumValues);
+ EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), 10);
for (auto e : kExpect) {
SCOPED_TRACE(e.line);
- LengthMod mod = LengthMod::FromId(e.id);
- EXPECT_EQ(e.id, mod.id());
- EXPECT_EQ(e.name, mod.name());
+ EXPECT_EQ(e.name, LengthModToString(e.mod));
}
}
TEST(ConversionCharTest, Names) {
struct Expectation {
- ConversionChar::Id id;
+ FormatConversionChar id;
char name;
};
// clang-format off
const Expectation kExpect[] = {
-#define X(c) {ConversionChar::c, #c[0]}
- X(c), X(C), X(s), X(S), // text
+#define X(c) {FormatConversionCharInternal::c, #c[0]}
+ X(c), X(s), // text
X(d), X(i), X(o), X(u), X(x), X(X), // int
X(f), X(F), X(e), X(E), X(g), X(G), X(a), X(A), // float
X(n), X(p), // misc
#undef X
- {ConversionChar::none, '\0'},
+ {FormatConversionCharInternal::kNone, '\0'},
};
// clang-format on
- EXPECT_EQ(ABSL_ARRAYSIZE(kExpect), ConversionChar::kNumValues);
for (auto e : kExpect) {
SCOPED_TRACE(e.name);
- ConversionChar v = ConversionChar::FromId(e.id);
- EXPECT_EQ(e.id, v.id());
- EXPECT_EQ(e.name, v.Char());
+ FormatConversionChar v = e.id;
+ EXPECT_EQ(e.name, FormatConversionCharToChar(v));
}
}
class ConsumeUnboundConversionTest : public ::testing::Test {
public:
- typedef UnboundConversion Props;
- string_view Consume(string_view* src) {
+ std::pair<string_view, string_view> Consume(string_view src) {
int next = 0;
- const char* prev_begin = src->data();
o = UnboundConversion(); // refresh
- ConsumeUnboundConversion(src, &o, &next);
- return {prev_begin, static_cast<size_t>(src->data() - prev_begin)};
+ const char* p = ConsumeUnboundConversion(
+ src.data(), src.data() + src.size(), &o, &next);
+ if (!p) return {{}, src};
+ return {string_view(src.data(), p - src.data()),
+ string_view(p, src.data() + src.size() - p)};
}
bool Run(const char *fmt, bool force_positional = false) {
- string_view src = fmt;
int next = force_positional ? -1 : 0;
o = UnboundConversion(); // refresh
- return ConsumeUnboundConversion(&src, &o, &next) && src.empty();
+ return ConsumeUnboundConversion(fmt, fmt + strlen(fmt), &o, &next) ==
+ fmt + strlen(fmt);
}
UnboundConversion o;
};
@@ -104,11 +120,7 @@ TEST_F(ConsumeUnboundConversionTest, ConsumeSpecification) {
};
for (const auto& e : kExpect) {
SCOPED_TRACE(e.line);
- string_view src = e.src;
- EXPECT_EQ(e.src, src);
- string_view out = Consume(&src);
- EXPECT_EQ(e.out, out);
- EXPECT_EQ(e.src_post, src);
+ EXPECT_THAT(Consume(e.src), Pair(e.out, e.src_post));
}
}
@@ -119,13 +131,12 @@ TEST_F(ConsumeUnboundConversionTest, BasicConversion) {
EXPECT_FALSE(Run("dd")); // no excess allowed
EXPECT_TRUE(Run("d"));
- EXPECT_EQ('d', o.conv.Char());
+ EXPECT_EQ('d', FormatConversionCharToChar(o.conv));
EXPECT_FALSE(o.width.is_from_arg());
EXPECT_LT(o.width.value(), 0);
EXPECT_FALSE(o.precision.is_from_arg());
EXPECT_LT(o.precision.value(), 0);
EXPECT_EQ(1, o.arg_position);
- EXPECT_EQ(LengthMod::none, o.length_mod.id());
}
TEST_F(ConsumeUnboundConversionTest, ArgPosition) {
@@ -161,7 +172,7 @@ TEST_F(ConsumeUnboundConversionTest, ArgPosition) {
TEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) {
EXPECT_TRUE(Run("14d"));
- EXPECT_EQ('d', o.conv.Char());
+ EXPECT_EQ('d', FormatConversionCharToChar(o.conv));
EXPECT_FALSE(o.width.is_from_arg());
EXPECT_EQ(14, o.width.value());
EXPECT_FALSE(o.precision.is_from_arg());
@@ -246,6 +257,8 @@ TEST_F(ConsumeUnboundConversionTest, WidthAndPrecision) {
EXPECT_FALSE(Run("1000000000.999999999d"));
EXPECT_FALSE(Run("999999999.1000000000d"));
+ EXPECT_FALSE(Run("9999999999d"));
+ EXPECT_FALSE(Run(".9999999999d"));
}
TEST_F(ConsumeUnboundConversionTest, Flags) {
@@ -286,6 +299,29 @@ TEST_F(ConsumeUnboundConversionTest, BasicFlag) {
}
}
+TEST_F(ConsumeUnboundConversionTest, LengthMod) {
+ EXPECT_TRUE(Run("d"));
+ EXPECT_EQ(LengthMod::none, o.length_mod);
+ EXPECT_TRUE(Run("hd"));
+ EXPECT_EQ(LengthMod::h, o.length_mod);
+ EXPECT_TRUE(Run("hhd"));
+ EXPECT_EQ(LengthMod::hh, o.length_mod);
+ EXPECT_TRUE(Run("ld"));
+ EXPECT_EQ(LengthMod::l, o.length_mod);
+ EXPECT_TRUE(Run("lld"));
+ EXPECT_EQ(LengthMod::ll, o.length_mod);
+ EXPECT_TRUE(Run("Lf"));
+ EXPECT_EQ(LengthMod::L, o.length_mod);
+ EXPECT_TRUE(Run("qf"));
+ EXPECT_EQ(LengthMod::q, o.length_mod);
+ EXPECT_TRUE(Run("jd"));
+ EXPECT_EQ(LengthMod::j, o.length_mod);
+ EXPECT_TRUE(Run("zd"));
+ EXPECT_EQ(LengthMod::z, o.length_mod);
+ EXPECT_TRUE(Run("td"));
+ EXPECT_EQ(LengthMod::t, o.length_mod);
+}
+
struct SummarizeConsumer {
std::string* out;
explicit SummarizeConsumer(std::string* out) : out(out) {}
@@ -306,7 +342,7 @@ struct SummarizeConsumer {
if (conv.precision.is_from_arg()) {
*out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
}
- *out += conv.conv.Char();
+ *out += FormatConversionCharToChar(conv.conv);
*out += "}";
return true;
}
@@ -327,7 +363,8 @@ TEST_F(ParsedFormatTest, ValueSemantics) {
ParsedFormatBase p2 = p1; // copy construct (empty)
EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2));
- p1 = ParsedFormatBase("hello%s", true, {Conv::s}); // move assign
+ p1 = ParsedFormatBase("hello%s", true,
+ {FormatConversionCharSetInternal::s}); // move assign
EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p1));
ParsedFormatBase p3 = p1; // copy construct (nonempty)
@@ -345,7 +382,7 @@ TEST_F(ParsedFormatTest, ValueSemantics) {
struct ExpectParse {
const char* in;
- std::initializer_list<Conv> conv_set;
+ std::initializer_list<FormatConversionCharSet> conv_set;
const char* out;
};
@@ -355,9 +392,9 @@ TEST_F(ParsedFormatTest, Parsing) {
const ExpectParse kExpect[] = {
{"", {}, ""},
{"ab", {}, "[ab]"},
- {"a%d", {Conv::d}, "[a]{d:1$d}"},
- {"a%+d", {Conv::d}, "[a]{+d:1$d}"},
- {"a% d", {Conv::d}, "[a]{ d:1$d}"},
+ {"a%d", {FormatConversionCharSetInternal::d}, "[a]{d:1$d}"},
+ {"a%+d", {FormatConversionCharSetInternal::d}, "[a]{+d:1$d}"},
+ {"a% d", {FormatConversionCharSetInternal::d}, "[a]{ d:1$d}"},
{"a%b %d", {}, "[a]!"}, // stop after error
};
for (const auto& e : kExpect) {
@@ -369,13 +406,13 @@ TEST_F(ParsedFormatTest, Parsing) {
TEST_F(ParsedFormatTest, ParsingFlagOrder) {
const ExpectParse kExpect[] = {
- {"a%+ 0d", {Conv::d}, "[a]{+ 0d:1$d}"},
- {"a%+0 d", {Conv::d}, "[a]{+0 d:1$d}"},
- {"a%0+ d", {Conv::d}, "[a]{0+ d:1$d}"},
- {"a% +0d", {Conv::d}, "[a]{ +0d:1$d}"},
- {"a%0 +d", {Conv::d}, "[a]{0 +d:1$d}"},
- {"a% 0+d", {Conv::d}, "[a]{ 0+d:1$d}"},
- {"a%+ 0+d", {Conv::d}, "[a]{+ 0+d:1$d}"},
+ {"a%+ 0d", {FormatConversionCharSetInternal::d}, "[a]{+ 0d:1$d}"},
+ {"a%+0 d", {FormatConversionCharSetInternal::d}, "[a]{+0 d:1$d}"},
+ {"a%0+ d", {FormatConversionCharSetInternal::d}, "[a]{0+ d:1$d}"},
+ {"a% +0d", {FormatConversionCharSetInternal::d}, "[a]{ +0d:1$d}"},
+ {"a%0 +d", {FormatConversionCharSetInternal::d}, "[a]{0 +d:1$d}"},
+ {"a% 0+d", {FormatConversionCharSetInternal::d}, "[a]{ 0+d:1$d}"},
+ {"a%+ 0+d", {FormatConversionCharSetInternal::d}, "[a]{+ 0+d:1$d}"},
};
for (const auto& e : kExpect) {
SCOPED_TRACE(e.in);
@@ -386,4 +423,5 @@ TEST_F(ParsedFormatTest, ParsingFlagOrder) {
} // namespace
} // namespace str_format_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_join_internal.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_join_internal.h
index 0058fc8aa4d..31dbf672f0b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_join_internal.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_join_internal.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -43,6 +43,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
//
@@ -193,7 +194,7 @@ struct DefaultFormatter<std::unique_ptr<ValueType>>
// and formats each element using the provided Formatter object.
template <typename Iterator, typename Formatter>
std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
- Formatter&& f) {
+ Formatter&& f) {
std::string result;
absl::string_view sep("");
for (Iterator it = start; it != end; ++it) {
@@ -212,7 +213,7 @@ std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
// This is an overload of the previous JoinAlgorithm() function. Here the
// Formatter argument is of type NoFormatter. Since NoFormatter is an internal
// type, this overload is only invoked when strings::Join() is called with a
-// range of string-like objects (e.g., string, absl::string_view), and an
+// range of string-like objects (e.g., std::string, absl::string_view), and an
// explicit Formatter argument was NOT specified.
//
// The optimization is that the needed space will be reserved in the output
@@ -224,7 +225,7 @@ template <typename Iterator,
typename std::iterator_traits<Iterator>::iterator_category,
std::forward_iterator_tag>::value>::type>
std::string JoinAlgorithm(Iterator start, Iterator end, absl::string_view s,
- NoFormatter) {
+ NoFormatter) {
std::string result;
if (start != end) {
// Sums size
@@ -276,14 +277,15 @@ struct JoinTupleLoop<N, N> {
template <typename... T, typename Formatter>
std::string JoinAlgorithm(const std::tuple<T...>& tup, absl::string_view sep,
- Formatter&& fmt) {
+ Formatter&& fmt) {
std::string result;
JoinTupleLoop<0, sizeof...(T)>()(&result, tup, sep, fmt);
return result;
}
template <typename Iterator>
-std::string JoinRange(Iterator first, Iterator last, absl::string_view separator) {
+std::string JoinRange(Iterator first, Iterator last,
+ absl::string_view separator) {
// No formatter was explicitly given, so a default must be chosen.
typedef typename std::iterator_traits<Iterator>::value_type ValueType;
typedef typename DefaultFormatter<ValueType>::Type Formatter;
@@ -292,7 +294,7 @@ std::string JoinRange(Iterator first, Iterator last, absl::string_view separator
template <typename Range, typename Formatter>
std::string JoinRange(const Range& range, absl::string_view separator,
- Formatter&& fmt) {
+ Formatter&& fmt) {
using std::begin;
using std::end;
return JoinAlgorithm(begin(range), end(range), separator, fmt);
@@ -306,6 +308,7 @@ std::string JoinRange(const Range& range, absl::string_view separator) {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_JOIN_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_split_internal.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_split_internal.h
index 81e8d555446..a2f41c15313 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_split_internal.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/str_split_internal.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -47,12 +47,13 @@
#endif // _GLIBCXX_DEBUG
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// This class is implicitly constructible from everything that absl::string_view
-// is implicitly constructible from. If it's constructed from a temporary
-// string, the data is moved into a data member so its lifetime matches that of
-// the ConvertibleToStringView instance.
+// is implicitly constructible from, except for rvalue strings. This means it
+// can be used as a function parameter in places where passing a temporary
+// string might cause memory lifetime issues.
class ConvertibleToStringView {
public:
ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit)
@@ -64,41 +65,12 @@ class ConvertibleToStringView {
: value_(s) {}
// Matches rvalue strings and moves their data to a member.
-ConvertibleToStringView(std::string&& s) // NOLINT(runtime/explicit)
- : copy_(std::move(s)), value_(copy_) {}
-
- ConvertibleToStringView(const ConvertibleToStringView& other)
- : copy_(other.copy_),
- value_(other.IsSelfReferential() ? copy_ : other.value_) {}
-
- ConvertibleToStringView(ConvertibleToStringView&& other) {
- StealMembers(std::move(other));
- }
-
- ConvertibleToStringView& operator=(ConvertibleToStringView other) {
- StealMembers(std::move(other));
- return *this;
- }
+ ConvertibleToStringView(std::string&& s) = delete;
+ ConvertibleToStringView(const std::string&& s) = delete;
absl::string_view value() const { return value_; }
private:
- // Returns true if ctsp's value refers to its internal copy_ member.
- bool IsSelfReferential() const { return value_.data() == copy_.data(); }
-
- void StealMembers(ConvertibleToStringView&& other) {
- if (other.IsSelfReferential()) {
- copy_ = std::move(other.copy_);
- value_ = copy_;
- other.value_ = other.copy_;
- } else {
- value_ = other.value_;
- }
- }
-
- // Holds the data moved from temporary std::string arguments. Declared first so
- // that 'value' can refer to 'copy_'.
- std::string copy_;
absl::string_view value_;
};
@@ -272,7 +244,11 @@ struct SplitterIsConvertibleTo
// the split strings: only strings for which the predicate returns true will be
// kept. A Predicate object is any unary functor that takes an absl::string_view
// and returns bool.
-template <typename Delimiter, typename Predicate>
+//
+// The StringType parameter can be either string_view or string, depending on
+// whether the Splitter refers to a string stored elsewhere, or if the string
+// resides inside the Splitter itself.
+template <typename Delimiter, typename Predicate, typename StringType>
class Splitter {
public:
using DelimiterType = Delimiter;
@@ -280,12 +256,12 @@ class Splitter {
using const_iterator = strings_internal::SplitIterator<Splitter>;
using value_type = typename std::iterator_traits<const_iterator>::value_type;
- Splitter(ConvertibleToStringView input_text, Delimiter d, Predicate p)
+ Splitter(StringType input_text, Delimiter d, Predicate p)
: text_(std::move(input_text)),
delimiter_(std::move(d)),
predicate_(std::move(p)) {}
- absl::string_view text() const { return text_.value(); }
+ absl::string_view text() const { return text_; }
const Delimiter& delimiter() const { return delimiter_; }
const Predicate& predicate() const { return predicate_; }
@@ -335,7 +311,7 @@ class Splitter {
Container operator()(const Splitter& splitter) const {
Container c;
auto it = std::inserter(c, c.end());
- for (const auto sp : splitter) {
+ for (const auto& sp : splitter) {
*it++ = ValueType(sp);
}
return c;
@@ -376,10 +352,10 @@ class Splitter {
// Partial specialization for a std::vector<std::string>.
//
- // Optimized for the common case of splitting to a std::vector<std::string>. In
- // this case we first split the results to a std::vector<absl::string_view> so
- // the returned std::vector<std::string> can have space reserved to avoid std::string
- // moves.
+ // Optimized for the common case of splitting to a std::vector<std::string>.
+ // In this case we first split the results to a std::vector<absl::string_view>
+ // so the returned std::vector<std::string> can have space reserved to avoid
+ // std::string moves.
template <typename A>
struct ConvertToContainer<std::vector<std::string, A>, std::string, false> {
std::vector<std::string, A> operator()(const Splitter& splitter) const {
@@ -400,7 +376,7 @@ class Splitter {
Container m;
typename Container::iterator it;
bool insert = true;
- for (const auto sp : splitter) {
+ for (const auto& sp : splitter) {
if (insert) {
it = Inserter<Container>::Insert(&m, First(sp), Second());
} else {
@@ -442,12 +418,13 @@ class Splitter {
};
};
- ConvertibleToStringView text_;
+ StringType text_;
Delimiter delimiter_;
Predicate predicate_;
};
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_STR_SPLIT_INTERNAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant.h
new file mode 100644
index 00000000000..a11336b7f03
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant.h
@@ -0,0 +1,64 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+#define ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace strings_internal {
+
+// StringConstant<T> represents a compile time string constant.
+// It can be accessed via its `absl::string_view value` static member.
+// It is guaranteed that the `string_view` returned has constant `.data()`,
+// constant `.size()` and constant `value[i]` for all `0 <= i < .size()`
+//
+// The `T` is an opaque type. It is guaranteed that different string constants
+// will have different values of `T`. This allows users to associate the string
+// constant with other static state at compile time.
+//
+// Instances should be made using the `MakeStringConstant()` factory function
+// below.
+template <typename T>
+struct StringConstant {
+ static constexpr absl::string_view value = T{}();
+ constexpr absl::string_view operator()() const { return value; }
+
+ // Check to be sure `view` points to constant data.
+ // Otherwise, it can't be constant evaluated.
+ static_assert(value.empty() || 2 * value[0] != 1,
+ "The input string_view must point to constant data.");
+};
+
+template <typename T>
+constexpr absl::string_view StringConstant<T>::value; // NOLINT
+
+// Factory function for `StringConstant` instances.
+// It supports callables that have a constexpr default constructor and a
+// constexpr operator().
+// It must return an `absl::string_view` or `const char*` pointing to constant
+// data. This is validated at compile time.
+template <typename T>
+constexpr StringConstant<T> MakeStringConstant(T) {
+ return {};
+}
+
+} // namespace strings_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_STRINGS_INTERNAL_STRING_CONSTANT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant_test.cc
new file mode 100644
index 00000000000..392833cf159
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/string_constant_test.cc
@@ -0,0 +1,60 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/internal/string_constant.h"
+
+#include "absl/meta/type_traits.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+using absl::strings_internal::MakeStringConstant;
+
+struct Callable {
+ constexpr absl::string_view operator()() const {
+ return absl::string_view("Callable", 8);
+ }
+};
+
+TEST(StringConstant, Traits) {
+ constexpr auto str = MakeStringConstant(Callable{});
+ using T = decltype(str);
+
+ EXPECT_TRUE(std::is_empty<T>::value);
+ EXPECT_TRUE(std::is_trivial<T>::value);
+ EXPECT_TRUE(absl::is_trivially_default_constructible<T>::value);
+ EXPECT_TRUE(absl::is_trivially_copy_constructible<T>::value);
+ EXPECT_TRUE(absl::is_trivially_move_constructible<T>::value);
+ EXPECT_TRUE(absl::is_trivially_destructible<T>::value);
+}
+
+TEST(StringConstant, MakeFromCallable) {
+ constexpr auto str = MakeStringConstant(Callable{});
+ using T = decltype(str);
+ EXPECT_EQ(Callable{}(), T::value);
+ EXPECT_EQ(Callable{}(), str());
+}
+
+TEST(StringConstant, MakeFromStringConstant) {
+ // We want to make sure the StringConstant itself is a valid input to the
+ // factory function.
+ constexpr auto str = MakeStringConstant(Callable{});
+ constexpr auto str2 = MakeStringConstant(str);
+ using T = decltype(str2);
+ EXPECT_EQ(Callable{}(), T::value);
+ EXPECT_EQ(Callable{}(), str2());
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.cc
index 2415c2ccc45..8fd8edc1ec6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/strings/internal/utf8.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
@@ -48,4 +49,5 @@ size_t EncodeUTF8Char(char *buffer, char32_t utf8_char) {
}
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.h
index d2c3c0b0120..32fb1093bea 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -13,7 +13,6 @@
// limitations under the License.
//
// UTF8 utilities, implemented to reduce dependencies.
-//
#ifndef ABSL_STRINGS_INTERNAL_UTF8_H_
#define ABSL_STRINGS_INTERNAL_UTF8_H_
@@ -21,7 +20,10 @@
#include <cstddef>
#include <cstdint>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// For Unicode code points 0 through 0x10FFFF, EncodeUTF8Char writes
@@ -42,6 +44,7 @@ enum { kMaxEncodedUTF8Size = 4 };
size_t EncodeUTF8Char(char *buffer, char32_t utf8_char);
} // namespace strings_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_UTF8_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8_test.cc
index 64cec70df7e..88dd5036e3d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/internal/utf8_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,12 +22,17 @@
namespace {
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
TEST(EncodeUTF8Char, BasicFunction) {
std::pair<char32_t, std::string> tests[] = {{0x0030, u8"\u0030"},
- {0x00A3, u8"\u00A3"},
- {0x00010000, u8"\U00010000"},
- {0x0000FFFF, u8"\U0000FFFF"},
- {0x0010FFFD, u8"\U0010FFFD"}};
+ {0x00A3, u8"\u00A3"},
+ {0x00010000, u8"\U00010000"},
+ {0x0000FFFF, u8"\U0000FFFF"},
+ {0x0010FFFD, u8"\U0010FFFD"}};
for (auto &test : tests) {
char buf0[7] = {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'};
char buf1[7] = {'\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF', '\xFF'};
@@ -53,5 +58,9 @@ TEST(EncodeUTF8Char, BasicFunction) {
EXPECT_LE(absl::strings_internal::EncodeUTF8Char(buf2, -1),
absl::strings_internal::kMaxEncodedUTF8Size);
}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif // !defined(__cpp_char8_t)
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.cc
index a2e9064c076..2d67250970a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,22 +17,27 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
-bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
+bool EqualsIgnoreCase(absl::string_view piece1,
+ absl::string_view piece2) noexcept {
return (piece1.size() == piece2.size() &&
0 == absl::strings_internal::memcasecmp(piece1.data(), piece2.data(),
piece1.size()));
// memcasecmp uses absl::ascii_tolower().
}
-bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
+bool StartsWithIgnoreCase(absl::string_view text,
+ absl::string_view prefix) noexcept {
return (text.size() >= prefix.size()) &&
EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
}
-bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
+bool EndsWithIgnoreCase(absl::string_view text,
+ absl::string_view suffix) noexcept {
return (text.size() >= suffix.size()) &&
EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.h
index 6e8ed10fc50..038cbb3fa8b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,7 +20,7 @@
// This file contains simple utilities for performing string matching checks.
// All of these function parameters are specified as `absl::string_view`,
// meaning that these functions can accept `std::string`, `absl::string_view` or
-// nul-terminated C-style strings.
+// NUL-terminated C-style strings.
//
// Examples:
// std::string s = "foo";
@@ -38,18 +38,25 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// StrContains()
//
// Returns whether a given string `haystack` contains the substring `needle`.
-inline bool StrContains(absl::string_view haystack, absl::string_view needle) {
+inline bool StrContains(absl::string_view haystack,
+ absl::string_view needle) noexcept {
return haystack.find(needle, 0) != haystack.npos;
}
+inline bool StrContains(absl::string_view haystack, char needle) noexcept {
+ return haystack.find(needle) != haystack.npos;
+}
+
// StartsWith()
//
// Returns whether a given string `text` begins with `prefix`.
-inline bool StartsWith(absl::string_view text, absl::string_view prefix) {
+inline bool StartsWith(absl::string_view text,
+ absl::string_view prefix) noexcept {
return prefix.empty() ||
(text.size() >= prefix.size() &&
memcmp(text.data(), prefix.data(), prefix.size()) == 0);
@@ -58,32 +65,36 @@ inline bool StartsWith(absl::string_view text, absl::string_view prefix) {
// EndsWith()
//
// Returns whether a given string `text` ends with `suffix`.
-inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
+inline bool EndsWith(absl::string_view text,
+ absl::string_view suffix) noexcept {
return suffix.empty() ||
(text.size() >= suffix.size() &&
memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
- suffix.size()) == 0
- );
+ suffix.size()) == 0);
}
// EqualsIgnoreCase()
//
// Returns whether given ASCII strings `piece1` and `piece2` are equal, ignoring
// case in the comparison.
-bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2);
+bool EqualsIgnoreCase(absl::string_view piece1,
+ absl::string_view piece2) noexcept;
// StartsWithIgnoreCase()
//
-// Returns whether a given ASCII string `text` starts with `starts_with`,
+// Returns whether a given ASCII string `text` starts with `prefix`,
// ignoring case in the comparison.
-bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
+bool StartsWithIgnoreCase(absl::string_view text,
+ absl::string_view prefix) noexcept;
// EndsWithIgnoreCase()
//
-// Returns whether a given ASCII string `text` ends with `ends_with`, ignoring
+// Returns whether a given ASCII string `text` ends with `suffix`, ignoring
// case in the comparison.
-bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
+bool EndsWithIgnoreCase(absl::string_view text,
+ absl::string_view suffix) noexcept;
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_MATCH_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match_test.cc
index c21e00bf807..5841bc1b486 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/match_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,7 +19,7 @@
namespace {
TEST(MatchTest, StartsWith) {
- const std::string s1("123" "\0" "456", 7);
+ const std::string s1("123\0abc", 7);
const absl::string_view a("foobar");
const absl::string_view b(s1);
const absl::string_view e;
@@ -36,7 +36,7 @@ TEST(MatchTest, StartsWith) {
}
TEST(MatchTest, EndsWith) {
- const std::string s1("123" "\0" "456", 7);
+ const std::string s1("123\0abc", 7);
const absl::string_view a("foobar");
const absl::string_view b(s1);
const absl::string_view e;
@@ -66,6 +66,23 @@ TEST(MatchTest, Contains) {
EXPECT_FALSE(absl::StrContains("", "a"));
}
+TEST(MatchTest, ContainsChar) {
+ absl::string_view a("abcdefg");
+ absl::string_view b("abcd");
+ EXPECT_TRUE(absl::StrContains(a, 'a'));
+ EXPECT_TRUE(absl::StrContains(a, 'b'));
+ EXPECT_TRUE(absl::StrContains(a, 'e'));
+ EXPECT_FALSE(absl::StrContains(a, 'h'));
+
+ EXPECT_TRUE(absl::StrContains(b, 'a'));
+ EXPECT_TRUE(absl::StrContains(b, 'b'));
+ EXPECT_FALSE(absl::StrContains(b, 'e'));
+ EXPECT_FALSE(absl::StrContains(b, 'h'));
+
+ EXPECT_FALSE(absl::StrContains("", 'a'));
+ EXPECT_FALSE(absl::StrContains("", 'a'));
+}
+
TEST(MatchTest, ContainsNull) {
const std::string s = "foo";
const char* cs = "foo";
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.cc
index 9309f9da9dc..966d94bd707 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,8 +19,8 @@
#include <algorithm>
#include <cassert>
-#include <cfloat> // for DBL_DIG and FLT_DIG
-#include <cmath> // for HUGE_VAL
+#include <cfloat> // for DBL_DIG and FLT_DIG
+#include <cmath> // for HUGE_VAL
#include <cstdint>
#include <cstdio>
#include <cstdlib>
@@ -30,22 +30,31 @@
#include <memory>
#include <utility>
-#include "absl/base/internal/bits.h"
+#include "absl/base/attributes.h"
#include "absl/base/internal/raw_logging.h"
+#include "absl/numeric/bits.h"
#include "absl/strings/ascii.h"
#include "absl/strings/charconv.h"
+#include "absl/strings/escaping.h"
#include "absl/strings/internal/memutil.h"
+#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
-bool SimpleAtof(absl::string_view str, float* value) {
- *value = 0.0;
+bool SimpleAtof(absl::string_view str, float* out) {
+ *out = 0.0;
str = StripAsciiWhitespace(str);
+ // std::from_chars doesn't accept an initial +, but SimpleAtof does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
- auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+ auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
return false;
}
@@ -53,25 +62,30 @@ bool SimpleAtof(absl::string_view str, float* value) {
// not all non-whitespace characters consumed
return false;
}
- // from_chars() with DR 3801's current wording will return max() on
+ // from_chars() with DR 3081's current wording will return max() on
// overflow. SimpleAtof returns infinity instead.
if (result.ec == std::errc::result_out_of_range) {
- if (*value > 1.0) {
- *value = std::numeric_limits<float>::infinity();
- } else if (*value < -1.0) {
- *value = -std::numeric_limits<float>::infinity();
+ if (*out > 1.0) {
+ *out = std::numeric_limits<float>::infinity();
+ } else if (*out < -1.0) {
+ *out = -std::numeric_limits<float>::infinity();
}
}
return true;
}
-bool SimpleAtod(absl::string_view str, double* value) {
- *value = 0.0;
+bool SimpleAtod(absl::string_view str, double* out) {
+ *out = 0.0;
str = StripAsciiWhitespace(str);
+ // std::from_chars doesn't accept an initial +, but SimpleAtod does, so if one
+ // is present, skip it, while avoiding accepting "+-0" as valid.
if (!str.empty() && str[0] == '+') {
str.remove_prefix(1);
+ if (!str.empty() && str[0] == '-') {
+ return false;
+ }
}
- auto result = absl::from_chars(str.data(), str.data() + str.size(), *value);
+ auto result = absl::from_chars(str.data(), str.data() + str.size(), *out);
if (result.ec == std::errc::invalid_argument) {
return false;
}
@@ -79,75 +93,30 @@ bool SimpleAtod(absl::string_view str, double* value) {
// not all non-whitespace characters consumed
return false;
}
- // from_chars() with DR 3801's current wording will return max() on
+ // from_chars() with DR 3081's current wording will return max() on
// overflow. SimpleAtod returns infinity instead.
if (result.ec == std::errc::result_out_of_range) {
- if (*value > 1.0) {
- *value = std::numeric_limits<double>::infinity();
- } else if (*value < -1.0) {
- *value = -std::numeric_limits<double>::infinity();
+ if (*out > 1.0) {
+ *out = std::numeric_limits<double>::infinity();
+ } else if (*out < -1.0) {
+ *out = -std::numeric_limits<double>::infinity();
}
}
return true;
}
-namespace {
-
-// TODO(rogeeff): replace with the real released thing once we figure out what
-// it is.
-inline bool CaseEqual(absl::string_view piece1, absl::string_view piece2) {
- return (piece1.size() == piece2.size() &&
- 0 == strings_internal::memcasecmp(piece1.data(), piece2.data(),
- piece1.size()));
-}
-
-// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
-// range 0 <= i < 100, and buf must have space for two characters. Example:
-// char buf[2];
-// PutTwoDigits(42, buf);
-// // buf[0] == '4'
-// // buf[1] == '2'
-inline void PutTwoDigits(size_t i, char* buf) {
- static const char two_ASCII_digits[100][2] = {
- {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'},
- {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
- {'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'},
- {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
- {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'},
- {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
- {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'},
- {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
- {'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'},
- {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
- {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'},
- {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
- {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'},
- {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
- {'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'},
- {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
- {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'},
- {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
- {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'},
- {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}
- };
- assert(i < 100);
- memcpy(buf, two_ASCII_digits[i], 2);
-}
-
-} // namespace
-
-bool SimpleAtob(absl::string_view str, bool* value) {
- ABSL_RAW_CHECK(value != nullptr, "Output pointer must not be nullptr.");
- if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
- CaseEqual(str, "yes") || CaseEqual(str, "y") ||
- CaseEqual(str, "1")) {
- *value = true;
+bool SimpleAtob(absl::string_view str, bool* out) {
+ ABSL_RAW_CHECK(out != nullptr, "Output pointer must not be nullptr.");
+ if (EqualsIgnoreCase(str, "true") || EqualsIgnoreCase(str, "t") ||
+ EqualsIgnoreCase(str, "yes") || EqualsIgnoreCase(str, "y") ||
+ EqualsIgnoreCase(str, "1")) {
+ *out = true;
return true;
}
- if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
- CaseEqual(str, "no") || CaseEqual(str, "n") ||
- CaseEqual(str, "0")) {
- *value = false;
+ if (EqualsIgnoreCase(str, "false") || EqualsIgnoreCase(str, "f") ||
+ EqualsIgnoreCase(str, "no") || EqualsIgnoreCase(str, "n") ||
+ EqualsIgnoreCase(str, "0")) {
+ *out = false;
return true;
}
return false;
@@ -344,7 +313,7 @@ static std::pair<uint64_t, uint64_t> Mul32(std::pair<uint64_t, uint64_t> num,
uint64_t bits128_up = (bits96_127 >> 32) + (bits64_127 < bits64_95);
if (bits128_up == 0) return {bits64_127, bits0_63};
- int shift = 64 - base_internal::CountLeadingZeros64(bits128_up);
+ auto shift = static_cast<unsigned>(bit_width(bits128_up));
uint64_t lo = (bits0_63 >> shift) + (bits64_127 << (64 - shift));
uint64_t hi = (bits64_127 >> shift) + (bits128_up << (64 - shift));
return {hi, lo};
@@ -375,7 +344,7 @@ static std::pair<uint64_t, uint64_t> PowFive(uint64_t num, int expfive) {
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5};
result = Mul32(result, powers_of_five[expfive & 15]);
- int shift = base_internal::CountLeadingZeros64(result.first);
+ int shift = countl_zero(result.first);
if (shift != 0) {
result.first = (result.first << shift) + (result.second >> (64 - shift));
result.second = (result.second << shift);
@@ -502,13 +471,13 @@ static ExpDigits SplitToSix(const double value) {
int two_digits = dddddd / 10000;
dddddd -= two_digits * 10000;
- PutTwoDigits(two_digits, &exp_dig.digits[0]);
+ numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[0]);
two_digits = dddddd / 100;
dddddd -= two_digits * 100;
- PutTwoDigits(two_digits, &exp_dig.digits[2]);
+ numbers_internal::PutTwoDigits(two_digits, &exp_dig.digits[2]);
- PutTwoDigits(dddddd, &exp_dig.digits[4]);
+ numbers_internal::PutTwoDigits(dddddd, &exp_dig.digits[4]);
return exp_dig;
}
@@ -761,8 +730,8 @@ inline bool safe_parse_sign_and_base(absl::string_view* text /*inout*/,
// commonly used bases.
template <typename IntType>
struct LookupTables {
- static const IntType kVmaxOverBase[];
- static const IntType kVminOverBase[];
+ ABSL_CONST_INIT static const IntType kVmaxOverBase[];
+ ABSL_CONST_INIT static const IntType kVminOverBase[];
};
// An array initializer macro for X/base where base in [0, 36].
@@ -777,6 +746,163 @@ struct LookupTables {
X / 35, X / 36, \
}
+// This kVmaxOverBase is generated with
+// for (int base = 2; base < 37; ++base) {
+// absl::uint128 max = std::numeric_limits<absl::uint128>::max();
+// auto result = max / base;
+// std::cout << " MakeUint128(" << absl::Uint128High64(result) << "u, "
+// << absl::Uint128Low64(result) << "u),\n";
+// }
+// See https://godbolt.org/z/aneYsb
+//
+// uint128& operator/=(uint128) is not constexpr, so hardcode the resulting
+// array to avoid a static initializer.
+template<>
+const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
+ 0,
+ 0,
+ MakeUint128(9223372036854775807u, 18446744073709551615u),
+ MakeUint128(6148914691236517205u, 6148914691236517205u),
+ MakeUint128(4611686018427387903u, 18446744073709551615u),
+ MakeUint128(3689348814741910323u, 3689348814741910323u),
+ MakeUint128(3074457345618258602u, 12297829382473034410u),
+ MakeUint128(2635249153387078802u, 5270498306774157604u),
+ MakeUint128(2305843009213693951u, 18446744073709551615u),
+ MakeUint128(2049638230412172401u, 14347467612885206812u),
+ MakeUint128(1844674407370955161u, 11068046444225730969u),
+ MakeUint128(1676976733973595601u, 8384883669867978007u),
+ MakeUint128(1537228672809129301u, 6148914691236517205u),
+ MakeUint128(1418980313362273201u, 4256940940086819603u),
+ MakeUint128(1317624576693539401u, 2635249153387078802u),
+ MakeUint128(1229782938247303441u, 1229782938247303441u),
+ MakeUint128(1152921504606846975u, 18446744073709551615u),
+ MakeUint128(1085102592571150095u, 1085102592571150095u),
+ MakeUint128(1024819115206086200u, 16397105843297379214u),
+ MakeUint128(970881267037344821u, 16504981539634861972u),
+ MakeUint128(922337203685477580u, 14757395258967641292u),
+ MakeUint128(878416384462359600u, 14054662151397753612u),
+ MakeUint128(838488366986797800u, 13415813871788764811u),
+ MakeUint128(802032351030850070u, 4812194106185100421u),
+ MakeUint128(768614336404564650u, 12297829382473034410u),
+ MakeUint128(737869762948382064u, 11805916207174113034u),
+ MakeUint128(709490156681136600u, 11351842506898185609u),
+ MakeUint128(683212743470724133u, 17080318586768103348u),
+ MakeUint128(658812288346769700u, 10540996613548315209u),
+ MakeUint128(636094623231363848u, 15266270957552732371u),
+ MakeUint128(614891469123651720u, 9838263505978427528u),
+ MakeUint128(595056260442243600u, 9520900167075897608u),
+ MakeUint128(576460752303423487u, 18446744073709551615u),
+ MakeUint128(558992244657865200u, 8943875914525843207u),
+ MakeUint128(542551296285575047u, 9765923333140350855u),
+ MakeUint128(527049830677415760u, 8432797290838652167u),
+ MakeUint128(512409557603043100u, 8198552921648689607u),
+};
+
+// This kVmaxOverBase generated with
+// for (int base = 2; base < 37; ++base) {
+// absl::int128 max = std::numeric_limits<absl::int128>::max();
+// auto result = max / base;
+// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+// << absl::Int128Low64(result) << "u),\n";
+// }
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVmaxOverBase[] = {
+ 0,
+ 0,
+ MakeInt128(4611686018427387903, 18446744073709551615u),
+ MakeInt128(3074457345618258602, 12297829382473034410u),
+ MakeInt128(2305843009213693951, 18446744073709551615u),
+ MakeInt128(1844674407370955161, 11068046444225730969u),
+ MakeInt128(1537228672809129301, 6148914691236517205u),
+ MakeInt128(1317624576693539401, 2635249153387078802u),
+ MakeInt128(1152921504606846975, 18446744073709551615u),
+ MakeInt128(1024819115206086200, 16397105843297379214u),
+ MakeInt128(922337203685477580, 14757395258967641292u),
+ MakeInt128(838488366986797800, 13415813871788764811u),
+ MakeInt128(768614336404564650, 12297829382473034410u),
+ MakeInt128(709490156681136600, 11351842506898185609u),
+ MakeInt128(658812288346769700, 10540996613548315209u),
+ MakeInt128(614891469123651720, 9838263505978427528u),
+ MakeInt128(576460752303423487, 18446744073709551615u),
+ MakeInt128(542551296285575047, 9765923333140350855u),
+ MakeInt128(512409557603043100, 8198552921648689607u),
+ MakeInt128(485440633518672410, 17475862806672206794u),
+ MakeInt128(461168601842738790, 7378697629483820646u),
+ MakeInt128(439208192231179800, 7027331075698876806u),
+ MakeInt128(419244183493398900, 6707906935894382405u),
+ MakeInt128(401016175515425035, 2406097053092550210u),
+ MakeInt128(384307168202282325, 6148914691236517205u),
+ MakeInt128(368934881474191032, 5902958103587056517u),
+ MakeInt128(354745078340568300, 5675921253449092804u),
+ MakeInt128(341606371735362066, 17763531330238827482u),
+ MakeInt128(329406144173384850, 5270498306774157604u),
+ MakeInt128(318047311615681924, 7633135478776366185u),
+ MakeInt128(307445734561825860, 4919131752989213764u),
+ MakeInt128(297528130221121800, 4760450083537948804u),
+ MakeInt128(288230376151711743, 18446744073709551615u),
+ MakeInt128(279496122328932600, 4471937957262921603u),
+ MakeInt128(271275648142787523, 14106333703424951235u),
+ MakeInt128(263524915338707880, 4216398645419326083u),
+ MakeInt128(256204778801521550, 4099276460824344803u),
+};
+
+// This kVminOverBase generated with
+// for (int base = 2; base < 37; ++base) {
+// absl::int128 min = std::numeric_limits<absl::int128>::min();
+// auto result = min / base;
+// std::cout << "\tMakeInt128(" << absl::Int128High64(result) << ", "
+// << absl::Int128Low64(result) << "u),\n";
+// }
+//
+// See https://godbolt.org/z/7djYWz
+//
+// int128& operator/=(int128) is not constexpr, so hardcode the resulting array
+// to avoid a static initializer.
+template<>
+const int128 LookupTables<int128>::kVminOverBase[] = {
+ 0,
+ 0,
+ MakeInt128(-4611686018427387904, 0u),
+ MakeInt128(-3074457345618258603, 6148914691236517206u),
+ MakeInt128(-2305843009213693952, 0u),
+ MakeInt128(-1844674407370955162, 7378697629483820647u),
+ MakeInt128(-1537228672809129302, 12297829382473034411u),
+ MakeInt128(-1317624576693539402, 15811494920322472814u),
+ MakeInt128(-1152921504606846976, 0u),
+ MakeInt128(-1024819115206086201, 2049638230412172402u),
+ MakeInt128(-922337203685477581, 3689348814741910324u),
+ MakeInt128(-838488366986797801, 5030930201920786805u),
+ MakeInt128(-768614336404564651, 6148914691236517206u),
+ MakeInt128(-709490156681136601, 7094901566811366007u),
+ MakeInt128(-658812288346769701, 7905747460161236407u),
+ MakeInt128(-614891469123651721, 8608480567731124088u),
+ MakeInt128(-576460752303423488, 0u),
+ MakeInt128(-542551296285575048, 8680820740569200761u),
+ MakeInt128(-512409557603043101, 10248191152060862009u),
+ MakeInt128(-485440633518672411, 970881267037344822u),
+ MakeInt128(-461168601842738791, 11068046444225730970u),
+ MakeInt128(-439208192231179801, 11419412998010674810u),
+ MakeInt128(-419244183493398901, 11738837137815169211u),
+ MakeInt128(-401016175515425036, 16040647020617001406u),
+ MakeInt128(-384307168202282326, 12297829382473034411u),
+ MakeInt128(-368934881474191033, 12543785970122495099u),
+ MakeInt128(-354745078340568301, 12770822820260458812u),
+ MakeInt128(-341606371735362067, 683212743470724134u),
+ MakeInt128(-329406144173384851, 13176245766935394012u),
+ MakeInt128(-318047311615681925, 10813608594933185431u),
+ MakeInt128(-307445734561825861, 13527612320720337852u),
+ MakeInt128(-297528130221121801, 13686293990171602812u),
+ MakeInt128(-288230376151711744, 0u),
+ MakeInt128(-279496122328932601, 13974806116446630013u),
+ MakeInt128(-271275648142787524, 4340410370284600381u),
+ MakeInt128(-263524915338707881, 14230345428290225533u),
+ MakeInt128(-256204778801521551, 14347467612885206813u),
+};
+
template <typename IntType>
const IntType LookupTables<IntType>::kVmaxOverBase[] =
X_OVER_BASE_INITIALIZER(std::numeric_limits<IntType>::max());
@@ -796,6 +922,8 @@ inline bool safe_parse_positive_int(absl::string_view text, int base,
assert(base >= 0);
assert(vmax >= static_cast<IntType>(base));
const IntType vmax_over_base = LookupTables<IntType>::kVmaxOverBase[base];
+ assert(base < 2 ||
+ std::numeric_limits<IntType>::max() / base == vmax_over_base);
const char* start = text.data();
const char* end = start + text.size();
// loop over digits
@@ -829,6 +957,8 @@ inline bool safe_parse_negative_int(absl::string_view text, int base,
assert(vmin < 0);
assert(vmin <= 0 - base);
IntType vmin_over_base = LookupTables<IntType>::kVminOverBase[base];
+ assert(base < 2 ||
+ std::numeric_limits<IntType>::min() / base == vmin_over_base);
// 2003 c++ standard [expr.mul]
// "... the sign of the remainder is implementation-defined."
// Although (vmin/base)*base + vmin%base is always vmin.
@@ -892,6 +1022,48 @@ inline bool safe_uint_internal(absl::string_view text, IntType* value_p,
} // anonymous namespace
namespace numbers_internal {
+
+// Digit conversion.
+ABSL_CONST_INIT ABSL_DLL const char kHexChar[] =
+ "0123456789abcdef";
+
+ABSL_CONST_INIT ABSL_DLL const char kHexTable[513] =
+ "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+ABSL_CONST_INIT ABSL_DLL const char two_ASCII_digits[100][2] = {
+ {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
+ {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
+ {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
+ {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
+ {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
+ {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
+ {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
+ {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
+ {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
+ {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
+ {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
+ {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
+ {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
+ {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
+ {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
+ {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
+ {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
+
bool safe_strto32_base(absl::string_view text, int32_t* value, int base) {
return safe_int_internal<int32_t>(text, value, base);
}
@@ -900,6 +1072,10 @@ bool safe_strto64_base(absl::string_view text, int64_t* value, int base) {
return safe_int_internal<int64_t>(text, value, base);
}
+bool safe_strto128_base(absl::string_view text, int128* value, int base) {
+ return safe_int_internal<absl::int128>(text, value, base);
+}
+
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
return safe_uint_internal<uint32_t>(text, value, base);
}
@@ -907,6 +1083,11 @@ bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base) {
bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base) {
return safe_uint_internal<uint64_t>(text, value, base);
}
-} // namespace numbers_internal
+bool safe_strtou128_base(absl::string_view text, uint128* value, int base) {
+ return safe_uint_internal<absl::uint128>(text, value, base);
+}
+
+} // namespace numbers_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.h
index f9b2ccef94d..1780bb44bd5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers.h
@@ -1,11 +1,10 @@
-//
// 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
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +23,10 @@
#ifndef ABSL_STRINGS_NUMBERS_H_
#define ABSL_STRINGS_NUMBERS_H_
+#ifdef __SSE4_2__
+#include <x86intrin.h>
+#endif
+
#include <cstddef>
#include <cstdlib>
#include <cstring>
@@ -32,58 +35,104 @@
#include <string>
#include <type_traits>
+#include "absl/base/config.h"
+#ifdef __SSE4_2__
+// TODO(jorg): Remove this when we figure out the right way
+// to swap bytes on SSE 4.2 that works with the compilers
+// we claim to support. Also, add tests for the compiler
+// that doesn't support the Intel _bswap64 intrinsic but
+// does support all the SSE 4.2 intrinsics
+#include "absl/base/internal/endian.h"
+#endif
#include "absl/base/macros.h"
#include "absl/base/port.h"
+#include "absl/numeric/bits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// SimpleAtoi()
//
-// Converts the given string into an integer value, returning `true` if
-// successful. The string must reflect a base-10 integer (optionally followed or
-// preceded by ASCII whitespace) whose value falls within the range of the
-// integer type.
+// Converts the given string (optionally followed or preceded by ASCII
+// whitespace) into an integer value, returning `true` if successful. The string
+// must reflect a base-10 integer whose value falls within the range of the
+// integer type (optionally preceded by a `+` or `-`). If any errors are
+// encountered, this function returns `false`, leaving `out` in an unspecified
+// state.
template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out);
+ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out);
// SimpleAtof()
//
// Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a float, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* value);
+// whitespace) into a float, which may be rounded on overflow or underflow,
+// returning `true` if successful.
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`, except SimpleAtof() is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtof(absl::string_view str, float* out);
// SimpleAtod()
//
// Converts the given string (optionally followed or preceded by ASCII
-// whitespace) into a double, which may be rounded on overflow or underflow.
-// See http://en.cppreference.com/w/c/string/byte/strtof for details about the
-// allowed formats for `str`.
-ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* value);
+// whitespace) into a double, which may be rounded on overflow or underflow,
+// returning `true` if successful.
+// See https://en.cppreference.com/w/c/string/byte/strtof for details about the
+// allowed formats for `str`, except SimpleAtod is locale-independent and will
+// always use the "C" locale. If any errors are encountered, this function
+// returns `false`, leaving `out` in an unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
// SimpleAtob()
//
// Converts the given string into a boolean, returning `true` if successful.
// The following case-insensitive strings are interpreted as boolean `true`:
// "true", "t", "yes", "y", "1". The following case-insensitive strings
-// are interpreted as boolean `false`: "false", "f", "no", "n", "0".
-ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* value);
+// are interpreted as boolean `false`: "false", "f", "no", "n", "0". If any
+// errors are encountered, this function returns `false`, leaving `out` in an
+// unspecified state.
+ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
+ABSL_NAMESPACE_END
} // namespace absl
// End of public API. Implementation details follow.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace numbers_internal {
+// Digit conversion.
+ABSL_DLL extern const char kHexChar[17]; // 0123456789abcdef
+ABSL_DLL extern const char
+ kHexTable[513]; // 000102030405060708090a0b0c0d0e0f1011...
+ABSL_DLL extern const char
+ two_ASCII_digits[100][2]; // 00, 01, 02, 03...
+
+// Writes a two-character representation of 'i' to 'buf'. 'i' must be in the
+// range 0 <= i < 100, and buf must have space for two characters. Example:
+// char buf[2];
+// PutTwoDigits(42, buf);
+// // buf[0] == '4'
+// // buf[1] == '2'
+inline void PutTwoDigits(size_t i, char* buf) {
+ assert(i < 100);
+ memcpy(buf, two_ASCII_digits[i], 2);
+}
+
// safe_strto?() functions for implementing SimpleAtoi()
+
bool safe_strto32_base(absl::string_view text, int32_t* value, int base);
bool safe_strto64_base(absl::string_view text, int64_t* value, int base);
+bool safe_strto128_base(absl::string_view text, absl::int128* value,
+ int base);
bool safe_strtou32_base(absl::string_view text, uint32_t* value, int base);
bool safe_strtou64_base(absl::string_view text, uint64_t* value, int base);
+bool safe_strtou128_base(absl::string_view text, absl::uint128* value,
+ int base);
static const int kFastToBufferSize = 32;
static const int kSixDigitsToBufferSize = 16;
@@ -165,20 +214,53 @@ ABSL_MUST_USE_RESULT bool safe_strtoi_base(absl::string_view s, int_type* out,
return parsed;
}
+// FastHexToBufferZeroPad16()
+//
+// Outputs `val` into `out` as if by `snprintf(out, 17, "%016x", val)` but
+// without the terminating null character. Thus `out` must be of length >= 16.
+// Returns the number of non-pad digits of the output (it can never be zero
+// since 0 has one digit).
+inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
+#ifdef __SSE4_2__
+ uint64_t be = absl::big_endian::FromHost64(val);
+ const auto kNibbleMask = _mm_set1_epi8(0xf);
+ const auto kHexDigits = _mm_setr_epi8('0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
+ auto v = _mm_loadl_epi64(reinterpret_cast<__m128i*>(&be)); // load lo dword
+ auto v4 = _mm_srli_epi64(v, 4); // shift 4 right
+ auto il = _mm_unpacklo_epi8(v4, v); // interleave bytes
+ auto m = _mm_and_si128(il, kNibbleMask); // mask out nibbles
+ auto hexchars = _mm_shuffle_epi8(kHexDigits, m); // hex chars
+ _mm_storeu_si128(reinterpret_cast<__m128i*>(out), hexchars);
+#else
+ for (int i = 0; i < 8; ++i) {
+ auto byte = (val >> (56 - 8 * i)) & 0xFF;
+ auto* hex = &absl::numbers_internal::kHexTable[byte * 2];
+ std::memcpy(out + 2 * i, hex, 2);
+ }
+#endif
+ // | 0x1 so that even 0 has 1 digit.
+ return 16 - countl_zero(val | 0x1) / 4;
+}
+
} // namespace numbers_internal
-// SimpleAtoi()
-//
-// Converts a string to an integer, using `safe_strto?()` functions for actual
-// parsing, returning `true` if successful. The `safe_strto?()` functions apply
-// strict checking; the string must be a base-10 integer, optionally followed or
-// preceded by ASCII whitespace, with a value in the range of the corresponding
-// integer type.
template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view s, int_type* out) {
- return numbers_internal::safe_strtoi_base(s, out, 10);
+ABSL_MUST_USE_RESULT bool SimpleAtoi(absl::string_view str, int_type* out) {
+ return numbers_internal::safe_strtoi_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+ absl::int128* out) {
+ return numbers_internal::safe_strto128_base(str, out, 10);
+}
+
+ABSL_MUST_USE_RESULT inline bool SimpleAtoi(absl::string_view str,
+ absl::uint128* out) {
+ return numbers_internal::safe_strtou128_base(str, out, 10);
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_NUMBERS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_benchmark.cc
index 0570b758633..6e79b3e811f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,6 +20,8 @@
#include "benchmark/benchmark.h"
#include "absl/base/internal/raw_logging.h"
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
#include "absl/strings/numbers.h"
namespace {
@@ -260,4 +262,25 @@ BENCHMARK_TEMPLATE(BM_SimpleAtod, std::string)
->ArgPair(10, 4)
->ArgPair(10, 8);
+void BM_FastHexToBufferZeroPad16(benchmark::State& state) {
+ absl::BitGen rng;
+ std::vector<uint64_t> nums;
+ nums.resize(1000);
+ auto min = std::numeric_limits<uint64_t>::min();
+ auto max = std::numeric_limits<uint64_t>::max();
+ for (auto& num : nums) {
+ num = absl::LogUniform(rng, min, max);
+ }
+
+ char buf[16];
+ while (state.KeepRunningBatch(nums.size())) {
+ for (auto num : nums) {
+ auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(num, buf);
+ benchmark::DoNotOptimize(digits);
+ benchmark::DoNotOptimize(buf);
+ }
+ }
+}
+BENCHMARK(BM_FastHexToBufferZeroPad16);
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_test.cc
index 099326c270a..f3103106b44 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/numbers_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/strings/numbers.h"
#include <sys/types.h>
+
#include <cfenv> // NOLINT(build/c++11)
#include <cinttypes>
#include <climits>
@@ -36,13 +37,16 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/str_cat.h"
-
+#include "absl/random/distributions.h"
+#include "absl/random/random.h"
#include "absl/strings/internal/numbers_test_common.h"
+#include "absl/strings/internal/ostringstream.h"
#include "absl/strings/internal/pow10_helper.h"
+#include "absl/strings/str_cat.h"
namespace {
+using absl::SimpleAtoi;
using absl::numbers_internal::kSixDigitsToBufferSize;
using absl::numbers_internal::safe_strto32_base;
using absl::numbers_internal::safe_strto64_base;
@@ -52,7 +56,6 @@ using absl::numbers_internal::SixDigitsToBuffer;
using absl::strings_internal::Itoa;
using absl::strings_internal::strtouint32_test_cases;
using absl::strings_internal::strtouint64_test_cases;
-using absl::SimpleAtoi;
using testing::Eq;
using testing::MatchesRegex;
@@ -191,7 +194,8 @@ void CheckUInt64(uint64_t x) {
EXPECT_EQ(expected, std::string(&buffer[1], actual)) << " Input " << x;
char* generic_actual = absl::numbers_internal::FastIntToBuffer(x, &buffer[1]);
- EXPECT_EQ(expected, std::string(&buffer[1], generic_actual)) << " Input " << x;
+ EXPECT_EQ(expected, std::string(&buffer[1], generic_actual))
+ << " Input " << x;
char* my_actual =
absl::numbers_internal::FastIntToBuffer(MyUInt64(x), &buffer[1]);
@@ -203,6 +207,9 @@ void CheckHex64(uint64_t v) {
std::string actual = absl::StrCat(absl::Hex(v, absl::kZeroPad16));
snprintf(expected, sizeof(expected), "%016" PRIx64, static_cast<uint64_t>(v));
EXPECT_EQ(expected, actual) << " Input " << v;
+ actual = absl::StrCat(absl::Hex(v, absl::kSpacePad16));
+ snprintf(expected, sizeof(expected), "%16" PRIx64, static_cast<uint64_t>(v));
+ EXPECT_EQ(expected, actual) << " Input " << v;
}
TEST(Numbers, TestFastPrints) {
@@ -243,7 +250,9 @@ TEST(Numbers, TestFastPrints) {
template <typename int_type, typename in_val_type>
void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
- std::string s = absl::StrCat(in_value);
+ std::string s;
+ // (u)int128 can be streamed but not StrCat'd.
+ absl::strings_internal::OStringStream(&s) << in_value;
int_type x = static_cast<int_type>(~exp_value);
EXPECT_TRUE(SimpleAtoi(s, &x))
<< "in_value=" << in_value << " s=" << s << " x=" << x;
@@ -255,7 +264,9 @@ void VerifySimpleAtoiGood(in_val_type in_value, int_type exp_value) {
template <typename int_type, typename in_val_type>
void VerifySimpleAtoiBad(in_val_type in_value) {
- std::string s = absl::StrCat(in_value);
+ std::string s;
+ // (u)int128 can be streamed but not StrCat'd.
+ absl::strings_internal::OStringStream(&s) << in_value;
int_type x;
EXPECT_FALSE(SimpleAtoi(s, &x));
EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
@@ -319,18 +330,90 @@ TEST(NumbersTest, Atoi) {
VerifySimpleAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max());
+ // SimpleAtoi(absl::string_view, absl::uint128)
+ VerifySimpleAtoiGood<absl::uint128>(0, 0);
+ VerifySimpleAtoiGood<absl::uint128>(42, 42);
+ VerifySimpleAtoiBad<absl::uint128>(-42);
+
+ VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
+ VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
+ std::numeric_limits<int32_t>::max());
+ VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
+ std::numeric_limits<uint32_t>::max());
+ VerifySimpleAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
+ VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
+ std::numeric_limits<int64_t>::max());
+ VerifySimpleAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
+ std::numeric_limits<uint64_t>::max());
+ VerifySimpleAtoiGood<absl::uint128>(
+ std::numeric_limits<absl::uint128>::max(),
+ std::numeric_limits<absl::uint128>::max());
+
+ // SimpleAtoi(absl::string_view, absl::int128)
+ VerifySimpleAtoiGood<absl::int128>(0, 0);
+ VerifySimpleAtoiGood<absl::int128>(42, 42);
+ VerifySimpleAtoiGood<absl::int128>(-42, -42);
+
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::min(),
+ std::numeric_limits<int32_t>::min());
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int32_t>::max(),
+ std::numeric_limits<int32_t>::max());
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint32_t>::max(),
+ std::numeric_limits<uint32_t>::max());
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::min(),
+ std::numeric_limits<int64_t>::min());
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<int64_t>::max(),
+ std::numeric_limits<int64_t>::max());
+ VerifySimpleAtoiGood<absl::int128>(std::numeric_limits<uint64_t>::max(),
+ std::numeric_limits<uint64_t>::max());
+ VerifySimpleAtoiGood<absl::int128>(
+ std::numeric_limits<absl::int128>::min(),
+ std::numeric_limits<absl::int128>::min());
+ VerifySimpleAtoiGood<absl::int128>(
+ std::numeric_limits<absl::int128>::max(),
+ std::numeric_limits<absl::int128>::max());
+ VerifySimpleAtoiBad<absl::int128>(std::numeric_limits<absl::uint128>::max());
+
// Some other types
VerifySimpleAtoiGood<int>(-42, -42);
VerifySimpleAtoiGood<int32_t>(-42, -42);
VerifySimpleAtoiGood<uint32_t>(42, 42);
VerifySimpleAtoiGood<unsigned int>(42, 42);
VerifySimpleAtoiGood<int64_t>(-42, -42);
- VerifySimpleAtoiGood<long>(-42, -42); // NOLINT(runtime/int)
+ VerifySimpleAtoiGood<long>(-42, -42); // NOLINT: runtime-int
VerifySimpleAtoiGood<uint64_t>(42, 42);
VerifySimpleAtoiGood<size_t>(42, 42);
VerifySimpleAtoiGood<std::string::size_type>(42, 42);
}
+TEST(NumbersTest, Atod) {
+ double d;
+ EXPECT_TRUE(absl::SimpleAtod("nan", &d));
+ EXPECT_TRUE(std::isnan(d));
+}
+
+TEST(NumbersTest, Prefixes) {
+ double d;
+ EXPECT_FALSE(absl::SimpleAtod("++1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("+-1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("-+1", &d));
+ EXPECT_FALSE(absl::SimpleAtod("--1", &d));
+ EXPECT_TRUE(absl::SimpleAtod("-1", &d));
+ EXPECT_EQ(d, -1.);
+ EXPECT_TRUE(absl::SimpleAtod("+1", &d));
+ EXPECT_EQ(d, +1.);
+
+ float f;
+ EXPECT_FALSE(absl::SimpleAtof("++1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("+-1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("-+1", &f));
+ EXPECT_FALSE(absl::SimpleAtof("--1", &f));
+ EXPECT_TRUE(absl::SimpleAtof("-1", &f));
+ EXPECT_EQ(f, -1.f);
+ EXPECT_TRUE(absl::SimpleAtof("+1", &f));
+ EXPECT_EQ(f, +1.f);
+}
+
TEST(NumbersTest, Atoenum) {
enum E01 {
E01_zero = 0,
@@ -454,7 +537,7 @@ TEST(stringtest, safe_strto32_base) {
EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
- // Base-10 std::string version.
+ // Base-10 string version.
EXPECT_TRUE(safe_strto32_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
@@ -595,7 +678,7 @@ TEST(stringtest, safe_strto64_base) {
EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
- // Base-10 std::string version.
+ // Base-10 string version.
EXPECT_TRUE(safe_strto64_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
@@ -651,6 +734,91 @@ TEST(stringtest, safe_strtou32_random) {
TEST(stringtest, safe_strtou64_random) {
test_random_integer_parse_base<uint64_t>(&safe_strtou64_base);
}
+TEST(stringtest, safe_strtou128_random) {
+ // random number generators don't work for uint128, and
+ // uint128 can be streamed but not StrCat'd, so this code must be custom
+ // implemented for uint128, but is generally the same as what's above.
+ // test_random_integer_parse_base<absl::uint128>(
+ // &absl::numbers_internal::safe_strtou128_base);
+ using RandomEngine = std::minstd_rand0;
+ using IntType = absl::uint128;
+ constexpr auto parse_func = &absl::numbers_internal::safe_strtou128_base;
+
+ std::random_device rd;
+ RandomEngine rng(rd());
+ std::uniform_int_distribution<uint64_t> random_uint64(
+ std::numeric_limits<uint64_t>::min());
+ std::uniform_int_distribution<int> random_base(2, 35);
+
+ for (size_t i = 0; i < kNumRandomTests; i++) {
+ IntType value = random_uint64(rng);
+ value = (value << 64) + random_uint64(rng);
+ int base = random_base(rng);
+ std::string str_value;
+ EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+ IntType parsed_value;
+
+ // Test successful parse
+ EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+ EXPECT_EQ(parsed_value, value);
+
+ // Test overflow
+ std::string s;
+ absl::strings_internal::OStringStream(&s)
+ << std::numeric_limits<IntType>::max() << value;
+ EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+ // Test underflow
+ s.clear();
+ absl::strings_internal::OStringStream(&s) << "-" << value;
+ EXPECT_FALSE(parse_func(s, &parsed_value, base));
+ }
+}
+TEST(stringtest, safe_strto128_random) {
+ // random number generators don't work for int128, and
+ // int128 can be streamed but not StrCat'd, so this code must be custom
+ // implemented for int128, but is generally the same as what's above.
+ // test_random_integer_parse_base<absl::int128>(
+ // &absl::numbers_internal::safe_strto128_base);
+ using RandomEngine = std::minstd_rand0;
+ using IntType = absl::int128;
+ constexpr auto parse_func = &absl::numbers_internal::safe_strto128_base;
+
+ std::random_device rd;
+ RandomEngine rng(rd());
+ std::uniform_int_distribution<int64_t> random_int64(
+ std::numeric_limits<int64_t>::min());
+ std::uniform_int_distribution<uint64_t> random_uint64(
+ std::numeric_limits<uint64_t>::min());
+ std::uniform_int_distribution<int> random_base(2, 35);
+
+ for (size_t i = 0; i < kNumRandomTests; ++i) {
+ int64_t high = random_int64(rng);
+ uint64_t low = random_uint64(rng);
+ IntType value = absl::MakeInt128(high, low);
+
+ int base = random_base(rng);
+ std::string str_value;
+ EXPECT_TRUE(Itoa<IntType>(value, base, &str_value));
+ IntType parsed_value;
+
+ // Test successful parse
+ EXPECT_TRUE(parse_func(str_value, &parsed_value, base));
+ EXPECT_EQ(parsed_value, value);
+
+ // Test overflow
+ std::string s;
+ absl::strings_internal::OStringStream(&s)
+ << std::numeric_limits<IntType>::max() << value;
+ EXPECT_FALSE(parse_func(s, &parsed_value, base));
+
+ // Test underflow
+ s.clear();
+ absl::strings_internal::OStringStream(&s)
+ << std::numeric_limits<IntType>::min() << value;
+ EXPECT_FALSE(parse_func(s, &parsed_value, base));
+ }
+}
TEST(stringtest, safe_strtou32_base) {
for (int i = 0; strtouint32_test_cases()[i].str != nullptr; ++i) {
@@ -712,11 +880,11 @@ TEST(stringtest, safe_strtou64_base_length_delimited) {
}
}
-// feenableexcept() and fedisableexcept() are missing on Mac OS X, MSVC,
-// and WebAssembly.
-#if defined(_MSC_VER) || defined(__APPLE__) || defined(__EMSCRIPTEN__)
-#define ABSL_MISSING_FEENABLEEXCEPT 1
-#define ABSL_MISSING_FEDISABLEEXCEPT 1
+// feenableexcept() and fedisableexcept() are extensions supported by some libc
+// implementations.
+#if defined(__GLIBC__) || defined(__BIONIC__)
+#define ABSL_HAVE_FEENABLEEXCEPT 1
+#define ABSL_HAVE_FEDISABLEEXCEPT 1
#endif
class SimpleDtoaTest : public testing::Test {
@@ -724,7 +892,7 @@ class SimpleDtoaTest : public testing::Test {
void SetUp() override {
// Store the current floating point env & clear away any pending exceptions.
feholdexcept(&fp_env_);
-#ifndef ABSL_MISSING_FEENABLEEXCEPT
+#ifdef ABSL_HAVE_FEENABLEEXCEPT
// Turn on floating point exceptions.
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
@@ -734,7 +902,7 @@ class SimpleDtoaTest : public testing::Test {
// Restore the floating point environment to the original state.
// In theory fedisableexcept is unnecessary; fesetenv will also do it.
// In practice, our toolchains have subtle bugs.
-#ifndef ABSL_MISSING_FEDISABLEEXCEPT
+#ifdef ABSL_HAVE_FEDISABLEEXCEPT
fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
fesetenv(&fp_env_);
@@ -784,7 +952,7 @@ void ExhaustiveFloat(uint32_t cases, R&& runnable) {
if (iters_per_float == 0) iters_per_float = 1;
for (float f : floats) {
if (f == last) continue;
- float testf = nextafter(last, std::numeric_limits<float>::max());
+ float testf = std::nextafter(last, std::numeric_limits<float>::max());
runnable(testf);
runnable(-testf);
last = testf;
@@ -798,7 +966,7 @@ void ExhaustiveFloat(uint32_t cases, R&& runnable) {
last = testf;
}
}
- testf = nextafter(f, 0.0f);
+ testf = std::nextafter(f, 0.0f);
if (testf > last) {
runnable(testf);
runnable(-testf);
@@ -879,8 +1047,8 @@ TEST_F(SimpleDtoaTest, ExhaustiveDoubleToSixDigits) {
char buf[kSixDigitsToBufferSize];
ABSL_RAW_LOG(
INFO, "%s",
- absl::StrCat("Exp ", exponent, " powten=", powten, "(",
- powten, ") (",
+ absl::StrCat("Exp ", exponent, " powten=", powten, "(", powten,
+ ") (",
std::string(buf, SixDigitsToBuffer(powten, buf)), ")")
.c_str());
}
@@ -1183,4 +1351,28 @@ TEST(StrToUint64Base, PrefixOnly) {
}
}
+void TestFastHexToBufferZeroPad16(uint64_t v) {
+ char buf[16];
+ auto digits = absl::numbers_internal::FastHexToBufferZeroPad16(v, buf);
+ absl::string_view res(buf, 16);
+ char buf2[17];
+ snprintf(buf2, sizeof(buf2), "%016" PRIx64, v);
+ EXPECT_EQ(res, buf2) << v;
+ size_t expected_digits = snprintf(buf2, sizeof(buf2), "%" PRIx64, v);
+ EXPECT_EQ(digits, expected_digits) << v;
+}
+
+TEST(FastHexToBufferZeroPad16, Smoke) {
+ TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::min());
+ TestFastHexToBufferZeroPad16(std::numeric_limits<uint64_t>::max());
+ TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::min());
+ TestFastHexToBufferZeroPad16(std::numeric_limits<int64_t>::max());
+ absl::BitGen rng;
+ for (int i = 0; i < 100000; ++i) {
+ TestFastHexToBufferZeroPad16(
+ absl::LogUniform(rng, std::numeric_limits<uint64_t>::min(),
+ std::numeric_limits<uint64_t>::max()));
+ }
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.cc
index b14d571ff24..dd5d25b0d6d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,34 +15,34 @@
#include "absl/strings/str_cat.h"
#include <assert.h>
+
#include <algorithm>
#include <cstdint>
#include <cstring>
#include "absl/strings/ascii.h"
#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/numbers.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
AlphaNum::AlphaNum(Hex hex) {
+ static_assert(numbers_internal::kFastToBufferSize >= 32,
+ "This function only works when output buffer >= 32 bytes long");
char* const end = &digits_[numbers_internal::kFastToBufferSize];
- char* writer = end;
- uint64_t value = hex.value;
- static const char hexdigits[] = "0123456789abcdef";
- do {
- *--writer = hexdigits[value & 0xF];
- value >>= 4;
- } while (value != 0);
-
- char* beg;
- if (end - writer < hex.width) {
- beg = end - hex.width;
- std::fill_n(beg, writer - beg, hex.fill);
+ auto real_width =
+ absl::numbers_internal::FastHexToBufferZeroPad16(hex.value, end - 16);
+ if (real_width >= hex.width) {
+ piece_ = absl::string_view(end - real_width, real_width);
} else {
- beg = writer;
+ // Pad first 16 chars because FastHexToBufferZeroPad16 pads only to 16 and
+ // max pad width can be up to 20.
+ std::memset(end - 32, hex.fill, 16);
+ // Patch up everything else up to the real_width.
+ std::memset(end - real_width - 16, hex.fill, 16);
+ piece_ = absl::string_view(end - hex.width, hex.width);
}
-
- piece_ = absl::string_view(beg, end - beg);
}
AlphaNum::AlphaNum(Dec dec) {
@@ -78,7 +78,7 @@ AlphaNum::AlphaNum(Dec dec) {
// ----------------------------------------------------------------------
// StrCat()
-// This merges the given strings or integers, with no delimiter. This
+// This merges the given strings or integers, with no delimiter. This
// is designed to be the fastest possible way to construct a string out
// of a mix of raw C strings, string_views, strings, and integer values.
// ----------------------------------------------------------------------
@@ -89,7 +89,9 @@ static char* Append(char* out, const AlphaNum& x) {
// memcpy is allowed to overwrite arbitrary memory, so doing this after the
// call would force an extra fetch of x.size().
char* after = out + x.size();
- memcpy(out, x.data(), x.size());
+ if (x.size() != 0) {
+ memcpy(out, x.data(), x.size());
+ }
return after;
}
@@ -97,7 +99,7 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b) {
std::string result;
absl::strings_internal::STLStringResizeUninitialized(&result,
a.size() + b.size());
- char* const begin = &*result.begin();
+ char* const begin = &result[0];
char* out = begin;
out = Append(out, a);
out = Append(out, b);
@@ -109,7 +111,7 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
std::string result;
strings_internal::STLStringResizeUninitialized(
&result, a.size() + b.size() + c.size());
- char* const begin = &*result.begin();
+ char* const begin = &result[0];
char* out = begin;
out = Append(out, a);
out = Append(out, b);
@@ -119,11 +121,11 @@ std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c) {
}
std::string StrCat(const AlphaNum& a, const AlphaNum& b, const AlphaNum& c,
- const AlphaNum& d) {
+ const AlphaNum& d) {
std::string result;
strings_internal::STLStringResizeUninitialized(
&result, a.size() + b.size() + c.size() + d.size());
- char* const begin = &*result.begin();
+ char* const begin = &result[0];
char* out = begin;
out = Append(out, a);
out = Append(out, b);
@@ -139,15 +141,17 @@ namespace strings_internal {
std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
std::string result;
size_t total_size = 0;
- for (const absl::string_view piece : pieces) total_size += piece.size();
+ for (const absl::string_view& piece : pieces) total_size += piece.size();
strings_internal::STLStringResizeUninitialized(&result, total_size);
- char* const begin = &*result.begin();
+ char* const begin = &result[0];
char* out = begin;
- for (const absl::string_view piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
const size_t this_size = piece.size();
- memcpy(out, piece.data(), this_size);
- out += this_size;
+ if (this_size != 0) {
+ memcpy(out, piece.data(), this_size);
+ out += this_size;
+ }
}
assert(out == begin + result.size());
return result;
@@ -166,18 +170,20 @@ void AppendPieces(std::string* dest,
std::initializer_list<absl::string_view> pieces) {
size_t old_size = dest->size();
size_t total_size = old_size;
- for (const absl::string_view piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
ASSERT_NO_OVERLAP(*dest, piece);
total_size += piece.size();
}
strings_internal::STLStringResizeUninitialized(dest, total_size);
- char* const begin = &*dest->begin();
+ char* const begin = &(*dest)[0];
char* out = begin + old_size;
- for (const absl::string_view piece : pieces) {
+ for (const absl::string_view& piece : pieces) {
const size_t this_size = piece.size();
- memcpy(out, piece.data(), this_size);
- out += this_size;
+ if (this_size != 0) {
+ memcpy(out, piece.data(), this_size);
+ out += this_size;
+ }
}
assert(out == begin + dest->size());
}
@@ -195,7 +201,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) {
std::string::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size());
- char* const begin = &*dest->begin();
+ char* const begin = &(*dest)[0];
char* out = begin + old_size;
out = Append(out, a);
out = Append(out, b);
@@ -210,7 +216,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
std::string::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size() + c.size());
- char* const begin = &*dest->begin();
+ char* const begin = &(*dest)[0];
char* out = begin + old_size;
out = Append(out, a);
out = Append(out, b);
@@ -227,7 +233,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
std::string::size_type old_size = dest->size();
strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size() + c.size() + d.size());
- char* const begin = &*dest->begin();
+ char* const begin = &(*dest)[0];
char* out = begin + old_size;
out = Append(out, a);
out = Append(out, b);
@@ -236,4 +242,5 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
assert(out == begin + dest->size());
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.h
index 8ba0592fdaa..a8a85c7322b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -37,12 +37,12 @@
// attempt to pass ':' instead of ":" might result in a 58 ending up in your
// result.
//
-// Bools convert to "0" or "1".
+// Bools convert to "0" or "1". Pointers to types other than `char *` are not
+// valid inputs. No output is generated for null `char *` pointers.
//
// Floating point numbers are formatted with six-digit precision, which is
// the default for "std::cout <<" or printf "%g" (the same as "%.6g").
//
-//
// You can convert to hexadecimal output rather than decimal output using the
// `Hex` type contained here. To do so, pass `Hex(my_int)` as a parameter to
// `StrCat()` or `StrAppend()`. You may specify a minimum hex field width using
@@ -57,12 +57,14 @@
#include <cstdint>
#include <string>
#include <type_traits>
+#include <vector>
#include "absl/base/port.h"
#include "absl/strings/numbers.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// AlphaNumBuffer allows a way to pass a string to StrCat without having to do
@@ -78,8 +80,8 @@ struct AlphaNumBuffer {
// Enum that specifies the number of significant digits to return in a `Hex` or
// `Dec` conversion and fill character to use. A `kZeroPad2` value, for example,
-// would produce hexadecimal strings such as "0A","0F" and a 'kSpacePad5' value
-// would produce hexadecimal strings such as " A"," F".
+// would produce hexadecimal strings such as "0a","0f" and a 'kSpacePad5' value
+// would produce hexadecimal strings such as " a"," f".
enum PadSpec : uint8_t {
kNoPad = 1,
kZeroPad2,
@@ -245,12 +247,13 @@ class AlphaNum {
AlphaNum(const char* c_str) : piece_(c_str) {} // NOLINT(runtime/explicit)
AlphaNum(absl::string_view pc) : piece_(pc) {} // NOLINT(runtime/explicit)
+
template <typename Allocator>
AlphaNum( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
: piece_(str) {}
- // Use std::string literals ":" instead of character literals ':'.
+ // Use string literals ":" instead of character literals ':'.
AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
AlphaNum(const AlphaNum&) = delete;
@@ -268,6 +271,17 @@ class AlphaNum {
AlphaNum(T e) // NOLINT(runtime/explicit)
: AlphaNum(static_cast<typename std::underlying_type<T>::type>(e)) {}
+ // vector<bool>::reference and const_reference require special help to
+ // convert to `AlphaNum` because it requires two user defined conversions.
+ template <
+ typename T,
+ typename std::enable_if<
+ std::is_class<T>::value &&
+ (std::is_same<T, std::vector<bool>::reference>::value ||
+ std::is_same<T, std::vector<bool>::const_reference>::value)>::type* =
+ nullptr>
+ AlphaNum(T e) : AlphaNum(static_cast<bool>(e)) {} // NOLINT(runtime/explicit)
+
private:
absl::string_view piece_;
char digits_[numbers_internal::kFastToBufferSize];
@@ -277,7 +291,8 @@ class AlphaNum {
// StrCat()
// -----------------------------------------------------------------------------
//
-// Merges given strings or numbers, using no delimiter(s).
+// Merges given strings or numbers, using no delimiter(s), returning the merged
+// result as a string.
//
// `StrCat()` is designed to be the fastest possible way to construct a string
// out of a mix of raw C strings, string_views, strings, bool values,
@@ -317,16 +332,15 @@ ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a) {
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b);
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c);
+ const AlphaNum& c);
ABSL_MUST_USE_RESULT std::string StrCat(const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d);
+ const AlphaNum& c, const AlphaNum& d);
// Support 5 or more arguments
template <typename... AV>
-ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum& b,
- const AlphaNum& c, const AlphaNum& d,
- const AlphaNum& e,
- const AV&... args) {
+ABSL_MUST_USE_RESULT inline std::string StrCat(
+ const AlphaNum& a, const AlphaNum& b, const AlphaNum& c, const AlphaNum& d,
+ const AlphaNum& e, const AV&... args) {
return strings_internal::CatPieces(
{a.Piece(), b.Piece(), c.Piece(), d.Piece(), e.Piece(),
static_cast<const AlphaNum&>(args).Piece()...});
@@ -344,18 +358,18 @@ ABSL_MUST_USE_RESULT inline std::string StrCat(const AlphaNum& a, const AlphaNum
// not try to check each of its input arguments to be sure that they are not
// a subset of the string being appended to. That is, while this will work:
//
-// string s = "foo";
+// std::string s = "foo";
// s += s;
//
// This output is undefined:
//
-// string s = "foo";
+// std::string s = "foo";
// StrAppend(&s, s);
//
// This output is undefined as well, since `absl::string_view` does not own its
// data:
//
-// string s = "foobar";
+// std::string s = "foobar";
// absl::string_view p = s;
// StrAppend(&s, p);
@@ -388,6 +402,7 @@ SixDigits(double d) {
return result;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_CAT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_benchmark.cc
index b6df9e309c4..02c4dbe6d8f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,7 +23,7 @@
namespace {
const char kStringOne[] = "Once Upon A Time, ";
-const char kStringTwo[] = "There was a std::string benchmark";
+const char kStringTwo[] = "There was a string benchmark";
// We want to include negative numbers in the benchmark, so this function
// is used to count 0, 1, -1, 2, -2, 3, -3, ...
@@ -137,4 +137,51 @@ void BM_DoubleToString_By_SixDigits(benchmark::State& state) {
}
BENCHMARK(BM_DoubleToString_By_SixDigits);
+template <typename... Chunks>
+void BM_StrAppendImpl(benchmark::State& state, size_t total_bytes,
+ Chunks... chunks) {
+ for (auto s : state) {
+ std::string result;
+ while (result.size() < total_bytes) {
+ absl::StrAppend(&result, chunks...);
+ benchmark::DoNotOptimize(result);
+ }
+ }
+}
+
+void BM_StrAppend(benchmark::State& state) {
+ const int total_bytes = state.range(0);
+ const int chunks_at_a_time = state.range(1);
+ const absl::string_view kChunk = "0123456789";
+
+ switch (chunks_at_a_time) {
+ case 1:
+ return BM_StrAppendImpl(state, total_bytes, kChunk);
+ case 2:
+ return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk);
+ case 4:
+ return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+ kChunk);
+ case 8:
+ return BM_StrAppendImpl(state, total_bytes, kChunk, kChunk, kChunk,
+ kChunk, kChunk, kChunk, kChunk, kChunk);
+ default:
+ std::abort();
+ }
+}
+
+template <typename B>
+void StrAppendConfig(B* benchmark) {
+ for (int bytes : {10, 100, 1000, 10000}) {
+ for (int chunks : {1, 2, 4, 8}) {
+ // Only add the ones that divide properly. Otherwise we are over counting.
+ if (bytes % (10 * chunks) == 0) {
+ benchmark->Args({bytes, chunks});
+ }
+ }
+ }
+}
+
+BENCHMARK(BM_StrAppend)->Apply(StrAppendConfig);
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_test.cc
index 0714107267a..f3770dc076f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_cat_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#include <cstdint>
#include <string>
+#include <vector>
#include "gtest/gtest.h"
#include "absl/strings/substitute.h"
@@ -106,11 +107,7 @@ TEST(StrCat, Enums) {
TEST(StrCat, Basics) {
std::string result;
- std::string strs[] = {
- "Hello",
- "Cruel",
- "World"
- };
+ std::string strs[] = {"Hello", "Cruel", "World"};
std::string stdstrs[] = {
"std::Hello",
@@ -164,9 +161,10 @@ TEST(StrCat, Basics) {
result = absl::StrCat(ui64s[0], ", ", ui64s[1], "!");
EXPECT_EQ(result, "12345678910, 10987654321!");
- std::string one = "1"; // Actually, it's the size of this std::string that we want; a
- // 64-bit build distinguishes between size_t and uint64_t,
- // even though they're both unsigned 64-bit values.
+ std::string one =
+ "1"; // Actually, it's the size of this string that we want; a
+ // 64-bit build distinguishes between size_t and uint64_t,
+ // even though they're both unsigned 64-bit values.
result = absl::StrCat("And a ", one.size(), " and a ",
&result[2] - &result[0], " and a ", one, " 2 3 4", "!");
EXPECT_EQ(result, "And a 1 and a 2 and a 1 2 3 4!");
@@ -197,6 +195,21 @@ TEST(StrCat, Basics) {
EXPECT_EQ(result, "12333444455555666666777777788888888999999999");
}
+TEST(StrCat, CornerCases) {
+ std::string result;
+
+ result = absl::StrCat(""); // NOLINT
+ EXPECT_EQ(result, "");
+ result = absl::StrCat("", "");
+ EXPECT_EQ(result, "");
+ result = absl::StrCat("", "", "");
+ EXPECT_EQ(result, "");
+ result = absl::StrCat("", "", "", "");
+ EXPECT_EQ(result, "");
+ result = absl::StrCat("", "", "", "", "");
+ EXPECT_EQ(result, "");
+}
+
// A minimal allocator that uses malloc().
template <typename T>
struct Mallocator {
@@ -306,11 +319,7 @@ TEST(StrCat, MaxArgs) {
TEST(StrAppend, Basics) {
std::string result = "existing text";
- std::string strs[] = {
- "Hello",
- "Cruel",
- "World"
- };
+ std::string strs[] = {"Hello", "Cruel", "World"};
std::string stdstrs[] = {
"std::Hello",
@@ -365,9 +374,10 @@ TEST(StrAppend, Basics) {
absl::StrAppend(&result, ui64s[0], ", ", ui64s[1], "!");
EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
- std::string one = "1"; // Actually, it's the size of this std::string that we want; a
- // 64-bit build distinguishes between size_t and uint64_t,
- // even though they're both unsigned 64-bit values.
+ std::string one =
+ "1"; // Actually, it's the size of this string that we want; a
+ // 64-bit build distinguishes between size_t and uint64_t,
+ // even though they're both unsigned 64-bit values.
old_size = result.size();
absl::StrAppend(&result, "And a ", one.size(), " and a ",
&result[2] - &result[0], " and a ", one, " 2 3 4", "!");
@@ -401,6 +411,32 @@ TEST(StrAppend, Basics) {
"No limit thanks to C++11's variadic templates");
}
+TEST(StrCat, VectorBoolReferenceTypes) {
+ std::vector<bool> v;
+ v.push_back(true);
+ v.push_back(false);
+ std::vector<bool> const& cv = v;
+ // Test that vector<bool>::reference and vector<bool>::const_reference
+ // are handled as if the were really bool types and not the proxy types
+ // they really are.
+ std::string result = absl::StrCat(v[0], v[1], cv[0], cv[1]); // NOLINT
+ EXPECT_EQ(result, "1010");
+}
+
+// Passing nullptr to memcpy is undefined behavior and this test
+// provides coverage of codepaths that handle empty strings with nullptrs.
+TEST(StrCat, AvoidsMemcpyWithNullptr) {
+ EXPECT_EQ(absl::StrCat(42, absl::string_view{}), "42");
+
+ // Cover CatPieces code.
+ EXPECT_EQ(absl::StrCat(1, 2, 3, 4, 5, absl::string_view{}), "12345");
+
+ // Cover AppendPieces.
+ std::string result;
+ absl::StrAppend(&result, 1, 2, 3, 4, 5, absl::string_view{});
+ EXPECT_EQ(result, "12345");
+}
+
#ifdef GTEST_HAS_DEATH_TEST
TEST(StrAppend, Death) {
std::string s = "self";
@@ -412,10 +448,34 @@ TEST(StrAppend, Death) {
}
#endif // GTEST_HAS_DEATH_TEST
-TEST(StrAppend, EmptyString) {
- std::string s = "";
- absl::StrAppend(&s, s);
- EXPECT_EQ(s, "");
+TEST(StrAppend, CornerCases) {
+ std::string result;
+ absl::StrAppend(&result, "");
+ EXPECT_EQ(result, "");
+ absl::StrAppend(&result, "", "");
+ EXPECT_EQ(result, "");
+ absl::StrAppend(&result, "", "", "");
+ EXPECT_EQ(result, "");
+ absl::StrAppend(&result, "", "", "", "");
+ EXPECT_EQ(result, "");
+ absl::StrAppend(&result, "", "", "", "", "");
+ EXPECT_EQ(result, "");
+}
+
+TEST(StrAppend, CornerCasesNonEmptyAppend) {
+ for (std::string result : {"hello", "a string too long to fit in the SSO"}) {
+ const std::string expected = result;
+ absl::StrAppend(&result, "");
+ EXPECT_EQ(result, expected);
+ absl::StrAppend(&result, "", "");
+ EXPECT_EQ(result, expected);
+ absl::StrAppend(&result, "", "", "");
+ EXPECT_EQ(result, expected);
+ absl::StrAppend(&result, "", "", "", "");
+ EXPECT_EQ(result, expected);
+ absl::StrAppend(&result, "", "", "", "", "");
+ EXPECT_EQ(result, expected);
+ }
}
template <typename IntType>
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format.h
index 2d07725de21..01465107e10 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,12 +19,14 @@
//
// The `str_format` library is a typesafe replacement for the family of
// `printf()` string formatting routines within the `<cstdio>` standard library
-// header. Like the `printf` family, the `str_format` uses a "format string" to
-// perform argument substitutions based on types.
+// header. Like the `printf` family, `str_format` uses a "format string" to
+// perform argument substitutions based on types. See the `FormatSpec` section
+// below for format string documentation.
//
// Example:
//
-// string s = absl::StrFormat("%s %s You have $%d!", "Hello", name, dollars);
+// std::string s = absl::StrFormat(
+// "%s %s You have $%d!", "Hello", name, dollars);
//
// The library consists of the following basic utilities:
//
@@ -49,14 +51,13 @@
// * A `ParsedFormat` instance, which encapsulates a specific, pre-compiled
// format string for a specific set of type(s), and which can be passed
// between API boundaries. (The `FormatSpec` type should not be used
-// directly.)
+// directly except as an argument type for wrapper functions.)
//
// The `str_format` library provides the ability to output its format strings to
// arbitrary sink types:
//
// * A generic `Format()` function to write outputs to arbitrary sink types,
-// which must implement a `RawSinkFormat` interface. (See
-// `str_format_sink.h` for more information.)
+// which must implement a `FormatRawSink` interface.
//
// * A `FormatUntyped()` function that is similar to `Format()` except it is
// loosely typed. `FormatUntyped()` is not a template and does not perform
@@ -64,8 +65,8 @@
// boolean from a runtime check.
//
// In addition, the `str_format` library provides extension points for
-// augmenting formatting to new types. These extensions are fully documented
-// within the `str_format_extension.h` header file.
+// augmenting formatting to new types. See "StrFormat Extensions" below.
+
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
@@ -79,6 +80,7 @@
#include "absl/strings/internal/str_format/parser.h" // IWYU pragma: export
namespace absl {
+ABSL_NAMESPACE_BEGIN
// UntypedFormatSpec
//
@@ -89,7 +91,7 @@ namespace absl {
// Example:
//
// absl::UntypedFormatSpec format("%d");
-// string out;
+// std::string out;
// CHECK(absl::FormatUntyped(&out, format, {absl::FormatArg(1)}));
class UntypedFormatSpec {
public:
@@ -135,8 +137,8 @@ str_format_internal::StreamedWrapper<T> FormatStreamed(const T& v) {
// Example:
//
// int n = 0;
-// string s = absl::StrFormat("%s%d%n", "hello", 123,
-// absl::FormatCountCapture(&n));
+// std::string s = absl::StrFormat("%s%d%n", "hello", 123,
+// absl::FormatCountCapture(&n));
// EXPECT_EQ(8, n);
class FormatCountCapture {
public:
@@ -156,10 +158,15 @@ class FormatCountCapture {
// FormatSpec
//
// The `FormatSpec` type defines the makeup of a format string within the
-// `str_format` library. You should not need to use or manipulate this type
-// directly. A `FormatSpec` is a variadic class template that is evaluated at
-// compile-time, according to the format string and arguments that are passed
-// to it.
+// `str_format` library. It is a variadic class template that is evaluated at
+// compile-time, according to the format string and arguments that are passed to
+// it.
+//
+// You should not need to manipulate this type directly. You should only name it
+// if you are writing wrapper functions which accept format arguments that will
+// be provided unmodified to functions in this library. Such a wrapper function
+// might be a class method that provides format arguments and/or internally uses
+// the result of formatting.
//
// For a `FormatSpec` to be valid at compile-time, it must be provided as
// either:
@@ -186,7 +193,7 @@ class FormatCountCapture {
// A format string generally follows the POSIX syntax as used within the POSIX
// `printf` specification.
//
-// (See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html.)
+// (See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fprintf.html.)
//
// In specific, the `FormatSpec` supports the following type specifiers:
// * `c` for characters
@@ -205,6 +212,11 @@ class FormatCountCapture {
// written to this point. The resulting value must be captured within an
// `absl::FormatCountCapture` type.
//
+// Implementation-defined behavior:
+// * A null pointer provided to "%s" or "%p" is output as "(nil)".
+// * A non-null pointer provided to "%p" is output in hex as if by %#x or
+// %#lx.
+//
// NOTE: `o`, `x\X` and `u` will convert signed values to their unsigned
// counterpart before formatting.
//
@@ -220,10 +232,10 @@ class FormatCountCapture {
// "%e", .01 -> "1.00000e-2"
// "%a", -3.0 -> "-0x1.8p+1"
// "%g", .01 -> "1e-2"
-// "%p", *int -> "0x7ffdeb6ad2a4"
+// "%p", (void*)&value -> "0x7ffdeb6ad2a4"
//
// int n = 0;
-// string s = absl::StrFormat(
+// std::string s = absl::StrFormat(
// "%s%d%n", "hello", 123, absl::FormatCountCapture(&n));
// EXPECT_EQ(8, n);
//
@@ -241,8 +253,8 @@ class FormatCountCapture {
// argument, etc.
template <typename... Args>
-using FormatSpec =
- typename str_format_internal::FormatSpecDeductionBarrier<Args...>::type;
+using FormatSpec = str_format_internal::FormatSpecTemplate<
+ str_format_internal::ArgumentToConv<Args>()...>;
// ParsedFormat
//
@@ -269,9 +281,36 @@ using FormatSpec =
// } else {
// ... error case ...
// }
+
+#if defined(__cpp_nontype_template_parameter_auto)
+// If C++17 is available, an 'extended' format is also allowed that can specify
+// multiple conversion characters per format argument, using a combination of
+// `absl::FormatConversionCharSet` enum values (logically a set union)
+// via the `|` operator. (Single character-based arguments are still accepted,
+// but cannot be combined). Some common conversions also have predefined enum
+// values, such as `absl::FormatConversionCharSet::kIntegral`.
+//
+// Example:
+// // Extended format supports multiple conversion characters per argument,
+// // specified via a combination of `FormatConversionCharSet` enums.
+// using MyFormat = absl::ParsedFormat<absl::FormatConversionCharSet::d |
+// absl::FormatConversionCharSet::x>;
+// MyFormat GetFormat(bool use_hex) {
+// if (use_hex) return MyFormat("foo %x bar");
+// return MyFormat("foo %d bar");
+// }
+// // `format` can be used with any value that supports 'd' and 'x',
+// // like `int`.
+// auto format = GetFormat(use_hex);
+// value = StringF(format, i);
+template <auto... Conv>
+using ParsedFormat = absl::str_format_internal::ExtendedParsedFormat<
+ absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#else
template <char... Conv>
using ParsedFormat = str_format_internal::ExtendedParsedFormat<
- str_format_internal::ConversionCharToConv(Conv)...>;
+ absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
+#endif // defined(__cpp_nontype_template_parameter_auto)
// StrFormat()
//
@@ -290,14 +329,14 @@ using ParsedFormat = str_format_internal::ExtendedParsedFormat<
//
// Example:
//
-// string s = absl::StrFormat(
+// std::string s = absl::StrFormat(
// "Welcome to %s, Number %d!", "The Village", 6);
// EXPECT_EQ("Welcome to The Village, Number 6!", s);
//
// Returns an empty string in case of error.
template <typename... Args>
ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
- const Args&... args) {
+ const Args&... args) {
return str_format_internal::FormatPack(
str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
@@ -311,11 +350,12 @@ ABSL_MUST_USE_RESULT std::string StrFormat(const FormatSpec<Args...>& format,
//
// Example:
//
-// string orig("For example PI is approximately ");
+// std::string orig("For example PI is approximately ");
// std::cout << StrAppendFormat(&orig, "%12.6f", 3.14);
template <typename... Args>
-std::string& StrAppendFormat(std::string* dst, const FormatSpec<Args...>& format,
- const Args&... args) {
+std::string& StrAppendFormat(std::string* dst,
+ const FormatSpec<Args...>& format,
+ const Args&... args) {
return str_format_internal::AppendPack(
dst, str_format_internal::UntypedFormatSpecImpl::Extract(format),
{str_format_internal::FormatArgImpl(args)...});
@@ -386,6 +426,12 @@ int FPrintF(std::FILE* output, const FormatSpec<Args...>& format,
// This function is functionally equivalent to `std::snprintf()` (and
// type-safe); prefer `absl::SNPrintF()` over `std::snprintf()`.
//
+// In particular, a successful call to `absl::SNPrintF()` writes at most `size`
+// bytes of the formatted output to `output`, including a NUL-terminator, and
+// returns the number of bytes that would have been written if truncation did
+// not occur. In the event of an error, a negative value is returned and `errno`
+// is set.
+//
// Example:
//
// std::string_view s = "Ulaanbaatar";
@@ -411,6 +457,16 @@ int SNPrintF(char* output, std::size_t size, const FormatSpec<Args...>& format,
//
// FormatRawSink is a type erased wrapper around arbitrary sink objects
// specifically used as an argument to `Format()`.
+//
+// All the object has to do define an overload of `AbslFormatFlush()` for the
+// sink, usually by adding a ADL-based free function in the same namespace as
+// the sink:
+//
+// void AbslFormatFlush(MySink* dest, absl::string_view part);
+//
+// where `dest` is the pointer passed to `absl::Format()`. The function should
+// append `part` to `dest`.
+//
// FormatRawSink does not own the passed sink object. The passed object must
// outlive the FormatRawSink.
class FormatRawSink {
@@ -434,11 +490,13 @@ class FormatRawSink {
// `absl::FormatRawSink` interface), using a format string and zero or more
// additional arguments.
//
-// By default, `string` and `std::ostream` are supported as destination objects.
+// By default, `std::string`, `std::ostream`, and `absl::Cord` are supported as
+// destination objects. If a `std::string` is used the formatted string is
+// appended to it.
//
-// `absl::Format()` is a generic version of `absl::StrFormat(), for custom
-// sinks. The format string, like format strings for `StrFormat()`, is checked
-// at compile-time.
+// `absl::Format()` is a generic version of `absl::StrAppendFormat()`, for
+// custom sinks. The format string, like format strings for `StrFormat()`, is
+// checked at compile-time.
//
// On failure, this function returns `false` and the state of the sink is
// unspecified.
@@ -483,9 +541,10 @@ using FormatArg = str_format_internal::FormatArgImpl;
//
// Example:
//
-// std::optional<string> FormatDynamic(const string& in_format,
-// const vector<string>& in_args) {
-// string out;
+// std::optional<std::string> FormatDynamic(
+// const std::string& in_format,
+// const vector<std::string>& in_args) {
+// std::string out;
// std::vector<absl::FormatArg> args;
// for (const auto& v : in_args) {
// // It is important that 'v' is a reference to the objects in in_args.
@@ -508,5 +567,247 @@ ABSL_MUST_USE_RESULT inline bool FormatUntyped(
str_format_internal::UntypedFormatSpecImpl::Extract(format), args);
}
+//------------------------------------------------------------------------------
+// StrFormat Extensions
+//------------------------------------------------------------------------------
+//
+// AbslFormatConvert()
+//
+// The StrFormat library provides a customization API for formatting
+// user-defined types using absl::StrFormat(). The API relies on detecting an
+// overload in the user-defined type's namespace of a free (non-member)
+// `AbslFormatConvert()` function, usually as a friend definition with the
+// following signature:
+//
+// absl::FormatConvertResult<...> AbslFormatConvert(
+// const X& value,
+// const absl::FormatConversionSpec& spec,
+// absl::FormatSink *sink);
+//
+// An `AbslFormatConvert()` overload for a type should only be declared in the
+// same file and namespace as said type.
+//
+// The abstractions within this definition include:
+//
+// * An `absl::FormatConversionSpec` to specify the fields to pull from a
+// user-defined type's format string
+// * An `absl::FormatSink` to hold the converted string data during the
+// conversion process.
+// * An `absl::FormatConvertResult` to hold the status of the returned
+// formatting operation
+//
+// The return type encodes all the conversion characters that your
+// AbslFormatConvert() routine accepts. The return value should be {true}.
+// A return value of {false} will result in `StrFormat()` returning
+// an empty string. This result will be propagated to the result of
+// `FormatUntyped`.
+//
+// Example:
+//
+// struct Point {
+// // To add formatting support to `Point`, we simply need to add a free
+// // (non-member) function `AbslFormatConvert()`. This method interprets
+// // `spec` to print in the request format. The allowed conversion characters
+// // can be restricted via the type of the result, in this example
+// // string and integral formatting are allowed (but not, for instance
+// // floating point characters like "%f"). You can add such a free function
+// // using a friend declaration within the body of the class:
+// friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+// absl::FormatConversionCharSet::kIntegral>
+// AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+// absl::FormatSink* s) {
+// if (spec.conversion_char() == absl::FormatConversionChar::s) {
+// s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+// } else {
+// s->Append(absl::StrCat(p.x, ",", p.y));
+// }
+// return {true};
+// }
+//
+// int x;
+// int y;
+// };
+
+// clang-format off
+
+// FormatConversionChar
+//
+// Specifies the formatting character provided in the format string
+// passed to `StrFormat()`.
+enum class FormatConversionChar : uint8_t {
+ c, s, // text
+ d, i, o, u, x, X, // int
+ f, F, e, E, g, G, a, A, // float
+ n, p // misc
+};
+// clang-format on
+
+// FormatConversionSpec
+//
+// Specifies modifications to the conversion of the format string, through use
+// of one or more format flags in the source format string.
+class FormatConversionSpec {
+ public:
+ // FormatConversionSpec::is_basic()
+ //
+ // Indicates that width and precision are not specified, and no additional
+ // flags are set for this conversion character in the format string.
+ bool is_basic() const { return impl_.is_basic(); }
+
+ // FormatConversionSpec::has_left_flag()
+ //
+ // Indicates whether the result should be left justified for this conversion
+ // character in the format string. This flag is set through use of a '-'
+ // character in the format string. E.g. "%-s"
+ bool has_left_flag() const { return impl_.has_left_flag(); }
+
+ // FormatConversionSpec::has_show_pos_flag()
+ //
+ // Indicates whether a sign column is prepended to the result for this
+ // conversion character in the format string, even if the result is positive.
+ // This flag is set through use of a '+' character in the format string.
+ // E.g. "%+d"
+ bool has_show_pos_flag() const { return impl_.has_show_pos_flag(); }
+
+ // FormatConversionSpec::has_sign_col_flag()
+ //
+ // Indicates whether a mandatory sign column is added to the result for this
+ // conversion character. This flag is set through use of a space character
+ // (' ') in the format string. E.g. "% i"
+ bool has_sign_col_flag() const { return impl_.has_sign_col_flag(); }
+
+ // FormatConversionSpec::has_alt_flag()
+ //
+ // Indicates whether an "alternate" format is applied to the result for this
+ // conversion character. Alternative forms depend on the type of conversion
+ // character, and unallowed alternatives are undefined. This flag is set
+ // through use of a '#' character in the format string. E.g. "%#h"
+ bool has_alt_flag() const { return impl_.has_alt_flag(); }
+
+ // FormatConversionSpec::has_zero_flag()
+ //
+ // Indicates whether zeroes should be prepended to the result for this
+ // conversion character instead of spaces. This flag is set through use of the
+ // '0' character in the format string. E.g. "%0f"
+ bool has_zero_flag() const { return impl_.has_zero_flag(); }
+
+ // FormatConversionSpec::conversion_char()
+ //
+ // Returns the underlying conversion character.
+ FormatConversionChar conversion_char() const {
+ return impl_.conversion_char();
+ }
+
+ // FormatConversionSpec::width()
+ //
+ // Returns the specified width (indicated through use of a non-zero integer
+ // value or '*' character) of the conversion character. If width is
+ // unspecified, it returns a negative value.
+ int width() const { return impl_.width(); }
+
+ // FormatConversionSpec::precision()
+ //
+ // Returns the specified precision (through use of the '.' character followed
+ // by a non-zero integer value or '*' character) of the conversion character.
+ // If precision is unspecified, it returns a negative value.
+ int precision() const { return impl_.precision(); }
+
+ private:
+ explicit FormatConversionSpec(
+ str_format_internal::FormatConversionSpecImpl impl)
+ : impl_(impl) {}
+
+ friend str_format_internal::FormatConversionSpecImpl;
+
+ absl::str_format_internal::FormatConversionSpecImpl impl_;
+};
+
+// Type safe OR operator for FormatConversionCharSet to allow accepting multiple
+// conversion chars in custom format converters.
+constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
+ FormatConversionCharSet b) {
+ return static_cast<FormatConversionCharSet>(static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(b));
+}
+
+// FormatConversionCharSet
+//
+// Specifies the _accepted_ conversion types as a template parameter to
+// FormatConvertResult for custom implementations of `AbslFormatConvert`.
+// Note the helper predefined alias definitions (kIntegral, etc.) below.
+enum class FormatConversionCharSet : uint64_t {
+ // text
+ c = str_format_internal::FormatConversionCharToConvInt('c'),
+ s = str_format_internal::FormatConversionCharToConvInt('s'),
+ // integer
+ d = str_format_internal::FormatConversionCharToConvInt('d'),
+ i = str_format_internal::FormatConversionCharToConvInt('i'),
+ o = str_format_internal::FormatConversionCharToConvInt('o'),
+ u = str_format_internal::FormatConversionCharToConvInt('u'),
+ x = str_format_internal::FormatConversionCharToConvInt('x'),
+ X = str_format_internal::FormatConversionCharToConvInt('X'),
+ // Float
+ f = str_format_internal::FormatConversionCharToConvInt('f'),
+ F = str_format_internal::FormatConversionCharToConvInt('F'),
+ e = str_format_internal::FormatConversionCharToConvInt('e'),
+ E = str_format_internal::FormatConversionCharToConvInt('E'),
+ g = str_format_internal::FormatConversionCharToConvInt('g'),
+ G = str_format_internal::FormatConversionCharToConvInt('G'),
+ a = str_format_internal::FormatConversionCharToConvInt('a'),
+ A = str_format_internal::FormatConversionCharToConvInt('A'),
+ // misc
+ n = str_format_internal::FormatConversionCharToConvInt('n'),
+ p = str_format_internal::FormatConversionCharToConvInt('p'),
+
+ // Used for width/precision '*' specification.
+ kStar = static_cast<uint64_t>(
+ absl::str_format_internal::FormatConversionCharSetInternal::kStar),
+ // Some predefined values:
+ kIntegral = d | i | u | o | x | X,
+ kFloating = a | e | f | g | A | E | F | G,
+ kNumeric = kIntegral | kFloating,
+ kString = s,
+ kPointer = p,
+};
+
+// FormatSink
+//
+// An abstraction to which conversions write their string data.
+//
+class FormatSink {
+ public:
+ // Appends `count` copies of `ch`.
+ void Append(size_t count, char ch) { sink_->Append(count, ch); }
+
+ void Append(string_view v) { sink_->Append(v); }
+
+ // Appends the first `precision` bytes of `v`. If this is less than
+ // `width`, spaces will be appended first (if `left` is false), or
+ // after (if `left` is true) to ensure the total amount appended is
+ // at least `width`.
+ bool PutPaddedString(string_view v, int width, int precision, bool left) {
+ return sink_->PutPaddedString(v, width, precision, left);
+ }
+
+ private:
+ friend str_format_internal::FormatSinkImpl;
+ explicit FormatSink(str_format_internal::FormatSinkImpl* s) : sink_(s) {}
+ str_format_internal::FormatSinkImpl* sink_;
+};
+
+// FormatConvertResult
+//
+// Indicates whether a call to AbslFormatConvert() was successful.
+// This return type informs the StrFormat extension framework (through
+// ADL but using the return type) of what conversion characters are supported.
+// It is strongly discouraged to return {false}, as this will result in an
+// empty string in StrFormat.
+template <FormatConversionCharSet C>
+struct FormatConvertResult {
+ bool value;
+};
+
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_STRINGS_STR_FORMAT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
index 87ed234fe82..c60027ad297 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_format_test.cc
@@ -1,3 +1,18 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/strings/str_format.h"
#include <cstdarg>
#include <cstdint>
@@ -6,14 +21,16 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/str_format.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
using str_format_internal::FormatArgImpl;
-class FormatEntryPointTest : public ::testing::Test { };
+using FormatEntryPointTest = ::testing::Test;
TEST_F(FormatEntryPointTest, Format) {
std::string sink;
@@ -30,8 +47,8 @@ TEST_F(FormatEntryPointTest, UntypedFormat) {
"",
"a",
"%80d",
-#if !defined(_MSC_VER) && !defined(__ANDROID__)
- // MSVC and Android don't support positional syntax.
+#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
+ // MSVC, NaCL and Android don't support positional syntax.
"complicated multipart %% %1$d format %1$0999d",
#endif // _MSC_VER
};
@@ -153,17 +170,20 @@ TEST_F(FormatEntryPointTest, Stream) {
"",
"a",
"%80d",
-#if !defined(_MSC_VER) && !defined(__ANDROID__)
- // MSVC doesn't support positional syntax.
+ "%d %u %c %s %f %g",
+#if !defined(_MSC_VER) && !defined(__ANDROID__) && !defined(__native_client__)
+ // MSVC, NaCL and Android don't support positional syntax.
"complicated multipart %% %1$d format %1$080d",
#endif // _MSC_VER
};
std::string buf(4096, '\0');
for (const auto& fmt : formats) {
- const auto parsed = ParsedFormat<'d'>::NewAllowIgnored(fmt);
+ const auto parsed =
+ ParsedFormat<'d', 'u', 'c', 's', 'f', 'g'>::NewAllowIgnored(fmt);
std::ostringstream oss;
- oss << StreamFormat(*parsed, 123);
- int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), 123);
+ oss << StreamFormat(*parsed, 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
+ int fmt_result = snprintf(&*buf.begin(), buf.size(), fmt.c_str(), //
+ 123, 3, 49, "multistreaming!!!", 1.01, 1.01);
ASSERT_TRUE(oss) << fmt;
ASSERT_TRUE(fmt_result >= 0 && static_cast<size_t>(fmt_result) < buf.size())
<< fmt_result;
@@ -238,7 +258,7 @@ class TempFile {
std::FILE* file() const { return file_; }
- // Read the file into a std::string.
+ // Read the file into a string.
std::string ReadFile() {
std::fseek(file_, 0, SEEK_END);
int size = std::ftell(file_);
@@ -271,7 +291,7 @@ TEST_F(FormatEntryPointTest, FPrintFError) {
EXPECT_EQ(errno, EBADF);
}
-#if __GLIBC__
+#ifdef __GLIBC__
TEST_F(FormatEntryPointTest, FprintfTooLarge) {
std::FILE* f = std::fopen("/dev/null", "w");
int width = 2000000000;
@@ -341,11 +361,12 @@ TEST(StrFormat, BehavesAsDocumented) {
EXPECT_EQ(StrFormat("%c", int{'a'}), "a");
EXPECT_EQ(StrFormat("%c", long{'a'}), "a"); // NOLINT
EXPECT_EQ(StrFormat("%c", uint64_t{'a'}), "a");
- // "s" - std::string Eg: "C" -> "C", std::string("C++") -> "C++"
+ // "s" - string Eg: "C" -> "C", std::string("C++") -> "C++"
// Formats std::string, char*, string_view, and Cord.
EXPECT_EQ(StrFormat("%s", "C"), "C");
EXPECT_EQ(StrFormat("%s", std::string("C++")), "C++");
EXPECT_EQ(StrFormat("%s", string_view("view")), "view");
+ EXPECT_EQ(StrFormat("%s", absl::Cord("cord")), "cord");
// Integral Conversion
// These format integral types: char, int, long, uint64_t, etc.
EXPECT_EQ(StrFormat("%d", char{10}), "10");
@@ -446,7 +467,7 @@ struct SummarizeConsumer {
if (conv.precision.is_from_arg()) {
*out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
}
- *out += conv.conv.Char();
+ *out += str_format_internal::FormatConversionCharToChar(conv.conv);
*out += "}";
return true;
}
@@ -458,7 +479,7 @@ std::string SummarizeParsedFormat(const ParsedFormatBase& pc) {
return out;
}
-class ParsedFormatTest : public testing::Test {};
+using ParsedFormatTest = ::testing::Test;
TEST_F(ParsedFormatTest, SimpleChecked) {
EXPECT_EQ("[ABC]{d:1$d}[DEF]",
@@ -528,99 +549,226 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
}
-using str_format_internal::Conv;
+#if defined(__cpp_nontype_template_parameter_auto)
+
+template <auto T>
+std::true_type IsValidParsedFormatArgTest(ParsedFormat<T>*);
+
+template <auto T>
+std::false_type IsValidParsedFormatArgTest(...);
+
+template <auto T>
+using IsValidParsedFormatArg = decltype(IsValidParsedFormatArgTest<T>(nullptr));
+
+TEST_F(ParsedFormatTest, OnlyValidTypesAllowed) {
+ ASSERT_TRUE(IsValidParsedFormatArg<'c'>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<FormatConversionCharSet::d>::value);
+
+ ASSERT_TRUE(IsValidParsedFormatArg<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::value);
+ ASSERT_TRUE(
+ IsValidParsedFormatArg<absl::FormatConversionCharSet::kIntegral>::value);
+
+ // This is an easy mistake to make, however, this will reduce to an integer
+ // which has no meaning, so we need to ensure it doesn't compile.
+ ASSERT_FALSE(IsValidParsedFormatArg<'x' | 'd'>::value);
+
+ // For now, we disallow construction based on ConversionChar (rather than
+ // CharSet)
+ ASSERT_FALSE(IsValidParsedFormatArg<absl::FormatConversionChar::d>::value);
+}
+
+TEST_F(ParsedFormatTest, ExtendedTyping) {
+ EXPECT_FALSE(ParsedFormat<FormatConversionCharSet::d>::New(""));
+ ASSERT_TRUE(ParsedFormat<absl::FormatConversionCharSet::d>::New("%d"));
+ auto v1 = ParsedFormat<'d', absl::FormatConversionCharSet::s>::New("%d%s");
+ ASSERT_TRUE(v1);
+ auto v2 = ParsedFormat<absl::FormatConversionCharSet::d, 's'>::New("%d%s");
+ ASSERT_TRUE(v2);
+ auto v3 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%d%s");
+ ASSERT_TRUE(v3);
+ auto v4 = ParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::s,
+ 's'>::New("%s%s");
+ ASSERT_TRUE(v4);
+}
+#endif
TEST_F(ParsedFormatTest, UncheckedCorrect) {
- auto f = ExtendedParsedFormat<Conv::d>::New("ABC%dDEF");
+ auto f =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{d:1$d}[DEF]", SummarizeParsedFormat(*f));
std::string format = "%sFFF%dZZZ%f";
- auto f2 =
- ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
+ auto f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New(format);
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
- "%s %d %f");
+ f2 = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
- auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
+ auto star =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
+ absl::FormatConversionCharSet::d>::New("%*d");
ASSERT_TRUE(star);
EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
- auto dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d");
+ auto dollar =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}", SummarizeParsedFormat(*dollar));
// with reuse
- dollar = ExtendedParsedFormat<Conv::d, Conv::s>::New("%2$s %1$d %1$d");
+ dollar = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
ASSERT_TRUE(dollar);
EXPECT_EQ("{2$s:2$s}[ ]{1$d:1$d}[ ]{1$d:1$d}",
SummarizeParsedFormat(*dollar));
}
TEST_F(ParsedFormatTest, UncheckedIgnoredArgs) {
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC")));
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("%dABC")));
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::s>::New("ABC%2$s")));
- auto f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC");
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("%dABC")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::New("ABC%2$s")));
+ auto f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
+ f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
ASSERT_TRUE(f);
EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
+ f = ExtendedParsedFormat<
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
- auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
+ auto dx =
+ ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d %1$x");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
- dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
+ dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
+ absl::FormatConversionCharSet::x>::New("%1$d");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
}
TEST_F(ParsedFormatTest, UncheckedIncorrect) {
- EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
- EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
+ EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
+ "ABC%dDEF%d"));
std::string format = "%sFFF%dZZZ%f";
- EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
+ absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::g>::New(format)));
}
TEST_F(ParsedFormatTest, RegressionMixPositional) {
- EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
+ EXPECT_FALSE(
+ (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
+ absl::FormatConversionCharSet::o>::New("%1$d %o")));
+}
+
+using FormatWrapperTest = ::testing::Test;
+
+// Plain wrapper for StrFormat.
+template <typename... Args>
+std::string WrappedFormat(const absl::FormatSpec<Args...>& format,
+ const Args&... args) {
+ return StrFormat(format, args...);
+}
+
+TEST_F(FormatWrapperTest, ConstexprStringFormat) {
+ EXPECT_EQ(WrappedFormat("%s there", "hello"), "hello there");
+}
+
+TEST_F(FormatWrapperTest, ParsedFormat) {
+ ParsedFormat<'s'> format("%s there");
+ EXPECT_EQ(WrappedFormat(format, "hello"), "hello there");
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+using FormatExtensionTest = ::testing::Test;
+
+struct Point {
+ friend absl::FormatConvertResult<absl::FormatConversionCharSet::kString |
+ absl::FormatConversionCharSet::kIntegral>
+ AbslFormatConvert(const Point& p, const absl::FormatConversionSpec& spec,
+ absl::FormatSink* s) {
+ if (spec.conversion_char() == absl::FormatConversionChar::s) {
+ s->Append(absl::StrCat("x=", p.x, " y=", p.y));
+ } else {
+ s->Append(absl::StrCat(p.x, ",", p.y));
+ }
+ return {true};
+ }
+
+ int x = 10;
+ int y = 20;
+};
+
+TEST_F(FormatExtensionTest, AbslFormatConvertExample) {
+ Point p;
+ EXPECT_EQ(absl::StrFormat("a %s z", p), "a x=10 y=20 z");
+ EXPECT_EQ(absl::StrFormat("a %d z", p), "a 10,20 z");
+
+ // Typed formatting will fail to compile an invalid format.
+ // StrFormat("%f", p); // Does not compile.
+ std::string actual;
+ absl::UntypedFormatSpec f1("%f");
+ // FormatUntyped will return false for bad character.
+ EXPECT_FALSE(absl::FormatUntyped(&actual, f1, {absl::FormatArg(p)}));
+}
+
// Some codegen thunks that we can use to easily dump the generated assembly for
// different StrFormat calls.
-std::string CodegenAbslStrFormatInt(int i) { // NOLINT
+std::string CodegenAbslStrFormatInt(int i) { // NOLINT
return absl::StrFormat("%d", i);
}
std::string CodegenAbslStrFormatIntStringInt64(int i, const std::string& s,
- int64_t i64) { // NOLINT
+ int64_t i64) { // NOLINT
return absl::StrFormat("%d %s %d", i, s, i64);
}
-void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
+void CodegenAbslStrAppendFormatInt(std::string* out, int i) { // NOLINT
absl::StrAppendFormat(out, "%d", i);
}
void CodegenAbslStrAppendFormatIntStringInt64(std::string* out, int i,
- const std::string& s,
- int64_t i64) { // NOLINT
+ const std::string& s,
+ int64_t i64) { // NOLINT
absl::StrAppendFormat(out, "%d %s %d", i, s, i64);
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join.h
index f9611ad3b47..33534536cfd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,13 +18,13 @@
// -----------------------------------------------------------------------------
//
// This header file contains functions for joining a range of elements and
-// returning the result as a string. StrJoin operations are specified by passing
-// a range, a separator string to use between the elements joined, and an
-// optional Formatter responsible for converting each argument in the range to a
-// string. If omitted, a default `AlphaNumFormatter()` is called on the elements
-// to be joined, using the same formatting that `absl::StrCat()` uses. This
-// package defines a number of default formatters, and you can define your own
-// implementations.
+// returning the result as a std::string. StrJoin operations are specified by
+// passing a range, a separator string to use between the elements joined, and
+// an optional Formatter responsible for converting each argument in the range
+// to a string. If omitted, a default `AlphaNumFormatter()` is called on the
+// elements to be joined, using the same formatting that `absl::StrCat()` uses.
+// This package defines a number of default formatters, and you can define your
+// own implementations.
//
// Ranges are specified by passing a container with `std::begin()` and
// `std::end()` iterators, container-specific `begin()` and `end()` iterators, a
@@ -37,8 +37,8 @@
//
// Example:
//
-// std::vector<string> v = {"foo", "bar", "baz"};
-// string s = absl::StrJoin(v, "-");
+// std::vector<std::string> v = {"foo", "bar", "baz"};
+// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s);
//
// See comments on the `absl::StrJoin()` function for more examples.
@@ -60,22 +60,23 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// Concept: Formatter
// -----------------------------------------------------------------------------
//
// A Formatter is a function object that is responsible for formatting its
-// argument as a string and appending it to a given output string. Formatters
-// may be implemented as function objects, lambdas, or normal functions. You may
-// provide your own Formatter to enable `absl::StrJoin()` to work with arbitrary
-// types.
+// argument as a string and appending it to a given output std::string.
+// Formatters may be implemented as function objects, lambdas, or normal
+// functions. You may provide your own Formatter to enable `absl::StrJoin()` to
+// work with arbitrary types.
//
// The following is an example of a custom Formatter that simply uses
-// `std::to_string()` to format an integer as a string.
+// `std::to_string()` to format an integer as a std::string.
//
// struct MyFormatter {
-// void operator()(string* out, int i) const {
+// void operator()(std::string* out, int i) const {
// out->append(std::to_string(i));
// }
// };
@@ -84,7 +85,7 @@ namespace absl {
// argument to `absl::StrJoin()`:
//
// std::vector<int> v = {1, 2, 3, 4};
-// string s = absl::StrJoin(v, "-", MyFormatter());
+// std::string s = absl::StrJoin(v, "-", MyFormatter());
// EXPECT_EQ("1-2-3-4", s);
//
// The following standard formatters are provided within this file:
@@ -143,7 +144,7 @@ strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
std::forward<Formatter>(f));
}
-// Function overload of `DererefenceFormatter()` for using a default
+// Function overload of `DereferenceFormatter()` for using a default
// `AlphaNumFormatter()`.
inline strings_internal::DereferenceFormatterImpl<
strings_internal::AlphaNumFormatterImpl>
@@ -156,7 +157,7 @@ DereferenceFormatter() {
// StrJoin()
// -----------------------------------------------------------------------------
//
-// Joins a range of elements and returns the result as a string.
+// Joins a range of elements and returns the result as a std::string.
// `absl::StrJoin()` takes a range, a separator string to use between the
// elements joined, and an optional Formatter responsible for converting each
// argument in the range to a string.
@@ -167,22 +168,22 @@ DereferenceFormatter() {
// Example 1:
// // Joins a collection of strings. This pattern also works with a collection
// // of `absl::string_view` or even `const char*`.
-// std::vector<string> v = {"foo", "bar", "baz"};
-// string s = absl::StrJoin(v, "-");
+// std::vector<std::string> v = {"foo", "bar", "baz"};
+// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("foo-bar-baz", s);
//
// Example 2:
// // Joins the values in the given `std::initializer_list<>` specified using
// // brace initialization. This pattern also works with an initializer_list
// // of ints or `absl::string_view` -- any `AlphaNum`-compatible type.
-// string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
+// std::string s = absl::StrJoin({"foo", "bar", "baz"}, "-");
// EXPECT_EQ("foo-bar-baz", s);
//
// Example 3:
// // Joins a collection of ints. This pattern also works with floats,
// // doubles, int64s -- any `StrCat()`-compatible type.
// std::vector<int> v = {1, 2, 3, -4};
-// string s = absl::StrJoin(v, "-");
+// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("1-2-3--4", s);
//
// Example 4:
@@ -193,7 +194,7 @@ DereferenceFormatter() {
// // `std::vector<int*>`.
// int x = 1, y = 2, z = 3;
// std::vector<int*> v = {&x, &y, &z};
-// string s = absl::StrJoin(v, "-");
+// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("1-2-3", s);
//
// Example 5:
@@ -202,65 +203,65 @@ DereferenceFormatter() {
// v.emplace_back(new int(1));
// v.emplace_back(new int(2));
// v.emplace_back(new int(3));
-// string s = absl::StrJoin(v, "-");
+// std::string s = absl::StrJoin(v, "-");
// EXPECT_EQ("1-2-3", s);
//
// Example 6:
// // Joins a `std::map`, with each key-value pair separated by an equals
// // sign. This pattern would also work with, say, a
// // `std::vector<std::pair<>>`.
-// std::map<string, int> m = {
+// std::map<std::string, int> m = {
// std::make_pair("a", 1),
// std::make_pair("b", 2),
// std::make_pair("c", 3)};
-// string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
+// std::string s = absl::StrJoin(m, ",", absl::PairFormatter("="));
// EXPECT_EQ("a=1,b=2,c=3", s);
//
// Example 7:
// // These examples show how `absl::StrJoin()` handles a few common edge
// // cases:
-// std::vector<string> v_empty;
+// std::vector<std::string> v_empty;
// EXPECT_EQ("", absl::StrJoin(v_empty, "-"));
//
-// std::vector<string> v_one_item = {"foo"};
+// std::vector<std::string> v_one_item = {"foo"};
// EXPECT_EQ("foo", absl::StrJoin(v_one_item, "-"));
//
-// std::vector<string> v_empty_string = {""};
+// std::vector<std::string> v_empty_string = {""};
// EXPECT_EQ("", absl::StrJoin(v_empty_string, "-"));
//
-// std::vector<string> v_one_item_empty_string = {"a", ""};
+// std::vector<std::string> v_one_item_empty_string = {"a", ""};
// EXPECT_EQ("a-", absl::StrJoin(v_one_item_empty_string, "-"));
//
-// std::vector<string> v_two_empty_string = {"", ""};
+// std::vector<std::string> v_two_empty_string = {"", ""};
// EXPECT_EQ("-", absl::StrJoin(v_two_empty_string, "-"));
//
// Example 8:
// // Joins a `std::tuple<T...>` of heterogeneous types, converting each to
-// // a string using the `absl::AlphaNum` class.
-// string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
+// // a std::string using the `absl::AlphaNum` class.
+// std::string s = absl::StrJoin(std::make_tuple(123, "abc", 0.456), "-");
// EXPECT_EQ("123-abc-0.456", s);
template <typename Iterator, typename Formatter>
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep,
- Formatter&& fmt) {
+ Formatter&& fmt) {
return strings_internal::JoinAlgorithm(start, end, sep, fmt);
}
template <typename Range, typename Formatter>
std::string StrJoin(const Range& range, absl::string_view separator,
- Formatter&& fmt) {
+ Formatter&& fmt) {
return strings_internal::JoinRange(range, separator, fmt);
}
template <typename T, typename Formatter>
std::string StrJoin(std::initializer_list<T> il, absl::string_view separator,
- Formatter&& fmt) {
+ Formatter&& fmt) {
return strings_internal::JoinRange(il, separator, fmt);
}
template <typename... T, typename Formatter>
std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator,
- Formatter&& fmt) {
+ Formatter&& fmt) {
return strings_internal::JoinAlgorithm(value, separator, fmt);
}
@@ -275,15 +276,18 @@ std::string StrJoin(const Range& range, absl::string_view separator) {
}
template <typename T>
-std::string StrJoin(std::initializer_list<T> il, absl::string_view separator) {
+std::string StrJoin(std::initializer_list<T> il,
+ absl::string_view separator) {
return strings_internal::JoinRange(il, separator);
}
template <typename... T>
-std::string StrJoin(const std::tuple<T...>& value, absl::string_view separator) {
+std::string StrJoin(const std::tuple<T...>& value,
+ absl::string_view separator) {
return strings_internal::JoinAlgorithm(value, separator, AlphaNumFormatter());
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_JOIN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_benchmark.cc
index 7fb0e4973cb..d6f689ff300 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_benchmark.cc
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -58,7 +58,8 @@ void BM_Join2_KeysAndValues(benchmark::State& state) {
const int string_len = state.range(0);
const int num_pairs = state.range(1);
const std::string s(string_len, 'x');
- const std::vector<std::pair<std::string, int>> v(num_pairs, std::make_pair(s, 42));
+ const std::vector<std::pair<std::string, int>> v(num_pairs,
+ std::make_pair(s, 42));
for (auto _ : state) {
std::string s = absl::StrJoin(v, ",", absl::PairFormatter("="));
benchmark::DoNotOptimize(s);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_test.cc
index c941f9c80d4..2be6256e43f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_join_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -118,7 +118,7 @@ TEST(StrJoin, APIExamples) {
{
// A std::map, which is a collection of std::pair<>s.
- std::map<std::string, int> m = { {"a", 1}, {"b", 2}, {"c", 3} };
+ std::map<std::string, int> m = {{"a", 1}, {"b", 2}, {"c", 3}};
EXPECT_EQ("a=1,b=2,c=3", absl::StrJoin(m, ",", absl::PairFormatter("=")));
}
@@ -134,25 +134,26 @@ TEST(StrJoin, APIExamples) {
//
{
- // Empty range yields an empty std::string.
+ // Empty range yields an empty string.
std::vector<std::string> v;
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{
- // A range of 1 element gives a std::string with that element but no separator.
+ // A range of 1 element gives a string with that element but no
+ // separator.
std::vector<std::string> v = {"foo"};
EXPECT_EQ("foo", absl::StrJoin(v, "-"));
}
{
- // A range with a single empty std::string element
+ // A range with a single empty string element
std::vector<std::string> v = {""};
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{
- // A range with 2 elements, one of which is an empty std::string
+ // A range with 2 elements, one of which is an empty string
std::vector<std::string> v = {"a", ""};
EXPECT_EQ("a-", absl::StrJoin(v, "-"));
}
@@ -173,9 +174,10 @@ TEST(StrJoin, APIExamples) {
TEST(StrJoin, CustomFormatter) {
std::vector<std::string> v{"One", "Two", "Three"};
{
- std::string joined = absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
- absl::StrAppend(out, "(", in, ")");
- });
+ std::string joined =
+ absl::StrJoin(v, "", [](std::string* out, const std::string& in) {
+ absl::StrAppend(out, "(", in, ")");
+ });
EXPECT_EQ("(One)(Two)(Three)", joined);
}
{
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.cc
index 69efa357138..2bd5fa98218 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/strings/str_cat.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace strings_internal {
using FixedMapping =
@@ -68,12 +69,14 @@ int ApplySubstitutions(
// aren't inlined.
std::string StrReplaceAll(absl::string_view s,
- strings_internal::FixedMapping replacements) {
+ strings_internal::FixedMapping replacements) {
return StrReplaceAll<strings_internal::FixedMapping>(s, replacements);
}
-int StrReplaceAll(strings_internal::FixedMapping replacements, std::string* target) {
+int StrReplaceAll(strings_internal::FixedMapping replacements,
+ std::string* target) {
return StrReplaceAll<strings_internal::FixedMapping>(replacements, target);
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.h
index 3bfe4c61ebd..273c7077353 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -29,12 +29,12 @@
//
// Example:
//
-// string html_escaped = absl::StrReplaceAll(user_input, {
-// {"&", "&amp;"},
-// {"<", "&lt;"},
-// {">", "&gt;"},
-// {"\"", "&quot;"},
-// {"'", "&#39;"}});
+// std::string html_escaped = absl::StrReplaceAll(user_input, {
+// {"&", "&amp;"},
+// {"<", "&lt;"},
+// {">", "&gt;"},
+// {"\"", "&quot;"},
+// {"'", "&#39;"}});
#ifndef ABSL_STRINGS_STR_REPLACE_H_
#define ABSL_STRINGS_STR_REPLACE_H_
@@ -46,6 +46,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// StrReplaceAll()
//
@@ -58,10 +59,11 @@ namespace absl {
//
// Example:
//
-// string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-// {{"$count", absl::StrCat(5)},
-// {"$who", "Bob"},
-// {"#Noun", "Apples"}});
+// std::string s = absl::StrReplaceAll(
+// "$who bought $count #Noun. Thanks $who!",
+// {{"$count", absl::StrCat(5)},
+// {"$who", "Bob"},
+// {"#Noun", "Apples"}});
// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
ABSL_MUST_USE_RESULT std::string StrReplaceAll(
absl::string_view s,
@@ -78,20 +80,22 @@ ABSL_MUST_USE_RESULT std::string StrReplaceAll(
// replacements["$who"] = "Bob";
// replacements["$count"] = "5";
// replacements["#Noun"] = "Apples";
-// string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
-// replacements);
+// std::string s = absl::StrReplaceAll(
+// "$who bought $count #Noun. Thanks $who!",
+// replacements);
// EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
//
// // A std::vector of std::pair elements can be more efficient.
-// std::vector<std::pair<const absl::string_view, string>> replacements;
+// std::vector<std::pair<const absl::string_view, std::string>> replacements;
// replacements.push_back({"&", "&amp;"});
// replacements.push_back({"<", "&lt;"});
// replacements.push_back({">", "&gt;"});
-// string s = absl::StrReplaceAll("if (ptr < &foo)",
+// std::string s = absl::StrReplaceAll("if (ptr < &foo)",
// replacements);
// EXPECT_EQ("if (ptr &lt; &amp;foo)", s);
template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements);
+std::string StrReplaceAll(absl::string_view s,
+ const StrToStrMapping& replacements);
// Overload of `StrReplaceAll()` to replace character sequences within a given
// output string *in place* with replacements provided within an initializer
@@ -99,7 +103,7 @@ std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacemen
//
// Example:
//
-// string s = std::string("$who bought $count #Noun. Thanks $who!");
+// std::string s = std::string("$who bought $count #Noun. Thanks $who!");
// int count;
// count = absl::StrReplaceAll({{"$count", absl::StrCat(5)},
// {"$who", "Bob"},
@@ -117,7 +121,7 @@ int StrReplaceAll(
//
// Example:
//
-// string s = std::string("if (ptr < &foo)");
+// std::string s = std::string("if (ptr < &foo)");
// int count = absl::StrReplaceAll({{"&", "&amp;"},
// {"<", "&lt;"},
// {">", "&gt;"}}, &s);
@@ -187,7 +191,8 @@ int ApplySubstitutions(absl::string_view s,
} // namespace strings_internal
template <typename StrToStrMapping>
-std::string StrReplaceAll(absl::string_view s, const StrToStrMapping& replacements) {
+std::string StrReplaceAll(absl::string_view s,
+ const StrToStrMapping& replacements) {
auto subs = strings_internal::FindSubstitutions(s, replacements);
std::string result;
result.reserve(s.size());
@@ -208,6 +213,7 @@ int StrReplaceAll(const StrToStrMapping& replacements, std::string* target) {
return substitutions;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_REPLACE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_benchmark.cc
index 8386f2e6bf1..01331da29f6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -54,7 +54,7 @@ void SetUpStrings() {
size_t r = 0;
big_string = new std::string(1000 * 1000, ' ');
for (std::string phrase : {"the quick brown fox jumped over the lazy dogs",
- "pack my box with the five dozen liquor jugs"}) {
+ "pack my box with the five dozen liquor jugs"}) {
for (int i = 0; i < 10 * 1000; ++i) {
r = r * 237 + 41; // not very random.
memcpy(&(*big_string)[r % (big_string->size() - phrase.size())],
@@ -62,7 +62,7 @@ void SetUpStrings() {
}
}
// big_string->resize(50);
- // OK, we've set up the std::string, now let's set up expectations - first by
+ // OK, we've set up the string, now let's set up expectations - first by
// just replacing "the" with "box"
after_replacing_the = new std::string(*big_string);
for (size_t pos = 0;
@@ -108,11 +108,11 @@ void BM_StrReplaceAll(benchmark::State& state) {
std::string src = *big_string;
for (auto _ : state) {
std::string dest = absl::StrReplaceAll(src, {{"the", "box"},
- {"brown", "quick"},
- {"jumped", "liquored"},
- {"dozen", "brown"},
- {"lazy", "pack"},
- {"liquor", "shakes"}});
+ {"brown", "quick"},
+ {"jumped", "liquored"},
+ {"dozen", "brown"},
+ {"lazy", "pack"},
+ {"liquor", "shakes"}});
ABSL_RAW_CHECK(dest == *after_replacing_many,
"not benchmarking intended behavior");
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_test.cc
index 5d003a224a4..9d8c7f75b57 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_replace_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,7 +25,7 @@
TEST(StrReplaceAll, OneReplacement) {
std::string s;
- // Empty std::string.
+ // Empty string.
s = absl::StrReplaceAll(s, {{"", ""}});
EXPECT_EQ(s, "");
s = absl::StrReplaceAll(s, {{"x", ""}});
@@ -47,7 +47,7 @@ TEST(StrReplaceAll, OneReplacement) {
s = absl::StrReplaceAll("abc", {{"xyz", "123"}});
EXPECT_EQ(s, "abc");
- // Replace entire std::string.
+ // Replace entire string.
s = absl::StrReplaceAll("abc", {{"abc", "xyz"}});
EXPECT_EQ(s, "xyz");
@@ -88,7 +88,7 @@ TEST(StrReplaceAll, OneReplacement) {
TEST(StrReplaceAll, ManyReplacements) {
std::string s;
- // Empty std::string.
+ // Empty string.
s = absl::StrReplaceAll("", {{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}});
EXPECT_EQ(s, "");
@@ -96,7 +96,7 @@ TEST(StrReplaceAll, ManyReplacements) {
s = absl::StrReplaceAll("abc", {{"", ""}, {"", "y"}, {"x", ""}});
EXPECT_EQ(s, "abc");
- // Replace entire std::string, one char at a time
+ // Replace entire string, one char at a time
s = absl::StrReplaceAll("abc", {{"a", "x"}, {"b", "y"}, {"c", "z"}});
EXPECT_EQ(s, "xyz");
s = absl::StrReplaceAll("zxy", {{"z", "x"}, {"x", "y"}, {"y", "z"}});
@@ -148,7 +148,7 @@ TEST(StrReplaceAll, ManyReplacementsInMap) {
replacements["$count"] = "5";
replacements["#Noun"] = "Apples";
std::string s = absl::StrReplaceAll("$who bought $count #Noun. Thanks $who!",
- replacements);
+ replacements);
EXPECT_EQ("Bob bought 5 Apples. Thanks Bob!", s);
}
@@ -264,7 +264,7 @@ TEST(StrReplaceAll, Inplace) {
std::string s;
int reps;
- // Empty std::string.
+ // Empty string.
s = "";
reps = absl::StrReplaceAll({{"", ""}, {"x", ""}, {"", "y"}, {"x", "y"}}, &s);
EXPECT_EQ(reps, 0);
@@ -276,7 +276,7 @@ TEST(StrReplaceAll, Inplace) {
EXPECT_EQ(reps, 0);
EXPECT_EQ(s, "abc");
- // Replace entire std::string, one char at a time
+ // Replace entire string, one char at a time
s = "abc";
reps = absl::StrReplaceAll({{"a", "x"}, {"b", "y"}, {"c", "z"}}, &s);
EXPECT_EQ(reps, 3);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.cc
index 0a68c52d14f..e08c26b6bbb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,6 +27,7 @@
#include "absl/strings/ascii.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -41,7 +42,7 @@ absl::string_view GenericFind(absl::string_view text,
absl::string_view delimiter, size_t pos,
FindPolicy find_policy) {
if (delimiter.empty() && text.length() > 0) {
- // Special case for empty std::string delimiters: always return a zero-length
+ // Special case for empty string delimiters: always return a zero-length
// absl::string_view referring to the item at position 1 past pos.
return absl::string_view(text.data() + pos + 1, 0);
}
@@ -126,7 +127,7 @@ absl::string_view ByLength::Find(absl::string_view text,
size_t pos) const {
pos = std::min(pos, text.size()); // truncate `pos`
absl::string_view substr = text.substr(pos);
- // If the std::string is shorter than the chunk size we say we
+ // If the string is shorter than the chunk size we say we
// "can't find the delimiter" so this will be the last chunk.
if (substr.length() <= static_cast<size_t>(length_))
return absl::string_view(text.data() + text.size(), 0);
@@ -134,4 +135,5 @@ absl::string_view ByLength::Find(absl::string_view text,
return absl::string_view(substr.data() + length_, 0);
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.h
index c7eb280c411..bfbca422a8d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -44,11 +44,13 @@
#include <vector>
#include "absl/base/internal/raw_logging.h"
+#include "absl/base/macros.h"
#include "absl/strings/internal/str_split_internal.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Delimiters
@@ -71,23 +73,23 @@ namespace absl {
// - `ByLength`
// - `MaxSplits`
//
-//
-// A Delimiter's Find() member function will be passed the input text that is to
-// be split and the position to begin searching for the next delimiter in the
-// input text. The returned absl::string_view should refer to the next
-// occurrence (after pos) of the represented delimiter; this returned
-// absl::string_view represents the next location where the input string should
-// be broken. The returned absl::string_view may be zero-length if the Delimiter
-// does not represent a part of the string (e.g., a fixed-length delimiter). If
-// no delimiter is found in the given text, a zero-length absl::string_view
-// referring to text.end() should be returned (e.g.,
-// absl::string_view(text.end(), 0)). It is important that the returned
-// absl::string_view always be within the bounds of input text given as an
+// A Delimiter's `Find()` member function will be passed an input `text` that is
+// to be split and a position (`pos`) to begin searching for the next delimiter
+// in `text`. The returned absl::string_view should refer to the next occurrence
+// (after `pos`) of the represented delimiter; this returned absl::string_view
+// represents the next location where the input `text` should be broken.
+//
+// The returned absl::string_view may be zero-length if the Delimiter does not
+// represent a part of the string (e.g., a fixed-length delimiter). If no
+// delimiter is found in the input `text`, a zero-length absl::string_view
+// referring to `text.end()` should be returned (e.g.,
+// `text.substr(text.size())`). It is important that the returned
+// absl::string_view always be within the bounds of the input `text` given as an
// argument--it must not refer to a string that is physically located outside of
// the given string.
//
// The following example is a simple Delimiter object that is created with a
-// single char and will look for that char in the text passed to the Find()
+// single char and will look for that char in the text passed to the `Find()`
// function:
//
// struct SimpleDelimiter {
@@ -96,9 +98,9 @@ namespace absl {
// absl::string_view Find(absl::string_view text, size_t pos) {
// auto found = text.find(c_, pos);
// if (found == absl::string_view::npos)
-// return absl::string_view(text.end(), 0);
+// return text.substr(text.size());
//
-// return absl::string_view(text, found, 1);
+// return text.substr(found, 1);
// }
// };
@@ -131,8 +133,7 @@ class ByString {
// ByChar
//
// A single character delimiter. `ByChar` is functionally equivalent to a
-// 1-char string within a `ByString` delimiter, but slightly more
-// efficient.
+// 1-char string within a `ByString` delimiter, but slightly more efficient.
//
// Example:
//
@@ -368,6 +369,12 @@ struct SkipWhitespace {
}
};
+template <typename T>
+using EnableSplitIfString =
+ typename std::enable_if<std::is_same<T, std::string>::value ||
+ std::is_same<T, const std::string>::value,
+ int>::type;
+
//------------------------------------------------------------------------------
// StrSplit()
//------------------------------------------------------------------------------
@@ -413,10 +420,10 @@ struct SkipWhitespace {
//
// The `StrSplit()` function adapts the returned collection to the collection
// specified by the caller (e.g. `std::vector` above). The returned collections
-// may contain `string`, `absl::string_view` (in which case the original string
-// being split must ensure that it outlives the collection), or any object that
-// can be explicitly created from an `absl::string_view`. This behavior works
-// for:
+// may contain `std::string`, `absl::string_view` (in which case the original
+// string being split must ensure that it outlives the collection), or any
+// object that can be explicitly created from an `absl::string_view`. This
+// behavior works for:
//
// 1) All standard STL containers including `std::vector`, `std::list`,
// `std::deque`, `std::set`,`std::multiset`, 'std::map`, and `std::multimap`
@@ -460,7 +467,7 @@ struct SkipWhitespace {
// Example:
//
// // Stores first two split strings as the members in a std::pair.
-// std::pair<string, string> p = absl::StrSplit("a,b,c", ',');
+// std::pair<std::string, std::string> p = absl::StrSplit("a,b,c", ',');
// // p.first == "a", p.second == "b" // "c" is omitted.
//
// The `StrSplit()` function can be used multiple times to perform more
@@ -470,7 +477,7 @@ struct SkipWhitespace {
//
// // The input string "a=b=c,d=e,f=,g" becomes
// // { "a" => "b=c", "d" => "e", "f" => "", "g" => "" }
-// std::map<string, string> m;
+// std::map<std::string, std::string> m;
// for (absl::string_view sp : absl::StrSplit("a=b=c,d=e,f=,g", ',')) {
// m.insert(absl::StrSplit(sp, absl::MaxSplits('=', 1)));
// }
@@ -488,25 +495,54 @@ struct SkipWhitespace {
// Try not to depend on this distinction because the bug may one day be fixed.
template <typename Delimiter>
strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+ absl::string_view>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, AllowEmpty>(
+ return strings_internal::Splitter<DelimiterType, AllowEmpty,
+ absl::string_view>(
+ text.value(), DelimiterType(d), AllowEmpty());
+}
+
+template <typename Delimiter, typename StringType,
+ EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+ typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty,
+ std::string>
+StrSplit(StringType&& text, Delimiter d) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
+ return strings_internal::Splitter<DelimiterType, AllowEmpty, std::string>(
std::move(text), DelimiterType(d), AllowEmpty());
}
template <typename Delimiter, typename Predicate>
strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+ absl::string_view>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
Predicate p) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- return strings_internal::Splitter<DelimiterType, Predicate>(
+ return strings_internal::Splitter<DelimiterType, Predicate,
+ absl::string_view>(
+ text.value(), DelimiterType(d), std::move(p));
+}
+
+template <typename Delimiter, typename Predicate, typename StringType,
+ EnableSplitIfString<StringType> = 0>
+strings_internal::Splitter<
+ typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
+ std::string>
+StrSplit(StringType&& text, Delimiter d, Predicate p) {
+ using DelimiterType =
+ typename strings_internal::SelectDelimiter<Delimiter>::type;
+ return strings_internal::Splitter<DelimiterType, Predicate, std::string>(
std::move(text), DelimiterType(d), std::move(p));
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STR_SPLIT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_benchmark.cc
index 0ac297c83ad..f38dfcfe5af 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -44,6 +44,29 @@ void BM_Split2StringView(benchmark::State& state) {
}
BENCHMARK_RANGE(BM_Split2StringView, 0, 1 << 20);
+static const absl::string_view kDelimiters = ";:,.";
+
+std::string MakeMultiDelimiterTestString(int desired_length) {
+ static const int kAverageValueLen = 25;
+ std::string test(desired_length * kAverageValueLen, 'x');
+ for (int i = 0; i * kAverageValueLen < test.size(); ++i) {
+ // Cycle through a variety of delimiters.
+ test[i * kAverageValueLen] = kDelimiters[i % kDelimiters.size()];
+ }
+ return test;
+}
+
+// Measure StrSplit with ByAnyChar with four delimiters to choose from.
+void BM_Split2StringViewByAnyChar(benchmark::State& state) {
+ std::string test = MakeMultiDelimiterTestString(state.range(0));
+ for (auto _ : state) {
+ std::vector<absl::string_view> result =
+ absl::StrSplit(test, absl::ByAnyChar(kDelimiters));
+ benchmark::DoNotOptimize(result);
+ }
+}
+BENCHMARK_RANGE(BM_Split2StringViewByAnyChar, 0, 1 << 20);
+
void BM_Split2StringViewLifted(benchmark::State& state) {
std::string test = MakeTestString(state.range(0));
std::vector<absl::string_view> result;
@@ -69,7 +92,8 @@ BENCHMARK_RANGE(BM_Split2String, 0, 1 << 20);
void BM_Split2SplitStringUsing(benchmark::State& state) {
std::string test = MakeTestString(state.range(0));
for (auto _ : state) {
- std::vector<std::string> result = absl::StrSplit(test, ';', absl::SkipEmpty());
+ std::vector<std::string> result =
+ absl::StrSplit(test, ';', absl::SkipEmpty());
benchmark::DoNotOptimize(result);
}
}
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_test.cc
index caa882776c5..7f7c097faee 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/str_split_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,8 +27,10 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/base/dynamic_annotations.h" // for RunningOnValgrind
+#include "absl/base/dynamic_annotations.h"
#include "absl/base/macros.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/node_hash_map.h"
#include "absl/strings/numbers.h"
namespace {
@@ -40,8 +42,8 @@ using ::testing::UnorderedElementsAre;
TEST(Split, TraitsTest) {
static_assert(!absl::strings_internal::SplitterIsConvertibleTo<int>::value,
"");
- static_assert(!absl::strings_internal::SplitterIsConvertibleTo<std::string>::value,
- "");
+ static_assert(
+ !absl::strings_internal::SplitterIsConvertibleTo<std::string>::value, "");
static_assert(absl::strings_internal::SplitterIsConvertibleTo<
std::vector<std::string>>::value,
"");
@@ -71,8 +73,8 @@ TEST(Split, TraitsTest) {
// namespaces just like callers will need to use.
TEST(Split, APIExamples) {
{
- // Passes std::string delimiter. Assumes the default of Literal.
- std::vector<std::string> v = absl::StrSplit("a,b,c", ',');
+ // Passes string delimiter. Assumes the default of ByString.
+ std::vector<std::string> v = absl::StrSplit("a,b,c", ","); // NOLINT
EXPECT_THAT(v, ElementsAre("a", "b", "c"));
// Equivalent to...
@@ -97,18 +99,7 @@ TEST(Split, APIExamples) {
}
{
- // Same as above, but using std::string
- std::vector<std::string> v = absl::StrSplit("a,b,c", ',');
- EXPECT_THAT(v, ElementsAre("a", "b", "c"));
-
- // Equivalent to...
- using absl::ByChar;
- v = absl::StrSplit("a,b,c", ByChar(','));
- EXPECT_THAT(v, ElementsAre("a", "b", "c"));
- }
-
- {
- // Uses the Literal std::string "=>" as the delimiter.
+ // Uses the Literal string "=>" as the delimiter.
const std::vector<std::string> v = absl::StrSplit("a=>b=>c", "=>");
EXPECT_THAT(v, ElementsAre("a", "b", "c"));
}
@@ -132,17 +123,17 @@ TEST(Split, APIExamples) {
}
{
- // Splits the input std::string into individual characters by using an empty
- // std::string as the delimiter.
+ // Splits the input string into individual characters by using an empty
+ // string as the delimiter.
std::vector<std::string> v = absl::StrSplit("abc", "");
EXPECT_THAT(v, ElementsAre("a", "b", "c"));
}
{
- // Splits std::string data with embedded NUL characters, using NUL as the
+ // Splits string data with embedded NUL characters, using NUL as the
// delimiter. A simple delimiter of "\0" doesn't work because strlen() will
- // say that's the empty std::string when constructing the absl::string_view
- // delimiter. Instead, a non-empty std::string containing NUL can be used as the
+ // say that's the empty string when constructing the absl::string_view
+ // delimiter. Instead, a non-empty string containing NUL can be used as the
// delimiter.
std::string embedded_nulls("a\0b\0c", 5);
std::string null_delim("\0", 1);
@@ -182,7 +173,8 @@ TEST(Split, APIExamples) {
{
// Uses the SkipWhitespace predicate.
using absl::SkipWhitespace;
- std::vector<std::string> v = absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
+ std::vector<std::string> v =
+ absl::StrSplit(" a , ,,b,", ',', SkipWhitespace());
EXPECT_THAT(v, ElementsAre(" a ", "b"));
}
@@ -215,7 +207,8 @@ TEST(Split, APIExamples) {
{
// Results stored in a std::multimap.
- std::multimap<std::string, std::string> m = absl::StrSplit("a,1,b,2,a,3", ',');
+ std::multimap<std::string, std::string> m =
+ absl::StrSplit("a,1,b,2,a,3", ',');
EXPECT_EQ(3, m.size());
auto it = m.find("a");
EXPECT_EQ("1", it->second);
@@ -271,7 +264,8 @@ TEST(SplitIterator, Basics) {
EXPECT_EQ("a", *it); // tests dereference
++it; // tests preincrement
EXPECT_NE(it, end);
- EXPECT_EQ("b", std::string(it->data(), it->size())); // tests dereference as ptr
+ EXPECT_EQ("b",
+ std::string(it->data(), it->size())); // tests dereference as ptr
it++; // tests postincrement
EXPECT_EQ(it, end);
}
@@ -295,7 +289,8 @@ TEST(SplitIterator, Predicate) {
EXPECT_EQ("a", *it); // tests dereference
++it; // tests preincrement -- "b" should be skipped here.
EXPECT_NE(it, end);
- EXPECT_EQ("c", std::string(it->data(), it->size())); // tests dereference as ptr
+ EXPECT_EQ("c",
+ std::string(it->data(), it->size())); // tests dereference as ptr
it++; // tests postincrement
EXPECT_EQ(it, end);
}
@@ -372,7 +367,7 @@ TEST(SplitIterator, EqualityAsEndCondition) {
TEST(Splitter, RangeIterators) {
auto splitter = absl::StrSplit("a,b,c", ',');
std::vector<absl::string_view> output;
- for (const absl::string_view p : splitter) {
+ for (const absl::string_view& p : splitter) {
output.push_back(p);
}
EXPECT_THAT(output, ElementsAre("a", "b", "c"));
@@ -421,10 +416,25 @@ TEST(Splitter, ConversionOperator) {
TestMapConversionOperator<std::map<std::string, std::string>>(splitter);
TestMapConversionOperator<
std::multimap<absl::string_view, absl::string_view>>(splitter);
- TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(splitter);
- TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(splitter);
+ TestMapConversionOperator<std::multimap<absl::string_view, std::string>>(
+ splitter);
+ TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(
+ splitter);
TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
- TestMapConversionOperator<std::unordered_map<std::string, std::string>>(splitter);
+ TestMapConversionOperator<std::unordered_map<std::string, std::string>>(
+ splitter);
+ TestMapConversionOperator<
+ absl::node_hash_map<absl::string_view, absl::string_view>>(splitter);
+ TestMapConversionOperator<
+ absl::node_hash_map<absl::string_view, std::string>>(splitter);
+ TestMapConversionOperator<
+ absl::node_hash_map<std::string, absl::string_view>>(splitter);
+ TestMapConversionOperator<
+ absl::flat_hash_map<absl::string_view, absl::string_view>>(splitter);
+ TestMapConversionOperator<
+ absl::flat_hash_map<absl::string_view, std::string>>(splitter);
+ TestMapConversionOperator<
+ absl::flat_hash_map<std::string, absl::string_view>>(splitter);
// Tests conversion to std::pair
@@ -440,7 +450,7 @@ TEST(Splitter, ConversionOperator) {
// less-than, equal-to, and more-than 2 strings.
TEST(Splitter, ToPair) {
{
- // Empty std::string
+ // Empty string
std::pair<std::string, std::string> p = absl::StrSplit("", ',');
EXPECT_EQ("", p.first);
EXPECT_EQ("", p.second);
@@ -568,10 +578,9 @@ TEST(Split, AcceptsCertainTemporaries) {
}
TEST(Split, Temporary) {
- // Use a std::string longer than the small-std::string-optimization length, so that when
- // the temporary is destroyed, if the splitter keeps a reference to the
- // std::string's contents, it'll reference freed memory instead of just dead
- // on-stack memory.
+ // Use a std::string longer than the SSO length, so that when the temporary is
+ // destroyed, if the splitter keeps a reference to the string's contents,
+ // it'll reference freed memory instead of just dead on-stack memory.
const char input[] = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u";
EXPECT_LT(sizeof(std::string), ABSL_ARRAYSIZE(input))
<< "Input should be larger than fits on the stack.";
@@ -647,18 +656,23 @@ TEST(Split, StringDelimiter) {
}
}
+#if !defined(__cpp_char8_t)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++2a-compat"
+#endif
TEST(Split, UTF8) {
// Tests splitting utf8 strings and utf8 delimiters.
std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5";
{
- // A utf8 input std::string with an ascii delimiter.
+ // A utf8 input string with an ascii delimiter.
std::string to_split = "a," + utf8_string;
std::vector<absl::string_view> v = absl::StrSplit(to_split, ',');
EXPECT_THAT(v, ElementsAre("a", utf8_string));
}
{
- // A utf8 input std::string and a utf8 delimiter.
+ // A utf8 input string and a utf8 delimiter.
std::string to_split = "a," + utf8_string + ",b";
std::string unicode_delimiter = "," + utf8_string + ",";
std::vector<absl::string_view> v =
@@ -667,12 +681,16 @@ TEST(Split, UTF8) {
}
{
- // A utf8 input std::string and ByAnyChar with ascii chars.
+ // A utf8 input string and ByAnyChar with ascii chars.
std::vector<absl::string_view> v =
absl::StrSplit(u8"Foo h\u00E4llo th\u4E1Ere", absl::ByAnyChar(" \t"));
EXPECT_THAT(v, ElementsAre("Foo", u8"h\u00E4llo", u8"th\u4E1Ere"));
}
}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
+#endif // !defined(__cpp_char8_t)
TEST(Split, EmptyStringDelimiter) {
{
@@ -782,7 +800,7 @@ static bool IsFoundAt(absl::string_view text, Delimiter d, int expected_pos) {
}
//
-// Tests for Literal
+// Tests for ByString
//
// Tests using any delimiter that represents a single comma.
@@ -802,7 +820,7 @@ void TestComma(Delimiter d) {
EXPECT_FALSE(IsFoundAt(";", d, -1));
}
-TEST(Delimiter, Literal) {
+TEST(Delimiter, ByString) {
using absl::ByString;
TestComma(ByString(","));
@@ -810,10 +828,10 @@ TEST(Delimiter, Literal) {
ByString comma_string(",");
TestComma(comma_string);
- // The first occurrence of empty std::string ("") in a std::string is at position 0.
+ // The first occurrence of empty string ("") in a string is at position 0.
// There is a test below that demonstrates this for absl::string_view::find().
// If the ByString delimiter returned position 0 for this, there would
- // be an infinite loop in the SplitIterator code. To avoid this, empty std::string
+ // be an infinite loop in the SplitIterator code. To avoid this, empty string
// is a special case in that it always returns the item at position 1.
absl::string_view abc("abc");
EXPECT_EQ(0, abc.find("")); // "" is found at position 0
@@ -872,7 +890,7 @@ TEST(Delimiter, ByAnyChar) {
EXPECT_FALSE(IsFoundAt("=", two_delims, -1));
// ByAnyChar behaves just like ByString when given a delimiter of empty
- // std::string. That is, it always returns a zero-length absl::string_view
+ // string. That is, it always returns a zero-length absl::string_view
// referring to the item at position 1, not position 0.
ByAnyChar empty("");
EXPECT_FALSE(IsFoundAt("", empty, 0));
@@ -909,7 +927,7 @@ TEST(Split, WorksWithLargeStrings) {
std::vector<absl::string_view> v = absl::StrSplit(s, '-');
EXPECT_EQ(2, v.size());
// The first element will contain 2G of 'x's.
- // testing::StartsWith is too slow with a 2G std::string.
+ // testing::StartsWith is too slow with a 2G string.
EXPECT_EQ('x', v[0][0]);
EXPECT_EQ('x', v[0][1]);
EXPECT_EQ('x', v[0][3]);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.cc
index 4ceeb6bff58..c5f5de936de 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,7 @@
#include "absl/strings/string_view.h"
-#ifndef ABSL_HAVE_STD_STRING_VIEW
+#ifndef ABSL_USES_STD_STRING_VIEW
#include <algorithm>
#include <climits>
@@ -24,6 +24,7 @@
#include "absl/strings/internal/memutil.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
void WritePadding(std::ostream& o, size_t pad) {
@@ -77,18 +78,6 @@ std::ostream& operator<<(std::ostream& o, string_view piece) {
return o;
}
-string_view::size_type string_view::copy(char* buf, size_type n,
- size_type pos) const {
- size_type ulen = length_;
- assert(pos <= ulen);
- size_type rlen = std::min(ulen - pos, n);
- if (rlen > 0) {
- const char* start = ptr_ + pos;
- std::copy(start, start + rlen, buf);
- }
- return rlen;
-}
-
string_view::size_type string_view::find(string_view s, size_type pos) const
noexcept {
if (empty() || pos > length_) {
@@ -228,7 +217,7 @@ string_view::size_type string_view::find_last_not_of(char c,
// member definitions that are required by the C++ standard, resulting in
// LNK1169 "multiply defined" errors at link time. __declspec(selectany) asks
// MSVC to choose only one definition for the symbol it decorates. See details
-// at http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
+// at https://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx
#ifdef _MSC_VER
#define ABSL_STRING_VIEW_SELECTANY __declspec(selectany)
#else
@@ -240,6 +229,7 @@ constexpr string_view::size_type string_view::npos;
ABSL_STRING_VIEW_SELECTANY
constexpr string_view::size_type string_view::kMaxSize;
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_STRING_VIEW
+#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.h
index 8cd4fa24e2b..5260b5b73f4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,18 +28,6 @@
#define ABSL_STRINGS_STRING_VIEW_H_
#include <algorithm>
-#include "absl/base/config.h"
-
-#ifdef ABSL_HAVE_STD_STRING_VIEW
-
-#include <string_view>
-
-namespace absl {
-using std::string_view;
-} // namespace absl
-
-#else // ABSL_HAVE_STD_STRING_VIEW
-
#include <cassert>
#include <cstddef>
#include <cstring>
@@ -48,11 +36,33 @@ using std::string_view;
#include <limits>
#include <string>
+#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
+#include "absl/base/optimization.h"
#include "absl/base/port.h"
+#ifdef ABSL_USES_STD_STRING_VIEW
+
+#include <string_view> // IWYU pragma: export
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
+using string_view = std::string_view;
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#else // ABSL_USES_STD_STRING_VIEW
+
+#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP __builtin_memcmp
+#else // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
+#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
// absl::string_view
//
@@ -101,18 +111,22 @@ namespace absl {
// example, when splitting a string, `std::vector<absl::string_view>` is a
// natural data type for the output.
//
+// For another example, a Cord is a non-contiguous, potentially very
+// long string-like object. The Cord class has an interface that iteratively
+// provides string_view objects that point to the successive pieces of a Cord
+// object.
//
-// When constructed from a source which is nul-terminated, the `string_view`
-// itself will not include the nul-terminator unless a specific size (including
-// the nul) is passed to the constructor. As a result, common idioms that work
-// on nul-terminated strings do not work on `string_view` objects. If you write
+// When constructed from a source which is NUL-terminated, the `string_view`
+// itself will not include the NUL-terminator unless a specific size (including
+// the NUL) is passed to the constructor. As a result, common idioms that work
+// on NUL-terminated strings do not work on `string_view` objects. If you write
// code that scans a `string_view`, you must check its length rather than test
// for nul, for example. Note, however, that nuls may still be embedded within
// a `string_view` explicitly.
//
// You may create a null `string_view` in two ways:
//
-// absl::string_view sv();
+// absl::string_view sv;
// absl::string_view sv(nullptr, 0);
//
// For the above, `sv.data() == nullptr`, `sv.length() == 0`, and
@@ -168,24 +182,16 @@ class string_view {
string_view( // NOLINT(runtime/explicit)
const std::basic_string<char, std::char_traits<char>, Allocator>&
str) noexcept
- : ptr_(str.data()), length_(CheckLengthInternal(str.size())) {}
+ // This is implemented in terms of `string_view(p, n)` so `str.size()`
+ // doesn't need to be reevaluated after `ptr_` is set.
+ : string_view(str.data(), str.size()) {}
- // Implicit constructor of a `string_view` from nul-terminated `str`. When
+ // Implicit constructor of a `string_view` from NUL-terminated `str`. When
// accepting possibly null strings, use `absl::NullSafeStringView(str)`
// instead (see below).
-#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
- (defined(__GNUC__) && !defined(__clang__))
- // GCC has __builtin_strlen according to
- // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
- // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
- // __builtin_strlen is constexpr.
constexpr string_view(const char* str) // NOLINT(runtime/explicit)
: ptr_(str),
- length_(CheckLengthInternal(str ? __builtin_strlen(str) : 0)) {}
-#else
- constexpr string_view(const char* str) // NOLINT(runtime/explicit)
- : ptr_(str), length_(CheckLengthInternal(str ? strlen(str) : 0)) {}
-#endif
+ length_(str ? CheckLengthInternal(StrlenInternal(str)) : 0) {}
// Implicit constructor of a `string_view` from a `const char*` and length.
constexpr string_view(const char* data, size_type len)
@@ -277,29 +283,48 @@ class string_view {
// Checks if the `string_view` is empty (refers to no characters).
constexpr bool empty() const noexcept { return length_ == 0; }
- // std::string:view::operator[]
+ // string_view::operator[]
//
- // Returns the ith element of an `string_view` using the array operator.
+ // Returns the ith element of the `string_view` using the array operator.
// Note that this operator does not perform any bounds checking.
- constexpr const_reference operator[](size_type i) const { return ptr_[i]; }
+ constexpr const_reference operator[](size_type i) const {
+ return ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+ }
+
+ // string_view::at()
+ //
+ // Returns the ith element of the `string_view`. Bounds checking is performed,
+ // and an exception of type `std::out_of_range` will be thrown on invalid
+ // access.
+ constexpr const_reference at(size_type i) const {
+ return ABSL_PREDICT_TRUE(i < size())
+ ? ptr_[i]
+ : ((void)base_internal::ThrowStdOutOfRange(
+ "absl::string_view::at"),
+ ptr_[i]);
+ }
// string_view::front()
//
// Returns the first element of a `string_view`.
- constexpr const_reference front() const { return ptr_[0]; }
+ constexpr const_reference front() const {
+ return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+ }
// string_view::back()
//
// Returns the last element of a `string_view`.
- constexpr const_reference back() const { return ptr_[size() - 1]; }
+ constexpr const_reference back() const {
+ return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
+ }
// string_view::data()
//
// Returns a pointer to the underlying character array (which is of course
// stored elsewhere). Note that `string_view::data()` may contain embedded nul
- // characters, but the returned buffer may or may not be nul-terminated;
- // therefore, do not pass `data()` to a routine that expects a nul-terminated
- // std::string.
+ // characters, but the returned buffer may or may not be NUL-terminated;
+ // therefore, do not pass `data()` to a routine that expects a NUL-terminated
+ // string.
constexpr const_pointer data() const noexcept { return ptr_; }
// Modifiers
@@ -307,9 +332,9 @@ class string_view {
// string_view::remove_prefix()
//
// Removes the first `n` characters from the `string_view`. Note that the
- // underlying std::string is not changed, only the view.
+ // underlying string is not changed, only the view.
void remove_prefix(size_type n) {
- assert(n <= length_);
+ ABSL_HARDENING_ASSERT(n <= length_);
ptr_ += n;
length_ -= n;
}
@@ -317,9 +342,9 @@ class string_view {
// string_view::remove_suffix()
//
// Removes the last `n` characters from the `string_view`. Note that the
- // underlying std::string is not changed, only the view.
+ // underlying string is not changed, only the view.
void remove_suffix(size_type n) {
- assert(n <= length_);
+ ABSL_HARDENING_ASSERT(n <= length_);
length_ -= n;
}
@@ -345,38 +370,46 @@ class string_view {
//
// Copies the contents of the `string_view` at offset `pos` and length `n`
// into `buf`.
- size_type copy(char* buf, size_type n, size_type pos = 0) const;
+ size_type copy(char* buf, size_type n, size_type pos = 0) const {
+ if (ABSL_PREDICT_FALSE(pos > length_)) {
+ base_internal::ThrowStdOutOfRange("absl::string_view::copy");
+ }
+ size_type rlen = (std::min)(length_ - pos, n);
+ if (rlen > 0) {
+ const char* start = ptr_ + pos;
+ traits_type::copy(buf, start, rlen);
+ }
+ return rlen;
+ }
// string_view::substr()
//
// Returns a "substring" of the `string_view` (at offset `pos` and length
// `n`) as another string_view. This function throws `std::out_of_bounds` if
// `pos > size`.
- string_view substr(size_type pos, size_type n = npos) const {
- if (ABSL_PREDICT_FALSE(pos > length_))
- base_internal::ThrowStdOutOfRange("absl::string_view::substr");
- n = (std::min)(n, length_ - pos);
- return string_view(ptr_ + pos, n);
+ // Use absl::ClippedSubstr if you need a truncating substr operation.
+ constexpr string_view substr(size_type pos, size_type n = npos) const {
+ return ABSL_PREDICT_FALSE(pos > length_)
+ ? (base_internal::ThrowStdOutOfRange(
+ "absl::string_view::substr"),
+ string_view())
+ : string_view(ptr_ + pos, Min(n, length_ - pos));
}
// string_view::compare()
//
// Performs a lexicographical comparison between the `string_view` and
// another `absl::string_view`, returning -1 if `this` is less than, 0 if
- // `this` is equal to, and 1 if `this` is greater than the passed std::string
+ // `this` is equal to, and 1 if `this` is greater than the passed string
// view. Note that in the case of data equality, a further comparison is made
// on the respective sizes of the two `string_view`s to determine which is
// smaller, equal, or greater.
- int compare(string_view x) const noexcept {
- auto min_length = (std::min)(length_, x.length_);
- if (min_length > 0) {
- int r = memcmp(ptr_, x.ptr_, min_length);
- if (r < 0) return -1;
- if (r > 0) return 1;
- }
- if (length_ < x.length_) return -1;
- if (length_ > x.length_) return 1;
- return 0;
+ constexpr int compare(string_view x) const noexcept {
+ return CompareImpl(length_, x.length_,
+ Min(length_, x.length_) == 0
+ ? 0
+ : ABSL_INTERNAL_STRING_VIEW_MEMCMP(
+ ptr_, x.ptr_, Min(length_, x.length_)));
}
// Overload of `string_view::compare()` for comparing a substring of the
@@ -393,17 +426,17 @@ class string_view {
}
// Overload of `string_view::compare()` for comparing a `string_view` and a
- // a different C-style std::string `s`.
+ // a different C-style string `s`.
int compare(const char* s) const { return compare(string_view(s)); }
// Overload of `string_view::compare()` for comparing a substring of the
- // `string_view` and a different std::string C-style std::string `s`.
+ // `string_view` and a different string C-style string `s`.
int compare(size_type pos1, size_type count1, const char* s) const {
return substr(pos1, count1).compare(string_view(s));
}
// Overload of `string_view::compare()` for comparing a substring of the
- // `string_view` and a substring of a different C-style std::string `s`.
+ // `string_view` and a substring of a different C-style string `s`.
int compare(size_type pos1, size_type count1, const char* s,
size_type count2) const {
return substr(pos1, count1).compare(string_view(s, count2));
@@ -493,7 +526,36 @@ class string_view {
(std::numeric_limits<difference_type>::max)();
static constexpr size_type CheckLengthInternal(size_type len) {
- return ABSL_ASSERT(len <= kMaxSize), len;
+ return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
+ }
+
+ static constexpr size_type StrlenInternal(const char* str) {
+#if defined(_MSC_VER) && _MSC_VER >= 1910 && !defined(__clang__)
+ // MSVC 2017+ can evaluate this at compile-time.
+ const char* begin = str;
+ while (*str != '\0') ++str;
+ return str - begin;
+#elif ABSL_HAVE_BUILTIN(__builtin_strlen) || \
+ (defined(__GNUC__) && !defined(__clang__))
+ // GCC has __builtin_strlen according to
+ // https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Other-Builtins.html, but
+ // ABSL_HAVE_BUILTIN doesn't detect that, so we use the extra checks above.
+ // __builtin_strlen is constexpr.
+ return __builtin_strlen(str);
+#else
+ return str ? strlen(str) : 0;
+#endif
+ }
+
+ static constexpr size_t Min(size_type length_a, size_type length_b) {
+ return length_a < length_b ? length_a : length_b;
+ }
+
+ static constexpr int CompareImpl(size_type length_a, size_type length_b,
+ int compare_result) {
+ return compare_result == 0 ? static_cast<int>(length_a > length_b) -
+ static_cast<int>(length_a < length_b)
+ : (compare_result < 0 ? -1 : 1);
}
const char* ptr_;
@@ -503,43 +565,44 @@ class string_view {
// This large function is defined inline so that in a fairly common case where
// one of the arguments is a literal, the compiler can elide a lot of the
// following comparisons.
-inline bool operator==(string_view x, string_view y) noexcept {
- auto len = x.size();
- if (len != y.size()) {
- return false;
- }
- return x.data() == y.data() || len <= 0 ||
- memcmp(x.data(), y.data(), len) == 0;
+constexpr bool operator==(string_view x, string_view y) noexcept {
+ return x.size() == y.size() &&
+ (x.empty() ||
+ ABSL_INTERNAL_STRING_VIEW_MEMCMP(x.data(), y.data(), x.size()) == 0);
}
-inline bool operator!=(string_view x, string_view y) noexcept {
+constexpr bool operator!=(string_view x, string_view y) noexcept {
return !(x == y);
}
-inline bool operator<(string_view x, string_view y) noexcept {
- auto min_size = (std::min)(x.size(), y.size());
- const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size);
- return (r < 0) || (r == 0 && x.size() < y.size());
+constexpr bool operator<(string_view x, string_view y) noexcept {
+ return x.compare(y) < 0;
}
-inline bool operator>(string_view x, string_view y) noexcept { return y < x; }
+constexpr bool operator>(string_view x, string_view y) noexcept {
+ return y < x;
+}
-inline bool operator<=(string_view x, string_view y) noexcept {
+constexpr bool operator<=(string_view x, string_view y) noexcept {
return !(y < x);
}
-inline bool operator>=(string_view x, string_view y) noexcept {
+constexpr bool operator>=(string_view x, string_view y) noexcept {
return !(x < y);
}
// IO Insertion Operator
std::ostream& operator<<(std::ostream& o, string_view piece);
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_STRING_VIEW
+#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
+
+#endif // ABSL_USES_STD_STRING_VIEW
namespace absl {
+ABSL_NAMESPACE_BEGIN
// ClippedSubstr()
//
@@ -556,10 +619,11 @@ inline string_view ClippedSubstr(string_view s, size_t pos,
// Creates an `absl::string_view` from a pointer `p` even if it's null-valued.
// This function should be used where an `absl::string_view` can be created from
// a possibly-null pointer.
-inline string_view NullSafeStringView(const char* p) {
+constexpr string_view NullSafeStringView(const char* p) {
return p ? string_view(p) : string_view();
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STRING_VIEW_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_benchmark.cc
index f44203208fe..0d74e23e2fc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,6 +30,24 @@
namespace {
+void BM_StringViewFromString(benchmark::State& state) {
+ std::string s(state.range(0), 'x');
+ std::string* ps = &s;
+ struct SV {
+ SV() = default;
+ explicit SV(const std::string& s) : sv(s) {}
+ absl::string_view sv;
+ } sv;
+ SV* psv = &sv;
+ benchmark::DoNotOptimize(ps);
+ benchmark::DoNotOptimize(psv);
+ for (auto _ : state) {
+ new (psv) SV(*ps);
+ benchmark::DoNotOptimize(sv);
+ }
+}
+BENCHMARK(BM_StringViewFromString)->Arg(12)->Arg(128);
+
// Provide a forcibly out-of-line wrapper for operator== that can be used in
// benchmarks to measure the impact of inlining.
ABSL_ATTRIBUTE_NOINLINE
@@ -142,11 +160,45 @@ void BM_CompareSame(benchmark::State& state) {
absl::string_view b = y;
for (auto _ : state) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
benchmark::DoNotOptimize(a.compare(b));
}
}
BENCHMARK(BM_CompareSame)->DenseRange(0, 3)->Range(4, 1 << 10);
+void BM_CompareFirstOneLess(benchmark::State& state) {
+ const int len = state.range(0);
+ std::string x(len, 'a');
+ std::string y = x;
+ y.back() = 'b';
+ absl::string_view a = x;
+ absl::string_view b = y;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ benchmark::DoNotOptimize(a.compare(b));
+ }
+}
+BENCHMARK(BM_CompareFirstOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
+
+void BM_CompareSecondOneLess(benchmark::State& state) {
+ const int len = state.range(0);
+ std::string x(len, 'a');
+ std::string y = x;
+ x.back() = 'b';
+ absl::string_view a = x;
+ absl::string_view b = y;
+
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(a);
+ benchmark::DoNotOptimize(b);
+ benchmark::DoNotOptimize(a.compare(b));
+ }
+}
+BENCHMARK(BM_CompareSecondOneLess)->DenseRange(1, 3)->Range(4, 1 << 10);
+
void BM_find_string_view_len_one(benchmark::State& state) {
std::string haystack(state.range(0), '0');
absl::string_view s(haystack);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_test.cc
index ed34ed83237..643af8f81b8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/string_view_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,8 +28,10 @@
#include "gtest/gtest.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
+#include "absl/base/options.h"
-#ifdef __ANDROID__
+#if defined(ABSL_HAVE_STD_STRING_VIEW) || defined(__ANDROID__)
+// We don't control the death messaging when using std::string_view.
// Android assert messages only go to system log, so death tests cannot inspect
// the message for matching.
#define ABSL_EXPECT_DEATH_IF_SUPPORTED(statement, regex) \
@@ -284,9 +286,10 @@ TEST(StringViewTest, ComparisonOperatorsByCharacterPosition) {
}
#undef COMPARE
-// Sadly, our users often confuse string::npos with absl::string_view::npos;
-// So much so that we test here that they are the same. They need to
-// both be unsigned, and both be the maximum-valued integer of their type.
+// Sadly, our users often confuse std::string::npos with
+// absl::string_view::npos; So much so that we test here that they are the same.
+// They need to both be unsigned, and both be the maximum-valued integer of
+// their type.
template <typename T>
struct is_type {
@@ -368,6 +371,11 @@ TEST(StringViewTest, STL1) {
EXPECT_EQ(buf[1], c[1]);
EXPECT_EQ(buf[2], c[2]);
EXPECT_EQ(buf[3], a[3]);
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(a.copy(buf, 1, 27), std::out_of_range);
+#else
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(a.copy(buf, 1, 27), "absl::string_view::copy");
+#endif
}
// Separated from STL1() because some compilers produce an overly
@@ -403,7 +411,7 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(a.find(e, 17), 17);
absl::string_view g("xx not found bb");
EXPECT_EQ(a.find(g), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.find(b), absl::string_view::npos);
EXPECT_EQ(e.find(b), absl::string_view::npos);
EXPECT_EQ(d.find(b, 4), absl::string_view::npos);
@@ -431,7 +439,7 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(g.find('o', 4), 4);
EXPECT_EQ(g.find('o', 5), 8);
EXPECT_EQ(a.find('b', 5), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.find('\0'), absl::string_view::npos);
EXPECT_EQ(e.find('\0'), absl::string_view::npos);
EXPECT_EQ(d.find('\0', 4), absl::string_view::npos);
@@ -458,7 +466,7 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(e.rfind(b), absl::string_view::npos);
EXPECT_EQ(d.rfind(b, 4), absl::string_view::npos);
EXPECT_EQ(e.rfind(b, 7), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
EXPECT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
EXPECT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
@@ -477,7 +485,7 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(f.rfind('\0', 12), 3);
EXPECT_EQ(f.rfind('3'), 2);
EXPECT_EQ(f.rfind('5'), 5);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.rfind('o'), absl::string_view::npos);
EXPECT_EQ(e.rfind('o'), absl::string_view::npos);
EXPECT_EQ(d.rfind('o', 4), absl::string_view::npos);
@@ -513,7 +521,7 @@ TEST(StringViewTest, STL2FindFirst) {
EXPECT_EQ(g.find_first_of(c), 0);
EXPECT_EQ(a.find_first_of(f), absl::string_view::npos);
EXPECT_EQ(f.find_first_of(a), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(a.find_first_of(d), absl::string_view::npos);
EXPECT_EQ(a.find_first_of(e), absl::string_view::npos);
EXPECT_EQ(d.find_first_of(b), absl::string_view::npos);
@@ -531,7 +539,7 @@ TEST(StringViewTest, STL2FindFirst) {
EXPECT_EQ(a.find_first_not_of(f), 0);
EXPECT_EQ(a.find_first_not_of(d), 0);
EXPECT_EQ(a.find_first_not_of(e), 0);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(a.find_first_not_of(d), 0);
EXPECT_EQ(a.find_first_not_of(e), 0);
EXPECT_EQ(a.find_first_not_of(d, 1), 1);
@@ -559,7 +567,7 @@ TEST(StringViewTest, STL2FindFirst) {
EXPECT_EQ(f.find_first_not_of('\0'), 0);
EXPECT_EQ(f.find_first_not_of('\0', 3), 4);
EXPECT_EQ(f.find_first_not_of('\0', 2), 2);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.find_first_not_of('x'), absl::string_view::npos);
EXPECT_EQ(e.find_first_not_of('x'), absl::string_view::npos);
EXPECT_EQ(d.find_first_not_of('\0'), absl::string_view::npos);
@@ -599,7 +607,7 @@ TEST(StringViewTest, STL2FindLast) {
EXPECT_EQ(f.find_last_of(i, 5), 5);
EXPECT_EQ(f.find_last_of(i, 6), 6);
EXPECT_EQ(f.find_last_of(a, 4), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(f.find_last_of(d), absl::string_view::npos);
EXPECT_EQ(f.find_last_of(e), absl::string_view::npos);
EXPECT_EQ(f.find_last_of(d, 4), absl::string_view::npos);
@@ -625,7 +633,7 @@ TEST(StringViewTest, STL2FindLast) {
EXPECT_EQ(a.find_last_not_of(c, 24), 22);
EXPECT_EQ(a.find_last_not_of(b, 3), 3);
EXPECT_EQ(a.find_last_not_of(b, 2), absl::string_view::npos);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(f.find_last_not_of(d), f.size()-1);
EXPECT_EQ(f.find_last_not_of(e), f.size()-1);
EXPECT_EQ(f.find_last_not_of(d, 4), 4);
@@ -649,7 +657,7 @@ TEST(StringViewTest, STL2FindLast) {
EXPECT_EQ(h.find_last_not_of('x', 2), 2);
EXPECT_EQ(h.find_last_not_of('=', 2), absl::string_view::npos);
EXPECT_EQ(b.find_last_not_of('b', 1), 0);
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.find_last_not_of('x'), absl::string_view::npos);
EXPECT_EQ(e.find_last_not_of('x'), absl::string_view::npos);
EXPECT_EQ(d.find_last_not_of('\0'), absl::string_view::npos);
@@ -671,7 +679,7 @@ TEST(StringViewTest, STL2Substr) {
EXPECT_EQ(a.substr(23, 99), c);
EXPECT_EQ(a.substr(0), a);
EXPECT_EQ(a.substr(3, 2), "de");
- // empty std::string nonsense
+ // empty string nonsense
EXPECT_EQ(d.substr(0, 99), e);
// use of npos
EXPECT_EQ(a.substr(0, absl::string_view::npos), a);
@@ -680,7 +688,8 @@ TEST(StringViewTest, STL2Substr) {
#ifdef ABSL_HAVE_EXCEPTIONS
EXPECT_THROW((void)a.substr(99, 2), std::out_of_range);
#else
- EXPECT_DEATH((void)a.substr(99, 2), "absl::string_view::substr");
+ ABSL_EXPECT_DEATH_IF_SUPPORTED((void)a.substr(99, 2),
+ "absl::string_view::substr");
#endif
}
@@ -755,7 +764,6 @@ TEST(StringViewTest, Remove) {
std::string s1("123");
s1 += '\0';
s1 += "456";
- absl::string_view b(s1);
absl::string_view e;
std::string s2;
@@ -811,21 +819,35 @@ TEST(StringViewTest, FrontBackSingleChar) {
EXPECT_EQ(&c, &csp.back());
}
+TEST(StringViewTest, FrontBackEmpty) {
+#ifndef ABSL_USES_STD_STRING_VIEW
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ // Abseil's string_view implementation has debug assertions that check that
+ // front() and back() are not called on an empty string_view.
+ absl::string_view sv;
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.front(), "");
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(sv.back(), "");
+#endif
+#endif
+}
+
// `std::string_view::string_view(const char*)` calls
// `std::char_traits<char>::length(const char*)` to get the string length. In
// libc++, it doesn't allow `nullptr` in the constexpr context, with the error
// "read of dereferenced null pointer is not allowed in a constant expression".
// At run time, the behavior of `std::char_traits::length()` on `nullptr` is
// undefined by the standard and usually results in crash with libc++.
+// GCC also started rejected this in libstdc++ starting in GCC9.
// In MSVC, creating a constexpr string_view from nullptr also triggers an
// "unevaluable pointer value" error. This compiler implementation conforms
// to the standard, but `absl::string_view` implements a different
// behavior for historical reasons. We work around tests that construct
// `string_view` from `nullptr` when using libc++.
-#if !defined(ABSL_HAVE_STD_STRING_VIEW) || \
- (!defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
+#if !defined(ABSL_USES_STD_STRING_VIEW) || \
+ (!(defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE >= 9) && \
+ !defined(_LIBCPP_VERSION) && !defined(_MSC_VER))
#define ABSL_HAVE_STRING_VIEW_FROM_NULLPTR 1
-#endif // !defined(ABSL_HAVE_STD_STRING_VIEW) || !defined(_LIBCPP_VERSION)
+#endif
TEST(StringViewTest, NULLInput) {
absl::string_view s;
@@ -838,7 +860,7 @@ TEST(StringViewTest, NULLInput) {
EXPECT_EQ(s.size(), 0);
// .ToString() on a absl::string_view with nullptr should produce the empty
- // std::string.
+ // string.
EXPECT_EQ("", std::string(s));
#endif // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
}
@@ -887,6 +909,18 @@ TEST(StringViewTest, Comparisons2) {
EXPECT_LT(digits.compare(0, npos, "0123456789", 3, 5), 0); // 6
}
+TEST(StringViewTest, At) {
+ absl::string_view abc = "abc";
+ EXPECT_EQ(abc.at(0), 'a');
+ EXPECT_EQ(abc.at(1), 'b');
+ EXPECT_EQ(abc.at(2), 'c');
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW((void)abc.at(3), std::out_of_range);
+#else
+ ABSL_EXPECT_DEATH_IF_SUPPORTED((void)abc.at(3), "absl::string_view::at");
+#endif
+}
+
struct MyCharAlloc : std::allocator<char> {};
TEST(StringViewTest, ExplicitConversionOperator) {
@@ -910,6 +944,31 @@ TEST(StringViewTest, NullSafeStringView) {
}
}
+TEST(StringViewTest, ConstexprNullSafeStringView) {
+ {
+ constexpr absl::string_view s = absl::NullSafeStringView(nullptr);
+ EXPECT_EQ(nullptr, s.data());
+ EXPECT_EQ(0, s.size());
+ EXPECT_EQ(absl::string_view(), s);
+ }
+#if !defined(_MSC_VER) || _MSC_VER >= 1910
+ // MSVC 2017+ is required for good constexpr string_view support.
+ // See the implementation of `absl::string_view::StrlenInternal()`.
+ {
+ static constexpr char kHi[] = "hi";
+ absl::string_view s = absl::NullSafeStringView(kHi);
+ EXPECT_EQ(kHi, s.data());
+ EXPECT_EQ(strlen(kHi), s.size());
+ EXPECT_EQ(absl::string_view("hi"), s);
+ }
+ {
+ constexpr absl::string_view s = absl::NullSafeStringView("hello");
+ EXPECT_EQ(s.size(), 5);
+ EXPECT_EQ("hello", s);
+ }
+#endif
+}
+
TEST(StringViewTest, ConstexprCompiles) {
constexpr absl::string_view sp;
#ifdef ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
@@ -917,9 +976,9 @@ TEST(StringViewTest, ConstexprCompiles) {
#endif
constexpr absl::string_view cstr_len("cstr", 4);
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
+#if defined(ABSL_USES_STD_STRING_VIEW)
// In libstdc++ (as of 7.2), `std::string_view::string_view(const char*)`
- // calls `std::char_traits<char>::length(const char*)` to get the std::string
+ // calls `std::char_traits<char>::length(const char*)` to get the string
// length, but it is not marked constexpr yet. See GCC bug:
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78156
// Also, there is a LWG issue that adds constexpr to length() which was just
@@ -931,7 +990,7 @@ TEST(StringViewTest, ConstexprCompiles) {
#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
#endif // !__GLIBCXX__
-#else // ABSL_HAVE_STD_STRING_VIEW
+#else // ABSL_USES_STD_STRING_VIEW
// This duplicates the check for __builtin_strlen in the header.
#if ABSL_HAVE_BUILTIN(__builtin_strlen) || \
@@ -941,13 +1000,41 @@ TEST(StringViewTest, ConstexprCompiles) {
#error GCC/clang should have constexpr string_view.
#endif
-#endif // ABSL_HAVE_STD_STRING_VIEW
+// MSVC 2017+ should be able to construct a constexpr string_view from a cstr.
+#if defined(_MSC_VER) && _MSC_VER >= 1910
+#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR 1
+#endif
+
+#endif // ABSL_USES_STD_STRING_VIEW
#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_FROM_CSTR
constexpr absl::string_view cstr_strlen("foo");
EXPECT_EQ(cstr_strlen.length(), 3);
constexpr absl::string_view cstr_strlen2 = "bar";
EXPECT_EQ(cstr_strlen2, "bar");
+
+#if ABSL_HAVE_BUILTIN(__builtin_memcmp) || \
+ (defined(__GNUC__) && !defined(__clang__))
+#define ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON 1
+#endif
+#ifdef ABSL_HAVE_CONSTEXPR_STRING_VIEW_COMPARISON
+ constexpr absl::string_view foo = "foo";
+ constexpr absl::string_view bar = "bar";
+ constexpr bool foo_eq_bar = foo == bar;
+ constexpr bool foo_ne_bar = foo != bar;
+ constexpr bool foo_lt_bar = foo < bar;
+ constexpr bool foo_le_bar = foo <= bar;
+ constexpr bool foo_gt_bar = foo > bar;
+ constexpr bool foo_ge_bar = foo >= bar;
+ constexpr int foo_compare_bar = foo.compare(bar);
+ EXPECT_FALSE(foo_eq_bar);
+ EXPECT_TRUE(foo_ne_bar);
+ EXPECT_FALSE(foo_lt_bar);
+ EXPECT_FALSE(foo_le_bar);
+ EXPECT_TRUE(foo_gt_bar);
+ EXPECT_TRUE(foo_ge_bar);
+ EXPECT_GT(foo_compare_bar, 0);
+#endif
#endif
#if !defined(__clang__) || 3 < __clang_major__ || \
@@ -969,8 +1056,16 @@ TEST(StringViewTest, ConstexprCompiles) {
constexpr absl::string_view::iterator const_end = cstr_len.end();
constexpr absl::string_view::size_type const_size = cstr_len.size();
constexpr absl::string_view::size_type const_length = cstr_len.length();
+ static_assert(const_begin + const_size == const_end,
+ "pointer arithmetic check");
+ static_assert(const_begin + const_length == const_end,
+ "pointer arithmetic check");
+#ifndef _MSC_VER
+ // MSVC has bugs doing constexpr pointer arithmetic.
+ // https://developercommunity.visualstudio.com/content/problem/482192/bad-pointer-arithmetic-in-constepxr-2019-rc1-svc1.html
EXPECT_EQ(const_begin + const_size, const_end);
EXPECT_EQ(const_begin + const_length, const_end);
+#endif
constexpr bool isempty = sp.empty();
EXPECT_TRUE(isempty);
@@ -992,11 +1087,19 @@ TEST(StringViewTest, ConstexprCompiles) {
EXPECT_EQ(sp_npos, -1);
}
+TEST(StringViewTest, ConstexprSubstr) {
+ constexpr absl::string_view foobar("foobar", 6);
+ constexpr absl::string_view foo = foobar.substr(0, 3);
+ constexpr absl::string_view bar = foobar.substr(3);
+ EXPECT_EQ(foo, "foo");
+ EXPECT_EQ(bar, "bar");
+}
+
TEST(StringViewTest, Noexcept) {
EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
const std::string&>::value));
- EXPECT_TRUE(
- (std::is_nothrow_constructible<absl::string_view, const std::string&>::value));
+ EXPECT_TRUE((std::is_nothrow_constructible<absl::string_view,
+ const std::string&>::value));
EXPECT_TRUE(std::is_nothrow_constructible<absl::string_view>::value);
constexpr absl::string_view sp;
EXPECT_TRUE(noexcept(sp.begin()));
@@ -1026,6 +1129,17 @@ TEST(StringViewTest, Noexcept) {
EXPECT_TRUE(noexcept(sp.find_last_not_of('f')));
}
+TEST(StringViewTest, BoundsCheck) {
+#ifndef ABSL_USES_STD_STRING_VIEW
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ // Abseil's string_view implementation has bounds-checking in debug mode.
+ absl::string_view h = "hello";
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], "");
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(h[-1], "");
+#endif
+#endif
+}
+
TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
EXPECT_EQ("hello", std::string("hello"));
EXPECT_LT("hello", std::string("world"));
@@ -1063,11 +1177,11 @@ TEST(FindOneCharTest, EdgeCases) {
EXPECT_EQ(absl::string_view::npos, a.rfind('x'));
}
-#ifndef THREAD_SANITIZER // Allocates too much memory for tsan.
+#ifndef ABSL_HAVE_THREAD_SANITIZER // Allocates too much memory for tsan.
TEST(HugeStringView, TwoPointTwoGB) {
- if (sizeof(size_t) <= 4 || RunningOnValgrind())
+ if (sizeof(size_t) <= 4)
return;
- // Try a huge std::string piece.
+ // Try a huge string piece.
const size_t size = size_t{2200} * 1000 * 1000;
std::string s(size, 'a');
absl::string_view sp(s);
@@ -1077,9 +1191,9 @@ TEST(HugeStringView, TwoPointTwoGB) {
sp.remove_suffix(2);
EXPECT_EQ(size - 1 - 2, sp.length());
}
-#endif // THREAD_SANITIZER
+#endif // ABSL_HAVE_THREAD_SANITIZER
-#if !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
TEST(NonNegativeLenTest, NonNegativeLen) {
ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("xyz", -1),
"len <= kMaxSize");
@@ -1095,7 +1209,7 @@ TEST(LenExceedsMaxSizeTest, LenExceedsMaxSize) {
ABSL_EXPECT_DEATH_IF_SUPPORTED(absl::string_view("", max_size + 1),
"len <= kMaxSize");
}
-#endif // !defined(NDEBUG) && !defined(ABSL_HAVE_STD_STRING_VIEW)
+#endif // !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
class StringViewStreamTest : public ::testing::Test {
public:
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip.h
index 8d0d7c6bfc1..111872ca54b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -30,6 +30,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// ConsumePrefix()
//
@@ -84,6 +85,7 @@ ABSL_MUST_USE_RESULT inline absl::string_view StripSuffix(
return str;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_STRIP_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip_test.cc
index 40c4c607121..e4e00cb66eb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/strip_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,9 +27,6 @@
namespace {
-using testing::ElementsAre;
-using testing::IsEmpty;
-
TEST(Strip, ConsumePrefixOneChar) {
absl::string_view input("abc");
EXPECT_TRUE(absl::ConsumePrefix(&input, "a"));
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.cc
index 3b200594509..1f3c7409abb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,6 +23,7 @@
#include "absl/strings/string_view.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace substitute_internal {
void SubstituteAndAppendArray(std::string* output, absl::string_view format,
@@ -35,7 +36,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (i + 1 >= format.size()) {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid strings::Substitute() format std::string: \"%s\".",
+ "Invalid absl::Substitute() format string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -45,8 +46,8 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
#ifndef NDEBUG
ABSL_RAW_LOG(
FATAL,
- "Invalid strings::Substitute() format std::string: asked for \"$"
- "%d\", but only %d args were given. Full format std::string was: "
+ "Invalid absl::Substitute() format string: asked for \"$"
+ "%d\", but only %d args were given. Full format string was: "
"\"%s\".",
index, static_cast<int>(num_args), absl::CEscape(format).c_str());
#endif
@@ -60,7 +61,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
} else {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid strings::Substitute() format std::string: \"%s\".",
+ "Invalid absl::Substitute() format string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -72,7 +73,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (size == 0) return;
- // Build the std::string.
+ // Build the string.
size_t original_size = output->size();
strings_internal::STLStringResizeUninitialized(output, original_size + size);
char* target = &(*output)[original_size];
@@ -94,7 +95,6 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
assert(target == output->data() + output->size());
}
-static const char kHexDigits[] = "0123456789abcdef";
Arg::Arg(const void* value) {
static_assert(sizeof(scratch_) >= sizeof(value) * 2 + 2,
"fix sizeof(scratch_)");
@@ -104,7 +104,7 @@ Arg::Arg(const void* value) {
char* ptr = scratch_ + sizeof(scratch_);
uintptr_t num = reinterpret_cast<uintptr_t>(value);
do {
- *--ptr = kHexDigits[num & 0xf];
+ *--ptr = absl::numbers_internal::kHexChar[num & 0xf];
num >>= 4;
} while (num != 0);
*--ptr = 'x';
@@ -119,7 +119,7 @@ Arg::Arg(Hex hex) {
char* writer = end;
uint64_t value = hex.value;
do {
- *--writer = kHexDigits[value & 0xF];
+ *--writer = absl::numbers_internal::kHexChar[value & 0xF];
value >>= 4;
} while (value != 0);
@@ -167,4 +167,5 @@ Arg::Arg(Dec dec) {
}
} // namespace substitute_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.h
index 4de7b4e75ff..c6da4dc6e72 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -35,20 +35,22 @@
// and single digit positional ids to indicate which substitution arguments to
// use at that location within the format string.
//
+// A '$$' sequence in the format string causes a literal '$' character to be
+// output.
+//
// Example 1:
-// string s = Substitute("$1 purchased $0 $2. Thanks $1!",
-// 5, "Bob", "Apples");
-// EXPECT_EQ("Bob purchased 5 Apples. Thanks Bob!", s);
+// std::string s = Substitute("$1 purchased $0 $2 for $$10. Thanks $1!",
+// 5, "Bob", "Apples");
+// EXPECT_EQ("Bob purchased 5 Apples for $10. Thanks Bob!", s);
//
// Example 2:
-// string s = "Hi. ";
+// std::string s = "Hi. ";
// SubstituteAndAppend(&s, "My name is $0 and I am $1 years old.", "Bob", 5);
// EXPECT_EQ("Hi. My name is Bob and I am 5 years old.", s);
//
-//
// Supported types:
-// * absl::string_view, string, const char* (null is equivalent to "")
-// * int32_t, int64_t, uint32_t, uint64
+// * absl::string_view, std::string, const char* (null is equivalent to "")
+// * int32_t, int64_t, uint32_t, uint64_t
// * float, double
// * bool (Printed as "true" or "false")
// * pointer types other than char* (Printed as "0x<lower case hex string>",
@@ -70,6 +72,8 @@
#include <cstring>
#include <string>
+#include <type_traits>
+#include <vector>
#include "absl/base/macros.h"
#include "absl/base/port.h"
@@ -82,6 +86,7 @@
#include "absl/strings/strip.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace substitute_internal {
// Arg
@@ -94,7 +99,7 @@ namespace substitute_internal {
// This class has implicit constructors.
class Arg {
public:
- // Overloads for std::string-y things
+ // Overloads for string-y things
//
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(const char* value) // NOLINT(runtime/explicit)
@@ -115,7 +120,9 @@ class Arg {
// representation. However, we can't really know, so we make the caller decide
// what to do.
Arg(char value) // NOLINT(runtime/explicit)
- : piece_(scratch_, 1) { scratch_[0] = value; }
+ : piece_(scratch_, 1) {
+ scratch_[0] = value;
+ }
Arg(short value) // NOLINT(*)
: piece_(scratch_,
numbers_internal::FastIntToBuffer(value, scratch_) - scratch_) {}
@@ -152,6 +159,17 @@ class Arg {
Arg(Hex hex); // NOLINT(runtime/explicit)
Arg(Dec dec); // NOLINT(runtime/explicit)
+ // vector<bool>::reference and const_reference require special help to
+ // convert to `AlphaNum` because it requires two user defined conversions.
+ template <typename T,
+ absl::enable_if_t<
+ std::is_class<T>::value &&
+ (std::is_same<T, std::vector<bool>::reference>::value ||
+ std::is_same<T, std::vector<bool>::const_reference>::value)>* =
+ nullptr>
+ Arg(T value) // NOLINT(google-explicit-constructor)
+ : Arg(static_cast<bool>(value)) {}
+
// `void*` values, with the exception of `char*`, are printed as
// "0x<hex value>". However, in the case of `nullptr`, "NULL" is printed.
Arg(const void* value); // NOLINT(runtime/explicit)
@@ -174,7 +192,12 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
#if defined(ABSL_BAD_CALL_IF)
constexpr int CalculateOneBit(const char* format) {
- return (*format < '0' || *format > '9') ? 0 : (1 << (*format - '0'));
+ // Returns:
+ // * 2^N for '$N' when N is in [0-9]
+ // * 0 for correct '$' escaping: '$$'.
+ // * -1 otherwise.
+ return (*format < '0' || *format > '9') ? (*format == '$' ? 0 : -1)
+ : (1 << (*format - '0'));
}
constexpr const char* SkipNumber(const char* format) {
@@ -182,10 +205,11 @@ constexpr const char* SkipNumber(const char* format) {
}
constexpr int PlaceholderBitmask(const char* format) {
- return !*format ? 0 : *format != '$'
- ? PlaceholderBitmask(format + 1)
- : (CalculateOneBit(format + 1) |
- PlaceholderBitmask(SkipNumber(format + 1)));
+ return !*format
+ ? 0
+ : *format != '$' ? PlaceholderBitmask(format + 1)
+ : (CalculateOneBit(format + 1) |
+ PlaceholderBitmask(SkipNumber(format + 1)));
}
#endif // ABSL_BAD_CALL_IF
@@ -339,13 +363,13 @@ inline void SubstituteAndAppend(
void SubstituteAndAppend(std::string* output, const char* format)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
"There were no substitution arguments "
- "but this format std::string has a $[0-9] in it");
+ "but this format string has a $[0-9] in it");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
"There was 1 substitution argument given, but "
- "this format std::string is either missing its $0, or "
+ "this format string is either missing its $0, or "
"contains one of $1-$9");
void SubstituteAndAppend(std::string* output, const char* format,
@@ -353,7 +377,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
"There were 2 substitution arguments given, but "
- "this format std::string is either missing its $0/$1, or "
+ "this format string is either missing its $0/$1, or "
"contains one of $2-$9");
void SubstituteAndAppend(std::string* output, const char* format,
@@ -362,7 +386,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a2)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
"There were 3 substitution arguments given, but "
- "this format std::string is either missing its $0/$1/$2, or "
+ "this format string is either missing its $0/$1/$2, or "
"contains one of $3-$9");
void SubstituteAndAppend(std::string* output, const char* format,
@@ -372,7 +396,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a3)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
"There were 4 substitution arguments given, but "
- "this format std::string is either missing its $0-$3, or "
+ "this format string is either missing its $0-$3, or "
"contains one of $4-$9");
void SubstituteAndAppend(std::string* output, const char* format,
@@ -383,7 +407,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a4)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
"There were 5 substitution arguments given, but "
- "this format std::string is either missing its $0-$4, or "
+ "this format string is either missing its $0-$4, or "
"contains one of $5-$9");
void SubstituteAndAppend(std::string* output, const char* format,
@@ -395,7 +419,7 @@ void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a5)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
"There were 6 substitution arguments given, but "
- "this format std::string is either missing its $0-$5, or "
+ "this format string is either missing its $0-$5, or "
"contains one of $6-$9");
void SubstituteAndAppend(
@@ -405,7 +429,7 @@ void SubstituteAndAppend(
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but "
- "this format std::string is either missing its $0-$6, or "
+ "this format string is either missing its $0-$6, or "
"contains one of $7-$9");
void SubstituteAndAppend(
@@ -416,7 +440,7 @@ void SubstituteAndAppend(
const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but "
- "this format std::string is either missing its $0-$7, or "
+ "this format string is either missing its $0-$7, or "
"contains one of $8-$9");
void SubstituteAndAppend(
@@ -428,7 +452,7 @@ void SubstituteAndAppend(
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 511,
"There were 9 substitution arguments given, but "
- "this format std::string is either missing its $0-$8, or contains a $9");
+ "this format string is either missing its $0-$8, or contains a $9");
void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0,
@@ -439,7 +463,7 @@ void SubstituteAndAppend(
const substitute_internal::Arg& a9)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1023,
"There were 10 substitution arguments given, but this "
- "format std::string doesn't contain all of $0 through $9");
+ "format string doesn't contain all of $0 through $9");
#endif // ABSL_BAD_CALL_IF
// Substitute()
@@ -456,7 +480,7 @@ void SubstituteAndAppend(
// Example:
// template <typename... Args>
// void VarMsg(absl::string_view format, const Args&... args) {
-// string s = absl::Substitute(format, args...);
+// std::string s = absl::Substitute(format, args...);
ABSL_MUST_USE_RESULT inline std::string Substitute(absl::string_view format) {
std::string result;
@@ -565,82 +589,82 @@ ABSL_MUST_USE_RESULT inline std::string Substitute(
std::string Substitute(const char* format)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 0,
"There were no substitution arguments "
- "but this format std::string has a $[0-9] in it");
+ "but this format string has a $[0-9] in it");
std::string Substitute(const char* format, const substitute_internal::Arg& a0)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1,
"There was 1 substitution argument given, but "
- "this format std::string is either missing its $0, or "
+ "this format string is either missing its $0, or "
"contains one of $1-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1)
+ const substitute_internal::Arg& a1)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 3,
"There were 2 substitution arguments given, but "
- "this format std::string is either missing its $0/$1, or "
+ "this format string is either missing its $0/$1, or "
"contains one of $2-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 7,
"There were 3 substitution arguments given, but "
- "this format std::string is either missing its $0/$1/$2, or "
+ "this format string is either missing its $0/$1/$2, or "
"contains one of $3-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 15,
"There were 4 substitution arguments given, but "
- "this format std::string is either missing its $0-$3, or "
+ "this format string is either missing its $0-$3, or "
"contains one of $4-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 31,
"There were 5 substitution arguments given, but "
- "this format std::string is either missing its $0-$4, or "
+ "this format string is either missing its $0-$4, or "
"contains one of $5-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 63,
"There were 6 substitution arguments given, but "
- "this format std::string is either missing its $0-$5, or "
+ "this format string is either missing its $0-$5, or "
"contains one of $6-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 127,
"There were 7 substitution arguments given, but "
- "this format std::string is either missing its $0-$6, or "
+ "this format string is either missing its $0-$6, or "
"contains one of $7-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
- const substitute_internal::Arg& a1,
- const substitute_internal::Arg& a2,
- const substitute_internal::Arg& a3,
- const substitute_internal::Arg& a4,
- const substitute_internal::Arg& a5,
- const substitute_internal::Arg& a6,
- const substitute_internal::Arg& a7)
+ const substitute_internal::Arg& a1,
+ const substitute_internal::Arg& a2,
+ const substitute_internal::Arg& a3,
+ const substitute_internal::Arg& a4,
+ const substitute_internal::Arg& a5,
+ const substitute_internal::Arg& a6,
+ const substitute_internal::Arg& a7)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 255,
"There were 8 substitution arguments given, but "
- "this format std::string is either missing its $0-$7, or "
+ "this format string is either missing its $0-$7, or "
"contains one of $8-$9");
std::string Substitute(
@@ -652,7 +676,7 @@ std::string Substitute(
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 511,
"There were 9 substitution arguments given, but "
- "this format std::string is either missing its $0-$8, or contains a $9");
+ "this format string is either missing its $0-$8, or contains a $9");
std::string Substitute(
const char* format, const substitute_internal::Arg& a0,
@@ -663,9 +687,10 @@ std::string Substitute(
const substitute_internal::Arg& a9)
ABSL_BAD_CALL_IF(substitute_internal::PlaceholderBitmask(format) != 1023,
"There were 10 substitution arguments given, but this "
- "format std::string doesn't contain all of $0 through $9");
+ "format string doesn't contain all of $0 through $9");
#endif // ABSL_BAD_CALL_IF
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_SUBSTITUTE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute_test.cc
index 144df01ec18..442c921528d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/substitute_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/strings/substitute.h"
#include <cstdint>
+#include <vector>
#include "gtest/gtest.h"
#include "absl/strings/str_cat.h"
@@ -88,7 +89,7 @@ TEST(SubstituteTest, Substitute) {
str = absl::Substitute("$0", char_buf);
EXPECT_EQ("print me too", str);
- // null char* is "doubly" special. Represented as the empty std::string.
+ // null char* is "doubly" special. Represented as the empty string.
char_p = nullptr;
str = absl::Substitute("$0", char_p);
EXPECT_EQ("", str);
@@ -172,19 +173,30 @@ TEST(SubstituteTest, SubstituteAndAppend) {
EXPECT_EQ("a b c d e f g h i j", str);
}
+TEST(SubstituteTest, VectorBoolRef) {
+ std::vector<bool> v = {true, false};
+ const auto& cv = v;
+ EXPECT_EQ("true false true false",
+ absl::Substitute("$0 $1 $2 $3", v[0], v[1], cv[0], cv[1]));
+
+ std::string str = "Logic be like: ";
+ absl::SubstituteAndAppend(&str, "$0 $1 $2 $3", v[0], v[1], cv[0], cv[1]);
+ EXPECT_EQ("Logic be like: true false true false", str);
+}
+
#ifdef GTEST_HAS_DEATH_TEST
TEST(SubstituteDeathTest, SubstituteDeath) {
EXPECT_DEBUG_DEATH(
static_cast<void>(absl::Substitute(absl::string_view("-$2"), "a", "b")),
- "Invalid strings::Substitute\\(\\) format std::string: asked for \"\\$2\", "
+ "Invalid absl::Substitute\\(\\) format string: asked for \"\\$2\", "
"but only 2 args were given.");
EXPECT_DEBUG_DEATH(
- static_cast<void>(absl::Substitute("-$z-")),
- "Invalid strings::Substitute\\(\\) format std::string: \"-\\$z-\"");
+ static_cast<void>(absl::Substitute(absl::string_view("-$z-"))),
+ "Invalid absl::Substitute\\(\\) format string: \"-\\$z-\"");
EXPECT_DEBUG_DEATH(
- static_cast<void>(absl::Substitute("-$")),
- "Invalid strings::Substitute\\(\\) format std::string: \"-\\$\"");
+ static_cast<void>(absl::Substitute(absl::string_view("-$"))),
+ "Invalid absl::Substitute\\(\\) format string: \"-\\$\"");
}
#endif // GTEST_HAS_DEATH_TEST
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-1.txt b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-1.txt
deleted file mode 100644
index 19b909733ae..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-1.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-alpha
-
-beta gamma
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-2.txt b/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-2.txt
deleted file mode 100644
index d6842d8ee36..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/strings/testdata/getline-2.txt
+++ /dev/null
@@ -1 +0,0 @@
-one.two.three
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/BUILD.bazel
index 53e7988457e..5ce169587b7 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,15 +14,17 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
# Internal data structure for efficiently detecting mutex dependency cycles
cc_library(
@@ -34,14 +36,32 @@ cc_library(
"internal/graphcycles.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
"//absl/base",
"//absl/base:base_internal",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:malloc_internal",
+ "//absl/base:raw_logging_internal",
+ ],
+)
+
+cc_library(
+ name = "kernel_timeout_internal",
+ hdrs = ["internal/kernel_timeout.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/synchronization:__pkg__",
+ ],
+ deps = [
+ "//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
+ "//absl/time",
],
)
@@ -53,30 +73,37 @@ cc_library(
"internal/create_thread_identity.cc",
"internal/per_thread_sem.cc",
"internal/waiter.cc",
+ "mutex.cc",
"notification.cc",
- ] + select({
- "//conditions:default": ["mutex.cc"],
- }),
+ ],
hdrs = [
"barrier.h",
"blocking_counter.h",
"internal/create_thread_identity.h",
- "internal/kernel_timeout.h",
- "internal/mutex_nonprod.inc",
+ "internal/futex.h",
"internal/per_thread_sem.h",
"internal/waiter.h",
"mutex.h",
"notification.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = select({
+ "//absl:msvc_compiler": [],
+ "//absl:clang-cl_compiler": [],
+ "//absl:wasm": [],
+ "//conditions:default": ["-pthread"],
+ }) + ABSL_DEFAULT_LINKOPTS,
deps = [
":graphcycles_internal",
+ ":kernel_timeout_internal",
"//absl/base",
+ "//absl/base:atomic_hook",
"//absl/base:base_internal",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
"//absl/base:malloc_internal",
+ "//absl/base:raw_logging_internal",
"//absl/debugging:stacktrace",
"//absl/debugging:symbolize",
"//absl/time",
@@ -88,9 +115,7 @@ cc_test(
size = "small",
srcs = ["barrier_test.cc"],
copts = ABSL_TEST_COPTS,
- tags = [
- "no_test_wasm",
- ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":synchronization",
"//absl/time",
@@ -103,9 +128,7 @@ cc_test(
size = "small",
srcs = ["blocking_counter_test.cc"],
copts = ABSL_TEST_COPTS,
- tags = [
- "no_test_wasm",
- ],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":synchronization",
"//absl/time",
@@ -118,10 +141,11 @@ cc_test(
size = "medium",
srcs = ["internal/graphcycles_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":graphcycles_internal",
- "//absl/base",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"@com_google_googletest//:gtest_main",
],
)
@@ -130,12 +154,13 @@ cc_test(
name = "graphcycles_benchmark",
srcs = ["internal/graphcycles_benchmark.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = [
"benchmark",
],
deps = [
":graphcycles_internal",
- "//absl/base",
+ "//absl/base:raw_logging_internal",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -144,6 +169,7 @@ cc_library(
name = "thread_pool",
testonly = 1,
hdrs = ["internal/thread_pool.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
@@ -158,12 +184,15 @@ cc_test(
size = "large",
srcs = ["mutex_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
shard_count = 25,
deps = [
":synchronization",
":thread_pool",
"//absl/base",
+ "//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/memory",
"//absl/time",
"@com_google_googletest//:gtest_main",
@@ -174,7 +203,8 @@ cc_library(
name = "mutex_benchmark_common",
testonly = 1,
srcs = ["mutex_benchmark.cc"],
- copts = ABSL_DEFAULT_COPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/synchronization:__pkg__",
],
@@ -182,6 +212,7 @@ cc_library(
":synchronization",
":thread_pool",
"//absl/base",
+ "//absl/base:config",
"@com_github_google_benchmark//:benchmark_main",
],
alwayslink = 1,
@@ -191,6 +222,7 @@ cc_binary(
name = "mutex_benchmark",
testonly = 1,
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
":mutex_benchmark_common",
@@ -202,6 +234,7 @@ cc_test(
size = "small",
srcs = ["notification_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":synchronization",
"//absl/time",
@@ -214,9 +247,11 @@ cc_library(
testonly = 1,
srcs = ["internal/per_thread_sem_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":synchronization",
"//absl/base",
+ "//absl/base:config",
"//absl/strings",
"//absl/time",
"@com_google_googletest//:gtest",
@@ -228,11 +263,10 @@ cc_test(
name = "per_thread_sem_test",
size = "medium",
copts = ABSL_TEST_COPTS,
- tags = ["no_test_wasm"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":per_thread_sem_test_common",
":synchronization",
- "//absl/base",
"//absl/strings",
"//absl/time",
"@com_google_googletest//:gtest_main",
@@ -245,14 +279,11 @@ cc_test(
"lifetime_test.cc",
],
copts = ABSL_TEST_COPTS,
- linkopts = select({
- "//absl:windows": [],
- "//conditions:default": ["-pthread"],
- }),
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["no_test_ios_x86_64"],
deps = [
":synchronization",
- "//absl/base",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
],
)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.cc
index a1b3ad5c217..0dfd795e7b5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,6 +18,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Return whether int *arg is zero.
static bool IsZero(void *arg) {
@@ -47,4 +48,5 @@ bool Barrier::Block() {
return this->num_to_exit_ == 0;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.h
index f834feec11d..d8e754406f4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,6 +23,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Barrier
//
@@ -69,9 +70,10 @@ class Barrier {
private:
Mutex lock_;
- int num_to_block_ GUARDED_BY(lock_);
- int num_to_exit_ GUARDED_BY(lock_);
+ int num_to_block_ ABSL_GUARDED_BY(lock_);
+ int num_to_exit_ ABSL_GUARDED_BY(lock_);
};
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_BARRIER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier_test.cc
index d6cababdf73..bfc6cb1883b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/barrier_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.cc
index 7e68e960bc3..3cea7aed244 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,6 +17,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Return whether int *arg is zero.
static bool IsZero(void *arg) {
@@ -52,4 +53,5 @@ void BlockingCounter::Wait() {
// after we return from this method.
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.h
index 557ed028fe5..1f53f9f2404 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,6 +24,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// BlockingCounter
//
@@ -88,10 +89,11 @@ class BlockingCounter {
private:
Mutex lock_;
- int count_ GUARDED_BY(lock_);
- int num_waiting_ GUARDED_BY(lock_);
+ int count_ ABSL_GUARDED_BY(lock_);
+ int num_waiting_ ABSL_GUARDED_BY(lock_);
};
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter_test.cc
index e8223f841a5..2926224af75 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/blocking_counter_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
void PauseAndDecreaseCounter(BlockingCounter* counter, int* done) {
@@ -63,4 +64,5 @@ TEST(BlockingCounterTest, BasicFunctionality) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
index e7a65cd884a..53a71b342b9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,16 +27,18 @@
#include "absl/synchronization/internal/per_thread_sem.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// ThreadIdentity storage is persistent, we maintain a free-list of previously
// released ThreadIdentity objects.
-static base_internal::SpinLock freelist_lock(base_internal::kLinkerInitialized);
-static base_internal::ThreadIdentity* thread_identity_freelist;
+ABSL_CONST_INIT static base_internal::SpinLock freelist_lock(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static base_internal::ThreadIdentity* thread_identity_freelist;
// A per-thread destructor for reclaiming associated ThreadIdentity objects.
// Since we must preserve their storage we cache them for re-use.
-static void ReclaimThreadIdentity(void* v) {
+void ReclaimThreadIdentity(void* v) {
base_internal::ThreadIdentity* identity =
static_cast<base_internal::ThreadIdentity*>(v);
@@ -46,6 +48,8 @@ static void ReclaimThreadIdentity(void* v) {
base_internal::LowLevelAlloc::Free(identity->per_thread_synch.all_locks);
}
+ PerThreadSem::Destroy(identity);
+
// We must explicitly clear the current thread's identity:
// (a) Subsequent (unrelated) per-thread destructors may require an identity.
// We must guarantee a new identity is used in this case (this instructor
@@ -67,6 +71,29 @@ static intptr_t RoundUp(intptr_t addr, intptr_t align) {
return (addr + align - 1) & ~(align - 1);
}
+static void ResetThreadIdentity(base_internal::ThreadIdentity* identity) {
+ base_internal::PerThreadSynch* pts = &identity->per_thread_synch;
+ pts->next = nullptr;
+ pts->skip = nullptr;
+ pts->may_skip = false;
+ pts->waitp = nullptr;
+ pts->suppress_fatal_errors = false;
+ pts->readers = 0;
+ pts->priority = 0;
+ pts->next_priority_read_cycles = 0;
+ pts->state.store(base_internal::PerThreadSynch::State::kAvailable,
+ std::memory_order_relaxed);
+ pts->maybe_unlocking = false;
+ pts->wake = false;
+ pts->cond_waiter = false;
+ pts->all_locks = nullptr;
+ identity->blocked_count_ptr = nullptr;
+ identity->ticker.store(0, std::memory_order_relaxed);
+ identity->wait_start.store(0, std::memory_order_relaxed);
+ identity->is_idle.store(false, std::memory_order_relaxed);
+ identity->next = nullptr;
+}
+
static base_internal::ThreadIdentity* NewThreadIdentity() {
base_internal::ThreadIdentity* identity = nullptr;
@@ -90,7 +117,7 @@ static base_internal::ThreadIdentity* NewThreadIdentity() {
RoundUp(reinterpret_cast<intptr_t>(allocation),
base_internal::PerThreadSynch::kAlignment));
}
- memset(identity, 0, sizeof(*identity));
+ ResetThreadIdentity(identity);
return identity;
}
@@ -107,6 +134,7 @@ base_internal::ThreadIdentity* CreateThreadIdentity() {
}
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.h
index 1bb87dee630..e121f68377b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/create_thread_identity.h
@@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -29,12 +29,17 @@
#include "absl/base/port.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// Allocates and attaches a ThreadIdentity object for the calling thread.
// For private use only.
base_internal::ThreadIdentity* CreateThreadIdentity();
+// A per-thread destructor for reclaiming associated ThreadIdentity objects.
+// For private use only.
+void ReclaimThreadIdentity(void* v);
+
// Returns the ThreadIdentity object representing the calling thread; guaranteed
// to be unique for its lifetime. The returned object will remain valid for the
// program's lifetime; although it may be re-assigned to a subsequent thread.
@@ -49,5 +54,7 @@ inline base_internal::ThreadIdentity* GetOrCreateCurrentThreadIdentity() {
}
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_CREATE_THREAD_IDENTITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/futex.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/futex.h
new file mode 100644
index 00000000000..06fbd6d072d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/futex.h
@@ -0,0 +1,154 @@
+// Copyright 2020 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+#define ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
+
+#include "absl/base/config.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#ifdef __linux__
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <time.h>
+
+#include <atomic>
+#include <cstdint>
+
+#include "absl/base/optimization.h"
+#include "absl/synchronization/internal/kernel_timeout.h"
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+#error ABSL_INTERNAL_HAVE_FUTEX may not be set on the command line
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
+#define ABSL_INTERNAL_HAVE_FUTEX
+#endif
+
+#ifdef ABSL_INTERNAL_HAVE_FUTEX
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace synchronization_internal {
+
+// Some Android headers are missing these definitions even though they
+// support these futex operations.
+#ifdef __BIONIC__
+#ifndef SYS_futex
+#define SYS_futex __NR_futex
+#endif
+#ifndef FUTEX_WAIT_BITSET
+#define FUTEX_WAIT_BITSET 9
+#endif
+#ifndef FUTEX_PRIVATE_FLAG
+#define FUTEX_PRIVATE_FLAG 128
+#endif
+#ifndef FUTEX_CLOCK_REALTIME
+#define FUTEX_CLOCK_REALTIME 256
+#endif
+#ifndef FUTEX_BITSET_MATCH_ANY
+#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
+#endif
+#endif
+
+#if defined(__NR_futex_time64) && !defined(SYS_futex_time64)
+#define SYS_futex_time64 __NR_futex_time64
+#endif
+
+#if defined(SYS_futex_time64) && !defined(SYS_futex)
+#define SYS_futex SYS_futex_time64
+#endif
+
+class FutexImpl {
+ public:
+ static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
+ KernelTimeout t) {
+ int err = 0;
+ if (t.has_timeout()) {
+ // https://locklessinc.com/articles/futex_cheat_sheet/
+ // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
+ struct timespec abs_timeout = t.MakeAbsTimespec();
+ // Atomically check that the futex value is still 0, and if it
+ // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
+ err = syscall(
+ SYS_futex, reinterpret_cast<int32_t *>(v),
+ FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
+ &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
+ } else {
+ // Atomically check that the futex value is still 0, and if it
+ // is, sleep until woken by FUTEX_WAKE.
+ err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+ FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
+ }
+ if (ABSL_PREDICT_FALSE(err != 0)) {
+ err = -errno;
+ }
+ return err;
+ }
+
+ static int WaitBitsetAbsoluteTimeout(std::atomic<int32_t> *v, int32_t val,
+ int32_t bits,
+ const struct timespec *abstime) {
+ int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+ FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG, val, abstime,
+ nullptr, bits);
+ if (ABSL_PREDICT_FALSE(err != 0)) {
+ err = -errno;
+ }
+ return err;
+ }
+
+ static int Wake(std::atomic<int32_t> *v, int32_t count) {
+ int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+ FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
+ if (ABSL_PREDICT_FALSE(err < 0)) {
+ err = -errno;
+ }
+ return err;
+ }
+
+ // FUTEX_WAKE_BITSET
+ static int WakeBitset(std::atomic<int32_t> *v, int32_t count, int32_t bits) {
+ int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
+ FUTEX_WAKE_BITSET | FUTEX_PRIVATE_FLAG, count, nullptr,
+ nullptr, bits);
+ if (ABSL_PREDICT_FALSE(err < 0)) {
+ err = -errno;
+ }
+ return err;
+ }
+};
+
+class Futex : public FutexImpl {};
+
+} // namespace synchronization_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_INTERNAL_HAVE_FUTEX
+
+#endif // ABSL_SYNCHRONIZATION_INTERNAL_FUTEX_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.cc
index d3878de2b68..27fec21681d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -37,6 +37,7 @@
#include <algorithm>
#include <array>
+#include <limits>
#include "absl/base/internal/hide_ptr.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/spinlock.h"
@@ -44,15 +45,16 @@
// Do not use STL. This module does not use standard memory allocation.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
namespace {
// Avoid LowLevelAlloc's default arena since it calls malloc hooks in
// which people are doing things like acquiring Mutexes.
-static absl::base_internal::SpinLock arena_mu(
- absl::base_internal::kLinkerInitialized);
-static base_internal::LowLevelAlloc::Arena* arena;
+ABSL_CONST_INIT static absl::base_internal::SpinLock arena_mu(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+ABSL_CONST_INIT static base_internal::LowLevelAlloc::Arena* arena;
static void InitArenaIfNecessary() {
arena_mu.Lock();
@@ -690,6 +692,7 @@ int GraphCycles::GetStackTrace(GraphId id, void*** ptr) {
}
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_LOW_LEVEL_ALLOC_MISSING
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.h
index 2e6686a4c06..ceba33e4de8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -36,11 +36,14 @@
// InsertEdge() is very fast when the edge already exists, and reasonably fast
// otherwise.
// FindPath() is linear in the size of the graph.
-// The current implemenation uses O(|V|+|E|) space.
+// The current implementation uses O(|V|+|E|) space.
#include <cstdint>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// Opaque identifier for a graph node.
@@ -132,6 +135,7 @@ class GraphCycles {
};
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc
index a239c25c3a8..54823e0ba51 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc
index 9a85b39074d..74eaffe7a80 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/graphcycles_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
#include "absl/base/macros.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// We emulate a GraphCycles object with a node vector and an edge vector.
@@ -459,4 +460,5 @@ TEST_F(GraphCyclesTest, ManyEdges) {
}
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/kernel_timeout.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
index 9e1eed75d3a..bbd4d2d70f4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,6 +26,7 @@
#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
#include <time.h>
+
#include <algorithm>
#include <limits>
@@ -34,6 +35,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
class Futex;
@@ -53,8 +55,13 @@ class KernelTimeout {
// We explicitly do not support other custom formats: timespec, int64_t nanos.
// Unify on this and absl::Time, please.
+
bool has_timeout() const { return ns_ != 0; }
+ // Convert to parameter for sem_timedwait/futex/similar. Only for approved
+ // users. Do not call if !has_timeout.
+ struct timespec MakeAbsTimespec();
+
private:
// internal rep, not user visible: ns after unix epoch.
// zero = no timeout.
@@ -80,34 +87,6 @@ class KernelTimeout {
return x;
}
- // Convert to parameter for sem_timedwait/futex/similar. Only for approved
- // users. Do not call if !has_timeout.
- struct timespec MakeAbsTimespec() {
- int64_t n = ns_;
- static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
- if (n == 0) {
- ABSL_RAW_LOG(
- ERROR,
- "Tried to create a timespec from a non-timeout; never do this.");
- // But we'll try to continue sanely. no-timeout ~= saturated timeout.
- n = (std::numeric_limits<int64_t>::max)();
- }
-
- // Kernel APIs validate timespecs as being at or after the epoch,
- // despite the kernel time type being signed. However, no one can
- // tell the difference between a timeout at or before the epoch (since
- // all such timeouts have expired!)
- if (n < 0) n = 0;
-
- struct timespec abstime;
- int64_t seconds = (std::min)(n / kNanosPerSecond,
- int64_t{(std::numeric_limits<time_t>::max)()});
- abstime.tv_sec = static_cast<time_t>(seconds);
- abstime.tv_nsec =
- static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
- return abstime;
- }
-
#ifdef _WIN32
// Converts to milliseconds from now, or INFINITE when
// !has_timeout(). For use by SleepConditionVariableSRW on
@@ -146,6 +125,32 @@ class KernelTimeout {
friend class Waiter;
};
+inline struct timespec KernelTimeout::MakeAbsTimespec() {
+ int64_t n = ns_;
+ static const int64_t kNanosPerSecond = 1000 * 1000 * 1000;
+ if (n == 0) {
+ ABSL_RAW_LOG(
+ ERROR, "Tried to create a timespec from a non-timeout; never do this.");
+ // But we'll try to continue sanely. no-timeout ~= saturated timeout.
+ n = (std::numeric_limits<int64_t>::max)();
+ }
+
+ // Kernel APIs validate timespecs as being at or after the epoch,
+ // despite the kernel time type being signed. However, no one can
+ // tell the difference between a timeout at or before the epoch (since
+ // all such timeouts have expired!)
+ if (n < 0) n = 0;
+
+ struct timespec abstime;
+ int64_t seconds = (std::min)(n / kNanosPerSecond,
+ int64_t{(std::numeric_limits<time_t>::max)()});
+ abstime.tv_sec = static_cast<time_t>(seconds);
+ abstime.tv_nsec = static_cast<decltype(abstime.tv_nsec)>(n % kNanosPerSecond);
+ return abstime;
+}
+
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc
deleted file mode 100644
index 45c60326dba..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-// 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
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Implementation of a small subset of Mutex and CondVar functionality
-// for platforms where the production implementation hasn't been fully
-// ported yet.
-
-#include "absl/synchronization/mutex.h"
-
-#if defined(_WIN32)
-#include <chrono> // NOLINT(build/c++11)
-#else
-#include <sys/time.h>
-#include <time.h>
-#endif
-
-#include <algorithm>
-
-#include "absl/base/internal/raw_logging.h"
-#include "absl/time/time.h"
-
-namespace absl {
-namespace synchronization_internal {
-
-namespace {
-
-// Return the current time plus the timeout.
-absl::Time DeadlineFromTimeout(absl::Duration timeout) {
- return absl::Now() + timeout;
-}
-
-// Limit the deadline to a positive, 32-bit time_t value to accommodate
-// implementation restrictions. This also deals with InfinitePast and
-// InfiniteFuture.
-absl::Time LimitedDeadline(absl::Time deadline) {
- deadline = std::max(absl::FromTimeT(0), deadline);
- deadline = std::min(deadline, absl::FromTimeT(0x7fffffff));
- return deadline;
-}
-
-} // namespace
-
-#if defined(_WIN32)
-
-MutexImpl::MutexImpl() {}
-
-MutexImpl::~MutexImpl() {
- if (locked_) {
- std_mutex_.unlock();
- }
-}
-
-void MutexImpl::Lock() {
- std_mutex_.lock();
- locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
- bool locked = std_mutex_.try_lock();
- if (locked) locked_ = true;
- return locked;
-}
-
-void MutexImpl::Unlock() {
- locked_ = false;
- released_.SignalAll();
- std_mutex_.unlock();
-}
-
-CondVarImpl::CondVarImpl() {}
-
-CondVarImpl::~CondVarImpl() {}
-
-void CondVarImpl::Signal() { std_cv_.notify_one(); }
-
-void CondVarImpl::SignalAll() { std_cv_.notify_all(); }
-
-void CondVarImpl::Wait(MutexImpl* mu) {
- mu->released_.SignalAll();
- std_cv_.wait(mu->std_mutex_);
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
- mu->released_.SignalAll();
- time_t when = ToTimeT(deadline);
- int64_t nanos = ToInt64Nanoseconds(deadline - absl::FromTimeT(when));
- std::chrono::system_clock::time_point deadline_tp =
- std::chrono::system_clock::from_time_t(when) +
- std::chrono::duration_cast<std::chrono::system_clock::duration>(
- std::chrono::nanoseconds(nanos));
- auto deadline_since_epoch =
- std::chrono::duration_cast<std::chrono::duration<double>>(
- deadline_tp - std::chrono::system_clock::from_time_t(0));
- return std_cv_.wait_until(mu->std_mutex_, deadline_tp) ==
- std::cv_status::timeout;
-}
-
-#else // ! _WIN32
-
-MutexImpl::MutexImpl() {
- ABSL_RAW_CHECK(pthread_mutex_init(&pthread_mutex_, nullptr) == 0,
- "pthread error");
-}
-
-MutexImpl::~MutexImpl() {
- if (locked_) {
- ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
- }
- ABSL_RAW_CHECK(pthread_mutex_destroy(&pthread_mutex_) == 0, "pthread error");
-}
-
-void MutexImpl::Lock() {
- ABSL_RAW_CHECK(pthread_mutex_lock(&pthread_mutex_) == 0, "pthread error");
- locked_ = true;
-}
-
-bool MutexImpl::TryLock() {
- bool locked = (0 == pthread_mutex_trylock(&pthread_mutex_));
- if (locked) locked_ = true;
- return locked;
-}
-
-void MutexImpl::Unlock() {
- locked_ = false;
- released_.SignalAll();
- ABSL_RAW_CHECK(pthread_mutex_unlock(&pthread_mutex_) == 0, "pthread error");
-}
-
-CondVarImpl::CondVarImpl() {
- ABSL_RAW_CHECK(pthread_cond_init(&pthread_cv_, nullptr) == 0,
- "pthread error");
-}
-
-CondVarImpl::~CondVarImpl() {
- ABSL_RAW_CHECK(pthread_cond_destroy(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Signal() {
- ABSL_RAW_CHECK(pthread_cond_signal(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::SignalAll() {
- ABSL_RAW_CHECK(pthread_cond_broadcast(&pthread_cv_) == 0, "pthread error");
-}
-
-void CondVarImpl::Wait(MutexImpl* mu) {
- mu->released_.SignalAll();
- ABSL_RAW_CHECK(pthread_cond_wait(&pthread_cv_, &mu->pthread_mutex_) == 0,
- "pthread error");
-}
-
-bool CondVarImpl::WaitWithDeadline(MutexImpl* mu, absl::Time deadline) {
- mu->released_.SignalAll();
- struct timespec ts = ToTimespec(deadline);
- int rc = pthread_cond_timedwait(&pthread_cv_, &mu->pthread_mutex_, &ts);
- if (rc == ETIMEDOUT) return true;
- ABSL_RAW_CHECK(rc == 0, "pthread error");
- return false;
-}
-
-#endif // ! _WIN32
-
-void MutexImpl::Await(const Condition& cond) {
- if (cond.Eval()) return;
- released_.SignalAll();
- do {
- released_.Wait(this);
- } while (!cond.Eval());
-}
-
-bool MutexImpl::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
- if (cond.Eval()) return true;
- released_.SignalAll();
- while (true) {
- if (released_.WaitWithDeadline(this, deadline)) return false;
- if (cond.Eval()) return true;
- }
-}
-
-} // namespace synchronization_internal
-
-Mutex::Mutex() {}
-
-Mutex::~Mutex() {}
-
-void Mutex::Lock() { impl()->Lock(); }
-
-void Mutex::Unlock() { impl()->Unlock(); }
-
-bool Mutex::TryLock() { return impl()->TryLock(); }
-
-void Mutex::ReaderLock() { Lock(); }
-
-void Mutex::ReaderUnlock() { Unlock(); }
-
-void Mutex::Await(const Condition& cond) { impl()->Await(cond); }
-
-void Mutex::LockWhen(const Condition& cond) {
- Lock();
- Await(cond);
-}
-
-bool Mutex::AwaitWithDeadline(const Condition& cond, absl::Time deadline) {
- return impl()->AwaitWithDeadline(
- cond, synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool Mutex::AwaitWithTimeout(const Condition& cond, absl::Duration timeout) {
- return AwaitWithDeadline(
- cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-bool Mutex::LockWhenWithDeadline(const Condition& cond, absl::Time deadline) {
- Lock();
- return AwaitWithDeadline(cond, deadline);
-}
-
-bool Mutex::LockWhenWithTimeout(const Condition& cond, absl::Duration timeout) {
- return LockWhenWithDeadline(
- cond, synchronization_internal::DeadlineFromTimeout(timeout));
-}
-
-void Mutex::ReaderLockWhen(const Condition& cond) {
- ReaderLock();
- Await(cond);
-}
-
-bool Mutex::ReaderLockWhenWithTimeout(const Condition& cond,
- absl::Duration timeout) {
- return LockWhenWithTimeout(cond, timeout);
-}
-bool Mutex::ReaderLockWhenWithDeadline(const Condition& cond,
- absl::Time deadline) {
- return LockWhenWithDeadline(cond, deadline);
-}
-
-void Mutex::EnableDebugLog(const char*) {}
-void Mutex::EnableInvariantDebugging(void (*)(void*), void*) {}
-void Mutex::ForgetDeadlockInfo() {}
-void Mutex::AssertHeld() const {}
-void Mutex::AssertReaderHeld() const {}
-void Mutex::AssertNotHeld() const {}
-
-CondVar::CondVar() {}
-
-CondVar::~CondVar() {}
-
-void CondVar::Signal() { impl()->Signal(); }
-
-void CondVar::SignalAll() { impl()->SignalAll(); }
-
-void CondVar::Wait(Mutex* mu) { return impl()->Wait(mu->impl()); }
-
-bool CondVar::WaitWithDeadline(Mutex* mu, absl::Time deadline) {
- return impl()->WaitWithDeadline(
- mu->impl(), synchronization_internal::LimitedDeadline(deadline));
-}
-
-bool CondVar::WaitWithTimeout(Mutex* mu, absl::Duration timeout) {
- return WaitWithDeadline(mu, absl::Now() + timeout);
-}
-
-void CondVar::EnableDebugLog(const char*) {}
-
-#ifdef THREAD_SANITIZER
-extern "C" void __tsan_read1(void *addr);
-#else
-#define __tsan_read1(addr) // do nothing if TSan not enabled
-#endif
-
-// A function that just returns its argument, dereferenced
-static bool Dereference(void *arg) {
- // ThreadSanitizer does not instrument this file for memory accesses.
- // This function dereferences a user variable that can participate
- // in a data race, so we need to manually tell TSan about this memory access.
- __tsan_read1(arg);
- return *(static_cast<bool *>(arg));
-}
-
-Condition::Condition() {} // null constructor, used for kTrue only
-const Condition Condition::kTrue;
-
-Condition::Condition(bool (*func)(void *), void *arg)
- : eval_(&CallVoidPtrFunction),
- function_(func),
- method_(nullptr),
- arg_(arg) {}
-
-bool Condition::CallVoidPtrFunction(const Condition *c) {
- return (*c->function_)(c->arg_);
-}
-
-Condition::Condition(const bool *cond)
- : eval_(CallVoidPtrFunction),
- function_(Dereference),
- method_(nullptr),
- // const_cast is safe since Dereference does not modify arg
- arg_(const_cast<bool *>(cond)) {}
-
-bool Condition::Eval() const {
- // eval_ == null for kTrue
- return (this->eval_ == nullptr) || (*this->eval_)(this);
-}
-
-void RegisterSymbolizer(bool (*)(const void*, char*, int)) {}
-
-} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc
deleted file mode 100644
index b8d5af79ad3..00000000000
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc
+++ /dev/null
@@ -1,259 +0,0 @@
-// Do not include. This is an implementation detail of base/mutex.h.
-//
-// Declares three classes:
-//
-// base::internal::MutexImpl - implementation helper for Mutex
-// base::internal::CondVarImpl - implementation helper for CondVar
-// base::internal::SynchronizationStorage<T> - implementation helper for
-// Mutex, CondVar
-
-#include <type_traits>
-
-#if defined(_WIN32)
-#include <condition_variable>
-#include <mutex>
-#else
-#include <pthread.h>
-#endif
-
-#include "absl/base/call_once.h"
-#include "absl/time/time.h"
-
-// Declare that Mutex::ReaderLock is actually Lock(). Intended primarily
-// for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE
-#error ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE cannot be directly set
-#else
-#define ABSL_MUTEX_READER_LOCK_IS_EXCLUSIVE 1
-#endif
-
-// Declare that Mutex::EnableInvariantDebugging is not implemented.
-// Intended primarily for tests, and even then as a last resort.
-#ifdef ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED
-#error ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED cannot be directly set
-#else
-#define ABSL_MUTEX_ENABLE_INVARIANT_DEBUGGING_NOT_IMPLEMENTED 1
-#endif
-
-namespace absl {
-class Condition;
-
-namespace synchronization_internal {
-
-class MutexImpl;
-
-// Do not use this implementation detail of CondVar. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class CondVarImpl {
- public:
- CondVarImpl();
- CondVarImpl(const CondVarImpl&) = delete;
- CondVarImpl& operator=(const CondVarImpl&) = delete;
- ~CondVarImpl();
-
- void Signal();
- void SignalAll();
- void Wait(MutexImpl* mutex);
- bool WaitWithDeadline(MutexImpl* mutex, absl::Time deadline);
-
- private:
-#if defined(_WIN32)
- std::condition_variable_any std_cv_;
-#else
- pthread_cond_t pthread_cv_;
-#endif
-};
-
-// Do not use this implementation detail of Mutex. Provides most of the
-// implementation, but should not be placed directly in static storage
-// because it will not linker initialize properly. See
-// SynchronizationStorage<T> below for what we mean by linker
-// initialization.
-class MutexImpl {
- public:
- MutexImpl();
- MutexImpl(const MutexImpl&) = delete;
- MutexImpl& operator=(const MutexImpl&) = delete;
- ~MutexImpl();
-
- void Lock();
- bool TryLock();
- void Unlock();
- void Await(const Condition& cond);
- bool AwaitWithDeadline(const Condition& cond, absl::Time deadline);
-
- private:
- friend class CondVarImpl;
-
-#if defined(_WIN32)
- std::mutex std_mutex_;
-#else
- pthread_mutex_t pthread_mutex_;
-#endif
-
- // True if the underlying mutex is locked. If the destructor is entered
- // while locked_, the underlying mutex is unlocked. Mutex supports
- // destruction while locked, but the same is undefined behavior for both
- // pthread_mutex_t and std::mutex.
- bool locked_ = false;
-
- // Signaled before releasing the lock, in support of Await.
- CondVarImpl released_;
-};
-
-// Do not use this implementation detail of CondVar and Mutex. A storage
-// space for T that supports a LinkerInitialized constructor. T must
-// have a default constructor, which is called by the first call to
-// get(). T's destructor is never called if the LinkerInitialized
-// constructor is called.
-//
-// Objects constructed with the default constructor are constructed and
-// destructed like any other object, and should never be allocated in
-// static storage.
-//
-// Objects constructed with the LinkerInitialized constructor should
-// always be in static storage. For such objects, calls to get() are always
-// valid, except from signal handlers.
-//
-// Note that this implementation relies on undefined language behavior that
-// are known to hold for the set of supported compilers. An analysis
-// follows.
-//
-// From the C++11 standard:
-//
-// [basic.life] says an object has non-trivial initialization if it is of
-// class type and it is initialized by a constructor other than a trivial
-// default constructor. (the LinkerInitialized constructor is
-// non-trivial)
-//
-// [basic.life] says the lifetime of an object with a non-trivial
-// constructor begins when the call to the constructor is complete.
-//
-// [basic.life] says the lifetime of an object with non-trivial destructor
-// ends when the call to the destructor begins.
-//
-// [basic.life] p5 specifies undefined behavior when accessing non-static
-// members of an instance outside its
-// lifetime. (SynchronizationStorage::get() access non-static members)
-//
-// So, LinkerInitialized object of SynchronizationStorage uses a
-// non-trivial constructor, which is called at some point during dynamic
-// initialization, and is therefore subject to order of dynamic
-// initialization bugs, where get() is called before the object's
-// constructor is, resulting in undefined behavior.
-//
-// Similarly, a LinkerInitialized SynchronizationStorage object has a
-// non-trivial destructor, and so its lifetime ends at some point during
-// destruction of objects with static storage duration [basic.start.term]
-// p4. There is a window where other exit code could call get() after this
-// occurs, resulting in undefined behavior.
-//
-// Combined, these statements imply that LinkerInitialized instances
-// of SynchronizationStorage<T> rely on undefined behavior.
-//
-// However, in practice, the implementation works on all supported
-// compilers. Specifically, we rely on:
-//
-// a) zero-initialization being sufficient to initialize
-// LinkerInitialized instances for the purposes of calling
-// get(), regardless of when the constructor is called. This is
-// because the is_dynamic_ boolean is correctly zero-initialized to
-// false.
-//
-// b) the LinkerInitialized constructor is a NOP, and immaterial to
-// even to concurrent calls to get().
-//
-// c) the destructor being a NOP for LinkerInitialized objects
-// (guaranteed by a check for !is_dynamic_), and so any concurrent and
-// subsequent calls to get() functioning as if the destructor were not
-// called, by virtue of the instances' storage remaining valid after the
-// destructor runs.
-//
-// d) That a-c apply transitively when SynchronizationStorage<T> is the
-// only member of a class allocated in static storage.
-//
-// Nothing in the language standard guarantees that a-d hold. In practice,
-// these hold in all supported compilers.
-//
-// Future direction:
-//
-// Ideally, we would simply use std::mutex or a similar class, which when
-// allocated statically would support use immediately after static
-// initialization up until static storage is reclaimed (i.e. the properties
-// we require of all "linker initialized" instances).
-//
-// Regarding construction in static storage, std::mutex is required to
-// provide a constexpr default constructor [thread.mutex.class], which
-// ensures the instance's lifetime begins with static initialization
-// [basic.start.init], and so is immune to any problems caused by the order
-// of dynamic initialization. However, as of this writing Microsoft's
-// Visual Studio does not provide a constexpr constructor for std::mutex.
-// See
-// https://blogs.msdn.microsoft.com/vcblog/2015/06/02/constexpr-complete-for-vs-2015-rtm-c11-compiler-c17-stl/
-//
-// Regarding destruction of instances in static storage, [basic.life] does
-// say an object ends when storage in which the occupies is released, in
-// the case of non-trivial destructor. However, std::mutex is not specified
-// to have a trivial destructor.
-//
-// So, we would need a class with a constexpr default constructor and a
-// trivial destructor. Today, we can achieve neither desired property using
-// std::mutex directly.
-template <typename T>
-class SynchronizationStorage {
- public:
- // Instances allocated on the heap or on the stack should use the default
- // constructor.
- SynchronizationStorage()
- : is_dynamic_(true), once_() {}
-
- // Instances allocated in static storage (not on the heap, not on the
- // stack) should use this constructor.
- explicit SynchronizationStorage(base_internal::LinkerInitialized) {}
-
- constexpr explicit SynchronizationStorage(absl::ConstInitType)
- : is_dynamic_(false), once_(), space_{{0}} {}
-
- SynchronizationStorage(SynchronizationStorage&) = delete;
- SynchronizationStorage& operator=(SynchronizationStorage&) = delete;
-
- ~SynchronizationStorage() {
- if (is_dynamic_) {
- get()->~T();
- }
- }
-
- // Retrieve the object in storage. This is fast and thread safe, but does
- // incur the cost of absl::call_once().
- //
- // For instances in static storage constructed with the
- // LinkerInitialized constructor, may be called at any time without
- // regard for order of dynamic initialization or destruction of objects
- // in static storage. See the class comment for caveats.
- T* get() {
- absl::call_once(once_, SynchronizationStorage::Construct, this);
- return reinterpret_cast<T*>(&space_);
- }
-
- private:
- static void Construct(SynchronizationStorage<T>* self) {
- new (&self->space_) T();
- }
-
- // When true, T's destructor is run when this is destructed.
- //
- // The LinkerInitialized constructor assumes this value will be set
- // false by static initialization.
- bool is_dynamic_;
-
- absl::once_flag once_;
-
- // An aligned space for T.
- typename std::aligned_storage<sizeof(T), alignof(T)>::type space_;
-};
-
-} // namespace synchronization_internal
-} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
index caa2baf64bd..a6031787e0b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
#include "absl/synchronization/internal/waiter.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
void PerThreadSem::SetThreadBlockedCounter(std::atomic<int> *counter) {
@@ -40,12 +41,16 @@ std::atomic<int> *PerThreadSem::GetThreadBlockedCounter() {
}
void PerThreadSem::Init(base_internal::ThreadIdentity *identity) {
- Waiter::GetWaiter(identity)->Init();
+ new (Waiter::GetWaiter(identity)) Waiter();
identity->ticker.store(0, std::memory_order_relaxed);
identity->wait_start.store(0, std::memory_order_relaxed);
identity->is_idle.store(false, std::memory_order_relaxed);
}
+void PerThreadSem::Destroy(base_internal::ThreadIdentity *identity) {
+ Waiter::GetWaiter(identity)->~Waiter();
+}
+
void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) {
const int ticker =
identity->ticker.fetch_add(1, std::memory_order_relaxed) + 1;
@@ -58,16 +63,17 @@ void PerThreadSem::Tick(base_internal::ThreadIdentity *identity) {
}
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalPerThreadSemPost(
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
absl::base_internal::ThreadIdentity *identity) {
absl::synchronization_internal::Waiter::GetWaiter(identity)->Post();
}
-ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait(
+ABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
absl::synchronization_internal::KernelTimeout t) {
bool timeout = false;
absl::base_internal::ThreadIdentity *identity;
@@ -89,6 +95,7 @@ ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait(
if (identity->blocked_count_ptr != nullptr) {
identity->blocked_count_ptr->fetch_sub(1, std::memory_order_relaxed);
}
+
identity->is_idle.store(false, std::memory_order_relaxed);
identity->wait_start.store(0, std::memory_order_relaxed);
return !timeout;
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
index 678b69e487a..7beae8ef1d0 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -32,6 +32,7 @@
#include "absl/synchronization/internal/kernel_timeout.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
class Mutex;
@@ -65,6 +66,10 @@ class PerThreadSem {
// REQUIRES: May only be called by ThreadIdentity.
static void Init(base_internal::ThreadIdentity* identity);
+ // Destroy the PerThreadSem associated with "identity".
+ // REQUIRES: May only be called by ThreadIdentity.
+ static void Destroy(base_internal::ThreadIdentity* identity);
+
// Increments "identity"'s count.
static inline void Post(base_internal::ThreadIdentity* identity);
@@ -73,13 +78,15 @@ class PerThreadSem {
// !t.has_timeout() => Wait(t) will return true.
static inline bool Wait(KernelTimeout t);
- // White-listed callers.
+ // Permitted callers.
friend class PerThreadSemTest;
friend class absl::Mutex;
friend absl::base_internal::ThreadIdentity* CreateThreadIdentity();
+ friend void ReclaimThreadIdentity(void* v);
};
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
@@ -89,19 +96,20 @@ class PerThreadSem {
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void AbslInternalPerThreadSemPost(
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
absl::base_internal::ThreadIdentity* identity);
-bool AbslInternalPerThreadSemWait(
+bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
absl::synchronization_internal::KernelTimeout t);
} // extern "C"
void absl::synchronization_internal::PerThreadSem::Post(
absl::base_internal::ThreadIdentity* identity) {
- AbslInternalPerThreadSemPost(identity);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(identity);
}
bool absl::synchronization_internal::PerThreadSem::Wait(
absl::synchronization_internal::KernelTimeout t) {
- return AbslInternalPerThreadSemWait(t);
+ return ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(t);
}
+
#endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
index c29d8403df4..8cf59e64e96 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -23,6 +23,7 @@
#include <thread> // NOLINT(build/c++11)
#include "gtest/gtest.h"
+#include "absl/base/config.h"
#include "absl/base/internal/cycleclock.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/strings/str_cat.h"
@@ -33,6 +34,7 @@
// primitives which might use PerThreadSem, most notably absl::Mutex.
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
class SimpleSemaphore {
@@ -114,10 +116,9 @@ class PerThreadSemTest : public testing::Test {
min_cycles = std::min(min_cycles, cycles);
total_cycles += cycles;
}
- std::string out =
- StrCat(msg, "min cycle count=", min_cycles, " avg cycle count=",
- absl::SixDigits(static_cast<double>(total_cycles) /
- kNumIterations));
+ std::string out = StrCat(
+ msg, "min cycle count=", min_cycles, " avg cycle count=",
+ absl::SixDigits(static_cast<double>(total_cycles) / kNumIterations));
printf("%s\n", out.c_str());
partner_thread.join();
@@ -152,12 +153,16 @@ TEST_F(PerThreadSemTest, WithTimeout) {
}
TEST_F(PerThreadSemTest, Timeouts) {
- absl::Time timeout = absl::Now() + absl::Milliseconds(50);
+ const absl::Duration delay = absl::Milliseconds(50);
+ const absl::Time start = absl::Now();
+ EXPECT_FALSE(Wait(start + delay));
+ const absl::Duration elapsed = absl::Now() - start;
// Allow for a slight early return, to account for quality of implementation
// issues on various platforms.
const absl::Duration slop = absl::Microseconds(200);
- EXPECT_FALSE(Wait(timeout));
- EXPECT_LE(timeout, absl::Now() + slop);
+ EXPECT_LE(delay - slop, elapsed)
+ << "Wait returned " << delay - elapsed
+ << " early (with " << slop << " slop), start time was " << start;
absl::Time negative_timeout = absl::UnixEpoch() - absl::Milliseconds(100);
EXPECT_FALSE(Wait(negative_timeout));
@@ -172,4 +177,5 @@ TEST_F(PerThreadSemTest, Timeouts) {
} // namespace
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/thread_pool.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/thread_pool.h
index 846404277a0..0cb96dacde8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/thread_pool.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/thread_pool.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,6 +16,7 @@
#define ABSL_SYNCHRONIZATION_INTERNAL_THREAD_POOL_H_
#include <cassert>
+#include <cstddef>
#include <functional>
#include <queue>
#include <thread> // NOLINT(build/c++11)
@@ -25,6 +26,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// A simple ThreadPool implementation for tests.
@@ -42,7 +44,7 @@ class ThreadPool {
~ThreadPool() {
{
absl::MutexLock l(&mu_);
- for (int i = 0; i < threads_.size(); ++i) {
+ for (size_t i = 0; i < threads_.size(); i++) {
queue_.push(nullptr); // Shutdown signal.
}
}
@@ -59,7 +61,7 @@ class ThreadPool {
}
private:
- bool WorkAvailable() const EXCLUSIVE_LOCKS_REQUIRED(mu_) {
+ bool WorkAvailable() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_) {
return !queue_.empty();
}
@@ -80,11 +82,12 @@ class ThreadPool {
}
absl::Mutex mu_;
- std::queue<std::function<void()>> queue_ GUARDED_BY(mu_);
+ std::queue<std::function<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/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.cc
index 768c52085cd..2123be60f54 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -40,12 +40,17 @@
#include <atomic>
#include <cassert>
#include <cstdint>
+#include <new>
+#include <type_traits>
+
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/thread_identity.h"
#include "absl/base/optimization.h"
#include "absl/synchronization/internal/kernel_timeout.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
static void MaybeBecomeIdle() {
@@ -62,72 +67,21 @@ static void MaybeBecomeIdle() {
#if ABSL_WAITER_MODE == ABSL_WAITER_MODE_FUTEX
-// Some Android headers are missing these definitions even though they
-// support these futex operations.
-#ifdef __BIONIC__
-#ifndef SYS_futex
-#define SYS_futex __NR_futex
-#endif
-#ifndef FUTEX_WAIT_BITSET
-#define FUTEX_WAIT_BITSET 9
-#endif
-#ifndef FUTEX_PRIVATE_FLAG
-#define FUTEX_PRIVATE_FLAG 128
-#endif
-#ifndef FUTEX_CLOCK_REALTIME
-#define FUTEX_CLOCK_REALTIME 256
-#endif
-#ifndef FUTEX_BITSET_MATCH_ANY
-#define FUTEX_BITSET_MATCH_ANY 0xFFFFFFFF
-#endif
-#endif
-class Futex {
- public:
- static int WaitUntil(std::atomic<int32_t> *v, int32_t val,
- KernelTimeout t) {
- int err = 0;
- if (t.has_timeout()) {
- // https://locklessinc.com/articles/futex_cheat_sheet/
- // Unlike FUTEX_WAIT, FUTEX_WAIT_BITSET uses absolute time.
- struct timespec abs_timeout = t.MakeAbsTimespec();
- // Atomically check that the futex value is still 0, and if it
- // is, sleep until abs_timeout or until woken by FUTEX_WAKE.
- err = syscall(
- SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAIT_BITSET | FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME, val,
- &abs_timeout, nullptr, FUTEX_BITSET_MATCH_ANY);
- } else {
- // Atomically check that the futex value is still 0, and if it
- // is, sleep until woken by FUTEX_WAKE.
- err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAIT | FUTEX_PRIVATE_FLAG, val, nullptr);
- }
- if (err != 0) {
- err = -errno;
- }
- return err;
- }
-
- static int Wake(std::atomic<int32_t> *v, int32_t count) {
- int err = syscall(SYS_futex, reinterpret_cast<int32_t *>(v),
- FUTEX_WAKE | FUTEX_PRIVATE_FLAG, count);
- if (ABSL_PREDICT_FALSE(err < 0)) {
- err = -errno;
- }
- return err;
- }
-};
-
-void Waiter::Init() {
+Waiter::Waiter() {
futex_.store(0, std::memory_order_relaxed);
}
+Waiter::~Waiter() = default;
+
bool Waiter::Wait(KernelTimeout t) {
// Loop until we can atomically decrement futex from a positive
// value, waiting on a futex while we believe it is zero.
+ // Note that, since the thread ticker is just reset, we don't need to check
+ // whether the thread is idle on the very first pass of the loop.
+ bool first_pass = true;
while (true) {
int32_t x = futex_.load(std::memory_order_relaxed);
- if (x != 0) {
+ while (x != 0) {
if (!futex_.compare_exchange_weak(x, x - 1,
std::memory_order_acquire,
std::memory_order_relaxed)) {
@@ -136,6 +90,8 @@ bool Waiter::Wait(KernelTimeout t) {
return true; // Consumed a wakeup, we are done.
}
+
+ if (!first_pass) MaybeBecomeIdle();
const int err = Futex::WaitUntil(&futex_, 0, t);
if (err != 0) {
if (err == -EINTR || err == -EWOULDBLOCK) {
@@ -146,14 +102,13 @@ bool Waiter::Wait(KernelTimeout t) {
ABSL_RAW_LOG(FATAL, "Futex operation failed with error %d\n", err);
}
}
-
- MaybeBecomeIdle();
+ first_pass = false;
}
}
void Waiter::Post() {
if (futex_.fetch_add(1, std::memory_order_release) == 0) {
- // We incremented from 0, need to wake a potential waker.
+ // We incremented from 0, need to wake a potential waiter.
Poke();
}
}
@@ -191,7 +146,7 @@ class PthreadMutexHolder {
pthread_mutex_t *mu_;
};
-void Waiter::Init() {
+Waiter::Waiter() {
const int err = pthread_mutex_init(&mu_, 0);
if (err != 0) {
ABSL_RAW_LOG(FATAL, "pthread_mutex_init failed: %d", err);
@@ -202,8 +157,20 @@ void Waiter::Init() {
ABSL_RAW_LOG(FATAL, "pthread_cond_init failed: %d", err2);
}
- waiter_count_.store(0, std::memory_order_relaxed);
- wakeup_count_.store(0, std::memory_order_relaxed);
+ waiter_count_ = 0;
+ wakeup_count_ = 0;
+}
+
+Waiter::~Waiter() {
+ const int err = pthread_mutex_destroy(&mu_);
+ if (err != 0) {
+ ABSL_RAW_LOG(FATAL, "pthread_mutex_destroy failed: %d", err);
+ }
+
+ const int err2 = pthread_cond_destroy(&cv_);
+ if (err2 != 0) {
+ ABSL_RAW_LOG(FATAL, "pthread_cond_destroy failed: %d", err2);
+ }
}
bool Waiter::Wait(KernelTimeout t) {
@@ -213,21 +180,13 @@ bool Waiter::Wait(KernelTimeout t) {
}
PthreadMutexHolder h(&mu_);
- waiter_count_.fetch_add(1, std::memory_order_relaxed);
+ ++waiter_count_;
// Loop until we find a wakeup to consume or timeout.
- while (true) {
- int x = wakeup_count_.load(std::memory_order_relaxed);
- if (x != 0) {
- if (!wakeup_count_.compare_exchange_weak(x, x - 1,
- std::memory_order_acquire,
- std::memory_order_relaxed)) {
- continue; // Raced with someone, retry.
- }
- // Successfully consumed a wakeup, we're done.
- waiter_count_.fetch_sub(1, std::memory_order_relaxed);
- return true;
- }
-
+ // Note that, since the thread ticker is just reset, we don't need to check
+ // whether the thread is idle on the very first pass of the loop.
+ bool first_pass = true;
+ while (wakeup_count_ == 0) {
+ if (!first_pass) MaybeBecomeIdle();
// No wakeups available, time to wait.
if (!t.has_timeout()) {
const int err = pthread_cond_wait(&cv_, &mu_);
@@ -237,46 +196,56 @@ bool Waiter::Wait(KernelTimeout t) {
} else {
const int err = pthread_cond_timedwait(&cv_, &mu_, &abs_timeout);
if (err == ETIMEDOUT) {
- waiter_count_.fetch_sub(1, std::memory_order_relaxed);
+ --waiter_count_;
return false;
}
if (err != 0) {
- ABSL_RAW_LOG(FATAL, "pthread_cond_wait failed: %d", err);
+ ABSL_RAW_LOG(FATAL, "pthread_cond_timedwait failed: %d", err);
}
}
- MaybeBecomeIdle();
+ first_pass = false;
}
+ // Consume a wakeup and we're done.
+ --wakeup_count_;
+ --waiter_count_;
+ return true;
}
void Waiter::Post() {
- wakeup_count_.fetch_add(1, std::memory_order_release);
- Poke();
+ PthreadMutexHolder h(&mu_);
+ ++wakeup_count_;
+ InternalCondVarPoke();
}
void Waiter::Poke() {
- if (waiter_count_.load(std::memory_order_relaxed) == 0) {
- return;
- }
- // Potentially a waker. Take the lock and check again.
PthreadMutexHolder h(&mu_);
- if (waiter_count_.load(std::memory_order_relaxed) == 0) {
- return;
- }
- const int err = pthread_cond_signal(&cv_);
- if (err != 0) {
- ABSL_RAW_LOG(FATAL, "pthread_cond_signal failed: %d", err);
+ InternalCondVarPoke();
+}
+
+void Waiter::InternalCondVarPoke() {
+ if (waiter_count_ != 0) {
+ const int err = pthread_cond_signal(&cv_);
+ if (ABSL_PREDICT_FALSE(err != 0)) {
+ ABSL_RAW_LOG(FATAL, "pthread_cond_signal failed: %d", err);
+ }
}
}
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
-void Waiter::Init() {
+Waiter::Waiter() {
if (sem_init(&sem_, 0, 0) != 0) {
ABSL_RAW_LOG(FATAL, "sem_init failed with errno %d\n", errno);
}
wakeups_.store(0, std::memory_order_relaxed);
}
+Waiter::~Waiter() {
+ if (sem_destroy(&sem_) != 0) {
+ ABSL_RAW_LOG(FATAL, "sem_destroy failed with errno %d\n", errno);
+ }
+}
+
bool Waiter::Wait(KernelTimeout t) {
struct timespec abs_timeout;
if (t.has_timeout()) {
@@ -284,9 +253,12 @@ bool Waiter::Wait(KernelTimeout t) {
}
// Loop until we timeout or consume a wakeup.
+ // Note that, since the thread ticker is just reset, we don't need to check
+ // whether the thread is idle on the very first pass of the loop.
+ bool first_pass = true;
while (true) {
int x = wakeups_.load(std::memory_order_relaxed);
- if (x != 0) {
+ while (x != 0) {
if (!wakeups_.compare_exchange_weak(x, x - 1,
std::memory_order_acquire,
std::memory_order_relaxed)) {
@@ -296,6 +268,7 @@ bool Waiter::Wait(KernelTimeout t) {
return true;
}
+ if (!first_pass) MaybeBecomeIdle();
// Nothing to consume, wait (looping on EINTR).
while (true) {
if (!t.has_timeout()) {
@@ -309,13 +282,16 @@ bool Waiter::Wait(KernelTimeout t) {
ABSL_RAW_LOG(FATAL, "sem_timedwait failed: %d", errno);
}
}
- MaybeBecomeIdle();
+ first_pass = false;
}
}
void Waiter::Post() {
- wakeups_.fetch_add(1, std::memory_order_release); // Post a wakeup.
- Poke();
+ // Post a wakeup.
+ if (wakeups_.fetch_add(1, std::memory_order_release) == 0) {
+ // We incremented from 0, need to wake a potential waiter.
+ Poke();
+ }
}
void Waiter::Poke() {
@@ -326,6 +302,41 @@ void Waiter::Poke() {
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
+class Waiter::WinHelper {
+ public:
+ static SRWLOCK *GetLock(Waiter *w) {
+ return reinterpret_cast<SRWLOCK *>(&w->mu_storage_);
+ }
+
+ static CONDITION_VARIABLE *GetCond(Waiter *w) {
+ return reinterpret_cast<CONDITION_VARIABLE *>(&w->cv_storage_);
+ }
+
+ static_assert(sizeof(SRWLOCK) == sizeof(void *),
+ "`mu_storage_` does not have the same size as SRWLOCK");
+ static_assert(alignof(SRWLOCK) == alignof(void *),
+ "`mu_storage_` does not have the same alignment as SRWLOCK");
+
+ static_assert(sizeof(CONDITION_VARIABLE) == sizeof(void *),
+ "`ABSL_CONDITION_VARIABLE_STORAGE` does not have the same size "
+ "as `CONDITION_VARIABLE`");
+ static_assert(
+ alignof(CONDITION_VARIABLE) == alignof(void *),
+ "`cv_storage_` does not have the same alignment as `CONDITION_VARIABLE`");
+
+ // The SRWLOCK and CONDITION_VARIABLE types must be trivially constructible
+ // and destructible because we never call their constructors or destructors.
+ static_assert(std::is_trivially_constructible<SRWLOCK>::value,
+ "The `SRWLOCK` type must be trivially constructible");
+ static_assert(
+ std::is_trivially_constructible<CONDITION_VARIABLE>::value,
+ "The `CONDITION_VARIABLE` type must be trivially constructible");
+ static_assert(std::is_trivially_destructible<SRWLOCK>::value,
+ "The `SRWLOCK` type must be trivially destructible");
+ static_assert(std::is_trivially_destructible<CONDITION_VARIABLE>::value,
+ "The `CONDITION_VARIABLE` type must be trivially destructible");
+};
+
class LockHolder {
public:
explicit LockHolder(SRWLOCK* mu) : mu_(mu) {
@@ -343,65 +354,69 @@ class LockHolder {
SRWLOCK* mu_;
};
-void Waiter::Init() {
- InitializeSRWLock(&mu_);
- InitializeConditionVariable(&cv_);
- waiter_count_.store(0, std::memory_order_relaxed);
- wakeup_count_.store(0, std::memory_order_relaxed);
+Waiter::Waiter() {
+ auto *mu = ::new (static_cast<void *>(&mu_storage_)) SRWLOCK;
+ auto *cv = ::new (static_cast<void *>(&cv_storage_)) CONDITION_VARIABLE;
+ InitializeSRWLock(mu);
+ InitializeConditionVariable(cv);
+ waiter_count_ = 0;
+ wakeup_count_ = 0;
}
+// SRW locks and condition variables do not need to be explicitly destroyed.
+// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializesrwlock
+// https://stackoverflow.com/questions/28975958/why-does-windows-have-no-deleteconditionvariable-function-to-go-together-with
+Waiter::~Waiter() = default;
+
bool Waiter::Wait(KernelTimeout t) {
- LockHolder h(&mu_);
- waiter_count_.fetch_add(1, std::memory_order_relaxed);
+ SRWLOCK *mu = WinHelper::GetLock(this);
+ CONDITION_VARIABLE *cv = WinHelper::GetCond(this);
- // Loop until we find a wakeup to consume or timeout.
- while (true) {
- int x = wakeup_count_.load(std::memory_order_relaxed);
- if (x != 0) {
- if (!wakeup_count_.compare_exchange_weak(x, x - 1,
- std::memory_order_acquire,
- std::memory_order_relaxed)) {
- continue; // Raced with someone, retry.
- }
- // Successfully consumed a wakeup, we're done.
- waiter_count_.fetch_sub(1, std::memory_order_relaxed);
- return true;
- }
+ LockHolder h(mu);
+ ++waiter_count_;
+ // Loop until we find a wakeup to consume or timeout.
+ // Note that, since the thread ticker is just reset, we don't need to check
+ // whether the thread is idle on the very first pass of the loop.
+ bool first_pass = true;
+ while (wakeup_count_ == 0) {
+ if (!first_pass) MaybeBecomeIdle();
// No wakeups available, time to wait.
- if (!SleepConditionVariableSRW(
- &cv_, &mu_, t.InMillisecondsFromNow(), 0)) {
+ if (!SleepConditionVariableSRW(cv, mu, t.InMillisecondsFromNow(), 0)) {
// GetLastError() returns a Win32 DWORD, but we assign to
// unsigned long to simplify the ABSL_RAW_LOG case below. The uniform
// initialization guarantees this is not a narrowing conversion.
const unsigned long err{GetLastError()}; // NOLINT(runtime/int)
if (err == ERROR_TIMEOUT) {
- waiter_count_.fetch_sub(1, std::memory_order_relaxed);
+ --waiter_count_;
return false;
} else {
ABSL_RAW_LOG(FATAL, "SleepConditionVariableSRW failed: %lu", err);
}
}
-
- MaybeBecomeIdle();
+ first_pass = false;
}
+ // Consume a wakeup and we're done.
+ --wakeup_count_;
+ --waiter_count_;
+ return true;
}
void Waiter::Post() {
- wakeup_count_.fetch_add(1, std::memory_order_release);
- Poke();
+ LockHolder h(WinHelper::GetLock(this));
+ ++wakeup_count_;
+ InternalCondVarPoke();
}
void Waiter::Poke() {
- if (waiter_count_.load(std::memory_order_relaxed) == 0) {
- return;
- }
- // Potentially a waker. Take the lock and check again.
- LockHolder h(&mu_);
- if (waiter_count_.load(std::memory_order_relaxed) == 0) {
- return;
+ LockHolder h(WinHelper::GetLock(this));
+ InternalCondVarPoke();
+}
+
+void Waiter::InternalCondVarPoke() {
+ if (waiter_count_ != 0) {
+ WakeConditionVariable(WinHelper::GetCond(this));
}
- WakeConditionVariable(&cv_);
}
#else
@@ -409,4 +424,5 @@ void Waiter::Poke() {
#endif
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.h
index 23166f4bfa3..be3df180d4e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/internal/waiter.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,11 +19,15 @@
#include "absl/base/config.h"
#ifdef _WIN32
-#include <windows.h>
+#include <sdkddkver.h>
#else
#include <pthread.h>
#endif
+#ifdef __linux__
+#include <linux/futex.h>
+#endif
+
#ifdef ABSL_HAVE_SEMAPHORE_H
#include <semaphore.h>
#endif
@@ -32,6 +36,7 @@
#include <cstdint>
#include "absl/base/internal/thread_identity.h"
+#include "absl/synchronization/internal/futex.h"
#include "absl/synchronization/internal/kernel_timeout.h"
// May be chosen at compile time via -DABSL_FORCE_WAITER_MODE=<index>
@@ -42,9 +47,9 @@
#if defined(ABSL_FORCE_WAITER_MODE)
#define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
-#elif defined(_WIN32)
+#elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(__linux__)
+#elif defined(ABSL_INTERNAL_HAVE_FUTEX)
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
#elif defined(ABSL_HAVE_SEMAPHORE_H)
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
@@ -53,19 +58,21 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
// Waiter is an OS-specific semaphore.
class Waiter {
public:
- // No constructor, instances use the reserved space in ThreadIdentity.
- // All initialization logic belongs in `Init()`.
- Waiter() = delete;
+ // Prepare any data to track waits.
+ Waiter();
+
+ // Not copyable or movable
Waiter(const Waiter&) = delete;
Waiter& operator=(const Waiter&) = delete;
- // Prepare any data to track waits.
- void Init();
+ // Destroy any data to track waits.
+ ~Waiter();
// Blocks the calling thread until a matching call to `Post()` or
// `t` has passed. Returns `true` if woken (`Post()` called),
@@ -89,8 +96,8 @@ class Waiter {
}
// How many periods to remain idle before releasing resources
-#ifndef THREAD_SANITIZER
- static const int kIdlePeriods = 60;
+#ifndef ABSL_HAVE_THREAD_SANITIZER
+ static constexpr int kIdlePeriods = 60;
#else
// Memory consumption under ThreadSanitizer is a serious concern,
// so we release resources sooner. The value of 1 leads to 1 to 2 second
@@ -106,10 +113,13 @@ class Waiter {
static_assert(sizeof(int32_t) == sizeof(futex_), "Wrong size for futex");
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_CONDVAR
+ // REQUIRES: mu_ must be held.
+ void InternalCondVarPoke();
+
pthread_mutex_t mu_;
pthread_cond_t cv_;
- std::atomic<int> waiter_count_;
- std::atomic<int> wakeup_count_; // Unclaimed wakeups, written under lock.
+ int waiter_count_;
+ int wakeup_count_; // Unclaimed wakeups.
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_SEM
sem_t sem_;
@@ -119,14 +129,19 @@ class Waiter {
std::atomic<int> wakeups_;
#elif ABSL_WAITER_MODE == ABSL_WAITER_MODE_WIN32
- // The Windows API has lots of choices for synchronization
- // primivitives. We are using SRWLOCK and CONDITION_VARIABLE
- // because they don't require a destructor to release system
- // resources.
- SRWLOCK mu_;
- CONDITION_VARIABLE cv_;
- std::atomic<int> waiter_count_;
- std::atomic<int> wakeup_count_;
+ // WinHelper - Used to define utilities for accessing the lock and
+ // condition variable storage once the types are complete.
+ class WinHelper;
+
+ // REQUIRES: WinHelper::GetLock(this) must be held.
+ void InternalCondVarPoke();
+
+ // We can't include Windows.h in our headers, so we use aligned charachter
+ // buffers to define the storage of SRWLOCK and CONDITION_VARIABLE.
+ alignas(void*) unsigned char mu_storage_[sizeof(void*)];
+ alignas(void*) unsigned char cv_storage_[sizeof(void*)];
+ int waiter_count_;
+ int wakeup_count_;
#else
#error Unknown ABSL_WAITER_MODE
@@ -134,6 +149,7 @@ class Waiter {
};
} // namespace synchronization_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_SYNCHRONIZATION_INTERNAL_WAITER_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/lifetime_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/lifetime_test.cc
index 8b168e21a31..cc973a32907 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/lifetime_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/lifetime_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -122,6 +122,11 @@ class OnDestruction {
Function fn_;
};
+// These tests require that the compiler correctly supports C++11 constant
+// initialization... but MSVC has a known regression since v19.10:
+// https://developercommunity.visualstudio.com/content/problem/336946/class-with-constexpr-constructor-not-using-static.html
+// TODO(epastor): Limit the affected range once MSVC fixes this bug.
+#if defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)
// kConstInit
// Test early usage. (Declaration comes first; definitions must appear after
// the test runner.)
@@ -143,14 +148,15 @@ ABSL_CONST_INIT absl::Mutex early_const_init_mutex(absl::kConstInit);
// constructors of globals "happen at link time"; memory is pre-initialized,
// before the constructors of either grab_lock or check_still_locked are run.)
extern absl::Mutex const_init_sanity_mutex;
-OnConstruction grab_lock([]() NO_THREAD_SAFETY_ANALYSIS {
+OnConstruction grab_lock([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {
const_init_sanity_mutex.Lock();
});
ABSL_CONST_INIT absl::Mutex const_init_sanity_mutex(absl::kConstInit);
-OnConstruction check_still_locked([]() NO_THREAD_SAFETY_ANALYSIS {
+OnConstruction check_still_locked([]() ABSL_NO_THREAD_SAFETY_ANALYSIS {
const_init_sanity_mutex.AssertHeld();
const_init_sanity_mutex.Unlock();
});
+#endif // defined(__clang__) || !(defined(_MSC_VER) && _MSC_VER > 1900)
// Test shutdown usage. (Declarations come first; definitions must appear after
// the test runner.)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.cc
index f1b42db15f9..76ad41fe163 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -39,6 +39,7 @@
#include <thread> // NOLINT(build/c++11)
#include "absl/base/attributes.h"
+#include "absl/base/call_once.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/atomic_hook.h"
@@ -49,6 +50,7 @@
#include "absl/base/internal/spinlock.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/base/internal/thread_identity.h"
+#include "absl/base/internal/tsan_mutex_interface.h"
#include "absl/base/port.h"
#include "absl/debugging/stacktrace.h"
#include "absl/debugging/symbolize.h"
@@ -58,6 +60,7 @@
using absl::base_internal::CurrentThreadIdentityIfPresent;
using absl::base_internal::PerThreadSynch;
+using absl::base_internal::SchedulingGuard;
using absl::base_internal::ThreadIdentity;
using absl::synchronization_internal::GetOrCreateCurrentThreadIdentity;
using absl::synchronization_internal::GraphCycles;
@@ -67,14 +70,17 @@ using absl::synchronization_internal::KernelTimeout;
using absl::synchronization_internal::PerThreadSem;
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalMutexYield() { std::this_thread::yield(); }
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)() {
+ std::this_thread::yield();
+}
} // extern "C"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
-#if defined(THREAD_SANITIZER)
+#if defined(ABSL_HAVE_THREAD_SANITIZER)
constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;
#else
constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;
@@ -84,40 +90,25 @@ ABSL_CONST_INIT std::atomic<OnDeadlockCycle> synch_deadlock_detection(
kDeadlockDetectionDefault);
ABSL_CONST_INIT std::atomic<bool> synch_check_invariants(false);
-// ------------------------------------------ spinlock support
-
-// Make sure read-only globals used in the Mutex code are contained on the
-// same cacheline and cacheline aligned to eliminate any false sharing with
-// other globals from this and other modules.
-static struct MutexGlobals {
- MutexGlobals() {
- // Find machine-specific data needed for Delay() and
- // TryAcquireWithSpinning(). This runs in the global constructor
- // sequence, and before that zeros are safe values.
- num_cpus = absl::base_internal::NumCPUs();
- spinloop_iterations = num_cpus > 1 ? 1500 : 0;
- }
- int num_cpus;
- int spinloop_iterations;
- // Pad this struct to a full cacheline to prevent false sharing.
- char padding[ABSL_CACHELINE_SIZE - 2 * sizeof(int)];
-} ABSL_CACHELINE_ALIGNED mutex_globals;
-static_assert(
- sizeof(MutexGlobals) == ABSL_CACHELINE_SIZE,
- "MutexGlobals must occupy an entire cacheline to prevent false sharing");
-
-ABSL_CONST_INIT absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
submit_profile_data;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
- void (*)(const char *msg, const void *obj, int64_t wait_cycles)> mutex_tracer;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
- void (*)(const char *msg, const void *cv)> cond_var_tracer;
-ABSL_CONST_INIT absl::base_internal::AtomicHook<
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
+ const char *msg, const void *obj, int64_t wait_cycles)>
+ mutex_tracer;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
+ absl::base_internal::AtomicHook<void (*)(const char *msg, const void *cv)>
+ cond_var_tracer;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<
bool (*)(const void *pc, char *out, int out_size)>
symbolizer(absl::Symbolize);
} // namespace
+static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
+ bool locking, bool trylock,
+ bool read_lock);
+
void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp)) {
submit_profile_data.Store(fn);
}
@@ -135,33 +126,64 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) {
symbolizer.Store(fn);
}
-// spinlock delay on iteration c. Returns new c.
namespace {
- enum DelayMode { AGGRESSIVE, GENTLE };
+// Represents the strategy for spin and yield.
+// See the comment in GetMutexGlobals() for more information.
+enum DelayMode { AGGRESSIVE, GENTLE };
+
+struct ABSL_CACHELINE_ALIGNED MutexGlobals {
+ absl::once_flag once;
+ int spinloop_iterations = 0;
+ int32_t mutex_sleep_limit[2] = {};
};
-static int Delay(int32_t c, DelayMode mode) {
- // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
- // aggressive then spin many times before yielding. If the mode is
- // gentle then spin only a few times before yielding. Aggressive spinning is
- // used to ensure that an Unlock() call, which must get the spin lock for
- // any thread to make progress gets it without undue delay.
- int32_t limit = (mutex_globals.num_cpus > 1) ?
- ((mode == AGGRESSIVE) ? 5000 : 250) : 0;
+
+const MutexGlobals &GetMutexGlobals() {
+ ABSL_CONST_INIT static MutexGlobals data;
+ absl::base_internal::LowLevelCallOnce(&data.once, [&]() {
+ const int num_cpus = absl::base_internal::NumCPUs();
+ data.spinloop_iterations = num_cpus > 1 ? 1500 : 0;
+ // If this a uniprocessor, only yield/sleep. Otherwise, if the mode is
+ // aggressive then spin many times before yielding. If the mode is
+ // gentle then spin only a few times before yielding. Aggressive spinning
+ // is used to ensure that an Unlock() call, which must get the spin lock
+ // for any thread to make progress gets it without undue delay.
+ if (num_cpus > 1) {
+ data.mutex_sleep_limit[AGGRESSIVE] = 5000;
+ data.mutex_sleep_limit[GENTLE] = 250;
+ } else {
+ data.mutex_sleep_limit[AGGRESSIVE] = 0;
+ data.mutex_sleep_limit[GENTLE] = 0;
+ }
+ });
+ return data;
+}
+} // namespace
+
+namespace synchronization_internal {
+// Returns the Mutex delay on iteration `c` depending on the given `mode`.
+// The returned value should be used as `c` for the next call to `MutexDelay`.
+int MutexDelay(int32_t c, int mode) {
+ const int32_t limit = GetMutexGlobals().mutex_sleep_limit[mode];
if (c < limit) {
- c++; // spin
+ // Spin.
+ c++;
} else {
- ABSL_TSAN_MUTEX_PRE_DIVERT(0, 0);
- if (c == limit) { // yield once
- AbslInternalMutexYield();
+ SchedulingGuard::ScopedEnable enable_rescheduling;
+ ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
+ if (c == limit) {
+ // Yield once.
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
c++;
- } else { // then wait
+ } else {
+ // Then wait.
absl::SleepFor(absl::Microseconds(10));
c = 0;
}
- ABSL_TSAN_MUTEX_POST_DIVERT(0, 0);
+ ABSL_TSAN_MUTEX_POST_DIVERT(nullptr, 0);
}
- return (c);
+ return c;
}
+} // namespace synchronization_internal
// --------------------------Generic atomic ops
// Ensure that "(*pv & bits) == bits" by doing an atomic update of "*pv" to
@@ -199,12 +221,12 @@ static void AtomicClearBits(std::atomic<intptr_t>* pv, intptr_t bits,
//------------------------------------------------------------------
// Data for doing deadlock detection.
-static absl::base_internal::SpinLock deadlock_graph_mu(
- absl::base_internal::kLinkerInitialized);
+ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
-// graph used to detect deadlocks.
-static GraphCycles *deadlock_graph GUARDED_BY(deadlock_graph_mu)
- PT_GUARDED_BY(deadlock_graph_mu);
+// Graph used to detect deadlocks.
+ABSL_CONST_INIT static GraphCycles *deadlock_graph
+ ABSL_GUARDED_BY(deadlock_graph_mu) ABSL_PT_GUARDED_BY(deadlock_graph_mu);
//------------------------------------------------------------------
// An event mechanism for debugging mutex use.
@@ -233,15 +255,14 @@ enum { // Mutex and CondVar events passed as "ev" to PostSynchEvent
SYNCH_EV_SIGNALALL,
};
-enum { // Event flags
- SYNCH_F_R = 0x01, // reader event
- SYNCH_F_LCK = 0x02, // PostSynchEvent called with mutex held
- SYNCH_F_ACQ = 0x04, // event is an acquire
+enum { // Event flags
+ SYNCH_F_R = 0x01, // reader event
+ SYNCH_F_LCK = 0x02, // PostSynchEvent called with mutex held
+ SYNCH_F_TRY = 0x04, // TryLock or ReaderTryLock
+ SYNCH_F_UNLOCK = 0x08, // Unlock or ReaderUnlock
SYNCH_F_LCK_W = SYNCH_F_LCK,
SYNCH_F_LCK_R = SYNCH_F_LCK | SYNCH_F_R,
- SYNCH_F_ACQ_W = SYNCH_F_ACQ,
- SYNCH_F_ACQ_R = SYNCH_F_ACQ | SYNCH_F_R,
};
} // anonymous namespace
@@ -250,35 +271,35 @@ static const struct {
int flags;
const char *msg;
} event_properties[] = {
- { SYNCH_F_LCK_W|SYNCH_F_ACQ_W, "TryLock succeeded " },
- { 0, "TryLock failed " },
- { SYNCH_F_LCK_R|SYNCH_F_ACQ_R, "ReaderTryLock succeeded " },
- { 0, "ReaderTryLock failed " },
- { SYNCH_F_ACQ_W, "Lock blocking " },
- { SYNCH_F_LCK_W, "Lock returning " },
- { SYNCH_F_ACQ_R, "ReaderLock blocking " },
- { SYNCH_F_LCK_R, "ReaderLock returning " },
- { SYNCH_F_LCK_W, "Unlock " },
- { SYNCH_F_LCK_R, "ReaderUnlock " },
- { 0, "Wait on " },
- { 0, "Wait unblocked " },
- { 0, "Signal on " },
- { 0, "SignalAll on " },
+ {SYNCH_F_LCK_W | SYNCH_F_TRY, "TryLock succeeded "},
+ {0, "TryLock failed "},
+ {SYNCH_F_LCK_R | SYNCH_F_TRY, "ReaderTryLock succeeded "},
+ {0, "ReaderTryLock failed "},
+ {0, "Lock blocking "},
+ {SYNCH_F_LCK_W, "Lock returning "},
+ {0, "ReaderLock blocking "},
+ {SYNCH_F_LCK_R, "ReaderLock returning "},
+ {SYNCH_F_LCK_W | SYNCH_F_UNLOCK, "Unlock "},
+ {SYNCH_F_LCK_R | SYNCH_F_UNLOCK, "ReaderUnlock "},
+ {0, "Wait on "},
+ {0, "Wait unblocked "},
+ {0, "Signal on "},
+ {0, "SignalAll on "},
};
-static absl::base_internal::SpinLock synch_event_mu(
- absl::base_internal::kLinkerInitialized);
-// protects synch_event
+
+ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu(
+ absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
// Hash table size; should be prime > 2.
// Can't be too small, as it's used for deadlock detection information.
-static const uint32_t kNSynchEvent = 1031;
+static constexpr uint32_t kNSynchEvent = 1031;
static struct SynchEvent { // this is a trivial hash table for the events
// struct is freed when refcount reaches 0
- int refcount GUARDED_BY(synch_event_mu);
+ int refcount ABSL_GUARDED_BY(synch_event_mu);
// buckets have linear, 0-terminated chains
- SynchEvent *next GUARDED_BY(synch_event_mu);
+ SynchEvent *next ABSL_GUARDED_BY(synch_event_mu);
// Constant after initialization
uintptr_t masked_addr; // object at this address is called "name"
@@ -291,8 +312,8 @@ static struct SynchEvent { // this is a trivial hash table for the events
bool log; // logging turned on
// Constant after initialization
- char name[1]; // actually longer---null-terminated std::string
-} *synch_event[kNSynchEvent] GUARDED_BY(synch_event_mu);
+ char name[1]; // actually longer---NUL-terminated string
+} * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
// Ensure that the object at "addr" has a SynchEvent struct associated with it,
// set "bits" in the word there (waiting until lockbit is clear before doing
@@ -414,9 +435,26 @@ static void PostSynchEvent(void *obj, int ev) {
ABSL_RAW_LOG(INFO, "%s%p %s %s", event_properties[ev].msg, obj,
(e == nullptr ? "" : e->name), buffer);
}
- if ((event_properties[ev].flags & SYNCH_F_LCK) != 0 && e != nullptr &&
- e->invariant != nullptr) {
- (*e->invariant)(e->arg);
+ const int flags = event_properties[ev].flags;
+ if ((flags & SYNCH_F_LCK) != 0 && e != nullptr && e->invariant != nullptr) {
+ // Calling the invariant as is causes problems under ThreadSanitizer.
+ // We are currently inside of Mutex Lock/Unlock and are ignoring all
+ // memory accesses and synchronization. If the invariant transitively
+ // synchronizes something else and we ignore the synchronization, we will
+ // get false positive race reports later.
+ // Reuse EvalConditionAnnotated to properly call into user code.
+ struct local {
+ static bool pred(SynchEvent *ev) {
+ (*ev->invariant)(ev->arg);
+ return false;
+ }
+ };
+ Condition cond(&local::pred, e);
+ Mutex *mu = static_cast<Mutex *>(obj);
+ const bool locking = (flags & SYNCH_F_UNLOCK) == 0;
+ const bool trylock = (flags & SYNCH_F_TRY) != 0;
+ const bool read_lock = (flags & SYNCH_F_R) != 0;
+ EvalConditionAnnotated(&cond, mu, locking, trylock, read_lock);
}
UnrefSynchEvent(e);
}
@@ -465,7 +503,7 @@ struct SynchWaitParams {
std::atomic<intptr_t> *cv_word;
int64_t contention_start_cycles; // Time (in cycles) when this thread started
- // to contend for the mutex.
+ // to contend for the mutex.
};
struct SynchLocksHeld {
@@ -521,7 +559,7 @@ static SynchLocksHeld *Synch_GetAllLocks() {
}
// Post on "w"'s associated PerThreadSem.
-inline void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
+void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
if (mu) {
ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
}
@@ -679,7 +717,7 @@ static constexpr bool kDebugMode = false;
static constexpr bool kDebugMode = true;
#endif
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
static unsigned TsanFlags(Mutex::MuHow how) {
return how == kShared ? __tsan_mutex_read_lock : 0;
}
@@ -725,11 +763,13 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) {
synch_deadlock_detection.store(mode, std::memory_order_release);
}
-// Return true iff threads x and y are waiting on the same condition for the
-// same type of lock. Requires that x and y be waiting on the same Mutex
-// queue.
-static bool MuSameCondition(PerThreadSynch *x, PerThreadSynch *y) {
- return x->waitp->how == y->waitp->how &&
+// Return true iff threads x and y are part of the same equivalence
+// class of waiters. An equivalence class is defined as the set of
+// waiters with the same condition, type of lock, and thread priority.
+//
+// Requires that x and y be waiting on the same Mutex queue.
+static bool MuEquivalentWaiter(PerThreadSynch *x, PerThreadSynch *y) {
+ return x->waitp->how == y->waitp->how && x->priority == y->priority &&
Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond);
}
@@ -748,18 +788,19 @@ static inline PerThreadSynch *GetPerThreadSynch(intptr_t v) {
// - invalid (iff x is not in a Mutex wait queue),
// - null, or
// - a pointer to a distinct thread waiting later in the same Mutex queue
-// such that all threads in [x, x->skip] have the same condition and
-// lock type (MuSameCondition() is true for all pairs in [x, x->skip]).
+// such that all threads in [x, x->skip] have the same condition, priority
+// and lock type (MuEquivalentWaiter() is true for all pairs in [x,
+// x->skip]).
// In addition, if x->skip is valid, (x->may_skip || x->skip == null)
//
-// By the spec of MuSameCondition(), it is not necessary when removing the
+// By the spec of MuEquivalentWaiter(), it is not necessary when removing the
// first runnable thread y from the front a Mutex queue to adjust the skip
// field of another thread x because if x->skip==y, x->skip must (have) become
// invalid before y is removed. The function TryRemove can remove a specified
// thread from an arbitrary position in the queue whether runnable or not, so
// it fixes up skip fields that would otherwise be left dangling.
// The statement
-// if (x->may_skip && MuSameCondition(x, x->next)) { x->skip = x->next; }
+// if (x->may_skip && MuEquivalentWaiter(x, x->next)) { x->skip = x->next; }
// maintains the invariant provided x is not the last waiter in a Mutex queue
// The statement
// if (x->skip != null) { x->skip = x->skip->skip; }
@@ -880,33 +921,30 @@ static PerThreadSynch *Enqueue(PerThreadSynch *head,
// base_internal::CycleClock::Now() is 0.5%.
int policy;
struct sched_param param;
- pthread_getschedparam(pthread_self(), &policy, &param);
- s->priority = param.sched_priority;
- s->next_priority_read_cycles =
- now_cycles +
- static_cast<int64_t>(base_internal::CycleClock::Frequency());
+ const int err = pthread_getschedparam(pthread_self(), &policy, &param);
+ if (err != 0) {
+ ABSL_RAW_LOG(ERROR, "pthread_getschedparam failed: %d", err);
+ } else {
+ s->priority = param.sched_priority;
+ s->next_priority_read_cycles =
+ now_cycles +
+ static_cast<int64_t>(base_internal::CycleClock::Frequency());
+ }
}
if (s->priority > head->priority) { // s's priority is above head's
// try to put s in priority-fifo order, or failing that at the front.
if (!head->maybe_unlocking) {
- // No unlocker can be scanning the queue, so we can insert between
- // skip-chains, and within a skip-chain if it has the same condition as
- // s. We insert in priority-fifo order, examining the end of every
- // skip-chain, plus every element with the same condition as s.
+ // No unlocker can be scanning the queue, so we can insert into the
+ // middle of the queue.
+ //
+ // Within a skip chain, all waiters have the same priority, so we can
+ // skip forward through the chains until we find one with a lower
+ // priority than the waiter to be enqueued.
PerThreadSynch *advance_to = head; // next value of enqueue_after
- PerThreadSynch *cur; // successor of enqueue_after
do {
enqueue_after = advance_to;
- cur = enqueue_after->next; // this advance ensures progress
- advance_to = Skip(cur); // normally, advance to end of skip chain
- // (side-effect: optimizes skip chain)
- if (advance_to != cur && s->priority > advance_to->priority &&
- MuSameCondition(s, cur)) {
- // but this skip chain is not a singleton, s has higher priority
- // than its tail and has the same condition as the chain,
- // so we can insert within the skip-chain
- advance_to = cur; // advance by just one
- }
+ // (side-effect: optimizes skip chain)
+ advance_to = Skip(enqueue_after->next);
} while (s->priority <= advance_to->priority);
// termination guaranteed because s->priority > head->priority
// and head is the end of a skip chain
@@ -925,21 +963,21 @@ static PerThreadSynch *Enqueue(PerThreadSynch *head,
// enqueue_after can be: head, Skip(...), or cur.
// The first two imply enqueue_after->skip == nullptr, and
- // the last is used only if MuSameCondition(s, cur).
+ // the last is used only if MuEquivalentWaiter(s, cur).
// We require this because clearing enqueue_after->skip
// is impossible; enqueue_after's predecessors might also
// incorrectly skip over s if we were to allow other
// insertion points.
- ABSL_RAW_CHECK(
- enqueue_after->skip == nullptr || MuSameCondition(enqueue_after, s),
- "Mutex Enqueue failure");
+ ABSL_RAW_CHECK(enqueue_after->skip == nullptr ||
+ MuEquivalentWaiter(enqueue_after, s),
+ "Mutex Enqueue failure");
if (enqueue_after != head && enqueue_after->may_skip &&
- MuSameCondition(enqueue_after, enqueue_after->next)) {
+ MuEquivalentWaiter(enqueue_after, enqueue_after->next)) {
// enqueue_after can skip to its new successor, s
enqueue_after->skip = enqueue_after->next;
}
- if (MuSameCondition(s, s->next)) { // s->may_skip is known to be true
+ if (MuEquivalentWaiter(s, s->next)) { // s->may_skip is known to be true
s->skip = s->next; // s may skip to its successor
}
} else { // enqueue not done any other way, so
@@ -949,7 +987,7 @@ static PerThreadSynch *Enqueue(PerThreadSynch *head,
head->next = s;
s->readers = head->readers; // reader count is from previous head
s->maybe_unlocking = head->maybe_unlocking; // same for unlock hint
- if (head->may_skip && MuSameCondition(head, s)) {
+ if (head->may_skip && MuEquivalentWaiter(head, s)) {
// head now has successor; may skip
head->skip = s;
}
@@ -969,7 +1007,7 @@ static PerThreadSynch *Dequeue(PerThreadSynch *head, PerThreadSynch *pw) {
pw->next = w->next; // snip w out of list
if (head == w) { // we removed the head
head = (pw == w) ? nullptr : pw; // either emptied list, or pw is new head
- } else if (pw != head && MuSameCondition(pw, pw->next)) {
+ } else if (pw != head && MuEquivalentWaiter(pw, pw->next)) {
// pw can skip to its new successor
if (pw->next->skip !=
nullptr) { // either skip to its successors skip target
@@ -1026,6 +1064,7 @@ static PerThreadSynch *DequeueAllWakeable(PerThreadSynch *head,
// Try to remove thread s from the list of waiters on this mutex.
// Does nothing if s is not on the waiter list.
void Mutex::TryRemove(PerThreadSynch *s) {
+ SchedulingGuard::ScopedDisable disable_rescheduling;
intptr_t v = mu_.load(std::memory_order_relaxed);
// acquire spinlock & lock
if ((v & (kMuWait | kMuSpin | kMuWriter | kMuReader)) == kMuWait &&
@@ -1038,11 +1077,13 @@ void Mutex::TryRemove(PerThreadSynch *s) {
PerThreadSynch *w;
if ((w = pw->next) != s) { // search for thread,
do { // processing at least one element
- if (!MuSameCondition(s, w)) { // seeking different condition
+ // If the current element isn't equivalent to the waiter to be
+ // removed, we can skip the entire chain.
+ if (!MuEquivalentWaiter(s, w)) {
pw = Skip(w); // so skip all that won't match
// we don't have to worry about dangling skip fields
// in the threads we skipped; none can point to s
- // because their condition differs from s
+ // because they are in a different equivalence class.
} else { // seeking same condition
FixSkip(w, s); // fix up any skip pointer from w to s
pw = w;
@@ -1090,7 +1131,7 @@ ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
this->TryRemove(s);
int c = 0;
while (s->next != nullptr) {
- c = Delay(c, GENTLE);
+ c = synchronization_internal::MutexDelay(c, GENTLE);
this->TryRemove(s);
}
if (kDebugMode) {
@@ -1118,7 +1159,7 @@ PerThreadSynch *Mutex::Wakeup(PerThreadSynch *w) {
}
static GraphId GetGraphIdLocked(Mutex *mu)
- EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(deadlock_graph_mu) {
if (!deadlock_graph) { // (re)create the deadlock graph.
deadlock_graph =
new (base_internal::LowLevelAlloc::Alloc(sizeof(*deadlock_graph)))
@@ -1127,7 +1168,7 @@ static GraphId GetGraphIdLocked(Mutex *mu)
return deadlock_graph->GetId(mu);
}
-static GraphId GetGraphId(Mutex *mu) LOCKS_EXCLUDED(deadlock_graph_mu) {
+static GraphId GetGraphId(Mutex *mu) ABSL_LOCKS_EXCLUDED(deadlock_graph_mu) {
deadlock_graph_mu.Lock();
GraphId id = GetGraphIdLocked(mu);
deadlock_graph_mu.Unlock();
@@ -1333,7 +1374,9 @@ static GraphId DeadlockCheck(Mutex *mu) {
len += static_cast<int>(strlen(&b->buf[len]));
}
}
- ABSL_RAW_LOG(ERROR, "Acquiring %p Mutexes held: %s",
+ ABSL_RAW_LOG(ERROR,
+ "Acquiring absl::Mutex %p while holding %s; a cycle in the "
+ "historical lock ordering graph has been observed",
static_cast<void *>(mu), b->buf);
ABSL_RAW_LOG(ERROR, "Cycle: ");
int path_len = deadlock_graph->FindPath(
@@ -1409,21 +1452,19 @@ void Mutex::AssertNotHeld() const {
// Attempt to acquire *mu, and return whether successful. The implementation
// may spin for a short while if the lock cannot be acquired immediately.
static bool TryAcquireWithSpinning(std::atomic<intptr_t>* mu) {
- int c = mutex_globals.spinloop_iterations;
- int result = -1; // result of operation: 0=false, 1=true, -1=unknown
-
+ int c = GetMutexGlobals().spinloop_iterations;
do { // do/while somewhat faster on AMD
intptr_t v = mu->load(std::memory_order_relaxed);
- if ((v & (kMuReader|kMuEvent)) != 0) { // a reader or tracing -> give up
- result = 0;
+ if ((v & (kMuReader|kMuEvent)) != 0) {
+ return false; // a reader or tracing -> give up
} else if (((v & kMuWriter) == 0) && // no holder -> try to acquire
mu->compare_exchange_strong(v, kMuWriter | v,
std::memory_order_acquire,
std::memory_order_relaxed)) {
- result = 1;
+ return true;
}
- } while (result == -1 && --c > 0);
- return result == 1;
+ } while (--c > 0);
+ return false;
}
ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
@@ -1552,7 +1593,7 @@ bool Mutex::AwaitCommon(const Condition &cond, KernelTimeout t) {
ABSL_TSAN_MUTEX_PRE_LOCK(this, TsanFlags(how));
this->LockSlowLoop(&waitp, flags);
bool res = waitp.cond != nullptr || // => cond known true from LockSlowLoop
- cond.Eval();
+ EvalConditionAnnotated(&cond, this, true, false, how == kShared);
ABSL_TSAN_MUTEX_POST_LOCK(this, TsanFlags(how), 0);
return res;
}
@@ -1722,7 +1763,8 @@ static const intptr_t ignore_waiting_writers[] = {
};
// Internal version of LockWhen(). See LockSlowWithDeadline()
-void Mutex::LockSlow(MuHow how, const Condition *cond, int flags) {
+ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition *cond,
+ int flags) {
ABSL_RAW_CHECK(
this->LockSlowWithDeadline(how, cond, KernelTimeout::Never(), flags),
"condition untrue on return from LockSlow");
@@ -1730,12 +1772,17 @@ void Mutex::LockSlow(MuHow how, const Condition *cond, int flags) {
// Compute cond->Eval() and tell race detectors that we do it under mutex mu.
static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
- bool locking, Mutex::MuHow how) {
+ bool locking, bool trylock,
+ bool read_lock) {
// Delicate annotation dance.
// We are currently inside of read/write lock/unlock operation.
// All memory accesses are ignored inside of mutex operations + for unlock
// operation tsan considers that we've already released the mutex.
bool res = false;
+#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
+ const int flags = read_lock ? __tsan_mutex_read_lock : 0;
+ const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
+#endif
if (locking) {
// For lock we pretend that we have finished the operation,
// evaluate the predicate, then unlock the mutex and start locking it again
@@ -1743,24 +1790,26 @@ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
// Note: we can't simply do POST_LOCK, Eval, PRE_LOCK, because then tsan
// will think the lock acquisition is recursive which will trigger
// deadlock detector.
- ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+ ABSL_TSAN_MUTEX_POST_LOCK(mu, tryflags, 0);
res = cond->Eval();
- ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
- ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
- ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
+ // There is no "try" version of Unlock, so use flags instead of tryflags.
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
+ ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+ ABSL_TSAN_MUTEX_PRE_LOCK(mu, tryflags);
} else {
// Similarly, for unlock we pretend that we have unlocked the mutex,
// lock the mutex, evaluate the predicate, and start unlocking it again
// to match the annotation at the end of outer unlock operation.
- ABSL_TSAN_MUTEX_POST_UNLOCK(mu, TsanFlags(how));
- ABSL_TSAN_MUTEX_PRE_LOCK(mu, TsanFlags(how));
- ABSL_TSAN_MUTEX_POST_LOCK(mu, TsanFlags(how), 0);
+ ABSL_TSAN_MUTEX_POST_UNLOCK(mu, flags);
+ ABSL_TSAN_MUTEX_PRE_LOCK(mu, flags);
+ ABSL_TSAN_MUTEX_POST_LOCK(mu, flags, 0);
res = cond->Eval();
- ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, TsanFlags(how));
+ ABSL_TSAN_MUTEX_PRE_UNLOCK(mu, flags);
}
// Prevent unused param warnings in non-TSAN builds.
static_cast<void>(mu);
- static_cast<void>(how);
+ static_cast<void>(trylock);
+ static_cast<void>(read_lock);
return res;
}
@@ -1780,9 +1829,9 @@ static inline bool EvalConditionIgnored(Mutex *mu, const Condition *cond) {
// So we "divert" (which un-ignores both memory accesses and synchronization)
// and then separately turn on ignores of memory accesses.
ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
- ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bool res = cond->Eval();
- ANNOTATE_IGNORE_READS_AND_WRITES_END();
+ ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
ABSL_TSAN_MUTEX_POST_DIVERT(mu, 0);
static_cast<void>(mu); // Prevent unused param warning in non-TSAN builds.
return res;
@@ -1806,7 +1855,8 @@ bool Mutex::LockSlowWithDeadline(MuHow how, const Condition *cond,
v, (how->fast_or | (v & zap_desig_waker[flags & kMuHasBlocked])) +
how->fast_add,
std::memory_order_acquire, std::memory_order_relaxed)) {
- if (cond == nullptr || EvalConditionAnnotated(cond, this, true, how)) {
+ if (cond == nullptr ||
+ EvalConditionAnnotated(cond, this, true, false, how == kShared)) {
return true;
}
unlock = true;
@@ -1824,7 +1874,8 @@ bool Mutex::LockSlowWithDeadline(MuHow how, const Condition *cond,
}
this->LockSlowLoop(&waitp, flags);
return waitp.cond != nullptr || // => cond known true from LockSlowLoop
- cond == nullptr || EvalConditionAnnotated(cond, this, true, how);
+ cond == nullptr ||
+ EvalConditionAnnotated(cond, this, true, false, how == kShared);
}
// RAW_CHECK_FMT() takes a condition, a printf-style format string, and
@@ -1841,7 +1892,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) {
// Test for either of two situations that should not occur in v:
// kMuWriter and kMuReader
// kMuWrWait and !kMuWait
- const intptr_t w = v ^ kMuWait;
+ const uintptr_t w = v ^ kMuWait;
// By flipping that bit, we can now test for:
// kMuWriter and kMuReader in w
// kMuWrWait and kMuWait in w
@@ -1861,6 +1912,7 @@ static void CheckForMutexCorruption(intptr_t v, const char* label) {
}
void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
+ SchedulingGuard::ScopedDisable disable_rescheduling;
int c = 0;
intptr_t v = mu_.load(std::memory_order_relaxed);
if ((v & kMuEvent) != 0) {
@@ -1880,7 +1932,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
waitp->how->fast_add,
std::memory_order_acquire, std::memory_order_relaxed)) {
if (waitp->cond == nullptr ||
- EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+ EvalConditionAnnotated(waitp->cond, this, true, false,
+ waitp->how == kShared)) {
break; // we timed out, or condition true, so return
}
this->UnlockSlow(waitp); // got lock but condition false
@@ -1923,7 +1976,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
std::memory_order_release,
std::memory_order_relaxed));
if (waitp->cond == nullptr ||
- EvalConditionAnnotated(waitp->cond, this, true, waitp->how)) {
+ EvalConditionAnnotated(waitp->cond, this, true, false,
+ waitp->how == kShared)) {
break; // we timed out, or condition true, so return
}
this->UnlockSlow(waitp); // got lock but condition false
@@ -1960,7 +2014,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
ABSL_RAW_CHECK(
waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
"detected illegal recursion into Mutex code");
- c = Delay(c, GENTLE); // delay, then try again
+ // delay, then try again
+ c = synchronization_internal::MutexDelay(c, GENTLE);
}
ABSL_RAW_CHECK(
waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
@@ -1977,7 +2032,8 @@ void Mutex::LockSlowLoop(SynchWaitParams *waitp, int flags) {
// which holds the lock but is not runnable because its condition is false
// or it is in the process of blocking on a condition variable; it must requeue
// itself on the mutex/condvar to wait for its condition to become true.
-void Mutex::UnlockSlow(SynchWaitParams *waitp) {
+ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
+ SchedulingGuard::ScopedDisable disable_rescheduling;
intptr_t v = mu_.load(std::memory_order_relaxed);
this->AssertReaderHeld();
CheckForMutexCorruption(v, "Unlock");
@@ -2094,7 +2150,7 @@ void Mutex::UnlockSlow(SynchWaitParams *waitp) {
!old_h->may_skip) { // we used old_h as a terminator
old_h->may_skip = true; // allow old_h to skip once more
ABSL_RAW_CHECK(old_h->skip == nullptr, "illegal skip from head");
- if (h != old_h && MuSameCondition(old_h, old_h->next)) {
+ if (h != old_h && MuEquivalentWaiter(old_h, old_h->next)) {
old_h->skip = old_h->next; // old_h not head & can skip to successor
}
}
@@ -2254,7 +2310,8 @@ void Mutex::UnlockSlow(SynchWaitParams *waitp) {
mu_.store(nv, std::memory_order_release);
break; // out of for(;;)-loop
}
- c = Delay(c, AGGRESSIVE); // aggressive here; no one can proceed till we do
+ // aggressive here; no one can proceed till we do
+ c = synchronization_internal::MutexDelay(c, AGGRESSIVE);
} // end of for(;;)-loop
if (wake_list != kPerThreadSynchNull) {
@@ -2266,7 +2323,8 @@ void Mutex::UnlockSlow(SynchWaitParams *waitp) {
if (!cond_waiter) {
// Sample lock contention events only if the (first) waiter was trying to
// acquire the lock, not waiting on a condition variable or Condition.
- int64_t wait_cycles = base_internal::CycleClock::Now() - enqueue_timestamp;
+ int64_t wait_cycles =
+ base_internal::CycleClock::Now() - enqueue_timestamp;
mutex_tracer("slow release", this, wait_cycles);
ABSL_TSAN_MUTEX_PRE_DIVERT(this, 0);
submit_profile_data(enqueue_timestamp);
@@ -2293,6 +2351,7 @@ void Mutex::Trans(MuHow how) {
// It will later acquire the mutex with high probability. Otherwise, we
// enqueue thread w on this mutex.
void Mutex::Fer(PerThreadSynch *w) {
+ SchedulingGuard::ScopedDisable disable_rescheduling;
int c = 0;
ABSL_RAW_CHECK(w->waitp->cond == nullptr,
"Mutex::Fer while waiting on Condition");
@@ -2342,7 +2401,7 @@ void Mutex::Fer(PerThreadSynch *w) {
return;
}
}
- c = Delay(c, GENTLE);
+ c = synchronization_internal::MutexDelay(c, GENTLE);
}
}
@@ -2391,6 +2450,7 @@ CondVar::~CondVar() {
// Remove thread s from the list of waiters on this condition variable.
void CondVar::Remove(PerThreadSynch *s) {
+ SchedulingGuard::ScopedDisable disable_rescheduling;
intptr_t v;
int c = 0;
for (v = cv_.load(std::memory_order_relaxed);;
@@ -2419,7 +2479,8 @@ void CondVar::Remove(PerThreadSynch *s) {
std::memory_order_release);
return;
} else {
- c = Delay(c, GENTLE); // try again after a delay
+ // try again after a delay
+ c = synchronization_internal::MutexDelay(c, GENTLE);
}
}
}
@@ -2452,7 +2513,7 @@ static void CondVarEnqueue(SynchWaitParams *waitp) {
!cv_word->compare_exchange_weak(v, v | kCvSpin,
std::memory_order_acquire,
std::memory_order_relaxed)) {
- c = Delay(c, GENTLE);
+ c = synchronization_internal::MutexDelay(c, GENTLE);
v = cv_word->load(std::memory_order_relaxed);
}
ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
@@ -2551,7 +2612,8 @@ void CondVar::Wakeup(PerThreadSynch *w) {
}
void CondVar::Signal() {
- ABSL_TSAN_MUTEX_PRE_SIGNAL(0, 0);
+ SchedulingGuard::ScopedDisable disable_rescheduling;
+ ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
intptr_t v;
int c = 0;
for (v = cv_.load(std::memory_order_relaxed); v != 0;
@@ -2580,17 +2642,17 @@ void CondVar::Signal() {
if ((v & kCvEvent) != 0) {
PostSynchEvent(this, SYNCH_EV_SIGNAL);
}
- ABSL_TSAN_MUTEX_POST_SIGNAL(0, 0);
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
return;
} else {
- c = Delay(c, GENTLE);
+ c = synchronization_internal::MutexDelay(c, GENTLE);
}
}
- ABSL_TSAN_MUTEX_POST_SIGNAL(0, 0);
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
}
void CondVar::SignalAll () {
- ABSL_TSAN_MUTEX_PRE_SIGNAL(0, 0);
+ ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
intptr_t v;
int c = 0;
for (v = cv_.load(std::memory_order_relaxed); v != 0;
@@ -2617,13 +2679,14 @@ void CondVar::SignalAll () {
if ((v & kCvEvent) != 0) {
PostSynchEvent(this, SYNCH_EV_SIGNALALL);
}
- ABSL_TSAN_MUTEX_POST_SIGNAL(0, 0);
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
return;
} else {
- c = Delay(c, GENTLE); // try again after a delay
+ // try again after a delay
+ c = synchronization_internal::MutexDelay(c, GENTLE);
}
}
- ABSL_TSAN_MUTEX_POST_SIGNAL(0, 0);
+ ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
}
void ReleasableMutexLock::Release() {
@@ -2633,7 +2696,7 @@ void ReleasableMutexLock::Release() {
this->mu_ = nullptr;
}
-#ifdef THREAD_SANITIZER
+#ifdef ABSL_HAVE_THREAD_SANITIZER
extern "C" void __tsan_read1(void *addr);
#else
#define __tsan_read1(addr) // do nothing if TSan not enabled
@@ -2684,4 +2747,5 @@ bool Condition::GuaranteedEqual(const Condition *a, const Condition *b) {
a->arg_ == b->arg_ && a->method_ == b->method_;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.h
index 4b65e92cb3d..f49e0c83d6d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -31,22 +31,23 @@
//
// MutexLock - An RAII wrapper to acquire and release a `Mutex` for exclusive/
// write access within the current scope.
+//
// ReaderMutexLock
// - An RAII wrapper to acquire and release a `Mutex` for shared/read
// access within the current scope.
//
// WriterMutexLock
-// - Alias for `MutexLock` above, designed for use in distinguishing
-// reader and writer locks within code.
+// - Effectively an alias for `MutexLock` above, designed for use in
+// distinguishing reader and writer locks within code.
//
// In addition to simple mutex locks, this file also defines ways to perform
// locking under certain conditions.
//
-// Condition - (Preferred) Used to wait for a particular predicate that
-// depends on state protected by the `Mutex` to become true.
-// CondVar - A lower-level variant of `Condition` that relies on
-// application code to explicitly signal the `CondVar` when
-// a condition has been met.
+// Condition - (Preferred) Used to wait for a particular predicate that
+// depends on state protected by the `Mutex` to become true.
+// CondVar - A lower-level variant of `Condition` that relies on
+// application code to explicitly signal the `CondVar` when
+// a condition has been met.
//
// See below for more information on using `Condition` or `CondVar`.
//
@@ -72,16 +73,8 @@
#include "absl/synchronization/internal/per_thread_sem.h"
#include "absl/time/time.h"
-// Decide if we should use the non-production implementation because
-// the production implementation hasn't been fully ported yet.
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-#error ABSL_INTERNAL_USE_NONPROD_MUTEX cannot be directly set
-#elif defined(ABSL_LOW_LEVEL_ALLOC_MISSING)
-#define ABSL_INTERNAL_USE_NONPROD_MUTEX 1
-#include "absl/synchronization/internal/mutex_nonprod.inc"
-#endif
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
class Condition;
struct SynchWaitParams;
@@ -135,7 +128,7 @@ struct SynchWaitParams;
//
// See also `MutexLock`, below, for scoped `Mutex` acquisition.
-class LOCKABLE Mutex {
+class ABSL_LOCKABLE Mutex {
public:
// Creates a `Mutex` that is not held by anyone. This constructor is
// typically used for Mutexes allocated on the heap or the stack.
@@ -154,36 +147,37 @@ class LOCKABLE Mutex {
//
// Example usage:
// namespace foo {
- // ABSL_CONST_INIT Mutex mu(absl::kConstInit);
+ // ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit);
// }
explicit constexpr Mutex(absl::ConstInitType);
+
~Mutex();
// Mutex::Lock()
//
// Blocks the calling thread, if necessary, until this `Mutex` is free, and
// then acquires it exclusively. (This lock is also known as a "write lock.")
- void Lock() EXCLUSIVE_LOCK_FUNCTION();
+ void Lock() ABSL_EXCLUSIVE_LOCK_FUNCTION();
// Mutex::Unlock()
//
// Releases this `Mutex` and returns it from the exclusive/write state to the
- // free state. Caller must hold the `Mutex` exclusively.
- void Unlock() UNLOCK_FUNCTION();
+ // free state. Calling thread must hold the `Mutex` exclusively.
+ void Unlock() ABSL_UNLOCK_FUNCTION();
// Mutex::TryLock()
//
// If the mutex can be acquired without blocking, does so exclusively and
// returns `true`. Otherwise, returns `false`. Returns `true` with high
// probability if the `Mutex` was free.
- bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
+ bool TryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true);
// Mutex::AssertHeld()
//
// Return immediately if this thread holds the `Mutex` exclusively (in write
// mode). Otherwise, may report an error (typically by crashing with a
// diagnostic), or may return immediately.
- void AssertHeld() const ASSERT_EXCLUSIVE_LOCK();
+ void AssertHeld() const ABSL_ASSERT_EXCLUSIVE_LOCK();
// ---------------------------------------------------------------------------
// Reader-Writer Locking
@@ -224,28 +218,28 @@ class LOCKABLE Mutex {
// `ReaderLock()` will block if some other thread has an exclusive/writer lock
// on the mutex.
- void ReaderLock() SHARED_LOCK_FUNCTION();
+ void ReaderLock() ABSL_SHARED_LOCK_FUNCTION();
// Mutex::ReaderUnlock()
//
// Releases a read share of this `Mutex`. `ReaderUnlock` may return a mutex to
// the free state if this thread holds the last reader lock on the mutex. Note
// that you cannot call `ReaderUnlock()` on a mutex held in write mode.
- void ReaderUnlock() UNLOCK_FUNCTION();
+ void ReaderUnlock() ABSL_UNLOCK_FUNCTION();
// Mutex::ReaderTryLock()
//
// If the mutex can be acquired without blocking, acquires this mutex for
// shared access and returns `true`. Otherwise, returns `false`. Returns
// `true` with high probability if the `Mutex` was free or shared.
- bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
+ bool ReaderTryLock() ABSL_SHARED_TRYLOCK_FUNCTION(true);
// Mutex::AssertReaderHeld()
//
// Returns immediately if this thread holds the `Mutex` in at least shared
// mode (read mode). Otherwise, may report an error (typically by
// crashing with a diagnostic), or may return immediately.
- void AssertReaderHeld() const ASSERT_SHARED_LOCK();
+ void AssertReaderHeld() const ABSL_ASSERT_SHARED_LOCK();
// Mutex::WriterLock()
// Mutex::WriterUnlock()
@@ -256,11 +250,11 @@ class LOCKABLE Mutex {
// These methods may be used (along with the complementary `Reader*()`
// methods) to distingish simple exclusive `Mutex` usage (`Lock()`,
// etc.) from reader/writer lock usage.
- void WriterLock() EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); }
+ void WriterLock() ABSL_EXCLUSIVE_LOCK_FUNCTION() { this->Lock(); }
- void WriterUnlock() UNLOCK_FUNCTION() { this->Unlock(); }
+ void WriterUnlock() ABSL_UNLOCK_FUNCTION() { this->Unlock(); }
- bool WriterTryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true) {
+ bool WriterTryLock() ABSL_EXCLUSIVE_TRYLOCK_FUNCTION(true) {
return this->TryLock();
}
@@ -314,11 +308,11 @@ class LOCKABLE Mutex {
// be acquired, then atomically acquires this `Mutex`. `LockWhen()` is
// logically equivalent to `*Lock(); Await();` though they may have different
// performance characteristics.
- void LockWhen(const Condition &cond) EXCLUSIVE_LOCK_FUNCTION();
+ void LockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION();
- void ReaderLockWhen(const Condition &cond) SHARED_LOCK_FUNCTION();
+ void ReaderLockWhen(const Condition &cond) ABSL_SHARED_LOCK_FUNCTION();
- void WriterLockWhen(const Condition &cond) EXCLUSIVE_LOCK_FUNCTION() {
+ void WriterLockWhen(const Condition &cond) ABSL_EXCLUSIVE_LOCK_FUNCTION() {
this->LockWhen(cond);
}
@@ -329,17 +323,16 @@ class LOCKABLE Mutex {
// Mutex::AwaitWithTimeout()
// Mutex::AwaitWithDeadline()
//
- // If `cond` is initially true, do nothing, or act as though `cond` is
- // initially false.
- //
- // If `cond` is initially false, unlock this `Mutex` and block until
- // simultaneously:
+ // Unlocks this `Mutex` and blocks until simultaneously:
// - either `cond` is true or the {timeout has expired, deadline has passed}
// and
// - this `Mutex` can be reacquired,
// then reacquire this `Mutex` in the same mode in which it was previously
// held, returning `true` iff `cond` is `true` on return.
//
+ // If the condition is initially `true`, the implementation *may* skip the
+ // release/re-acquire step and return immediately.
+ //
// Deadlines in the past are equivalent to an immediate deadline.
// Negative timeouts are equivalent to a zero timeout.
//
@@ -360,11 +353,11 @@ class LOCKABLE Mutex {
//
// Negative timeouts are equivalent to a zero timeout.
bool LockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
- EXCLUSIVE_LOCK_FUNCTION();
+ ABSL_EXCLUSIVE_LOCK_FUNCTION();
bool ReaderLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
- SHARED_LOCK_FUNCTION();
+ ABSL_SHARED_LOCK_FUNCTION();
bool WriterLockWhenWithTimeout(const Condition &cond, absl::Duration timeout)
- EXCLUSIVE_LOCK_FUNCTION() {
+ ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return this->LockWhenWithTimeout(cond, timeout);
}
@@ -380,11 +373,11 @@ class LOCKABLE Mutex {
//
// Deadlines in the past are equivalent to an immediate deadline.
bool LockWhenWithDeadline(const Condition &cond, absl::Time deadline)
- EXCLUSIVE_LOCK_FUNCTION();
+ ABSL_EXCLUSIVE_LOCK_FUNCTION();
bool ReaderLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
- SHARED_LOCK_FUNCTION();
+ ABSL_SHARED_LOCK_FUNCTION();
bool WriterLockWhenWithDeadline(const Condition &cond, absl::Time deadline)
- EXCLUSIVE_LOCK_FUNCTION() {
+ ABSL_EXCLUSIVE_LOCK_FUNCTION() {
return this->LockWhenWithDeadline(cond, deadline);
}
@@ -460,24 +453,13 @@ class LOCKABLE Mutex {
static void InternalAttemptToUseMutexInFatalSignalHandler();
private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
- friend class CondVar;
-
- synchronization_internal::MutexImpl *impl() { return impl_.get(); }
-
- synchronization_internal::SynchronizationStorage<
- synchronization_internal::MutexImpl>
- impl_;
-#else
std::atomic<intptr_t> mu_; // The Mutex state.
// Post()/Wait() versus associated PerThreadSem; in class for required
// friendship with PerThreadSem.
- static inline void IncrementSynchSem(Mutex *mu,
- base_internal::PerThreadSynch *w);
- static inline bool DecrementSynchSem(
- Mutex *mu, base_internal::PerThreadSynch *w,
- synchronization_internal::KernelTimeout t);
+ static void IncrementSynchSem(Mutex *mu, base_internal::PerThreadSynch *w);
+ static bool DecrementSynchSem(Mutex *mu, base_internal::PerThreadSynch *w,
+ synchronization_internal::KernelTimeout t);
// slow path acquire
void LockSlowLoop(SynchWaitParams *waitp, int flags);
@@ -503,7 +485,6 @@ class LOCKABLE Mutex {
void Trans(MuHow how); // used for CondVar->Mutex transfer
void Fer(
base_internal::PerThreadSynch *w); // used for CondVar->Mutex transfer
-#endif
// Catch the error of writing Mutex when intending MutexLock.
Mutex(const volatile Mutex * /*ignored*/) {} // NOLINT(runtime/explicit)
@@ -524,28 +505,42 @@ class LOCKABLE Mutex {
// Example:
//
// Class Foo {
-//
+// public:
// Foo::Bar* Baz() {
-// MutexLock l(&lock_);
+// MutexLock lock(&mu_);
// ...
// return bar;
// }
//
// private:
-// Mutex lock_;
+// Mutex mu_;
// };
-class SCOPED_LOCKABLE MutexLock {
+class ABSL_SCOPED_LOCKABLE MutexLock {
public:
- explicit MutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
+ // Constructors
+
+ // Calls `mu->Lock()` and returns when that call returns. That is, `*mu` is
+ // guaranteed to be locked when this object is constructed. Requires that
+ // `mu` be dereferenceable.
+ explicit MutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu) : mu_(mu) {
this->mu_->Lock();
}
+ // Like above, but calls `mu->LockWhen(cond)` instead. That is, in addition to
+ // the above, the condition given by `cond` is also guaranteed to hold when
+ // this object is constructed.
+ explicit MutexLock(Mutex *mu, const Condition &cond)
+ ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ this->mu_->LockWhen(cond);
+ }
+
MutexLock(const MutexLock &) = delete; // NOLINT(runtime/mutex)
MutexLock(MutexLock&&) = delete; // NOLINT(runtime/mutex)
MutexLock& operator=(const MutexLock&) = delete;
MutexLock& operator=(MutexLock&&) = delete;
- ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
+ ~MutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->Unlock(); }
private:
Mutex *const mu_;
@@ -555,21 +550,24 @@ class SCOPED_LOCKABLE MutexLock {
//
// The `ReaderMutexLock` is a helper class, like `MutexLock`, which acquires and
// releases a shared lock on a `Mutex` via RAII.
-class SCOPED_LOCKABLE ReaderMutexLock {
+class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
public:
- explicit ReaderMutexLock(Mutex *mu) SHARED_LOCK_FUNCTION(mu)
- : mu_(mu) {
+ explicit ReaderMutexLock(Mutex *mu) ABSL_SHARED_LOCK_FUNCTION(mu) : mu_(mu) {
mu->ReaderLock();
}
+ explicit ReaderMutexLock(Mutex *mu, const Condition &cond)
+ ABSL_SHARED_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ mu->ReaderLockWhen(cond);
+ }
+
ReaderMutexLock(const ReaderMutexLock&) = delete;
ReaderMutexLock(ReaderMutexLock&&) = delete;
ReaderMutexLock& operator=(const ReaderMutexLock&) = delete;
ReaderMutexLock& operator=(ReaderMutexLock&&) = delete;
- ~ReaderMutexLock() UNLOCK_FUNCTION() {
- this->mu_->ReaderUnlock();
- }
+ ~ReaderMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->ReaderUnlock(); }
private:
Mutex *const mu_;
@@ -579,21 +577,25 @@ class SCOPED_LOCKABLE ReaderMutexLock {
//
// The `WriterMutexLock` is a helper class, like `MutexLock`, which acquires and
// releases a write (exclusive) lock on a `Mutex` via RAII.
-class SCOPED_LOCKABLE WriterMutexLock {
+class ABSL_SCOPED_LOCKABLE WriterMutexLock {
public:
- explicit WriterMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
+ explicit WriterMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
mu->WriterLock();
}
+ explicit WriterMutexLock(Mutex *mu, const Condition &cond)
+ ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ mu->WriterLockWhen(cond);
+ }
+
WriterMutexLock(const WriterMutexLock&) = delete;
WriterMutexLock(WriterMutexLock&&) = delete;
WriterMutexLock& operator=(const WriterMutexLock&) = delete;
WriterMutexLock& operator=(WriterMutexLock&&) = delete;
- ~WriterMutexLock() UNLOCK_FUNCTION() {
- this->mu_->WriterUnlock();
- }
+ ~WriterMutexLock() ABSL_UNLOCK_FUNCTION() { this->mu_->WriterUnlock(); }
private:
Mutex *const mu_;
@@ -626,16 +628,26 @@ class SCOPED_LOCKABLE WriterMutexLock {
// `noexcept`; until then this requirement cannot be enforced in the
// type system.)
//
-// Note: to use a `Condition`, you need only construct it and pass it within the
-// appropriate `Mutex' member function, such as `Mutex::Await()`.
+// Note: to use a `Condition`, you need only construct it and pass it to a
+// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
+// constructor of one of the scope guard classes.
//
-// Example:
+// Example using LockWhen/Unlock:
//
// // assume count_ is not internal reference count
-// int count_ GUARDED_BY(mu_);
+// int count_ ABSL_GUARDED_BY(mu_);
+// Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
+//
+// mu_.LockWhen(count_is_zero);
+// // ...
+// mu_.Unlock();
//
-// mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
-// &count_));
+// Example using a scope guard:
+//
+// {
+// MutexLock lock(&mu_, count_is_zero);
+// // ...
+// }
//
// When multiple threads are waiting on exactly the same condition, make sure
// that they are constructed with the same parameters (same pointer to function
@@ -689,6 +701,11 @@ class Condition {
// return processed_ >= current;
// };
// mu_.Await(Condition(&reached));
+ //
+ // NOTE: never use "mu_.AssertHeld()" instead of "mu_.AssertReaderHeld()" in
+ // the lambda as it may be called when the mutex is being unlocked from a
+ // scope holding only a reader lock, which will make the assertion not
+ // fulfilled and crash the binary.
// See class comment for performance advice. In particular, if there
// might be more than one waiter for the same condition, make sure
@@ -773,6 +790,8 @@ class Condition {
//
class CondVar {
public:
+ // A `CondVar` allocated on the heap or on the stack can use the this
+ // constructor.
CondVar();
~CondVar();
@@ -835,17 +854,10 @@ class CondVar {
void EnableDebugLog(const char *name);
private:
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
- synchronization_internal::CondVarImpl *impl() { return impl_.get(); }
- synchronization_internal::SynchronizationStorage<
- synchronization_internal::CondVarImpl>
- impl_;
-#else
bool WaitCommon(Mutex *mutex, synchronization_internal::KernelTimeout t);
void Remove(base_internal::PerThreadSynch *s);
void Wakeup(base_internal::PerThreadSynch *w);
std::atomic<intptr_t> cv_; // Condition variable state.
-#endif
CondVar(const CondVar&) = delete;
CondVar& operator=(const CondVar&) = delete;
};
@@ -859,13 +871,27 @@ class CondVar {
// MutexLockMaybe
//
// MutexLockMaybe is like MutexLock, but is a no-op when mu is null.
-class SCOPED_LOCKABLE MutexLockMaybe {
+class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
public:
- explicit MutexLockMaybe(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
- : mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } }
- ~MutexLockMaybe() UNLOCK_FUNCTION() {
+ explicit MutexLockMaybe(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ if (this->mu_ != nullptr) {
+ this->mu_->Lock();
+ }
+ }
+
+ explicit MutexLockMaybe(Mutex *mu, const Condition &cond)
+ ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ if (this->mu_ != nullptr) {
+ this->mu_->LockWhen(cond);
+ }
+ }
+
+ ~MutexLockMaybe() ABSL_UNLOCK_FUNCTION() {
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
}
+
private:
Mutex *const mu_;
MutexLockMaybe(const MutexLockMaybe&) = delete;
@@ -878,17 +904,24 @@ class SCOPED_LOCKABLE MutexLockMaybe {
//
// ReleasableMutexLock is like MutexLock, but permits `Release()` of its
// mutex before destruction. `Release()` may be called at most once.
-class SCOPED_LOCKABLE ReleasableMutexLock {
+class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
public:
- explicit ReleasableMutexLock(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
+ explicit ReleasableMutexLock(Mutex *mu) ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
: mu_(mu) {
this->mu_->Lock();
}
- ~ReleasableMutexLock() UNLOCK_FUNCTION() {
+
+ explicit ReleasableMutexLock(Mutex *mu, const Condition &cond)
+ ABSL_EXCLUSIVE_LOCK_FUNCTION(mu)
+ : mu_(mu) {
+ this->mu_->LockWhen(cond);
+ }
+
+ ~ReleasableMutexLock() ABSL_UNLOCK_FUNCTION() {
if (this->mu_ != nullptr) { this->mu_->Unlock(); }
}
- void Release() UNLOCK_FUNCTION();
+ void Release() ABSL_UNLOCK_FUNCTION();
private:
Mutex *mu_;
@@ -898,16 +931,13 @@ class SCOPED_LOCKABLE ReleasableMutexLock {
ReleasableMutexLock& operator=(ReleasableMutexLock&&) = delete;
};
-#ifdef ABSL_INTERNAL_USE_NONPROD_MUTEX
-inline constexpr Mutex::Mutex(absl::ConstInitType) : impl_(absl::kConstInit) {}
-#else
inline Mutex::Mutex() : mu_(0) {
ABSL_TSAN_MUTEX_CREATE(this, __tsan_mutex_not_static);
}
+
inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
inline CondVar::CondVar() : cv_(0) {}
-#endif
// static
template <typename T>
@@ -975,7 +1005,7 @@ void RegisterMutexProfiler(void (*fn)(int64_t wait_timestamp));
//
// This has the same memory ordering concerns as RegisterMutexProfiler() above.
void RegisterMutexTracer(void (*fn)(const char *msg, const void *obj,
- int64_t wait_cycles));
+ int64_t wait_cycles));
// TODO(gfalcon): Combine RegisterMutexProfiler() and RegisterMutexTracer()
// into a single interface, since they are only ever called in pairs.
@@ -997,7 +1027,7 @@ void RegisterCondVarTracer(void (*fn)(const char *msg, const void *cv));
//
// 'pc' is the program counter being symbolized, 'out' is the buffer to write
// into, and 'out_size' is the size of the buffer. This function can return
-// false if symbolizing failed, or true if a null-terminated symbol was written
+// false if symbolizing failed, or true if a NUL-terminated symbol was written
// to 'out.'
//
// This has the same memory ordering concerns as RegisterMutexProfiler() above.
@@ -1036,6 +1066,7 @@ enum class OnDeadlockCycle {
// the manner chosen here.
void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);
+ABSL_NAMESPACE_END
} // namespace absl
// In some build configurations we pass --detect-odr-violations to the
@@ -1045,6 +1076,7 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode);
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void AbslInternalMutexYield();
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
} // extern "C"
+
#endif // ABSL_SYNCHRONIZATION_MUTEX_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_benchmark.cc
index 2652bb974e9..e35aed8bd64 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,6 +16,7 @@
#include <mutex> // NOLINT(build/c++11)
#include <vector>
+#include "absl/base/config.h"
#include "absl/base/internal/cycleclock.h"
#include "absl/base/internal/spinlock.h"
#include "absl/synchronization/blocking_counter.h"
@@ -60,8 +61,124 @@ class RaiiLocker<std::mutex> {
std::mutex* mu_;
};
+// RAII object to change the Mutex priority of the running thread.
+class ScopedThreadMutexPriority {
+ public:
+ explicit ScopedThreadMutexPriority(int priority) {
+ absl::base_internal::ThreadIdentity* identity =
+ absl::synchronization_internal::GetOrCreateCurrentThreadIdentity();
+ identity->per_thread_synch.priority = priority;
+ // Bump next_priority_read_cycles to the infinite future so that the
+ // implementation doesn't re-read the thread's actual scheduler priority
+ // and replace our temporary scoped priority.
+ identity->per_thread_synch.next_priority_read_cycles =
+ std::numeric_limits<int64_t>::max();
+ }
+ ~ScopedThreadMutexPriority() {
+ // Reset the "next priority read time" back to the infinite past so that
+ // the next time the Mutex implementation wants to know this thread's
+ // priority, it re-reads it from the OS instead of using our overridden
+ // priority.
+ absl::synchronization_internal::GetOrCreateCurrentThreadIdentity()
+ ->per_thread_synch.next_priority_read_cycles =
+ std::numeric_limits<int64_t>::min();
+ }
+};
+
+void BM_MutexEnqueue(benchmark::State& state) {
+ // In the "multiple priorities" variant of the benchmark, one of the
+ // threads runs with Mutex priority 0 while the rest run at elevated priority.
+ // This benchmarks the performance impact of the presence of a low priority
+ // waiter when a higher priority waiter adds itself of the queue
+ // (b/175224064).
+ //
+ // NOTE: The actual scheduler priority is not modified in this benchmark:
+ // all of the threads get CPU slices with the same priority. Only the
+ // Mutex queueing behavior is modified.
+ const bool multiple_priorities = state.range(0);
+ ScopedThreadMutexPriority priority_setter(
+ (multiple_priorities && state.thread_index != 0) ? 1 : 0);
+
+ struct Shared {
+ absl::Mutex mu;
+ std::atomic<int> looping_threads{0};
+ std::atomic<int> blocked_threads{0};
+ std::atomic<bool> thread_has_mutex{false};
+ };
+ static Shared* shared = new Shared;
+
+ // Set up 'blocked_threads' to count how many threads are currently blocked
+ // in Abseil synchronization code.
+ //
+ // NOTE: Blocking done within the Google Benchmark library itself (e.g.
+ // the barrier which synchronizes threads entering and exiting the benchmark
+ // loop) does _not_ get registered in this counter. This is because Google
+ // Benchmark uses its own synchronization primitives based on std::mutex, not
+ // Abseil synchronization primitives. If at some point the benchmark library
+ // merges into Abseil, this code may break.
+ absl::synchronization_internal::PerThreadSem::SetThreadBlockedCounter(
+ &shared->blocked_threads);
+
+ // The benchmark framework may run several iterations in the same process,
+ // reusing the same static-initialized 'shared' object. Given the semantics
+ // of the members, here, we expect everything to be reset to zero by the
+ // end of any iteration. Assert that's the case, just to be sure.
+ ABSL_RAW_CHECK(
+ shared->looping_threads.load(std::memory_order_relaxed) == 0 &&
+ shared->blocked_threads.load(std::memory_order_relaxed) == 0 &&
+ !shared->thread_has_mutex.load(std::memory_order_relaxed),
+ "Shared state isn't zeroed at start of benchmark iteration");
+
+ static constexpr int kBatchSize = 1000;
+ while (state.KeepRunningBatch(kBatchSize)) {
+ shared->looping_threads.fetch_add(1);
+ for (int i = 0; i < kBatchSize; i++) {
+ {
+ absl::MutexLock l(&shared->mu);
+ shared->thread_has_mutex.store(true, std::memory_order_relaxed);
+ // Spin until all other threads are either out of the benchmark loop
+ // or blocked on the mutex. This ensures that the mutex queue is kept
+ // at its maximal length to benchmark the performance of queueing on
+ // a highly contended mutex.
+ while (shared->looping_threads.load(std::memory_order_relaxed) -
+ shared->blocked_threads.load(std::memory_order_relaxed) !=
+ 1) {
+ }
+ shared->thread_has_mutex.store(false);
+ }
+ // Spin until some other thread has acquired the mutex before we block
+ // again. This ensures that we always go through the slow (queueing)
+ // acquisition path rather than reacquiring the mutex we just released.
+ while (!shared->thread_has_mutex.load(std::memory_order_relaxed) &&
+ shared->looping_threads.load(std::memory_order_relaxed) > 1) {
+ }
+ }
+ // The benchmark framework uses a barrier to ensure that all of the threads
+ // complete their benchmark loop together before any of the threads exit
+ // the loop. So, we need to remove ourselves from the "looping threads"
+ // counter here before potentially blocking on that barrier. Otherwise,
+ // another thread spinning above might wait forever for this thread to
+ // block on the mutex while we in fact are waiting to exit.
+ shared->looping_threads.fetch_add(-1);
+ }
+ absl::synchronization_internal::PerThreadSem::SetThreadBlockedCounter(
+ nullptr);
+}
+
+BENCHMARK(BM_MutexEnqueue)
+ ->Threads(4)
+ ->Threads(64)
+ ->Threads(128)
+ ->Threads(512)
+ ->ArgName("multiple_priorities")
+ ->Arg(false)
+ ->Arg(true);
+
template <typename MutexType>
void BM_Contended(benchmark::State& state) {
+ int priority = state.thread_index % state.range(1);
+ ScopedThreadMutexPriority priority_setter(priority);
+
struct Shared {
MutexType mu;
int data = 0;
@@ -84,81 +201,51 @@ void BM_Contended(benchmark::State& state) {
DelayNs(state.range(0), &shared->data);
}
}
+void SetupBenchmarkArgs(benchmark::internal::Benchmark* bm,
+ bool do_test_priorities) {
+ const int max_num_priorities = do_test_priorities ? 2 : 1;
+ bm->UseRealTime()
+ // ThreadPerCpu poorly handles non-power-of-two CPU counts.
+ ->Threads(1)
+ ->Threads(2)
+ ->Threads(4)
+ ->Threads(6)
+ ->Threads(8)
+ ->Threads(12)
+ ->Threads(16)
+ ->Threads(24)
+ ->Threads(32)
+ ->Threads(48)
+ ->Threads(64)
+ ->Threads(96)
+ ->Threads(128)
+ ->Threads(192)
+ ->Threads(256)
+ ->ArgNames({"cs_ns", "num_prios"});
+ // Some empirically chosen amounts of work in critical section.
+ // 1 is low contention, 2000 is high contention and few values in between.
+ for (int critical_section_ns : {1, 20, 50, 200, 2000}) {
+ for (int num_priorities = 1; num_priorities <= max_num_priorities;
+ num_priorities++) {
+ bm->ArgPair(critical_section_ns, num_priorities);
+ }
+ }
+}
BENCHMARK_TEMPLATE(BM_Contended, absl::Mutex)
- ->UseRealTime()
- // ThreadPerCpu poorly handles non-power-of-two CPU counts.
- ->Threads(1)
- ->Threads(2)
- ->Threads(4)
- ->Threads(6)
- ->Threads(8)
- ->Threads(12)
- ->Threads(16)
- ->Threads(24)
- ->Threads(32)
- ->Threads(48)
- ->Threads(64)
- ->Threads(96)
- ->Threads(128)
- ->Threads(192)
- ->Threads(256)
- // Some empirically chosen amounts of work in critical section.
- // 1 is low contention, 200 is high contention and few values in between.
- ->Arg(1)
- ->Arg(20)
- ->Arg(50)
- ->Arg(200);
+ ->Apply([](benchmark::internal::Benchmark* bm) {
+ SetupBenchmarkArgs(bm, /*do_test_priorities=*/true);
+ });
BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)
- ->UseRealTime()
- // ThreadPerCpu poorly handles non-power-of-two CPU counts.
- ->Threads(1)
- ->Threads(2)
- ->Threads(4)
- ->Threads(6)
- ->Threads(8)
- ->Threads(12)
- ->Threads(16)
- ->Threads(24)
- ->Threads(32)
- ->Threads(48)
- ->Threads(64)
- ->Threads(96)
- ->Threads(128)
- ->Threads(192)
- ->Threads(256)
- // Some empirically chosen amounts of work in critical section.
- // 1 is low contention, 200 is high contention and few values in between.
- ->Arg(1)
- ->Arg(20)
- ->Arg(50)
- ->Arg(200);
+ ->Apply([](benchmark::internal::Benchmark* bm) {
+ SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);
+ });
BENCHMARK_TEMPLATE(BM_Contended, std::mutex)
- ->UseRealTime()
- // ThreadPerCpu poorly handles non-power-of-two CPU counts.
- ->Threads(1)
- ->Threads(2)
- ->Threads(4)
- ->Threads(6)
- ->Threads(8)
- ->Threads(12)
- ->Threads(16)
- ->Threads(24)
- ->Threads(32)
- ->Threads(48)
- ->Threads(64)
- ->Threads(96)
- ->Threads(128)
- ->Threads(192)
- ->Threads(256)
- // Some empirically chosen amounts of work in critical section.
- // 1 is low contention, 200 is high contention and few values in between.
- ->Arg(1)
- ->Arg(20)
- ->Arg(50)
- ->Arg(200);
+ ->Apply([](benchmark::internal::Benchmark* bm) {
+ SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);
+ });
// Measure the overhead of conditions on mutex release (when they must be
// evaluated). Mutex has (some) support for equivalence classes allowing
@@ -213,7 +300,7 @@ void BM_ConditionWaiters(benchmark::State& state) {
}
// Some configurations have higher thread limits than others.
-#if defined(__linux__) && !defined(THREAD_SANITIZER)
+#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER)
constexpr int kMaxConditionWaiters = 8192;
#else
constexpr int kMaxConditionWaiters = 1024;
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_test.cc
index b2820e2068d..f8fbf9488ca 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/mutex_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,7 @@
#include "absl/synchronization/mutex.h"
-#ifdef WIN32
+#ifdef _WIN32
#include <windows.h>
#endif
@@ -30,6 +30,7 @@
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
+#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/memory/memory.h"
@@ -425,10 +426,10 @@ TEST(Mutex, CondVarWaitSignalsAwait) {
// Use a struct so the lock annotations apply.
struct {
absl::Mutex barrier_mu;
- bool barrier GUARDED_BY(barrier_mu) = false;
+ bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
absl::Mutex release_mu;
- bool release GUARDED_BY(release_mu) = false;
+ bool release ABSL_GUARDED_BY(release_mu) = false;
absl::CondVar released_cv;
} state;
@@ -466,10 +467,10 @@ TEST(Mutex, CondVarWaitWithTimeoutSignalsAwait) {
// Use a struct so the lock annotations apply.
struct {
absl::Mutex barrier_mu;
- bool barrier GUARDED_BY(barrier_mu) = false;
+ bool barrier ABSL_GUARDED_BY(barrier_mu) = false;
absl::Mutex release_mu;
- bool release GUARDED_BY(release_mu) = false;
+ bool release ABSL_GUARDED_BY(release_mu) = false;
absl::CondVar released_cv;
} state;
@@ -610,9 +611,9 @@ TEST_P(CondVarWaitDeadlock, Test) {
waiter2.reset(); // "join" waiter2
}
-INSTANTIATE_TEST_CASE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
- ::testing::Range(0, 8),
- ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(CondVarWaitDeadlockTest, CondVarWaitDeadlock,
+ ::testing::Range(0, 8),
+ ::testing::PrintToStringParamName());
// --------------------------------------------------------
// Test for fix of bug in DequeueAllWakeable()
@@ -706,6 +707,40 @@ TEST(Mutex, LockWhen) {
t.join();
}
+TEST(Mutex, LockWhenGuard) {
+ absl::Mutex mu;
+ int n = 30;
+ bool done = false;
+
+ // We don't inline the lambda because the conversion is ambiguous in MSVC.
+ bool (*cond_eq_10)(int *) = [](int *p) { return *p == 10; };
+ bool (*cond_lt_10)(int *) = [](int *p) { return *p < 10; };
+
+ std::thread t1([&mu, &n, &done, cond_eq_10]() {
+ absl::ReaderMutexLock lock(&mu, absl::Condition(cond_eq_10, &n));
+ done = true;
+ });
+
+ std::thread t2[10];
+ for (std::thread &t : t2) {
+ t = std::thread([&mu, &n, cond_lt_10]() {
+ absl::WriterMutexLock lock(&mu, absl::Condition(cond_lt_10, &n));
+ ++n;
+ });
+ }
+
+ {
+ absl::MutexLock lock(&mu);
+ n = 0;
+ }
+
+ for (std::thread &t : t2) t.join();
+ t1.join();
+
+ EXPECT_TRUE(done);
+ EXPECT_EQ(n, 10);
+}
+
// --------------------------------------------------------
// The following test requires Mutex::ReaderLock to be a real shared
// lock, which is not the case in all builds.
@@ -770,7 +805,7 @@ static void GetReadLock(ReaderDecrementBugStruct *x) {
// Test for reader counter being decremented incorrectly by waiter
// with false condition.
-TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
ReaderDecrementBugStruct x;
x.cond = false;
x.waiting_on_cond = false;
@@ -815,7 +850,12 @@ TEST(Mutex, MutexReaderDecrementBug) NO_THREAD_SAFETY_ANALYSIS {
// Test that we correctly handle the situation when a lock is
// held and then destroyed (w/o unlocking).
-TEST(Mutex, LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+// TSAN reports errors when locked Mutexes are destroyed.
+TEST(Mutex, DISABLED_LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+#else
+TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+#endif
for (int i = 0; i != 10; i++) {
// Create, lock and destroy 10 locks.
const int kNumLocks = 10;
@@ -996,9 +1036,6 @@ TEST(Mutex, AcquireFromCondition) {
x.mu0.Unlock();
}
-// The deadlock detector is not part of non-prod builds, so do not test it.
-#if !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
-
TEST(Mutex, DeadlockDetector) {
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
@@ -1030,11 +1067,11 @@ TEST(Mutex, DeadlockDetector) {
class ScopedDisableBazelTestWarnings {
public:
ScopedDisableBazelTestWarnings() {
-#ifdef WIN32
+#ifdef _WIN32
char file[MAX_PATH];
- if (GetEnvironmentVariable(kVarName, file, sizeof(file)) < sizeof(file)) {
+ if (GetEnvironmentVariableA(kVarName, file, sizeof(file)) < sizeof(file)) {
warnings_output_file_ = file;
- SetEnvironmentVariable(kVarName, nullptr);
+ SetEnvironmentVariableA(kVarName, nullptr);
}
#else
const char *file = getenv(kVarName);
@@ -1047,8 +1084,8 @@ class ScopedDisableBazelTestWarnings {
~ScopedDisableBazelTestWarnings() {
if (!warnings_output_file_.empty()) {
-#ifdef WIN32
- SetEnvironmentVariable(kVarName, warnings_output_file_.c_str());
+#ifdef _WIN32
+ SetEnvironmentVariableA(kVarName, warnings_output_file_.c_str());
#else
setenv(kVarName, warnings_output_file_.c_str(), 0);
#endif
@@ -1062,7 +1099,12 @@ class ScopedDisableBazelTestWarnings {
const char ScopedDisableBazelTestWarnings::kVarName[] =
"TEST_WARNINGS_OUTPUT_FILE";
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+// This test intentionally creates deadlocks to test the deadlock detector.
+TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
+#else
TEST(Mutex, DeadlockDetectorBazelWarning) {
+#endif
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kReport);
// Cause deadlock detection to detect something, if it's
@@ -1091,7 +1133,7 @@ TEST(Mutex, DeadlockDetectorBazelWarning) {
// annotation-based static thread-safety analysis is not currently
// predicate-aware and cannot tell if the two for-loops that acquire and
// release the locks have the same predicates.
-TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
// Stress test: Here we create a large number of locks and use all of them.
// If a deadlock detector keeps a full graph of lock acquisition order,
// it will likely be too slow for this test to pass.
@@ -1109,7 +1151,12 @@ TEST(Mutex, DeadlockDetectorStessTest) NO_THREAD_SAFETY_ANALYSIS {
}
}
-TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
+#ifdef ABSL_HAVE_THREAD_SANITIZER
+// TSAN reports errors when locked Mutexes are destroyed.
+TEST(Mutex, DISABLED_DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+#else
+TEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+#endif
// Test a scenario where a cached deadlock graph node id in the
// list of held locks is not invalidated when the corresponding
// mutex is deleted.
@@ -1142,7 +1189,6 @@ TEST(Mutex, DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
c.Lock();
c.Unlock();
}
-#endif // !defined(ABSL_INTERNAL_USE_NONPROD_MUTEX)
// --------------------------------------------------------
// Test for timeouts/deadlines on condition waits that are specified using
@@ -1367,8 +1413,8 @@ std::vector<TimeoutTestParam> MakeTimeoutTestParamValues() {
}
// Instantiate `TimeoutTest` with `MakeTimeoutTestParamValues()`.
-INSTANTIATE_TEST_CASE_P(All, TimeoutTest,
- testing::ValuesIn(MakeTimeoutTestParamValues()));
+INSTANTIATE_TEST_SUITE_P(All, TimeoutTest,
+ testing::ValuesIn(MakeTimeoutTestParamValues()));
TEST_P(TimeoutTest, Await) {
const TimeoutTestParam params = GetParam();
@@ -1548,9 +1594,9 @@ static std::vector<int> AllThreadCountValues() {
class MutexVariableThreadCountTest : public ::testing::TestWithParam<int> {};
// Instantiate the above with AllThreadCountOptions().
-INSTANTIATE_TEST_CASE_P(ThreadCounts, MutexVariableThreadCountTest,
- ::testing::ValuesIn(AllThreadCountValues()),
- ::testing::PrintToStringParamName());
+INSTANTIATE_TEST_SUITE_P(ThreadCounts, MutexVariableThreadCountTest,
+ ::testing::ValuesIn(AllThreadCountValues()),
+ ::testing::PrintToStringParamName());
// Reduces iterations by some factor for slow platforms
// (determined empirically).
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.cc
index cdcbc134fa6..e91b9038227 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -22,6 +22,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
void Notification::Notify() {
MutexLock l(&this->mutex_);
@@ -44,15 +45,6 @@ Notification::~Notification() {
MutexLock l(&this->mutex_);
}
-static inline bool HasBeenNotifiedInternal(
- const std::atomic<bool> *notified_yet) {
- return notified_yet->load(std::memory_order_acquire);
-}
-
-bool Notification::HasBeenNotified() const {
- return HasBeenNotifiedInternal(&this->notified_yet_);
-}
-
void Notification::WaitForNotification() const {
if (!HasBeenNotifiedInternal(&this->notified_yet_)) {
this->mutex_.LockWhen(Condition(&HasBeenNotifiedInternal,
@@ -82,4 +74,5 @@ bool Notification::WaitForNotificationWithDeadline(absl::Time deadline) const {
return notified;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.h
index f95f4d142a0..9a354ca2c02 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -57,6 +57,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// Notification
@@ -73,7 +74,9 @@ class Notification {
// Notification::HasBeenNotified()
//
// Returns the value of the notification's internal "notified" state.
- bool HasBeenNotified() const;
+ bool HasBeenNotified() const {
+ return HasBeenNotifiedInternal(&this->notified_yet_);
+ }
// Notification::WaitForNotification()
//
@@ -105,9 +108,16 @@ class Notification {
void Notify();
private:
+ static inline bool HasBeenNotifiedInternal(
+ const std::atomic<bool>* notified_yet) {
+ return notified_yet->load(std::memory_order_acquire);
+ }
+
mutable Mutex mutex_;
std::atomic<bool> notified_yet_; // written under mutex_
};
+ABSL_NAMESPACE_END
} // namespace absl
+
#endif // ABSL_SYNCHRONIZATION_NOTIFICATION_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification_test.cc
index d8708d551a1..100ea76f33a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/synchronization/notification_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,6 +21,7 @@
#include "absl/synchronization/mutex.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// A thread-safe class that holds a counter.
class ThreadSafeCounter {
@@ -72,12 +73,16 @@ static void BasicTests(bool notify_before_waiting, Notification* notification) {
EXPECT_FALSE(notification->WaitForNotificationWithDeadline(absl::Now()));
const absl::Duration delay = absl::Milliseconds(50);
+ const absl::Time start = absl::Now();
+ EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
+ const absl::Duration elapsed = absl::Now() - start;
+
// Allow for a slight early return, to account for quality of implementation
// issues on various platforms.
const absl::Duration slop = absl::Microseconds(200);
- absl::Time start = absl::Now();
- EXPECT_FALSE(notification->WaitForNotificationWithTimeout(delay));
- EXPECT_LE(start + delay, absl::Now() + slop);
+ EXPECT_LE(delay - slop, elapsed)
+ << "WaitForNotificationWithTimeout returned " << delay - elapsed
+ << " early (with " << slop << " slop), start time was " << start;
ThreadSafeCounter ready_counter;
ThreadSafeCounter done_counter;
@@ -124,4 +129,5 @@ TEST(NotificationTest, SanityTest) {
BasicTests(true, &local_notification2);
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/BUILD.bazel
index 2082f52c17a..3e25ca269cf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/BUILD.bazel
@@ -5,7 +5,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -14,15 +14,17 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "time",
@@ -41,9 +43,11 @@ cc_library(
"time.h",
],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base",
"//absl/base:core_headers",
+ "//absl/base:raw_logging_internal",
"//absl/numeric:int128",
"//absl/strings",
"//absl/time/internal/cctz:civil_time",
@@ -60,12 +64,14 @@ cc_library(
],
hdrs = ["internal/test_util.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl/time:__pkg__",
],
deps = [
":time",
- "//absl/base",
+ "//absl/base:config",
+ "//absl/base:raw_logging_internal",
"//absl/time/internal/cctz:time_zone",
"@com_google_googletest//:gtest",
],
@@ -82,12 +88,13 @@ cc_test(
"time_zone_test.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":test_util",
":time",
- "//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
+ "//absl/numeric:int128",
"//absl/time/internal/cctz:time_zone",
"@com_google_googletest//:gtest_main",
],
@@ -103,6 +110,7 @@ cc_test(
"time_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = [
"benchmark",
],
@@ -110,6 +118,8 @@ cc_test(
":test_util",
":time",
"//absl/base",
+ "//absl/base:core_headers",
+ "//absl/flags:flag",
"//absl/hash",
"@com_github_google_benchmark//:benchmark_main",
],
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.cc
index 56541799fca..bdfe9ce0efb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,6 +21,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -37,29 +38,114 @@ std::string FormatYearAnd(string_view fmt, CivilSecond cs) {
const CivilSecond ncs(NormalizeYear(cs.year()), cs.month(), cs.day(),
cs.hour(), cs.minute(), cs.second());
const TimeZone utc = UTCTimeZone();
- // TODO(absl-team): Avoid conversion of fmt std::string.
- return StrCat(cs.year(), FormatTime(std::string(fmt), FromCivil(ncs, utc), utc));
+ // TODO(absl-team): Avoid conversion of fmt string.
+ return StrCat(cs.year(),
+ FormatTime(std::string(fmt), FromCivil(ncs, utc), utc));
}
+template <typename CivilT>
+bool ParseYearAnd(string_view fmt, string_view s, CivilT* c) {
+ // Civil times support a larger year range than absl::Time, so we need to
+ // parse the year separately, normalize it, then use absl::ParseTime on the
+ // normalized string.
+ const std::string ss = std::string(s); // TODO(absl-team): Avoid conversion.
+ const char* const np = ss.c_str();
+ char* endp;
+ errno = 0;
+ const civil_year_t y =
+ std::strtoll(np, &endp, 10); // NOLINT(runtime/deprecated_fn)
+ if (endp == np || errno == ERANGE) return false;
+ const std::string norm = StrCat(NormalizeYear(y), endp);
+
+ const TimeZone utc = UTCTimeZone();
+ Time t;
+ if (ParseTime(StrCat("%Y", fmt), norm, utc, &t, nullptr)) {
+ const auto cs = ToCivilSecond(t, utc);
+ *c = CivilT(y, cs.month(), cs.day(), cs.hour(), cs.minute(), cs.second());
+ return true;
+ }
+
+ return false;
+}
+
+// Tries to parse the type as a CivilT1, but then assigns the result to the
+// argument of type CivilT2.
+template <typename CivilT1, typename CivilT2>
+bool ParseAs(string_view s, CivilT2* c) {
+ CivilT1 t1;
+ if (ParseCivilTime(s, &t1)) {
+ *c = CivilT2(t1);
+ return true;
+ }
+ return false;
+}
+
+template <typename CivilT>
+bool ParseLenient(string_view s, CivilT* c) {
+ // A fastpath for when the given string data parses exactly into the given
+ // type T (e.g., s="YYYY-MM-DD" and CivilT=CivilDay).
+ if (ParseCivilTime(s, c)) return true;
+ // Try parsing as each of the 6 types, trying the most common types first
+ // (based on csearch results).
+ if (ParseAs<CivilDay>(s, c)) return true;
+ if (ParseAs<CivilSecond>(s, c)) return true;
+ if (ParseAs<CivilHour>(s, c)) return true;
+ if (ParseAs<CivilMonth>(s, c)) return true;
+ if (ParseAs<CivilMinute>(s, c)) return true;
+ if (ParseAs<CivilYear>(s, c)) return true;
+ return false;
+}
} // namespace
std::string FormatCivilTime(CivilSecond c) {
- return FormatYearAnd("-%m-%dT%H:%M:%S", c);
+ return FormatYearAnd("-%m-%d%ET%H:%M:%S", c);
}
std::string FormatCivilTime(CivilMinute c) {
- return FormatYearAnd("-%m-%dT%H:%M", c);
+ return FormatYearAnd("-%m-%d%ET%H:%M", c);
}
std::string FormatCivilTime(CivilHour c) {
- return FormatYearAnd("-%m-%dT%H", c);
+ return FormatYearAnd("-%m-%d%ET%H", c);
+}
+std::string FormatCivilTime(CivilDay c) { return FormatYearAnd("-%m-%d", c); }
+std::string FormatCivilTime(CivilMonth c) { return FormatYearAnd("-%m", c); }
+std::string FormatCivilTime(CivilYear c) { return FormatYearAnd("", c); }
+
+bool ParseCivilTime(string_view s, CivilSecond* c) {
+ return ParseYearAnd("-%m-%d%ET%H:%M:%S", s, c);
+}
+bool ParseCivilTime(string_view s, CivilMinute* c) {
+ return ParseYearAnd("-%m-%d%ET%H:%M", s, c);
+}
+bool ParseCivilTime(string_view s, CivilHour* c) {
+ return ParseYearAnd("-%m-%d%ET%H", s, c);
+}
+bool ParseCivilTime(string_view s, CivilDay* c) {
+ return ParseYearAnd("-%m-%d", s, c);
+}
+bool ParseCivilTime(string_view s, CivilMonth* c) {
+ return ParseYearAnd("-%m", s, c);
+}
+bool ParseCivilTime(string_view s, CivilYear* c) {
+ return ParseYearAnd("", s, c);
+}
+
+bool ParseLenientCivilTime(string_view s, CivilSecond* c) {
+ return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilMinute* c) {
+ return ParseLenient(s, c);
+}
+bool ParseLenientCivilTime(string_view s, CivilHour* c) {
+ return ParseLenient(s, c);
}
-std::string FormatCivilTime(CivilDay c) {
- return FormatYearAnd("-%m-%d", c);
+bool ParseLenientCivilTime(string_view s, CivilDay* c) {
+ return ParseLenient(s, c);
}
-std::string FormatCivilTime(CivilMonth c) {
- return FormatYearAnd("-%m", c);
+bool ParseLenientCivilTime(string_view s, CivilMonth* c) {
+ return ParseLenient(s, c);
}
-std::string FormatCivilTime(CivilYear c) {
- return FormatYearAnd("", c);
+bool ParseLenientCivilTime(string_view s, CivilYear* c) {
+ return ParseLenient(s, c);
}
namespace time_internal {
@@ -85,4 +171,5 @@ std::ostream& operator<<(std::ostream& os, CivilSecond s) {
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.h
index 30d73c8769e..bb460044344 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -66,7 +66,6 @@
//
// // Valid in C++14
// constexpr absl::CivilDay cd(1969, 07, 20);
-//
#ifndef ABSL_TIME_CIVIL_TIME_H_
#define ABSL_TIME_CIVIL_TIME_H_
@@ -77,6 +76,7 @@
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
struct second_tag : cctz::detail::second_tag {};
@@ -248,7 +248,7 @@ struct year_tag : month_tag, cctz::detail::year_tag {};
// int minute()
// int second()
//
-// Recall that fields inferior to the type's aligment will be set to their
+// Recall that fields inferior to the type's alignment will be set to their
// minimum valid value.
//
// Example:
@@ -371,15 +371,15 @@ using Weekday = time_internal::cctz::weekday;
// GetWeekday()
//
-// Returns the absl::Weekday for the given absl::CivilDay.
+// Returns the absl::Weekday for the given (realigned) civil-time value.
//
// Example:
//
// absl::CivilDay a(2015, 8, 13);
// absl::Weekday wd = absl::GetWeekday(a); // wd == absl::Weekday::thursday
//
-inline Weekday GetWeekday(CivilDay cd) {
- return time_internal::cctz::get_weekday(cd);
+inline Weekday GetWeekday(CivilSecond cs) {
+ return time_internal::cctz::get_weekday(cs);
}
// NextWeekday()
@@ -408,9 +408,9 @@ inline Weekday GetWeekday(CivilDay cd) {
//
// absl::CivilDay d = ...
// // Gets the following Thursday if d is not already Thursday
-// absl::CivilDay thurs1 = absl::PrevWeekday(d, absl::Weekday::thursday) + 7;
+// absl::CivilDay thurs1 = absl::NextWeekday(d - 1, absl::Weekday::thursday);
// // Gets the previous Thursday if d is not already Thursday
-// absl::CivilDay thurs2 = absl::NextWeekday(d, absl::Weekday::thursday) - 7;
+// absl::CivilDay thurs2 = absl::PrevWeekday(d + 1, absl::Weekday::thursday);
//
inline CivilDay NextWeekday(CivilDay cd, Weekday wd) {
return CivilDay(time_internal::cctz::next_weekday(cd, wd));
@@ -421,7 +421,7 @@ inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {
// GetYearDay()
//
-// Returns the day-of-year for the given absl::CivilDay.
+// Returns the day-of-year for the given (realigned) civil-time value.
//
// Example:
//
@@ -430,8 +430,8 @@ inline CivilDay PrevWeekday(CivilDay cd, Weekday wd) {
// absl::CivilDay b(2015, 12, 31);
// int yd_dec_31 = absl::GetYearDay(b); // yd_dec_31 = 365
//
-inline int GetYearDay(CivilDay cd) {
- return time_internal::cctz::get_yearday(cd);
+inline int GetYearDay(CivilSecond cs) {
+ return time_internal::cctz::get_yearday(cs);
}
// FormatCivilTime()
@@ -451,7 +451,7 @@ inline int GetYearDay(CivilDay cd) {
// Example:
//
// absl::CivilDay d = absl::CivilDay(1969, 7, 20);
-// string day_string = absl::FormatCivilTime(d); // "1969-07-20"
+// std::string day_string = absl::FormatCivilTime(d); // "1969-07-20"
//
std::string FormatCivilTime(CivilSecond c);
std::string FormatCivilTime(CivilMinute c);
@@ -460,6 +460,57 @@ std::string FormatCivilTime(CivilDay c);
std::string FormatCivilTime(CivilMonth c);
std::string FormatCivilTime(CivilYear c);
+// absl::ParseCivilTime()
+//
+// Parses a civil-time value from the specified `absl::string_view` into the
+// passed output parameter. Returns `true` upon successful parsing.
+//
+// The expected form of the input string is as follows:
+//
+// Type | Format
+// ---------------------------------
+// CivilSecond | YYYY-MM-DDTHH:MM:SS
+// CivilMinute | YYYY-MM-DDTHH:MM
+// CivilHour | YYYY-MM-DDTHH
+// CivilDay | YYYY-MM-DD
+// CivilMonth | YYYY-MM
+// CivilYear | YYYY
+//
+// Example:
+//
+// absl::CivilDay d;
+// bool ok = absl::ParseCivilTime("2018-01-02", &d); // OK
+//
+// Note that parsing will fail if the string's format does not match the
+// expected type exactly. `ParseLenientCivilTime()` below is more lenient.
+//
+bool ParseCivilTime(absl::string_view s, CivilSecond* c);
+bool ParseCivilTime(absl::string_view s, CivilMinute* c);
+bool ParseCivilTime(absl::string_view s, CivilHour* c);
+bool ParseCivilTime(absl::string_view s, CivilDay* c);
+bool ParseCivilTime(absl::string_view s, CivilMonth* c);
+bool ParseCivilTime(absl::string_view s, CivilYear* c);
+
+// ParseLenientCivilTime()
+//
+// Parses any of the formats accepted by `absl::ParseCivilTime()`, but is more
+// lenient if the format of the string does not exactly match the associated
+// type.
+//
+// Example:
+//
+// absl::CivilDay d;
+// bool ok = absl::ParseLenientCivilTime("1969-07-20", &d); // OK
+// ok = absl::ParseLenientCivilTime("1969-07-20T10", &d); // OK: T10 floored
+// ok = absl::ParseLenientCivilTime("1969-07", &d); // OK: day defaults to 1
+//
+bool ParseLenientCivilTime(absl::string_view s, CivilSecond* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilMinute* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilHour* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilDay* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilMonth* c);
+bool ParseLenientCivilTime(absl::string_view s, CivilYear* c);
+
namespace time_internal { // For functions found via ADL on civil-time tags.
// Streaming Operators
@@ -469,7 +520,7 @@ namespace time_internal { // For functions found via ADL on civil-time tags.
//
// Example:
//
-// absl::CivilDay d = absl::CivilDay("1969-07-20");
+// absl::CivilDay d = absl::CivilDay(1969, 7, 20);
// std::cout << "Date is: " << d << "\n";
//
std::ostream& operator<<(std::ostream& os, CivilYear y);
@@ -481,6 +532,7 @@ std::ostream& operator<<(std::ostream& os, CivilSecond s);
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_CIVIL_TIME_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_benchmark.cc
index f30f636dccc..f04dbe200ed 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -66,6 +66,26 @@ void BM_Format(benchmark::State& state) {
}
BENCHMARK(BM_Format);
+void BM_Parse(benchmark::State& state) {
+ const std::string f = "2014-01-02T03:04:05";
+ absl::CivilSecond c;
+ while (state.KeepRunning()) {
+ const bool b = absl::ParseCivilTime(f, &c);
+ benchmark::DoNotOptimize(b);
+ }
+}
+BENCHMARK(BM_Parse);
+
+void BM_RoundTripFormatParse(benchmark::State& state) {
+ const absl::CivilSecond c(2014, 1, 2, 3, 4, 5);
+ absl::CivilSecond out;
+ while (state.KeepRunning()) {
+ const bool b = absl::ParseCivilTime(absl::FormatCivilTime(c), &out);
+ benchmark::DoNotOptimize(b);
+ }
+}
+BENCHMARK(BM_RoundTripFormatParse);
+
template <typename T>
void BM_CivilTimeAbslHash(benchmark::State& state) {
const int kSize = 100000;
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_test.cc
index dc83d7a9668..0ebd97adbc5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/civil_time_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -616,6 +616,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, ss.hour());
EXPECT_EQ(5, ss.minute());
EXPECT_EQ(6, ss.second());
+ EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ss));
+ EXPECT_EQ(34, absl::GetYearDay(ss));
absl::CivilMinute mm(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, mm.year());
@@ -624,6 +626,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, mm.hour());
EXPECT_EQ(5, mm.minute());
EXPECT_EQ(0, mm.second());
+ EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(mm));
+ EXPECT_EQ(34, absl::GetYearDay(mm));
absl::CivilHour hh(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, hh.year());
@@ -632,6 +636,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, hh.hour());
EXPECT_EQ(0, hh.minute());
EXPECT_EQ(0, hh.second());
+ EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(hh));
+ EXPECT_EQ(34, absl::GetYearDay(hh));
absl::CivilDay d(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, d.year());
@@ -640,6 +646,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, d.hour());
EXPECT_EQ(0, d.minute());
EXPECT_EQ(0, d.second());
+ EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(d));
+ EXPECT_EQ(34, absl::GetYearDay(d));
absl::CivilMonth m(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, m.year());
@@ -648,6 +656,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, m.hour());
EXPECT_EQ(0, m.minute());
EXPECT_EQ(0, m.second());
+ EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(m));
+ EXPECT_EQ(32, absl::GetYearDay(m));
absl::CivilYear y(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, y.year());
@@ -656,6 +666,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, y.hour());
EXPECT_EQ(0, y.minute());
EXPECT_EQ(0, y.second());
+ EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(y));
+ EXPECT_EQ(1, absl::GetYearDay(y));
}
TEST(CivilTime, Format) {
@@ -678,6 +690,69 @@ TEST(CivilTime, Format) {
EXPECT_EQ("1970", absl::FormatCivilTime(y));
}
+TEST(CivilTime, Parse) {
+ absl::CivilSecond ss;
+ absl::CivilMinute mm;
+ absl::CivilHour hh;
+ absl::CivilDay d;
+ absl::CivilMonth m;
+ absl::CivilYear y;
+
+ // CivilSecond OK; others fail
+ EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04:05", &ss));
+ EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &mm));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &hh));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &d));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &m));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04:05", &y));
+
+ // CivilMinute OK; others fail
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &ss));
+ EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03:04", &mm));
+ EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &hh));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &d));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &m));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03:04", &y));
+
+ // CivilHour OK; others fail
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &ss));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &mm));
+ EXPECT_TRUE(absl::ParseCivilTime("2015-01-02T03", &hh));
+ EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &d));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &m));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02T03", &y));
+
+ // CivilDay OK; others fail
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &ss));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &mm));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &hh));
+ EXPECT_TRUE(absl::ParseCivilTime("2015-01-02", &d));
+ EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &m));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01-02", &y));
+
+ // CivilMonth OK; others fail
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01", &ss));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01", &mm));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01", &hh));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01", &d));
+ EXPECT_TRUE(absl::ParseCivilTime("2015-01", &m));
+ EXPECT_EQ("2015-01", absl::FormatCivilTime(m));
+ EXPECT_FALSE(absl::ParseCivilTime("2015-01", &y));
+
+ // CivilYear OK; others fail
+ EXPECT_FALSE(absl::ParseCivilTime("2015", &ss));
+ EXPECT_FALSE(absl::ParseCivilTime("2015", &mm));
+ EXPECT_FALSE(absl::ParseCivilTime("2015", &hh));
+ EXPECT_FALSE(absl::ParseCivilTime("2015", &d));
+ EXPECT_FALSE(absl::ParseCivilTime("2015", &m));
+ EXPECT_TRUE(absl::ParseCivilTime("2015", &y));
+ EXPECT_EQ("2015", absl::FormatCivilTime(y));
+}
+
TEST(CivilTime, FormatAndParseLenient) {
absl::CivilSecond ss;
EXPECT_EQ("1970-01-01T00:00:00", absl::FormatCivilTime(ss));
@@ -696,6 +771,101 @@ TEST(CivilTime, FormatAndParseLenient) {
absl::CivilYear y;
EXPECT_EQ("1970", absl::FormatCivilTime(y));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &ss));
+ EXPECT_EQ("2015-01-02T03:04:05", absl::FormatCivilTime(ss));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &mm));
+ EXPECT_EQ("2015-01-02T03:04", absl::FormatCivilTime(mm));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &hh));
+ EXPECT_EQ("2015-01-02T03", absl::FormatCivilTime(hh));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &d));
+ EXPECT_EQ("2015-01-02", absl::FormatCivilTime(d));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &m));
+ EXPECT_EQ("2015-01", absl::FormatCivilTime(m));
+
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-01-02T03:04:05", &y));
+ EXPECT_EQ("2015", absl::FormatCivilTime(y));
+}
+
+TEST(CivilTime, ParseEdgeCases) {
+ absl::CivilSecond ss;
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59:59", &ss));
+ EXPECT_EQ("9223372036854775807-12-31T23:59:59", absl::FormatCivilTime(ss));
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00:00", &ss));
+ EXPECT_EQ("-9223372036854775808-01-01T00:00:00", absl::FormatCivilTime(ss));
+
+ absl::CivilMinute mm;
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("9223372036854775807-12-31T23:59", &mm));
+ EXPECT_EQ("9223372036854775807-12-31T23:59", absl::FormatCivilTime(mm));
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("-9223372036854775808-01-01T00:00", &mm));
+ EXPECT_EQ("-9223372036854775808-01-01T00:00", absl::FormatCivilTime(mm));
+
+ absl::CivilHour hh;
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("9223372036854775807-12-31T23", &hh));
+ EXPECT_EQ("9223372036854775807-12-31T23", absl::FormatCivilTime(hh));
+ EXPECT_TRUE(
+ absl::ParseLenientCivilTime("-9223372036854775808-01-01T00", &hh));
+ EXPECT_EQ("-9223372036854775808-01-01T00", absl::FormatCivilTime(hh));
+
+ absl::CivilDay d;
+ EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12-31", &d));
+ EXPECT_EQ("9223372036854775807-12-31", absl::FormatCivilTime(d));
+ EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01-01", &d));
+ EXPECT_EQ("-9223372036854775808-01-01", absl::FormatCivilTime(d));
+
+ absl::CivilMonth m;
+ EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807-12", &m));
+ EXPECT_EQ("9223372036854775807-12", absl::FormatCivilTime(m));
+ EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808-01", &m));
+ EXPECT_EQ("-9223372036854775808-01", absl::FormatCivilTime(m));
+
+ absl::CivilYear y;
+ EXPECT_TRUE(absl::ParseLenientCivilTime("9223372036854775807", &y));
+ EXPECT_EQ("9223372036854775807", absl::FormatCivilTime(y));
+ EXPECT_TRUE(absl::ParseLenientCivilTime("-9223372036854775808", &y));
+ EXPECT_EQ("-9223372036854775808", absl::FormatCivilTime(y));
+
+ // Tests some valid, but interesting, cases
+ EXPECT_TRUE(absl::ParseLenientCivilTime("0", &ss)) << ss;
+ EXPECT_EQ(absl::CivilYear(0), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime("0-1", &ss)) << ss;
+ EXPECT_EQ(absl::CivilMonth(0, 1), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015 ", &ss)) << ss;
+ EXPECT_EQ(absl::CivilYear(2015), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6 ", &ss)) << ss;
+ EXPECT_EQ(absl::CivilMonth(2015, 6), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-6-7", &ss)) << ss;
+ EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-6-7 ", &ss)) << ss;
+ EXPECT_EQ(absl::CivilDay(2015, 6, 7), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime("2015-06-07T10:11:12 ", &ss)) << ss;
+ EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime(" 2015-06-07T10:11:12 ", &ss)) << ss;
+ EXPECT_EQ(absl::CivilSecond(2015, 6, 7, 10, 11, 12), ss);
+ EXPECT_TRUE(absl::ParseLenientCivilTime("-01-01", &ss)) << ss;
+ EXPECT_EQ(absl::CivilMonth(-1, 1), ss);
+
+ // Tests some invalid cases
+ EXPECT_FALSE(absl::ParseLenientCivilTime("01-01-2015", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015-", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("0xff-01", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-30T04:05:06", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:96", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("X2015-02-03T04:05:06", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03T04:05:003", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015 -02-03T04:05:06", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015-02-03-04:05:06", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("2015:02:03T04-05-06", &ss)) << ss;
+ EXPECT_FALSE(absl::ParseLenientCivilTime("9223372036854775808", &y)) << y;
}
TEST(CivilTime, OutputStream) {
@@ -1028,7 +1198,7 @@ TEST(CivilTime, LeapYears) {
TEST(CivilTime, FirstThursdayInMonth) {
const absl::CivilDay nov1(2014, 11, 1);
const absl::CivilDay thursday =
- absl::PrevWeekday(nov1, absl::Weekday::thursday) + 7;
+ absl::NextWeekday(nov1 - 1, absl::Weekday::thursday);
EXPECT_EQ("2014-11-06", absl::FormatCivilTime(thursday));
// Bonus: Date of Thanksgiving in the United States
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.cc
index 74ee1401b98..7b204c4ee09 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,7 @@
#include "absl/time/clock.h"
#include "absl/base/attributes.h"
+#include "absl/base/optimization.h"
#ifdef _WIN32
#include <windows.h>
@@ -34,6 +35,7 @@
#include "absl/base/thread_annotations.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
Time Now() {
// TODO(bww): Get a timespec instead so we don't have to divide.
int64_t n = absl::GetCurrentTimeNanos();
@@ -43,6 +45,7 @@ Time Now() {
}
return time_internal::FromUnixDuration(absl::Nanoseconds(n));
}
+ABSL_NAMESPACE_END
} // namespace absl
// Decide if we should use the fast GetCurrentTimeNanos() algorithm
@@ -71,9 +74,9 @@ Time Now() {
#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
namespace absl {
-int64_t GetCurrentTimeNanos() {
- return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
-}
+ABSL_NAMESPACE_BEGIN
+int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }
+ABSL_NAMESPACE_END
} // namespace absl
#else // Use the cyclecounter-based implementation below.
@@ -83,14 +86,8 @@ int64_t GetCurrentTimeNanos() {
::absl::time_internal::UnscaledCycleClockWrapperForGetCurrentTime::Now()
#endif
-// The following counters are used only by the test code.
-static int64_t stats_initializations;
-static int64_t stats_reinitializations;
-static int64_t stats_calibrations;
-static int64_t stats_slow_paths;
-static int64_t stats_fast_slow_paths;
-
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
// This is a friend wrapper around UnscaledCycleClock::Now()
// (needed to access UnscaledCycleClock).
@@ -102,72 +99,6 @@ class UnscaledCycleClockWrapperForGetCurrentTime {
// uint64_t is used in this module to provide an extra bit in multiplications
-// Return the time in ns as told by the kernel interface. Place in *cycleclock
-// the value of the cycleclock at about the time of the syscall.
-// This call represents the time base that this module synchronizes to.
-// Ensures that *cycleclock does not step back by up to (1 << 16) from
-// last_cycleclock, to discard small backward counter steps. (Larger steps are
-// assumed to be complete resyncs, which shouldn't happen. If they do, a full
-// reinitialization of the outer algorithm should occur.)
-static int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock,
- uint64_t *cycleclock) {
- // We try to read clock values at about the same time as the kernel clock.
- // This value gets adjusted up or down as estimate of how long that should
- // take, so we can reject attempts that take unusually long.
- static std::atomic<uint64_t> approx_syscall_time_in_cycles{10 * 1000};
-
- uint64_t local_approx_syscall_time_in_cycles = // local copy
- approx_syscall_time_in_cycles.load(std::memory_order_relaxed);
-
- int64_t current_time_nanos_from_system;
- uint64_t before_cycles;
- uint64_t after_cycles;
- uint64_t elapsed_cycles;
- int loops = 0;
- do {
- before_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
- current_time_nanos_from_system = GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
- after_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
- // elapsed_cycles is unsigned, so is large on overflow
- elapsed_cycles = after_cycles - before_cycles;
- if (elapsed_cycles >= local_approx_syscall_time_in_cycles &&
- ++loops == 20) { // clock changed frequencies? Back off.
- loops = 0;
- if (local_approx_syscall_time_in_cycles < 1000 * 1000) {
- local_approx_syscall_time_in_cycles =
- (local_approx_syscall_time_in_cycles + 1) << 1;
- }
- approx_syscall_time_in_cycles.store(
- local_approx_syscall_time_in_cycles,
- std::memory_order_relaxed);
- }
- } while (elapsed_cycles >= local_approx_syscall_time_in_cycles ||
- last_cycleclock - after_cycles < (static_cast<uint64_t>(1) << 16));
-
- // Number of times in a row we've seen a kernel time call take substantially
- // less than approx_syscall_time_in_cycles.
- static std::atomic<uint32_t> seen_smaller{ 0 };
-
- // Adjust approx_syscall_time_in_cycles to be within a factor of 2
- // of the typical time to execute one iteration of the loop above.
- if ((local_approx_syscall_time_in_cycles >> 1) < elapsed_cycles) {
- // measured time is no smaller than half current approximation
- seen_smaller.store(0, std::memory_order_relaxed);
- } else if (seen_smaller.fetch_add(1, std::memory_order_relaxed) >= 3) {
- // smaller delays several times in a row; reduce approximation by 12.5%
- const uint64_t new_approximation =
- local_approx_syscall_time_in_cycles -
- (local_approx_syscall_time_in_cycles >> 3);
- approx_syscall_time_in_cycles.store(new_approximation,
- std::memory_order_relaxed);
- seen_smaller.store(0, std::memory_order_relaxed);
- }
-
- *cycleclock = after_cycles;
- return current_time_nanos_from_system;
-}
-
-
// ---------------------------------------------------------------------
// An implementation of reader-write locks that use no atomic ops in the read
// case. This is a generalization of Lamport's method for reading a multiword
@@ -219,32 +150,110 @@ static_assert(((kMinNSBetweenSamples << (kScale + 1)) >> (kScale + 1)) ==
kMinNSBetweenSamples,
"cannot represent kMaxBetweenSamplesNSScaled");
-// A reader-writer lock protecting the static locations below.
-// See SeqAcquire() and SeqRelease() above.
-static absl::base_internal::SpinLock lock(
- absl::base_internal::kLinkerInitialized);
-static std::atomic<uint64_t> seq(0);
-
// data from a sample of the kernel's time value
struct TimeSampleAtomic {
- std::atomic<uint64_t> raw_ns; // raw kernel time
- std::atomic<uint64_t> base_ns; // our estimate of time
- std::atomic<uint64_t> base_cycles; // cycle counter reading
- std::atomic<uint64_t> nsscaled_per_cycle; // cycle period
+ std::atomic<uint64_t> raw_ns{0}; // raw kernel time
+ std::atomic<uint64_t> base_ns{0}; // our estimate of time
+ std::atomic<uint64_t> base_cycles{0}; // cycle counter reading
+ std::atomic<uint64_t> nsscaled_per_cycle{0}; // cycle period
// cycles before we'll sample again (a scaled reciprocal of the period,
// to avoid a division on the fast path).
- std::atomic<uint64_t> min_cycles_per_sample;
+ std::atomic<uint64_t> min_cycles_per_sample{0};
};
// Same again, but with non-atomic types
struct TimeSample {
- uint64_t raw_ns; // raw kernel time
- uint64_t base_ns; // our estimate of time
- uint64_t base_cycles; // cycle counter reading
- uint64_t nsscaled_per_cycle; // cycle period
- uint64_t min_cycles_per_sample; // approx cycles before next sample
+ uint64_t raw_ns = 0; // raw kernel time
+ uint64_t base_ns = 0; // our estimate of time
+ uint64_t base_cycles = 0; // cycle counter reading
+ uint64_t nsscaled_per_cycle = 0; // cycle period
+ uint64_t min_cycles_per_sample = 0; // approx cycles before next sample
};
-static struct TimeSampleAtomic last_sample; // the last sample; under seq
+struct ABSL_CACHELINE_ALIGNED TimeState {
+ std::atomic<uint64_t> seq{0};
+ TimeSampleAtomic last_sample; // the last sample; under seq
+
+ // The following counters are used only by the test code.
+ int64_t stats_initializations{0};
+ int64_t stats_reinitializations{0};
+ int64_t stats_calibrations{0};
+ int64_t stats_slow_paths{0};
+ int64_t stats_fast_slow_paths{0};
+
+ uint64_t last_now_cycles ABSL_GUARDED_BY(lock){0};
+
+ // Used by GetCurrentTimeNanosFromKernel().
+ // We try to read clock values at about the same time as the kernel clock.
+ // This value gets adjusted up or down as estimate of how long that should
+ // take, so we can reject attempts that take unusually long.
+ std::atomic<uint64_t> approx_syscall_time_in_cycles{10 * 1000};
+ // Number of times in a row we've seen a kernel time call take substantially
+ // less than approx_syscall_time_in_cycles.
+ std::atomic<uint32_t> kernel_time_seen_smaller{0};
+
+ // A reader-writer lock protecting the static locations below.
+ // See SeqAcquire() and SeqRelease() above.
+ absl::base_internal::SpinLock lock{absl::kConstInit,
+ base_internal::SCHEDULE_KERNEL_ONLY};
+};
+ABSL_CONST_INIT static TimeState time_state{};
+
+// Return the time in ns as told by the kernel interface. Place in *cycleclock
+// the value of the cycleclock at about the time of the syscall.
+// This call represents the time base that this module synchronizes to.
+// Ensures that *cycleclock does not step back by up to (1 << 16) from
+// last_cycleclock, to discard small backward counter steps. (Larger steps are
+// assumed to be complete resyncs, which shouldn't happen. If they do, a full
+// reinitialization of the outer algorithm should occur.)
+static int64_t GetCurrentTimeNanosFromKernel(uint64_t last_cycleclock,
+ uint64_t *cycleclock)
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) {
+ uint64_t local_approx_syscall_time_in_cycles = // local copy
+ time_state.approx_syscall_time_in_cycles.load(std::memory_order_relaxed);
+
+ int64_t current_time_nanos_from_system;
+ uint64_t before_cycles;
+ uint64_t after_cycles;
+ uint64_t elapsed_cycles;
+ int loops = 0;
+ do {
+ before_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
+ current_time_nanos_from_system = GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
+ after_cycles = GET_CURRENT_TIME_NANOS_CYCLECLOCK_NOW();
+ // elapsed_cycles is unsigned, so is large on overflow
+ elapsed_cycles = after_cycles - before_cycles;
+ if (elapsed_cycles >= local_approx_syscall_time_in_cycles &&
+ ++loops == 20) { // clock changed frequencies? Back off.
+ loops = 0;
+ if (local_approx_syscall_time_in_cycles < 1000 * 1000) {
+ local_approx_syscall_time_in_cycles =
+ (local_approx_syscall_time_in_cycles + 1) << 1;
+ }
+ time_state.approx_syscall_time_in_cycles.store(
+ local_approx_syscall_time_in_cycles, std::memory_order_relaxed);
+ }
+ } while (elapsed_cycles >= local_approx_syscall_time_in_cycles ||
+ last_cycleclock - after_cycles < (static_cast<uint64_t>(1) << 16));
+
+ // Adjust approx_syscall_time_in_cycles to be within a factor of 2
+ // of the typical time to execute one iteration of the loop above.
+ if ((local_approx_syscall_time_in_cycles >> 1) < elapsed_cycles) {
+ // measured time is no smaller than half current approximation
+ time_state.kernel_time_seen_smaller.store(0, std::memory_order_relaxed);
+ } else if (time_state.kernel_time_seen_smaller.fetch_add(
+ 1, std::memory_order_relaxed) >= 3) {
+ // smaller delays several times in a row; reduce approximation by 12.5%
+ const uint64_t new_approximation =
+ local_approx_syscall_time_in_cycles -
+ (local_approx_syscall_time_in_cycles >> 3);
+ time_state.approx_syscall_time_in_cycles.store(new_approximation,
+ std::memory_order_relaxed);
+ time_state.kernel_time_seen_smaller.store(0, std::memory_order_relaxed);
+ }
+
+ *cycleclock = after_cycles;
+ return current_time_nanos_from_system;
+}
static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD;
@@ -312,14 +321,15 @@ int64_t GetCurrentTimeNanos() {
// Acquire pairs with the barrier in SeqRelease - if this load sees that
// store, the shared-data reads necessarily see that SeqRelease's updates
// to the same shared data.
- seq_read0 = seq.load(std::memory_order_acquire);
+ seq_read0 = time_state.seq.load(std::memory_order_acquire);
- base_ns = last_sample.base_ns.load(std::memory_order_relaxed);
- base_cycles = last_sample.base_cycles.load(std::memory_order_relaxed);
+ base_ns = time_state.last_sample.base_ns.load(std::memory_order_relaxed);
+ base_cycles =
+ time_state.last_sample.base_cycles.load(std::memory_order_relaxed);
nsscaled_per_cycle =
- last_sample.nsscaled_per_cycle.load(std::memory_order_relaxed);
- min_cycles_per_sample =
- last_sample.min_cycles_per_sample.load(std::memory_order_relaxed);
+ time_state.last_sample.nsscaled_per_cycle.load(std::memory_order_relaxed);
+ min_cycles_per_sample = time_state.last_sample.min_cycles_per_sample.load(
+ std::memory_order_relaxed);
// This acquire fence pairs with the release fence in SeqAcquire. Since it
// is sequenced between reads of shared data and seq_read1, the reads of
@@ -330,7 +340,7 @@ int64_t GetCurrentTimeNanos() {
// shared-data writes are effectively release ordered. Therefore if our
// shared-data reads see any of a particular update's shared-data writes,
// seq_read1 is guaranteed to see that update's SeqAcquire.
- seq_read1 = seq.load(std::memory_order_relaxed);
+ seq_read1 = time_state.seq.load(std::memory_order_relaxed);
// Fast path. Return if min_cycles_per_sample has not yet elapsed since the
// last sample, and we read a consistent sample. The fast path activates
@@ -343,9 +353,9 @@ int64_t GetCurrentTimeNanos() {
// last_sample was updated). This is harmless, because delta_cycles will wrap
// and report a time much much bigger than min_cycles_per_sample. In that case
// we will take the slow path.
- uint64_t delta_cycles = now_cycles - base_cycles;
+ uint64_t delta_cycles;
if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 &&
- delta_cycles < min_cycles_per_sample) {
+ (delta_cycles = now_cycles - base_cycles) < min_cycles_per_sample) {
return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale);
}
return GetCurrentTimeNanosSlowPath();
@@ -379,30 +389,31 @@ static uint64_t UpdateLastSample(
//
// Manually mark this 'noinline' to minimize stack frame size of the fast
// path. Without this, sometimes a compiler may inline this big block of code
-// into the fast past. That causes lots of register spills and reloads that
+// into the fast path. That causes lots of register spills and reloads that
// are unnecessary unless the slow path is taken.
//
// TODO(absl-team): Remove this attribute when our compiler is smart enough
// to do the right thing.
ABSL_ATTRIBUTE_NOINLINE
-static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) {
+static int64_t GetCurrentTimeNanosSlowPath()
+ ABSL_LOCKS_EXCLUDED(time_state.lock) {
// Serialize access to slow-path. Fast-path readers are not blocked yet, and
// code below must not modify last_sample until the seqlock is acquired.
- lock.Lock();
+ time_state.lock.Lock();
// Sample the kernel time base. This is the definition of
// "now" if we take the slow path.
- static uint64_t last_now_cycles; // protected by lock
uint64_t now_cycles;
- uint64_t now_ns = GetCurrentTimeNanosFromKernel(last_now_cycles, &now_cycles);
- last_now_cycles = now_cycles;
+ uint64_t now_ns =
+ GetCurrentTimeNanosFromKernel(time_state.last_now_cycles, &now_cycles);
+ time_state.last_now_cycles = now_cycles;
uint64_t estimated_base_ns;
// ----------
// Read the "last_sample" values again; this time holding the write lock.
struct TimeSample sample;
- ReadTimeSampleAtomic(&last_sample, &sample);
+ ReadTimeSampleAtomic(&time_state.last_sample, &sample);
// ----------
// Try running the fast path again; another thread may have updated the
@@ -413,13 +424,13 @@ static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) {
// so that blocked readers can make progress without blocking new readers.
estimated_base_ns = sample.base_ns +
((delta_cycles * sample.nsscaled_per_cycle) >> kScale);
- stats_fast_slow_paths++;
+ time_state.stats_fast_slow_paths++;
} else {
estimated_base_ns =
UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample);
}
- lock.Unlock();
+ time_state.lock.Unlock();
return estimated_base_ns;
}
@@ -430,9 +441,10 @@ static int64_t GetCurrentTimeNanosSlowPath() LOCKS_EXCLUDED(lock) {
static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
uint64_t delta_cycles,
const struct TimeSample *sample)
- EXCLUSIVE_LOCKS_REQUIRED(lock) {
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) {
uint64_t estimated_base_ns = now_ns;
- uint64_t lock_value = SeqAcquire(&seq); // acquire seqlock to block readers
+ uint64_t lock_value =
+ SeqAcquire(&time_state.seq); // acquire seqlock to block readers
// The 5s in the next if-statement limits the time for which we will trust
// the cycle counter and our last sample to give a reasonable result.
@@ -442,14 +454,18 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
sample->raw_ns + static_cast<uint64_t>(5) * 1000 * 1000 * 1000 < now_ns ||
now_ns < sample->raw_ns || now_cycles < sample->base_cycles) {
// record this sample, and forget any previously known slope.
- last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
- last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed);
- last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed);
- last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed);
- last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
- stats_initializations++;
+ time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
+ time_state.last_sample.base_ns.store(estimated_base_ns,
+ std::memory_order_relaxed);
+ time_state.last_sample.base_cycles.store(now_cycles,
+ std::memory_order_relaxed);
+ time_state.last_sample.nsscaled_per_cycle.store(0,
+ std::memory_order_relaxed);
+ time_state.last_sample.min_cycles_per_sample.store(
+ 0, std::memory_order_relaxed);
+ time_state.stats_initializations++;
} else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns &&
- sample->base_cycles + 100 < now_cycles) {
+ sample->base_cycles + 50 < now_cycles) {
// Enough time has passed to compute the cycle time.
if (sample->nsscaled_per_cycle != 0) { // Have a cycle time estimate.
// Compute time from counter reading, but avoiding overflow
@@ -490,35 +506,41 @@ static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
if (new_nsscaled_per_cycle != 0 &&
diff_ns < 100 * 1000 * 1000 && -diff_ns < 100 * 1000 * 1000) {
// record the cycle time measurement
- last_sample.nsscaled_per_cycle.store(
+ time_state.last_sample.nsscaled_per_cycle.store(
new_nsscaled_per_cycle, std::memory_order_relaxed);
uint64_t new_min_cycles_per_sample =
SafeDivideAndScale(kMinNSBetweenSamples, new_nsscaled_per_cycle);
- last_sample.min_cycles_per_sample.store(
+ time_state.last_sample.min_cycles_per_sample.store(
new_min_cycles_per_sample, std::memory_order_relaxed);
- stats_calibrations++;
+ time_state.stats_calibrations++;
} else { // something went wrong; forget the slope
- last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed);
- last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
+ time_state.last_sample.nsscaled_per_cycle.store(
+ 0, std::memory_order_relaxed);
+ time_state.last_sample.min_cycles_per_sample.store(
+ 0, std::memory_order_relaxed);
estimated_base_ns = now_ns;
- stats_reinitializations++;
+ time_state.stats_reinitializations++;
}
- last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
- last_sample.base_ns.store(estimated_base_ns, std::memory_order_relaxed);
- last_sample.base_cycles.store(now_cycles, std::memory_order_relaxed);
+ time_state.last_sample.raw_ns.store(now_ns, std::memory_order_relaxed);
+ time_state.last_sample.base_ns.store(estimated_base_ns,
+ std::memory_order_relaxed);
+ time_state.last_sample.base_cycles.store(now_cycles,
+ std::memory_order_relaxed);
} else {
// have a sample, but no slope; waiting for enough time for a calibration
- stats_slow_paths++;
+ time_state.stats_slow_paths++;
}
- SeqRelease(&seq, lock_value); // release the readers
+ SeqRelease(&time_state.seq, lock_value); // release the readers
return estimated_base_ns;
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
// Returns the maximum duration that SleepOnce() can sleep for.
@@ -546,11 +568,13 @@ void SleepOnce(absl::Duration to_sleep) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
extern "C" {
-ABSL_ATTRIBUTE_WEAK void AbslInternalSleepFor(absl::Duration duration) {
+ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(
+ absl::Duration duration) {
while (duration > absl::ZeroDuration()) {
absl::Duration to_sleep = std::min(duration, absl::MaxSleep());
absl::SleepOnce(to_sleep);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.h
index 3753d4ee43a..5fe244d6381 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,6 +26,7 @@
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// Now()
//
@@ -49,6 +50,7 @@ int64_t GetCurrentTimeNanos();
// * Returns immediately when passed a nonpositive duration.
void SleepFor(absl::Duration duration);
+ABSL_NAMESPACE_END
} // namespace absl
// -----------------------------------------------------------------------------
@@ -62,11 +64,11 @@ void SleepFor(absl::Duration duration);
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void AbslInternalSleepFor(absl::Duration duration);
+void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(absl::Duration duration);
} // extern "C"
inline void absl::SleepFor(absl::Duration duration) {
- AbslInternalSleepFor(duration);
+ ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(duration);
}
#endif // ABSL_TIME_CLOCK_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_benchmark.cc
index 3d3cd9d5c42..c5c795ecbd2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_benchmark.cc
@@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,6 +15,8 @@
#if !defined(_WIN32)
#include <sys/time.h>
+#else
+#include <winsock2.h>
#endif // _WIN32
#include <cstdio>
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_test.cc
index 707166d0c28..4bcfc6bc727 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/clock_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration.cc
index b77d5ec9006..4443109a512 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -49,6 +49,10 @@
//
// Arithmetic overflows/underflows to +/- infinity and saturates.
+#if defined(_MSC_VER)
+#include <winsock2.h> // for timeval
+#endif
+
#include <algorithm>
#include <cassert>
#include <cctype>
@@ -63,10 +67,14 @@
#include <string>
#include "absl/base/casts.h"
+#include "absl/base/macros.h"
#include "absl/numeric/int128.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
#include "absl/time/time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -193,11 +201,11 @@ inline int64_t DecodeTwosComp(uint64_t v) { return absl::bit_cast<int64_t>(v); }
// double as overflow cases.
inline bool SafeAddRepHi(double a_hi, double b_hi, Duration* d) {
double c = a_hi + b_hi;
- if (c >= kint64max) {
+ if (c >= static_cast<double>(kint64max)) {
*d = InfiniteDuration();
return false;
}
- if (c <= kint64min) {
+ if (c <= static_cast<double>(kint64min)) {
*d = -InfiniteDuration();
return false;
}
@@ -348,7 +356,7 @@ namespace time_internal {
// the remainder. If it does not saturate, the remainder remain accurate,
// but the returned quotient will over/underflow int64_t and should not be used.
int64_t IDivDuration(bool satq, const Duration num, const Duration den,
- Duration* rem) {
+ Duration* rem) {
int64_t q = 0;
if (IDivFastPath(num, den, &q, rem)) {
return q;
@@ -703,16 +711,17 @@ char* Format64(char* ep, int width, int64_t v) {
// fractional digits, because it is in the noise of what a Duration can
// represent.
struct DisplayUnit {
- const char* abbr;
+ absl::string_view abbr;
int prec;
double pow10;
};
-const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
-const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
-const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
-const DisplayUnit kDisplaySec = {"s", 11, 1e11};
-const DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored
-const DisplayUnit kDisplayHour = {"h", -1, 0.0}; // prec ignored
+ABSL_CONST_INIT const DisplayUnit kDisplayNano = {"ns", 2, 1e2};
+ABSL_CONST_INIT const DisplayUnit kDisplayMicro = {"us", 5, 1e5};
+ABSL_CONST_INIT const DisplayUnit kDisplayMilli = {"ms", 8, 1e8};
+ABSL_CONST_INIT const DisplayUnit kDisplaySec = {"s", 11, 1e11};
+ABSL_CONST_INIT const DisplayUnit kDisplayMin = {"m", -1, 0.0}; // prec ignored
+ABSL_CONST_INIT const DisplayUnit kDisplayHour = {"h", -1,
+ 0.0}; // prec ignored
void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
char buf[sizeof("2562047788015216")]; // hours in max duration
@@ -720,16 +729,16 @@ void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
char* bp = Format64(ep, 0, n);
if (*bp != '0' || bp + 1 != ep) {
out->append(bp, ep - bp);
- out->append(unit.abbr);
+ out->append(unit.abbr.data(), unit.abbr.size());
}
}
// Note: unit.prec is limited to double's digits10 value (typically 15) so it
// always fits in buf[].
void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
- const int buf_size = std::numeric_limits<double>::digits10;
- const int prec = std::min(buf_size, unit.prec);
- char buf[buf_size]; // also large enough to hold integer part
+ constexpr int kBufferSize = std::numeric_limits<double>::digits10;
+ const int prec = std::min(kBufferSize, unit.prec);
+ char buf[kBufferSize]; // also large enough to hold integer part
char* ep = buf + sizeof(buf);
double d = 0;
int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
@@ -743,18 +752,19 @@ void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
while (ep[-1] == '0') --ep;
out->append(bp, ep - bp);
}
- out->append(unit.abbr);
+ out->append(unit.abbr.data(), unit.abbr.size());
}
}
} // namespace
-// From Go's doc at http://golang.org/pkg/time/#Duration.String
+// From Go's doc at https://golang.org/pkg/time/#Duration.String
// [FormatDuration] returns a string representing the duration in the
-// form "72h3m0.5s". Leading zero units are omitted. As a special
+// form "72h3m0.5s". Leading zero units are omitted. As a special
// case, durations less than one second format use a smaller unit
// (milli-, micro-, or nanoseconds) to ensure that the leading digit
-// is non-zero. The zero duration formats as 0, with no unit.
+// is non-zero.
+// Unlike Go, we format the zero duration as 0, with no unit.
std::string FormatDuration(Duration d) {
const Duration min_duration = Seconds(kint64min);
if (d == min_duration) {
@@ -795,23 +805,27 @@ namespace {
// A helper for ParseDuration() that parses a leading number from the given
// string and stores the result in *int_part/*frac_part/*frac_scale. The
// given string pointer is modified to point to the first unconsumed char.
-bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
+bool ConsumeDurationNumber(const char** dpp, const char* ep, int64_t* int_part,
int64_t* frac_part, int64_t* frac_scale) {
*int_part = 0;
*frac_part = 0;
*frac_scale = 1; // invariant: *frac_part < *frac_scale
const char* start = *dpp;
- for (; std::isdigit(**dpp); *dpp += 1) {
+ for (; *dpp != ep; *dpp += 1) {
const int d = **dpp - '0'; // contiguous digits
+ if (d < 0 || 10 <= d) break;
+
if (*int_part > kint64max / 10) return false;
*int_part *= 10;
if (*int_part > kint64max - d) return false;
*int_part += d;
}
const bool int_part_empty = (*dpp == start);
- if (**dpp != '.') return !int_part_empty;
- for (*dpp += 1; std::isdigit(**dpp); *dpp += 1) {
+ if (*dpp == ep || **dpp != '.') return !int_part_empty;
+
+ for (*dpp += 1; *dpp != ep; *dpp += 1) {
const int d = **dpp - '0'; // contiguous digits
+ if (d < 0 || 10 <= d) break;
if (*frac_scale <= kint64max / 10) {
*frac_part *= 10;
*frac_part += d;
@@ -825,74 +839,97 @@ bool ConsumeDurationNumber(const char** dpp, int64_t* int_part,
// ns, us, ms, s, m, h) from the given string and stores the resulting unit
// in "*unit". The given string pointer is modified to point to the first
// unconsumed char.
-bool ConsumeDurationUnit(const char** start, Duration* unit) {
- const char *s = *start;
- bool ok = true;
- if (strncmp(s, "ns", 2) == 0) {
- s += 2;
- *unit = Nanoseconds(1);
- } else if (strncmp(s, "us", 2) == 0) {
- s += 2;
- *unit = Microseconds(1);
- } else if (strncmp(s, "ms", 2) == 0) {
- s += 2;
- *unit = Milliseconds(1);
- } else if (strncmp(s, "s", 1) == 0) {
- s += 1;
- *unit = Seconds(1);
- } else if (strncmp(s, "m", 1) == 0) {
- s += 1;
- *unit = Minutes(1);
- } else if (strncmp(s, "h", 1) == 0) {
- s += 1;
- *unit = Hours(1);
- } else {
- ok = false;
+bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {
+ size_t size = end - *start;
+ switch (size) {
+ case 0:
+ return false;
+ default:
+ switch (**start) {
+ case 'n':
+ if (*(*start + 1) == 's') {
+ *start += 2;
+ *unit = Nanoseconds(1);
+ return true;
+ }
+ break;
+ case 'u':
+ if (*(*start + 1) == 's') {
+ *start += 2;
+ *unit = Microseconds(1);
+ return true;
+ }
+ break;
+ case 'm':
+ if (*(*start + 1) == 's') {
+ *start += 2;
+ *unit = Milliseconds(1);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ ABSL_FALLTHROUGH_INTENDED;
+ case 1:
+ switch (**start) {
+ case 's':
+ *unit = Seconds(1);
+ *start += 1;
+ return true;
+ case 'm':
+ *unit = Minutes(1);
+ *start += 1;
+ return true;
+ case 'h':
+ *unit = Hours(1);
+ *start += 1;
+ return true;
+ default:
+ return false;
+ }
}
- *start = s;
- return ok;
}
} // namespace
-// From Go's doc at http://golang.org/pkg/time/#ParseDuration
-// [ParseDuration] parses a duration string. A duration string is
+// From Go's doc at https://golang.org/pkg/time/#ParseDuration
+// [ParseDuration] parses a duration string. A duration string is
// a possibly signed sequence of decimal numbers, each with optional
// fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
// Valid time units are "ns", "us" "ms", "s", "m", "h".
-bool ParseDuration(const std::string& dur_string, Duration* d) {
- const char* start = dur_string.c_str();
+bool ParseDuration(absl::string_view dur_sv, Duration* d) {
int sign = 1;
-
- if (*start == '-' || *start == '+') {
- sign = *start == '-' ? -1 : 1;
- ++start;
- }
-
- // Can't parse a duration from an empty std::string.
- if (*start == '\0') {
- return false;
+ if (absl::ConsumePrefix(&dur_sv, "-")) {
+ sign = -1;
+ } else {
+ absl::ConsumePrefix(&dur_sv, "+");
}
+ if (dur_sv.empty()) return false;
- // Special case for a std::string of "0".
- if (*start == '0' && *(start + 1) == '\0') {
+ // Special case for a string of "0".
+ if (dur_sv == "0") {
*d = ZeroDuration();
return true;
}
- if (strcmp(start, "inf") == 0) {
+ if (dur_sv == "inf") {
*d = sign * InfiniteDuration();
return true;
}
+ const char* start = dur_sv.data();
+ const char* end = start + dur_sv.size();
+
Duration dur;
- while (*start != '\0') {
+ while (start != end) {
int64_t int_part;
int64_t frac_part;
int64_t frac_scale;
Duration unit;
- if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
- !ConsumeDurationUnit(&start, &unit)) {
+ if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,
+ &frac_scale) ||
+ !ConsumeDurationUnit(&start, end, &unit)) {
return false;
}
if (int_part != 0) dur += sign * int_part * unit;
@@ -901,10 +938,17 @@ bool ParseDuration(const std::string& dur_string, Duration* d) {
*d = dur;
return true;
}
+
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {
+ return ParseDuration(text, dst);
+}
+
+std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }
bool ParseFlag(const std::string& text, Duration* dst, std::string* ) {
return ParseDuration(text, dst);
}
std::string UnparseFlag(Duration d) { return FormatDuration(d); }
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_benchmark.cc
index d5657bd576a..56820f377b5 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_benchmark.cc
@@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,9 +17,15 @@
#include <ctime>
#include <string>
+#include "absl/base/attributes.h"
+#include "absl/flags/flag.h"
#include "absl/time/time.h"
#include "benchmark/benchmark.h"
+ABSL_FLAG(absl::Duration, absl_duration_flag_for_benchmark,
+ absl::Milliseconds(1),
+ "Flag to use for benchmarking duration flag access speed.");
+
namespace {
//
@@ -424,4 +430,15 @@ void BM_Duration_ParseDuration(benchmark::State& state) {
}
BENCHMARK(BM_Duration_ParseDuration)->DenseRange(0, kNumDurations - 1);
+//
+// Flag access
+//
+void BM_Duration_GetFlag(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(
+ absl::GetFlag(FLAGS_absl_duration_flag_for_benchmark));
+ }
+}
+BENCHMARK(BM_Duration_GetFlag);
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_test.cc
index 61f3c5c07fa..fb28fa987f6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/duration_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#if defined(_MSC_VER)
+#include <winsock2.h> // for timeval
+#endif
+
#include <chrono> // NOLINT(build/c++11)
#include <cmath>
#include <cstdint>
@@ -758,11 +762,6 @@ TEST(Duration, DivisionByZero) {
const double dbl_inf = std::numeric_limits<double>::infinity();
const double dbl_denorm = std::numeric_limits<double>::denorm_min();
- // IEEE 754 behavior
- double z = 0.0, two = 2.0;
- EXPECT_TRUE(std::isinf(two / z));
- EXPECT_TRUE(std::isnan(z / z)); // We'll return inf
-
// Operator/(Duration, double)
EXPECT_EQ(inf, zero / 0.0);
EXPECT_EQ(-inf, zero / -0.0);
@@ -1046,7 +1045,7 @@ TEST(Duration, Multiplication) {
EXPECT_EQ(absl::Seconds(666666666) + absl::Nanoseconds(666666667) +
absl::Nanoseconds(1) / 2,
sigfigs / 3);
- sigfigs = absl::Seconds(7000000000LL);
+ sigfigs = absl::Seconds(int64_t{7000000000});
EXPECT_EQ(absl::Seconds(2333333333) + absl::Nanoseconds(333333333) +
absl::Nanoseconds(1) / 4,
sigfigs / 3);
@@ -1370,10 +1369,13 @@ TEST(Duration, SmallConversions) {
EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv));
}
-void VerifySameAsMul(double time_as_seconds, int* const misses) {
+void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) {
auto direct_seconds = absl::Seconds(time_as_seconds);
auto mul_by_one_second = time_as_seconds * absl::Seconds(1);
- if (direct_seconds != mul_by_one_second) {
+ // These are expected to differ by up to one tick due to fused multiply/add
+ // contraction.
+ if (absl::AbsDuration(direct_seconds - mul_by_one_second) >
+ absl::time_internal::MakeDuration(0, 1u)) {
if (*misses > 10) return;
ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more.";
EXPECT_EQ(direct_seconds, mul_by_one_second)
@@ -1385,7 +1387,8 @@ void VerifySameAsMul(double time_as_seconds, int* const misses) {
// For a variety of interesting durations, we find the exact point
// where one double converts to that duration, and the very next double
// converts to the next duration. For both of those points, verify that
-// Seconds(point) returns the same duration as point * Seconds(1.0)
+// Seconds(point) returns a duration near point * Seconds(1.0). (They may
+// not be exactly equal due to fused multiply/add contraction.)
TEST(Duration, ToDoubleSecondsCheckEdgeCases) {
constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond;
constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u);
@@ -1424,8 +1427,8 @@ TEST(Duration, ToDoubleSecondsCheckEdgeCases) {
}
// Now low_edge is the highest double that converts to Duration d,
// and high_edge is the lowest double that converts to Duration after_d.
- VerifySameAsMul(low_edge, &misses);
- VerifySameAsMul(high_edge, &misses);
+ VerifyApproxSameAsMul(low_edge, &misses);
+ VerifyApproxSameAsMul(high_edge, &misses);
}
}
}
@@ -1445,8 +1448,8 @@ TEST(Duration, ToDoubleSecondsCheckRandom) {
int misses = 0;
for (int i = 0; i < 1000000; ++i) {
double d = std::exp(uniform(gen));
- VerifySameAsMul(d, &misses);
- VerifySameAsMul(-d, &misses);
+ VerifyApproxSameAsMul(d, &misses);
+ VerifyApproxSameAsMul(-d, &misses);
}
}
@@ -1771,7 +1774,7 @@ TEST(Duration, ParseDuration) {
TEST(Duration, FormatParseRoundTrip) {
#define TEST_PARSE_ROUNDTRIP(d) \
do { \
- std::string s = absl::FormatDuration(d); \
+ std::string s = absl::FormatDuration(d); \
absl::Duration dur; \
EXPECT_TRUE(absl::ParseDuration(s, &dur)); \
EXPECT_EQ(d, dur); \
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format.cc
index ee597e407a9..4005fb704cf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -13,21 +13,25 @@
// limitations under the License.
#include <string.h>
+
#include <cctype>
#include <cstdint>
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#include "absl/time/time.h"
namespace cctz = absl::time_internal::cctz;
namespace absl {
+ABSL_NAMESPACE_BEGIN
-extern const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+ABSL_DLL extern const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
-extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
-extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_full[] = "%a, %d %b %E4Y %H:%M:%S %z";
+ABSL_DLL extern const char RFC1123_no_wday[] = "%d %b %E4Y %H:%M:%S %z";
namespace {
@@ -67,11 +71,12 @@ absl::Time Join(const cctz_parts& parts) {
} // namespace
-std::string FormatTime(const std::string& format, absl::Time t, absl::TimeZone tz) {
- if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
- if (t == absl::InfinitePast()) return kInfinitePastStr;
+std::string FormatTime(absl::string_view format, absl::Time t,
+ absl::TimeZone tz) {
+ if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr);
+ if (t == absl::InfinitePast()) return std::string(kInfinitePastStr);
const auto parts = Split(t);
- return cctz::detail::format(format, parts.sec, parts.fem,
+ return cctz::detail::format(std::string(format), parts.sec, parts.fem,
cctz::time_zone(tz));
}
@@ -83,42 +88,50 @@ std::string FormatTime(absl::Time t) {
return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
}
-bool ParseTime(const std::string& format, const std::string& input, absl::Time* time,
- std::string* err) {
+bool ParseTime(absl::string_view format, absl::string_view input,
+ absl::Time* time, std::string* err) {
return absl::ParseTime(format, input, absl::UTCTimeZone(), time, err);
}
// If the input string does not contain an explicit UTC offset, interpret
// the fields with respect to the given TimeZone.
-bool ParseTime(const std::string& format, const std::string& input, absl::TimeZone tz,
- absl::Time* time, std::string* err) {
- const char* data = input.c_str();
- while (std::isspace(*data)) ++data;
-
- size_t inf_size = strlen(kInfiniteFutureStr);
- if (strncmp(data, kInfiniteFutureStr, inf_size) == 0) {
- const char* new_data = data + inf_size;
- while (std::isspace(*new_data)) ++new_data;
- if (*new_data == '\0') {
- *time = InfiniteFuture();
- return true;
+bool ParseTime(absl::string_view format, absl::string_view input,
+ absl::TimeZone tz, absl::Time* time, std::string* err) {
+ auto strip_leading_space = [](absl::string_view* sv) {
+ while (!sv->empty()) {
+ if (!std::isspace(sv->front())) return;
+ sv->remove_prefix(1);
}
- }
-
- inf_size = strlen(kInfinitePastStr);
- if (strncmp(data, kInfinitePastStr, inf_size) == 0) {
- const char* new_data = data + inf_size;
- while (std::isspace(*new_data)) ++new_data;
- if (*new_data == '\0') {
- *time = InfinitePast();
- return true;
+ };
+
+ // Portable toolchains means we don't get nice constexpr here.
+ struct Literal {
+ const char* name;
+ size_t size;
+ absl::Time value;
+ };
+ static Literal literals[] = {
+ {kInfiniteFutureStr, strlen(kInfiniteFutureStr), InfiniteFuture()},
+ {kInfinitePastStr, strlen(kInfinitePastStr), InfinitePast()},
+ };
+ strip_leading_space(&input);
+ for (const auto& lit : literals) {
+ if (absl::StartsWith(input, absl::string_view(lit.name, lit.size))) {
+ absl::string_view tail = input;
+ tail.remove_prefix(lit.size);
+ strip_leading_space(&tail);
+ if (tail.empty()) {
+ *time = lit.value;
+ return true;
+ }
}
}
std::string error;
cctz_parts parts;
- const bool b = cctz::detail::parse(format, input, cctz::time_zone(tz),
- &parts.sec, &parts.fem, &error);
+ const bool b =
+ cctz::detail::parse(std::string(format), std::string(input),
+ cctz::time_zone(tz), &parts.sec, &parts.fem, &error);
if (b) {
*time = Join(parts);
} else if (err != nullptr) {
@@ -128,6 +141,13 @@ bool ParseTime(const std::string& format, const std::string& input, absl::TimeZo
}
// Functions required to support absl::Time flags.
+bool AbslParseFlag(absl::string_view text, absl::Time* t, std::string* error) {
+ return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
+}
+
+std::string AbslUnparseFlag(absl::Time t) {
+ return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
+}
bool ParseFlag(const std::string& text, absl::Time* t, std::string* error) {
return absl::ParseTime(RFC3339_full, text, absl::UTCTimeZone(), t, error);
}
@@ -136,4 +156,5 @@ std::string UnparseFlag(absl::Time t) {
return absl::FormatTime(RFC3339_full, t, absl::UTCTimeZone());
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_benchmark.cc
index 766f1b39a55..19e481dbd1a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_benchmark.cc
@@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -26,7 +26,7 @@ const char* const kFormats[] = {
absl::RFC1123_no_wday, // 1
absl::RFC3339_full, // 2
absl::RFC3339_sec, // 3
- "%Y-%m-%dT%H:%M:%S", // 4
+ "%Y-%m-%d%ET%H:%M:%S", // 4
"%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_test.cc
index ac8d5ea303a..a9a1eb8ee1d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/format_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,8 +27,8 @@ namespace {
// A helper that tests the given format specifier by itself, and with leading
// and trailing characters. For example: TestFormatSpecifier(t, "%a", "Thu").
-void TestFormatSpecifier(absl::Time t, absl::TimeZone tz, const std::string& fmt,
- const std::string& ans) {
+void TestFormatSpecifier(absl::Time t, absl::TimeZone tz,
+ const std::string& fmt, const std::string& ans) {
EXPECT_EQ(ans, absl::FormatTime(fmt, t, tz));
EXPECT_EQ("xxx " + ans, absl::FormatTime("xxx " + fmt, t, tz));
EXPECT_EQ(ans + " yyy", absl::FormatTime(fmt + " yyy", t, tz));
@@ -173,7 +173,7 @@ TEST(ParseTime, WithTimeZone) {
absl::Time t;
std::string e;
- // We can parse a std::string without a UTC offset if we supply a timezone.
+ // We can parse a string without a UTC offset if we supply a timezone.
EXPECT_TRUE(
absl::ParseTime("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &t, &e))
<< e;
@@ -201,7 +201,7 @@ TEST(ParseTime, ErrorCases) {
err.clear();
EXPECT_FALSE(absl::ParseTime("%Q", "x", &t, &err)) << err;
// Exact contents of "err" are platform-dependent because of
- // differences in the strptime implementation between OSX and Linux.
+ // differences in the strptime implementation between macOS and Linux.
EXPECT_FALSE(err.empty());
// Fails because of trailing, unparsed data "blah".
@@ -327,7 +327,7 @@ TEST(ParseTime, InfiniteTime) {
EXPECT_TRUE(absl::ParseTime("%H:%M blah", " infinite-past ", &t, &err));
EXPECT_EQ(absl::InfinitePast(), t);
- // "infinite-future" as literal std::string
+ // "infinite-future" as literal string
absl::TimeZone tz = absl::UTCTimeZone();
EXPECT_TRUE(absl::ParseTime("infinite-future %H:%M", "infinite-future 03:04",
&t, &err));
@@ -335,7 +335,7 @@ TEST(ParseTime, InfiniteTime) {
EXPECT_EQ(3, tz.At(t).cs.hour());
EXPECT_EQ(4, tz.At(t).cs.minute());
- // "infinite-past" as literal std::string
+ // "infinite-past" as literal string
EXPECT_TRUE(
absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
EXPECT_NE(absl::InfinitePast(), t);
@@ -375,7 +375,8 @@ TEST(FormatParse, RoundTrip) {
// RFC3339, which renders subseconds.
{
absl::Time out;
- const std::string s = absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
+ const std::string s =
+ absl::FormatTime(absl::RFC3339_full, in + subseconds, lax);
EXPECT_TRUE(absl::ParseTime(absl::RFC3339_full, s, &out, &err))
<< s << ": " << err;
EXPECT_EQ(in + subseconds, out); // RFC3339_full includes %Ez
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
index e2cfe801f23..45a952924d9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
@@ -4,7 +4,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# 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,
@@ -12,22 +12,33 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+
package(features = ["-parse_headers"])
-licenses(["notice"]) # Apache License
+licenses(["notice"])
-### libraries
+filegroup(
+ name = "zoneinfo",
+ srcs = glob(["testdata/zoneinfo/**"]),
+)
-cc_library(
- name = "includes",
- textual_hdrs = [
- "include/cctz/civil_time.h",
- "include/cctz/civil_time_detail.h",
- "include/cctz/time_zone.h",
+config_setting(
+ name = "osx",
+ constraint_values = [
+ "@bazel_tools//platforms:osx",
+ ],
+)
+
+config_setting(
+ name = "ios",
+ constraint_values = [
+ "@bazel_tools//platforms:ios",
],
- visibility = ["//absl/time:__pkg__"],
)
+### libraries
+
cc_library(
name = "civil_time",
srcs = ["src/civil_time_detail.cc"],
@@ -36,6 +47,7 @@ cc_library(
],
textual_hdrs = ["include/cctz/civil_time_detail.h"],
visibility = ["//visibility:public"],
+ deps = ["//absl/base:config"],
)
cc_library(
@@ -62,18 +74,36 @@ cc_library(
"include/cctz/time_zone.h",
"include/cctz/zone_info_source.h",
],
+ linkopts = select({
+ ":osx": [
+ "-framework Foundation",
+ ],
+ ":ios": [
+ "-framework Foundation",
+ ],
+ "//conditions:default": [],
+ }),
visibility = ["//visibility:public"],
- deps = [":civil_time"],
+ deps = [
+ ":civil_time",
+ "//absl/base:config",
+ ],
)
### tests
+test_suite(
+ name = "all_tests",
+ visibility = ["//visibility:public"],
+)
+
cc_test(
name = "civil_time_test",
size = "small",
srcs = ["src/civil_time_test.cc"],
deps = [
":civil_time",
+ "//absl/base:config",
"@com_google_googletest//:gtest_main",
],
)
@@ -91,6 +121,7 @@ cc_test(
deps = [
":civil_time",
":time_zone",
+ "//absl/base:config",
"@com_google_googletest//:gtest_main",
],
)
@@ -98,17 +129,18 @@ cc_test(
cc_test(
name = "time_zone_lookup_test",
size = "small",
+ timeout = "moderate",
srcs = ["src/time_zone_lookup_test.cc"],
data = [":zoneinfo"],
tags = [
"no_test_android_arm",
"no_test_android_arm64",
"no_test_android_x86",
- "no_test_wasm",
],
deps = [
":civil_time",
":time_zone",
+ "//absl/base:config",
"@com_google_googletest//:gtest_main",
],
)
@@ -129,6 +161,7 @@ cc_test(
deps = [
":civil_time",
":time_zone",
+ "//absl/base:config",
"@com_github_google_benchmark//:benchmark_main",
],
)
@@ -136,8 +169,3 @@ cc_test(
### examples
### binaries
-
-filegroup(
- name = "zoneinfo",
- srcs = glob(["testdata/zoneinfo/**"]),
-)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h
index 0842fa4a468..d47ff86fe43 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,9 +15,11 @@
#ifndef ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
#define ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time_detail.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -150,7 +152,7 @@ namespace cctz {
//
// All civil-time types have accessors for all six of the civil-time fields:
// year, month, day, hour, minute, and second. Recall that fields inferior to
-// the type's aligment will be set to their minimum valid value.
+// the type's alignment will be set to their minimum valid value.
//
// civil_day d(2015, 6, 28);
// // d.year() == 2015
@@ -279,7 +281,7 @@ using civil_second = detail::civil_second;
//
using detail::weekday;
-// Returns the weekday for the given civil_day.
+// Returns the weekday for the given civil-time value.
//
// civil_day a(2015, 8, 13);
// weekday wd = get_weekday(a); // wd == weekday::thursday
@@ -306,14 +308,14 @@ using detail::get_weekday;
//
// civil_day d = ...
// // Gets the following Thursday if d is not already Thursday
-// civil_day thurs1 = prev_weekday(d, weekday::thursday) + 7;
+// civil_day thurs1 = next_weekday(d - 1, weekday::thursday);
// // Gets the previous Thursday if d is not already Thursday
-// civil_day thurs2 = next_weekday(d, weekday::thursday) - 7;
+// civil_day thurs2 = prev_weekday(d + 1, weekday::thursday);
//
using detail::next_weekday;
using detail::prev_weekday;
-// Returns the day-of-year for the given civil_day.
+// Returns the day-of-year for the given civil-time value.
//
// civil_day a(2015, 1, 1);
// int yd_jan_1 = get_yearday(a); // yd_jan_1 = 1
@@ -324,6 +326,7 @@ using detail::get_yearday;
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_CIVIL_TIME_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index 1c5d0970827..8aadde57ca7 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,8 +20,10 @@
#include <ostream>
#include <type_traits>
+#include "absl/base/config.h"
+
// Disable constexpr support unless we are in C++14 mode.
-#if __cpp_constexpr >= 201304 || _MSC_VER >= 1910
+#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
#define CONSTEXPR_D constexpr // data
#define CONSTEXPR_F constexpr // function
#define CONSTEXPR_M constexpr // member
@@ -32,6 +34,7 @@
#endif
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -53,8 +56,8 @@ using second_t = std::int_fast8_t; // [0:59]
// Normalized civil-time fields: Y-M-D HH:MM:SS.
struct fields {
- CONSTEXPR_M fields(year_t year, month_t month, day_t day,
- hour_t hour, minute_t minute, second_t second)
+ CONSTEXPR_M fields(year_t year, month_t month, day_t day, hour_t hour,
+ minute_t minute, second_t second)
: y(year), m(month), d(day), hh(hour), mm(minute), ss(second) {}
std::int_least64_t y;
std::int_least8_t m;
@@ -101,59 +104,69 @@ CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept {
return k_days_per_month[m] + (m == 2 && is_leap_year(y));
}
-CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd,
- hour_t hh, minute_t mm, second_t ss) noexcept {
- y += (cd / 146097) * 400;
+CONSTEXPR_F fields n_day(year_t y, month_t m, diff_t d, diff_t cd, hour_t hh,
+ minute_t mm, second_t ss) noexcept {
+ year_t ey = y % 400;
+ const year_t oey = ey;
+ ey += (cd / 146097) * 400;
cd %= 146097;
if (cd < 0) {
- y -= 400;
+ ey -= 400;
cd += 146097;
}
- y += (d / 146097) * 400;
+ ey += (d / 146097) * 400;
d = d % 146097 + cd;
if (d > 0) {
if (d > 146097) {
- y += 400;
+ ey += 400;
d -= 146097;
}
} else {
if (d > -365) {
// We often hit the previous year when stepping a civil time backwards,
// so special case it to avoid counting up by 100/4/1-year chunks.
- y -= 1;
- d += days_per_year(y, m);
+ ey -= 1;
+ d += days_per_year(ey, m);
} else {
- y -= 400;
+ ey -= 400;
d += 146097;
}
}
if (d > 365) {
- for (int n = days_per_century(y, m); d > n; n = days_per_century(y, m)) {
+ for (;;) {
+ int n = days_per_century(ey, m);
+ if (d <= n) break;
d -= n;
- y += 100;
+ ey += 100;
}
- for (int n = days_per_4years(y, m); d > n; n = days_per_4years(y, m)) {
+ for (;;) {
+ int n = days_per_4years(ey, m);
+ if (d <= n) break;
d -= n;
- y += 4;
+ ey += 4;
}
- for (int n = days_per_year(y, m); d > n; n = days_per_year(y, m)) {
+ for (;;) {
+ int n = days_per_year(ey, m);
+ if (d <= n) break;
d -= n;
- ++y;
+ ++ey;
}
}
if (d > 28) {
- for (int n = days_per_month(y, m); d > n; n = days_per_month(y, m)) {
+ for (;;) {
+ int n = days_per_month(ey, m);
+ if (d <= n) break;
d -= n;
if (++m > 12) {
- ++y;
+ ++ey;
m = 1;
}
}
}
- return fields(y, m, static_cast<day_t>(d), hh, mm, ss);
+ return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);
}
-CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd,
- hour_t hh, minute_t mm, second_t ss) noexcept {
+CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd, hour_t hh,
+ minute_t mm, second_t ss) noexcept {
if (m != 12) {
y += m / 12;
m %= 12;
@@ -164,8 +177,8 @@ CONSTEXPR_F fields n_mon(year_t y, diff_t m, diff_t d, diff_t cd,
}
return n_day(y, static_cast<month_t>(m), d, cd, hh, mm, ss);
}
-CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd,
- diff_t hh, minute_t mm, second_t ss) noexcept {
+CONSTEXPR_F fields n_hour(year_t y, diff_t m, diff_t d, diff_t cd, diff_t hh,
+ minute_t mm, second_t ss) noexcept {
cd += hh / 24;
hh %= 24;
if (hh < 0) {
@@ -264,8 +277,8 @@ CONSTEXPR_F diff_t ymd_ord(year_t y, month_t m, day_t d) noexcept {
// yet the difference between two such extreme values may actually be
// small, so we take a little care to avoid overflow when possible by
// exploiting the 146097-day cycle.
-CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1,
- year_t y2, month_t m2, day_t d2) noexcept {
+CONSTEXPR_F diff_t day_difference(year_t y1, month_t m1, day_t d1, year_t y2,
+ month_t m2, day_t d2) noexcept {
const diff_t a_c4_off = y1 % 400;
const diff_t b_c4_off = y2 % 400;
diff_t c4_diff = (y1 - a_c4_off) - (y2 - b_c4_off);
@@ -305,9 +318,7 @@ CONSTEXPR_F diff_t difference(second_tag, fields f1, fields f2) noexcept {
////////////////////////////////////////////////////////////////////////
// Aligns the (normalized) fields struct to the indicated field.
-CONSTEXPR_F fields align(second_tag, fields f) noexcept {
- return f;
-}
+CONSTEXPR_F fields align(second_tag, fields f) noexcept { return f; }
CONSTEXPR_F fields align(minute_tag, fields f) noexcept {
return fields{f.y, f.m, f.d, f.hh, f.mm, 0};
}
@@ -386,11 +397,11 @@ class civil_time {
: civil_time(ct.f_) {}
// Factories for the maximum/minimum representable civil_time.
- static CONSTEXPR_F civil_time (max)() {
+ static CONSTEXPR_F civil_time(max)() {
const auto max_year = (std::numeric_limits<std::int_least64_t>::max)();
return civil_time(max_year, 12, 31, 23, 59, 59);
}
- static CONSTEXPR_F civil_time (min)() {
+ static CONSTEXPR_F civil_time(min)() {
const auto min_year = (std::numeric_limits<std::int_least64_t>::min)();
return civil_time(min_year, 1, 1, 0, 0, 0);
}
@@ -405,28 +416,18 @@ class civil_time {
// Assigning arithmetic.
CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
- f_ = step(T{}, f_, n);
- return *this;
+ return *this = *this + n;
}
CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
- if (n != (std::numeric_limits<diff_t>::min)()) {
- f_ = step(T{}, f_, -n);
- } else {
- f_ = step(T{}, step(T{}, f_, -(n + 1)), 1);
- }
- return *this;
- }
- CONSTEXPR_M civil_time& operator++() noexcept {
- return *this += 1;
+ return *this = *this - n;
}
+ CONSTEXPR_M civil_time& operator++() noexcept { return *this += 1; }
CONSTEXPR_M civil_time operator++(int) noexcept {
const civil_time a = *this;
++*this;
return a;
}
- CONSTEXPR_M civil_time& operator--() noexcept {
- return *this -= 1;
- }
+ CONSTEXPR_M civil_time& operator--() noexcept { return *this -= 1; }
CONSTEXPR_M civil_time operator--(int) noexcept {
const civil_time a = *this;
--*this;
@@ -435,13 +436,15 @@ class civil_time {
// Binary arithmetic operators.
friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
- return a += n;
+ return civil_time(step(T{}, a.f_, n));
}
friend CONSTEXPR_F civil_time operator+(diff_t n, civil_time a) noexcept {
- return a += n;
+ return a + n;
}
friend CONSTEXPR_F civil_time operator-(civil_time a, diff_t n) noexcept {
- return a -= n;
+ return n != (std::numeric_limits<diff_t>::min)()
+ ? civil_time(step(T{}, a.f_, -n))
+ : civil_time(step(T{}, step(T{}, a.f_, -(n + 1)), 1));
}
friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
return difference(T{}, lhs.f_, rhs.f_);
@@ -483,17 +486,17 @@ using civil_second = civil_time<second_tag>;
template <typename T1, typename T2>
CONSTEXPR_F bool operator<(const civil_time<T1>& lhs,
const civil_time<T2>& rhs) noexcept {
- return (lhs.year() < rhs.year() ||
- (lhs.year() == rhs.year() &&
- (lhs.month() < rhs.month() ||
- (lhs.month() == rhs.month() &&
- (lhs.day() < rhs.day() ||
- (lhs.day() == rhs.day() &&
- (lhs.hour() < rhs.hour() ||
- (lhs.hour() == rhs.hour() &&
- (lhs.minute() < rhs.minute() ||
- (lhs.minute() == rhs.minute() &&
- (lhs.second() < rhs.second())))))))))));
+ return (
+ lhs.year() < rhs.year() ||
+ (lhs.year() == rhs.year() &&
+ (lhs.month() < rhs.month() ||
+ (lhs.month() == rhs.month() &&
+ (lhs.day() < rhs.day() || (lhs.day() == rhs.day() &&
+ (lhs.hour() < rhs.hour() ||
+ (lhs.hour() == rhs.hour() &&
+ (lhs.minute() < rhs.minute() ||
+ (lhs.minute() == rhs.minute() &&
+ (lhs.second() < rhs.second())))))))))));
}
template <typename T1, typename T2>
CONSTEXPR_F bool operator<=(const civil_time<T1>& lhs,
@@ -535,7 +538,7 @@ enum class weekday {
sunday,
};
-CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
+CONSTEXPR_F weekday get_weekday(const civil_second& cs) noexcept {
CONSTEXPR_D weekday k_weekday_by_mon_off[13] = {
weekday::monday, weekday::tuesday, weekday::wednesday,
weekday::thursday, weekday::friday, weekday::saturday,
@@ -546,30 +549,60 @@ CONSTEXPR_F weekday get_weekday(const civil_day& cd) noexcept {
CONSTEXPR_D int k_weekday_offsets[1 + 12] = {
-1, 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4,
};
- year_t wd = 2400 + (cd.year() % 400) - (cd.month() < 3);
+ year_t wd = 2400 + (cs.year() % 400) - (cs.month() < 3);
wd += wd / 4 - wd / 100 + wd / 400;
- wd += k_weekday_offsets[cd.month()] + cd.day();
+ wd += k_weekday_offsets[cs.month()] + cs.day();
return k_weekday_by_mon_off[wd % 7 + 6];
}
////////////////////////////////////////////////////////////////////////
CONSTEXPR_F civil_day next_weekday(civil_day cd, weekday wd) noexcept {
- do { cd += 1; } while (get_weekday(cd) != wd);
- return cd;
+ CONSTEXPR_D weekday k_weekdays_forw[14] = {
+ weekday::monday, weekday::tuesday, weekday::wednesday,
+ weekday::thursday, weekday::friday, weekday::saturday,
+ weekday::sunday, weekday::monday, weekday::tuesday,
+ weekday::wednesday, weekday::thursday, weekday::friday,
+ weekday::saturday, weekday::sunday,
+ };
+ weekday base = get_weekday(cd);
+ for (int i = 0;; ++i) {
+ if (base == k_weekdays_forw[i]) {
+ for (int j = i + 1;; ++j) {
+ if (wd == k_weekdays_forw[j]) {
+ return cd + (j - i);
+ }
+ }
+ }
+ }
}
CONSTEXPR_F civil_day prev_weekday(civil_day cd, weekday wd) noexcept {
- do { cd -= 1; } while (get_weekday(cd) != wd);
- return cd;
+ CONSTEXPR_D weekday k_weekdays_back[14] = {
+ weekday::sunday, weekday::saturday, weekday::friday,
+ weekday::thursday, weekday::wednesday, weekday::tuesday,
+ weekday::monday, weekday::sunday, weekday::saturday,
+ weekday::friday, weekday::thursday, weekday::wednesday,
+ weekday::tuesday, weekday::monday,
+ };
+ weekday base = get_weekday(cd);
+ for (int i = 0;; ++i) {
+ if (base == k_weekdays_back[i]) {
+ for (int j = i + 1;; ++j) {
+ if (wd == k_weekdays_back[j]) {
+ return cd - (j - i);
+ }
+ }
+ }
+ }
}
-CONSTEXPR_F int get_yearday(const civil_day& cd) noexcept {
+CONSTEXPR_F int get_yearday(const civil_second& cs) noexcept {
CONSTEXPR_D int k_month_offsets[1 + 12] = {
-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
};
- const int feb29 = (cd.month() > 2 && impl::is_leap_year(cd.year()));
- return k_month_offsets[cd.month()] + feb29 + cd.day();
+ const int feb29 = (cs.month() > 2 && impl::is_leap_year(cs.year()));
+ return k_month_offsets[cs.month()] + feb29 + cs.day();
}
////////////////////////////////////////////////////////////////////////
@@ -585,6 +618,7 @@ std::ostream& operator<<(std::ostream& os, weekday wd);
} // namespace detail
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#undef CONSTEXPR_M
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
index f28dad17550..5562a37bc80 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,9 +25,11 @@
#include <string>
#include <utility>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -39,8 +41,8 @@ using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead.
namespace detail {
template <typename D>
-inline std::pair<time_point<seconds>, D>
-split_seconds(const time_point<D>& tp) {
+inline std::pair<time_point<seconds>, D> split_seconds(
+ const time_point<D>& tp) {
auto sec = std::chrono::time_point_cast<seconds>(tp);
auto sub = tp - sec;
if (sub.count() < 0) {
@@ -49,8 +51,8 @@ split_seconds(const time_point<D>& tp) {
}
return {sec, std::chrono::duration_cast<D>(sub)};
}
-inline std::pair<time_point<seconds>, seconds>
-split_seconds(const time_point<seconds>& tp) {
+inline std::pair<time_point<seconds>, seconds> split_seconds(
+ const time_point<seconds>& tp) {
return {tp, seconds::zero()};
}
} // namespace detail
@@ -72,7 +74,7 @@ split_seconds(const time_point<seconds>& tp) {
//
// See also:
// - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://en.wikipedia.org/wiki/Zoneinfo
class time_zone {
public:
time_zone() : time_zone(nullptr) {} // Equivalent to UTC
@@ -194,22 +196,20 @@ class time_zone {
bool next_transition(const time_point<seconds>& tp,
civil_transition* trans) const;
template <typename D>
- bool next_transition(const time_point<D>& tp,
- civil_transition* trans) const {
+ bool next_transition(const time_point<D>& tp, civil_transition* trans) const {
return next_transition(detail::split_seconds(tp).first, trans);
}
bool prev_transition(const time_point<seconds>& tp,
civil_transition* trans) const;
template <typename D>
- bool prev_transition(const time_point<D>& tp,
- civil_transition* trans) const {
+ bool prev_transition(const time_point<D>& tp, civil_transition* trans) const {
return prev_transition(detail::split_seconds(tp).first, trans);
}
// version() and description() provide additional information about the
// time zone. The content of each of the returned strings is unspecified,
// however, when the IANA Time Zone Database is the underlying data source
- // the version() std::string will be in the familar form (e.g, "2018e") or
+ // the version() string will be in the familar form (e.g, "2018e") or
// empty when unavailable.
//
// Note: These functions are for informational or testing purposes only.
@@ -220,9 +220,7 @@ class time_zone {
friend bool operator==(time_zone lhs, time_zone rhs) {
return &lhs.effective_impl() == &rhs.effective_impl();
}
- friend bool operator!=(time_zone lhs, time_zone rhs) {
- return !(lhs == rhs);
- }
+ friend bool operator!=(time_zone lhs, time_zone rhs) { return !(lhs == rhs); }
template <typename H>
friend H AbslHashValue(H h, time_zone tz) {
@@ -294,6 +292,7 @@ bool parse(const std::string&, const std::string&, const time_zone&,
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
@@ -323,7 +322,8 @@ inline std::string format(const std::string& fmt, const time_point<D>& tp,
// returns the corresponding time_point. Uses strftime()-like formatting
// options, with the same extensions as cctz::format(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
@@ -380,6 +380,7 @@ inline bool parse(const std::string& fmt, const std::string& input,
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
index 20a76979370..012eb4ec30e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,7 +20,10 @@
#include <memory>
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -30,19 +33,21 @@ class ZoneInfoSource {
virtual ~ZoneInfoSource();
virtual std::size_t Read(void* ptr, std::size_t size) = 0; // like fread()
- virtual int Skip(std::size_t offset) = 0; // like fseek()
+ virtual int Skip(std::size_t offset) = 0; // like fseek()
// Until the zoneinfo data supports versioning information, we provide
// a way for a ZoneInfoSource to indicate it out-of-band. The default
- // implementation returns an empty std::string.
+ // implementation returns an empty string.
virtual std::string Version() const;
};
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz_extension {
@@ -52,8 +57,8 @@ namespace cctz_extension {
using ZoneInfoSourceFactory =
std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> (*)(
const std::string&,
- const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
- const std::string&)>&);
+ const std::function<std::unique_ptr<
+ absl::time_internal::cctz::ZoneInfoSource>(const std::string&)>&);
// The user can control the mapping of zone names to zoneinfo data by
// providing a definition for cctz_extension::zone_info_source_factory.
@@ -91,6 +96,7 @@ extern ZoneInfoSourceFactory zone_info_source_factory;
} // namespace cctz_extension
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_ZONE_INFO_SOURCE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
index 4498d7d0b6b..4e39188ff3e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -47,608 +47,658 @@ void BM_Step_Days(benchmark::State& state) {
}
BENCHMARK(BM_Step_Days);
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+void BM_GetWeekday(benchmark::State& state) {
+ const cctz::civil_day c(2014, 8, 22);
+ while (state.KeepRunning()) {
+ benchmark::DoNotOptimize(cctz::get_weekday(c));
+ }
+}
+BENCHMARK(BM_GetWeekday);
+
+void BM_NextWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::next_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_NextWeekday);
+
+void BM_PrevWeekday(benchmark::State& state) {
+ const cctz::civil_day kStart(2014, 8, 22);
+ const cctz::civil_day kDays[7] = {
+ kStart + 0, kStart + 1, kStart + 2, kStart + 3,
+ kStart + 4, kStart + 5, kStart + 6,
+ };
+ const cctz::weekday kWeekdays[7] = {
+ cctz::weekday::monday, cctz::weekday::tuesday, cctz::weekday::wednesday,
+ cctz::weekday::thursday, cctz::weekday::friday, cctz::weekday::saturday,
+ cctz::weekday::sunday,
+ };
+ while (state.KeepRunningBatch(7 * 7)) {
+ for (const auto from : kDays) {
+ for (const auto to : kWeekdays) {
+ benchmark::DoNotOptimize(cctz::prev_weekday(from, to));
+ }
+ }
+ }
+}
+BENCHMARK(BM_PrevWeekday);
+
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
// A list of known time-zone names.
// TODO: Refactor with src/time_zone_lookup_test.cc.
-const char* const kTimeZoneNames[] = {
- "Africa/Abidjan",
- "Africa/Accra",
- "Africa/Addis_Ababa",
- "Africa/Algiers",
- "Africa/Asmara",
- "Africa/Asmera",
- "Africa/Bamako",
- "Africa/Bangui",
- "Africa/Banjul",
- "Africa/Bissau",
- "Africa/Blantyre",
- "Africa/Brazzaville",
- "Africa/Bujumbura",
- "Africa/Cairo",
- "Africa/Casablanca",
- "Africa/Ceuta",
- "Africa/Conakry",
- "Africa/Dakar",
- "Africa/Dar_es_Salaam",
- "Africa/Djibouti",
- "Africa/Douala",
- "Africa/El_Aaiun",
- "Africa/Freetown",
- "Africa/Gaborone",
- "Africa/Harare",
- "Africa/Johannesburg",
- "Africa/Juba",
- "Africa/Kampala",
- "Africa/Khartoum",
- "Africa/Kigali",
- "Africa/Kinshasa",
- "Africa/Lagos",
- "Africa/Libreville",
- "Africa/Lome",
- "Africa/Luanda",
- "Africa/Lubumbashi",
- "Africa/Lusaka",
- "Africa/Malabo",
- "Africa/Maputo",
- "Africa/Maseru",
- "Africa/Mbabane",
- "Africa/Mogadishu",
- "Africa/Monrovia",
- "Africa/Nairobi",
- "Africa/Ndjamena",
- "Africa/Niamey",
- "Africa/Nouakchott",
- "Africa/Ouagadougou",
- "Africa/Porto-Novo",
- "Africa/Sao_Tome",
- "Africa/Timbuktu",
- "Africa/Tripoli",
- "Africa/Tunis",
- "Africa/Windhoek",
- "America/Adak",
- "America/Anchorage",
- "America/Anguilla",
- "America/Antigua",
- "America/Araguaina",
- "America/Argentina/Buenos_Aires",
- "America/Argentina/Catamarca",
- "America/Argentina/ComodRivadavia",
- "America/Argentina/Cordoba",
- "America/Argentina/Jujuy",
- "America/Argentina/La_Rioja",
- "America/Argentina/Mendoza",
- "America/Argentina/Rio_Gallegos",
- "America/Argentina/Salta",
- "America/Argentina/San_Juan",
- "America/Argentina/San_Luis",
- "America/Argentina/Tucuman",
- "America/Argentina/Ushuaia",
- "America/Aruba",
- "America/Asuncion",
- "America/Atikokan",
- "America/Atka",
- "America/Bahia",
- "America/Bahia_Banderas",
- "America/Barbados",
- "America/Belem",
- "America/Belize",
- "America/Blanc-Sablon",
- "America/Boa_Vista",
- "America/Bogota",
- "America/Boise",
- "America/Buenos_Aires",
- "America/Cambridge_Bay",
- "America/Campo_Grande",
- "America/Cancun",
- "America/Caracas",
- "America/Catamarca",
- "America/Cayenne",
- "America/Cayman",
- "America/Chicago",
- "America/Chihuahua",
- "America/Coral_Harbour",
- "America/Cordoba",
- "America/Costa_Rica",
- "America/Creston",
- "America/Cuiaba",
- "America/Curacao",
- "America/Danmarkshavn",
- "America/Dawson",
- "America/Dawson_Creek",
- "America/Denver",
- "America/Detroit",
- "America/Dominica",
- "America/Edmonton",
- "America/Eirunepe",
- "America/El_Salvador",
- "America/Ensenada",
- "America/Fort_Nelson",
- "America/Fort_Wayne",
- "America/Fortaleza",
- "America/Glace_Bay",
- "America/Godthab",
- "America/Goose_Bay",
- "America/Grand_Turk",
- "America/Grenada",
- "America/Guadeloupe",
- "America/Guatemala",
- "America/Guayaquil",
- "America/Guyana",
- "America/Halifax",
- "America/Havana",
- "America/Hermosillo",
- "America/Indiana/Indianapolis",
- "America/Indiana/Knox",
- "America/Indiana/Marengo",
- "America/Indiana/Petersburg",
- "America/Indiana/Tell_City",
- "America/Indiana/Vevay",
- "America/Indiana/Vincennes",
- "America/Indiana/Winamac",
- "America/Indianapolis",
- "America/Inuvik",
- "America/Iqaluit",
- "America/Jamaica",
- "America/Jujuy",
- "America/Juneau",
- "America/Kentucky/Louisville",
- "America/Kentucky/Monticello",
- "America/Knox_IN",
- "America/Kralendijk",
- "America/La_Paz",
- "America/Lima",
- "America/Los_Angeles",
- "America/Louisville",
- "America/Lower_Princes",
- "America/Maceio",
- "America/Managua",
- "America/Manaus",
- "America/Marigot",
- "America/Martinique",
- "America/Matamoros",
- "America/Mazatlan",
- "America/Mendoza",
- "America/Menominee",
- "America/Merida",
- "America/Metlakatla",
- "America/Mexico_City",
- "America/Miquelon",
- "America/Moncton",
- "America/Monterrey",
- "America/Montevideo",
- "America/Montreal",
- "America/Montserrat",
- "America/Nassau",
- "America/New_York",
- "America/Nipigon",
- "America/Nome",
- "America/Noronha",
- "America/North_Dakota/Beulah",
- "America/North_Dakota/Center",
- "America/North_Dakota/New_Salem",
- "America/Ojinaga",
- "America/Panama",
- "America/Pangnirtung",
- "America/Paramaribo",
- "America/Phoenix",
- "America/Port-au-Prince",
- "America/Port_of_Spain",
- "America/Porto_Acre",
- "America/Porto_Velho",
- "America/Puerto_Rico",
- "America/Punta_Arenas",
- "America/Rainy_River",
- "America/Rankin_Inlet",
- "America/Recife",
- "America/Regina",
- "America/Resolute",
- "America/Rio_Branco",
- "America/Rosario",
- "America/Santa_Isabel",
- "America/Santarem",
- "America/Santiago",
- "America/Santo_Domingo",
- "America/Sao_Paulo",
- "America/Scoresbysund",
- "America/Shiprock",
- "America/Sitka",
- "America/St_Barthelemy",
- "America/St_Johns",
- "America/St_Kitts",
- "America/St_Lucia",
- "America/St_Thomas",
- "America/St_Vincent",
- "America/Swift_Current",
- "America/Tegucigalpa",
- "America/Thule",
- "America/Thunder_Bay",
- "America/Tijuana",
- "America/Toronto",
- "America/Tortola",
- "America/Vancouver",
- "America/Virgin",
- "America/Whitehorse",
- "America/Winnipeg",
- "America/Yakutat",
- "America/Yellowknife",
- "Antarctica/Casey",
- "Antarctica/Davis",
- "Antarctica/DumontDUrville",
- "Antarctica/Macquarie",
- "Antarctica/Mawson",
- "Antarctica/McMurdo",
- "Antarctica/Palmer",
- "Antarctica/Rothera",
- "Antarctica/South_Pole",
- "Antarctica/Syowa",
- "Antarctica/Troll",
- "Antarctica/Vostok",
- "Arctic/Longyearbyen",
- "Asia/Aden",
- "Asia/Almaty",
- "Asia/Amman",
- "Asia/Anadyr",
- "Asia/Aqtau",
- "Asia/Aqtobe",
- "Asia/Ashgabat",
- "Asia/Ashkhabad",
- "Asia/Atyrau",
- "Asia/Baghdad",
- "Asia/Bahrain",
- "Asia/Baku",
- "Asia/Bangkok",
- "Asia/Barnaul",
- "Asia/Beirut",
- "Asia/Bishkek",
- "Asia/Brunei",
- "Asia/Calcutta",
- "Asia/Chita",
- "Asia/Choibalsan",
- "Asia/Chongqing",
- "Asia/Chungking",
- "Asia/Colombo",
- "Asia/Dacca",
- "Asia/Damascus",
- "Asia/Dhaka",
- "Asia/Dili",
- "Asia/Dubai",
- "Asia/Dushanbe",
- "Asia/Famagusta",
- "Asia/Gaza",
- "Asia/Harbin",
- "Asia/Hebron",
- "Asia/Ho_Chi_Minh",
- "Asia/Hong_Kong",
- "Asia/Hovd",
- "Asia/Irkutsk",
- "Asia/Istanbul",
- "Asia/Jakarta",
- "Asia/Jayapura",
- "Asia/Jerusalem",
- "Asia/Kabul",
- "Asia/Kamchatka",
- "Asia/Karachi",
- "Asia/Kashgar",
- "Asia/Kathmandu",
- "Asia/Katmandu",
- "Asia/Khandyga",
- "Asia/Kolkata",
- "Asia/Krasnoyarsk",
- "Asia/Kuala_Lumpur",
- "Asia/Kuching",
- "Asia/Kuwait",
- "Asia/Macao",
- "Asia/Macau",
- "Asia/Magadan",
- "Asia/Makassar",
- "Asia/Manila",
- "Asia/Muscat",
- "Asia/Nicosia",
- "Asia/Novokuznetsk",
- "Asia/Novosibirsk",
- "Asia/Omsk",
- "Asia/Oral",
- "Asia/Phnom_Penh",
- "Asia/Pontianak",
- "Asia/Pyongyang",
- "Asia/Qatar",
- "Asia/Qyzylorda",
- "Asia/Rangoon",
- "Asia/Riyadh",
- "Asia/Saigon",
- "Asia/Sakhalin",
- "Asia/Samarkand",
- "Asia/Seoul",
- "Asia/Shanghai",
- "Asia/Singapore",
- "Asia/Srednekolymsk",
- "Asia/Taipei",
- "Asia/Tashkent",
- "Asia/Tbilisi",
- "Asia/Tehran",
- "Asia/Tel_Aviv",
- "Asia/Thimbu",
- "Asia/Thimphu",
- "Asia/Tokyo",
- "Asia/Tomsk",
- "Asia/Ujung_Pandang",
- "Asia/Ulaanbaatar",
- "Asia/Ulan_Bator",
- "Asia/Urumqi",
- "Asia/Ust-Nera",
- "Asia/Vientiane",
- "Asia/Vladivostok",
- "Asia/Yakutsk",
- "Asia/Yangon",
- "Asia/Yekaterinburg",
- "Asia/Yerevan",
- "Atlantic/Azores",
- "Atlantic/Bermuda",
- "Atlantic/Canary",
- "Atlantic/Cape_Verde",
- "Atlantic/Faeroe",
- "Atlantic/Faroe",
- "Atlantic/Jan_Mayen",
- "Atlantic/Madeira",
- "Atlantic/Reykjavik",
- "Atlantic/South_Georgia",
- "Atlantic/St_Helena",
- "Atlantic/Stanley",
- "Australia/ACT",
- "Australia/Adelaide",
- "Australia/Brisbane",
- "Australia/Broken_Hill",
- "Australia/Canberra",
- "Australia/Currie",
- "Australia/Darwin",
- "Australia/Eucla",
- "Australia/Hobart",
- "Australia/LHI",
- "Australia/Lindeman",
- "Australia/Lord_Howe",
- "Australia/Melbourne",
- "Australia/NSW",
- "Australia/North",
- "Australia/Perth",
- "Australia/Queensland",
- "Australia/South",
- "Australia/Sydney",
- "Australia/Tasmania",
- "Australia/Victoria",
- "Australia/West",
- "Australia/Yancowinna",
- "Brazil/Acre",
- "Brazil/DeNoronha",
- "Brazil/East",
- "Brazil/West",
- "CET",
- "CST6CDT",
- "Canada/Atlantic",
- "Canada/Central",
- "Canada/Eastern",
- "Canada/Mountain",
- "Canada/Newfoundland",
- "Canada/Pacific",
- "Canada/Saskatchewan",
- "Canada/Yukon",
- "Chile/Continental",
- "Chile/EasterIsland",
- "Cuba",
- "EET",
- "EST",
- "EST5EDT",
- "Egypt",
- "Eire",
- "Etc/GMT",
- "Etc/GMT+0",
- "Etc/GMT+1",
- "Etc/GMT+10",
- "Etc/GMT+11",
- "Etc/GMT+12",
- "Etc/GMT+2",
- "Etc/GMT+3",
- "Etc/GMT+4",
- "Etc/GMT+5",
- "Etc/GMT+6",
- "Etc/GMT+7",
- "Etc/GMT+8",
- "Etc/GMT+9",
- "Etc/GMT-0",
- "Etc/GMT-1",
- "Etc/GMT-10",
- "Etc/GMT-11",
- "Etc/GMT-12",
- "Etc/GMT-13",
- "Etc/GMT-14",
- "Etc/GMT-2",
- "Etc/GMT-3",
- "Etc/GMT-4",
- "Etc/GMT-5",
- "Etc/GMT-6",
- "Etc/GMT-7",
- "Etc/GMT-8",
- "Etc/GMT-9",
- "Etc/GMT0",
- "Etc/Greenwich",
- "Etc/UCT",
- "Etc/UTC",
- "Etc/Universal",
- "Etc/Zulu",
- "Europe/Amsterdam",
- "Europe/Andorra",
- "Europe/Astrakhan",
- "Europe/Athens",
- "Europe/Belfast",
- "Europe/Belgrade",
- "Europe/Berlin",
- "Europe/Bratislava",
- "Europe/Brussels",
- "Europe/Bucharest",
- "Europe/Budapest",
- "Europe/Busingen",
- "Europe/Chisinau",
- "Europe/Copenhagen",
- "Europe/Dublin",
- "Europe/Gibraltar",
- "Europe/Guernsey",
- "Europe/Helsinki",
- "Europe/Isle_of_Man",
- "Europe/Istanbul",
- "Europe/Jersey",
- "Europe/Kaliningrad",
- "Europe/Kiev",
- "Europe/Kirov",
- "Europe/Lisbon",
- "Europe/Ljubljana",
- "Europe/London",
- "Europe/Luxembourg",
- "Europe/Madrid",
- "Europe/Malta",
- "Europe/Mariehamn",
- "Europe/Minsk",
- "Europe/Monaco",
- "Europe/Moscow",
- "Europe/Nicosia",
- "Europe/Oslo",
- "Europe/Paris",
- "Europe/Podgorica",
- "Europe/Prague",
- "Europe/Riga",
- "Europe/Rome",
- "Europe/Samara",
- "Europe/San_Marino",
- "Europe/Sarajevo",
- "Europe/Saratov",
- "Europe/Simferopol",
- "Europe/Skopje",
- "Europe/Sofia",
- "Europe/Stockholm",
- "Europe/Tallinn",
- "Europe/Tirane",
- "Europe/Tiraspol",
- "Europe/Ulyanovsk",
- "Europe/Uzhgorod",
- "Europe/Vaduz",
- "Europe/Vatican",
- "Europe/Vienna",
- "Europe/Vilnius",
- "Europe/Volgograd",
- "Europe/Warsaw",
- "Europe/Zagreb",
- "Europe/Zaporozhye",
- "Europe/Zurich",
- "GB",
- "GB-Eire",
- "GMT",
- "GMT+0",
- "GMT-0",
- "GMT0",
- "Greenwich",
- "HST",
- "Hongkong",
- "Iceland",
- "Indian/Antananarivo",
- "Indian/Chagos",
- "Indian/Christmas",
- "Indian/Cocos",
- "Indian/Comoro",
- "Indian/Kerguelen",
- "Indian/Mahe",
- "Indian/Maldives",
- "Indian/Mauritius",
- "Indian/Mayotte",
- "Indian/Reunion",
- "Iran",
- "Israel",
- "Jamaica",
- "Japan",
- "Kwajalein",
- "Libya",
- "MET",
- "MST",
- "MST7MDT",
- "Mexico/BajaNorte",
- "Mexico/BajaSur",
- "Mexico/General",
- "NZ",
- "NZ-CHAT",
- "Navajo",
- "PRC",
- "PST8PDT",
- "Pacific/Apia",
- "Pacific/Auckland",
- "Pacific/Bougainville",
- "Pacific/Chatham",
- "Pacific/Chuuk",
- "Pacific/Easter",
- "Pacific/Efate",
- "Pacific/Enderbury",
- "Pacific/Fakaofo",
- "Pacific/Fiji",
- "Pacific/Funafuti",
- "Pacific/Galapagos",
- "Pacific/Gambier",
- "Pacific/Guadalcanal",
- "Pacific/Guam",
- "Pacific/Honolulu",
- "Pacific/Johnston",
- "Pacific/Kiritimati",
- "Pacific/Kosrae",
- "Pacific/Kwajalein",
- "Pacific/Majuro",
- "Pacific/Marquesas",
- "Pacific/Midway",
- "Pacific/Nauru",
- "Pacific/Niue",
- "Pacific/Norfolk",
- "Pacific/Noumea",
- "Pacific/Pago_Pago",
- "Pacific/Palau",
- "Pacific/Pitcairn",
- "Pacific/Pohnpei",
- "Pacific/Ponape",
- "Pacific/Port_Moresby",
- "Pacific/Rarotonga",
- "Pacific/Saipan",
- "Pacific/Samoa",
- "Pacific/Tahiti",
- "Pacific/Tarawa",
- "Pacific/Tongatapu",
- "Pacific/Truk",
- "Pacific/Wake",
- "Pacific/Wallis",
- "Pacific/Yap",
- "Poland",
- "Portugal",
- "ROC",
- "ROK",
- "Singapore",
- "Turkey",
- "UCT",
- "US/Alaska",
- "US/Aleutian",
- "US/Arizona",
- "US/Central",
- "US/East-Indiana",
- "US/Eastern",
- "US/Hawaii",
- "US/Indiana-Starke",
- "US/Michigan",
- "US/Mountain",
- "US/Pacific",
- "US/Samoa",
- "UTC",
- "Universal",
- "W-SU",
- "WET",
- "Zulu",
- nullptr
-};
+const char* const kTimeZoneNames[] = {"Africa/Abidjan",
+ "Africa/Accra",
+ "Africa/Addis_Ababa",
+ "Africa/Algiers",
+ "Africa/Asmara",
+ "Africa/Asmera",
+ "Africa/Bamako",
+ "Africa/Bangui",
+ "Africa/Banjul",
+ "Africa/Bissau",
+ "Africa/Blantyre",
+ "Africa/Brazzaville",
+ "Africa/Bujumbura",
+ "Africa/Cairo",
+ "Africa/Casablanca",
+ "Africa/Ceuta",
+ "Africa/Conakry",
+ "Africa/Dakar",
+ "Africa/Dar_es_Salaam",
+ "Africa/Djibouti",
+ "Africa/Douala",
+ "Africa/El_Aaiun",
+ "Africa/Freetown",
+ "Africa/Gaborone",
+ "Africa/Harare",
+ "Africa/Johannesburg",
+ "Africa/Juba",
+ "Africa/Kampala",
+ "Africa/Khartoum",
+ "Africa/Kigali",
+ "Africa/Kinshasa",
+ "Africa/Lagos",
+ "Africa/Libreville",
+ "Africa/Lome",
+ "Africa/Luanda",
+ "Africa/Lubumbashi",
+ "Africa/Lusaka",
+ "Africa/Malabo",
+ "Africa/Maputo",
+ "Africa/Maseru",
+ "Africa/Mbabane",
+ "Africa/Mogadishu",
+ "Africa/Monrovia",
+ "Africa/Nairobi",
+ "Africa/Ndjamena",
+ "Africa/Niamey",
+ "Africa/Nouakchott",
+ "Africa/Ouagadougou",
+ "Africa/Porto-Novo",
+ "Africa/Sao_Tome",
+ "Africa/Timbuktu",
+ "Africa/Tripoli",
+ "Africa/Tunis",
+ "Africa/Windhoek",
+ "America/Adak",
+ "America/Anchorage",
+ "America/Anguilla",
+ "America/Antigua",
+ "America/Araguaina",
+ "America/Argentina/Buenos_Aires",
+ "America/Argentina/Catamarca",
+ "America/Argentina/ComodRivadavia",
+ "America/Argentina/Cordoba",
+ "America/Argentina/Jujuy",
+ "America/Argentina/La_Rioja",
+ "America/Argentina/Mendoza",
+ "America/Argentina/Rio_Gallegos",
+ "America/Argentina/Salta",
+ "America/Argentina/San_Juan",
+ "America/Argentina/San_Luis",
+ "America/Argentina/Tucuman",
+ "America/Argentina/Ushuaia",
+ "America/Aruba",
+ "America/Asuncion",
+ "America/Atikokan",
+ "America/Atka",
+ "America/Bahia",
+ "America/Bahia_Banderas",
+ "America/Barbados",
+ "America/Belem",
+ "America/Belize",
+ "America/Blanc-Sablon",
+ "America/Boa_Vista",
+ "America/Bogota",
+ "America/Boise",
+ "America/Buenos_Aires",
+ "America/Cambridge_Bay",
+ "America/Campo_Grande",
+ "America/Cancun",
+ "America/Caracas",
+ "America/Catamarca",
+ "America/Cayenne",
+ "America/Cayman",
+ "America/Chicago",
+ "America/Chihuahua",
+ "America/Coral_Harbour",
+ "America/Cordoba",
+ "America/Costa_Rica",
+ "America/Creston",
+ "America/Cuiaba",
+ "America/Curacao",
+ "America/Danmarkshavn",
+ "America/Dawson",
+ "America/Dawson_Creek",
+ "America/Denver",
+ "America/Detroit",
+ "America/Dominica",
+ "America/Edmonton",
+ "America/Eirunepe",
+ "America/El_Salvador",
+ "America/Ensenada",
+ "America/Fort_Nelson",
+ "America/Fort_Wayne",
+ "America/Fortaleza",
+ "America/Glace_Bay",
+ "America/Godthab",
+ "America/Goose_Bay",
+ "America/Grand_Turk",
+ "America/Grenada",
+ "America/Guadeloupe",
+ "America/Guatemala",
+ "America/Guayaquil",
+ "America/Guyana",
+ "America/Halifax",
+ "America/Havana",
+ "America/Hermosillo",
+ "America/Indiana/Indianapolis",
+ "America/Indiana/Knox",
+ "America/Indiana/Marengo",
+ "America/Indiana/Petersburg",
+ "America/Indiana/Tell_City",
+ "America/Indiana/Vevay",
+ "America/Indiana/Vincennes",
+ "America/Indiana/Winamac",
+ "America/Indianapolis",
+ "America/Inuvik",
+ "America/Iqaluit",
+ "America/Jamaica",
+ "America/Jujuy",
+ "America/Juneau",
+ "America/Kentucky/Louisville",
+ "America/Kentucky/Monticello",
+ "America/Knox_IN",
+ "America/Kralendijk",
+ "America/La_Paz",
+ "America/Lima",
+ "America/Los_Angeles",
+ "America/Louisville",
+ "America/Lower_Princes",
+ "America/Maceio",
+ "America/Managua",
+ "America/Manaus",
+ "America/Marigot",
+ "America/Martinique",
+ "America/Matamoros",
+ "America/Mazatlan",
+ "America/Mendoza",
+ "America/Menominee",
+ "America/Merida",
+ "America/Metlakatla",
+ "America/Mexico_City",
+ "America/Miquelon",
+ "America/Moncton",
+ "America/Monterrey",
+ "America/Montevideo",
+ "America/Montreal",
+ "America/Montserrat",
+ "America/Nassau",
+ "America/New_York",
+ "America/Nipigon",
+ "America/Nome",
+ "America/Noronha",
+ "America/North_Dakota/Beulah",
+ "America/North_Dakota/Center",
+ "America/North_Dakota/New_Salem",
+ "America/Nuuk",
+ "America/Ojinaga",
+ "America/Panama",
+ "America/Pangnirtung",
+ "America/Paramaribo",
+ "America/Phoenix",
+ "America/Port-au-Prince",
+ "America/Port_of_Spain",
+ "America/Porto_Acre",
+ "America/Porto_Velho",
+ "America/Puerto_Rico",
+ "America/Punta_Arenas",
+ "America/Rainy_River",
+ "America/Rankin_Inlet",
+ "America/Recife",
+ "America/Regina",
+ "America/Resolute",
+ "America/Rio_Branco",
+ "America/Rosario",
+ "America/Santa_Isabel",
+ "America/Santarem",
+ "America/Santiago",
+ "America/Santo_Domingo",
+ "America/Sao_Paulo",
+ "America/Scoresbysund",
+ "America/Shiprock",
+ "America/Sitka",
+ "America/St_Barthelemy",
+ "America/St_Johns",
+ "America/St_Kitts",
+ "America/St_Lucia",
+ "America/St_Thomas",
+ "America/St_Vincent",
+ "America/Swift_Current",
+ "America/Tegucigalpa",
+ "America/Thule",
+ "America/Thunder_Bay",
+ "America/Tijuana",
+ "America/Toronto",
+ "America/Tortola",
+ "America/Vancouver",
+ "America/Virgin",
+ "America/Whitehorse",
+ "America/Winnipeg",
+ "America/Yakutat",
+ "America/Yellowknife",
+ "Antarctica/Casey",
+ "Antarctica/Davis",
+ "Antarctica/DumontDUrville",
+ "Antarctica/Macquarie",
+ "Antarctica/Mawson",
+ "Antarctica/McMurdo",
+ "Antarctica/Palmer",
+ "Antarctica/Rothera",
+ "Antarctica/South_Pole",
+ "Antarctica/Syowa",
+ "Antarctica/Troll",
+ "Antarctica/Vostok",
+ "Arctic/Longyearbyen",
+ "Asia/Aden",
+ "Asia/Almaty",
+ "Asia/Amman",
+ "Asia/Anadyr",
+ "Asia/Aqtau",
+ "Asia/Aqtobe",
+ "Asia/Ashgabat",
+ "Asia/Ashkhabad",
+ "Asia/Atyrau",
+ "Asia/Baghdad",
+ "Asia/Bahrain",
+ "Asia/Baku",
+ "Asia/Bangkok",
+ "Asia/Barnaul",
+ "Asia/Beirut",
+ "Asia/Bishkek",
+ "Asia/Brunei",
+ "Asia/Calcutta",
+ "Asia/Chita",
+ "Asia/Choibalsan",
+ "Asia/Chongqing",
+ "Asia/Chungking",
+ "Asia/Colombo",
+ "Asia/Dacca",
+ "Asia/Damascus",
+ "Asia/Dhaka",
+ "Asia/Dili",
+ "Asia/Dubai",
+ "Asia/Dushanbe",
+ "Asia/Famagusta",
+ "Asia/Gaza",
+ "Asia/Harbin",
+ "Asia/Hebron",
+ "Asia/Ho_Chi_Minh",
+ "Asia/Hong_Kong",
+ "Asia/Hovd",
+ "Asia/Irkutsk",
+ "Asia/Istanbul",
+ "Asia/Jakarta",
+ "Asia/Jayapura",
+ "Asia/Jerusalem",
+ "Asia/Kabul",
+ "Asia/Kamchatka",
+ "Asia/Karachi",
+ "Asia/Kashgar",
+ "Asia/Kathmandu",
+ "Asia/Katmandu",
+ "Asia/Khandyga",
+ "Asia/Kolkata",
+ "Asia/Krasnoyarsk",
+ "Asia/Kuala_Lumpur",
+ "Asia/Kuching",
+ "Asia/Kuwait",
+ "Asia/Macao",
+ "Asia/Macau",
+ "Asia/Magadan",
+ "Asia/Makassar",
+ "Asia/Manila",
+ "Asia/Muscat",
+ "Asia/Nicosia",
+ "Asia/Novokuznetsk",
+ "Asia/Novosibirsk",
+ "Asia/Omsk",
+ "Asia/Oral",
+ "Asia/Phnom_Penh",
+ "Asia/Pontianak",
+ "Asia/Pyongyang",
+ "Asia/Qatar",
+ "Asia/Qostanay",
+ "Asia/Qyzylorda",
+ "Asia/Rangoon",
+ "Asia/Riyadh",
+ "Asia/Saigon",
+ "Asia/Sakhalin",
+ "Asia/Samarkand",
+ "Asia/Seoul",
+ "Asia/Shanghai",
+ "Asia/Singapore",
+ "Asia/Srednekolymsk",
+ "Asia/Taipei",
+ "Asia/Tashkent",
+ "Asia/Tbilisi",
+ "Asia/Tehran",
+ "Asia/Tel_Aviv",
+ "Asia/Thimbu",
+ "Asia/Thimphu",
+ "Asia/Tokyo",
+ "Asia/Tomsk",
+ "Asia/Ujung_Pandang",
+ "Asia/Ulaanbaatar",
+ "Asia/Ulan_Bator",
+ "Asia/Urumqi",
+ "Asia/Ust-Nera",
+ "Asia/Vientiane",
+ "Asia/Vladivostok",
+ "Asia/Yakutsk",
+ "Asia/Yangon",
+ "Asia/Yekaterinburg",
+ "Asia/Yerevan",
+ "Atlantic/Azores",
+ "Atlantic/Bermuda",
+ "Atlantic/Canary",
+ "Atlantic/Cape_Verde",
+ "Atlantic/Faeroe",
+ "Atlantic/Faroe",
+ "Atlantic/Jan_Mayen",
+ "Atlantic/Madeira",
+ "Atlantic/Reykjavik",
+ "Atlantic/South_Georgia",
+ "Atlantic/St_Helena",
+ "Atlantic/Stanley",
+ "Australia/ACT",
+ "Australia/Adelaide",
+ "Australia/Brisbane",
+ "Australia/Broken_Hill",
+ "Australia/Canberra",
+ "Australia/Currie",
+ "Australia/Darwin",
+ "Australia/Eucla",
+ "Australia/Hobart",
+ "Australia/LHI",
+ "Australia/Lindeman",
+ "Australia/Lord_Howe",
+ "Australia/Melbourne",
+ "Australia/NSW",
+ "Australia/North",
+ "Australia/Perth",
+ "Australia/Queensland",
+ "Australia/South",
+ "Australia/Sydney",
+ "Australia/Tasmania",
+ "Australia/Victoria",
+ "Australia/West",
+ "Australia/Yancowinna",
+ "Brazil/Acre",
+ "Brazil/DeNoronha",
+ "Brazil/East",
+ "Brazil/West",
+ "CET",
+ "CST6CDT",
+ "Canada/Atlantic",
+ "Canada/Central",
+ "Canada/Eastern",
+ "Canada/Mountain",
+ "Canada/Newfoundland",
+ "Canada/Pacific",
+ "Canada/Saskatchewan",
+ "Canada/Yukon",
+ "Chile/Continental",
+ "Chile/EasterIsland",
+ "Cuba",
+ "EET",
+ "EST",
+ "EST5EDT",
+ "Egypt",
+ "Eire",
+ "Etc/GMT",
+ "Etc/GMT+0",
+ "Etc/GMT+1",
+ "Etc/GMT+10",
+ "Etc/GMT+11",
+ "Etc/GMT+12",
+ "Etc/GMT+2",
+ "Etc/GMT+3",
+ "Etc/GMT+4",
+ "Etc/GMT+5",
+ "Etc/GMT+6",
+ "Etc/GMT+7",
+ "Etc/GMT+8",
+ "Etc/GMT+9",
+ "Etc/GMT-0",
+ "Etc/GMT-1",
+ "Etc/GMT-10",
+ "Etc/GMT-11",
+ "Etc/GMT-12",
+ "Etc/GMT-13",
+ "Etc/GMT-14",
+ "Etc/GMT-2",
+ "Etc/GMT-3",
+ "Etc/GMT-4",
+ "Etc/GMT-5",
+ "Etc/GMT-6",
+ "Etc/GMT-7",
+ "Etc/GMT-8",
+ "Etc/GMT-9",
+ "Etc/GMT0",
+ "Etc/Greenwich",
+ "Etc/UCT",
+ "Etc/UTC",
+ "Etc/Universal",
+ "Etc/Zulu",
+ "Europe/Amsterdam",
+ "Europe/Andorra",
+ "Europe/Astrakhan",
+ "Europe/Athens",
+ "Europe/Belfast",
+ "Europe/Belgrade",
+ "Europe/Berlin",
+ "Europe/Bratislava",
+ "Europe/Brussels",
+ "Europe/Bucharest",
+ "Europe/Budapest",
+ "Europe/Busingen",
+ "Europe/Chisinau",
+ "Europe/Copenhagen",
+ "Europe/Dublin",
+ "Europe/Gibraltar",
+ "Europe/Guernsey",
+ "Europe/Helsinki",
+ "Europe/Isle_of_Man",
+ "Europe/Istanbul",
+ "Europe/Jersey",
+ "Europe/Kaliningrad",
+ "Europe/Kiev",
+ "Europe/Kirov",
+ "Europe/Lisbon",
+ "Europe/Ljubljana",
+ "Europe/London",
+ "Europe/Luxembourg",
+ "Europe/Madrid",
+ "Europe/Malta",
+ "Europe/Mariehamn",
+ "Europe/Minsk",
+ "Europe/Monaco",
+ "Europe/Moscow",
+ "Europe/Nicosia",
+ "Europe/Oslo",
+ "Europe/Paris",
+ "Europe/Podgorica",
+ "Europe/Prague",
+ "Europe/Riga",
+ "Europe/Rome",
+ "Europe/Samara",
+ "Europe/San_Marino",
+ "Europe/Sarajevo",
+ "Europe/Saratov",
+ "Europe/Simferopol",
+ "Europe/Skopje",
+ "Europe/Sofia",
+ "Europe/Stockholm",
+ "Europe/Tallinn",
+ "Europe/Tirane",
+ "Europe/Tiraspol",
+ "Europe/Ulyanovsk",
+ "Europe/Uzhgorod",
+ "Europe/Vaduz",
+ "Europe/Vatican",
+ "Europe/Vienna",
+ "Europe/Vilnius",
+ "Europe/Volgograd",
+ "Europe/Warsaw",
+ "Europe/Zagreb",
+ "Europe/Zaporozhye",
+ "Europe/Zurich",
+ "GB",
+ "GB-Eire",
+ "GMT",
+ "GMT+0",
+ "GMT-0",
+ "GMT0",
+ "Greenwich",
+ "HST",
+ "Hongkong",
+ "Iceland",
+ "Indian/Antananarivo",
+ "Indian/Chagos",
+ "Indian/Christmas",
+ "Indian/Cocos",
+ "Indian/Comoro",
+ "Indian/Kerguelen",
+ "Indian/Mahe",
+ "Indian/Maldives",
+ "Indian/Mauritius",
+ "Indian/Mayotte",
+ "Indian/Reunion",
+ "Iran",
+ "Israel",
+ "Jamaica",
+ "Japan",
+ "Kwajalein",
+ "Libya",
+ "MET",
+ "MST",
+ "MST7MDT",
+ "Mexico/BajaNorte",
+ "Mexico/BajaSur",
+ "Mexico/General",
+ "NZ",
+ "NZ-CHAT",
+ "Navajo",
+ "PRC",
+ "PST8PDT",
+ "Pacific/Apia",
+ "Pacific/Auckland",
+ "Pacific/Bougainville",
+ "Pacific/Chatham",
+ "Pacific/Chuuk",
+ "Pacific/Easter",
+ "Pacific/Efate",
+ "Pacific/Enderbury",
+ "Pacific/Fakaofo",
+ "Pacific/Fiji",
+ "Pacific/Funafuti",
+ "Pacific/Galapagos",
+ "Pacific/Gambier",
+ "Pacific/Guadalcanal",
+ "Pacific/Guam",
+ "Pacific/Honolulu",
+ "Pacific/Johnston",
+ "Pacific/Kiritimati",
+ "Pacific/Kosrae",
+ "Pacific/Kwajalein",
+ "Pacific/Majuro",
+ "Pacific/Marquesas",
+ "Pacific/Midway",
+ "Pacific/Nauru",
+ "Pacific/Niue",
+ "Pacific/Norfolk",
+ "Pacific/Noumea",
+ "Pacific/Pago_Pago",
+ "Pacific/Palau",
+ "Pacific/Pitcairn",
+ "Pacific/Pohnpei",
+ "Pacific/Ponape",
+ "Pacific/Port_Moresby",
+ "Pacific/Rarotonga",
+ "Pacific/Saipan",
+ "Pacific/Samoa",
+ "Pacific/Tahiti",
+ "Pacific/Tarawa",
+ "Pacific/Tongatapu",
+ "Pacific/Truk",
+ "Pacific/Wake",
+ "Pacific/Wallis",
+ "Pacific/Yap",
+ "Poland",
+ "Portugal",
+ "ROC",
+ "ROK",
+ "Singapore",
+ "Turkey",
+ "UCT",
+ "US/Alaska",
+ "US/Aleutian",
+ "US/Arizona",
+ "US/Central",
+ "US/East-Indiana",
+ "US/Eastern",
+ "US/Hawaii",
+ "US/Indiana-Starke",
+ "US/Michigan",
+ "US/Mountain",
+ "US/Pacific",
+ "US/Samoa",
+ "UTC",
+ "Universal",
+ "W-SU",
+ "WET",
+ "Zulu",
+ nullptr};
std::vector<std::string> AllTimeZoneNames() {
std::vector<std::string> names;
@@ -941,12 +991,12 @@ void BM_Time_FromCivilDay0_Libc(benchmark::State& state) {
BENCHMARK(BM_Time_FromCivilDay0_Libc);
const char* const kFormats[] = {
- RFC1123_full, // 0
- RFC1123_no_wday, // 1
- RFC3339_full, // 2
- RFC3339_sec, // 3
- "%Y-%m-%dT%H:%M:%S", // 4
- "%Y-%m-%d", // 5
+ RFC1123_full, // 0
+ RFC1123_no_wday, // 1
+ RFC3339_full, // 2
+ RFC3339_sec, // 3
+ "%Y-%m-%d%ET%H:%M:%S", // 4
+ "%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc
index 780d5c96e8b..0b07e397e56 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_detail.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,7 +18,10 @@
#include <ostream>
#include <sstream>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
namespace detail {
@@ -87,4 +90,5 @@ std::ostream& operator<<(std::ostream& os, weekday wd) {
} // namespace detail
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
index faffde470af..a5a71230419 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,8 +21,10 @@
#include <type_traits>
#include "gtest/gtest.h"
+#include "absl/base/config.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -37,7 +39,7 @@ std::string Format(const T& t) {
} // namespace
-#if __cpp_constexpr >= 201304 || _MSC_VER >= 1910
+#if __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
// Construction constexpr tests
TEST(CivilTime, Normal) {
@@ -233,6 +235,16 @@ TEST(CivilTime, Difference) {
}
// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
+TEST(CivilTime, ConstructionWithHugeYear) {
+ constexpr civil_hour h(-9223372036854775807, 1, 1, -1);
+ static_assert(h.year() == -9223372036854775807 - 1,
+ "ConstructionWithHugeYear");
+ static_assert(h.month() == 12, "ConstructionWithHugeYear");
+ static_assert(h.day() == 31, "ConstructionWithHugeYear");
+ static_assert(h.hour() == 23, "ConstructionWithHugeYear");
+}
+
+// NOTE: Run this with --copt=-ftrapv to detect overflow problems.
TEST(CivilTime, DifferenceWithHugeYear) {
{
constexpr civil_day d1(9223372036854775807, 1, 1);
@@ -319,7 +331,7 @@ TEST(CivilTime, YearDay) {
constexpr int yd = get_yearday(cd);
static_assert(yd == 28, "YearDay");
}
-#endif // __cpp_constexpr >= 201304 || _MSC_VER >= 1910
+#endif // __cpp_constexpr >= 201304 || (defined(_MSC_VER) && _MSC_VER >= 1910)
// The remaining tests do not use constexpr.
@@ -821,6 +833,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, ss.hour());
EXPECT_EQ(5, ss.minute());
EXPECT_EQ(6, ss.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(ss));
+ EXPECT_EQ(34, get_yearday(ss));
civil_minute mm(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, mm.year());
@@ -829,6 +843,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, mm.hour());
EXPECT_EQ(5, mm.minute());
EXPECT_EQ(0, mm.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(mm));
+ EXPECT_EQ(34, get_yearday(mm));
civil_hour hh(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, hh.year());
@@ -837,6 +853,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(4, hh.hour());
EXPECT_EQ(0, hh.minute());
EXPECT_EQ(0, hh.second());
+ EXPECT_EQ(weekday::tuesday, get_weekday(hh));
+ EXPECT_EQ(34, get_yearday(hh));
civil_day d(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, d.year());
@@ -855,6 +873,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, m.hour());
EXPECT_EQ(0, m.minute());
EXPECT_EQ(0, m.second());
+ EXPECT_EQ(weekday::sunday, get_weekday(m));
+ EXPECT_EQ(32, get_yearday(m));
civil_year y(2015, 2, 3, 4, 5, 6);
EXPECT_EQ(2015, y.year());
@@ -863,6 +883,8 @@ TEST(CivilTime, Properties) {
EXPECT_EQ(0, y.hour());
EXPECT_EQ(0, y.minute());
EXPECT_EQ(0, y.second());
+ EXPECT_EQ(weekday::thursday, get_weekday(y));
+ EXPECT_EQ(1, get_yearday(y));
}
TEST(CivilTime, OutputStream) {
@@ -1004,19 +1026,13 @@ TEST(CivilTime, LeapYears) {
int day;
} leap_day; // The date of the day after Feb 28.
} kLeapYearTable[]{
- {1900, 365, {3, 1}},
- {1999, 365, {3, 1}},
+ {1900, 365, {3, 1}}, {1999, 365, {3, 1}},
{2000, 366, {2, 29}}, // leap year
- {2001, 365, {3, 1}},
- {2002, 365, {3, 1}},
- {2003, 365, {3, 1}},
- {2004, 366, {2, 29}}, // leap year
- {2005, 365, {3, 1}},
- {2006, 365, {3, 1}},
- {2007, 365, {3, 1}},
- {2008, 366, {2, 29}}, // leap year
- {2009, 365, {3, 1}},
- {2100, 365, {3, 1}},
+ {2001, 365, {3, 1}}, {2002, 365, {3, 1}},
+ {2003, 365, {3, 1}}, {2004, 366, {2, 29}}, // leap year
+ {2005, 365, {3, 1}}, {2006, 365, {3, 1}},
+ {2007, 365, {3, 1}}, {2008, 366, {2, 29}}, // leap year
+ {2009, 365, {3, 1}}, {2100, 365, {3, 1}},
};
for (const auto& e : kLeapYearTable) {
@@ -1035,7 +1051,7 @@ TEST(CivilTime, LeapYears) {
TEST(CivilTime, FirstThursdayInMonth) {
const civil_day nov1(2014, 11, 1);
- const civil_day thursday = prev_weekday(nov1, weekday::thursday) + 7;
+ const civil_day thursday = next_weekday(nov1 - 1, weekday::thursday);
EXPECT_EQ("2014-11-06", Format(thursday));
// Bonus: Date of Thanksgiving in the United States
@@ -1046,4 +1062,5 @@ TEST(CivilTime, FirstThursdayInMonth) {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
index db9a475a9b4..303c0244a82 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,14 +20,17 @@
#include <cstring>
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
namespace {
// The prefix used for the internal names of fixed-offset zones.
-const char kFixedOffsetPrefix[] = "Fixed/UTC";
+const char kFixedZonePrefix[] = "Fixed/UTC";
const char kDigits[] = "0123456789";
@@ -55,15 +58,13 @@ bool FixedOffsetFromName(const std::string& name, seconds* offset) {
return true;
}
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
- const char* const ep = kFixedOffsetPrefix + prefix_len;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ const char* const ep = kFixedZonePrefix + prefix_len;
if (name.size() != prefix_len + 9) // <prefix>+99:99:99
return false;
- if (!std::equal(kFixedOffsetPrefix, ep, name.begin()))
- return false;
+ if (!std::equal(kFixedZonePrefix, ep, name.begin())) return false;
const char* np = name.data() + prefix_len;
- if (np[0] != '+' && np[0] != '-')
- return false;
+ if (np[0] != '+' && np[0] != '-') return false;
if (np[3] != ':' || np[6] != ':') // see note below about large offsets
return false;
@@ -88,29 +89,29 @@ std::string FixedOffsetToName(const seconds& offset) {
// offsets and to (somewhat) limit the total number of zones.
return "UTC";
}
- int seconds = static_cast<int>(offset.count());
- const char sign = (seconds < 0 ? '-' : '+');
- int minutes = seconds / 60;
- seconds %= 60;
+ int offset_seconds = static_cast<int>(offset.count());
+ const char sign = (offset_seconds < 0 ? '-' : '+');
+ int offset_minutes = offset_seconds / 60;
+ offset_seconds %= 60;
if (sign == '-') {
- if (seconds > 0) {
- seconds -= 60;
- minutes += 1;
+ if (offset_seconds > 0) {
+ offset_seconds -= 60;
+ offset_minutes += 1;
}
- seconds = -seconds;
- minutes = -minutes;
+ offset_seconds = -offset_seconds;
+ offset_minutes = -offset_minutes;
}
- int hours = minutes / 60;
- minutes %= 60;
- char buf[sizeof(kFixedOffsetPrefix) - 1 + sizeof("-24:00:00")];
- std::strcpy(buf, kFixedOffsetPrefix);
- char* ep = buf + sizeof(kFixedOffsetPrefix) - 1;
+ int offset_hours = offset_minutes / 60;
+ offset_minutes %= 60;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
+ char buf[prefix_len + sizeof("-24:00:00")];
+ char* ep = std::copy(kFixedZonePrefix, kFixedZonePrefix + prefix_len, buf);
*ep++ = sign;
- ep = Format02d(ep, hours);
+ ep = Format02d(ep, offset_hours);
*ep++ = ':';
- ep = Format02d(ep, minutes);
+ ep = Format02d(ep, offset_minutes);
*ep++ = ':';
- ep = Format02d(ep, seconds);
+ ep = Format02d(ep, offset_seconds);
*ep++ = '\0';
assert(ep == buf + sizeof(buf));
return buf;
@@ -118,7 +119,7 @@ std::string FixedOffsetToName(const seconds& offset) {
std::string FixedOffsetToAbbr(const seconds& offset) {
std::string abbr = FixedOffsetToName(offset);
- const std::size_t prefix_len = sizeof(kFixedOffsetPrefix) - 1;
+ const std::size_t prefix_len = sizeof(kFixedZonePrefix) - 1;
if (abbr.size() == prefix_len + 9) { // <prefix>+99:99:99
abbr.erase(0, prefix_len); // +99:99:99
abbr.erase(6, 1); // +99:9999
@@ -135,4 +136,5 @@ std::string FixedOffsetToAbbr(const seconds& offset) {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h
index 489b857d5df..e74a0bbd9dd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,9 +17,11 @@
#include <string>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -44,6 +46,7 @@ std::string FixedOffsetToAbbr(const seconds& offset);
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_FIXED_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
index a02b1e341ac..d8cb047425e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -13,13 +13,24 @@
// limitations under the License.
#if !defined(HAS_STRPTIME)
-# if !defined(_MSC_VER)
-# define HAS_STRPTIME 1 // assume everyone has strptime() except windows
-# endif
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#define HAS_STRPTIME 1 // assume everyone has strptime() except windows
+#endif
#endif
+#if defined(HAS_STRPTIME) && HAS_STRPTIME
+#if !defined(_XOPEN_SOURCE)
+#define _XOPEN_SOURCE // Definedness suffices for strptime.
+#endif
+#endif
+
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
+// Include time.h directly since, by C++ standards, ctime doesn't have to
+// declare strptime.
+#include <time.h>
+
#include <cctype>
#include <chrono>
#include <cstddef>
@@ -38,6 +49,7 @@
#include "time_zone_if.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
namespace detail {
@@ -55,6 +67,48 @@ char* strptime(const char* s, const char* fmt, std::tm* tm) {
}
#endif
+// Convert a cctz::weekday to a tm_wday value (0-6, Sunday = 0).
+int ToTmWday(weekday wd) {
+ switch (wd) {
+ case weekday::sunday:
+ return 0;
+ case weekday::monday:
+ return 1;
+ case weekday::tuesday:
+ return 2;
+ case weekday::wednesday:
+ return 3;
+ case weekday::thursday:
+ return 4;
+ case weekday::friday:
+ return 5;
+ case weekday::saturday:
+ return 6;
+ }
+ return 0; /*NOTREACHED*/
+}
+
+// Convert a tm_wday value (0-6, Sunday = 0) to a cctz::weekday.
+weekday FromTmWday(int tm_wday) {
+ switch (tm_wday) {
+ case 0:
+ return weekday::sunday;
+ case 1:
+ return weekday::monday;
+ case 2:
+ return weekday::tuesday;
+ case 3:
+ return weekday::wednesday;
+ case 4:
+ return weekday::thursday;
+ case 5:
+ return weekday::friday;
+ case 6:
+ return weekday::saturday;
+ }
+ return weekday::sunday; /*NOTREACHED*/
+}
+
std::tm ToTM(const time_zone::absolute_lookup& al) {
std::tm tm{};
tm.tm_sec = al.cs.second();
@@ -72,34 +126,19 @@ std::tm ToTM(const time_zone::absolute_lookup& al) {
tm.tm_year = static_cast<int>(al.cs.year() - 1900);
}
- switch (get_weekday(civil_day(al.cs))) {
- case weekday::sunday:
- tm.tm_wday = 0;
- break;
- case weekday::monday:
- tm.tm_wday = 1;
- break;
- case weekday::tuesday:
- tm.tm_wday = 2;
- break;
- case weekday::wednesday:
- tm.tm_wday = 3;
- break;
- case weekday::thursday:
- tm.tm_wday = 4;
- break;
- case weekday::friday:
- tm.tm_wday = 5;
- break;
- case weekday::saturday:
- tm.tm_wday = 6;
- break;
- }
- tm.tm_yday = get_yearday(civil_day(al.cs)) - 1;
+ tm.tm_wday = ToTmWday(get_weekday(al.cs));
+ tm.tm_yday = get_yearday(al.cs) - 1;
tm.tm_isdst = al.is_dst ? 1 : 0;
return tm;
}
+// Returns the week of the year [0:53] given a civil day and the day on
+// which weeks are defined to start.
+int ToWeek(const civil_day& cd, weekday week_start) {
+ const civil_day d(cd.year() % 400, cd.month(), cd.day());
+ return static_cast<int>((d - prev_weekday(civil_year(d), week_start)) / 7);
+}
+
const char kDigits[] = "0123456789";
// Formats a 64-bit integer in the given field width. Note that it is up
@@ -149,15 +188,25 @@ char* FormatOffset(char* ep, int offset, const char* mode) {
offset = -offset; // bounded by 24h so no overflow
sign = '-';
}
- char sep = mode[0];
- if (sep != '\0' && mode[1] == '*') {
- ep = Format02d(ep, offset % 60);
+ const int seconds = offset % 60;
+ const int minutes = (offset /= 60) % 60;
+ const int hours = offset /= 60;
+ const char sep = mode[0];
+ const bool ext = (sep != '\0' && mode[1] == '*');
+ const bool ccc = (ext && mode[2] == ':');
+ if (ext && (!ccc || seconds != 0)) {
+ ep = Format02d(ep, seconds);
*--ep = sep;
+ } else {
+ // If we're not rendering seconds, sub-minute negative offsets
+ // should get a positive sign (e.g., offset=-10s => "+00:00").
+ if (hours == 0 && minutes == 0) sign = '+';
+ }
+ if (!ccc || minutes != 0 || seconds != 0) {
+ ep = Format02d(ep, minutes);
+ if (sep != '\0') *--ep = sep;
}
- int minutes = offset / 60;
- ep = Format02d(ep, minutes % 60);
- if (sep != '\0') *--ep = sep;
- ep = Format02d(ep, minutes / 60);
+ ep = Format02d(ep, hours);
*--ep = sign;
return ep;
}
@@ -167,7 +216,7 @@ void FormatTM(std::string* out, const std::string& fmt, const std::tm& tm) {
// strftime(3) returns the number of characters placed in the output
// array (which may be 0 characters). It also returns 0 to indicate
// an error, like the array wasn't large enough. To accommodate this,
- // the following code grows the buffer size from 2x the format std::string
+ // the following code grows the buffer size from 2x the format string
// length up to 32x.
for (std::size_t i = 2; i != 32; i *= 2) {
std::size_t buf_size = fmt.size() * i;
@@ -268,6 +317,7 @@ const std::int_fast64_t kExp10[kDigits10_64 + 1] = {
// - %E#S - Seconds with # digits of fractional precision
// - %E*S - Seconds with full fractional precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
// handled internally for performance reasons. strftime(3) is slow due to
@@ -332,7 +382,7 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
if (cur == end || (cur - percent) % 2 == 0) continue;
// Simple specifiers that we handle ourselves.
- if (strchr("YmdeHMSzZs%", *cur)) {
+ if (strchr("YmdeUuWwHMSzZs%", *cur)) {
if (cur - 1 != pending) {
FormatTM(&result, std::string(pending, cur - 1), tm);
}
@@ -353,6 +403,22 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
if (*cur == 'e' && *bp == '0') *bp = ' '; // for Windows
result.append(bp, static_cast<std::size_t>(ep - bp));
break;
+ case 'U':
+ bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::sunday));
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ break;
+ case 'u':
+ bp = Format64(ep, 0, tm.tm_wday ? tm.tm_wday : 7);
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ break;
+ case 'W':
+ bp = Format02d(ep, ToWeek(civil_day(al.cs), weekday::monday));
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ break;
+ case 'w':
+ bp = Format64(ep, 0, tm.tm_wday);
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ break;
case 'H':
bp = Format02d(ep, al.cs.hour());
result.append(bp, static_cast<std::size_t>(ep - bp));
@@ -384,11 +450,56 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
continue;
}
+ // More complex specifiers that we handle ourselves.
+ if (*cur == ':' && cur + 1 != end) {
+ if (*(cur + 1) == 'z') {
+ // Formats %:z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 2;
+ continue;
+ }
+ if (*(cur + 1) == ':' && cur + 2 != end) {
+ if (*(cur + 2) == 'z') {
+ // Formats %::z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":*");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 3;
+ continue;
+ }
+ if (*(cur + 2) == ':' && cur + 3 != end) {
+ if (*(cur + 3) == 'z') {
+ // Formats %:::z.
+ if (cur - 1 != pending) {
+ FormatTM(&result, std::string(pending, cur - 1), tm);
+ }
+ bp = FormatOffset(ep, al.offset, ":*:");
+ result.append(bp, static_cast<std::size_t>(ep - bp));
+ pending = cur += 4;
+ continue;
+ }
+ }
+ }
+ }
+
// Loop if there is no E modifier.
if (*cur != 'E' || ++cur == end) continue;
// Format our extensions.
- if (*cur == 'z') {
+ if (*cur == 'T') {
+ // Formats %ET.
+ if (cur - 2 != pending) {
+ FormatTM(&result, std::string(pending, cur - 2), tm);
+ }
+ result.append("T");
+ pending = ++cur;
+ } else if (*cur == 'z') {
// Formats %Ez.
if (cur - 2 != pending) {
FormatTM(&result, std::string(pending, cur - 2), tm);
@@ -444,8 +555,9 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
bp = ep;
if (n > 0) {
if (n > kDigits10_64) n = kDigits10_64;
- bp = Format64(bp, n, (n > 15) ? fs.count() * kExp10[n - 15]
- : fs.count() / kExp10[15 - n]);
+ bp = Format64(bp, n,
+ (n > 15) ? fs.count() * kExp10[n - 15]
+ : fs.count() / kExp10[15 - n]);
if (*np == 'S') *--bp = '.';
}
if (*np == 'S') bp = Format02d(bp, al.cs.second());
@@ -490,7 +602,7 @@ const char* ParseOffset(const char* dp, const char* mode, int* offset) {
} else {
dp = nullptr;
}
- } else if (first == 'Z') { // Zulu
+ } else if (first == 'Z' || first == 'z') { // Zulu
*offset = 0;
} else {
dp = nullptr;
@@ -541,12 +653,32 @@ const char* ParseTM(const char* dp, const char* fmt, std::tm* tm) {
return dp;
}
+// Sets year, tm_mon and tm_mday given the year, week_num, and tm_wday,
+// and the day on which weeks are defined to start. Returns false if year
+// would need to move outside its bounds.
+bool FromWeek(int week_num, weekday week_start, year_t* year, std::tm* tm) {
+ const civil_year y(*year % 400);
+ civil_day cd = prev_weekday(y, week_start); // week 0
+ cd = next_weekday(cd - 1, FromTmWday(tm->tm_wday)) + (week_num * 7);
+ if (const year_t shift = cd.year() - y.year()) {
+ if (shift > 0) {
+ if (*year > std::numeric_limits<year_t>::max() - shift) return false;
+ } else {
+ if (*year < std::numeric_limits<year_t>::min() - shift) return false;
+ }
+ *year += shift;
+ }
+ tm->tm_mon = cd.month() - 1;
+ tm->tm_mday = cd.day();
+ return true;
+}
+
} // namespace
// Uses strptime(3) to parse the given input. Supports the same extended
// format specifiers as format(), although %E#S and %E*S are treated
// identically (and similarly for %E#f and %E*f). %Ez and %E*z also accept
-// the same inputs.
+// the same inputs. %ET accepts either 'T' or 't'.
//
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
// handled internally so that we can normally avoid strptime() altogether
@@ -590,6 +722,8 @@ bool parse(const std::string& format, const std::string& input,
const char* fmt = format.c_str(); // NUL terminated
bool twelve_hour = false;
bool afternoon = false;
+ int week_num = -1;
+ weekday week_start = weekday::sunday;
bool saw_percent_s = false;
std::int_fast64_t percent_s = 0;
@@ -628,10 +762,27 @@ bool parse(const std::string& format, const std::string& input,
case 'm':
data = ParseInt(data, 2, 1, 12, &tm.tm_mon);
if (data != nullptr) tm.tm_mon -= 1;
+ week_num = -1;
continue;
case 'd':
case 'e':
data = ParseInt(data, 2, 1, 31, &tm.tm_mday);
+ week_num = -1;
+ continue;
+ case 'U':
+ data = ParseInt(data, 0, 0, 53, &week_num);
+ week_start = weekday::sunday;
+ continue;
+ case 'W':
+ data = ParseInt(data, 0, 0, 53, &week_num);
+ week_start = weekday::monday;
+ continue;
+ case 'u':
+ data = ParseInt(data, 0, 1, 7, &tm.tm_wday);
+ if (data != nullptr) tm.tm_wday %= 7;
+ continue;
+ case 'w':
+ data = ParseInt(data, 0, 0, 6, &tm.tm_wday);
continue;
case 'H':
data = ParseInt(data, 2, 0, 23, &tm.tm_hour);
@@ -662,23 +813,41 @@ bool parse(const std::string& format, const std::string& input,
data = ParseZone(data, &zone);
continue;
case 's':
- data = ParseInt(data, 0,
- std::numeric_limits<std::int_fast64_t>::min(),
- std::numeric_limits<std::int_fast64_t>::max(),
- &percent_s);
+ data =
+ ParseInt(data, 0, std::numeric_limits<std::int_fast64_t>::min(),
+ std::numeric_limits<std::int_fast64_t>::max(), &percent_s);
if (data != nullptr) saw_percent_s = true;
continue;
+ case ':':
+ if (fmt[0] == 'z' ||
+ (fmt[0] == ':' &&
+ (fmt[1] == 'z' || (fmt[1] == ':' && fmt[2] == 'z')))) {
+ data = ParseOffset(data, ":", &offset);
+ if (data != nullptr) saw_offset = true;
+ fmt += (fmt[0] == 'z') ? 1 : (fmt[1] == 'z') ? 2 : 3;
+ continue;
+ }
+ break;
case '%':
data = (*data == '%' ? data + 1 : nullptr);
continue;
case 'E':
- if (*fmt == 'z' || (*fmt == '*' && *(fmt + 1) == 'z')) {
+ if (fmt[0] == 'T') {
+ if (*data == 'T' || *data == 't') {
+ ++data;
+ ++fmt;
+ } else {
+ data = nullptr;
+ }
+ continue;
+ }
+ if (fmt[0] == 'z' || (fmt[0] == '*' && fmt[1] == 'z')) {
data = ParseOffset(data, ":", &offset);
if (data != nullptr) saw_offset = true;
- fmt += (*fmt == 'z') ? 1 : 2;
+ fmt += (fmt[0] == 'z') ? 1 : 2;
continue;
}
- if (*fmt == '*' && *(fmt + 1) == 'S') {
+ if (fmt[0] == '*' && fmt[1] == 'S') {
data = ParseInt(data, 2, 0, 60, &tm.tm_sec);
if (data != nullptr && *data == '.') {
data = ParseSubSeconds(data + 1, &subseconds);
@@ -686,14 +855,14 @@ bool parse(const std::string& format, const std::string& input,
fmt += 2;
continue;
}
- if (*fmt == '*' && *(fmt + 1) == 'f') {
+ if (fmt[0] == '*' && fmt[1] == 'f') {
if (data != nullptr && std::isdigit(*data)) {
data = ParseSubSeconds(data, &subseconds);
}
fmt += 2;
continue;
}
- if (*fmt == '4' && *(fmt + 1) == 'Y') {
+ if (fmt[0] == '4' && fmt[1] == 'Y') {
const char* bp = data;
data = ParseInt(data, 4, year_t{-999}, year_t{9999}, &year);
if (data != nullptr) {
@@ -769,7 +938,7 @@ bool parse(const std::string& format, const std::string& input,
// Skip any remaining whitespace.
while (std::isspace(*data)) ++data;
- // parse() must consume the entire input std::string.
+ // parse() must consume the entire input string.
if (*data != '\0') {
if (err != nullptr) *err = "Illegal trailing data in input string";
return false;
@@ -804,6 +973,14 @@ bool parse(const std::string& format, const std::string& input,
year += 1900;
}
+ // Compute year, tm.tm_mon and tm.tm_mday if we parsed a week number.
+ if (week_num != -1) {
+ if (!FromWeek(week_num, week_start, &year, &tm)) {
+ if (err != nullptr) *err = "Out-of-range field";
+ return false;
+ }
+ }
+
const int month = tm.tm_mon + 1;
civil_second cs(year, month, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
@@ -848,4 +1025,5 @@ bool parse(const std::string& format, const std::string& input,
} // namespace detail
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
index 6b9928ed32f..a11f93e2a59 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,20 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/time/internal/cctz/include/cctz/time_zone.h"
-
#include <chrono>
#include <iomanip>
#include <sstream>
#include <string>
-#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace chrono = std::chrono;
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -47,11 +48,11 @@ namespace {
EXPECT_STREQ(zone, al.abbr); \
} while (0)
-const char RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
-const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
+const char RFC3339_full[] = "%Y-%m-%d%ET%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const char RFC1123_full[] = "%a, %d %b %Y %H:%M:%S %z";
-const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
+const char RFC1123_no_wday[] = "%d %b %Y %H:%M:%S %z";
// A helper that tests the given format specifier by itself, and with leading
// and trailing characters. For example: TestFormatSpecifier(tp, "%a", "Thu").
@@ -64,17 +65,6 @@ void TestFormatSpecifier(time_point<D> tp, time_zone tz, const std::string& fmt,
EXPECT_EQ("xxx " + ans + " yyy", format("xxx " + fmt + " yyy", tp, tz));
}
-// These tests sometimes run on platforms that have zoneinfo data so old
-// that the transition we are attempting to check does not exist, most
-// notably Android emulators. Fortunately, AndroidZoneInfoSource supports
-// time_zone::version() so, in cases where we've learned that it matters,
-// we can make the check conditionally.
-int VersionCmp(time_zone tz, const std::string& target) {
- std::string version = tz.version();
- if (version.empty() && !target.empty()) return 1; // unknown > known
- return version.compare(target);
-}
-
} // namespace
//
@@ -99,8 +89,11 @@ TEST(Format, TimePointResolution) {
format(kFmt, chrono::time_point_cast<chrono::milliseconds>(t0), utc));
EXPECT_EQ("03:04:05",
format(kFmt, chrono::time_point_cast<chrono::seconds>(t0), utc));
- EXPECT_EQ("03:04:05",
- format(kFmt, chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc));
+ EXPECT_EQ(
+ "03:04:05",
+ format(kFmt,
+ chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
+ utc));
EXPECT_EQ("03:04:00",
format(kFmt, chrono::time_point_cast<chrono::minutes>(t0), utc));
EXPECT_EQ("03:00:00",
@@ -121,12 +114,10 @@ TEST(Format, TimePointExtendedResolution) {
EXPECT_EQ(
"12:34:56.012345678901234",
detail::format(kFmt, tp, detail::femtoseconds(12345678901234), utc));
- EXPECT_EQ(
- "12:34:56.001234567890123",
- detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
- EXPECT_EQ(
- "12:34:56.000123456789012",
- detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
+ EXPECT_EQ("12:34:56.001234567890123",
+ detail::format(kFmt, tp, detail::femtoseconds(1234567890123), utc));
+ EXPECT_EQ("12:34:56.000123456789012",
+ detail::format(kFmt, tp, detail::femtoseconds(123456789012), utc));
EXPECT_EQ("12:34:56.000000000000123",
detail::format(kFmt, tp, detail::femtoseconds(123), utc));
@@ -174,7 +165,9 @@ TEST(Format, PosixConversions) {
TestFormatSpecifier(tp, tz, "%M", "00");
TestFormatSpecifier(tp, tz, "%S", "00");
TestFormatSpecifier(tp, tz, "%U", "00");
+#if !defined(__EMSCRIPTEN__)
TestFormatSpecifier(tp, tz, "%w", "4"); // 4=Thursday
+#endif
TestFormatSpecifier(tp, tz, "%W", "00");
TestFormatSpecifier(tp, tz, "%y", "70");
TestFormatSpecifier(tp, tz, "%Y", "1970");
@@ -436,51 +429,165 @@ TEST(Format, CompareExtendSecondsVsSubseconds) {
}
TEST(Format, ExtendedOffset) {
- auto tp = chrono::system_clock::from_time_t(0);
+ const auto tp = chrono::system_clock::from_time_t(0);
- time_zone tz = utc_time_zone();
+ auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("America/New_York", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "-05:00");
-
- EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "-08:00");
+ tz = fixed_time_zone(chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("Australia/Sydney", &tz));
- TestFormatSpecifier(tp, tz, "%Ez", "+10:00");
+ tz = fixed_time_zone(-chrono::seconds(56)); // NOTE: +00:00
+ TestFormatSpecifier(tp, tz, "%z", "+0000");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:00");
- EXPECT_TRUE(load_time_zone("Africa/Monrovia", &tz));
- // The true offset is -00:44:30 but %z only gives (truncated) minutes.
- TestFormatSpecifier(tp, tz, "%z", "-0044");
- TestFormatSpecifier(tp, tz, "%Ez", "-00:44");
+ tz = fixed_time_zone(chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "+0034");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "-0034");
+ TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+ tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+0034");
+ TestFormatSpecifier(tp, tz, "%:z", "+00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-0034");
+ TestFormatSpecifier(tp, tz, "%:z", "-00:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-00:34");
+
+ tz = fixed_time_zone(chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%z", "+1200");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+ tz = fixed_time_zone(-chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%z", "-1200");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+1200");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:00");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-1200");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:00");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:00");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "+1234");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%z", "-1234");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "+1234");
+ TestFormatSpecifier(tp, tz, "%:z", "+12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%z", "-1234");
+ TestFormatSpecifier(tp, tz, "%:z", "-12:34");
+ TestFormatSpecifier(tp, tz, "%Ez", "-12:34");
}
TEST(Format, ExtendedSecondOffset) {
- const time_zone utc = utc_time_zone();
- time_point<chrono::seconds> tp;
- time_zone tz;
-
- EXPECT_TRUE(load_time_zone("America/New_York", &tz));
- tp = convert(civil_second(1883, 11, 18, 16, 59, 59), utc);
- if (tz.lookup(tp).offset == -5 * 60 * 60) {
- // It looks like the tzdata is only 32 bit (probably macOS),
- // which bottoms out at 1901-12-13T20:45:52+00:00.
- } else {
- TestFormatSpecifier(tp, tz, "%E*z", "-04:56:02");
- TestFormatSpecifier(tp, tz, "%Ez", "-04:56");
- }
- tp += chrono::seconds(1);
- TestFormatSpecifier(tp, tz, "%E*z", "-05:00:00");
-
- EXPECT_TRUE(load_time_zone("Europe/Moscow", &tz));
- tp = convert(civil_second(1919, 6, 30, 23, 59, 59), utc);
- if (VersionCmp(tz, "2016g") >= 0) {
- TestFormatSpecifier(tp, tz, "%E*z", "+04:31:19");
- TestFormatSpecifier(tp, tz, "%Ez", "+04:31");
- }
- tp += chrono::seconds(1);
- TestFormatSpecifier(tp, tz, "%E*z", "+04:00:00");
+ const auto tp = chrono::system_clock::from_time_t(0);
+
+ auto tz = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00");
+
+ tz = fixed_time_zone(chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:00:56");
+
+ tz = fixed_time_zone(-chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:00:56");
+
+ tz = fixed_time_zone(chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:34");
+
+ tz = fixed_time_zone(-chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:34");
+
+ tz = fixed_time_zone(chrono::minutes(34) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+00:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+00:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+00:34:56");
+
+ tz = fixed_time_zone(-chrono::minutes(34) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-00:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-00:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-00:34:56");
+
+ tz = fixed_time_zone(chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12");
+
+ tz = fixed_time_zone(-chrono::hours(12));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:00:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:00:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:00:56");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:00:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:00:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:00:56");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:34");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:34:00");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:34:00");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:34");
+
+ tz = fixed_time_zone(chrono::hours(12) + chrono::minutes(34) +
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "+12:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "+12:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "+12:34:56");
+
+ tz = fixed_time_zone(-chrono::hours(12) - chrono::minutes(34) -
+ chrono::seconds(56));
+ TestFormatSpecifier(tp, tz, "%E*z", "-12:34:56");
+ TestFormatSpecifier(tp, tz, "%::z", "-12:34:56");
+ TestFormatSpecifier(tp, tz, "%:::z", "-12:34:56");
}
TEST(Format, ExtendedYears) {
@@ -572,6 +679,34 @@ TEST(Format, RFC1123Format) { // locale specific
EXPECT_EQ("28 Jun 1977 09:08:07 -0700", format(RFC1123_no_wday, tp, tz));
}
+TEST(Format, Week) {
+ const time_zone utc = utc_time_zone();
+
+ auto tp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
+ EXPECT_EQ("2017-01-7", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2017-00-0", format("%Y-%W-%w", tp, utc));
+
+ tp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
+ EXPECT_EQ("2017-53-7", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2017-52-0", format("%Y-%W-%w", tp, utc));
+
+ tp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
+ EXPECT_EQ("2018-00-1", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2018-01-1", format("%Y-%W-%w", tp, utc));
+
+ tp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
+ EXPECT_EQ("2018-52-1", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2018-53-1", format("%Y-%W-%w", tp, utc));
+
+ tp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
+ EXPECT_EQ("2019-00-2", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2019-00-2", format("%Y-%W-%w", tp, utc));
+
+ tp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+ EXPECT_EQ("2019-52-2", format("%Y-%U-%u", tp, utc));
+ EXPECT_EQ("2019-52-2", format("%Y-%W-%w", tp, utc));
+}
+
//
// Testing parse()
//
@@ -660,7 +795,7 @@ TEST(Parse, WithTimeZone) {
EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
time_point<chrono::nanoseconds> tp;
- // We can parse a std::string without a UTC offset if we supply a timezone.
+ // We can parse a string without a UTC offset if we supply a timezone.
EXPECT_TRUE(parse("%Y-%m-%d %H:%M:%S", "2013-06-28 19:08:09", tz, &tp));
ExpectTime(tp, tz, 2013, 6, 28, 19, 8, 9, -7 * 60 * 60, true, "PDT");
@@ -1145,9 +1280,9 @@ TEST(Parse, ExtendedSubecondsScan) {
const auto expected = chrono::system_clock::from_time_t(0) +
chrono::nanoseconds(micros * 1000 + ns);
for (int ps = 0; ps < 1000; ps += 250) {
- std::ostringstream oss;
+ std::ostringstream ps_oss;
oss << std::setfill('0') << std::setw(3) << ps;
- const std::string input = nanos + oss.str() + "999";
+ const std::string input = nanos + ps_oss.str() + "999";
EXPECT_TRUE(parse("%E*f", input, tz, &tp));
EXPECT_EQ(expected + chrono::nanoseconds(ps) / 1000, tp) << input;
}
@@ -1160,25 +1295,6 @@ TEST(Parse, ExtendedOffset) {
const time_zone utc = utc_time_zone();
time_point<absl::time_internal::cctz::seconds> tp;
- // %z against +-HHMM.
- EXPECT_TRUE(parse("%z", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%z", "-123", utc, &tp));
-
- // %z against +-HH.
- EXPECT_TRUE(parse("%z", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%z", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%z", "-1", utc, &tp));
-
- // %Ez against +-HH:MM.
EXPECT_TRUE(parse("%Ez", "+00:00", utc, &tp));
EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
EXPECT_TRUE(parse("%Ez", "-12:34", utc, &tp));
@@ -1187,91 +1303,70 @@ TEST(Parse, ExtendedOffset) {
EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
EXPECT_FALSE(parse("%Ez", "-12:3", utc, &tp));
- // %Ez against +-HHMM.
- EXPECT_TRUE(parse("%Ez", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-123", utc, &tp));
-
- // %Ez against +-HH.
- EXPECT_TRUE(parse("%Ez", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-1", utc, &tp));
+ for (auto fmt : {"%Ez", "%z"}) {
+ EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+ }
}
TEST(Parse, ExtendedSecondOffset) {
const time_zone utc = utc_time_zone();
time_point<absl::time_internal::cctz::seconds> tp;
- // %Ez against +-HH:MM:SS.
- EXPECT_TRUE(parse("%Ez", "+00:00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-12:34:5", utc, &tp));
-
- // %Ez against +-HHMMSS.
- EXPECT_TRUE(parse("%Ez", "+000000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%Ez", "-123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%Ez", "+123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%Ez", "-12345", utc, &tp));
-
- // %E*z against +-HH:MM:SS.
- EXPECT_TRUE(parse("%E*z", "+00:00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12:34:56", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12:34:5", utc, &tp));
-
- // %E*z against +-HHMMSS.
- EXPECT_TRUE(parse("%E*z", "+000000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+123456", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12345", utc, &tp));
-
- // %E*z against +-HH:MM.
- EXPECT_TRUE(parse("%E*z", "+00:00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12:34", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12:34", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-12:3", utc, &tp));
-
- // %E*z against +-HHMM.
- EXPECT_TRUE(parse("%E*z", "+0000", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+1234", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-123", utc, &tp));
-
- // %E*z against +-HH.
- EXPECT_TRUE(parse("%E*z", "+00", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "-12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
- EXPECT_TRUE(parse("%E*z", "+12", utc, &tp));
- EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
- EXPECT_FALSE(parse("%E*z", "-1", utc, &tp));
+ for (auto fmt : {"%Ez", "%E*z", "%:z", "%::z", "%:::z"}) {
+ EXPECT_TRUE(parse(fmt, "+00:00:00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12:34:56", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12:34:56", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12:34:5", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+000000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-123456", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 56), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+123456", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 25, 4), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12345", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00:00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12:34", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12:34", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-12:3", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+0000", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 34, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+1234", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 11, 26, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-123", utc, &tp));
+
+ EXPECT_TRUE(parse(fmt, "+00", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 0, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "-12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1970, 1, 1, 12, 0, 0), utc), tp);
+ EXPECT_TRUE(parse(fmt, "+12", utc, &tp));
+ EXPECT_EQ(convert(civil_second(1969, 12, 31, 12, 0, 0), utc), tp);
+ EXPECT_FALSE(parse(fmt, "-1", utc, &tp));
+ }
}
TEST(Parse, ExtendedYears) {
@@ -1312,10 +1407,85 @@ TEST(Parse, RFC3339Format) {
EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00+00:00", tz, &tp));
ExpectTime(tp, tz, 2014, 2, 12, 20, 21, 0, 0, false, "UTC");
- // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+ // Check that %ET also accepts "t".
time_point<chrono::nanoseconds> tp2;
- EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp2));
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
EXPECT_EQ(tp, tp2);
+
+ // Check that %Ez also accepts "Z" as a synonym for "+00:00".
+ time_point<chrono::nanoseconds> tp3;
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", tz, &tp3));
+ EXPECT_EQ(tp, tp3);
+
+ // Check that %Ez also accepts "z" as a synonym for "+00:00".
+ time_point<chrono::nanoseconds> tp4;
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00z", tz, &tp4));
+ EXPECT_EQ(tp, tp4);
+}
+
+TEST(Parse, Week) {
+ const time_zone utc = utc_time_zone();
+ time_point<absl::time_internal::cctz::seconds> tp;
+
+ auto exp = convert(civil_second(2017, 1, 1, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2017-01-7", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2017-00-0", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2017, 12, 31, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2017-53-7", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2017-52-0", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2018, 1, 1, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2018-00-1", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2018-01-1", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2018, 12, 31, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2018-52-1", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2018-53-1", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2019, 1, 1, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2019-00-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2019-00-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2019-52-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2019-52-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+}
+
+TEST(Parse, WeekYearShift) {
+ // %U/%W conversions with week values in {0, 52, 53} can slip
+ // into the previous/following calendar years.
+ const time_zone utc = utc_time_zone();
+ time_point<absl::time_internal::cctz::seconds> tp;
+
+ auto exp = convert(civil_second(2019, 12, 31, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2020-00-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2020-00-2", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ exp = convert(civil_second(2021, 1, 1, 0, 0, 0), utc);
+ EXPECT_TRUE(parse("%Y-%U-%u", "2020-52-5", utc, &tp));
+ EXPECT_EQ(exp, tp);
+ EXPECT_TRUE(parse("%Y-%W-%w", "2020-52-5", utc, &tp));
+ EXPECT_EQ(exp, tp);
+
+ // Slipping into the previous/following calendar years should fail when
+ // we're already at the extremes.
+ EXPECT_FALSE(parse("%Y-%U-%u", "-9223372036854775808-0-7", utc, &tp));
+ EXPECT_FALSE(parse("%Y-%U-%u", "9223372036854775807-53-7", utc, &tp));
}
TEST(Parse, MaxRange) {
@@ -1351,8 +1521,8 @@ TEST(Parse, MaxRange) {
parse(RFC3339_sec, "-292277022657-01-27T08:29:51+01:00", utc, &tp));
// tests max/min civil-second overflow
- EXPECT_FALSE(parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01",
- utc, &tp));
+ EXPECT_FALSE(
+ parse(RFC3339_sec, "9223372036854775807-12-31T23:59:59-00:01", utc, &tp));
EXPECT_FALSE(parse(RFC3339_sec, "-9223372036854775808-01-01T00:00:00+00:01",
utc, &tp));
@@ -1390,6 +1560,10 @@ TEST(FormatParse, RoundTrip) {
#if defined(_WIN32) || defined(_WIN64)
// Initial investigations indicate the %c does not roundtrip on Windows.
// TODO: Figure out what is going on here (perhaps a locale problem).
+#elif defined(__EMSCRIPTEN__)
+ // strftime() and strptime() use different defintions for "%c" under
+ // emscripten (see https://github.com/kripken/emscripten/pull/7491),
+ // causing its round-trip test to fail.
#else
// Even though we don't know what %c will produce, it should roundtrip,
// but only in the 0-offset timezone.
@@ -1405,7 +1579,8 @@ TEST(FormatParse, RoundTrip) {
TEST(FormatParse, RoundTripDistantFuture) {
const time_zone utc = utc_time_zone();
- const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::max();
+ const time_point<absl::time_internal::cctz::seconds> in =
+ time_point<absl::time_internal::cctz::seconds>::max();
const std::string s = format(RFC3339_full, in, utc);
time_point<absl::time_internal::cctz::seconds> out;
EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@@ -1414,7 +1589,8 @@ TEST(FormatParse, RoundTripDistantFuture) {
TEST(FormatParse, RoundTripDistantPast) {
const time_zone utc = utc_time_zone();
- const time_point<absl::time_internal::cctz::seconds> in = time_point<absl::time_internal::cctz::seconds>::min();
+ const time_point<absl::time_internal::cctz::seconds> in =
+ time_point<absl::time_internal::cctz::seconds>::min();
const std::string s = format(RFC3339_full, in, utc);
time_point<absl::time_internal::cctz::seconds> out;
EXPECT_TRUE(parse(RFC3339_full, s, utc, &out)) << s;
@@ -1423,4 +1599,5 @@ TEST(FormatParse, RoundTripDistantPast) {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc
index 380834a172a..0319b2f98e6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -13,10 +13,13 @@
// limitations under the License.
#include "time_zone_if.h"
+
+#include "absl/base/config.h"
#include "time_zone_info.h"
#include "time_zone_libc.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -38,4 +41,5 @@ TimeZoneIf::~TimeZoneIf() {}
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
index e4bd3866a87..32c0891c1e7 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,10 +20,12 @@
#include <memory>
#include <string>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -38,8 +40,7 @@ class TimeZoneIf {
virtual time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const = 0;
- virtual time_zone::civil_lookup MakeTime(
- const civil_second& cs) const = 0;
+ virtual time_zone::civil_lookup MakeTime(const civil_second& cs) const = 0;
virtual bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const = 0;
@@ -58,15 +59,18 @@ class TimeZoneIf {
// Unix clock are second aligned, but not that they share an epoch.
inline std::int_fast64_t ToUnixSeconds(const time_point<seconds>& tp) {
return (tp - std::chrono::time_point_cast<seconds>(
- std::chrono::system_clock::from_time_t(0))).count();
+ std::chrono::system_clock::from_time_t(0)))
+ .count();
}
inline time_point<seconds> FromUnixSeconds(std::int_fast64_t t) {
return std::chrono::time_point_cast<seconds>(
- std::chrono::system_clock::from_time_t(0)) + seconds(t);
+ std::chrono::system_clock::from_time_t(0)) +
+ seconds(t);
}
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IF_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
index 3062ccd3ceb..f34e3aec84d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,14 +14,18 @@
#include "time_zone_impl.h"
+#include <deque>
+#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
+#include "absl/base/config.h"
#include "time_zone_fixed.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -33,28 +37,30 @@ using TimeZoneImplByName =
TimeZoneImplByName* time_zone_map = nullptr;
// Mutual exclusion for time_zone_map.
-std::mutex time_zone_mutex;
+std::mutex& TimeZoneMutex() {
+ // This mutex is intentionally "leaked" to avoid the static deinitialization
+ // order fiasco (std::mutex's destructor is not trivial on many platforms).
+ static std::mutex* time_zone_mutex = new std::mutex;
+ return *time_zone_mutex;
+}
} // namespace
-time_zone time_zone::Impl::UTC() {
- return time_zone(UTCImpl());
-}
+time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }
bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
- const time_zone::Impl* const utc_impl = UTCImpl();
+ const Impl* const utc_impl = UTCImpl();
- // First check for UTC (which is never a key in time_zone_map).
+ // Check for UTC (which is never a key in time_zone_map).
auto offset = seconds::zero();
if (FixedOffsetFromName(name, &offset) && offset == seconds::zero()) {
*tz = time_zone(utc_impl);
return true;
}
- // Then check, under a shared lock, whether the time zone has already
- // been loaded. This is the common path. TODO: Move to shared_mutex.
+ // Check whether the time zone has already been loaded.
{
- std::lock_guard<std::mutex> lock(time_zone_mutex);
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
if (time_zone_map != nullptr) {
TimeZoneImplByName::const_iterator itr = time_zone_map->find(name);
if (itr != time_zone_map->end()) {
@@ -64,45 +70,44 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
}
}
- // Now check again, under an exclusive lock.
- std::lock_guard<std::mutex> lock(time_zone_mutex);
+ // Load the new time zone (outside the lock).
+ std::unique_ptr<const Impl> new_impl(new Impl(name));
+
+ // Add the new time zone to the map.
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
if (time_zone_map == nullptr) time_zone_map = new TimeZoneImplByName;
const Impl*& impl = (*time_zone_map)[name];
- if (impl == nullptr) {
- // The first thread in loads the new time zone.
- Impl* new_impl = new Impl(name);
- new_impl->zone_ = TimeZoneIf::Load(new_impl->name_);
- if (new_impl->zone_ == nullptr) {
- delete new_impl; // free the nascent Impl
- impl = utc_impl; // and fallback to UTC
- } else {
- impl = new_impl; // install new time zone
- }
+ if (impl == nullptr) { // this thread won any load race
+ impl = new_impl->zone_ ? new_impl.release() : utc_impl;
}
*tz = time_zone(impl);
return impl != utc_impl;
}
void time_zone::Impl::ClearTimeZoneMapTestOnly() {
- std::lock_guard<std::mutex> lock(time_zone_mutex);
+ std::lock_guard<std::mutex> lock(TimeZoneMutex());
if (time_zone_map != nullptr) {
- // Existing time_zone::Impl* entries are in the wild, so we simply
- // leak them. Future requests will result in reloading the data.
+ // Existing time_zone::Impl* entries are in the wild, so we can't delete
+ // them. Instead, we move them to a private container, where they are
+ // logically unreachable but not "leaked". Future requests will result
+ // in reloading the data.
+ static auto* cleared = new std::deque<const time_zone::Impl*>;
+ for (const auto& element : *time_zone_map) {
+ cleared->push_back(element.second);
+ }
time_zone_map->clear();
}
}
-time_zone::Impl::Impl(const std::string& name) : name_(name) {}
+time_zone::Impl::Impl(const std::string& name)
+ : name_(name), zone_(TimeZoneIf::Load(name_)) {}
const time_zone::Impl* time_zone::Impl::UTCImpl() {
- static Impl* utc_impl = [] {
- Impl* impl = new Impl("UTC");
- impl->zone_ = TimeZoneIf::Load(impl->name_); // never fails
- return impl;
- }();
+ static const Impl* utc_impl = new Impl("UTC"); // never fails
return utc_impl;
}
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
index 14965ef54bf..7d747ba9661 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,12 +18,14 @@
#include <memory>
#include <string>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#include "time_zone_if.h"
#include "time_zone_info.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -69,7 +71,7 @@ class time_zone::Impl {
return zone_->PrevTransition(tp, trans);
}
- // Returns an implementation-defined version std::string for this time zone.
+ // Returns an implementation-defined version string for this time zone.
std::string Version() const { return zone_->Version(); }
// Returns an implementation-defined description of this time zone.
@@ -85,6 +87,7 @@ class time_zone::Impl {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_IMPL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
index 2cb358d048e..8039353e585 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,7 +25,7 @@
// a grain of salt.
//
// For more information see tzfile(5), http://www.iana.org/time-zones, or
-// http://en.wikipedia.org/wiki/Zoneinfo.
+// https://en.wikipedia.org/wiki/Zoneinfo.
//
// Note that we assume the proleptic Gregorian calendar and 60-second
// minutes throughout.
@@ -40,16 +40,17 @@
#include <cstdlib>
#include <cstring>
#include <functional>
-#include <iostream>
#include <memory>
#include <sstream>
#include <string>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "time_zone_fixed.h"
#include "time_zone_posix.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -65,8 +66,8 @@ const std::int_least32_t kDaysPerYear[2] = {365, 366};
// The day offsets of the beginning of each (1-based) month in non-leap and
// leap years respectively (e.g., 335 days before December in a leap year).
const std::int_least16_t kMonthOffsets[2][1 + 12 + 1] = {
- {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
- {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
+ {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
+ {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
};
// We reject leap-second encoded zoneinfo and so assume 60-second minutes.
@@ -77,10 +78,31 @@ const std::int_least64_t kSecsPer400Years = 146097LL * kSecsPerDay;
// Like kDaysPerYear[] but scaled up by a factor of kSecsPerDay.
const std::int_least32_t kSecsPerYear[2] = {
- 365 * kSecsPerDay,
- 366 * kSecsPerDay,
+ 365 * kSecsPerDay,
+ 366 * kSecsPerDay,
};
+// Convert a cctz::weekday to a POSIX TZ weekday number (0==Sun, ..., 6=Sat).
+inline int ToPosixWeekday(weekday wd) {
+ switch (wd) {
+ case weekday::sunday:
+ return 0;
+ case weekday::monday:
+ return 1;
+ case weekday::tuesday:
+ return 2;
+ case weekday::wednesday:
+ return 3;
+ case weekday::thursday:
+ return 4;
+ case weekday::friday:
+ return 5;
+ case weekday::saturday:
+ return 6;
+ }
+ return 0; /*NOTREACHED*/
+}
+
// Single-byte, unsigned numeric values are encoded directly.
inline std::uint_fast8_t Decode8(const char* cp) {
return static_cast<std::uint_fast8_t>(*cp) & 0xff;
@@ -172,8 +194,8 @@ inline time_zone::civil_lookup MakeRepeated(const Transition& tr,
}
inline civil_second YearShift(const civil_second& cs, year_t shift) {
- return civil_second(cs.year() + shift, cs.month(), cs.day(),
- cs.hour(), cs.minute(), cs.second());
+ return civil_second(cs.year() + shift, cs.month(), cs.day(), cs.hour(),
+ cs.minute(), cs.second());
}
} // namespace
@@ -186,15 +208,13 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
tt.is_dst = false;
tt.abbr_index = 0;
- // We temporarily add some redundant, contemporary (2013 through 2023)
+ // We temporarily add some redundant, contemporary (2015 through 2025)
// transitions for performance reasons. See TimeZoneInfo::LocalTime().
// TODO: Fix the performance issue and remove the extra transitions.
transitions_.clear();
transitions_.reserve(12);
for (const std::int_fast64_t unix_time : {
- -(1LL << 59), // BIG_BANG
- 1356998400LL, // 2013-01-01T00:00:00+00:00
- 1388534400LL, // 2014-01-01T00:00:00+00:00
+ -(1LL << 59), // a "first half" transition
1420070400LL, // 2015-01-01T00:00:00+00:00
1451606400LL, // 2016-01-01T00:00:00+00:00
1483228800LL, // 2017-01-01T00:00:00+00:00
@@ -204,7 +224,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
1609459200LL, // 2021-01-01T00:00:00+00:00
1640995200LL, // 2022-01-01T00:00:00+00:00
1672531200LL, // 2023-01-01T00:00:00+00:00
- 2147483647LL, // 2^31 - 1
+ 1704067200LL, // 2024-01-01T00:00:00+00:00
+ 1735689600LL, // 2025-01-01T00:00:00+00:00
}) {
Transition& tr(*transitions_.emplace(transitions_.end()));
tr.unix_time = unix_time;
@@ -215,7 +236,7 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
default_transition_type_ = 0;
abbreviations_ = FixedOffsetToAbbr(offset);
- abbreviations_.append(1, '\0'); // add NUL
+ abbreviations_.append(1, '\0');
future_spec_.clear(); // never needed for a fixed-offset zone
extended_ = false;
@@ -239,8 +260,8 @@ bool TimeZoneInfo::Header::Build(const tzhead& tzh) {
leapcnt = static_cast<std::size_t>(v);
if ((v = Decode32(tzh.tzh_ttisstdcnt)) < 0) return false;
ttisstdcnt = static_cast<std::size_t>(v);
- if ((v = Decode32(tzh.tzh_ttisgmtcnt)) < 0) return false;
- ttisgmtcnt = static_cast<std::size_t>(v);
+ if ((v = Decode32(tzh.tzh_ttisutcnt)) < 0) return false;
+ ttisutcnt = static_cast<std::size_t>(v);
return true;
}
@@ -253,25 +274,10 @@ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const {
len += 1 * charcnt; // abbreviations
len += (time_len + 4) * leapcnt; // leap-time + TAI-UTC
len += 1 * ttisstdcnt; // UTC/local indicators
- len += 1 * ttisgmtcnt; // standard/wall indicators
+ len += 1 * ttisutcnt; // standard/wall indicators
return len;
}
-// Check that the TransitionType has the expected offset/is_dst/abbreviation.
-void TimeZoneInfo::CheckTransition(const std::string& name,
- const TransitionType& tt,
- std::int_fast32_t offset, bool is_dst,
- const std::string& abbr) const {
- if (tt.utc_offset != offset || tt.is_dst != is_dst ||
- &abbreviations_[tt.abbr_index] != abbr) {
- std::clog << name << ": Transition"
- << " offset=" << tt.utc_offset << "/"
- << (tt.is_dst ? "DST" : "STD")
- << "/abbr=" << &abbreviations_[tt.abbr_index]
- << " does not match POSIX spec '" << future_spec_ << "'\n";
- }
-}
-
// zic(8) can generate no-op transitions when a zone changes rules at an
// instant when there is actually no discontinuity. So we check whether
// two transitions have equivalent types (same offset/is_dst/abbr).
@@ -280,144 +286,128 @@ bool TimeZoneInfo::EquivTransitions(std::uint_fast8_t tt1_index,
if (tt1_index == tt2_index) return true;
const TransitionType& tt1(transition_types_[tt1_index]);
const TransitionType& tt2(transition_types_[tt2_index]);
- if (tt1.is_dst != tt2.is_dst) return false;
if (tt1.utc_offset != tt2.utc_offset) return false;
+ if (tt1.is_dst != tt2.is_dst) return false;
if (tt1.abbr_index != tt2.abbr_index) return false;
return true;
}
+// Find/make a transition type with these attributes.
+bool TimeZoneInfo::GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+ const std::string& abbr,
+ std::uint_least8_t* index) {
+ std::size_t type_index = 0;
+ std::size_t abbr_index = abbreviations_.size();
+ for (; type_index != transition_types_.size(); ++type_index) {
+ const TransitionType& tt(transition_types_[type_index]);
+ const char* tt_abbr = &abbreviations_[tt.abbr_index];
+ if (tt_abbr == abbr) abbr_index = tt.abbr_index;
+ if (tt.utc_offset == utc_offset && tt.is_dst == is_dst) {
+ if (abbr_index == tt.abbr_index) break; // reuse
+ }
+ }
+ if (type_index > 255 || abbr_index > 255) {
+ // No index space (8 bits) available for a new type or abbreviation.
+ return false;
+ }
+ if (type_index == transition_types_.size()) {
+ TransitionType& tt(*transition_types_.emplace(transition_types_.end()));
+ tt.utc_offset = static_cast<std::int_least32_t>(utc_offset);
+ tt.is_dst = is_dst;
+ if (abbr_index == abbreviations_.size()) {
+ abbreviations_.append(abbr);
+ abbreviations_.append(1, '\0');
+ }
+ tt.abbr_index = static_cast<std::uint_least8_t>(abbr_index);
+ }
+ *index = static_cast<std::uint_least8_t>(type_index);
+ return true;
+}
+
// Use the POSIX-TZ-environment-variable-style string to handle times
// in years after the last transition stored in the zoneinfo data.
-void TimeZoneInfo::ExtendTransitions(const std::string& name,
- const Header& hdr) {
+bool TimeZoneInfo::ExtendTransitions() {
extended_ = false;
- bool extending = !future_spec_.empty();
+ if (future_spec_.empty()) return true; // last transition prevails
PosixTimeZone posix;
- if (extending && !ParsePosixSpec(future_spec_, &posix)) {
- std::clog << name << ": Failed to parse '" << future_spec_ << "'\n";
- extending = false;
- }
-
- if (extending && posix.dst_abbr.empty()) { // std only
- // The future specification should match the last/default transition,
- // and that means that handling the future will fall out naturally.
- std::uint_fast8_t index = default_transition_type_;
- if (hdr.timecnt != 0) index = transitions_[hdr.timecnt - 1].type_index;
- const TransitionType& tt(transition_types_[index]);
- CheckTransition(name, tt, posix.std_offset, false, posix.std_abbr);
- extending = false;
- }
-
- if (extending && hdr.timecnt < 2) {
- std::clog << name << ": Too few transitions for POSIX spec\n";
- extending = false;
- }
-
- if (!extending) {
- // Ensure that there is always a transition in the second half of the
- // time line (the BIG_BANG transition is in the first half) so that the
- // signed difference between a civil_second and the civil_second of its
- // previous transition is always representable, without overflow.
- const Transition& last(transitions_.back());
- if (last.unix_time < 0) {
- const std::uint_fast8_t type_index = last.type_index;
- Transition& tr(*transitions_.emplace(transitions_.end()));
- tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00
- tr.type_index = type_index;
- }
- return; // last transition wins
+ if (!ParsePosixSpec(future_spec_, &posix)) return false;
+
+ // Find transition type for the future std specification.
+ std::uint_least8_t std_ti;
+ if (!GetTransitionType(posix.std_offset, false, posix.std_abbr, &std_ti))
+ return false;
+
+ if (posix.dst_abbr.empty()) { // std only
+ // The future specification should match the last transition, and
+ // that means that handling the future will fall out naturally.
+ return EquivTransitions(transitions_.back().type_index, std_ti);
}
+ // Find transition type for the future dst specification.
+ std::uint_least8_t dst_ti;
+ if (!GetTransitionType(posix.dst_offset, true, posix.dst_abbr, &dst_ti))
+ return false;
+
// Extend the transitions for an additional 400 years using the
// future specification. Years beyond those can be handled by
// mapping back to a cycle-equivalent year within that range.
- // zic(8) should probably do this so that we don't have to.
- // TODO: Reduce the extension by the number of compatible
- // transitions already in place.
- transitions_.reserve(hdr.timecnt + 400 * 2 + 1);
- transitions_.resize(hdr.timecnt + 400 * 2);
+ // We may need two additional transitions for the current year.
+ transitions_.reserve(transitions_.size() + 400 * 2 + 2);
extended_ = true;
- // The future specification should match the last two transitions,
- // and those transitions should have different is_dst flags. Note
- // that nothing says the UTC offset used by the is_dst transition
- // must be greater than that used by the !is_dst transition. (See
- // Europe/Dublin, for example.)
- const Transition* tr0 = &transitions_[hdr.timecnt - 1];
- const Transition* tr1 = &transitions_[hdr.timecnt - 2];
- const TransitionType* tt0 = &transition_types_[tr0->type_index];
- const TransitionType* tt1 = &transition_types_[tr1->type_index];
- const TransitionType& dst(tt0->is_dst ? *tt0 : *tt1);
- const TransitionType& std(tt0->is_dst ? *tt1 : *tt0);
- CheckTransition(name, dst, posix.dst_offset, true, posix.dst_abbr);
- CheckTransition(name, std, posix.std_offset, false, posix.std_abbr);
-
- // Add the transitions to tr1 and back to tr0 for each extra year.
- last_year_ = LocalTime(tr0->unix_time, *tt0).cs.year();
+ const Transition& last(transitions_.back());
+ const std::int_fast64_t last_time = last.unix_time;
+ const TransitionType& last_tt(transition_types_[last.type_index]);
+ last_year_ = LocalTime(last_time, last_tt).cs.year();
bool leap_year = IsLeap(last_year_);
- const civil_day jan1(last_year_, 1, 1);
- std::int_fast64_t jan1_time = civil_second(jan1) - civil_second();
- int jan1_weekday = (static_cast<int>(get_weekday(jan1)) + 1) % 7;
- Transition* tr = &transitions_[hdr.timecnt]; // next trans to fill
- if (LocalTime(tr1->unix_time, *tt1).cs.year() != last_year_) {
- // Add a single extra transition to align to a calendar year.
- transitions_.resize(transitions_.size() + 1);
- assert(tr == &transitions_[hdr.timecnt]); // no reallocation
- const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
- std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
- tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
- tr++->type_index = tr1->type_index;
- tr0 = &transitions_[hdr.timecnt];
- tr1 = &transitions_[hdr.timecnt - 1];
- tt0 = &transition_types_[tr0->type_index];
- tt1 = &transition_types_[tr1->type_index];
- }
- const PosixTransition& pt1(tt0->is_dst ? posix.dst_end : posix.dst_start);
- const PosixTransition& pt0(tt0->is_dst ? posix.dst_start : posix.dst_end);
- for (const year_t limit = last_year_ + 400; last_year_ < limit;) {
- last_year_ += 1; // an additional year of generated transitions
+ const civil_second jan1(last_year_);
+ std::int_fast64_t jan1_time = jan1 - civil_second();
+ int jan1_weekday = ToPosixWeekday(get_weekday(jan1));
+
+ Transition dst = {0, dst_ti, civil_second(), civil_second()};
+ Transition std = {0, std_ti, civil_second(), civil_second()};
+ for (const year_t limit = last_year_ + 400;; ++last_year_) {
+ auto dst_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_start);
+ auto std_trans_off = TransOffset(leap_year, jan1_weekday, posix.dst_end);
+ dst.unix_time = jan1_time + dst_trans_off - posix.std_offset;
+ std.unix_time = jan1_time + std_trans_off - posix.dst_offset;
+ const auto* ta = dst.unix_time < std.unix_time ? &dst : &std;
+ const auto* tb = dst.unix_time < std.unix_time ? &std : &dst;
+ if (last_time < tb->unix_time) {
+ if (last_time < ta->unix_time) transitions_.push_back(*ta);
+ transitions_.push_back(*tb);
+ }
+ if (last_year_ == limit) break;
jan1_time += kSecsPerYear[leap_year];
jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
- leap_year = !leap_year && IsLeap(last_year_);
- std::int_fast64_t tr1_offset = TransOffset(leap_year, jan1_weekday, pt1);
- tr->unix_time = jan1_time + tr1_offset - tt0->utc_offset;
- tr++->type_index = tr1->type_index;
- std::int_fast64_t tr0_offset = TransOffset(leap_year, jan1_weekday, pt0);
- tr->unix_time = jan1_time + tr0_offset - tt1->utc_offset;
- tr++->type_index = tr0->type_index;
- }
- assert(tr == &transitions_[0] + transitions_.size());
+ leap_year = !leap_year && IsLeap(last_year_ + 1);
+ }
+
+ return true;
}
-bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
+bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
// Read and validate the header.
tzhead tzh;
- if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
- return false;
+ if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
return false;
Header hdr;
- if (!hdr.Build(tzh))
- return false;
+ if (!hdr.Build(tzh)) return false;
std::size_t time_len = 4;
if (tzh.tzh_version[0] != '\0') {
// Skip the 4-byte data.
- if (zip->Skip(hdr.DataLength(time_len)) != 0)
- return false;
+ if (zip->Skip(hdr.DataLength(time_len)) != 0) return false;
// Read and validate the header for the 8-byte data.
- if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh))
- return false;
+ if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
if (strncmp(tzh.tzh_magic, TZ_MAGIC, sizeof(tzh.tzh_magic)) != 0)
return false;
- if (tzh.tzh_version[0] == '\0')
- return false;
- if (!hdr.Build(tzh))
- return false;
+ if (tzh.tzh_version[0] == '\0') return false;
+ if (!hdr.Build(tzh)) return false;
time_len = 8;
}
- if (hdr.typecnt == 0)
- return false;
+ if (hdr.typecnt == 0) return false;
if (hdr.leapcnt != 0) {
// This code assumes 60-second minutes so we do not want
// the leap-second encoded zoneinfo. We could reverse the
@@ -425,20 +415,17 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// so currently we simply reject such data.
return false;
}
- if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt)
- return false;
- if (hdr.ttisgmtcnt != 0 && hdr.ttisgmtcnt != hdr.typecnt)
- return false;
+ if (hdr.ttisstdcnt != 0 && hdr.ttisstdcnt != hdr.typecnt) return false;
+ if (hdr.ttisutcnt != 0 && hdr.ttisutcnt != hdr.typecnt) return false;
// Read the data into a local buffer.
std::size_t len = hdr.DataLength(time_len);
std::vector<char> tbuf(len);
- if (zip->Read(tbuf.data(), len) != len)
- return false;
+ if (zip->Read(tbuf.data(), len) != len) return false;
const char* bp = tbuf.data();
// Decode and validate the transitions.
- transitions_.reserve(hdr.timecnt + 2); // We might add a couple.
+ transitions_.reserve(hdr.timecnt + 2);
transitions_.resize(hdr.timecnt);
for (std::size_t i = 0; i != hdr.timecnt; ++i) {
transitions_[i].unix_time = (time_len == 4) ? Decode32(bp) : Decode64(bp);
@@ -452,13 +439,12 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
bool seen_type_0 = false;
for (std::size_t i = 0; i != hdr.timecnt; ++i) {
transitions_[i].type_index = Decode8(bp++);
- if (transitions_[i].type_index >= hdr.typecnt)
- return false;
- if (transitions_[i].type_index == 0)
- seen_type_0 = true;
+ if (transitions_[i].type_index >= hdr.typecnt) return false;
+ if (transitions_[i].type_index == 0) seen_type_0 = true;
}
// Decode and validate the transition types.
+ transition_types_.reserve(hdr.typecnt + 2);
transition_types_.resize(hdr.typecnt);
for (std::size_t i = 0; i != hdr.typecnt; ++i) {
transition_types_[i].utc_offset =
@@ -469,8 +455,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
bp += 4;
transition_types_[i].is_dst = (Decode8(bp++) != 0);
transition_types_[i].abbr_index = Decode8(bp++);
- if (transition_types_[i].abbr_index >= hdr.charcnt)
- return false;
+ if (transition_types_[i].abbr_index >= hdr.charcnt) return false;
}
// Determine the before-first-transition type.
@@ -479,16 +464,14 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
std::uint_fast8_t index = 0;
if (transition_types_[0].is_dst) {
index = transitions_[0].type_index;
- while (index != 0 && transition_types_[index].is_dst)
- --index;
+ while (index != 0 && transition_types_[index].is_dst) --index;
}
- while (index != hdr.typecnt && transition_types_[index].is_dst)
- ++index;
- if (index != hdr.typecnt)
- default_transition_type_ = index;
+ while (index != hdr.typecnt && transition_types_[index].is_dst) ++index;
+ if (index != hdr.typecnt) default_transition_type_ = index;
}
// Copy all the abbreviations.
+ abbreviations_.reserve(hdr.charcnt + 10);
abbreviations_.assign(bp, hdr.charcnt);
bp += hdr.charcnt;
@@ -498,22 +481,20 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// that isn't the case here (see "zic -p").
bp += (8 + 4) * hdr.leapcnt; // leap-time + TAI-UTC
bp += 1 * hdr.ttisstdcnt; // UTC/local indicators
- bp += 1 * hdr.ttisgmtcnt; // standard/wall indicators
+ bp += 1 * hdr.ttisutcnt; // standard/wall indicators
assert(bp == tbuf.data() + tbuf.size());
future_spec_.clear();
if (tzh.tzh_version[0] != '\0') {
// Snarf up the NL-enclosed future POSIX spec. Note
// that version '3' files utilize an extended format.
- auto get_char = [](ZoneInfoSource* zip) -> int {
+ auto get_char = [](ZoneInfoSource* azip) -> int {
unsigned char ch; // all non-EOF results are positive
- return (zip->Read(&ch, 1) == 1) ? ch : EOF;
+ return (azip->Read(&ch, 1) == 1) ? ch : EOF;
};
- if (get_char(zip) != '\n')
- return false;
+ if (get_char(zip) != '\n') return false;
for (int c = get_char(zip); c != '\n'; c = get_char(zip)) {
- if (c == EOF)
- return false;
+ if (c == EOF) return false;
future_spec_.push_back(static_cast<char>(c));
}
}
@@ -522,7 +503,7 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// If we did not find version information during the standard loading
// process (as of tzh_version '3' that is unsupported), then ask the
- // ZoneInfoSource for any out-of-bound version std::string it may be privy to.
+ // ZoneInfoSource for any out-of-bound version string it may be privy to.
if (version_.empty()) {
version_ = zip->Version();
}
@@ -541,19 +522,29 @@ bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
transitions_.resize(hdr.timecnt);
// Ensure that there is always a transition in the first half of the
- // time line (the second half is handled in ExtendTransitions()) so that
- // the signed difference between a civil_second and the civil_second of
- // its previous transition is always representable, without overflow.
- // A contemporary zic will usually have already done this for us.
+ // time line (the second half is handled below) so that the signed
+ // difference between a civil_second and the civil_second of its
+ // previous transition is always representable, without overflow.
if (transitions_.empty() || transitions_.front().unix_time >= 0) {
Transition& tr(*transitions_.emplace(transitions_.begin()));
- tr.unix_time = -(1LL << 59); // see tz/zic.c "BIG_BANG"
+ tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00
tr.type_index = default_transition_type_;
- hdr.timecnt += 1;
}
// Extend the transitions using the future specification.
- ExtendTransitions(name, hdr);
+ if (!ExtendTransitions()) return false;
+
+ // Ensure that there is always a transition in the second half of the
+ // time line (the first half is handled above) so that the signed
+ // difference between a civil_second and the civil_second of its
+ // previous transition is always representable, without overflow.
+ const Transition& last(transitions_.back());
+ if (last.unix_time < 0) {
+ const std::uint_fast8_t type_index = last.type_index;
+ Transition& tr(*transitions_.emplace(transitions_.end()));
+ tr.unix_time = 2147483647; // 2038-01-19T03:14:07+00:00
+ tr.type_index = type_index;
+ }
// Compute the local civil time for each transition and the preceding
// second. These will be used for reverse conversions in MakeTime().
@@ -624,18 +615,18 @@ class FileZoneInfoSource : public ZoneInfoSource {
: fp_(fp, fclose), len_(len) {}
private:
- std::unique_ptr<FILE, int(*)(FILE*)> fp_;
+ std::unique_ptr<FILE, int (*)(FILE*)> fp_;
std::size_t len_;
};
std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
const std::string& name) {
// Use of the "file:" prefix is intended for testing purposes only.
- if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
+ const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
// Map the time-zone name to a path name.
std::string path;
- if (name.empty() || name[0] != '/') {
+ if (pos == name.size() || name[pos] != '/') {
const char* tzdir = "/usr/share/zoneinfo";
char* tzdir_env = nullptr;
#if defined(_MSC_VER)
@@ -650,16 +641,16 @@ std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
free(tzdir_env);
#endif
}
- path += name;
+ path.append(name, pos, std::string::npos);
// Open the zoneinfo file.
FILE* fp = FOpen(path.c_str(), "rb");
if (fp == nullptr) return nullptr;
std::size_t length = 0;
if (fseek(fp, 0, SEEK_END) == 0) {
- long pos = ftell(fp);
- if (pos >= 0) {
- length = static_cast<std::size_t>(pos);
+ long offset = ftell(fp);
+ if (offset >= 0) {
+ length = static_cast<std::size_t>(offset);
}
rewind(fp);
}
@@ -680,9 +671,8 @@ class AndroidZoneInfoSource : public FileZoneInfoSource {
std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
const std::string& name) {
// Use of the "file:" prefix is intended for testing purposes only.
- if (name.compare(0, 5, "file:") == 0) return Open(name.substr(5));
+ const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
-#if defined(__ANDROID__)
// See Android's libc/tzcode/bionic.cpp for additional information.
for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
"/system/usr/share/zoneinfo/tzdata"}) {
@@ -710,14 +700,14 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
const std::int_fast32_t length = Decode32(ebuf + 44);
if (start < 0 || length < 0) break;
ebuf[40] = '\0'; // ensure zone name is NUL terminated
- if (strcmp(name.c_str(), ebuf) == 0) {
+ if (strcmp(name.c_str() + pos, ebuf) == 0) {
if (fseek(fp.get(), static_cast<long>(start), SEEK_SET) != 0) break;
return std::unique_ptr<ZoneInfoSource>(new AndroidZoneInfoSource(
fp.release(), static_cast<std::size_t>(length), vers));
}
}
}
-#endif // __ANDROID__
+
return nullptr;
}
@@ -735,12 +725,12 @@ bool TimeZoneInfo::Load(const std::string& name) {
// Find and use a ZoneInfoSource to load the named zone.
auto zip = cctz_extension::zone_info_source_factory(
- name, [](const std::string& name) -> std::unique_ptr<ZoneInfoSource> {
- if (auto zip = FileZoneInfoSource::Open(name)) return zip;
- if (auto zip = AndroidZoneInfoSource::Open(name)) return zip;
+ name, [](const std::string& n) -> std::unique_ptr<ZoneInfoSource> {
+ if (auto z = FileZoneInfoSource::Open(n)) return z;
+ if (auto z = AndroidZoneInfoSource::Open(n)) return z;
return nullptr;
});
- return zip != nullptr && Load(name, zip.get());
+ return zip != nullptr && Load(zip.get());
}
// BreakTime() translation for a particular transition type.
@@ -749,13 +739,13 @@ time_zone::absolute_lookup TimeZoneInfo::LocalTime(
// A civil time in "+offset" looks like (time+offset) in UTC.
// Note: We perform two additions in the civil_second domain to
// sidestep the chance of overflow in (unix_time + tt.utc_offset).
- return {(civil_second() + unix_time) + tt.utc_offset,
- tt.utc_offset, tt.is_dst, &abbreviations_[tt.abbr_index]};
+ return {(civil_second() + unix_time) + tt.utc_offset, tt.utc_offset,
+ tt.is_dst, &abbreviations_[tt.abbr_index]};
}
// BreakTime() translation for a particular transition.
-time_zone::absolute_lookup TimeZoneInfo::LocalTime(
- std::int_fast64_t unix_time, const Transition& tr) const {
+time_zone::absolute_lookup TimeZoneInfo::LocalTime(std::int_fast64_t unix_time,
+ const Transition& tr) const {
const TransitionType& tt = transition_types_[tr.type_index];
// Note: (unix_time - tr.unix_time) will never overflow as we
// have ensured that there is always a "nearby" transition.
@@ -898,9 +888,7 @@ time_zone::civil_lookup TimeZoneInfo::MakeTime(const civil_second& cs) const {
return MakeUnique(tr->unix_time + (cs - tr->civil_sec));
}
-std::string TimeZoneInfo::Version() const {
- return version_;
-}
+std::string TimeZoneInfo::Version() const { return version_; }
std::string TimeZoneInfo::Description() const {
std::ostringstream oss;
@@ -916,14 +904,14 @@ bool TimeZoneInfo::NextTransition(const time_point<seconds>& tp,
const Transition* begin = &transitions_[0];
const Transition* end = begin + transitions_.size();
if (begin->unix_time <= -(1LL << 59)) {
- // Do not report the BIG_BANG found in recent zoneinfo data as it is
- // really a sentinel, not a transition. See tz/zic.c.
+ // Do not report the BIG_BANG found in some zoneinfo data as it is
+ // really a sentinel, not a transition. See pre-2018f tz/zic.c.
++begin;
}
std::int_fast64_t unix_time = ToUnixSeconds(tp);
- const Transition target = { unix_time };
- const Transition* tr = std::upper_bound(begin, end, target,
- Transition::ByUnixTime());
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
+ const Transition* tr =
+ std::upper_bound(begin, end, target, Transition::ByUnixTime());
for (; tr != end; ++tr) { // skip no-op transitions
std::uint_fast8_t prev_type_index =
(tr == begin) ? default_transition_type_ : tr[-1].type_index;
@@ -942,8 +930,8 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
const Transition* begin = &transitions_[0];
const Transition* end = begin + transitions_.size();
if (begin->unix_time <= -(1LL << 59)) {
- // Do not report the BIG_BANG found in recent zoneinfo data as it is
- // really a sentinel, not a transition. See tz/zic.c.
+ // Do not report the BIG_BANG found in some zoneinfo data as it is
+ // really a sentinel, not a transition. See pre-2018f tz/zic.c.
++begin;
}
std::int_fast64_t unix_time = ToUnixSeconds(tp);
@@ -956,9 +944,9 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
}
unix_time += 1; // ceils
}
- const Transition target = { unix_time };
- const Transition* tr = std::lower_bound(begin, end, target,
- Transition::ByUnixTime());
+ const Transition target = {unix_time, 0, civil_second(), civil_second()};
+ const Transition* tr =
+ std::lower_bound(begin, end, target, Transition::ByUnixTime());
for (; tr != begin; --tr) { // skip no-op transitions
std::uint_fast8_t prev_type_index =
(tr - 1 == begin) ? default_transition_type_ : tr[-2].type_index;
@@ -973,4 +961,5 @@ bool TimeZoneInfo::PrevTransition(const time_point<seconds>& tp,
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
index 958e9b6bd74..2467ff559d3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,6 +21,7 @@
#include <string>
#include <vector>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
@@ -28,6 +29,7 @@
#include "tzfile.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -72,8 +74,7 @@ class TimeZoneInfo : public TimeZoneIf {
// TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const override;
- time_zone::civil_lookup MakeTime(
- const civil_second& cs) const override;
+ time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const override;
bool PrevTransition(const time_point<seconds>& tp,
@@ -82,27 +83,26 @@ class TimeZoneInfo : public TimeZoneIf {
std::string Description() const override;
private:
- struct Header { // counts of:
+ struct Header { // counts of:
std::size_t timecnt; // transition times
std::size_t typecnt; // transition types
std::size_t charcnt; // zone abbreviation characters
std::size_t leapcnt; // leap seconds (we expect none)
std::size_t ttisstdcnt; // UTC/local indicators (unused)
- std::size_t ttisgmtcnt; // standard/wall indicators (unused)
+ std::size_t ttisutcnt; // standard/wall indicators (unused)
bool Build(const tzhead& tzh);
std::size_t DataLength(std::size_t time_len) const;
};
- void CheckTransition(const std::string& name, const TransitionType& tt,
- std::int_fast32_t offset, bool is_dst,
- const std::string& abbr) const;
+ bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
+ const std::string& abbr, std::uint_least8_t* index);
bool EquivTransitions(std::uint_fast8_t tt1_index,
std::uint_fast8_t tt2_index) const;
- void ExtendTransitions(const std::string& name, const Header& hdr);
+ bool ExtendTransitions();
bool ResetToBuiltinUTC(const seconds& offset);
- bool Load(const std::string& name, ZoneInfoSource* zip);
+ bool Load(ZoneInfoSource* zip);
// Helpers for BreakTime() and MakeTime().
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
@@ -114,7 +114,7 @@ class TimeZoneInfo : public TimeZoneIf {
std::vector<Transition> transitions_; // ordered by unix_time and civil_sec
std::vector<TransitionType> transition_types_; // distinct transition types
- std::uint_fast8_t default_transition_type_; // for before first transition
+ std::uint_fast8_t default_transition_type_; // for before first transition
std::string abbreviations_; // all the NUL-terminated abbreviations
std::string version_; // the tzdata version if available
@@ -131,6 +131,7 @@ class TimeZoneInfo : public TimeZoneIf {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_INFO_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
index 6db519e165c..887dd097c65 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -21,84 +21,107 @@
#include <chrono>
#include <ctime>
#include <limits>
-#include <tuple>
#include <utility>
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
+#if defined(_AIX)
+extern "C" {
+extern long altzone;
+}
+#endif
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
namespace {
-// .first is seconds east of UTC; .second is the time-zone abbreviation.
-using OffsetAbbr = std::pair<int, const char*>;
-
-// Defines a function that can be called as follows:
-//
-// std::tm tm = ...;
-// OffsetAbbr off_abbr = get_offset_abbr(tm);
-//
#if defined(_WIN32) || defined(_WIN64)
// Uses the globals: '_timezone', '_dstbias' and '_tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + _dstbias) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = _timezone + (is_dst ? _dstbias : 0);
- const char* abbr = _tzname[is_dst];
- return {off, abbr};
+ return _timezone + (is_dst ? _dstbias : 0);
}
-#elif defined(__sun)
+auto tm_zone(const std::tm& tm) -> decltype(_tzname[0]) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return _tzname[is_dst];
+}
+#elif defined(__sun) || defined(_AIX)
// Uses the globals: 'timezone', 'altzone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return is_dst ? altzone : timezone;
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = is_dst ? altzone : timezone;
- const char* abbr = tzname[is_dst];
- return {off, abbr};
+ return tzname[is_dst];
}
#elif defined(__native_client__) || defined(__myriad2__) || \
defined(__EMSCRIPTEN__)
// Uses the globals: 'timezone' and 'tzname'.
-OffsetAbbr get_offset_abbr(const std::tm& tm) {
+auto tm_gmtoff(const std::tm& tm) -> decltype(_timezone + 0) {
+ const bool is_dst = tm.tm_isdst > 0;
+ return _timezone + (is_dst ? 60 * 60 : 0);
+}
+auto tm_zone(const std::tm& tm) -> decltype(tzname[0]) {
const bool is_dst = tm.tm_isdst > 0;
- const int off = _timezone + (is_dst ? 60 * 60 : 0);
- const char* abbr = tzname[is_dst];
- return {off, abbr};
+ return tzname[is_dst];
+}
+#else
+// Adapt to different spellings of the struct std::tm extension fields.
+#if defined(tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.tm_gmtoff) {
+ return tm.tm_gmtoff;
+}
+#elif defined(__tm_gmtoff)
+auto tm_gmtoff(const std::tm& tm) -> decltype(tm.__tm_gmtoff) {
+ return tm.__tm_gmtoff;
+}
+#else
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.tm_gmtoff) {
+ return tm.tm_gmtoff;
+}
+template <typename T>
+auto tm_gmtoff(const T& tm) -> decltype(tm.__tm_gmtoff) {
+ return tm.__tm_gmtoff;
+}
+#endif // tm_gmtoff
+#if defined(tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.tm_zone) { return tm.tm_zone; }
+#elif defined(__tm_zone)
+auto tm_zone(const std::tm& tm) -> decltype(tm.__tm_zone) {
+ return tm.__tm_zone;
}
#else
-//
-// Returns an OffsetAbbr using std::tm fields with various spellings.
-//
-#if !defined(tm_gmtoff) && !defined(tm_zone)
template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::tm_gmtoff) = nullptr,
- decltype(&T::tm_zone) = nullptr) {
- return {tm.tm_gmtoff, tm.tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.tm_zone) {
+ return tm.tm_zone;
}
-#endif // !defined(tm_gmtoff) && !defined(tm_zone)
-#if !defined(__tm_gmtoff) && !defined(__tm_zone)
template <typename T>
-OffsetAbbr get_offset_abbr(const T& tm, decltype(&T::__tm_gmtoff) = nullptr,
- decltype(&T::__tm_zone) = nullptr) {
- return {tm.__tm_gmtoff, tm.__tm_zone};
+auto tm_zone(const T& tm) -> decltype(tm.__tm_zone) {
+ return tm.__tm_zone;
}
-#endif // !defined(__tm_gmtoff) && !defined(__tm_zone)
+#endif // tm_zone
#endif
-inline std::tm* gm_time(const std::time_t *timep, std::tm *result) {
+inline std::tm* gm_time(const std::time_t* timep, std::tm* result) {
#if defined(_WIN32) || defined(_WIN64)
- return gmtime_s(result, timep) ? nullptr : result;
+ return gmtime_s(result, timep) ? nullptr : result;
#else
- return gmtime_r(timep, result);
+ return gmtime_r(timep, result);
#endif
}
-inline std::tm* local_time(const std::time_t *timep, std::tm *result) {
+inline std::tm* local_time(const std::time_t* timep, std::tm* result) {
#if defined(_WIN32) || defined(_WIN64)
- return localtime_s(result, timep) ? nullptr : result;
+ return localtime_s(result, timep) ? nullptr : result;
#else
- return localtime_r(timep, result);
+ return localtime_r(timep, result);
#endif
}
@@ -126,7 +149,7 @@ bool make_time(const civil_second& cs, int is_dst, std::time_t* t, int* off) {
return false;
}
}
- *off = get_offset_abbr(tm).first;
+ *off = static_cast<int>(tm_gmtoff(tm));
return true;
}
@@ -136,8 +159,9 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
std::tm tm;
while (lo + 1 != hi) {
const std::time_t mid = lo + (hi - lo) / 2;
- if (std::tm* tmp = local_time(&mid, &tm)) {
- if (get_offset_abbr(*tmp).first == offset) {
+ std::tm* tmp = local_time(&mid, &tm);
+ if (tmp != nullptr) {
+ if (tm_gmtoff(*tmp) == offset) {
hi = mid;
} else {
lo = mid;
@@ -146,8 +170,9 @@ std::time_t find_trans(std::time_t lo, std::time_t hi, int offset) {
// If std::tm cannot hold some result we resort to a linear search,
// ignoring all failed conversions. Slow, but never really happens.
while (++lo != hi) {
- if (std::tm* tmp = local_time(&lo, &tm)) {
- if (get_offset_abbr(*tmp).first == offset) break;
+ tmp = local_time(&lo, &tm);
+ if (tmp != nullptr) {
+ if (tm_gmtoff(*tmp) == offset) break;
}
}
return lo;
@@ -191,10 +216,10 @@ time_zone::absolute_lookup TimeZoneLibC::BreakTime(
}
const year_t year = tmp->tm_year + year_t{1900};
- al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday,
- tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
- std::tie(al.offset, al.abbr) = get_offset_abbr(*tmp);
- if (!local_) al.abbr = "UTC"; // as expected by cctz
+ al.cs = civil_second(year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour,
+ tmp->tm_min, tmp->tm_sec);
+ al.offset = static_cast<int>(tm_gmtoff(*tmp));
+ al.abbr = local_ ? tm_zone(*tmp) : "UTC"; // as expected by cctz
al.is_dst = tmp->tm_isdst > 0;
return al;
}
@@ -206,11 +231,10 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
civil_second() + ToUnixSeconds(time_point<seconds>::min());
static const civil_second max_tp_cs =
civil_second() + ToUnixSeconds(time_point<seconds>::max());
- const time_point<seconds> tp =
- (cs < min_tp_cs)
- ? time_point<seconds>::min()
- : (cs > max_tp_cs) ? time_point<seconds>::max()
- : FromUnixSeconds(cs - civil_second());
+ const time_point<seconds> tp = (cs < min_tp_cs) ? time_point<seconds>::min()
+ : (cs > max_tp_cs)
+ ? time_point<seconds>::max()
+ : FromUnixSeconds(cs - civil_second());
return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
}
@@ -267,13 +291,13 @@ time_zone::civil_lookup TimeZoneLibC::MakeTime(const civil_second& cs) const {
return {time_zone::civil_lookup::UNIQUE, tp, tp, tp};
}
-bool TimeZoneLibC::NextTransition(const time_point<seconds>& tp,
- time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::NextTransition(const time_point<seconds>&,
+ time_zone::civil_transition*) const {
return false;
}
-bool TimeZoneLibC::PrevTransition(const time_point<seconds>& tp,
- time_zone::civil_transition* trans) const {
+bool TimeZoneLibC::PrevTransition(const time_point<seconds>&,
+ time_zone::civil_transition*) const {
return false;
}
@@ -287,4 +311,5 @@ std::string TimeZoneLibC::Description() const {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h
index 4e40c61ab24..1da9039a15e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,9 +17,11 @@
#include <string>
+#include "absl/base/config.h"
#include "time_zone_if.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -33,8 +35,7 @@ class TimeZoneLibC : public TimeZoneIf {
// TimeZoneIf implementations.
time_zone::absolute_lookup BreakTime(
const time_point<seconds>& tp) const override;
- time_zone::civil_lookup MakeTime(
- const civil_second& cs) const override;
+ time_zone::civil_lookup MakeTime(const civil_second& cs) const override;
bool NextTransition(const time_point<seconds>& tp,
time_zone::civil_transition* trans) const override;
bool PrevTransition(const time_point<seconds>& tp,
@@ -48,6 +49,7 @@ class TimeZoneLibC : public TimeZoneIf {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_LIBC_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
index f2d151e4d5e..efdea64b4eb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,14 +12,22 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
#if defined(__ANDROID__)
#include <sys/system_properties.h>
-#if __ANDROID_API__ >= 21
+#if defined(__ANDROID_API__) && __ANDROID_API__ >= 21
#include <dlfcn.h>
#endif
#endif
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CFTimeZone.h>
+
+#include <vector>
+#endif
+
#include <cstdlib>
#include <cstring>
#include <string>
@@ -28,10 +36,11 @@
#include "time_zone_impl.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
-#if defined(__ANDROID__) && __ANDROID_API__ >= 21
+#if defined(__ANDROID__) && defined(__ANDROID_API__) && __ANDROID_API__ >= 21
namespace {
// Android 'L' removes __system_property_get() from the NDK, however
// it is still a hidden symbol in libc so we use dlsym() to access it.
@@ -60,9 +69,7 @@ int __system_property_get(const char* name, char* value) {
} // namespace
#endif
-std::string time_zone::name() const {
- return effective_impl().Name();
-}
+std::string time_zone::name() const { return effective_impl().Name(); }
time_zone::absolute_lookup time_zone::lookup(
const time_point<seconds>& tp) const {
@@ -83,9 +90,7 @@ bool time_zone::prev_transition(const time_point<seconds>& tp,
return effective_impl().PrevTransition(tp, trans);
}
-std::string time_zone::version() const {
- return effective_impl().Version();
-}
+std::string time_zone::version() const { return effective_impl().Version(); }
std::string time_zone::description() const {
return effective_impl().Description();
@@ -116,6 +121,25 @@ time_zone fixed_time_zone(const seconds& offset) {
time_zone local_time_zone() {
const char* zone = ":localtime";
+#if defined(__ANDROID__)
+ char sysprop[PROP_VALUE_MAX];
+ if (__system_property_get("persist.sys.timezone", sysprop) > 0) {
+ zone = sysprop;
+ }
+#endif
+#if defined(__APPLE__)
+ std::vector<char> buffer;
+ CFTimeZoneRef tz_default = CFTimeZoneCopyDefault();
+ if (CFStringRef tz_name = CFTimeZoneGetName(tz_default)) {
+ CFStringEncoding encoding = kCFStringEncodingUTF8;
+ CFIndex length = CFStringGetLength(tz_name);
+ buffer.resize(CFStringGetMaximumSizeForEncoding(length, encoding) + 1);
+ if (CFStringGetCString(tz_name, &buffer[0], buffer.size(), encoding)) {
+ zone = &buffer[0];
+ }
+ }
+ CFRelease(tz_default);
+#endif
// Allow ${TZ} to override to default zone.
char* tz_env = nullptr;
@@ -124,12 +148,6 @@ time_zone local_time_zone() {
#else
tz_env = std::getenv("TZ");
#endif
-#if defined(__ANDROID__)
- char sysprop[PROP_VALUE_MAX];
- if (tz_env == nullptr)
- if (__system_property_get("persist.sys.timezone", sysprop) > 0)
- tz_env = sysprop;
-#endif
if (tz_env) zone = tz_env;
// We only support the "[:]<zone-name>" form.
@@ -165,4 +183,5 @@ time_zone local_time_zone() {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index e84b9469aa0..9a1a8d6e400 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/time/internal/cctz/include/cctz/time_zone.h"
-
#include <chrono>
#include <cstddef>
#include <cstdlib>
@@ -23,612 +21,615 @@
#include <thread>
#include <vector>
-#include "absl/time/internal/cctz/include/cctz/civil_time.h"
#include "gtest/gtest.h"
+#include "absl/base/config.h"
+#include "absl/time/internal/cctz/include/cctz/civil_time.h"
+#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace chrono = std::chrono;
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
namespace {
// A list of known time-zone names.
-const char* const kTimeZoneNames[] = {
- "Africa/Abidjan",
- "Africa/Accra",
- "Africa/Addis_Ababa",
- "Africa/Algiers",
- "Africa/Asmara",
- "Africa/Asmera",
- "Africa/Bamako",
- "Africa/Bangui",
- "Africa/Banjul",
- "Africa/Bissau",
- "Africa/Blantyre",
- "Africa/Brazzaville",
- "Africa/Bujumbura",
- "Africa/Cairo",
- "Africa/Casablanca",
- "Africa/Ceuta",
- "Africa/Conakry",
- "Africa/Dakar",
- "Africa/Dar_es_Salaam",
- "Africa/Djibouti",
- "Africa/Douala",
- "Africa/El_Aaiun",
- "Africa/Freetown",
- "Africa/Gaborone",
- "Africa/Harare",
- "Africa/Johannesburg",
- "Africa/Juba",
- "Africa/Kampala",
- "Africa/Khartoum",
- "Africa/Kigali",
- "Africa/Kinshasa",
- "Africa/Lagos",
- "Africa/Libreville",
- "Africa/Lome",
- "Africa/Luanda",
- "Africa/Lubumbashi",
- "Africa/Lusaka",
- "Africa/Malabo",
- "Africa/Maputo",
- "Africa/Maseru",
- "Africa/Mbabane",
- "Africa/Mogadishu",
- "Africa/Monrovia",
- "Africa/Nairobi",
- "Africa/Ndjamena",
- "Africa/Niamey",
- "Africa/Nouakchott",
- "Africa/Ouagadougou",
- "Africa/Porto-Novo",
- "Africa/Sao_Tome",
- "Africa/Timbuktu",
- "Africa/Tripoli",
- "Africa/Tunis",
- "Africa/Windhoek",
- "America/Adak",
- "America/Anchorage",
- "America/Anguilla",
- "America/Antigua",
- "America/Araguaina",
- "America/Argentina/Buenos_Aires",
- "America/Argentina/Catamarca",
- "America/Argentina/ComodRivadavia",
- "America/Argentina/Cordoba",
- "America/Argentina/Jujuy",
- "America/Argentina/La_Rioja",
- "America/Argentina/Mendoza",
- "America/Argentina/Rio_Gallegos",
- "America/Argentina/Salta",
- "America/Argentina/San_Juan",
- "America/Argentina/San_Luis",
- "America/Argentina/Tucuman",
- "America/Argentina/Ushuaia",
- "America/Aruba",
- "America/Asuncion",
- "America/Atikokan",
- "America/Atka",
- "America/Bahia",
- "America/Bahia_Banderas",
- "America/Barbados",
- "America/Belem",
- "America/Belize",
- "America/Blanc-Sablon",
- "America/Boa_Vista",
- "America/Bogota",
- "America/Boise",
- "America/Buenos_Aires",
- "America/Cambridge_Bay",
- "America/Campo_Grande",
- "America/Cancun",
- "America/Caracas",
- "America/Catamarca",
- "America/Cayenne",
- "America/Cayman",
- "America/Chicago",
- "America/Chihuahua",
- "America/Coral_Harbour",
- "America/Cordoba",
- "America/Costa_Rica",
- "America/Creston",
- "America/Cuiaba",
- "America/Curacao",
- "America/Danmarkshavn",
- "America/Dawson",
- "America/Dawson_Creek",
- "America/Denver",
- "America/Detroit",
- "America/Dominica",
- "America/Edmonton",
- "America/Eirunepe",
- "America/El_Salvador",
- "America/Ensenada",
- "America/Fort_Nelson",
- "America/Fort_Wayne",
- "America/Fortaleza",
- "America/Glace_Bay",
- "America/Godthab",
- "America/Goose_Bay",
- "America/Grand_Turk",
- "America/Grenada",
- "America/Guadeloupe",
- "America/Guatemala",
- "America/Guayaquil",
- "America/Guyana",
- "America/Halifax",
- "America/Havana",
- "America/Hermosillo",
- "America/Indiana/Indianapolis",
- "America/Indiana/Knox",
- "America/Indiana/Marengo",
- "America/Indiana/Petersburg",
- "America/Indiana/Tell_City",
- "America/Indiana/Vevay",
- "America/Indiana/Vincennes",
- "America/Indiana/Winamac",
- "America/Indianapolis",
- "America/Inuvik",
- "America/Iqaluit",
- "America/Jamaica",
- "America/Jujuy",
- "America/Juneau",
- "America/Kentucky/Louisville",
- "America/Kentucky/Monticello",
- "America/Knox_IN",
- "America/Kralendijk",
- "America/La_Paz",
- "America/Lima",
- "America/Los_Angeles",
- "America/Louisville",
- "America/Lower_Princes",
- "America/Maceio",
- "America/Managua",
- "America/Manaus",
- "America/Marigot",
- "America/Martinique",
- "America/Matamoros",
- "America/Mazatlan",
- "America/Mendoza",
- "America/Menominee",
- "America/Merida",
- "America/Metlakatla",
- "America/Mexico_City",
- "America/Miquelon",
- "America/Moncton",
- "America/Monterrey",
- "America/Montevideo",
- "America/Montreal",
- "America/Montserrat",
- "America/Nassau",
- "America/New_York",
- "America/Nipigon",
- "America/Nome",
- "America/Noronha",
- "America/North_Dakota/Beulah",
- "America/North_Dakota/Center",
- "America/North_Dakota/New_Salem",
- "America/Ojinaga",
- "America/Panama",
- "America/Pangnirtung",
- "America/Paramaribo",
- "America/Phoenix",
- "America/Port-au-Prince",
- "America/Port_of_Spain",
- "America/Porto_Acre",
- "America/Porto_Velho",
- "America/Puerto_Rico",
- "America/Punta_Arenas",
- "America/Rainy_River",
- "America/Rankin_Inlet",
- "America/Recife",
- "America/Regina",
- "America/Resolute",
- "America/Rio_Branco",
- "America/Rosario",
- "America/Santa_Isabel",
- "America/Santarem",
- "America/Santiago",
- "America/Santo_Domingo",
- "America/Sao_Paulo",
- "America/Scoresbysund",
- "America/Shiprock",
- "America/Sitka",
- "America/St_Barthelemy",
- "America/St_Johns",
- "America/St_Kitts",
- "America/St_Lucia",
- "America/St_Thomas",
- "America/St_Vincent",
- "America/Swift_Current",
- "America/Tegucigalpa",
- "America/Thule",
- "America/Thunder_Bay",
- "America/Tijuana",
- "America/Toronto",
- "America/Tortola",
- "America/Vancouver",
- "America/Virgin",
- "America/Whitehorse",
- "America/Winnipeg",
- "America/Yakutat",
- "America/Yellowknife",
- "Antarctica/Casey",
- "Antarctica/Davis",
- "Antarctica/DumontDUrville",
- "Antarctica/Macquarie",
- "Antarctica/Mawson",
- "Antarctica/McMurdo",
- "Antarctica/Palmer",
- "Antarctica/Rothera",
- "Antarctica/South_Pole",
- "Antarctica/Syowa",
- "Antarctica/Troll",
- "Antarctica/Vostok",
- "Arctic/Longyearbyen",
- "Asia/Aden",
- "Asia/Almaty",
- "Asia/Amman",
- "Asia/Anadyr",
- "Asia/Aqtau",
- "Asia/Aqtobe",
- "Asia/Ashgabat",
- "Asia/Ashkhabad",
- "Asia/Atyrau",
- "Asia/Baghdad",
- "Asia/Bahrain",
- "Asia/Baku",
- "Asia/Bangkok",
- "Asia/Barnaul",
- "Asia/Beirut",
- "Asia/Bishkek",
- "Asia/Brunei",
- "Asia/Calcutta",
- "Asia/Chita",
- "Asia/Choibalsan",
- "Asia/Chongqing",
- "Asia/Chungking",
- "Asia/Colombo",
- "Asia/Dacca",
- "Asia/Damascus",
- "Asia/Dhaka",
- "Asia/Dili",
- "Asia/Dubai",
- "Asia/Dushanbe",
- "Asia/Famagusta",
- "Asia/Gaza",
- "Asia/Harbin",
- "Asia/Hebron",
- "Asia/Ho_Chi_Minh",
- "Asia/Hong_Kong",
- "Asia/Hovd",
- "Asia/Irkutsk",
- "Asia/Istanbul",
- "Asia/Jakarta",
- "Asia/Jayapura",
- "Asia/Jerusalem",
- "Asia/Kabul",
- "Asia/Kamchatka",
- "Asia/Karachi",
- "Asia/Kashgar",
- "Asia/Kathmandu",
- "Asia/Katmandu",
- "Asia/Khandyga",
- "Asia/Kolkata",
- "Asia/Krasnoyarsk",
- "Asia/Kuala_Lumpur",
- "Asia/Kuching",
- "Asia/Kuwait",
- "Asia/Macao",
- "Asia/Macau",
- "Asia/Magadan",
- "Asia/Makassar",
- "Asia/Manila",
- "Asia/Muscat",
- "Asia/Nicosia",
- "Asia/Novokuznetsk",
- "Asia/Novosibirsk",
- "Asia/Omsk",
- "Asia/Oral",
- "Asia/Phnom_Penh",
- "Asia/Pontianak",
- "Asia/Pyongyang",
- "Asia/Qatar",
- "Asia/Qyzylorda",
- "Asia/Rangoon",
- "Asia/Riyadh",
- "Asia/Saigon",
- "Asia/Sakhalin",
- "Asia/Samarkand",
- "Asia/Seoul",
- "Asia/Shanghai",
- "Asia/Singapore",
- "Asia/Srednekolymsk",
- "Asia/Taipei",
- "Asia/Tashkent",
- "Asia/Tbilisi",
- "Asia/Tehran",
- "Asia/Tel_Aviv",
- "Asia/Thimbu",
- "Asia/Thimphu",
- "Asia/Tokyo",
- "Asia/Tomsk",
- "Asia/Ujung_Pandang",
- "Asia/Ulaanbaatar",
- "Asia/Ulan_Bator",
- "Asia/Urumqi",
- "Asia/Ust-Nera",
- "Asia/Vientiane",
- "Asia/Vladivostok",
- "Asia/Yakutsk",
- "Asia/Yangon",
- "Asia/Yekaterinburg",
- "Asia/Yerevan",
- "Atlantic/Azores",
- "Atlantic/Bermuda",
- "Atlantic/Canary",
- "Atlantic/Cape_Verde",
- "Atlantic/Faeroe",
- "Atlantic/Faroe",
- "Atlantic/Jan_Mayen",
- "Atlantic/Madeira",
- "Atlantic/Reykjavik",
- "Atlantic/South_Georgia",
- "Atlantic/St_Helena",
- "Atlantic/Stanley",
- "Australia/ACT",
- "Australia/Adelaide",
- "Australia/Brisbane",
- "Australia/Broken_Hill",
- "Australia/Canberra",
- "Australia/Currie",
- "Australia/Darwin",
- "Australia/Eucla",
- "Australia/Hobart",
- "Australia/LHI",
- "Australia/Lindeman",
- "Australia/Lord_Howe",
- "Australia/Melbourne",
- "Australia/NSW",
- "Australia/North",
- "Australia/Perth",
- "Australia/Queensland",
- "Australia/South",
- "Australia/Sydney",
- "Australia/Tasmania",
- "Australia/Victoria",
- "Australia/West",
- "Australia/Yancowinna",
- "Brazil/Acre",
- "Brazil/DeNoronha",
- "Brazil/East",
- "Brazil/West",
- "CET",
- "CST6CDT",
- "Canada/Atlantic",
- "Canada/Central",
- "Canada/Eastern",
- "Canada/Mountain",
- "Canada/Newfoundland",
- "Canada/Pacific",
- "Canada/Saskatchewan",
- "Canada/Yukon",
- "Chile/Continental",
- "Chile/EasterIsland",
- "Cuba",
- "EET",
- "EST",
- "EST5EDT",
- "Egypt",
- "Eire",
- "Etc/GMT",
- "Etc/GMT+0",
- "Etc/GMT+1",
- "Etc/GMT+10",
- "Etc/GMT+11",
- "Etc/GMT+12",
- "Etc/GMT+2",
- "Etc/GMT+3",
- "Etc/GMT+4",
- "Etc/GMT+5",
- "Etc/GMT+6",
- "Etc/GMT+7",
- "Etc/GMT+8",
- "Etc/GMT+9",
- "Etc/GMT-0",
- "Etc/GMT-1",
- "Etc/GMT-10",
- "Etc/GMT-11",
- "Etc/GMT-12",
- "Etc/GMT-13",
- "Etc/GMT-14",
- "Etc/GMT-2",
- "Etc/GMT-3",
- "Etc/GMT-4",
- "Etc/GMT-5",
- "Etc/GMT-6",
- "Etc/GMT-7",
- "Etc/GMT-8",
- "Etc/GMT-9",
- "Etc/GMT0",
- "Etc/Greenwich",
- "Etc/UCT",
- "Etc/UTC",
- "Etc/Universal",
- "Etc/Zulu",
- "Europe/Amsterdam",
- "Europe/Andorra",
- "Europe/Astrakhan",
- "Europe/Athens",
- "Europe/Belfast",
- "Europe/Belgrade",
- "Europe/Berlin",
- "Europe/Bratislava",
- "Europe/Brussels",
- "Europe/Bucharest",
- "Europe/Budapest",
- "Europe/Busingen",
- "Europe/Chisinau",
- "Europe/Copenhagen",
- "Europe/Dublin",
- "Europe/Gibraltar",
- "Europe/Guernsey",
- "Europe/Helsinki",
- "Europe/Isle_of_Man",
- "Europe/Istanbul",
- "Europe/Jersey",
- "Europe/Kaliningrad",
- "Europe/Kiev",
- "Europe/Kirov",
- "Europe/Lisbon",
- "Europe/Ljubljana",
- "Europe/London",
- "Europe/Luxembourg",
- "Europe/Madrid",
- "Europe/Malta",
- "Europe/Mariehamn",
- "Europe/Minsk",
- "Europe/Monaco",
- "Europe/Moscow",
- "Europe/Nicosia",
- "Europe/Oslo",
- "Europe/Paris",
- "Europe/Podgorica",
- "Europe/Prague",
- "Europe/Riga",
- "Europe/Rome",
- "Europe/Samara",
- "Europe/San_Marino",
- "Europe/Sarajevo",
- "Europe/Saratov",
- "Europe/Simferopol",
- "Europe/Skopje",
- "Europe/Sofia",
- "Europe/Stockholm",
- "Europe/Tallinn",
- "Europe/Tirane",
- "Europe/Tiraspol",
- "Europe/Ulyanovsk",
- "Europe/Uzhgorod",
- "Europe/Vaduz",
- "Europe/Vatican",
- "Europe/Vienna",
- "Europe/Vilnius",
- "Europe/Volgograd",
- "Europe/Warsaw",
- "Europe/Zagreb",
- "Europe/Zaporozhye",
- "Europe/Zurich",
- "GB",
- "GB-Eire",
- "GMT",
- "GMT+0",
- "GMT-0",
- "GMT0",
- "Greenwich",
- "HST",
- "Hongkong",
- "Iceland",
- "Indian/Antananarivo",
- "Indian/Chagos",
- "Indian/Christmas",
- "Indian/Cocos",
- "Indian/Comoro",
- "Indian/Kerguelen",
- "Indian/Mahe",
- "Indian/Maldives",
- "Indian/Mauritius",
- "Indian/Mayotte",
- "Indian/Reunion",
- "Iran",
- "Israel",
- "Jamaica",
- "Japan",
- "Kwajalein",
- "Libya",
- "MET",
- "MST",
- "MST7MDT",
- "Mexico/BajaNorte",
- "Mexico/BajaSur",
- "Mexico/General",
- "NZ",
- "NZ-CHAT",
- "Navajo",
- "PRC",
- "PST8PDT",
- "Pacific/Apia",
- "Pacific/Auckland",
- "Pacific/Bougainville",
- "Pacific/Chatham",
- "Pacific/Chuuk",
- "Pacific/Easter",
- "Pacific/Efate",
- "Pacific/Enderbury",
- "Pacific/Fakaofo",
- "Pacific/Fiji",
- "Pacific/Funafuti",
- "Pacific/Galapagos",
- "Pacific/Gambier",
- "Pacific/Guadalcanal",
- "Pacific/Guam",
- "Pacific/Honolulu",
- "Pacific/Johnston",
- "Pacific/Kiritimati",
- "Pacific/Kosrae",
- "Pacific/Kwajalein",
- "Pacific/Majuro",
- "Pacific/Marquesas",
- "Pacific/Midway",
- "Pacific/Nauru",
- "Pacific/Niue",
- "Pacific/Norfolk",
- "Pacific/Noumea",
- "Pacific/Pago_Pago",
- "Pacific/Palau",
- "Pacific/Pitcairn",
- "Pacific/Pohnpei",
- "Pacific/Ponape",
- "Pacific/Port_Moresby",
- "Pacific/Rarotonga",
- "Pacific/Saipan",
- "Pacific/Samoa",
- "Pacific/Tahiti",
- "Pacific/Tarawa",
- "Pacific/Tongatapu",
- "Pacific/Truk",
- "Pacific/Wake",
- "Pacific/Wallis",
- "Pacific/Yap",
- "Poland",
- "Portugal",
- "ROC",
- "ROK",
- "Singapore",
- "Turkey",
- "UCT",
- "US/Alaska",
- "US/Aleutian",
- "US/Arizona",
- "US/Central",
- "US/East-Indiana",
- "US/Eastern",
- "US/Hawaii",
- "US/Indiana-Starke",
- "US/Michigan",
- "US/Mountain",
- "US/Pacific",
- "US/Samoa",
- "UTC",
- "Universal",
- "W-SU",
- "WET",
- "Zulu",
- nullptr
-};
+const char* const kTimeZoneNames[] = {"Africa/Abidjan",
+ "Africa/Accra",
+ "Africa/Addis_Ababa",
+ "Africa/Algiers",
+ "Africa/Asmara",
+ "Africa/Asmera",
+ "Africa/Bamako",
+ "Africa/Bangui",
+ "Africa/Banjul",
+ "Africa/Bissau",
+ "Africa/Blantyre",
+ "Africa/Brazzaville",
+ "Africa/Bujumbura",
+ "Africa/Cairo",
+ "Africa/Casablanca",
+ "Africa/Ceuta",
+ "Africa/Conakry",
+ "Africa/Dakar",
+ "Africa/Dar_es_Salaam",
+ "Africa/Djibouti",
+ "Africa/Douala",
+ "Africa/El_Aaiun",
+ "Africa/Freetown",
+ "Africa/Gaborone",
+ "Africa/Harare",
+ "Africa/Johannesburg",
+ "Africa/Juba",
+ "Africa/Kampala",
+ "Africa/Khartoum",
+ "Africa/Kigali",
+ "Africa/Kinshasa",
+ "Africa/Lagos",
+ "Africa/Libreville",
+ "Africa/Lome",
+ "Africa/Luanda",
+ "Africa/Lubumbashi",
+ "Africa/Lusaka",
+ "Africa/Malabo",
+ "Africa/Maputo",
+ "Africa/Maseru",
+ "Africa/Mbabane",
+ "Africa/Mogadishu",
+ "Africa/Monrovia",
+ "Africa/Nairobi",
+ "Africa/Ndjamena",
+ "Africa/Niamey",
+ "Africa/Nouakchott",
+ "Africa/Ouagadougou",
+ "Africa/Porto-Novo",
+ "Africa/Sao_Tome",
+ "Africa/Timbuktu",
+ "Africa/Tripoli",
+ "Africa/Tunis",
+ "Africa/Windhoek",
+ "America/Adak",
+ "America/Anchorage",
+ "America/Anguilla",
+ "America/Antigua",
+ "America/Araguaina",
+ "America/Argentina/Buenos_Aires",
+ "America/Argentina/Catamarca",
+ "America/Argentina/ComodRivadavia",
+ "America/Argentina/Cordoba",
+ "America/Argentina/Jujuy",
+ "America/Argentina/La_Rioja",
+ "America/Argentina/Mendoza",
+ "America/Argentina/Rio_Gallegos",
+ "America/Argentina/Salta",
+ "America/Argentina/San_Juan",
+ "America/Argentina/San_Luis",
+ "America/Argentina/Tucuman",
+ "America/Argentina/Ushuaia",
+ "America/Aruba",
+ "America/Asuncion",
+ "America/Atikokan",
+ "America/Atka",
+ "America/Bahia",
+ "America/Bahia_Banderas",
+ "America/Barbados",
+ "America/Belem",
+ "America/Belize",
+ "America/Blanc-Sablon",
+ "America/Boa_Vista",
+ "America/Bogota",
+ "America/Boise",
+ "America/Buenos_Aires",
+ "America/Cambridge_Bay",
+ "America/Campo_Grande",
+ "America/Cancun",
+ "America/Caracas",
+ "America/Catamarca",
+ "America/Cayenne",
+ "America/Cayman",
+ "America/Chicago",
+ "America/Chihuahua",
+ "America/Coral_Harbour",
+ "America/Cordoba",
+ "America/Costa_Rica",
+ "America/Creston",
+ "America/Cuiaba",
+ "America/Curacao",
+ "America/Danmarkshavn",
+ "America/Dawson",
+ "America/Dawson_Creek",
+ "America/Denver",
+ "America/Detroit",
+ "America/Dominica",
+ "America/Edmonton",
+ "America/Eirunepe",
+ "America/El_Salvador",
+ "America/Ensenada",
+ "America/Fort_Nelson",
+ "America/Fort_Wayne",
+ "America/Fortaleza",
+ "America/Glace_Bay",
+ "America/Godthab",
+ "America/Goose_Bay",
+ "America/Grand_Turk",
+ "America/Grenada",
+ "America/Guadeloupe",
+ "America/Guatemala",
+ "America/Guayaquil",
+ "America/Guyana",
+ "America/Halifax",
+ "America/Havana",
+ "America/Hermosillo",
+ "America/Indiana/Indianapolis",
+ "America/Indiana/Knox",
+ "America/Indiana/Marengo",
+ "America/Indiana/Petersburg",
+ "America/Indiana/Tell_City",
+ "America/Indiana/Vevay",
+ "America/Indiana/Vincennes",
+ "America/Indiana/Winamac",
+ "America/Indianapolis",
+ "America/Inuvik",
+ "America/Iqaluit",
+ "America/Jamaica",
+ "America/Jujuy",
+ "America/Juneau",
+ "America/Kentucky/Louisville",
+ "America/Kentucky/Monticello",
+ "America/Knox_IN",
+ "America/Kralendijk",
+ "America/La_Paz",
+ "America/Lima",
+ "America/Los_Angeles",
+ "America/Louisville",
+ "America/Lower_Princes",
+ "America/Maceio",
+ "America/Managua",
+ "America/Manaus",
+ "America/Marigot",
+ "America/Martinique",
+ "America/Matamoros",
+ "America/Mazatlan",
+ "America/Mendoza",
+ "America/Menominee",
+ "America/Merida",
+ "America/Metlakatla",
+ "America/Mexico_City",
+ "America/Miquelon",
+ "America/Moncton",
+ "America/Monterrey",
+ "America/Montevideo",
+ "America/Montreal",
+ "America/Montserrat",
+ "America/Nassau",
+ "America/New_York",
+ "America/Nipigon",
+ "America/Nome",
+ "America/Noronha",
+ "America/North_Dakota/Beulah",
+ "America/North_Dakota/Center",
+ "America/North_Dakota/New_Salem",
+ "America/Nuuk",
+ "America/Ojinaga",
+ "America/Panama",
+ "America/Pangnirtung",
+ "America/Paramaribo",
+ "America/Phoenix",
+ "America/Port-au-Prince",
+ "America/Port_of_Spain",
+ "America/Porto_Acre",
+ "America/Porto_Velho",
+ "America/Puerto_Rico",
+ "America/Punta_Arenas",
+ "America/Rainy_River",
+ "America/Rankin_Inlet",
+ "America/Recife",
+ "America/Regina",
+ "America/Resolute",
+ "America/Rio_Branco",
+ "America/Rosario",
+ "America/Santa_Isabel",
+ "America/Santarem",
+ "America/Santiago",
+ "America/Santo_Domingo",
+ "America/Sao_Paulo",
+ "America/Scoresbysund",
+ "America/Shiprock",
+ "America/Sitka",
+ "America/St_Barthelemy",
+ "America/St_Johns",
+ "America/St_Kitts",
+ "America/St_Lucia",
+ "America/St_Thomas",
+ "America/St_Vincent",
+ "America/Swift_Current",
+ "America/Tegucigalpa",
+ "America/Thule",
+ "America/Thunder_Bay",
+ "America/Tijuana",
+ "America/Toronto",
+ "America/Tortola",
+ "America/Vancouver",
+ "America/Virgin",
+ "America/Whitehorse",
+ "America/Winnipeg",
+ "America/Yakutat",
+ "America/Yellowknife",
+ "Antarctica/Casey",
+ "Antarctica/Davis",
+ "Antarctica/DumontDUrville",
+ "Antarctica/Macquarie",
+ "Antarctica/Mawson",
+ "Antarctica/McMurdo",
+ "Antarctica/Palmer",
+ "Antarctica/Rothera",
+ "Antarctica/South_Pole",
+ "Antarctica/Syowa",
+ "Antarctica/Troll",
+ "Antarctica/Vostok",
+ "Arctic/Longyearbyen",
+ "Asia/Aden",
+ "Asia/Almaty",
+ "Asia/Amman",
+ "Asia/Anadyr",
+ "Asia/Aqtau",
+ "Asia/Aqtobe",
+ "Asia/Ashgabat",
+ "Asia/Ashkhabad",
+ "Asia/Atyrau",
+ "Asia/Baghdad",
+ "Asia/Bahrain",
+ "Asia/Baku",
+ "Asia/Bangkok",
+ "Asia/Barnaul",
+ "Asia/Beirut",
+ "Asia/Bishkek",
+ "Asia/Brunei",
+ "Asia/Calcutta",
+ "Asia/Chita",
+ "Asia/Choibalsan",
+ "Asia/Chongqing",
+ "Asia/Chungking",
+ "Asia/Colombo",
+ "Asia/Dacca",
+ "Asia/Damascus",
+ "Asia/Dhaka",
+ "Asia/Dili",
+ "Asia/Dubai",
+ "Asia/Dushanbe",
+ "Asia/Famagusta",
+ "Asia/Gaza",
+ "Asia/Harbin",
+ "Asia/Hebron",
+ "Asia/Ho_Chi_Minh",
+ "Asia/Hong_Kong",
+ "Asia/Hovd",
+ "Asia/Irkutsk",
+ "Asia/Istanbul",
+ "Asia/Jakarta",
+ "Asia/Jayapura",
+ "Asia/Jerusalem",
+ "Asia/Kabul",
+ "Asia/Kamchatka",
+ "Asia/Karachi",
+ "Asia/Kashgar",
+ "Asia/Kathmandu",
+ "Asia/Katmandu",
+ "Asia/Khandyga",
+ "Asia/Kolkata",
+ "Asia/Krasnoyarsk",
+ "Asia/Kuala_Lumpur",
+ "Asia/Kuching",
+ "Asia/Kuwait",
+ "Asia/Macao",
+ "Asia/Macau",
+ "Asia/Magadan",
+ "Asia/Makassar",
+ "Asia/Manila",
+ "Asia/Muscat",
+ "Asia/Nicosia",
+ "Asia/Novokuznetsk",
+ "Asia/Novosibirsk",
+ "Asia/Omsk",
+ "Asia/Oral",
+ "Asia/Phnom_Penh",
+ "Asia/Pontianak",
+ "Asia/Pyongyang",
+ "Asia/Qatar",
+ "Asia/Qostanay",
+ "Asia/Qyzylorda",
+ "Asia/Rangoon",
+ "Asia/Riyadh",
+ "Asia/Saigon",
+ "Asia/Sakhalin",
+ "Asia/Samarkand",
+ "Asia/Seoul",
+ "Asia/Shanghai",
+ "Asia/Singapore",
+ "Asia/Srednekolymsk",
+ "Asia/Taipei",
+ "Asia/Tashkent",
+ "Asia/Tbilisi",
+ "Asia/Tehran",
+ "Asia/Tel_Aviv",
+ "Asia/Thimbu",
+ "Asia/Thimphu",
+ "Asia/Tokyo",
+ "Asia/Tomsk",
+ "Asia/Ujung_Pandang",
+ "Asia/Ulaanbaatar",
+ "Asia/Ulan_Bator",
+ "Asia/Urumqi",
+ "Asia/Ust-Nera",
+ "Asia/Vientiane",
+ "Asia/Vladivostok",
+ "Asia/Yakutsk",
+ "Asia/Yangon",
+ "Asia/Yekaterinburg",
+ "Asia/Yerevan",
+ "Atlantic/Azores",
+ "Atlantic/Bermuda",
+ "Atlantic/Canary",
+ "Atlantic/Cape_Verde",
+ "Atlantic/Faeroe",
+ "Atlantic/Faroe",
+ "Atlantic/Jan_Mayen",
+ "Atlantic/Madeira",
+ "Atlantic/Reykjavik",
+ "Atlantic/South_Georgia",
+ "Atlantic/St_Helena",
+ "Atlantic/Stanley",
+ "Australia/ACT",
+ "Australia/Adelaide",
+ "Australia/Brisbane",
+ "Australia/Broken_Hill",
+ "Australia/Canberra",
+ "Australia/Currie",
+ "Australia/Darwin",
+ "Australia/Eucla",
+ "Australia/Hobart",
+ "Australia/LHI",
+ "Australia/Lindeman",
+ "Australia/Lord_Howe",
+ "Australia/Melbourne",
+ "Australia/NSW",
+ "Australia/North",
+ "Australia/Perth",
+ "Australia/Queensland",
+ "Australia/South",
+ "Australia/Sydney",
+ "Australia/Tasmania",
+ "Australia/Victoria",
+ "Australia/West",
+ "Australia/Yancowinna",
+ "Brazil/Acre",
+ "Brazil/DeNoronha",
+ "Brazil/East",
+ "Brazil/West",
+ "CET",
+ "CST6CDT",
+ "Canada/Atlantic",
+ "Canada/Central",
+ "Canada/Eastern",
+ "Canada/Mountain",
+ "Canada/Newfoundland",
+ "Canada/Pacific",
+ "Canada/Saskatchewan",
+ "Canada/Yukon",
+ "Chile/Continental",
+ "Chile/EasterIsland",
+ "Cuba",
+ "EET",
+ "EST",
+ "EST5EDT",
+ "Egypt",
+ "Eire",
+ "Etc/GMT",
+ "Etc/GMT+0",
+ "Etc/GMT+1",
+ "Etc/GMT+10",
+ "Etc/GMT+11",
+ "Etc/GMT+12",
+ "Etc/GMT+2",
+ "Etc/GMT+3",
+ "Etc/GMT+4",
+ "Etc/GMT+5",
+ "Etc/GMT+6",
+ "Etc/GMT+7",
+ "Etc/GMT+8",
+ "Etc/GMT+9",
+ "Etc/GMT-0",
+ "Etc/GMT-1",
+ "Etc/GMT-10",
+ "Etc/GMT-11",
+ "Etc/GMT-12",
+ "Etc/GMT-13",
+ "Etc/GMT-14",
+ "Etc/GMT-2",
+ "Etc/GMT-3",
+ "Etc/GMT-4",
+ "Etc/GMT-5",
+ "Etc/GMT-6",
+ "Etc/GMT-7",
+ "Etc/GMT-8",
+ "Etc/GMT-9",
+ "Etc/GMT0",
+ "Etc/Greenwich",
+ "Etc/UCT",
+ "Etc/UTC",
+ "Etc/Universal",
+ "Etc/Zulu",
+ "Europe/Amsterdam",
+ "Europe/Andorra",
+ "Europe/Astrakhan",
+ "Europe/Athens",
+ "Europe/Belfast",
+ "Europe/Belgrade",
+ "Europe/Berlin",
+ "Europe/Bratislava",
+ "Europe/Brussels",
+ "Europe/Bucharest",
+ "Europe/Budapest",
+ "Europe/Busingen",
+ "Europe/Chisinau",
+ "Europe/Copenhagen",
+ "Europe/Dublin",
+ "Europe/Gibraltar",
+ "Europe/Guernsey",
+ "Europe/Helsinki",
+ "Europe/Isle_of_Man",
+ "Europe/Istanbul",
+ "Europe/Jersey",
+ "Europe/Kaliningrad",
+ "Europe/Kiev",
+ "Europe/Kirov",
+ "Europe/Lisbon",
+ "Europe/Ljubljana",
+ "Europe/London",
+ "Europe/Luxembourg",
+ "Europe/Madrid",
+ "Europe/Malta",
+ "Europe/Mariehamn",
+ "Europe/Minsk",
+ "Europe/Monaco",
+ "Europe/Moscow",
+ "Europe/Nicosia",
+ "Europe/Oslo",
+ "Europe/Paris",
+ "Europe/Podgorica",
+ "Europe/Prague",
+ "Europe/Riga",
+ "Europe/Rome",
+ "Europe/Samara",
+ "Europe/San_Marino",
+ "Europe/Sarajevo",
+ "Europe/Saratov",
+ "Europe/Simferopol",
+ "Europe/Skopje",
+ "Europe/Sofia",
+ "Europe/Stockholm",
+ "Europe/Tallinn",
+ "Europe/Tirane",
+ "Europe/Tiraspol",
+ "Europe/Ulyanovsk",
+ "Europe/Uzhgorod",
+ "Europe/Vaduz",
+ "Europe/Vatican",
+ "Europe/Vienna",
+ "Europe/Vilnius",
+ "Europe/Volgograd",
+ "Europe/Warsaw",
+ "Europe/Zagreb",
+ "Europe/Zaporozhye",
+ "Europe/Zurich",
+ "GB",
+ "GB-Eire",
+ "GMT",
+ "GMT+0",
+ "GMT-0",
+ "GMT0",
+ "Greenwich",
+ "HST",
+ "Hongkong",
+ "Iceland",
+ "Indian/Antananarivo",
+ "Indian/Chagos",
+ "Indian/Christmas",
+ "Indian/Cocos",
+ "Indian/Comoro",
+ "Indian/Kerguelen",
+ "Indian/Mahe",
+ "Indian/Maldives",
+ "Indian/Mauritius",
+ "Indian/Mayotte",
+ "Indian/Reunion",
+ "Iran",
+ "Israel",
+ "Jamaica",
+ "Japan",
+ "Kwajalein",
+ "Libya",
+ "MET",
+ "MST",
+ "MST7MDT",
+ "Mexico/BajaNorte",
+ "Mexico/BajaSur",
+ "Mexico/General",
+ "NZ",
+ "NZ-CHAT",
+ "Navajo",
+ "PRC",
+ "PST8PDT",
+ "Pacific/Apia",
+ "Pacific/Auckland",
+ "Pacific/Bougainville",
+ "Pacific/Chatham",
+ "Pacific/Chuuk",
+ "Pacific/Easter",
+ "Pacific/Efate",
+ "Pacific/Enderbury",
+ "Pacific/Fakaofo",
+ "Pacific/Fiji",
+ "Pacific/Funafuti",
+ "Pacific/Galapagos",
+ "Pacific/Gambier",
+ "Pacific/Guadalcanal",
+ "Pacific/Guam",
+ "Pacific/Honolulu",
+ "Pacific/Johnston",
+ "Pacific/Kiritimati",
+ "Pacific/Kosrae",
+ "Pacific/Kwajalein",
+ "Pacific/Majuro",
+ "Pacific/Marquesas",
+ "Pacific/Midway",
+ "Pacific/Nauru",
+ "Pacific/Niue",
+ "Pacific/Norfolk",
+ "Pacific/Noumea",
+ "Pacific/Pago_Pago",
+ "Pacific/Palau",
+ "Pacific/Pitcairn",
+ "Pacific/Pohnpei",
+ "Pacific/Ponape",
+ "Pacific/Port_Moresby",
+ "Pacific/Rarotonga",
+ "Pacific/Saipan",
+ "Pacific/Samoa",
+ "Pacific/Tahiti",
+ "Pacific/Tarawa",
+ "Pacific/Tongatapu",
+ "Pacific/Truk",
+ "Pacific/Wake",
+ "Pacific/Wallis",
+ "Pacific/Yap",
+ "Poland",
+ "Portugal",
+ "ROC",
+ "ROK",
+ "Singapore",
+ "Turkey",
+ "UCT",
+ "US/Alaska",
+ "US/Aleutian",
+ "US/Arizona",
+ "US/Central",
+ "US/East-Indiana",
+ "US/Eastern",
+ "US/Hawaii",
+ "US/Indiana-Starke",
+ "US/Michigan",
+ "US/Mountain",
+ "US/Pacific",
+ "US/Samoa",
+ "UTC",
+ "Universal",
+ "W-SU",
+ "WET",
+ "Zulu",
+ nullptr};
// Helper to return a loaded time zone by value (UTC on error).
time_zone LoadZone(const std::string& name) {
@@ -666,6 +667,7 @@ int VersionCmp(time_zone tz, const std::string& target) {
} // namespace
+#if !defined(__EMSCRIPTEN__)
TEST(TimeZones, LoadZonesConcurrently) {
std::promise<void> ready_promise;
std::shared_future<void> ready_future(ready_promise.get_future());
@@ -713,6 +715,7 @@ TEST(TimeZones, LoadZonesConcurrently) {
}
EXPECT_LE(failures.size(), max_failures) << testing::PrintToString(failures);
}
+#endif
TEST(TimeZone, NamedTimeZones) {
const time_zone utc = utc_time_zone();
@@ -721,7 +724,8 @@ TEST(TimeZone, NamedTimeZones) {
EXPECT_EQ("America/New_York", nyc.name());
const time_zone syd = LoadZone("Australia/Sydney");
EXPECT_EQ("Australia/Sydney", syd.name());
- const time_zone fixed0 = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ const time_zone fixed0 =
+ fixed_time_zone(absl::time_internal::cctz::seconds::zero());
EXPECT_EQ("UTC", fixed0.name());
const time_zone fixed_pos = fixed_time_zone(
chrono::hours(3) + chrono::minutes(25) + chrono::seconds(45));
@@ -746,7 +750,7 @@ TEST(TimeZone, Failures) {
EXPECT_EQ(chrono::system_clock::from_time_t(0),
convert(civil_second(1970, 1, 1, 0, 0, 0), tz)); // UTC
- // Loading an empty std::string timezone should fail.
+ // Loading an empty string timezone should fail.
tz = LoadZone("America/Los_Angeles");
EXPECT_FALSE(load_time_zone("", &tz));
EXPECT_EQ(chrono::system_clock::from_time_t(0),
@@ -764,7 +768,8 @@ TEST(TimeZone, Equality) {
EXPECT_EQ(implicit_utc, explicit_utc);
EXPECT_EQ(implicit_utc.name(), explicit_utc.name());
- const time_zone fixed_zero = fixed_time_zone(absl::time_internal::cctz::seconds::zero());
+ const time_zone fixed_zero =
+ fixed_time_zone(absl::time_internal::cctz::seconds::zero());
EXPECT_EQ(fixed_zero, LoadZone(fixed_zero.name()));
EXPECT_EQ(fixed_zero, explicit_utc);
@@ -803,8 +808,8 @@ TEST(TimeZone, Equality) {
TEST(StdChronoTimePoint, TimeTAlignment) {
// Ensures that the Unix epoch and the system clock epoch are an integral
// number of seconds apart. This simplifies conversions to/from time_t.
- auto diff = chrono::system_clock::time_point() -
- chrono::system_clock::from_time_t(0);
+ auto diff =
+ chrono::system_clock::time_point() - chrono::system_clock::from_time_t(0);
EXPECT_EQ(chrono::system_clock::time_point::duration::zero(),
diff % chrono::seconds(1));
}
@@ -813,27 +818,27 @@ TEST(BreakTime, TimePointResolution) {
const time_zone utc = utc_time_zone();
const auto t0 = chrono::system_clock::from_time_t(0);
- ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc,
- 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::nanoseconds>(t0), utc, 1970, 1, 1,
+ 0, 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::microseconds>(t0), utc, 1970, 1, 1,
+ 0, 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::milliseconds>(t0), utc, 1970, 1, 1,
+ 0, 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::seconds>(t0), utc, 1970, 1, 1, 0,
+ 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<absl::time_internal::cctz::seconds>(t0),
+ utc, 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::minutes>(t0), utc, 1970, 1, 1, 0,
+ 0, 0, 0, false, "UTC");
+ ExpectTime(chrono::time_point_cast<chrono::hours>(t0), utc, 1970, 1, 1, 0, 0,
+ 0, 0, false, "UTC");
}
TEST(BreakTime, LocalTimeInUTC) {
const time_zone tz = utc_time_zone();
const auto tp = chrono::system_clock::from_time_t(0);
ExpectTime(tp, tz, 1970, 1, 1, 0, 0, 0, 0, false, "UTC");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInUTCUnaligned) {
@@ -841,7 +846,7 @@ TEST(BreakTime, LocalTimeInUTCUnaligned) {
const auto tp =
chrono::system_clock::from_time_t(0) - chrono::milliseconds(500);
ExpectTime(tp, tz, 1969, 12, 31, 23, 59, 59, 0, false, "UTC");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimePosix) {
@@ -849,7 +854,7 @@ TEST(BreakTime, LocalTimePosix) {
const time_zone tz = utc_time_zone();
const auto tp = chrono::system_clock::from_time_t(536457599);
ExpectTime(tp, tz, 1986, 12, 31, 23, 59, 59, 0, false, "UTC");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(TimeZoneImpl, LocalTimeInFixed) {
@@ -859,28 +864,28 @@ TEST(TimeZoneImpl, LocalTimeInFixed) {
const auto tp = chrono::system_clock::from_time_t(0);
ExpectTime(tp, tz, 1969, 12, 31, 15, 26, 13, offset.count(), false,
"-083347");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInNewYork) {
const time_zone tz = LoadZone("America/New_York");
const auto tp = chrono::system_clock::from_time_t(45);
ExpectTime(tp, tz, 1969, 12, 31, 19, 0, 45, -5 * 60 * 60, false, "EST");
- EXPECT_EQ(weekday::wednesday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::wednesday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInMTV) {
const time_zone tz = LoadZone("America/Los_Angeles");
const auto tp = chrono::system_clock::from_time_t(1380855729);
ExpectTime(tp, tz, 2013, 10, 3, 20, 2, 9, -7 * 60 * 60, true, "PDT");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(BreakTime, LocalTimeInSydney) {
const time_zone tz = LoadZone("Australia/Sydney");
const auto tp = chrono::system_clock::from_time_t(90);
ExpectTime(tp, tz, 1970, 1, 1, 10, 1, 30, 10 * 60 * 60, false, "AEST");
- EXPECT_EQ(weekday::thursday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::thursday, get_weekday(convert(tp, tz)));
}
TEST(MakeTime, TimePointResolution) {
@@ -908,9 +913,8 @@ TEST(MakeTime, TimePointResolution) {
chrono::time_point_cast<chrono::minutes>(
convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
EXPECT_EQ("04:00", format("%M:%E*S", tp_m, utc));
- const time_point<chrono::hours> tp_h =
- chrono::time_point_cast<chrono::hours>(
- convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
+ const time_point<chrono::hours> tp_h = chrono::time_point_cast<chrono::hours>(
+ convert(civil_second(2015, 1, 2, 3, 4, 5), utc));
EXPECT_EQ("00:00", format("%M:%E*S", tp_h, utc));
}
@@ -929,7 +933,7 @@ TEST(MakeTime, Normalization) {
// NOTE: Run this with -ftrapv to detect overflow problems.
TEST(MakeTime, SysSecondsLimits) {
- const char RFC3339[] = "%Y-%m-%dT%H:%M:%S%Ez";
+ const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
const time_zone utc = utc_time_zone();
const time_zone east = fixed_time_zone(chrono::hours(14));
const time_zone west = fixed_time_zone(-chrono::hours(14));
@@ -1000,13 +1004,17 @@ TEST(MakeTime, SysSecondsLimits) {
#if defined(_WIN32) || defined(_WIN64)
// localtime_s() and gmtime_s() don't believe in years outside [1970:3000].
#else
- const time_zone utc = LoadZone("libc:UTC");
+ const time_zone cut = LoadZone("libc:UTC");
const year_t max_tm_year = year_t{std::numeric_limits<int>::max()} + 1900;
- tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), utc);
- EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, utc));
+ tp = convert(civil_second(max_tm_year, 12, 31, 23, 59, 59), cut);
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ // The BSD gmtime_r() fails on extreme positive tm_year values.
+#else
+ EXPECT_EQ("2147485547-12-31T23:59:59+00:00", format(RFC3339, tp, cut));
+#endif
const year_t min_tm_year = year_t{std::numeric_limits<int>::min()} + 1900;
- tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), utc);
- EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, utc));
+ tp = convert(civil_second(min_tm_year, 1, 1, 0, 0, 0), cut);
+ EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut));
#endif
}
}
@@ -1018,24 +1026,24 @@ TEST(MakeTime, LocalTimeLibC) {
// 1) we know how to change the time zone used by localtime()/mktime(),
// 2) cctz and localtime()/mktime() will use similar-enough tzdata, and
// 3) we have some idea about how mktime() behaves during transitions.
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
const char* const ep = getenv("TZ");
std::string tz_name = (ep != nullptr) ? ep : "";
for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
ASSERT_EQ(0, setenv("TZ", *np, 1)); // change what "localtime" means
const auto zi = local_time_zone();
const auto lc = LoadZone("libc:localtime");
- time_zone::civil_transition trans;
+ time_zone::civil_transition transition;
for (auto tp = zi.lookup(civil_second()).trans;
- zi.next_transition(tp, &trans);
- tp = zi.lookup(trans.to).trans) {
- const auto fcl = zi.lookup(trans.from);
- const auto tcl = zi.lookup(trans.to);
+ zi.next_transition(tp, &transition);
+ tp = zi.lookup(transition.to).trans) {
+ const auto fcl = zi.lookup(transition.from);
+ const auto tcl = zi.lookup(transition.to);
civil_second cs; // compare cs in zi and lc
if (fcl.kind == time_zone::civil_lookup::UNIQUE) {
if (tcl.kind == time_zone::civil_lookup::UNIQUE) {
// Both unique; must be an is_dst or abbr change.
- ASSERT_EQ(trans.from, trans.to);
+ ASSERT_EQ(transition.from, transition.to);
const auto trans = fcl.trans;
const auto tal = zi.lookup(trans);
const auto tprev = trans - absl::time_internal::cctz::seconds(1);
@@ -1046,11 +1054,11 @@ TEST(MakeTime, LocalTimeLibC) {
continue;
}
ASSERT_EQ(time_zone::civil_lookup::REPEATED, tcl.kind);
- cs = trans.to;
+ cs = transition.to;
} else {
ASSERT_EQ(time_zone::civil_lookup::UNIQUE, tcl.kind);
ASSERT_EQ(time_zone::civil_lookup::SKIPPED, fcl.kind);
- cs = trans.from;
+ cs = transition.from;
}
if (cs.year() > 2037) break; // limit test time (and to 32-bit time_t)
const auto cl_zi = zi.lookup(cs);
@@ -1271,10 +1279,10 @@ TEST(TimeZoneEdgeCase, PacificApia) {
// 1325239200 == Sat, 31 Dec 2011 00:00:00 +1400 (+14)
auto tp = convert(civil_second(2011, 12, 29, 23, 59, 59), tz);
ExpectTime(tp, tz, 2011, 12, 29, 23, 59, 59, -10 * 3600, true, "-10");
- EXPECT_EQ(363, get_yearday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(363, get_yearday(convert(tp, tz)));
tp += absl::time_internal::cctz::seconds(1);
ExpectTime(tp, tz, 2011, 12, 31, 0, 0, 0, 14 * 3600, true, "+14");
- EXPECT_EQ(365, get_yearday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(365, get_yearday(convert(tp, tz)));
}
TEST(TimeZoneEdgeCase, AfricaCairo) {
@@ -1396,10 +1404,10 @@ TEST(TimeZoneEdgeCase, NegativeYear) {
const time_zone tz = utc_time_zone();
auto tp = convert(civil_second(0, 1, 1, 0, 0, 0), tz);
ExpectTime(tp, tz, 0, 1, 1, 0, 0, 0, 0 * 3600, false, "UTC");
- EXPECT_EQ(weekday::saturday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::saturday, get_weekday(convert(tp, tz)));
tp -= absl::time_internal::cctz::seconds(1);
ExpectTime(tp, tz, -1, 12, 31, 23, 59, 59, 0 * 3600, false, "UTC");
- EXPECT_EQ(weekday::friday, get_weekday(civil_day(convert(tp, tz))));
+ EXPECT_EQ(weekday::friday, get_weekday(convert(tp, tz)));
}
TEST(TimeZoneEdgeCase, UTC32bitLimit) {
@@ -1430,4 +1438,5 @@ TEST(TimeZoneEdgeCase, UTC5DigitYear) {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc
index 75ad8bcba93..5cdd09e89d0 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,7 +19,10 @@
#include <limits>
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -100,9 +103,9 @@ const char* ParseDateTime(const char* p, PosixTransition* res) {
int weekday = 0;
if ((p = ParseInt(p + 1, 0, 6, &weekday)) != nullptr) {
res->date.fmt = PosixTransition::M;
- res->date.m.month = static_cast<int_fast8_t>(month);
- res->date.m.week = static_cast<int_fast8_t>(week);
- res->date.m.weekday = static_cast<int_fast8_t>(weekday);
+ res->date.m.month = static_cast<std::int_fast8_t>(month);
+ res->date.m.week = static_cast<std::int_fast8_t>(week);
+ res->date.m.weekday = static_cast<std::int_fast8_t>(weekday);
}
}
}
@@ -110,13 +113,13 @@ const char* ParseDateTime(const char* p, PosixTransition* res) {
int day = 0;
if ((p = ParseInt(p + 1, 1, 365, &day)) != nullptr) {
res->date.fmt = PosixTransition::J;
- res->date.j.day = static_cast<int_fast16_t>(day);
+ res->date.j.day = static_cast<std::int_fast16_t>(day);
}
} else {
int day = 0;
if ((p = ParseInt(p, 0, 365, &day)) != nullptr) {
res->date.fmt = PosixTransition::N;
- res->date.j.day = static_cast<int_fast16_t>(day);
+ res->date.n.day = static_cast<std::int_fast16_t>(day);
}
}
}
@@ -152,4 +155,5 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res) {
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h
index ef2a8c1647d..0cf29055f56 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/time_zone_posix.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -55,7 +55,10 @@
#include <cstdint>
#include <string>
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -123,6 +126,7 @@ bool ParsePosixSpec(const std::string& spec, PosixTimeZone* res);
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_INTERNAL_CCTZ_TIME_ZONE_POSIX_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/tzfile.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
index 4485ba55e01..269fa36c537 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
@@ -22,33 +22,35 @@
*/
#ifndef TZDIR
-#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
-#endif /* !defined TZDIR */
+#define TZDIR "/usr/share/zoneinfo" /* Time zone object file directory */
+#endif /* !defined TZDIR */
#ifndef TZDEFAULT
-#define TZDEFAULT "/etc/localtime"
+#define TZDEFAULT "/etc/localtime"
#endif /* !defined TZDEFAULT */
#ifndef TZDEFRULES
-#define TZDEFRULES "posixrules"
+#define TZDEFRULES "posixrules"
#endif /* !defined TZDEFRULES */
+/* See Internet RFC 8536 for more details about the following format. */
+
/*
** Each file begins with. . .
*/
-#define TZ_MAGIC "TZif"
+#define TZ_MAGIC "TZif"
struct tzhead {
- char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
- char tzh_reserved[15]; /* reserved; must be zero */
- char tzh_ttisgmtcnt[4]; /* coded number of trans. time flags */
- char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
- char tzh_leapcnt[4]; /* coded number of leap seconds */
- char tzh_timecnt[4]; /* coded number of transition times */
- char tzh_typecnt[4]; /* coded number of local time types */
- char tzh_charcnt[4]; /* coded number of abbr. chars */
+ char tzh_magic[4]; /* TZ_MAGIC */
+ char tzh_version[1]; /* '\0' or '2' or '3' as of 2013 */
+ char tzh_reserved[15]; /* reserved; must be zero */
+ char tzh_ttisutcnt[4]; /* coded number of trans. time flags */
+ char tzh_ttisstdcnt[4]; /* coded number of trans. time flags */
+ char tzh_leapcnt[4]; /* coded number of leap seconds */
+ char tzh_timecnt[4]; /* coded number of transition times */
+ char tzh_typecnt[4]; /* coded number of local time types */
+ char tzh_charcnt[4]; /* coded number of abbr. chars */
};
/*
@@ -66,27 +68,28 @@ struct tzhead {
** one (char [4]) total correction after above
** tzh_ttisstdcnt (char)s indexed by type; if 1, transition
** time is standard time, if 0,
-** transition time is wall clock time
-** if absent, transition times are
-** assumed to be wall clock time
-** tzh_ttisgmtcnt (char)s indexed by type; if 1, transition
-** time is UT, if 0,
-** transition time is local time
-** if absent, transition times are
+** transition time is local (wall clock)
+** time; if absent, transition times are
** assumed to be local time
+** tzh_ttisutcnt (char)s indexed by type; if 1, transition
+** time is UT, if 0, transition time is
+** local time; if absent, transition
+** times are assumed to be local time.
+** When this is 1, the corresponding
+** std/wall indicator must also be 1.
*/
/*
** If tzh_version is '2' or greater, the above is followed by a second instance
** of tzhead and a second instance of the data in which each coded transition
** time uses 8 rather than 4 chars,
-** then a POSIX-TZ-environment-variable-style std::string for use in handling
+** then a POSIX-TZ-environment-variable-style string for use in handling
** instants after the last transition time stored in the file
** (with nothing between the newlines if there is no POSIX representation for
** such instants).
**
** If tz_version is '3' or greater, the above is extended as follows.
-** First, the POSIX TZ std::string's hour offset may range from -167
+** First, the POSIX TZ string's hour offset may range from -167
** through 167 as compared to the POSIX-required 0 through 24.
** Second, its DST start time may be January 1 at 00:00 and its stop
** time December 31 at 24:00 plus the difference between DST and
@@ -99,21 +102,21 @@ struct tzhead {
*/
#ifndef TZ_MAX_TIMES
-#define TZ_MAX_TIMES 2000
+#define TZ_MAX_TIMES 2000
#endif /* !defined TZ_MAX_TIMES */
#ifndef TZ_MAX_TYPES
/* This must be at least 17 for Europe/Samara and Europe/Vilnius. */
-#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined TZ_MAX_TYPES */
+#define TZ_MAX_TYPES 256 /* Limited by what (unsigned char)'s can hold */
+#endif /* !defined TZ_MAX_TYPES */
#ifndef TZ_MAX_CHARS
-#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
- /* (limited by what unsigned chars can hold) */
-#endif /* !defined TZ_MAX_CHARS */
+#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */
+ /* (limited by what unsigned chars can hold) */
+#endif /* !defined TZ_MAX_CHARS */
#ifndef TZ_MAX_LEAPS
-#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
-#endif /* !defined TZ_MAX_LEAPS */
+#define TZ_MAX_LEAPS 50 /* Maximum number of leap second corrections */
+#endif /* !defined TZ_MAX_LEAPS */
#endif /* !defined TZFILE_H */
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
index bf2d2d2d2b5..72095339c3c 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,10 @@
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
+#include "absl/base/config.h"
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz {
@@ -24,9 +27,11 @@ std::string ZoneInfoSource::Version() const { return std::string(); }
} // namespace cctz
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz_extension {
@@ -36,8 +41,9 @@ namespace {
// defers to the fallback factory.
std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
const std::string& name,
- const std::function<std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
- const std::string& name)>& fallback_factory) {
+ const std::function<
+ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource>(
+ const std::string& name)>& fallback_factory) {
return fallback_factory(name);
}
@@ -46,34 +52,65 @@ std::unique_ptr<absl::time_internal::cctz::ZoneInfoSource> DefaultFactory(
// A "weak" definition for cctz_extension::zone_info_source_factory.
// The user may override this with their own "strong" definition (see
// zone_info_source.h).
-#if defined(_MSC_VER)
+#if !defined(__has_attribute)
+#define __has_attribute(x) 0
+#endif
+// MinGW is GCC on Windows, so while it asserts __has_attribute(weak), the
+// Windows linker cannot handle that. Nor does the MinGW compiler know how to
+// pass "#pragma comment(linker, ...)" to the Windows linker.
+#if (__has_attribute(weak) || defined(__GNUC__)) && !defined(__MINGW32__)
+ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =
+ DefaultFactory;
+#elif defined(_MSC_VER) && !defined(__MINGW32__) && !defined(_LIBCPP_VERSION)
extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory;
ZoneInfoSourceFactory default_factory = DefaultFactory;
#if defined(_M_IX86)
-#pragma comment( \
- linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZA")
-#elif defined(_M_IA_64) || defined(_M_AMD64)
-#pragma comment( \
- linker, \
- "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA=?default_factory@cctz_extension@time_internal@absl@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@5@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@absl@@U?$default_delete@VZoneInfoSource@cctz@time_internal@absl@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@5@@ZEA")
+#pragma comment( \
+ linker, \
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@ABV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZA")
+#elif defined(_M_IA_64) || defined(_M_AMD64) || defined(_M_ARM) || \
+ defined(_M_ARM64)
+#pragma comment( \
+ linker, \
+ "/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZEA=?default_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@3P6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@AEBV?$function@$$A6A?AV?$unique_ptr@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@U?$default_delete@VZoneInfoSource@cctz@time_internal@" ABSL_INTERNAL_MANGLED_NS \
+ "@@@std@@@std@@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@@Z@" ABSL_INTERNAL_MANGLED_BACKREFERENCE \
+ "@@ZEA")
#else
#error Unsupported MSVC platform
-#endif
-#else // _MSC_VER
-#if !defined(__has_attribute)
-#define __has_attribute(x) 0
-#endif
-#if __has_attribute(weak) || defined(__GNUC__)
-ZoneInfoSourceFactory zone_info_source_factory
- __attribute__((weak)) = DefaultFactory;
+#endif // _M_<PLATFORM>
#else
// Make it a "strong" definition if we have no other choice.
ZoneInfoSourceFactory zone_info_source_factory = DefaultFactory;
#endif
-#endif // _MSC_VER
} // namespace cctz_extension
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/version b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/version
index ac954d74f97..1d590958afd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/version
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2018g-9-gf0d2759
+2021a
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
index c2e0f8eafc0..a4ff61a4d32 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/iso3166.tab
@@ -9,8 +9,8 @@
# All text uses UTF-8 encoding. The columns of the table are as follows:
#
# 1. ISO 3166-1 alpha-2 country code, current as of
-# ISO 3166-1 N905 (2016-11-15). See: Updates on ISO 3166-1
-# http://isotc.iso.org/livelink/livelink/Open/16944257
+# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1
+# https://isotc.iso.org/livelink/livelink/Open/16944257
# 2. The usual English name for the coded region,
# chosen so that alphabetic sorting of subsets produces helpful lists.
# This is not the same as the English name in the ISO 3166 tables.
@@ -166,7 +166,7 @@ ME Montenegro
MF St Martin (French)
MG Madagascar
MH Marshall Islands
-MK Macedonia
+MK North Macedonia
ML Mali
MM Myanmar (Burma)
MN Mongolia
@@ -235,7 +235,7 @@ ST Sao Tome & Principe
SV El Salvador
SX St Maarten (Dutch)
SY Syria
-SZ Swaziland
+SZ Eswatini (Swaziland)
TC Turks & Caicos Is
TD Chad
TF French Southern & Antarctic Lands
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index 2729e6e8f9a..396e4d3810b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -63,8 +63,7 @@ AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
AU -5430+15857 Antarctica/Macquarie Macquarie Island
-AU -4253+14719 Australia/Hobart Tasmania (most areas)
-AU -3956+14352 Australia/Currie Tasmania (King Island)
+AU -4253+14719 Australia/Hobart Tasmania
AU -3749+14458 Australia/Melbourne Victoria
AU -3352+15113 Australia/Sydney New South Wales (most areas)
AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
@@ -127,9 +126,9 @@ CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
CA +5946-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
+CA +6043-13503 America/Whitehorse MST - Yukon (east)
+CA +6404-13925 America/Dawson MST - Yukon (west)
CA +4916-12307 America/Vancouver Pacific - BC (most areas)
-CA +6043-13503 America/Whitehorse Pacific - Yukon (south)
-CA +6404-13925 America/Dawson Pacific - Yukon (north)
CC -1210+09655 Indian/Cocos
CH,DE,LI +4723+00832 Europe/Zurich Swiss time
CI,BF,GM,GN,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
@@ -173,7 +172,7 @@ GE +4143+04449 Asia/Tbilisi
GF +0456-05220 America/Cayenne
GH +0533-00013 Africa/Accra
GI +3608-00521 Europe/Gibraltar
-GL +6411-05144 America/Godthab Greenland (most areas)
+GL +6411-05144 America/Nuuk Greenland (most areas)
GL +7646-01840 America/Danmarkshavn National Park (east coast)
GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
GL +7634-06847 America/Thule Thule/Pituffik
@@ -211,6 +210,7 @@ KP +3901+12545 Asia/Pyongyang
KR +3733+12658 Asia/Seoul
KZ +4315+07657 Asia/Almaty Kazakhstan (most areas)
KZ +4448+06528 Asia/Qyzylorda Qyzylorda/Kyzylorda/Kzyl-Orda
+KZ +5312+06337 Asia/Qostanay Qostanay/Kostanay/Kustanay
KZ +5017+05710 Asia/Aqtobe Aqtöbe/Aktobe
KZ +4431+05016 Asia/Aqtau Mangghystaū/Mankistau
KZ +4707+05156 Asia/Atyrau Atyraū/Atirau/Gur'yev
@@ -288,10 +288,11 @@ RO +4426+02606 Europe/Bucharest
RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
-RU +4457+03406 Europe/Simferopol MSK+00 - Crimea
+# Mention RU and UA alphabetically. See "territorial claims" above.
+RU,UA +4457+03406 Europe/Simferopol Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
+RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
-RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
@@ -339,8 +340,8 @@ TT,AG,AI,BL,DM,GD,GP,KN,LC,MF,MS,VC,VG,VI +1039-06131 America/Port_of_Spain
TV -0831+17913 Pacific/Funafuti
TW +2503+12130 Asia/Taipei
UA +5026+03031 Europe/Kiev Ukraine (most areas)
-UA +4837+02218 Europe/Uzhgorod Ruthenia
-UA +4750+03510 Europe/Zaporozhye Zaporozh'ye/Zaporizhia; Lugansk/Luhansk (east)
+UA +4837+02218 Europe/Uzhgorod Transcarpathia
+UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk
UM +1917+16637 Pacific/Wake Wake Island
US +404251-0740023 America/New_York Eastern (most areas)
US +421953-0830245 America/Detroit Eastern - MI (most areas)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_chrono.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_chrono.inc
index cf884a10ed9..5eeb6406aaf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_chrono.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_chrono.inc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -16,6 +16,7 @@
#include <cstdint>
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
static int64_t GetCurrentTimeNanosFromSystem() {
@@ -26,4 +27,5 @@ static int64_t GetCurrentTimeNanosFromSystem() {
}
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_posix.inc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_posix.inc
index 65474ca6da1..42072000ae3 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_posix.inc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/get_current_time_posix.inc
@@ -7,6 +7,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
static int64_t GetCurrentTimeNanosFromSystem() {
@@ -19,4 +20,5 @@ static int64_t GetCurrentTimeNanosFromSystem() {
}
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.cc
index 4483f2a977e..9a485a0750e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -18,12 +18,14 @@
#include <cstddef>
#include <cstring>
+#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/time/internal/cctz/include/cctz/zone_info_source.h"
namespace cctz = absl::time_internal::cctz;
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
TimeZone LoadTimeZone(const std::string& name) {
@@ -33,9 +35,11 @@ TimeZone LoadTimeZone(const std::string& name) {
}
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace time_internal {
namespace cctz_extension {
namespace {
@@ -116,8 +120,12 @@ std::unique_ptr<cctz::ZoneInfoSource> TestFactory(
} // namespace
+#if !defined(__MINGW32__)
+// MinGW does not support the weak symbol extension mechanism.
ZoneInfoSourceFactory zone_info_source_factory = TestFactory;
+#endif
} // namespace cctz_extension
} // namespace time_internal
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.h
index d99402934c6..5c4bf1f680e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/internal/test_util.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -20,12 +20,14 @@
#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/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.cc
index ac2c8a8356f..1ec2026e254 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -33,6 +33,10 @@
#include "absl/time/time.h"
+#if defined(_MSC_VER)
+#include <winsock2.h> // for timeval
+#endif
+
#include <cstring>
#include <ctime>
#include <limits>
@@ -41,7 +45,9 @@
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace cctz = absl::time_internal::cctz;
+
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -54,9 +60,10 @@ inline cctz::time_point<cctz::seconds> unix_epoch() {
inline int64_t FloorToUnit(absl::Duration d, absl::Duration unit) {
absl::Duration rem;
int64_t q = absl::IDivDuration(d, unit, &rem);
- return (q > 0 ||
- rem >= ZeroDuration() ||
- q == std::numeric_limits<int64_t>::min()) ? q : q - 1;
+ return (q > 0 || rem >= ZeroDuration() ||
+ q == std::numeric_limits<int64_t>::min())
+ ? q
+ : q - 1;
}
inline absl::Time::Breakdown InfiniteFutureBreakdown() {
@@ -425,9 +432,17 @@ absl::TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
}
absl::Time FromTM(const struct tm& tm, absl::TimeZone tz) {
- const CivilSecond cs(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
- const auto ti = tz.At(cs);
+ civil_year_t tm_year = tm.tm_year;
+ // Avoids years that are too extreme for CivilSecond to normalize.
+ if (tm_year > 300000000000ll) return InfiniteFuture();
+ if (tm_year < -300000000000ll) return InfinitePast();
+ int tm_mon = tm.tm_mon;
+ if (tm_mon == std::numeric_limits<int>::max()) {
+ tm_mon -= 12;
+ tm_year += 1;
+ }
+ const auto ti = tz.At(CivilSecond(tm_year + 1900, tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec));
return tm.tm_isdst == 0 ? ti.post : ti.pre;
}
@@ -452,8 +467,7 @@ struct tm ToTM(absl::Time t, absl::TimeZone tz) {
tm.tm_year = static_cast<int>(cs.year() - 1900);
}
- const CivilDay cd(cs);
- switch (GetWeekday(cd)) {
+ switch (GetWeekday(cs)) {
case Weekday::sunday:
tm.tm_wday = 0;
break;
@@ -476,10 +490,11 @@ struct tm ToTM(absl::Time t, absl::TimeZone tz) {
tm.tm_wday = 6;
break;
}
- tm.tm_yday = GetYearDay(cd) - 1;
+ tm.tm_yday = GetYearDay(cs) - 1;
tm.tm_isdst = ci.is_dst ? 1 : 0;
return tm;
}
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.h
index ae3b3fad853..2df68581d1b 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -58,7 +58,6 @@
// std::string s = absl::FormatTime(
// "My flight will land in Sydney on %Y-%m-%d at %H:%M:%S",
// landing, syd);
-//
#ifndef ABSL_TIME_TIME_H_
#define ABSL_TIME_TIME_H_
@@ -66,7 +65,14 @@
#if !defined(_MSC_VER)
#include <sys/time.h>
#else
-#include <winsock2.h>
+// We don't include `winsock2.h` because it drags in `windows.h` and friends,
+// and they define conflicting macros like OPAQUE, ERROR, and more. This has the
+// potential to break Abseil users.
+//
+// Instead we only forward declare `timeval` and require Windows users include
+// `winsock2.h` themselves. This is both inconsistent and troublesome, but so is
+// including 'windows.h' so we are picking the lesser of two evils here.
+struct timeval;
#endif
#include <chrono> // NOLINT(build/c++11)
#include <cmath>
@@ -77,12 +83,13 @@
#include <type_traits>
#include <utility>
-#include "absl/base/port.h" // Needed for string vs std::string
+#include "absl/base/macros.h"
#include "absl/strings/string_view.h"
#include "absl/time/civil_time.h"
#include "absl/time/internal/cctz/include/cctz/time_zone.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
class Duration; // Defined below
class Time; // Defined below
@@ -174,6 +181,7 @@ class Duration {
Duration& operator%=(Duration rhs);
// Overloads that forward to either the int64_t or double overloads above.
+ // Integer operands must be representable as int64_t.
template <typename T>
Duration& operator*=(T r) {
int64_t x = r;
@@ -216,6 +224,7 @@ inline Duration operator+(Duration lhs, Duration rhs) { return lhs += rhs; }
inline Duration operator-(Duration lhs, Duration rhs) { return lhs -= rhs; }
// Multiplicative Operators
+// Integer operands must be representable as int64_t.
template <typename T>
Duration operator*(Duration lhs, T rhs) {
return lhs *= rhs;
@@ -370,13 +379,14 @@ constexpr Duration InfiniteDuration();
// Hours()
//
// Factory functions for constructing `Duration` values from an integral number
-// of the unit indicated by the factory function's name.
+// of the unit indicated by the factory function's name. The number must be
+// representable as int64_t.
//
-// Note: no "Days()" factory function exists because "a day" is ambiguous.
+// NOTE: no "Days()" factory function exists because "a day" is ambiguous.
// Civil days are not always 24 hours long, and a 24-hour duration often does
// not correspond with a civil day. If a 24-hour duration is needed, use
-// `absl::Hours(24)`. (If you actually want a civil day, use absl::CivilDay
-// from civil_time.h.)
+// `absl::Hours(24)`. If you actually want a civil day, use absl::CivilDay
+// from civil_time.h.
//
// Example:
//
@@ -413,7 +423,9 @@ Duration Milliseconds(T n) {
template <typename T, time_internal::EnableIfFloat<T> = 0>
Duration Seconds(T n) {
if (n >= 0) { // Note: `NaN >= 0` is false.
- if (n >= (std::numeric_limits<int64_t>::max)()) return InfiniteDuration();
+ if (n >= static_cast<T>((std::numeric_limits<int64_t>::max)())) {
+ return InfiniteDuration();
+ }
return time_internal::MakePosDoubleDuration(n);
} else {
if (std::isnan(n))
@@ -446,12 +458,12 @@ Duration Hours(T n) {
//
// absl::Duration d = absl::Milliseconds(1500);
// int64_t isec = absl::ToInt64Seconds(d); // isec == 1
-int64_t ToInt64Nanoseconds(Duration d);
-int64_t ToInt64Microseconds(Duration d);
-int64_t ToInt64Milliseconds(Duration d);
-int64_t ToInt64Seconds(Duration d);
-int64_t ToInt64Minutes(Duration d);
-int64_t ToInt64Hours(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Nanoseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Microseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Seconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Minutes(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d);
// ToDoubleNanoSeconds()
// ToDoubleMicroseconds()
@@ -468,12 +480,12 @@ int64_t ToInt64Hours(Duration d);
//
// absl::Duration d = absl::Milliseconds(1500);
// double dsec = absl::ToDoubleSeconds(d); // dsec == 1.5
-double ToDoubleNanoseconds(Duration d);
-double ToDoubleMicroseconds(Duration d);
-double ToDoubleMilliseconds(Duration d);
-double ToDoubleSeconds(Duration d);
-double ToDoubleMinutes(Duration d);
-double ToDoubleHours(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleNanoseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMicroseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMilliseconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleSeconds(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMinutes(Duration d);
+ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleHours(Duration d);
// FromChrono()
//
@@ -533,11 +545,15 @@ inline std::ostream& operator<<(std::ostream& os, Duration d) {
// suffix. The valid suffixes are "ns", "us" "ms", "s", "m", and "h".
// Simple examples include "300ms", "-1.5h", and "2h45m". Parses "0" as
// `ZeroDuration()`. Parses "inf" and "-inf" as +/- `InfiniteDuration()`.
-bool ParseDuration(const std::string& dur_string, Duration* d);
+bool ParseDuration(absl::string_view dur_string, Duration* d);
// Support for flag values of type Duration. Duration flags must be specified
// in a format that is valid input for absl::ParseDuration().
+bool AbslParseFlag(absl::string_view text, Duration* dst, std::string* error);
+std::string AbslUnparseFlag(Duration d);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Duration* dst, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
std::string UnparseFlag(Duration d);
// Time
@@ -570,7 +586,6 @@ std::string UnparseFlag(Duration d);
// The `absl::Time` class represents an instant in time as a count of clock
// ticks of some granularity (resolution) from some starting point (epoch).
//
-//
// `absl::Time` uses a resolution that is high enough to avoid loss in
// precision, and a range that is wide enough to avoid overflow, when
// converting between tick counts in most Google time scales (i.e., resolution
@@ -624,7 +639,7 @@ class Time {
// Deprecated. Use `absl::TimeZone::CivilInfo`.
struct
Breakdown {
- int64_t year; // year (e.g., 2013)
+ int64_t year; // year (e.g., 2013)
int month; // month of year [1:12]
int day; // day of month [1:31]
int hour; // hour of day [0:23]
@@ -808,7 +823,11 @@ std::chrono::system_clock::time_point ToChronoTime(Time);
// Additionally, if you'd like to specify a time as a count of
// seconds/milliseconds/etc from the Unix epoch, use an absl::Duration flag
// and add that duration to absl::UnixEpoch() to get an absl::Time.
+bool AbslParseFlag(absl::string_view text, Time* t, std::string* error);
+std::string AbslUnparseFlag(Time t);
+ABSL_DEPRECATED("Use AbslParseFlag() instead.")
bool ParseFlag(const std::string& text, Time* t, std::string* error);
+ABSL_DEPRECATED("Use AbslUnparseFlag() instead.")
std::string UnparseFlag(Time t);
// TimeZone
@@ -837,8 +856,8 @@ std::string UnparseFlag(Time t);
//
// See also:
// - https://github.com/google/cctz
-// - http://www.iana.org/time-zones
-// - http://en.wikipedia.org/wiki/Zoneinfo
+// - https://www.iana.org/time-zones
+// - https://en.wikipedia.org/wiki/Zoneinfo
class TimeZone {
public:
explicit TimeZone(time_internal::cctz::time_zone tz) : cz_(tz) {}
@@ -1002,13 +1021,13 @@ class TimeZone {
// Loads the named zone. May perform I/O on the initial load of the named
// zone. If the name is invalid, or some other kind of error occurs, returns
// `false` and `*tz` is set to the UTC time zone.
-inline bool LoadTimeZone(const std::string& name, TimeZone* tz) {
+inline bool LoadTimeZone(absl::string_view name, TimeZone* tz) {
if (name == "localtime") {
*tz = TimeZone(time_internal::cctz::local_time_zone());
return true;
}
time_internal::cctz::time_zone cz;
- const bool b = time_internal::cctz::load_time_zone(name, &cz);
+ const bool b = time_internal::cctz::load_time_zone(std::string(name), &cz);
*tz = TimeZone(cz);
return b;
}
@@ -1096,7 +1115,7 @@ inline Time FromCivil(CivilSecond ct, TimeZone tz) {
// An `absl::TimeConversion` represents the conversion of year, month, day,
// hour, minute, and second values (i.e., a civil time), in a particular
// `absl::TimeZone`, to a time instant (an absolute time), as returned by
-// `absl::ConvertDateTime()`. Lecacy version of `absl::TimeZone::TimeInfo`.
+// `absl::ConvertDateTime()`. Legacy version of `absl::TimeZone::TimeInfo`.
//
// Deprecated. Use `absl::TimeZone::TimeInfo`.
struct
@@ -1149,7 +1168,9 @@ TimeConversion ConvertDateTime(int64_t year, int mon, int day, int hour,
// absl::Time t = absl::FromDateTime(2017, 9, 26, 9, 30, 0, lax);
// // t = 2017-09-26 09:30:00 -0700
//
-// Deprecated. Use `absl::TimeZone::At(CivilSecond).pre`.
+// Deprecated. Use `absl::FromCivil(CivilSecond, TimeZone)`. Note that the
+// behavior of `FromCivil()` differs from `FromDateTime()` for skipped civil
+// times. If you care about that see `absl::TimeZone::At(absl::CivilSecond)`.
inline Time FromDateTime(int64_t year, int mon, int day, int hour,
int min, int sec, TimeZone tz) {
return ConvertDateTime(year, mon, day, hour, min, sec, tz).pre;
@@ -1159,11 +1180,15 @@ inline Time FromDateTime(int64_t year, int mon, int day, int hour,
//
// Converts the `tm_year`, `tm_mon`, `tm_mday`, `tm_hour`, `tm_min`, and
// `tm_sec` fields to an `absl::Time` using the given time zone. See ctime(3)
-// for a description of the expected values of the tm fields. If the indicated
-// time instant is not unique (see `absl::TimeZone::At(absl::CivilSecond)`
-// above), the `tm_isdst` field is consulted to select the desired instant
-// (`tm_isdst` > 0 means DST, `tm_isdst` == 0 means no DST, `tm_isdst` < 0
-// means use the post-transition offset).
+// for a description of the expected values of the tm fields. If the civil time
+// is unique (see `absl::TimeZone::At(absl::CivilSecond)` above), the matching
+// time instant is returned. Otherwise, the `tm_isdst` field is consulted to
+// choose between the possible results. For a repeated civil time, `tm_isdst !=
+// 0` returns the matching DST instant, while `tm_isdst == 0` returns the
+// matching non-DST instant. For a skipped civil time there is no matching
+// instant, so `tm_isdst != 0` returns the DST instant, and `tm_isdst == 0`
+// returns the non-DST instant, that would have matched if the transition never
+// happened.
Time FromTM(const struct tm& tm, TimeZone tz);
// ToTM()
@@ -1182,15 +1207,15 @@ struct tm ToTM(Time t, TimeZone tz);
// time with UTC offset. Also note the use of "%Y": RFC3339 mandates that
// years have exactly four digits, but we allow them to take their natural
// width.
-extern const char RFC3339_full[]; // %Y-%m-%dT%H:%M:%E*S%Ez
-extern const char RFC3339_sec[]; // %Y-%m-%dT%H:%M:%S%Ez
+ABSL_DLL extern const char RFC3339_full[]; // %Y-%m-%d%ET%H:%M:%E*S%Ez
+ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%d%ET%H:%M:%S%Ez
// RFC1123_full
// RFC1123_no_wday
//
// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
-extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_full[]; // %a, %d %b %E4Y %H:%M:%S %z
+ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// FormatTime()
//
@@ -1205,6 +1230,7 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// - %E#f - Fractional seconds with # digits of precision
// - %E*f - Fractional seconds with full precision (a literal '*')
// - %E4Y - Four-character years (-999 ... -001, 0000, 0001 ... 9999)
+// - %ET - The RFC3339 "date-time" separator "T"
//
// Note that %E0S behaves like %S, and %E0f produces no characters. In
// contrast %E*f always produces at least one digit, which may be '0'.
@@ -1220,7 +1246,7 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
//
// absl::CivilSecond cs(2013, 1, 2, 3, 4, 5);
// absl::Time t = absl::FromCivil(cs, lax);
-// string f = absl::FormatTime("%H:%M:%S", t, lax); // "03:04:05"
+// std::string f = absl::FormatTime("%H:%M:%S", t, lax); // "03:04:05"
// f = absl::FormatTime("%H:%M:%E3S", t, lax); // "03:04:05.000"
//
// Note: If the given `absl::Time` is `absl::InfiniteFuture()`, the returned
@@ -1228,7 +1254,7 @@ extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
// In both cases the given format string and `absl::TimeZone` are ignored.
//
-std::string FormatTime(const std::string& format, Time t, TimeZone tz);
+std::string FormatTime(absl::string_view format, Time t, TimeZone tz);
// Convenience functions that format the given time using the RFC3339_full
// format. The first overload uses the provided TimeZone, while the second
@@ -1247,7 +1273,8 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// returns the corresponding `absl::Time`. Uses strftime()-like formatting
// options, with the same extensions as FormatTime(), but with the
// exceptions that %E#S is interpreted as %E*S, and %E#f as %E*f. %Ez
-// and %E*z also accept the same inputs.
+// and %E*z also accept the same inputs, which (along with %z) includes
+// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
@@ -1289,7 +1316,7 @@ inline std::ostream& operator<<(std::ostream& os, Time t) {
// If the input string is "infinite-past", the returned `absl::Time` will be
// `absl::InfinitePast()` and `true` will be returned.
//
-bool ParseTime(const std::string& format, const std::string& input, Time* time,
+bool ParseTime(absl::string_view format, absl::string_view input, Time* time,
std::string* err);
// Like ParseTime() above, but if the format string does not contain a UTC
@@ -1299,7 +1326,7 @@ bool ParseTime(const std::string& format, const std::string& input, Time* time,
// of ambiguity or non-existence, in which case the "pre" time (as defined
// by TimeZone::TimeInfo) is returned. For these reasons we recommend that
// all date/time strings include a UTC offset so they're context independent.
-bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
+bool ParseTime(absl::string_view format, absl::string_view input, TimeZone tz,
Time* time, std::string* err);
// ============================================================================
@@ -1324,8 +1351,8 @@ constexpr Duration MakeDuration(int64_t hi, int64_t lo) {
// it's positive and can be converted to int64_t without risk of UB.
inline Duration MakePosDoubleDuration(double n) {
const int64_t int_secs = static_cast<int64_t>(n);
- const uint32_t ticks =
- static_cast<uint32_t>((n - int_secs) * kTicksPerSecond + 0.5);
+ const uint32_t ticks = static_cast<uint32_t>(
+ (n - static_cast<double>(int_secs)) * kTicksPerSecond + 0.5);
return ticks < kTicksPerSecond
? MakeDuration(int_secs, ticks)
: MakeDuration(int_secs + 1, ticks - kTicksPerSecond);
@@ -1392,8 +1419,7 @@ constexpr Duration FromInt64(int64_t v, std::ratio<3600>) {
// IsValidRep64<T>(0) is true if the expression `int64_t{std::declval<T>()}` is
// valid. That is, if a T can be assigned to an int64_t without narrowing.
template <typename T>
-constexpr auto IsValidRep64(int)
- -> decltype(int64_t{std::declval<T>()}, bool()) {
+constexpr auto IsValidRep64(int) -> decltype(int64_t{std::declval<T>()} == 0) {
return true;
}
template <typename T>
@@ -1449,6 +1475,7 @@ T ToChronoDuration(Duration d) {
}
} // namespace time_internal
+
constexpr Duration Nanoseconds(int64_t n) {
return time_internal::FromInt64(n, std::nano{});
}
@@ -1471,12 +1498,10 @@ constexpr Duration Hours(int64_t n) {
constexpr bool operator<(Duration lhs, Duration rhs) {
return time_internal::GetRepHi(lhs) != time_internal::GetRepHi(rhs)
? time_internal::GetRepHi(lhs) < time_internal::GetRepHi(rhs)
- : time_internal::GetRepHi(lhs) ==
- (std::numeric_limits<int64_t>::min)()
- ? time_internal::GetRepLo(lhs) + 1 <
- time_internal::GetRepLo(rhs) + 1
- : time_internal::GetRepLo(lhs) <
- time_internal::GetRepLo(rhs);
+ : time_internal::GetRepHi(lhs) == (std::numeric_limits<int64_t>::min)()
+ ? time_internal::GetRepLo(lhs) + 1 <
+ time_internal::GetRepLo(rhs) + 1
+ : time_internal::GetRepLo(lhs) < time_internal::GetRepLo(rhs);
}
constexpr bool operator==(Duration lhs, Duration rhs) {
@@ -1554,6 +1579,7 @@ constexpr Time FromTimeT(time_t t) {
return time_internal::FromUnixDuration(Seconds(t));
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TIME_TIME_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_benchmark.cc
index 9bbed6f81af..99e6279984e 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_benchmark.cc
@@ -3,7 +3,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_test.cc
index 4d71070925f..cde9423feb1 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,10 @@
#include "absl/time/time.h"
+#if defined(_MSC_VER)
+#include <winsock2.h> // for timeval
+#endif
+
#include <chrono> // NOLINT(build/c++11)
#include <cstring>
#include <ctime>
@@ -23,12 +27,13 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/numeric/int128.h"
#include "absl/time/clock.h"
#include "absl/time/internal/test_util.h"
namespace {
-#if GTEST_USES_SIMPLE_RE
+#if defined(GTEST_USES_SIMPLE_RE) && GTEST_USES_SIMPLE_RE
const char kZoneAbbrRE[] = ".*"; // just punt
#else
const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
@@ -53,8 +58,7 @@ const char kZoneAbbrRE[] = "[A-Za-z]{3,4}|[-+][0-9]{2}([0-9]{2})?";
// timespec ts1, ts2;
// EXPECT_THAT(ts1, TimespecMatcher(ts2));
MATCHER_P(TimespecMatcher, ts, "") {
- if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec)
- return true;
+ if (ts.tv_sec == arg.tv_sec && ts.tv_nsec == arg.tv_nsec) return true;
*result_listener << "expected: {" << ts.tv_sec << ", " << ts.tv_nsec << "} ";
*result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_nsec << "}";
return false;
@@ -64,8 +68,7 @@ MATCHER_P(TimespecMatcher, ts, "") {
// timeval tv1, tv2;
// EXPECT_THAT(tv1, TimevalMatcher(tv2));
MATCHER_P(TimevalMatcher, tv, "") {
- if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec)
- return true;
+ if (tv.tv_sec == arg.tv_sec && tv.tv_usec == arg.tv_usec) return true;
*result_listener << "expected: {" << tv.tv_sec << ", " << tv.tv_usec << "} ";
*result_listener << "actual: {" << arg.tv_sec << ", " << arg.tv_usec << "}";
return false;
@@ -98,7 +101,7 @@ TEST(Time, ValueSemantics) {
EXPECT_EQ(a, b);
EXPECT_EQ(a, c);
EXPECT_EQ(b, c);
- b = c; // Assignment
+ b = c; // Assignment
EXPECT_EQ(a, b);
EXPECT_EQ(a, c);
EXPECT_EQ(b, c);
@@ -108,7 +111,7 @@ TEST(Time, UnixEpoch) {
const auto ci = absl::UTCTimeZone().At(absl::UnixEpoch());
EXPECT_EQ(absl::CivilSecond(1970, 1, 1, 0, 0, 0), ci.cs);
EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
- EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs));
}
TEST(Time, Breakdown) {
@@ -119,14 +122,14 @@ TEST(Time, Breakdown) {
auto ci = tz.At(t);
EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 19, 0, 0, -18000, false);
EXPECT_EQ(absl::ZeroDuration(), ci.subsecond);
- EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs));
// Just before the epoch.
t -= absl::Nanoseconds(1);
ci = tz.At(t);
EXPECT_CIVIL_INFO(ci, 1969, 12, 31, 18, 59, 59, -18000, false);
EXPECT_EQ(absl::Nanoseconds(999999999), ci.subsecond);
- EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::wednesday, absl::GetWeekday(ci.cs));
// Some time later.
t += absl::Hours(24) * 2735;
@@ -135,7 +138,7 @@ TEST(Time, Breakdown) {
ci = tz.At(t);
EXPECT_CIVIL_INFO(ci, 1977, 6, 28, 14, 30, 15, -14400, true);
EXPECT_EQ(8, ci.subsecond / absl::Nanoseconds(1));
- EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::tuesday, absl::GetWeekday(ci.cs));
}
TEST(Time, AdditiveOperators) {
@@ -223,6 +226,9 @@ TEST(Time, Infinity) {
constexpr absl::Time t = absl::UnixEpoch(); // Any finite time.
static_assert(t < ifuture, "");
static_assert(t > ipast, "");
+
+ EXPECT_EQ(ifuture, t + absl::InfiniteDuration());
+ EXPECT_EQ(ipast, t - absl::InfiniteDuration());
}
TEST(Time, FloorConversion) {
@@ -353,19 +359,21 @@ TEST(Time, FloorConversion) {
const int64_t min_plus_1 = std::numeric_limits<int64_t>::min() + 1;
EXPECT_EQ(min_plus_1, absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1)));
EXPECT_EQ(std::numeric_limits<int64_t>::min(),
- absl::ToUnixSeconds(
- absl::FromUnixSeconds(min_plus_1) - absl::Nanoseconds(1) / 2));
+ absl::ToUnixSeconds(absl::FromUnixSeconds(min_plus_1) -
+ absl::Nanoseconds(1) / 2));
// Tests flooring near positive infinity.
EXPECT_EQ(std::numeric_limits<int64_t>::max(),
- absl::ToUnixSeconds(absl::FromUnixSeconds(
- std::numeric_limits<int64_t>::max()) + absl::Nanoseconds(1) / 2));
+ absl::ToUnixSeconds(
+ absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) +
+ absl::Nanoseconds(1) / 2));
EXPECT_EQ(std::numeric_limits<int64_t>::max(),
absl::ToUnixSeconds(
absl::FromUnixSeconds(std::numeric_limits<int64_t>::max())));
EXPECT_EQ(std::numeric_limits<int64_t>::max() - 1,
- absl::ToUnixSeconds(absl::FromUnixSeconds(
- std::numeric_limits<int64_t>::max()) - absl::Nanoseconds(1) / 2));
+ absl::ToUnixSeconds(
+ absl::FromUnixSeconds(std::numeric_limits<int64_t>::max()) -
+ absl::Nanoseconds(1) / 2));
}
TEST(Time, RoundtripConversion) {
@@ -571,6 +579,50 @@ TEST(Time, ToChronoTime) {
absl::ToChronoTime(absl::UnixEpoch() - tick));
}
+// Check that absl::int128 works as a std::chrono::duration representation.
+TEST(Time, Chrono128) {
+ // Define a std::chrono::time_point type whose time[sic]_since_epoch() is
+ // a signed 128-bit count of attoseconds. This has a range and resolution
+ // (currently) beyond those of absl::Time, and undoubtedly also beyond those
+ // of std::chrono::system_clock::time_point.
+ //
+ // Note: The to/from-chrono support should probably be updated to handle
+ // such wide representations.
+ using Timestamp =
+ std::chrono::time_point<std::chrono::system_clock,
+ std::chrono::duration<absl::int128, std::atto>>;
+
+ // Expect that we can round-trip the std::chrono::system_clock::time_point
+ // extremes through both absl::Time and Timestamp, and that Timestamp can
+ // handle the (current) absl::Time extremes.
+ //
+ // Note: We should use std::chrono::floor() instead of time_point_cast(),
+ // but floor() is only available since c++17.
+ for (const auto tp : {std::chrono::system_clock::time_point::min(),
+ std::chrono::system_clock::time_point::max()}) {
+ EXPECT_EQ(tp, absl::ToChronoTime(absl::FromChrono(tp)));
+ EXPECT_EQ(tp, std::chrono::time_point_cast<
+ std::chrono::system_clock::time_point::duration>(
+ std::chrono::time_point_cast<Timestamp::duration>(tp)));
+ }
+ Timestamp::duration::rep v = std::numeric_limits<int64_t>::min();
+ v *= Timestamp::duration::period::den;
+ auto ts = Timestamp(Timestamp::duration(v));
+ ts += std::chrono::duration<int64_t, std::atto>(0);
+ EXPECT_EQ(std::numeric_limits<int64_t>::min(),
+ ts.time_since_epoch().count() / Timestamp::duration::period::den);
+ EXPECT_EQ(0,
+ ts.time_since_epoch().count() % Timestamp::duration::period::den);
+ v = std::numeric_limits<int64_t>::max();
+ v *= Timestamp::duration::period::den;
+ ts = Timestamp(Timestamp::duration(v));
+ ts += std::chrono::duration<int64_t, std::atto>(999999999750000000);
+ EXPECT_EQ(std::numeric_limits<int64_t>::max(),
+ ts.time_since_epoch().count() / Timestamp::duration::period::den);
+ EXPECT_EQ(999999999750000000,
+ ts.time_since_epoch().count() % Timestamp::duration::period::den);
+}
+
TEST(Time, TimeZoneAt) {
const absl::TimeZone nyc =
absl::time_internal::LoadTimeZone("America/New_York");
@@ -791,6 +843,30 @@ TEST(Time, FromTM) {
tm.tm_isdst = 1;
t = FromTM(tm, nyc);
EXPECT_EQ("2014-03-09T03:30:42-04:00", absl::FormatTime(t, nyc)); // DST
+
+ // Adjusts tm to refer to a time with a year larger than 2147483647.
+ tm.tm_year = 2147483647 - 1900 + 1;
+ tm.tm_mon = 6 - 1;
+ tm.tm_mday = 28;
+ tm.tm_hour = 1;
+ tm.tm_min = 2;
+ tm.tm_sec = 3;
+ tm.tm_isdst = -1;
+ t = FromTM(tm, absl::UTCTimeZone());
+ EXPECT_EQ("2147483648-06-28T01:02:03+00:00",
+ absl::FormatTime(t, absl::UTCTimeZone()));
+
+ // Adjusts tm to refer to a time with a very large month.
+ tm.tm_year = 2019 - 1900;
+ tm.tm_mon = 2147483647;
+ tm.tm_mday = 28;
+ tm.tm_hour = 1;
+ tm.tm_min = 2;
+ tm.tm_sec = 3;
+ tm.tm_isdst = -1;
+ t = FromTM(tm, absl::UTCTimeZone());
+ EXPECT_EQ("178958989-08-28T01:02:03+00:00",
+ absl::FormatTime(t, absl::UTCTimeZone()));
}
TEST(Time, TMRoundTrip) {
@@ -972,18 +1048,18 @@ TEST(Time, ConversionSaturation) {
// Checks how TimeZone::At() saturates on infinities.
auto ci = utc.At(absl::InfiniteFuture());
- EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23,
- 59, 59, 0, false);
+ EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::max(), 12, 31, 23, 59, 59,
+ 0, false);
EXPECT_EQ(absl::InfiniteDuration(), ci.subsecond);
- EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(absl::CivilDay(ci.cs)));
- EXPECT_EQ(365, absl::GetYearDay(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::thursday, absl::GetWeekday(ci.cs));
+ EXPECT_EQ(365, absl::GetYearDay(ci.cs));
EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At()
ci = utc.At(absl::InfinitePast());
- EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0,
- 0, 0, false);
+ EXPECT_CIVIL_INFO(ci, std::numeric_limits<int64_t>::min(), 1, 1, 0, 0, 0, 0,
+ false);
EXPECT_EQ(-absl::InfiniteDuration(), ci.subsecond);
- EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(absl::CivilDay(ci.cs)));
- EXPECT_EQ(1, absl::GetYearDay(absl::CivilDay(ci.cs)));
+ EXPECT_EQ(absl::Weekday::sunday, absl::GetWeekday(ci.cs));
+ EXPECT_EQ(1, absl::GetYearDay(ci.cs));
EXPECT_STREQ("-00", ci.zone_abbr); // artifact of TimeZone::At()
// Approach the maximal Time value from below.
@@ -994,7 +1070,8 @@ TEST(Time, ConversionSaturation) {
EXPECT_EQ("292277026596-12-04T15:30:07+00:00",
absl::FormatTime(absl::RFC3339_full, t, utc));
EXPECT_EQ(
- absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+ absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+ t);
// Checks that we can also get the maximal Time value for a far-east zone.
const absl::TimeZone plus14 = absl::FixedTimeZone(14 * 60 * 60);
@@ -1002,7 +1079,8 @@ TEST(Time, ConversionSaturation) {
EXPECT_EQ("292277026596-12-05T05:30:07+14:00",
absl::FormatTime(absl::RFC3339_full, t, plus14));
EXPECT_EQ(
- absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()), t);
+ absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::max()),
+ t);
// One second later should push us to infinity.
t = absl::FromCivil(absl::CivilSecond(292277026596, 12, 4, 15, 30, 8), utc);
@@ -1016,7 +1094,8 @@ TEST(Time, ConversionSaturation) {
EXPECT_EQ("-292277022657-01-27T08:29:52+00:00",
absl::FormatTime(absl::RFC3339_full, t, utc));
EXPECT_EQ(
- absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+ absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+ t);
// Checks that we can also get the minimal Time value for a far-west zone.
const absl::TimeZone minus12 = absl::FixedTimeZone(-12 * 60 * 60);
@@ -1025,7 +1104,8 @@ TEST(Time, ConversionSaturation) {
EXPECT_EQ("-292277022657-01-26T20:29:52-12:00",
absl::FormatTime(absl::RFC3339_full, t, minus12));
EXPECT_EQ(
- absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()), t);
+ absl::UnixEpoch() + absl::Seconds(std::numeric_limits<int64_t>::min()),
+ t);
// One second before should push us to -infinity.
t = absl::FromCivil(absl::CivilSecond(-292277022657, 1, 27, 8, 29, 51), utc);
@@ -1098,14 +1178,13 @@ TEST(Time, LegacyDateTime) {
const int kMin = std::numeric_limits<int>::min();
absl::Time t;
- t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(),
- kMax, kMax, kMax, kMax, kMax, utc);
+ t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::max(), kMax,
+ kMax, kMax, kMax, kMax, utc);
EXPECT_EQ("infinite-future",
absl::FormatTime(ymdhms, t, utc)); // no overflow
- t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(),
- kMin, kMin, kMin, kMin, kMin, utc);
- EXPECT_EQ("infinite-past",
- absl::FormatTime(ymdhms, t, utc)); // no overflow
+ t = absl::FromDateTime(std::numeric_limits<absl::civil_year_t>::min(), kMin,
+ kMin, kMin, kMin, kMin, utc);
+ EXPECT_EQ("infinite-past", absl::FormatTime(ymdhms, t, utc)); // no overflow
// Check normalization.
EXPECT_TRUE(absl::ConvertDateTime(2013, 10, 32, 8, 30, 0, utc).normalized);
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_zone_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_zone_test.cc
index 43d91904044..229fcfccb0a 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_zone_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/time/time_zone_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -88,7 +88,7 @@ TEST(TimeZone, Failures) {
EXPECT_FALSE(LoadTimeZone("Invalid/TimeZone", &tz));
EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC
- // Loading an empty std::string timezone should fail.
+ // Loading an empty string timezone should fail.
tz = absl::time_internal::LoadTimeZone("America/Los_Angeles");
EXPECT_FALSE(LoadTimeZone("", &tz));
EXPECT_EQ(absl::UTCTimeZone(), tz); // guaranteed fallback to UTC
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/BUILD.bazel
index 2e490009c39..83be9360ff9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/BUILD.bazel
@@ -5,35 +5,36 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
-# http://www.apache.org/licenses/LICENSE-2.0
+# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
- "ABSL_EXCEPTIONS_FLAG",
- "ABSL_EXCEPTIONS_FLAG_LINKOPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "any",
hdrs = ["any.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_any_cast",
"//absl/base:config",
"//absl/base:core_headers",
+ "//absl/base:fast_type_id",
"//absl/meta:type_traits",
"//absl/utility",
],
@@ -43,6 +44,7 @@ cc_library(
name = "bad_any_cast",
hdrs = ["bad_any_cast.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_any_cast_impl",
"//absl/base:config",
@@ -55,12 +57,12 @@ cc_library(
"bad_any_cast.cc",
"bad_any_cast.h",
],
- copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
- "//absl/base",
"//absl/base:config",
+ "//absl/base:raw_logging_internal",
],
)
@@ -70,30 +72,13 @@ cc_test(
srcs = [
"any_test.cc",
],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
- deps = [
- ":any",
- "//absl/base",
- "//absl/base:config",
- "//absl/base:exception_testing",
- "//absl/container:test_instance_tracker",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "any_test_noexceptions",
- size = "small",
- srcs = [
- "any_test.cc",
- ],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
- "//absl/base",
"//absl/base:config",
"//absl/base:exception_testing",
+ "//absl/base:raw_logging_internal",
"//absl/container:test_instance_tracker",
"@com_google_googletest//:gtest_main",
],
@@ -102,10 +87,11 @@ cc_test(
cc_test(
name = "any_exception_safety_test",
srcs = ["any_exception_safety_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":any",
+ "//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
@@ -113,8 +99,14 @@ cc_test(
cc_library(
name = "span",
- hdrs = ["span.h"],
+ srcs = [
+ "internal/span.h",
+ ],
+ hdrs = [
+ "span.h",
+ ],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/algorithm",
"//absl/base:core_headers",
@@ -127,26 +119,8 @@ cc_test(
name = "span_test",
size = "small",
srcs = ["span_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
- deps = [
- ":span",
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/base:exception_testing",
- "//absl/container:fixed_array",
- "//absl/container:inlined_vector",
- "//absl/hash:hash_testing",
- "//absl/strings",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "span_test_noexceptions",
- size = "small",
- srcs = ["span_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":span",
"//absl/base:config",
@@ -162,11 +136,13 @@ cc_test(
cc_library(
name = "optional",
- srcs = ["optional.cc"],
+ srcs = ["internal/optional.h"],
hdrs = ["optional.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_optional_access",
+ "//absl/base:base_internal",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
@@ -179,11 +155,11 @@ cc_library(
name = "bad_optional_access",
srcs = ["bad_optional_access.cc"],
hdrs = ["bad_optional_access.h"],
- copts = ABSL_DEFAULT_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base",
"//absl/base:config",
+ "//absl/base:raw_logging_internal",
],
)
@@ -191,11 +167,11 @@ cc_library(
name = "bad_variant_access",
srcs = ["bad_variant_access.cc"],
hdrs = ["bad_variant_access.h"],
- copts = ABSL_EXCEPTIONS_FLAG + ABSL_DEFAULT_COPTS,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base",
"//absl/base:config",
+ "//absl/base:raw_logging_internal",
],
)
@@ -205,12 +181,12 @@ cc_test(
srcs = [
"optional_test.cc",
],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":optional",
- "//absl/base",
"//absl/base:config",
+ "//absl/base:raw_logging_internal",
"//absl/meta:type_traits",
"//absl/strings",
"@com_google_googletest//:gtest_main",
@@ -222,20 +198,60 @@ cc_test(
srcs = [
"optional_exception_safety_test.cc",
],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":optional",
+ "//absl/base:config",
"//absl/base:exception_safety_testing",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
+ name = "conformance_testing",
+ testonly = 1,
+ hdrs = [
+ "internal/conformance_aliases.h",
+ "internal/conformance_archetype.h",
+ "internal/conformance_profile.h",
+ "internal/conformance_testing.h",
+ "internal/conformance_testing_helpers.h",
+ "internal/parentheses.h",
+ "internal/transform_args.h",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ "//absl/algorithm:container",
+ "//absl/meta:type_traits",
+ "//absl/strings",
+ "//absl/utility",
+ "@com_google_googletest//:gtest",
+ ],
+)
+
+cc_test(
+ name = "conformance_testing_test",
+ size = "small",
+ srcs = [
+ "internal/conformance_testing_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ deps = [
+ ":conformance_testing",
+ "//absl/meta:type_traits",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
+
+cc_library(
name = "variant",
srcs = ["internal/variant.h"],
hdrs = ["variant.h"],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":bad_variant_access",
"//absl/base:base_internal",
@@ -250,8 +266,8 @@ cc_test(
name = "variant_test",
size = "small",
srcs = ["variant_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":variant",
"//absl/base:config",
@@ -269,6 +285,7 @@ cc_test(
"variant_benchmark.cc",
],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
deps = [
":variant",
@@ -283,8 +300,8 @@ cc_test(
srcs = [
"variant_exception_safety_test.cc",
],
- copts = ABSL_TEST_COPTS + ABSL_EXCEPTIONS_FLAG,
- linkopts = ABSL_EXCEPTIONS_FLAG_LINKOPTS,
+ copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":variant",
"//absl/base:config",
@@ -293,3 +310,27 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
+
+cc_library(
+ name = "compare",
+ hdrs = ["compare.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ deps = [
+ "//absl/base:core_headers",
+ "//absl/meta:type_traits",
+ ],
+)
+
+cc_test(
+ name = "compare_test",
+ size = "small",
+ srcs = [
+ "compare_test.cc",
+ ],
+ copts = ABSL_TEST_COPTS,
+ deps = [
+ ":compare",
+ "//absl/base",
+ "@com_google_googletest//:gtest_main",
+ ],
+)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any.h
index a973c6dab7e..fc5a07469f8 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -47,27 +47,29 @@
// this abstraction, make sure that you should not instead be rewriting your
// code to be more specific.
//
-// Abseil expects to release an `absl::variant` type shortly (a C++11 compatible
-// version of the C++17 `std::variant), which is generally preferred for use
-// over `absl::any`.
+// 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/config.h"
#include "absl/utility/utility.h"
-#ifdef ABSL_HAVE_STD_ANY
+#ifdef ABSL_USES_STD_ANY
-#include <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_HAVE_STD_ANY
+#else // ABSL_USES_STD_ANY
#include <algorithm>
#include <cstddef>
@@ -78,6 +80,7 @@ using std::make_any;
#include <typeinfo>
#include <utility>
+#include "absl/base/internal/fast_type_id.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
#include "absl/types/bad_any_cast.h"
@@ -91,26 +94,7 @@ using std::make_any;
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
namespace absl {
-
-namespace any_internal {
-
-template <typename Type>
-struct TypeTag {
- constexpr static char dummy_var = 0;
-};
-
-template <typename Type>
-constexpr char TypeTag<Type>::dummy_var;
-
-// FastTypeId<Type>() evaluates at compile/link-time to a unique pointer for the
-// passed in type. These are meant to be good match for keys into maps or
-// straight up comparisons.
-template<typename Type>
-constexpr inline const void* FastTypeId() {
- return &TypeTag<Type>::dummy_var;
-}
-
-} // namespace any_internal
+ABSL_NAMESPACE_BEGIN
class any;
@@ -182,7 +166,7 @@ ValueType* any_cast(any* operand) noexcept;
// 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-constructable; move-only
+// An `absl::any` can only store a type that is copy-constructible; move-only
// types are not allowed within an `any` object.
//
// Example:
@@ -190,7 +174,7 @@ ValueType* any_cast(any* operand) noexcept;
// 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-constructable
+// 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"),
@@ -420,11 +404,11 @@ class any {
using NormalizedType =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
- return any_internal::FastTypeId<NormalizedType>();
+ return base_internal::FastTypeId<NormalizedType>();
}
const void* GetObjTypeId() const {
- return obj_ ? obj_->ObjTypeId() : any_internal::FastTypeId<void>();
+ return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
}
// `absl::any` nonmember functions //
@@ -515,25 +499,30 @@ ValueType any_cast(any&& operand) {
// Description at the declaration site (top of file).
template <typename T>
const T* any_cast(const any* operand) noexcept {
- return operand && operand->GetObjTypeId() == any::IdForType<T>()
+ 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<T>*>(operand->obj_.get())->value)
+ 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 {
- return operand && operand->GetObjTypeId() == any::IdForType<T>()
+ 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<T>*>(operand->obj_.get())->value)
+ static_cast<any::Obj<U>*>(operand->obj_.get())->value)
: nullptr;
}
+ABSL_NAMESPACE_END
} // namespace absl
#undef ABSL_ANY_DETAIL_HAS_RTTI
-#endif // ABSL_HAVE_STD_ANY
+#endif // ABSL_USES_STD_ANY
#endif // ABSL_TYPES_ANY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_exception_safety_test.cc
index f9dd8c482c2..31c1140135f 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_exception_safety_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_exception_safety_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,12 @@
#include "absl/types/any.h"
+#include "absl/base/config.h"
+
+// This test is a no-op when absl::any is an alias for std::any and when
+// exceptions are not enabled.
+#if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
+
#include <typeinfo>
#include <vector>
@@ -135,8 +141,7 @@ TEST(AnyExceptionSafety, Assignment) {
EXPECT_TRUE(strong_empty_any_tester.Test(assign_val));
EXPECT_TRUE(strong_empty_any_tester.Test(move));
}
-// libstdc++ std::any fails this test
-#if !defined(ABSL_HAVE_STD_ANY)
+
TEST(AnyExceptionSafety, Emplace) {
auto initial_val =
absl::any{absl::in_place_type_t<Thrower>(), 1, testing::nothrow_ctor};
@@ -162,6 +167,7 @@ TEST(AnyExceptionSafety, Emplace) {
EXPECT_TRUE(empty_tester.Test(emp_thrower));
EXPECT_TRUE(empty_tester.Test(emp_throwervec));
}
-#endif // ABSL_HAVE_STD_ANY
} // namespace
+
+#endif // #if !defined(ABSL_USES_STD_ANY) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_test.cc
index 115e78df7af..70e4ba22b12 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/any_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,9 @@
#include "absl/types/any.h"
+// This test is a no-op when absl::any is an alias for std::any.
+#if !defined(ABSL_USES_STD_ANY)
+
#include <initializer_list>
#include <type_traits>
#include <utility>
@@ -154,6 +157,14 @@ TEST(AnyTest, InPlaceConstruction) {
EXPECT_EQ(5, v.value);
}
+TEST(AnyTest, InPlaceConstructionVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<IntMoveOnlyCopyOnly>, 5, MoveOnly(),
+ copy_only);
+ auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
+ EXPECT_EQ(5, v.value);
+}
+
TEST(AnyTest, InPlaceConstructionWithCV) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<const volatile IntMoveOnlyCopyOnly>(), 5,
@@ -162,12 +173,26 @@ TEST(AnyTest, InPlaceConstructionWithCV) {
EXPECT_EQ(5, v.value);
}
+TEST(AnyTest, InPlaceConstructionWithCVVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<const volatile IntMoveOnlyCopyOnly>, 5,
+ MoveOnly(), copy_only);
+ auto& v = absl::any_cast<IntMoveOnlyCopyOnly&>(o);
+ EXPECT_EQ(5, v.value);
+}
+
TEST(AnyTest, InPlaceConstructionWithFunction) {
absl::any o(absl::in_place_type_t<FunctionType>(), FunctionToEmplace);
FunctionType*& construction_result = absl::any_cast<FunctionType*&>(o);
EXPECT_EQ(&FunctionToEmplace, construction_result);
}
+TEST(AnyTest, InPlaceConstructionWithFunctionVariableTemplate) {
+ absl::any o(absl::in_place_type<FunctionType>, FunctionToEmplace);
+ auto& construction_result = absl::any_cast<FunctionType*&>(o);
+ EXPECT_EQ(&FunctionToEmplace, construction_result);
+}
+
TEST(AnyTest, InPlaceConstructionWithArray) {
ArrayType ar = {5, 42};
absl::any o(absl::in_place_type_t<ArrayType>(), ar);
@@ -175,6 +200,13 @@ TEST(AnyTest, InPlaceConstructionWithArray) {
EXPECT_EQ(&ar[0], construction_result);
}
+TEST(AnyTest, InPlaceConstructionWithArrayVariableTemplate) {
+ ArrayType ar = {5, 42};
+ absl::any o(absl::in_place_type<ArrayType>, ar);
+ auto& construction_result = absl::any_cast<DecayedArray&>(o);
+ EXPECT_EQ(&ar[0], construction_result);
+}
+
TEST(AnyTest, InPlaceConstructionIlist) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<ListMoveOnlyCopyOnly>(), {1, 2, 3, 4},
@@ -184,6 +216,15 @@ TEST(AnyTest, InPlaceConstructionIlist) {
EXPECT_EQ(expected_values, v.values);
}
+TEST(AnyTest, InPlaceConstructionIlistVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<ListMoveOnlyCopyOnly>, {1, 2, 3, 4},
+ MoveOnly(), copy_only);
+ auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
+ std::vector<int> expected_values = {1, 2, 3, 4};
+ EXPECT_EQ(expected_values, v.values);
+}
+
TEST(AnyTest, InPlaceConstructionIlistWithCV) {
const CopyOnly copy_only{};
absl::any o(absl::in_place_type_t<const volatile ListMoveOnlyCopyOnly>(),
@@ -193,11 +234,25 @@ TEST(AnyTest, InPlaceConstructionIlistWithCV) {
EXPECT_EQ(expected_values, v.values);
}
+TEST(AnyTest, InPlaceConstructionIlistWithCVVariableTemplate) {
+ const CopyOnly copy_only{};
+ absl::any o(absl::in_place_type<const volatile ListMoveOnlyCopyOnly>,
+ {1, 2, 3, 4}, MoveOnly(), copy_only);
+ auto& v = absl::any_cast<ListMoveOnlyCopyOnly&>(o);
+ std::vector<int> expected_values = {1, 2, 3, 4};
+ EXPECT_EQ(expected_values, v.values);
+}
+
TEST(AnyTest, InPlaceNoArgs) {
absl::any o(absl::in_place_type_t<int>{});
EXPECT_EQ(0, absl::any_cast<int&>(o));
}
+TEST(AnyTest, InPlaceNoArgsVariableTemplate) {
+ absl::any o(absl::in_place_type<int>);
+ EXPECT_EQ(0, absl::any_cast<int&>(o));
+}
+
template <typename Enabler, typename T, typename... Args>
struct CanEmplaceAnyImpl : std::false_type {};
@@ -501,7 +556,7 @@ TEST(AnyTest, Copy) {
InstanceTracker tracker_raii;
{
- absl::any o(absl::in_place_type_t<CopyableOnlyInstance>{}, 123);
+ absl::any o(absl::in_place_type<CopyableOnlyInstance>, 123);
CopyableOnlyInstance* f1 = absl::any_cast<CopyableOnlyInstance>(&o);
absl::any o2(o);
@@ -587,7 +642,7 @@ TEST(AnyTest, ConversionConstructionCausesOneCopy) {
// Tests for Exception Behavior //
//////////////////////////////////
-#if defined(ABSL_HAVE_STD_ANY)
+#if defined(ABSL_USES_STD_ANY)
// If using a std `any` implementation, we can't check for a specific message.
#define ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(...) \
@@ -601,7 +656,7 @@ TEST(AnyTest, ConversionConstructionCausesOneCopy) {
ABSL_BASE_INTERNAL_EXPECT_FAIL((__VA_ARGS__), absl::bad_any_cast, \
"Bad any cast")
-#endif // defined(ABSL_HAVE_STD_ANY)
+#endif // defined(ABSL_USES_STD_ANY)
TEST(AnyTest, ThrowBadAlloc) {
{
@@ -622,7 +677,7 @@ TEST(AnyTest, ThrowBadAlloc) {
}
{
- absl::any a(absl::in_place_type_t<int>{});
+ absl::any a(absl::in_place_type<int>);
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&>(a));
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<const float&>(a));
ABSL_ANY_TEST_EXPECT_BAD_ANY_CAST(absl::any_cast<float&&>(absl::any{}));
@@ -665,7 +720,7 @@ TEST(AnyTest, FailedCopy) {
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(absl::any{src});
}
@@ -677,21 +732,21 @@ TEST(AnyTest, FailedCopy) {
{
BadCopyable bad;
- absl::any target(absl::in_place_type_t<BadCopyable>{});
+ absl::any target(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = bad);
EXPECT_TRUE(target.has_value());
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
absl::any target;
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
EXPECT_FALSE(target.has_value());
}
{
- absl::any src(absl::in_place_type_t<BadCopyable>{});
- absl::any target(absl::in_place_type_t<BadCopyable>{});
+ absl::any src(absl::in_place_type<BadCopyable>);
+ absl::any target(absl::in_place_type<BadCopyable>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target = src);
EXPECT_TRUE(target.has_value());
}
@@ -707,9 +762,9 @@ TEST(AnyTest, FailedEmplace) {
{
BadCopyable bad;
- absl::any target(absl::in_place_type_t<int>{});
+ absl::any target(absl::in_place_type<int>);
ABSL_ANY_TEST_EXPECT_BAD_COPY(target.emplace<BadCopyable>(bad));
-#if defined(ABSL_HAVE_STD_ANY) && defined(__GLIBCXX__)
+#if defined(ABSL_USES_STD_ANY) && defined(__GLIBCXX__)
// libstdc++ std::any::emplace() implementation (as of 7.2) has a bug: if an
// exception is thrown, *this contains a value.
#define ABSL_GLIBCXX_ANY_EMPLACE_EXCEPTION_BUG 1
@@ -722,3 +777,5 @@ TEST(AnyTest, FailedEmplace) {
}
} // namespace
+
+#endif // #if !defined(ABSL_USES_STD_ANY)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.cc
index 2e2fd29a337..b0592cc9bcc 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,7 @@
#include "absl/types/bad_any_cast.h"
-#ifndef ABSL_HAVE_STD_ANY
+#ifndef ABSL_USES_STD_ANY
#include <cstdlib>
@@ -22,6 +22,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
bad_any_cast::~bad_any_cast() = default;
@@ -39,6 +40,7 @@ void ThrowBadAnyCast() {
}
} // namespace any_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_ANY
+#endif // ABSL_USES_STD_ANY
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.h
index 603901324af..114cef80cdd 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_any_cast.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,17 +25,20 @@
#include "absl/base/config.h"
-#ifdef ABSL_HAVE_STD_ANY
+#ifdef ABSL_USES_STD_ANY
#include <any>
namespace absl {
+ABSL_NAMESPACE_BEGIN
using std::bad_any_cast;
+ABSL_NAMESPACE_END
} // namespace absl
-#else // ABSL_HAVE_STD_ANY
+#else // ABSL_USES_STD_ANY
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// bad_any_cast
@@ -64,8 +67,9 @@ namespace any_internal {
[[noreturn]] void ThrowBadAnyCast();
} // namespace any_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_ANY
+#endif // ABSL_USES_STD_ANY
#endif // ABSL_TYPES_BAD_ANY_CAST_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.cc
index 558707760e9..26aca70d9cf 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,7 @@
#include "absl/types/bad_optional_access.h"
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
#include <cstdlib>
@@ -22,6 +22,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
bad_optional_access::~bad_optional_access() = default;
@@ -41,6 +42,7 @@ void throw_bad_optional_access() {
}
} // namespace optional_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.h
index c6c27460a76..a500286adc4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_optional_access.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,17 +25,20 @@
#include "absl/base/config.h"
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
#include <optional>
namespace absl {
+ABSL_NAMESPACE_BEGIN
using std::bad_optional_access;
+ABSL_NAMESPACE_END
} // namespace absl
-#else // ABSL_HAVE_STD_OPTIONAL
+#else // ABSL_USES_STD_OPTIONAL
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// bad_optional_access
@@ -67,8 +70,9 @@ namespace optional_internal {
[[noreturn]] void throw_bad_optional_access();
} // namespace optional_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
#endif // ABSL_TYPES_BAD_OPTIONAL_ACCESS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.cc
index d27d7756179..3dc88cc09f2 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,7 +14,7 @@
#include "absl/types/bad_variant_access.h"
-#ifndef ABSL_HAVE_STD_VARIANT
+#ifndef ABSL_USES_STD_VARIANT
#include <cstdlib>
#include <stdexcept>
@@ -23,6 +23,7 @@
#include "absl/base/internal/raw_logging.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
//////////////////////////
// [variant.bad.access] //
@@ -57,6 +58,7 @@ void Rethrow() {
}
} // namespace variant_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_VARIANT
+#endif // ABSL_USES_STD_VARIANT
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.h
index e7355a5a74c..095969f91ee 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/bad_variant_access.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,17 +25,20 @@
#include "absl/base/config.h"
-#ifdef ABSL_HAVE_STD_VARIANT
+#ifdef ABSL_USES_STD_VARIANT
#include <variant>
namespace absl {
+ABSL_NAMESPACE_BEGIN
using std::bad_variant_access;
+ABSL_NAMESPACE_END
} // namespace absl
-#else // ABSL_HAVE_STD_VARIANT
+#else // ABSL_USES_STD_VARIANT
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// bad_variant_access
@@ -71,8 +74,9 @@ namespace variant_internal {
[[noreturn]] void Rethrow();
} // namespace variant_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_VARIANT
+#endif // ABSL_USES_STD_VARIANT
#endif // ABSL_TYPES_BAD_VARIANT_ACCESS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare.h
new file mode 100644
index 00000000000..19b076e7f19
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare.h
@@ -0,0 +1,600 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// compare.h
+// -----------------------------------------------------------------------------
+//
+// This header file defines the `absl::weak_equality`, `absl::strong_equality`,
+// `absl::partial_ordering`, `absl::weak_ordering`, and `absl::strong_ordering`
+// types for storing the results of three way comparisons.
+//
+// Example:
+// absl::weak_ordering compare(const std::string& a, const std::string& b);
+//
+// These are C++11 compatible versions of the C++20 corresponding types
+// (`std::weak_equality`, etc.) and are designed to be drop-in replacements
+// for code compliant with C++20.
+
+#ifndef ABSL_TYPES_COMPARE_H_
+#define ABSL_TYPES_COMPARE_H_
+
+#include <cstddef>
+#include <cstdint>
+#include <cstdlib>
+#include <type_traits>
+
+#include "absl/base/attributes.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace compare_internal {
+
+using value_type = int8_t;
+
+template <typename T>
+struct Fail {
+ static_assert(sizeof(T) < 0, "Only literal `0` is allowed.");
+};
+
+// We need the NullPtrT template to avoid triggering the modernize-use-nullptr
+// ClangTidy warning in user code.
+template <typename NullPtrT = std::nullptr_t>
+struct OnlyLiteralZero {
+ constexpr OnlyLiteralZero(NullPtrT) noexcept {} // NOLINT
+
+ // Fails compilation when `nullptr` or integral type arguments other than
+ // `int` are passed. This constructor doesn't accept `int` because literal `0`
+ // has type `int`. Literal `0` arguments will be implicitly converted to
+ // `std::nullptr_t` and accepted by the above constructor, while other `int`
+ // arguments will fail to be converted and cause compilation failure.
+ template <
+ typename T,
+ typename = typename std::enable_if<
+ std::is_same<T, std::nullptr_t>::value ||
+ (std::is_integral<T>::value && !std::is_same<T, int>::value)>::type,
+ typename = typename Fail<T>::type>
+ OnlyLiteralZero(T); // NOLINT
+};
+
+enum class eq : value_type {
+ equal = 0,
+ equivalent = equal,
+ nonequal = 1,
+ nonequivalent = nonequal,
+};
+
+enum class ord : value_type { less = -1, greater = 1 };
+
+enum class ncmp : value_type { unordered = -127 };
+
+// Define macros to allow for creation or emulation of C++17 inline variables
+// based on whether the feature is supported. Note: we can't use
+// ABSL_INTERNAL_INLINE_CONSTEXPR here because the variables here are of
+// incomplete types so they need to be defined after the types are complete.
+#ifdef __cpp_inline_variables
+
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) static_assert(true, "")
+
+#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
+ static const type name
+
+#define ABSL_COMPARE_INLINE_INIT(type, name, init) \
+ inline constexpr type type::name(init)
+
+#else // __cpp_inline_variables
+
+#define ABSL_COMPARE_INLINE_BASECLASS_DECL(name) \
+ ABSL_CONST_INIT static const T name
+
+// A no-op expansion that can be followed by a semicolon at class level.
+#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) static_assert(true, "")
+
+#define ABSL_COMPARE_INLINE_INIT(type, name, init) \
+ template <typename T> \
+ const T compare_internal::type##_base<T>::name(init)
+
+#endif // __cpp_inline_variables
+
+// These template base classes allow for defining the values of the constants
+// in the header file (for performance) without using inline variables (which
+// aren't available in C++11).
+template <typename T>
+struct weak_equality_base {
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent);
+};
+
+template <typename T>
+struct strong_equality_base {
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equal);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequal);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(nonequivalent);
+};
+
+template <typename T>
+struct partial_ordering_base {
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(unordered);
+};
+
+template <typename T>
+struct weak_ordering_base {
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
+};
+
+template <typename T>
+struct strong_ordering_base {
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(less);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equal);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(equivalent);
+ ABSL_COMPARE_INLINE_BASECLASS_DECL(greater);
+};
+
+} // namespace compare_internal
+
+class weak_equality
+ : public compare_internal::weak_equality_base<weak_equality> {
+ explicit constexpr weak_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_equality_base<weak_equality>;
+
+ public:
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, equivalent);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_equality, nonequivalent);
+
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_equality v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator==(weak_equality v1,
+ weak_equality v2) noexcept {
+ return v1.value_ == v2.value_;
+ }
+ friend constexpr bool operator!=(weak_equality v1,
+ weak_equality v2) noexcept {
+ return v1.value_ != v2.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+ABSL_COMPARE_INLINE_INIT(weak_equality, equivalent,
+ compare_internal::eq::equivalent);
+ABSL_COMPARE_INLINE_INIT(weak_equality, nonequivalent,
+ compare_internal::eq::nonequivalent);
+
+class strong_equality
+ : public compare_internal::strong_equality_base<strong_equality> {
+ explicit constexpr strong_equality(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_equality_base<strong_equality>;
+
+ public:
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equal);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequal);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, equivalent);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_equality, nonequivalent);
+
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_equality v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_equality v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator==(strong_equality v1,
+ strong_equality v2) noexcept {
+ return v1.value_ == v2.value_;
+ }
+ friend constexpr bool operator!=(strong_equality v1,
+ strong_equality v2) noexcept {
+ return v1.value_ != v2.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+ABSL_COMPARE_INLINE_INIT(strong_equality, equal, compare_internal::eq::equal);
+ABSL_COMPARE_INLINE_INIT(strong_equality, nonequal,
+ compare_internal::eq::nonequal);
+ABSL_COMPARE_INLINE_INIT(strong_equality, equivalent,
+ compare_internal::eq::equivalent);
+ABSL_COMPARE_INLINE_INIT(strong_equality, nonequivalent,
+ compare_internal::eq::nonequivalent);
+
+class partial_ordering
+ : public compare_internal::partial_ordering_base<partial_ordering> {
+ explicit constexpr partial_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr partial_ordering(compare_internal::ncmp v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::partial_ordering_base<partial_ordering>;
+
+ constexpr bool is_ordered() const noexcept {
+ return value_ !=
+ compare_internal::value_type(compare_internal::ncmp::unordered);
+ }
+
+ public:
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, less);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, equivalent);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, greater);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(partial_ordering, unordered);
+
+ // Conversion
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return !v.is_ordered() || v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ partial_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.is_ordered() && v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return !v.is_ordered() || 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ partial_ordering v) noexcept {
+ return v.is_ordered() && 0 >= v.value_;
+ }
+ friend constexpr bool operator==(partial_ordering v1,
+ partial_ordering v2) noexcept {
+ return v1.value_ == v2.value_;
+ }
+ friend constexpr bool operator!=(partial_ordering v1,
+ partial_ordering v2) noexcept {
+ return v1.value_ != v2.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+ABSL_COMPARE_INLINE_INIT(partial_ordering, less, compare_internal::ord::less);
+ABSL_COMPARE_INLINE_INIT(partial_ordering, equivalent,
+ compare_internal::eq::equivalent);
+ABSL_COMPARE_INLINE_INIT(partial_ordering, greater,
+ compare_internal::ord::greater);
+ABSL_COMPARE_INLINE_INIT(partial_ordering, unordered,
+ compare_internal::ncmp::unordered);
+
+class weak_ordering
+ : public compare_internal::weak_ordering_base<weak_ordering> {
+ explicit constexpr weak_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr weak_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::weak_ordering_base<weak_ordering>;
+
+ public:
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, less);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, equivalent);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(weak_ordering, greater);
+
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ weak_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ weak_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+ friend constexpr bool operator==(weak_ordering v1,
+ weak_ordering v2) noexcept {
+ return v1.value_ == v2.value_;
+ }
+ friend constexpr bool operator!=(weak_ordering v1,
+ weak_ordering v2) noexcept {
+ return v1.value_ != v2.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+ABSL_COMPARE_INLINE_INIT(weak_ordering, less, compare_internal::ord::less);
+ABSL_COMPARE_INLINE_INIT(weak_ordering, equivalent,
+ compare_internal::eq::equivalent);
+ABSL_COMPARE_INLINE_INIT(weak_ordering, greater,
+ compare_internal::ord::greater);
+
+class strong_ordering
+ : public compare_internal::strong_ordering_base<strong_ordering> {
+ explicit constexpr strong_ordering(compare_internal::eq v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ explicit constexpr strong_ordering(compare_internal::ord v) noexcept
+ : value_(static_cast<compare_internal::value_type>(v)) {}
+ friend struct compare_internal::strong_ordering_base<strong_ordering>;
+
+ public:
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, less);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equal);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, equivalent);
+ ABSL_COMPARE_INLINE_SUBCLASS_DECL(strong_ordering, greater);
+
+ // Conversions
+ constexpr operator weak_equality() const noexcept { // NOLINT
+ return value_ == 0 ? weak_equality::equivalent
+ : weak_equality::nonequivalent;
+ }
+ constexpr operator strong_equality() const noexcept { // NOLINT
+ return value_ == 0 ? strong_equality::equal : strong_equality::nonequal;
+ }
+ constexpr operator partial_ordering() const noexcept { // NOLINT
+ return value_ == 0 ? partial_ordering::equivalent
+ : (value_ < 0 ? partial_ordering::less
+ : partial_ordering::greater);
+ }
+ constexpr operator weak_ordering() const noexcept { // NOLINT
+ return value_ == 0
+ ? weak_ordering::equivalent
+ : (value_ < 0 ? weak_ordering::less : weak_ordering::greater);
+ }
+ // Comparisons
+ friend constexpr bool operator==(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ == 0;
+ }
+ friend constexpr bool operator!=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ != 0;
+ }
+ friend constexpr bool operator<(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ < 0;
+ }
+ friend constexpr bool operator<=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ <= 0;
+ }
+ friend constexpr bool operator>(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ > 0;
+ }
+ friend constexpr bool operator>=(
+ strong_ordering v, compare_internal::OnlyLiteralZero<>) noexcept {
+ return v.value_ >= 0;
+ }
+ friend constexpr bool operator==(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 == v.value_;
+ }
+ friend constexpr bool operator!=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 != v.value_;
+ }
+ friend constexpr bool operator<(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 < v.value_;
+ }
+ friend constexpr bool operator<=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 <= v.value_;
+ }
+ friend constexpr bool operator>(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 > v.value_;
+ }
+ friend constexpr bool operator>=(compare_internal::OnlyLiteralZero<>,
+ strong_ordering v) noexcept {
+ return 0 >= v.value_;
+ }
+ friend constexpr bool operator==(strong_ordering v1,
+ strong_ordering v2) noexcept {
+ return v1.value_ == v2.value_;
+ }
+ friend constexpr bool operator!=(strong_ordering v1,
+ strong_ordering v2) noexcept {
+ return v1.value_ != v2.value_;
+ }
+
+ private:
+ compare_internal::value_type value_;
+};
+ABSL_COMPARE_INLINE_INIT(strong_ordering, less, compare_internal::ord::less);
+ABSL_COMPARE_INLINE_INIT(strong_ordering, equal, compare_internal::eq::equal);
+ABSL_COMPARE_INLINE_INIT(strong_ordering, equivalent,
+ compare_internal::eq::equivalent);
+ABSL_COMPARE_INLINE_INIT(strong_ordering, greater,
+ compare_internal::ord::greater);
+
+#undef ABSL_COMPARE_INLINE_BASECLASS_DECL
+#undef ABSL_COMPARE_INLINE_SUBCLASS_DECL
+#undef ABSL_COMPARE_INLINE_INIT
+
+namespace compare_internal {
+// We also provide these comparator adapter functions for internal absl use.
+
+// Helper functions to do a boolean comparison of two keys given a boolean
+// or three-way comparator.
+// SFINAE prevents implicit conversions to bool (such as from int).
+template <typename Bool,
+ absl::enable_if_t<std::is_same<bool, Bool>::value, int> = 0>
+constexpr bool compare_result_as_less_than(const Bool r) { return r; }
+constexpr bool compare_result_as_less_than(const absl::weak_ordering r) {
+ return r < 0;
+}
+
+template <typename Compare, typename K, typename LK>
+constexpr bool do_less_than_comparison(const Compare &compare, const K &x,
+ const LK &y) {
+ return compare_result_as_less_than(compare(x, y));
+}
+
+// Helper functions to do a three-way comparison of two keys given a boolean or
+// three-way comparator.
+// SFINAE prevents implicit conversions to int (such as from bool).
+template <typename Int,
+ absl::enable_if_t<std::is_same<int, Int>::value, int> = 0>
+constexpr absl::weak_ordering compare_result_as_ordering(const Int c) {
+ return c < 0 ? absl::weak_ordering::less
+ : c == 0 ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+}
+constexpr absl::weak_ordering compare_result_as_ordering(
+ const absl::weak_ordering c) {
+ return c;
+}
+
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<!std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare_result_as_ordering(compare(x, y));
+}
+template <
+ typename Compare, typename K, typename LK,
+ absl::enable_if_t<std::is_same<bool, absl::result_of_t<Compare(
+ const K &, const LK &)>>::value,
+ int> = 0>
+constexpr absl::weak_ordering do_three_way_comparison(const Compare &compare,
+ const K &x, const LK &y) {
+ return compare(x, y) ? absl::weak_ordering::less
+ : compare(y, x) ? absl::weak_ordering::greater
+ : absl::weak_ordering::equivalent;
+}
+
+} // namespace compare_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TYPES_COMPARE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare_test.cc
new file mode 100644
index 00000000000..8095baf9569
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/compare_test.cc
@@ -0,0 +1,389 @@
+// 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.
+
+#include "absl/types/compare.h"
+
+#include "gtest/gtest.h"
+#include "absl/base/casts.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace {
+
+// This is necessary to avoid a bunch of lint warnings suggesting that we use
+// EXPECT_EQ/etc., which doesn't work in this case because they convert the `0`
+// to an int, which can't be converted to the unspecified zero type.
+bool Identity(bool b) { return b; }
+
+TEST(Compare, WeakEquality) {
+ EXPECT_TRUE(Identity(weak_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_equality::equivalent));
+ EXPECT_TRUE(Identity(weak_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != weak_equality::nonequivalent));
+ const weak_equality values[] = {weak_equality::equivalent,
+ weak_equality::nonequivalent};
+ for (const auto& lhs : values) {
+ for (const auto& rhs : values) {
+ const bool are_equal = &lhs == &rhs;
+ EXPECT_EQ(lhs == rhs, are_equal);
+ EXPECT_EQ(lhs != rhs, !are_equal);
+ }
+ }
+}
+
+TEST(Compare, StrongEquality) {
+ EXPECT_TRUE(Identity(strong_equality::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equal));
+ EXPECT_TRUE(Identity(strong_equality::nonequal != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequal));
+ EXPECT_TRUE(Identity(strong_equality::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_equality::equivalent));
+ EXPECT_TRUE(Identity(strong_equality::nonequivalent != 0));
+ EXPECT_TRUE(Identity(0 != strong_equality::nonequivalent));
+ const strong_equality values[] = {strong_equality::equal,
+ strong_equality::nonequal};
+ for (const auto& lhs : values) {
+ for (const auto& rhs : values) {
+ const bool are_equal = &lhs == &rhs;
+ EXPECT_EQ(lhs == rhs, are_equal);
+ EXPECT_EQ(lhs != rhs, !are_equal);
+ }
+ }
+ EXPECT_TRUE(Identity(strong_equality::equivalent == strong_equality::equal));
+ EXPECT_TRUE(
+ Identity(strong_equality::nonequivalent == strong_equality::nonequal));
+}
+
+TEST(Compare, PartialOrdering) {
+ EXPECT_TRUE(Identity(partial_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= partial_ordering::less));
+ EXPECT_TRUE(Identity(partial_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == partial_ordering::equivalent));
+ EXPECT_TRUE(Identity(partial_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= partial_ordering::greater));
+ EXPECT_TRUE(Identity(partial_ordering::unordered != 0));
+ EXPECT_TRUE(Identity(0 != partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered < 0));
+ EXPECT_FALSE(Identity(0 < partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered <= 0));
+ EXPECT_FALSE(Identity(0 <= partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered > 0));
+ EXPECT_FALSE(Identity(0 > partial_ordering::unordered));
+ EXPECT_FALSE(Identity(partial_ordering::unordered >= 0));
+ EXPECT_FALSE(Identity(0 >= partial_ordering::unordered));
+ const partial_ordering values[] = {
+ partial_ordering::less, partial_ordering::equivalent,
+ partial_ordering::greater, partial_ordering::unordered};
+ for (const auto& lhs : values) {
+ for (const auto& rhs : values) {
+ const bool are_equal = &lhs == &rhs;
+ EXPECT_EQ(lhs == rhs, are_equal);
+ EXPECT_EQ(lhs != rhs, !are_equal);
+ }
+ }
+}
+
+TEST(Compare, WeakOrdering) {
+ EXPECT_TRUE(Identity(weak_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= weak_ordering::less));
+ EXPECT_TRUE(Identity(weak_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == weak_ordering::equivalent));
+ EXPECT_TRUE(Identity(weak_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < weak_ordering::greater));
+ EXPECT_TRUE(Identity(weak_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= weak_ordering::greater));
+ const weak_ordering values[] = {
+ weak_ordering::less, weak_ordering::equivalent, weak_ordering::greater};
+ for (const auto& lhs : values) {
+ for (const auto& rhs : values) {
+ const bool are_equal = &lhs == &rhs;
+ EXPECT_EQ(lhs == rhs, are_equal);
+ EXPECT_EQ(lhs != rhs, !are_equal);
+ }
+ }
+}
+
+TEST(Compare, StrongOrdering) {
+ EXPECT_TRUE(Identity(strong_ordering::less < 0));
+ EXPECT_TRUE(Identity(0 > strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::less <= 0));
+ EXPECT_TRUE(Identity(0 >= strong_ordering::less));
+ EXPECT_TRUE(Identity(strong_ordering::equal == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equal));
+ EXPECT_TRUE(Identity(strong_ordering::equivalent == 0));
+ EXPECT_TRUE(Identity(0 == strong_ordering::equivalent));
+ EXPECT_TRUE(Identity(strong_ordering::greater > 0));
+ EXPECT_TRUE(Identity(0 < strong_ordering::greater));
+ EXPECT_TRUE(Identity(strong_ordering::greater >= 0));
+ EXPECT_TRUE(Identity(0 <= strong_ordering::greater));
+ const strong_ordering values[] = {
+ strong_ordering::less, strong_ordering::equal, strong_ordering::greater};
+ for (const auto& lhs : values) {
+ for (const auto& rhs : values) {
+ const bool are_equal = &lhs == &rhs;
+ EXPECT_EQ(lhs == rhs, are_equal);
+ EXPECT_EQ(lhs != rhs, !are_equal);
+ }
+ }
+ EXPECT_TRUE(Identity(strong_ordering::equivalent == strong_ordering::equal));
+}
+
+TEST(Compare, Conversions) {
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::nonequal) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_equality::equivalent) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(strong_equality::nonequivalent) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::less) != 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<weak_equality>(partial_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(partial_ordering::unordered) != 0));
+
+ EXPECT_TRUE(implicit_cast<weak_equality>(weak_ordering::less) != 0);
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(weak_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::less) <= 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(weak_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(weak_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<strong_equality>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<strong_equality>(strong_ordering::greater) != 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(Identity(
+ implicit_cast<partial_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<partial_ordering>(strong_ordering::greater) >= 0));
+
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) < 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::less) <= 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equal) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::equivalent) == 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) != 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) > 0));
+ EXPECT_TRUE(
+ Identity(implicit_cast<weak_ordering>(strong_ordering::greater) >= 0));
+}
+
+struct WeakOrderingLess {
+ template <typename T>
+ absl::weak_ordering operator()(const T& a, const T& b) const {
+ return a < b ? absl::weak_ordering::less
+ : a == b ? absl::weak_ordering::equivalent
+ : absl::weak_ordering::greater;
+ }
+};
+
+TEST(CompareResultAsLessThan, SanityTest) {
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(false));
+ EXPECT_TRUE(absl::compare_internal::compare_result_as_less_than(true));
+
+ EXPECT_TRUE(
+ absl::compare_internal::compare_result_as_less_than(weak_ordering::less));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::equivalent));
+ EXPECT_FALSE(absl::compare_internal::compare_result_as_less_than(
+ weak_ordering::greater));
+}
+
+TEST(DoLessThanComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(less, -1, 0));
+ EXPECT_TRUE(absl::compare_internal::do_less_than_comparison(weak, -1, 0));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 10));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 10));
+
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(less, 10, 5));
+ EXPECT_FALSE(absl::compare_internal::do_less_than_comparison(weak, 10, 5));
+}
+
+TEST(CompareResultAsOrdering, SanityTest) {
+ EXPECT_TRUE(
+ Identity(absl::compare_internal::compare_result_as_ordering(-1) < 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(-1) == 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(-1) > 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::less) > 0));
+
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(0) < 0));
+ EXPECT_TRUE(
+ Identity(absl::compare_internal::compare_result_as_ordering(0) == 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(0) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) < 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) == 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::equivalent) > 0));
+
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(1) < 0));
+ EXPECT_FALSE(
+ Identity(absl::compare_internal::compare_result_as_ordering(1) == 0));
+ EXPECT_TRUE(
+ Identity(absl::compare_internal::compare_result_as_ordering(1) > 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) < 0));
+ EXPECT_FALSE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) == 0));
+ EXPECT_TRUE(Identity(absl::compare_internal::compare_result_as_ordering(
+ weak_ordering::greater) > 0));
+}
+
+TEST(DoThreeWayComparison, SanityTest) {
+ std::less<int> less;
+ WeakOrderingLess weak;
+
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, -1, 0) > 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, -1, 0) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 10) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) < 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) == 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 10) > 0));
+
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(less, 10, 5) > 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) < 0));
+ EXPECT_FALSE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) == 0));
+ EXPECT_TRUE(Identity(
+ absl::compare_internal::do_three_way_comparison(weak, 10, 5) > 0));
+}
+
+#ifdef __cpp_inline_variables
+TEST(Compare, StaticAsserts) {
+ static_assert(weak_equality::equivalent == 0, "");
+ static_assert(weak_equality::nonequivalent != 0, "");
+
+ static_assert(strong_equality::equal == 0, "");
+ static_assert(strong_equality::nonequal != 0, "");
+ static_assert(strong_equality::equivalent == 0, "");
+ static_assert(strong_equality::nonequivalent != 0, "");
+
+ static_assert(partial_ordering::less < 0, "");
+ static_assert(partial_ordering::equivalent == 0, "");
+ static_assert(partial_ordering::greater > 0, "");
+ static_assert(partial_ordering::unordered != 0, "");
+
+ static_assert(weak_ordering::less < 0, "");
+ static_assert(weak_ordering::equivalent == 0, "");
+ static_assert(weak_ordering::greater > 0, "");
+
+ static_assert(strong_ordering::less < 0, "");
+ static_assert(strong_ordering::equal == 0, "");
+ static_assert(strong_ordering::equivalent == 0, "");
+ static_assert(strong_ordering::greater > 0, "");
+}
+#endif // __cpp_inline_variables
+
+} // namespace
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_aliases.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_aliases.h
new file mode 100644
index 00000000000..0cc6884e309
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_aliases.h
@@ -0,0 +1,447 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// regularity_aliases.h
+// -----------------------------------------------------------------------------
+//
+// This file contains type aliases of common ConformanceProfiles and Archetypes
+// so that they can be directly used by name without creating them from scratch.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
+
+#include "absl/types/internal/conformance_archetype.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Creates both a Profile and a corresponding Archetype with root name "name".
+#define ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(name, ...) \
+ struct name##Profile : __VA_ARGS__ {}; \
+ \
+ using name##Archetype = ::absl::types_internal::Archetype<name##Profile>; \
+ \
+ template <class AbslInternalProfileTag> \
+ using name##Archetype##_ = ::absl::types_internal::Archetype< \
+ ::absl::types_internal::StrongProfileTypedef<name##Profile, \
+ AbslInternalProfileTag>>
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialDefaultConstructor,
+ ConformanceProfile<default_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowDefaultConstructor,
+ ConformanceProfile<default_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasDefaultConstructor, ConformanceProfile<default_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialMoveConstructor, ConformanceProfile<default_constructible::maybe,
+ move_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowMoveConstructor, ConformanceProfile<default_constructible::maybe,
+ move_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasMoveConstructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialCopyConstructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowCopyConstructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasCopyConstructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialMoveAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowMoveAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasMoveAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialCopyAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowCopyAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasCopyAssign,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasTrivialDestructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::trivial>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowDestructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasDestructor,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowEquality,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasEquality,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowInequality,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe,
+ inequality_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasInequality,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe, inequality_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowLessThan,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe, inequality_comparable::maybe,
+ less_than_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasLessThan,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe, inequality_comparable::maybe,
+ less_than_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowLessEqual,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe, inequality_comparable::maybe,
+ less_than_comparable::maybe,
+ less_equal_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasLessEqual,
+ ConformanceProfile<default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe,
+ equality_comparable::maybe, inequality_comparable::maybe,
+ less_than_comparable::maybe,
+ less_equal_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowGreaterEqual,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasGreaterEqual,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowGreaterThan,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::maybe,
+ greater_than_comparable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasGreaterThan,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::maybe,
+ greater_than_comparable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasNothrowSwap,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::maybe,
+ greater_than_comparable::maybe, swappable::nothrow>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasSwap,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::maybe,
+ greater_than_comparable::maybe, swappable::yes>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HasStdHashSpecialization,
+ ConformanceProfile<
+ default_constructible::maybe, move_constructible::maybe,
+ copy_constructible::maybe, move_assignable::maybe,
+ copy_assignable::maybe, destructible::maybe, equality_comparable::maybe,
+ inequality_comparable::maybe, less_than_comparable::maybe,
+ less_equal_comparable::maybe, greater_equal_comparable::maybe,
+ greater_than_comparable::maybe, swappable::maybe, hashable::yes>);
+
+////////////////////////////////////////////////////////////////////////////////
+//// The remaining aliases are combinations of the previous aliases. ////
+////////////////////////////////////////////////////////////////////////////////
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ Equatable, CombineProfiles<HasEqualityProfile, HasInequalityProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ Comparable,
+ CombineProfiles<EquatableProfile, HasLessThanProfile, HasLessEqualProfile,
+ HasGreaterEqualProfile, HasGreaterThanProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ NothrowEquatable,
+ CombineProfiles<HasNothrowEqualityProfile, HasNothrowInequalityProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ NothrowComparable,
+ CombineProfiles<NothrowEquatableProfile, HasNothrowLessThanProfile,
+ HasNothrowLessEqualProfile, HasNothrowGreaterEqualProfile,
+ HasNothrowGreaterThanProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ Value,
+ CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
+ HasNothrowMoveAssignProfile, HasCopyAssignProfile,
+ HasNothrowDestructorProfile, HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ EquatableValue, CombineProfiles<EquatableProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ ComparableValue, CombineProfiles<ComparableProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ DefaultConstructibleValue,
+ CombineProfiles<HasDefaultConstructorProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ NothrowMoveConstructible, CombineProfiles<HasNothrowMoveConstructorProfile,
+ HasNothrowDestructorProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ EquatableNothrowMoveConstructible,
+ CombineProfiles<EquatableProfile, NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ ComparableNothrowMoveConstructible,
+ CombineProfiles<ComparableProfile, NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ DefaultConstructibleNothrowMoveConstructible,
+ CombineProfiles<HasDefaultConstructorProfile,
+ NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ CopyConstructible,
+ CombineProfiles<HasNothrowMoveConstructorProfile, HasCopyConstructorProfile,
+ HasNothrowDestructorProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ EquatableCopyConstructible,
+ CombineProfiles<EquatableProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ ComparableCopyConstructible,
+ CombineProfiles<ComparableProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ DefaultConstructibleCopyConstructible,
+ CombineProfiles<HasDefaultConstructorProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ NothrowMovable,
+ CombineProfiles<HasNothrowMoveConstructorProfile,
+ HasNothrowMoveAssignProfile, HasNothrowDestructorProfile,
+ HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ EquatableNothrowMovable,
+ CombineProfiles<EquatableProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ ComparableNothrowMovable,
+ CombineProfiles<ComparableProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ DefaultConstructibleNothrowMovable,
+ CombineProfiles<HasDefaultConstructorProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ TrivialSpecialMemberFunctions,
+ CombineProfiles<HasTrivialDefaultConstructorProfile,
+ HasTrivialMoveConstructorProfile,
+ HasTrivialCopyConstructorProfile,
+ HasTrivialMoveAssignProfile, HasTrivialCopyAssignProfile,
+ HasTrivialDestructorProfile, HasNothrowSwapProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ TriviallyComplete,
+ CombineProfiles<TrivialSpecialMemberFunctionsProfile, ComparableProfile,
+ HasStdHashSpecializationProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HashableNothrowMoveConstructible,
+ CombineProfiles<HasStdHashSpecializationProfile,
+ NothrowMoveConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HashableCopyConstructible,
+ CombineProfiles<HasStdHashSpecializationProfile, CopyConstructibleProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HashableNothrowMovable,
+ CombineProfiles<HasStdHashSpecializationProfile, NothrowMovableProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ HashableValue,
+ CombineProfiles<HasStdHashSpecializationProfile, ValueProfile>);
+
+ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS(
+ ComparableHashableValue,
+ CombineProfiles<HashableValueProfile, ComparableProfile>);
+
+// The "preferred" profiles that we support in Abseil.
+template <template <class...> class Receiver>
+using ExpandBasicProfiles =
+ Receiver<NothrowMoveConstructibleProfile, CopyConstructibleProfile,
+ NothrowMovableProfile, ValueProfile>;
+
+// The basic profiles except that they are also all Equatable.
+template <template <class...> class Receiver>
+using ExpandBasicEquatableProfiles =
+ Receiver<EquatableNothrowMoveConstructibleProfile,
+ EquatableCopyConstructibleProfile, EquatableNothrowMovableProfile,
+ EquatableValueProfile>;
+
+// The basic profiles except that they are also all Comparable.
+template <template <class...> class Receiver>
+using ExpandBasicComparableProfiles =
+ Receiver<ComparableNothrowMoveConstructibleProfile,
+ ComparableCopyConstructibleProfile,
+ ComparableNothrowMovableProfile, ComparableValueProfile>;
+
+// The basic profiles except that they are also all Hashable.
+template <template <class...> class Receiver>
+using ExpandBasicHashableProfiles =
+ Receiver<HashableNothrowMoveConstructibleProfile,
+ HashableCopyConstructibleProfile, HashableNothrowMovableProfile,
+ HashableValueProfile>;
+
+// The basic profiles except that they are also all DefaultConstructible.
+template <template <class...> class Receiver>
+using ExpandBasicDefaultConstructibleProfiles =
+ Receiver<DefaultConstructibleNothrowMoveConstructibleProfile,
+ DefaultConstructibleCopyConstructibleProfile,
+ DefaultConstructibleNothrowMovableProfile,
+ DefaultConstructibleValueProfile>;
+
+// The type profiles that we support in Abseil (all of the previous lists).
+template <template <class...> class Receiver>
+using ExpandSupportedProfiles = Receiver<
+ NothrowMoveConstructibleProfile, CopyConstructibleProfile,
+ NothrowMovableProfile, ValueProfile,
+ EquatableNothrowMoveConstructibleProfile, EquatableCopyConstructibleProfile,
+ EquatableNothrowMovableProfile, EquatableValueProfile,
+ ComparableNothrowMoveConstructibleProfile,
+ ComparableCopyConstructibleProfile, ComparableNothrowMovableProfile,
+ ComparableValueProfile, DefaultConstructibleNothrowMoveConstructibleProfile,
+ DefaultConstructibleCopyConstructibleProfile,
+ DefaultConstructibleNothrowMovableProfile, DefaultConstructibleValueProfile,
+ HashableNothrowMoveConstructibleProfile, HashableCopyConstructibleProfile,
+ HashableNothrowMovableProfile, HashableValueProfile>;
+
+// TODO(calabrese) Include types that have throwing move constructors, since in
+// practice we still need to support them because of standard library types with
+// (potentially) non-noexcept moves.
+
+} // namespace types_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#undef ABSL_INTERNAL_PROFILE_AND_ARCHETYPE_ALIAS
+
+#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ALIASES_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_archetype.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_archetype.h
new file mode 100644
index 00000000000..2349e0f7263
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_archetype.h
@@ -0,0 +1,978 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// conformance_archetype.h
+// -----------------------------------------------------------------------------
+//
+// This file contains a facility for generating "archetypes" of out of
+// "Conformance Profiles" (see "conformance_profiles.h" for more information
+// about Conformance Profiles). An archetype is a type that aims to support the
+// bare minimum requirements of a given Conformance Profile. For instance, an
+// archetype that corresponds to an ImmutableProfile has exactly a nothrow
+// move-constructor, a potentially-throwing copy constructor, a nothrow
+// destructor, with all other special-member-functions deleted. These archetypes
+// are useful for testing to make sure that templates are able to work with the
+// kinds of types that they claim to support (i.e. that they do not accidentally
+// under-constrain),
+//
+// The main type template in this file is the Archetype template, which takes
+// a Conformance Profile as a template argument and its instantiations are a
+// minimum-conforming model of that profile.
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
+
+#include <cstddef>
+#include <functional>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// A minimum-conforming implementation of a type with properties specified in
+// `Prof`, where `Prof` is a valid Conformance Profile.
+template <class Prof, class /*Enabler*/ = void>
+class Archetype;
+
+// Given an Archetype, obtain the properties of the profile associated with that
+// archetype.
+template <class Archetype>
+struct PropertiesOfArchetype;
+
+template <class Prof>
+struct PropertiesOfArchetype<Archetype<Prof>> {
+ using type = PropertiesOfT<Prof>;
+};
+
+template <class Archetype>
+using PropertiesOfArchetypeT = typename PropertiesOfArchetype<Archetype>::type;
+
+// A metafunction to determine if a type is an `Archetype`.
+template <class T>
+struct IsArchetype : std::false_type {};
+
+template <class Prof>
+struct IsArchetype<Archetype<Prof>> : std::true_type {};
+
+// A constructor tag type used when creating an Archetype with internal state.
+struct MakeArchetypeState {};
+
+// Data stored within an archetype that is copied/compared/hashed when the
+// corresponding operations are used.
+using ArchetypeState = std::size_t;
+
+////////////////////////////////////////////////////////////////////////////////
+// This section of the file defines a chain of base classes for Archetype, //
+// where each base defines a specific special member function with the //
+// appropriate properties (deleted, noexcept(false), noexcept, or trivial). //
+////////////////////////////////////////////////////////////////////////////////
+
+// The bottom-most base, which contains the state and the default constructor.
+template <default_constructible DefaultConstructibleValue>
+struct ArchetypeStateBase {
+ static_assert(DefaultConstructibleValue == default_constructible::yes ||
+ DefaultConstructibleValue == default_constructible::nothrow,
+ "");
+
+ ArchetypeStateBase() noexcept(
+ DefaultConstructibleValue ==
+ default_constructible::
+ nothrow) /*Vacuous archetype_state initialization*/ {}
+ explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+ : archetype_state(state) {}
+
+ ArchetypeState archetype_state;
+};
+
+template <>
+struct ArchetypeStateBase<default_constructible::maybe> {
+ explicit ArchetypeStateBase() = delete;
+ explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+ : archetype_state(state) {}
+
+ ArchetypeState archetype_state;
+};
+
+template <>
+struct ArchetypeStateBase<default_constructible::trivial> {
+ ArchetypeStateBase() = default;
+ explicit ArchetypeStateBase(MakeArchetypeState, ArchetypeState state) noexcept
+ : archetype_state(state) {}
+
+ ArchetypeState archetype_state;
+};
+
+// The move-constructor base
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue>
+struct ArchetypeMoveConstructor
+ : ArchetypeStateBase<DefaultConstructibleValue> {
+ static_assert(MoveConstructibleValue == move_constructible::yes ||
+ MoveConstructibleValue == move_constructible::nothrow,
+ "");
+
+ explicit ArchetypeMoveConstructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeMoveConstructor() = default;
+ ArchetypeMoveConstructor(ArchetypeMoveConstructor&& other) noexcept(
+ MoveConstructibleValue == move_constructible::nothrow)
+ : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+ other.archetype_state) {}
+ ArchetypeMoveConstructor(const ArchetypeMoveConstructor&) = default;
+ ArchetypeMoveConstructor& operator=(ArchetypeMoveConstructor&&) = default;
+ ArchetypeMoveConstructor& operator=(const ArchetypeMoveConstructor&) =
+ default;
+};
+
+template <default_constructible DefaultConstructibleValue>
+struct ArchetypeMoveConstructor<DefaultConstructibleValue,
+ move_constructible::trivial>
+ : ArchetypeStateBase<DefaultConstructibleValue> {
+ explicit ArchetypeMoveConstructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeStateBase<DefaultConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeMoveConstructor() = default;
+};
+
+// The copy-constructor base
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue>
+struct ArchetypeCopyConstructor
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue> {
+ static_assert(CopyConstructibleValue == copy_constructible::yes ||
+ CopyConstructibleValue == copy_constructible::nothrow,
+ "");
+ explicit ArchetypeCopyConstructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeCopyConstructor() = default;
+ ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
+ ArchetypeCopyConstructor(const ArchetypeCopyConstructor& other) noexcept(
+ CopyConstructibleValue == copy_constructible::nothrow)
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue>(
+ MakeArchetypeState(), other.archetype_state) {}
+ ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
+ ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
+ default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue>
+struct ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue,
+ copy_constructible::maybe>
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue> {
+ explicit ArchetypeCopyConstructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeCopyConstructor() = default;
+ ArchetypeCopyConstructor(ArchetypeCopyConstructor&&) = default;
+ ArchetypeCopyConstructor(const ArchetypeCopyConstructor&) = delete;
+ ArchetypeCopyConstructor& operator=(ArchetypeCopyConstructor&&) = default;
+ ArchetypeCopyConstructor& operator=(const ArchetypeCopyConstructor&) =
+ default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue>
+struct ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue,
+ copy_constructible::trivial>
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue> {
+ explicit ArchetypeCopyConstructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeCopyConstructor() = default;
+};
+
+// The move-assign base
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue>
+struct ArchetypeMoveAssign
+ : ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue, CopyConstructibleValue> {
+ static_assert(MoveAssignableValue == move_assignable::yes ||
+ MoveAssignableValue == move_assignable::nothrow,
+ "");
+ explicit ArchetypeMoveAssign(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue,
+ CopyConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeMoveAssign() = default;
+ ArchetypeMoveAssign(ArchetypeMoveAssign&&) = default;
+ ArchetypeMoveAssign(const ArchetypeMoveAssign&) = default;
+ ArchetypeMoveAssign& operator=(ArchetypeMoveAssign&& other) noexcept(
+ MoveAssignableValue == move_assignable::nothrow) {
+ this->archetype_state = other.archetype_state;
+ return *this;
+ }
+
+ ArchetypeMoveAssign& operator=(const ArchetypeMoveAssign&) = default;
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue>
+struct ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, move_assignable::trivial>
+ : ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue, CopyConstructibleValue> {
+ explicit ArchetypeMoveAssign(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeCopyConstructor<DefaultConstructibleValue,
+ MoveConstructibleValue,
+ CopyConstructibleValue>(MakeArchetypeState(),
+ state) {}
+
+ ArchetypeMoveAssign() = default;
+};
+
+// The copy-assign base
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue,
+ copy_assignable CopyAssignableValue>
+struct ArchetypeCopyAssign
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue> {
+ static_assert(CopyAssignableValue == copy_assignable::yes ||
+ CopyAssignableValue == copy_assignable::nothrow,
+ "");
+ explicit ArchetypeCopyAssign(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue>(
+ MakeArchetypeState(), state) {}
+
+ ArchetypeCopyAssign() = default;
+ ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
+ ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
+ ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
+
+ ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign& other) noexcept(
+ CopyAssignableValue == copy_assignable::nothrow) {
+ this->archetype_state = other.archetype_state;
+ return *this;
+ }
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue>
+struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ copy_assignable::maybe>
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue> {
+ explicit ArchetypeCopyAssign(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue>(
+ MakeArchetypeState(), state) {}
+
+ ArchetypeCopyAssign() = default;
+ ArchetypeCopyAssign(ArchetypeCopyAssign&&) = default;
+ ArchetypeCopyAssign(const ArchetypeCopyAssign&) = default;
+ ArchetypeCopyAssign& operator=(ArchetypeCopyAssign&&) = default;
+ ArchetypeCopyAssign& operator=(const ArchetypeCopyAssign&) = delete;
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue>
+struct ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ copy_assignable::trivial>
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue> {
+ explicit ArchetypeCopyAssign(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeMoveAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue>(
+ MakeArchetypeState(), state) {}
+
+ ArchetypeCopyAssign() = default;
+};
+
+// The destructor base
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue,
+ copy_assignable CopyAssignableValue, destructible DestructibleValue>
+struct ArchetypeDestructor
+ : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ CopyAssignableValue> {
+ static_assert(DestructibleValue == destructible::yes ||
+ DestructibleValue == destructible::nothrow,
+ "");
+
+ explicit ArchetypeDestructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ CopyAssignableValue>(MakeArchetypeState(), state) {}
+
+ ArchetypeDestructor() = default;
+ ArchetypeDestructor(ArchetypeDestructor&&) = default;
+ ArchetypeDestructor(const ArchetypeDestructor&) = default;
+ ArchetypeDestructor& operator=(ArchetypeDestructor&&) = default;
+ ArchetypeDestructor& operator=(const ArchetypeDestructor&) = default;
+ ~ArchetypeDestructor() noexcept(DestructibleValue == destructible::nothrow) {}
+};
+
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue,
+ copy_assignable CopyAssignableValue>
+struct ArchetypeDestructor<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ CopyAssignableValue, destructible::trivial>
+ : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ CopyAssignableValue> {
+ explicit ArchetypeDestructor(MakeArchetypeState,
+ ArchetypeState state) noexcept
+ : ArchetypeCopyAssign<DefaultConstructibleValue, MoveConstructibleValue,
+ CopyConstructibleValue, MoveAssignableValue,
+ CopyAssignableValue>(MakeArchetypeState(), state) {}
+
+ ArchetypeDestructor() = default;
+};
+
+// An alias to the top of the chain of bases for special-member functions.
+// NOTE: move_constructible::maybe, move_assignable::maybe, and
+// destructible::maybe are handled in the top-level type by way of SFINAE.
+// Because of this, we never instantiate the base classes with
+// move_constructible::maybe, move_assignable::maybe, or destructible::maybe so
+// that we minimize the number of different possible type-template
+// instantiations.
+template <default_constructible DefaultConstructibleValue,
+ move_constructible MoveConstructibleValue,
+ copy_constructible CopyConstructibleValue,
+ move_assignable MoveAssignableValue,
+ copy_assignable CopyAssignableValue, destructible DestructibleValue>
+using ArchetypeSpecialMembersBase = ArchetypeDestructor<
+ DefaultConstructibleValue,
+ MoveConstructibleValue != move_constructible::maybe
+ ? MoveConstructibleValue
+ : move_constructible::nothrow,
+ CopyConstructibleValue,
+ MoveAssignableValue != move_assignable::maybe ? MoveAssignableValue
+ : move_assignable::nothrow,
+ CopyAssignableValue,
+ DestructibleValue != destructible::maybe ? DestructibleValue
+ : destructible::nothrow>;
+
+// A function that is used to create an archetype with some associated state.
+template <class Arch>
+Arch MakeArchetype(ArchetypeState state) noexcept {
+ static_assert(IsArchetype<Arch>::value,
+ "The explicit template argument to MakeArchetype is required "
+ "to be an Archetype.");
+ return Arch(MakeArchetypeState(), state);
+}
+
+// This is used to conditionally delete "copy" and "move" constructors in a way
+// that is consistent with what the ConformanceProfile requires and that also
+// strictly enforces the arguments to the copy/move to not come from implicit
+// conversions when dealing with the Archetype.
+template <class Prof, class T>
+constexpr bool ShouldDeleteConstructor() {
+ return !((PropertiesOfT<Prof>::move_constructible_support !=
+ move_constructible::maybe &&
+ std::is_same<T, Archetype<Prof>>::value) ||
+ (PropertiesOfT<Prof>::copy_constructible_support !=
+ copy_constructible::maybe &&
+ (std::is_same<T, const Archetype<Prof>&>::value ||
+ std::is_same<T, Archetype<Prof>&>::value ||
+ std::is_same<T, const Archetype<Prof>>::value)));
+}
+
+// This is used to conditionally delete "copy" and "move" assigns in a way
+// that is consistent with what the ConformanceProfile requires and that also
+// strictly enforces the arguments to the copy/move to not come from implicit
+// conversions when dealing with the Archetype.
+template <class Prof, class T>
+constexpr bool ShouldDeleteAssign() {
+ return !(
+ (PropertiesOfT<Prof>::move_assignable_support != move_assignable::maybe &&
+ std::is_same<T, Archetype<Prof>>::value) ||
+ (PropertiesOfT<Prof>::copy_assignable_support != copy_assignable::maybe &&
+ (std::is_same<T, const Archetype<Prof>&>::value ||
+ std::is_same<T, Archetype<Prof>&>::value ||
+ std::is_same<T, const Archetype<Prof>>::value)));
+}
+
+// TODO(calabrese) Inherit from a chain of secondary bases to pull in the
+// associated functions of other concepts.
+template <class Prof, class Enabler>
+class Archetype : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ static_assert(std::is_same<Enabler, void>::value,
+ "An explicit type must not be passed as the second template "
+ "argument to 'Archetype`.");
+
+ // The cases mentioned in these static_asserts are expected to be handled in
+ // the partial template specializations of Archetype that follow this
+ // definition.
+ static_assert(PropertiesOfT<Prof>::destructible_support !=
+ destructible::maybe,
+ "");
+ static_assert(PropertiesOfT<Prof>::move_constructible_support !=
+ move_constructible::maybe ||
+ PropertiesOfT<Prof>::copy_constructible_support ==
+ copy_constructible::maybe,
+ "");
+ static_assert(PropertiesOfT<Prof>::move_assignable_support !=
+ move_assignable::maybe ||
+ PropertiesOfT<Prof>::copy_assignable_support ==
+ copy_assignable::maybe,
+ "");
+
+ public:
+ Archetype() = default;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support !=
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support ==
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support !=
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = default;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = delete;
+ Archetype& operator=(const Archetype&) = default;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support ==
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support ==
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support !=
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = delete;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = delete;
+ Archetype& operator=(const Archetype&) = default;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support ==
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support !=
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support !=
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = delete;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = default;
+ Archetype& operator=(const Archetype&) = default;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support !=
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support ==
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support ==
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = default;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = delete;
+ Archetype& operator=(const Archetype&) = default;
+ ~Archetype() = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support ==
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support ==
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support ==
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = delete;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = delete;
+ Archetype& operator=(const Archetype&) = default;
+ ~Archetype() = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+template <class Prof>
+class Archetype<Prof, typename std::enable_if<
+ PropertiesOfT<Prof>::move_constructible_support ==
+ move_constructible::maybe &&
+ PropertiesOfT<Prof>::move_assignable_support !=
+ move_assignable::maybe &&
+ PropertiesOfT<Prof>::destructible_support ==
+ destructible::maybe>::type>
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support> {
+ public:
+ Archetype() = default;
+ Archetype(Archetype&&) = delete;
+ Archetype(const Archetype&) = default;
+ Archetype& operator=(Archetype&&) = default;
+ Archetype& operator=(const Archetype&) = default;
+ ~Archetype() = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteConstructor<Prof, T>()>::type* = nullptr>
+ Archetype(T&&) = delete;
+
+ // Disallow moves when requested, and disallow implicit conversions.
+ template <class T, typename std::enable_if<
+ ShouldDeleteAssign<Prof, T>()>::type* = nullptr>
+ Archetype& operator=(T&&) = delete;
+
+ using ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>::archetype_state;
+
+ private:
+ explicit Archetype(MakeArchetypeState, ArchetypeState state) noexcept
+ : ArchetypeSpecialMembersBase<
+ PropertiesOfT<Prof>::default_constructible_support,
+ PropertiesOfT<Prof>::move_constructible_support,
+ PropertiesOfT<Prof>::copy_constructible_support,
+ PropertiesOfT<Prof>::move_assignable_support,
+ PropertiesOfT<Prof>::copy_assignable_support,
+ PropertiesOfT<Prof>::destructible_support>(MakeArchetypeState(),
+ state) {}
+
+ friend Archetype MakeArchetype<Archetype>(ArchetypeState) noexcept;
+};
+
+// Explicitly deleted swap for Archetype if the profile does not require swap.
+// It is important to delete it rather than simply leave it out so that the
+// "using std::swap;" idiom will result in this deleted overload being picked.
+template <class Prof,
+ absl::enable_if_t<!PropertiesOfT<Prof>::is_swappable, int> = 0>
+void swap(Archetype<Prof>&, Archetype<Prof>&) = delete; // NOLINT
+
+// A conditionally-noexcept swap implementation for Archetype when the profile
+// supports swap.
+template <class Prof,
+ absl::enable_if_t<PropertiesOfT<Prof>::is_swappable, int> = 0>
+void swap(Archetype<Prof>& lhs, Archetype<Prof>& rhs) // NOLINT
+ noexcept(PropertiesOfT<Prof>::swappable_support != swappable::yes) {
+ std::swap(lhs.archetype_state, rhs.archetype_state);
+}
+
+// A convertible-to-bool type that is used as the return type of comparison
+// operators since the standard doesn't always require exactly bool.
+struct NothrowBool {
+ explicit NothrowBool() = delete;
+ ~NothrowBool() = default;
+
+ // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
+ // elision makes it not required when returning from a function.
+ // NothrowBool(NothrowBool const&) = delete;
+
+ NothrowBool& operator=(NothrowBool const&) = delete;
+
+ explicit operator bool() const noexcept { return value; }
+
+ static NothrowBool make(bool const value) noexcept {
+ return NothrowBool(value);
+ }
+
+ private:
+ explicit NothrowBool(bool const value) noexcept : value(value) {}
+
+ bool value;
+};
+
+// A convertible-to-bool type that is used as the return type of comparison
+// operators since the standard doesn't always require exactly bool.
+// Note: ExceptionalBool has a conversion operator that is not noexcept, so
+// that even when a comparison operator is noexcept, that operation may still
+// potentially throw when converted to bool.
+struct ExceptionalBool {
+ explicit ExceptionalBool() = delete;
+ ~ExceptionalBool() = default;
+
+ // TODO(calabrese) Delete the copy constructor in C++17 mode since guaranteed
+ // elision makes it not required when returning from a function.
+ // ExceptionalBool(ExceptionalBool const&) = delete;
+
+ ExceptionalBool& operator=(ExceptionalBool const&) = delete;
+
+ explicit operator bool() const { return value; } // NOLINT
+
+ static ExceptionalBool make(bool const value) noexcept {
+ return ExceptionalBool(value);
+ }
+
+ private:
+ explicit ExceptionalBool(bool const value) noexcept : value(value) {}
+
+ bool value;
+};
+
+// The following macro is only used as a helper in this file to stamp out
+// comparison operator definitions. It is undefined after usage.
+//
+// NOTE: Non-nothrow operators throw via their result's conversion to bool even
+// though the operation itself is noexcept.
+#define ABSL_TYPES_INTERNAL_OP(enum_name, op) \
+ template <class Prof> \
+ absl::enable_if_t<!PropertiesOfT<Prof>::is_##enum_name, bool> operator op( \
+ const Archetype<Prof>&, const Archetype<Prof>&) = delete; \
+ \
+ template <class Prof> \
+ typename absl::enable_if_t< \
+ PropertiesOfT<Prof>::is_##enum_name, \
+ std::conditional<PropertiesOfT<Prof>::enum_name##_support == \
+ enum_name::nothrow, \
+ NothrowBool, ExceptionalBool>>::type \
+ operator op(const Archetype<Prof>& lhs, \
+ const Archetype<Prof>& rhs) noexcept { \
+ return absl::conditional_t< \
+ PropertiesOfT<Prof>::enum_name##_support == enum_name::nothrow, \
+ NothrowBool, ExceptionalBool>::make(lhs.archetype_state op \
+ rhs.archetype_state); \
+ }
+
+ABSL_TYPES_INTERNAL_OP(equality_comparable, ==);
+ABSL_TYPES_INTERNAL_OP(inequality_comparable, !=);
+ABSL_TYPES_INTERNAL_OP(less_than_comparable, <);
+ABSL_TYPES_INTERNAL_OP(less_equal_comparable, <=);
+ABSL_TYPES_INTERNAL_OP(greater_equal_comparable, >=);
+ABSL_TYPES_INTERNAL_OP(greater_than_comparable, >);
+
+#undef ABSL_TYPES_INTERNAL_OP
+
+// Base class for std::hash specializations when an Archetype doesn't support
+// hashing.
+struct PoisonedHash {
+ PoisonedHash() = delete;
+ PoisonedHash(const PoisonedHash&) = delete;
+ PoisonedHash& operator=(const PoisonedHash&) = delete;
+};
+
+// Base class for std::hash specializations when an Archetype supports hashing.
+template <class Prof>
+struct EnabledHash {
+ using argument_type = Archetype<Prof>;
+ using result_type = std::size_t;
+ result_type operator()(const argument_type& arg) const {
+ return std::hash<ArchetypeState>()(arg.archetype_state);
+ }
+};
+
+} // namespace types_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+namespace std {
+
+template <class Prof> // NOLINT
+struct hash<::absl::types_internal::Archetype<Prof>>
+ : conditional<::absl::types_internal::PropertiesOfT<Prof>::is_hashable,
+ ::absl::types_internal::EnabledHash<Prof>,
+ ::absl::types_internal::PoisonedHash>::type {};
+
+} // namespace std
+
+#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_ARCHETYPE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_profile.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_profile.h
new file mode 100644
index 00000000000..cf64ff4fcd1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_profile.h
@@ -0,0 +1,931 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// conformance_profiles.h
+// -----------------------------------------------------------------------------
+//
+// This file contains templates for representing "Regularity Profiles" and
+// concisely-named versions of commonly used Regularity Profiles.
+//
+// A Regularity Profile is a compile-time description of the types of operations
+// that a given type supports, along with properties of those operations when
+// they do exist. For instance, a Regularity Profile may describe a type that
+// has a move-constructor that is noexcept and a copy constructor that is not
+// noexcept. This description can then be examined and passed around to other
+// templates for the purposes of asserting expectations on user-defined types
+// via a series trait checks, or for determining what kinds of run-time tests
+// are able to be performed.
+//
+// Regularity Profiles are also used when creating "archetypes," which are
+// minimum-conforming types that meet all of the requirements of a given
+// Regularity Profile. For more information regarding archetypes, see
+// "conformance_archetypes.h".
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
+
+#include <set>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "gtest/gtest.h"
+#include "absl/algorithm/container.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/internal/conformance_testing_helpers.h"
+#include "absl/utility/utility.h"
+
+// TODO(calabrese) Add support for extending profiles.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Converts an enum to its underlying integral value.
+template <typename Enum>
+constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) {
+ return static_cast<absl::underlying_type_t<Enum>>(value);
+}
+
+// A tag type used in place of a matcher when checking that an assertion result
+// does not actually contain any errors.
+struct NoError {};
+
+// -----------------------------------------------------------------------------
+// ConformanceErrors
+// -----------------------------------------------------------------------------
+class ConformanceErrors {
+ public:
+ // Setup the error reporting mechanism by seeding it with the name of the type
+ // that is being tested.
+ explicit ConformanceErrors(std::string type_name)
+ : assertion_result_(false), type_name_(std::move(type_name)) {
+ assertion_result_ << "\n\n"
+ "Assuming the following type alias:\n"
+ "\n"
+ " using _T = "
+ << type_name_ << ";\n\n";
+ outputDivider();
+ }
+
+ // Adds the test name to the list of successfully run tests iff it was not
+ // previously reported as failing. This behavior is useful for tests that
+ // have multiple parts, where failures and successes are reported individually
+ // with the same test name.
+ void addTestSuccess(absl::string_view test_name) {
+ auto normalized_test_name = absl::AsciiStrToLower(test_name);
+
+ // If the test is already reported as failing, do not add it to the list of
+ // successes.
+ if (test_failures_.find(normalized_test_name) == test_failures_.end()) {
+ test_successes_.insert(std::move(normalized_test_name));
+ }
+ }
+
+ // Streams a single error description into the internal buffer (a visual
+ // divider is automatically inserted after the error so that multiple errors
+ // are visibly distinct).
+ //
+ // This function increases the error count by 1.
+ //
+ // TODO(calabrese) Determine desired behavior when if this function throws.
+ template <class... P>
+ void addTestFailure(absl::string_view test_name, const P&... args) {
+ // Output a message related to the test failure.
+ assertion_result_ << "\n\n"
+ "Failed test: "
+ << test_name << "\n\n";
+ addTestFailureImpl(args...);
+ assertion_result_ << "\n\n";
+ outputDivider();
+
+ auto normalized_test_name = absl::AsciiStrToLower(test_name);
+
+ // If previous parts of this test succeeded, remove it from that set.
+ test_successes_.erase(normalized_test_name);
+
+ // Add the test name to the list of failed tests.
+ test_failures_.insert(std::move(normalized_test_name));
+
+ has_error_ = true;
+ }
+
+ // Convert this object into a testing::AssertionResult instance such that it
+ // can be used with gtest.
+ ::testing::AssertionResult assertionResult() const {
+ return has_error_ ? assertion_result_ : ::testing::AssertionSuccess();
+ }
+
+ // Convert this object into a testing::AssertionResult instance such that it
+ // can be used with gtest. This overload expects errors, using the specified
+ // matcher.
+ ::testing::AssertionResult expectFailedTests(
+ const std::set<std::string>& test_names) const {
+ // Since we are expecting nonconformance, output an error message when the
+ // type actually conformed to the specified profile.
+ if (!has_error_) {
+ return ::testing::AssertionFailure()
+ << "Unexpected conformance of type:\n"
+ " "
+ << type_name_ << "\n\n";
+ }
+
+ // Get a list of all expected failures that did not actually fail
+ // (or that were not run).
+ std::vector<std::string> nonfailing_tests;
+ absl::c_set_difference(test_names, test_failures_,
+ std::back_inserter(nonfailing_tests));
+
+ // Get a list of all "expected failures" that were never actually run.
+ std::vector<std::string> unrun_tests;
+ absl::c_set_difference(nonfailing_tests, test_successes_,
+ std::back_inserter(unrun_tests));
+
+ // Report when the user specified tests that were not run.
+ if (!unrun_tests.empty()) {
+ const bool tests_were_run =
+ !(test_failures_.empty() && test_successes_.empty());
+
+ // Prepare an assertion result used in the case that tests pass that were
+ // expected to fail.
+ ::testing::AssertionResult result = ::testing::AssertionFailure();
+ result << "When testing type:\n " << type_name_
+ << "\n\nThe following tests were expected to fail but were not "
+ "run";
+
+ if (tests_were_run) result << " (was the test name spelled correctly?)";
+
+ result << ":\n\n";
+
+ // List all of the tests that unexpectedly passed.
+ for (const auto& test_name : unrun_tests) {
+ result << " " << test_name << "\n";
+ }
+
+ if (!tests_were_run) result << "\nNo tests were run.";
+
+ if (!test_failures_.empty()) {
+ // List test failures
+ result << "\nThe tests that were run and failed are:\n\n";
+ for (const auto& test_name : test_failures_) {
+ result << " " << test_name << "\n";
+ }
+ }
+
+ if (!test_successes_.empty()) {
+ // List test successes
+ result << "\nThe tests that were run and succeeded are:\n\n";
+ for (const auto& test_name : test_successes_) {
+ result << " " << test_name << "\n";
+ }
+ }
+
+ return result;
+ }
+
+ // If some tests passed when they were expected to fail, alert the caller.
+ if (nonfailing_tests.empty()) return ::testing::AssertionSuccess();
+
+ // Prepare an assertion result used in the case that tests pass that were
+ // expected to fail.
+ ::testing::AssertionResult unexpected_successes =
+ ::testing::AssertionFailure();
+ unexpected_successes << "When testing type:\n " << type_name_
+ << "\n\nThe following tests passed when they were "
+ "expected to fail:\n\n";
+
+ // List all of the tests that unexpectedly passed.
+ for (const auto& test_name : nonfailing_tests) {
+ unexpected_successes << " " << test_name << "\n";
+ }
+
+ return unexpected_successes;
+ }
+
+ private:
+ void outputDivider() {
+ assertion_result_ << "========================================";
+ }
+
+ void addTestFailureImpl() {}
+
+ template <class H, class... T>
+ void addTestFailureImpl(const H& head, const T&... tail) {
+ assertion_result_ << head;
+ addTestFailureImpl(tail...);
+ }
+
+ ::testing::AssertionResult assertion_result_;
+ std::set<std::string> test_failures_;
+ std::set<std::string> test_successes_;
+ std::string type_name_;
+ bool has_error_ = false;
+};
+
+template <class T, class /*Enabler*/ = void>
+struct PropertiesOfImpl {};
+
+template <class T>
+struct PropertiesOfImpl<T, absl::void_t<typename T::properties>> {
+ using type = typename T::properties;
+};
+
+template <class T>
+struct PropertiesOfImpl<T, absl::void_t<typename T::profile_alias_of>> {
+ using type = typename PropertiesOfImpl<typename T::profile_alias_of>::type;
+};
+
+template <class T>
+struct PropertiesOf : PropertiesOfImpl<T> {};
+
+template <class T>
+using PropertiesOfT = typename PropertiesOf<T>::type;
+
+// NOTE: These enums use this naming convention to be consistent with the
+// standard trait names, which is useful since it allows us to match up each
+// enum name with a corresponding trait name in macro definitions.
+
+// An enum that describes the various expectations on an operations existence.
+enum class function_support { maybe, yes, nothrow, trivial };
+
+constexpr const char* PessimisticPropertyDescription(function_support v) {
+ return v == function_support::maybe
+ ? "no"
+ : v == function_support::yes
+ ? "yes, potentially throwing"
+ : v == function_support::nothrow ? "yes, nothrow"
+ : "yes, trivial";
+}
+
+// Return a string that describes the kind of property support that was
+// expected.
+inline std::string ExpectedFunctionKindList(function_support min,
+ function_support max) {
+ if (min == max) {
+ std::string result =
+ absl::StrCat("Expected:\n ",
+ PessimisticPropertyDescription(
+ static_cast<function_support>(UnderlyingValue(min))),
+ "\n");
+ return result;
+ }
+
+ std::string result = "Expected one of:\n";
+ for (auto curr_support = UnderlyingValue(min);
+ curr_support <= UnderlyingValue(max); ++curr_support) {
+ absl::StrAppend(&result, " ",
+ PessimisticPropertyDescription(
+ static_cast<function_support>(curr_support)),
+ "\n");
+ }
+
+ return result;
+}
+
+template <class Enum>
+void ExpectModelOfImpl(ConformanceErrors* errors, Enum min_support,
+ Enum max_support, Enum kind) {
+ const auto kind_value = UnderlyingValue(kind);
+ const auto min_support_value = UnderlyingValue(min_support);
+ const auto max_support_value = UnderlyingValue(max_support);
+
+ if (!(kind_value >= min_support_value && kind_value <= max_support_value)) {
+ errors->addTestFailure(
+ PropertyName(kind), "**Failed property expectation**\n\n",
+ ExpectedFunctionKindList(
+ static_cast<function_support>(min_support_value),
+ static_cast<function_support>(max_support_value)),
+ '\n', "Actual:\n ",
+ PessimisticPropertyDescription(
+ static_cast<function_support>(kind_value)));
+ } else {
+ errors->addTestSuccess(PropertyName(kind));
+ }
+}
+
+#define ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(description, name) \
+ enum class name { maybe, yes, nothrow, trivial }; \
+ \
+ constexpr const char* PropertyName(name v) { return description; } \
+ static_assert(true, "") // Force a semicolon when using this macro.
+
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for default construction",
+ default_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move construction",
+ move_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy construction",
+ copy_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for move assignment",
+ move_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for copy assignment",
+ copy_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM("support for destruction",
+ destructible);
+
+#undef ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM
+
+#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(description, name) \
+ enum class name { maybe, yes, nothrow }; \
+ \
+ constexpr const char* PropertyName(name v) { return description; } \
+ static_assert(true, "") // Force a semicolon when using this macro.
+
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for ==", equality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for !=", inequality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <", less_than_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for <=", less_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >=",
+ greater_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for >", greater_than_comparable);
+
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable);
+
+#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM
+
+enum class hashable { maybe, yes };
+
+constexpr const char* PropertyName(hashable v) {
+ return "support for std::hash";
+}
+
+template <class T>
+using AlwaysFalse = std::false_type;
+
+#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(name, property) \
+ template <class T> \
+ constexpr property property##_support_of() { \
+ return std::is_##property<T>::value \
+ ? std::is_nothrow_##property<T>::value \
+ ? absl::is_trivially_##property<T>::value \
+ ? property::trivial \
+ : property::nothrow \
+ : property::yes \
+ : property::maybe; \
+ } \
+ \
+ template <class T, class MinProf, class MaxProf> \
+ void ExpectModelOf##name(ConformanceErrors* errors) { \
+ (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \
+ PropertiesOfT<MaxProf>::property##_support, \
+ property##_support_of<T>()); \
+ }
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(DefaultConstructible,
+ default_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveConstructible,
+ move_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyConstructible,
+ copy_constructible);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(MoveAssignable,
+ move_assignable);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(CopyAssignable,
+ copy_assignable);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER(Destructible, destructible);
+
+#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_SPECIAL_MEMBER
+
+void BoolFunction(bool) noexcept;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction for checking if an operation exists through SFINAE.
+//
+// `T` is the type to test and Op is an alias containing the expression to test.
+template <class T, template <class...> class Op, class = void>
+struct IsOpableImpl : std::false_type {};
+
+template <class T, template <class...> class Op>
+struct IsOpableImpl<T, Op, absl::void_t<Op<T>>> : std::true_type {};
+
+template <template <class...> class Op>
+struct IsOpable {
+ template <class T>
+ using apply = typename IsOpableImpl<T, Op>::type;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction for checking if an operation exists and is also noexcept
+// through SFINAE and the noexcept operator.
+///
+// `T` is the type to test and Op is an alias containing the expression to test.
+template <class T, template <class...> class Op, class = void>
+struct IsNothrowOpableImpl : std::false_type {};
+
+template <class T, template <class...> class Op>
+struct IsNothrowOpableImpl<T, Op, absl::enable_if_t<Op<T>::value>>
+ : std::true_type {};
+
+template <template <class...> class Op>
+struct IsNothrowOpable {
+ template <class T>
+ using apply = typename IsNothrowOpableImpl<T, Op>::type;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A macro that produces the necessary function for reporting what kind of
+// support a specific comparison operation has and a function for reporting an
+// error if a given type's support for that operation does not meet the expected
+// requirements.
+#define ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(name, property, op) \
+ template <class T, \
+ class Result = std::integral_constant< \
+ bool, noexcept((BoolFunction)(std::declval<const T&>() op \
+ std::declval<const T&>()))>> \
+ using name = Result; \
+ \
+ template <class T> \
+ constexpr property property##_support_of() { \
+ return IsOpable<name>::apply<T>::value \
+ ? IsNothrowOpable<name>::apply<T>::value ? property::nothrow \
+ : property::yes \
+ : property::maybe; \
+ } \
+ \
+ template <class T, class MinProf, class MaxProf> \
+ void ExpectModelOf##name(ConformanceErrors* errors) { \
+ (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::property##_support, \
+ PropertiesOfT<MaxProf>::property##_support, \
+ property##_support_of<T>()); \
+ }
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Generate the necessary support-checking and error reporting functions for
+// each of the comparison operators.
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(EqualityComparable,
+ equality_comparable, ==);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(InequalityComparable,
+ inequality_comparable, !=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessThanComparable,
+ less_than_comparable, <);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(LessEqualComparable,
+ less_equal_comparable, <=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterEqualComparable,
+ greater_equal_comparable, >=);
+
+ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON(GreaterThanComparable,
+ greater_than_comparable, >);
+
+#undef ABSL_INTERNAL_PESSIMISTIC_MODEL_OF_COMPARISON
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The necessary support-checking and error-reporting functions for swap.
+template <class T>
+constexpr swappable swappable_support_of() {
+ return type_traits_internal::IsSwappable<T>::value
+ ? type_traits_internal::IsNothrowSwappable<T>::value
+ ? swappable::nothrow
+ : swappable::yes
+ : swappable::maybe;
+}
+
+template <class T, class MinProf, class MaxProf>
+void ExpectModelOfSwappable(ConformanceErrors* errors) {
+ (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::swappable_support,
+ PropertiesOfT<MaxProf>::swappable_support,
+ swappable_support_of<T>());
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The necessary support-checking and error-reporting functions for std::hash.
+template <class T>
+constexpr hashable hashable_support_of() {
+ return type_traits_internal::IsHashable<T>::value ? hashable::yes
+ : hashable::maybe;
+}
+
+template <class T, class MinProf, class MaxProf>
+void ExpectModelOfHashable(ConformanceErrors* errors) {
+ (ExpectModelOfImpl)(errors, PropertiesOfT<MinProf>::hashable_support,
+ PropertiesOfT<MaxProf>::hashable_support,
+ hashable_support_of<T>());
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+template <
+ default_constructible DefaultConstructibleValue =
+ default_constructible::maybe,
+ move_constructible MoveConstructibleValue = move_constructible::maybe,
+ copy_constructible CopyConstructibleValue = copy_constructible::maybe,
+ move_assignable MoveAssignableValue = move_assignable::maybe,
+ copy_assignable CopyAssignableValue = copy_assignable::maybe,
+ destructible DestructibleValue = destructible::maybe,
+ equality_comparable EqualityComparableValue = equality_comparable::maybe,
+ inequality_comparable InequalityComparableValue =
+ inequality_comparable::maybe,
+ less_than_comparable LessThanComparableValue = less_than_comparable::maybe,
+ less_equal_comparable LessEqualComparableValue =
+ less_equal_comparable::maybe,
+ greater_equal_comparable GreaterEqualComparableValue =
+ greater_equal_comparable::maybe,
+ greater_than_comparable GreaterThanComparableValue =
+ greater_than_comparable::maybe,
+ swappable SwappableValue = swappable::maybe,
+ hashable HashableValue = hashable::maybe>
+struct ConformanceProfile {
+ using properties = ConformanceProfile;
+
+ static constexpr default_constructible
+ default_constructible_support = // NOLINT
+ DefaultConstructibleValue;
+
+ static constexpr move_constructible move_constructible_support = // NOLINT
+ MoveConstructibleValue;
+
+ static constexpr copy_constructible copy_constructible_support = // NOLINT
+ CopyConstructibleValue;
+
+ static constexpr move_assignable move_assignable_support = // NOLINT
+ MoveAssignableValue;
+
+ static constexpr copy_assignable copy_assignable_support = // NOLINT
+ CopyAssignableValue;
+
+ static constexpr destructible destructible_support = // NOLINT
+ DestructibleValue;
+
+ static constexpr equality_comparable equality_comparable_support = // NOLINT
+ EqualityComparableValue;
+
+ static constexpr inequality_comparable
+ inequality_comparable_support = // NOLINT
+ InequalityComparableValue;
+
+ static constexpr less_than_comparable
+ less_than_comparable_support = // NOLINT
+ LessThanComparableValue;
+
+ static constexpr less_equal_comparable
+ less_equal_comparable_support = // NOLINT
+ LessEqualComparableValue;
+
+ static constexpr greater_equal_comparable
+ greater_equal_comparable_support = // NOLINT
+ GreaterEqualComparableValue;
+
+ static constexpr greater_than_comparable
+ greater_than_comparable_support = // NOLINT
+ GreaterThanComparableValue;
+
+ static constexpr swappable swappable_support = SwappableValue; // NOLINT
+
+ static constexpr hashable hashable_support = HashableValue; // NOLINT
+
+ static constexpr bool is_default_constructible = // NOLINT
+ DefaultConstructibleValue != default_constructible::maybe;
+
+ static constexpr bool is_move_constructible = // NOLINT
+ MoveConstructibleValue != move_constructible::maybe;
+
+ static constexpr bool is_copy_constructible = // NOLINT
+ CopyConstructibleValue != copy_constructible::maybe;
+
+ static constexpr bool is_move_assignable = // NOLINT
+ MoveAssignableValue != move_assignable::maybe;
+
+ static constexpr bool is_copy_assignable = // NOLINT
+ CopyAssignableValue != copy_assignable::maybe;
+
+ static constexpr bool is_destructible = // NOLINT
+ DestructibleValue != destructible::maybe;
+
+ static constexpr bool is_equality_comparable = // NOLINT
+ EqualityComparableValue != equality_comparable::maybe;
+
+ static constexpr bool is_inequality_comparable = // NOLINT
+ InequalityComparableValue != inequality_comparable::maybe;
+
+ static constexpr bool is_less_than_comparable = // NOLINT
+ LessThanComparableValue != less_than_comparable::maybe;
+
+ static constexpr bool is_less_equal_comparable = // NOLINT
+ LessEqualComparableValue != less_equal_comparable::maybe;
+
+ static constexpr bool is_greater_equal_comparable = // NOLINT
+ GreaterEqualComparableValue != greater_equal_comparable::maybe;
+
+ static constexpr bool is_greater_than_comparable = // NOLINT
+ GreaterThanComparableValue != greater_than_comparable::maybe;
+
+ static constexpr bool is_swappable = // NOLINT
+ SwappableValue != swappable::maybe;
+
+ static constexpr bool is_hashable = // NOLINT
+ HashableValue != hashable::maybe;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Compliant SFINAE-friendliness is not always present on the standard library
+// implementations that we support. This helper-struct (and associated enum) is
+// used as a means to conditionally check the hashability support of a type.
+enum class CheckHashability { no, yes };
+
+template <class T, CheckHashability ShouldCheckHashability>
+struct conservative_hashable_support_of;
+
+template <class T>
+struct conservative_hashable_support_of<T, CheckHashability::no> {
+ static constexpr hashable Invoke() { return hashable::maybe; }
+};
+
+template <class T>
+struct conservative_hashable_support_of<T, CheckHashability::yes> {
+ static constexpr hashable Invoke() { return hashable_support_of<T>(); }
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// The ConformanceProfile that is expected based on introspection into the type
+// by way of trait checks.
+template <class T, CheckHashability ShouldCheckHashability>
+struct SyntacticConformanceProfileOf {
+ using properties = ConformanceProfile<
+ default_constructible_support_of<T>(), move_constructible_support_of<T>(),
+ copy_constructible_support_of<T>(), move_assignable_support_of<T>(),
+ copy_assignable_support_of<T>(), destructible_support_of<T>(),
+ equality_comparable_support_of<T>(),
+ inequality_comparable_support_of<T>(),
+ less_than_comparable_support_of<T>(),
+ less_equal_comparable_support_of<T>(),
+ greater_equal_comparable_support_of<T>(),
+ greater_than_comparable_support_of<T>(), swappable_support_of<T>(),
+ conservative_hashable_support_of<T, ShouldCheckHashability>::Invoke()>;
+};
+
+#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, name) \
+ template <default_constructible DefaultConstructibleValue, \
+ move_constructible MoveConstructibleValue, \
+ copy_constructible CopyConstructibleValue, \
+ move_assignable MoveAssignableValue, \
+ copy_assignable CopyAssignableValue, \
+ destructible DestructibleValue, \
+ equality_comparable EqualityComparableValue, \
+ inequality_comparable InequalityComparableValue, \
+ less_than_comparable LessThanComparableValue, \
+ less_equal_comparable LessEqualComparableValue, \
+ greater_equal_comparable GreaterEqualComparableValue, \
+ greater_than_comparable GreaterThanComparableValue, \
+ swappable SwappableValue, hashable HashableValue> \
+ constexpr type ConformanceProfile< \
+ DefaultConstructibleValue, MoveConstructibleValue, \
+ CopyConstructibleValue, MoveAssignableValue, CopyAssignableValue, \
+ DestructibleValue, EqualityComparableValue, InequalityComparableValue, \
+ LessThanComparableValue, LessEqualComparableValue, \
+ GreaterEqualComparableValue, GreaterThanComparableValue, SwappableValue, \
+ HashableValue>::name
+
+#define ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(type) \
+ ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(type, \
+ type##_support); \
+ ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL(bool, is_##type)
+
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(default_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_constructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(move_assignable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(copy_assignable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(destructible);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(equality_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(inequality_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_than_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(less_equal_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_equal_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(greater_than_comparable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(swappable);
+ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF(hashable);
+
+#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF
+#undef ABSL_INTERNAL_CONFORMANCE_TESTING_DATA_MEMBER_DEF_IMPL
+
+// Retrieve the enum with the minimum underlying value.
+// Note: std::min is not constexpr in C++11, which is why this is necessary.
+template <class H>
+constexpr H MinEnum(H head) {
+ return head;
+}
+
+template <class H, class N, class... T>
+constexpr H MinEnum(H head, N next, T... tail) {
+ return (UnderlyingValue)(head) < (UnderlyingValue)(next)
+ ? (MinEnum)(head, tail...)
+ : (MinEnum)(next, tail...);
+}
+
+template <class... Profs>
+struct MinimalProfiles {
+ static constexpr default_constructible
+ default_constructible_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::default_constructible_support...);
+
+ static constexpr move_constructible move_constructible_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::move_constructible_support...);
+
+ static constexpr copy_constructible copy_constructible_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
+
+ static constexpr move_assignable move_assignable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::move_assignable_support...);
+
+ static constexpr copy_assignable copy_assignable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
+
+ static constexpr destructible destructible_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::destructible_support...);
+
+ static constexpr equality_comparable equality_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
+
+ static constexpr inequality_comparable
+ inequality_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
+
+ static constexpr less_than_comparable
+ less_than_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
+
+ static constexpr less_equal_comparable
+ less_equal_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
+
+ static constexpr greater_equal_comparable
+ greater_equal_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
+
+ static constexpr greater_than_comparable
+ greater_than_comparable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
+
+ static constexpr swappable swappable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::swappable_support...);
+
+ static constexpr hashable hashable_support = // NOLINT
+ (MinEnum)(PropertiesOfT<Profs>::hashable_support...);
+
+ using properties = ConformanceProfile<
+ default_constructible_support, move_constructible_support,
+ copy_constructible_support, move_assignable_support,
+ copy_assignable_support, destructible_support,
+ equality_comparable_support, inequality_comparable_support,
+ less_than_comparable_support, less_equal_comparable_support,
+ greater_equal_comparable_support, greater_than_comparable_support,
+ swappable_support, hashable_support>;
+};
+
+// Retrieve the enum with the greatest underlying value.
+// Note: std::max is not constexpr in C++11, which is why this is necessary.
+template <class H>
+constexpr H MaxEnum(H head) {
+ return head;
+}
+
+template <class H, class N, class... T>
+constexpr H MaxEnum(H head, N next, T... tail) {
+ return (UnderlyingValue)(next) < (UnderlyingValue)(head)
+ ? (MaxEnum)(head, tail...)
+ : (MaxEnum)(next, tail...);
+}
+
+template <class... Profs>
+struct CombineProfilesImpl {
+ static constexpr default_constructible
+ default_constructible_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::default_constructible_support...);
+
+ static constexpr move_constructible move_constructible_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::move_constructible_support...);
+
+ static constexpr copy_constructible copy_constructible_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::copy_constructible_support...);
+
+ static constexpr move_assignable move_assignable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::move_assignable_support...);
+
+ static constexpr copy_assignable copy_assignable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::copy_assignable_support...);
+
+ static constexpr destructible destructible_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::destructible_support...);
+
+ static constexpr equality_comparable equality_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::equality_comparable_support...);
+
+ static constexpr inequality_comparable
+ inequality_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::inequality_comparable_support...);
+
+ static constexpr less_than_comparable
+ less_than_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::less_than_comparable_support...);
+
+ static constexpr less_equal_comparable
+ less_equal_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::less_equal_comparable_support...);
+
+ static constexpr greater_equal_comparable
+ greater_equal_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::greater_equal_comparable_support...);
+
+ static constexpr greater_than_comparable
+ greater_than_comparable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::greater_than_comparable_support...);
+
+ static constexpr swappable swappable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::swappable_support...);
+
+ static constexpr hashable hashable_support = // NOLINT
+ (MaxEnum)(PropertiesOfT<Profs>::hashable_support...);
+
+ using properties = ConformanceProfile<
+ default_constructible_support, move_constructible_support,
+ copy_constructible_support, move_assignable_support,
+ copy_assignable_support, destructible_support,
+ equality_comparable_support, inequality_comparable_support,
+ less_than_comparable_support, less_equal_comparable_support,
+ greater_equal_comparable_support, greater_than_comparable_support,
+ swappable_support, hashable_support>;
+};
+
+// NOTE: We use this as opposed to a direct alias of CombineProfilesImpl so that
+// when named aliases of CombineProfiles are created (such as in
+// conformance_aliases.h), we only pay for the combination algorithm on the
+// profiles that are actually used.
+template <class... Profs>
+struct CombineProfiles {
+ using profile_alias_of = CombineProfilesImpl<Profs...>;
+};
+
+template <>
+struct CombineProfiles<> {
+ using properties = ConformanceProfile<>;
+};
+
+template <class Profile, class Tag>
+struct StrongProfileTypedef {
+ using properties = PropertiesOfT<Profile>;
+};
+
+template <class T, class /*Enabler*/ = void>
+struct IsProfileImpl : std::false_type {};
+
+template <class T>
+struct IsProfileImpl<T, absl::void_t<PropertiesOfT<T>>> : std::true_type {};
+
+template <class T>
+struct IsProfile : IsProfileImpl<T>::type {};
+
+// A tag that describes which set of properties we will check when the user
+// requires a strict match in conformance (as opposed to a loose match which
+// allows more-refined support of any given operation).
+//
+// Currently only the RegularityDomain exists and it includes all operations
+// that the conformance testing suite knows about. The intent is that if the
+// suite is expanded to support extension, such as for checking conformance of
+// concepts like Iterators or Containers, additional corresponding domains can
+// be created.
+struct RegularityDomain {};
+
+} // namespace types_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_PROFILE_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing.h
new file mode 100644
index 00000000000..487b0f786b4
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing.h
@@ -0,0 +1,1386 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// conformance_testing.h
+// -----------------------------------------------------------------------------
+//
+
+#ifndef ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
+
+////////////////////////////////////////////////////////////////////////////////
+// //
+// Many templates in this file take a `T` and a `Prof` type as explicit //
+// template arguments. These are a type to be checked and a //
+// "Regularity Profile" that describes what operations that type `T` is //
+// expected to support. See "regularity_profiles.h" for more details //
+// regarding Regularity Profiles. //
+// //
+////////////////////////////////////////////////////////////////////////////////
+
+#include <cstddef>
+#include <set>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/internal/conformance_aliases.h"
+#include "absl/types/internal/conformance_archetype.h"
+#include "absl/types/internal/conformance_profile.h"
+#include "absl/types/internal/conformance_testing_helpers.h"
+#include "absl/types/internal/parentheses.h"
+#include "absl/types/internal/transform_args.h"
+#include "absl/utility/utility.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Returns true if the compiler incorrectly greedily instantiates constexpr
+// templates in any unevaluated context.
+constexpr bool constexpr_instantiation_when_unevaluated() {
+#if defined(__apple_build_version__) // TODO(calabrese) Make more specific
+ return true;
+#elif defined(__clang__)
+ return __clang_major__ < 4;
+#elif defined(__GNUC__)
+ // TODO(calabrese) Figure out why gcc 7 fails (seems like a different bug)
+ return __GNUC__ < 5 || (__GNUC__ == 5 && __GNUC_MINOR__ < 2) || __GNUC__ >= 7;
+#else
+ return false;
+#endif
+}
+
+// Returns true if the standard library being used incorrectly produces an error
+// when instantiating the definition of a poisoned std::hash specialization.
+constexpr bool poisoned_hash_fails_instantiation() {
+#if defined(_MSC_VER) && !defined(_LIBCPP_VERSION)
+ return _MSC_VER < 1914;
+#else
+ return false;
+#endif
+}
+
+template <class Fun>
+struct GeneratorType {
+ decltype(std::declval<const Fun&>()()) operator()() const
+ noexcept(noexcept(std::declval<const Fun&>()())) {
+ return fun();
+ }
+
+ Fun fun;
+ const char* description;
+};
+
+// A "make" function for the GeneratorType template that deduces the function
+// object type.
+template <class Fun,
+ absl::enable_if_t<IsNullaryCallable<Fun>::value>** = nullptr>
+GeneratorType<Fun> Generator(Fun fun, const char* description) {
+ return GeneratorType<Fun>{absl::move(fun), description};
+}
+
+// A type that contains a set of nullary function objects that each return an
+// instance of the same type and value (though possibly different
+// representations, such as +0 and -0 or two vectors with the same elements but
+// with different capacities).
+template <class... Funs>
+struct EquivalenceClassType {
+ std::tuple<GeneratorType<Funs>...> generators;
+};
+
+// A "make" function for the EquivalenceClassType template that deduces the
+// function object types and is constrained such that a user can only pass in
+// function objects that all have the same return type.
+template <class... Funs, absl::enable_if_t<AreGeneratorsWithTheSameReturnType<
+ Funs...>::value>** = nullptr>
+EquivalenceClassType<Funs...> EquivalenceClass(GeneratorType<Funs>... funs) {
+ return {std::make_tuple(absl::move(funs)...)};
+}
+
+// A type that contains an ordered series of EquivalenceClassTypes, from
+// smallest value to largest value.
+template <class... EqClasses>
+struct OrderedEquivalenceClasses {
+ std::tuple<EqClasses...> eq_classes;
+};
+
+// An object containing the parts of a given (name, initialization expression),
+// and is capable of generating a string that describes the given.
+struct GivenDeclaration {
+ std::string outputDeclaration(std::size_t width) const {
+ const std::size_t indent_size = 2;
+ std::string result = absl::StrCat(" ", name);
+
+ if (!expression.empty()) {
+ // Indent
+ result.resize(indent_size + width, ' ');
+ absl::StrAppend(&result, " = ", expression, ";\n");
+ } else {
+ absl::StrAppend(&result, ";\n");
+ }
+
+ return result;
+ }
+
+ std::string name;
+ std::string expression;
+};
+
+// Produce a string that contains all of the givens of an error report.
+template <class... Decls>
+std::string PrepareGivenContext(const Decls&... decls) {
+ const std::size_t width = (std::max)({decls.name.size()...});
+ return absl::StrCat("Given:\n", decls.outputDeclaration(width)..., "\n");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Function objects that perform a check for each comparison operator //
+////////////////////////////////////////////////////////////////////////////////
+
+#define ABSL_INTERNAL_EXPECT_OP(name, op) \
+ struct Expect##name { \
+ template <class T> \
+ void operator()(absl::string_view test_name, absl::string_view context, \
+ const T& lhs, const T& rhs, absl::string_view lhs_name, \
+ absl::string_view rhs_name) const { \
+ if (!static_cast<bool>(lhs op rhs)) { \
+ errors->addTestFailure( \
+ test_name, absl::StrCat(context, \
+ "**Unexpected comparison result**\n" \
+ "\n" \
+ "Expression:\n" \
+ " ", \
+ lhs_name, " " #op " ", rhs_name, \
+ "\n" \
+ "\n" \
+ "Expected: true\n" \
+ " Actual: false")); \
+ } else { \
+ errors->addTestSuccess(test_name); \
+ } \
+ } \
+ \
+ ConformanceErrors* errors; \
+ }; \
+ \
+ struct ExpectNot##name { \
+ template <class T> \
+ void operator()(absl::string_view test_name, absl::string_view context, \
+ const T& lhs, const T& rhs, absl::string_view lhs_name, \
+ absl::string_view rhs_name) const { \
+ if (lhs op rhs) { \
+ errors->addTestFailure( \
+ test_name, absl::StrCat(context, \
+ "**Unexpected comparison result**\n" \
+ "\n" \
+ "Expression:\n" \
+ " ", \
+ lhs_name, " " #op " ", rhs_name, \
+ "\n" \
+ "\n" \
+ "Expected: false\n" \
+ " Actual: true")); \
+ } else { \
+ errors->addTestSuccess(test_name); \
+ } \
+ } \
+ \
+ ConformanceErrors* errors; \
+ }
+
+ABSL_INTERNAL_EXPECT_OP(Eq, ==);
+ABSL_INTERNAL_EXPECT_OP(Ne, !=);
+ABSL_INTERNAL_EXPECT_OP(Lt, <);
+ABSL_INTERNAL_EXPECT_OP(Le, <=);
+ABSL_INTERNAL_EXPECT_OP(Ge, >=);
+ABSL_INTERNAL_EXPECT_OP(Gt, >);
+
+#undef ABSL_INTERNAL_EXPECT_OP
+
+// A function object that verifies that two objects hash to the same value by
+// way of the std::hash specialization.
+struct ExpectSameHash {
+ template <class T>
+ void operator()(absl::string_view test_name, absl::string_view context,
+ const T& lhs, const T& rhs, absl::string_view lhs_name,
+ absl::string_view rhs_name) const {
+ if (std::hash<T>()(lhs) != std::hash<T>()(rhs)) {
+ errors->addTestFailure(
+ test_name, absl::StrCat(context,
+ "**Unexpected hash result**\n"
+ "\n"
+ "Expression:\n"
+ " std::hash<T>()(",
+ lhs_name, ") == std::hash<T>()(", rhs_name,
+ ")\n"
+ "\n"
+ "Expected: true\n"
+ " Actual: false"));
+ } else {
+ errors->addTestSuccess(test_name);
+ }
+ }
+
+ ConformanceErrors* errors;
+};
+
+// A function template that takes two objects and verifies that each comparison
+// operator behaves in a way that is consistent with equality. It has "OneWay"
+// in the name because the first argument will always be the left-hand operand
+// of the corresponding comparison operator and the second argument will
+// always be the right-hand operand. It will never switch that order.
+// At a higher level in the test suite, the one-way form is called once for each
+// of the two possible orders whenever lhs and rhs are not the same initializer.
+template <class T, class Prof>
+void ExpectOneWayEquality(ConformanceErrors* errors,
+ absl::string_view test_name,
+ absl::string_view context, const T& lhs, const T& rhs,
+ absl::string_view lhs_name,
+ absl::string_view rhs_name) {
+ If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+ ExpectEq{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+ ExpectNotNe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+ ExpectNotLt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+ ExpectLe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+ ExpectGe{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+ ExpectNotGt{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+
+ If<PropertiesOfT<Prof>::is_hashable>::Invoke(
+ ExpectSameHash{errors}, test_name, context, lhs, rhs, lhs_name, rhs_name);
+}
+
+// A function template that takes two objects and verifies that each comparison
+// operator behaves in a way that is consistent with equality. This function
+// differs from ExpectOneWayEquality in that this will do checks with argument
+// order reversed in addition to in-order.
+template <class T, class Prof>
+void ExpectEquality(ConformanceErrors* errors, absl::string_view test_name,
+ absl::string_view context, const T& lhs, const T& rhs,
+ absl::string_view lhs_name, absl::string_view rhs_name) {
+ (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, lhs, rhs,
+ lhs_name, rhs_name);
+ (ExpectOneWayEquality<T, Prof>)(errors, test_name, context, rhs, lhs,
+ rhs_name, lhs_name);
+}
+
+// Given a generator, makes sure that a generated value and a moved-from
+// generated value are equal.
+template <class T, class Prof>
+struct ExpectMoveConstructOneGenerator {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T object = generator();
+ const T moved_object = absl::move(generator()); // Force no elision.
+
+ (ExpectEquality<T, Prof>)(errors, "Move construction",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T object",
+ generator.description},
+ GivenDeclaration{"const _T moved_object",
+ std::string("std::move(") +
+ generator.description +
+ ")"}),
+ object, moved_object, "object", "moved_object");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Given a generator, makes sure that a generated value and a copied-from
+// generated value are equal.
+template <class T, class Prof>
+struct ExpectCopyConstructOneGenerator {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T object = generator();
+ const T copied_object = static_cast<const T&>(generator());
+
+ (ExpectEquality<T, Prof>)(errors, "Copy construction",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T object",
+ generator.description},
+ GivenDeclaration{
+ "const _T copied_object",
+ std::string("static_cast<const _T&>(") +
+ generator.description + ")"}),
+ object, copied_object, "object", "copied_object");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Default-construct and do nothing before destruction.
+//
+// This is useful in exercising the codepath of default construction followed by
+// destruction, but does not explicitly test anything. An example of where this
+// might fail is a default destructor that default-initializes a scalar and a
+// destructor reads the value of that member. Sanitizers can catch this as long
+// as our test attempts to execute such a case.
+template <class T>
+struct ExpectDefaultConstructWithDestruct {
+ void operator()() const {
+ // Scoped so that destructor gets called before reporting success.
+ {
+ T object;
+ static_cast<void>(object);
+ }
+
+ errors->addTestSuccess("Default construction");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Check move-assign into a default-constructed object.
+template <class T, class Prof>
+struct ExpectDefaultConstructWithMoveAssign {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T source_of_truth = generator();
+ T object;
+ object = generator();
+
+ (ExpectEquality<T, Prof>)(errors, "Move assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T object",
+ generator.description},
+ GivenDeclaration{"_T object", ""},
+ GivenDeclaration{"object",
+ generator.description}),
+ object, source_of_truth, "std::as_const(object)",
+ "source_of_truth");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Check copy-assign into a default-constructed object.
+template <class T, class Prof>
+struct ExpectDefaultConstructWithCopyAssign {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T source_of_truth = generator();
+ T object;
+ object = static_cast<const T&>(generator());
+
+ (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth",
+ generator.description},
+ GivenDeclaration{"_T object", ""},
+ GivenDeclaration{
+ "object",
+ std::string("static_cast<const _T&>(") +
+ generator.description + ")"}),
+ object, source_of_truth, "std::as_const(object)",
+ "source_of_truth");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Perform a self move-assign.
+template <class T, class Prof>
+struct ExpectSelfMoveAssign {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ T object = generator();
+ object = absl::move(object);
+
+ // NOTE: Self move-assign results in a valid-but-unspecified state.
+
+ (ExpectEquality<T, Prof>)(errors, "Move assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"_T object",
+ generator.description},
+ GivenDeclaration{"object",
+ "std::move(object)"}),
+ object, object, "object", "object");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Perform a self copy-assign.
+template <class T, class Prof>
+struct ExpectSelfCopyAssign {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T source_of_truth = generator();
+ T object = generator();
+ const T& const_object = object;
+ object = const_object;
+
+ (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth",
+ generator.description},
+ GivenDeclaration{"_T object",
+ generator.description},
+ GivenDeclaration{"object",
+ "std::as_const(object)"}),
+ const_object, source_of_truth,
+ "std::as_const(object)", "source_of_truth");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Perform a self-swap.
+template <class T, class Prof>
+struct ExpectSelfSwap {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T source_of_truth = generator();
+ T object = generator();
+
+ type_traits_internal::Swap(object, object);
+
+ std::string preliminary_info = absl::StrCat(
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth", generator.description},
+ GivenDeclaration{"_T object", generator.description}),
+ "After performing a self-swap:\n"
+ " using std::swap;\n"
+ " swap(object, object);\n"
+ "\n");
+
+ (ExpectEquality<T, Prof>)(errors, "Swap", std::move(preliminary_info),
+ object, source_of_truth, "std::as_const(object)",
+ "source_of_truth");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Perform each of the single-generator checks when necessary operations are
+// supported.
+template <class T, class Prof>
+struct ExpectSelfComparison {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ const T object = generator();
+ (ExpectOneWayEquality<T, Prof>)(errors, "Comparison",
+ PrepareGivenContext(GivenDeclaration{
+ "const _T object",
+ generator.description}),
+ object, object, "object", "object");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Perform each of the single-generator checks when necessary operations are
+// supported.
+template <class T, class Prof>
+struct ExpectConsistency {
+ template <class Fun>
+ void operator()(const Fun& generator) const {
+ If<PropertiesOfT<Prof>::is_move_constructible>::Invoke(
+ ExpectMoveConstructOneGenerator<T, Prof>{errors}, generator);
+
+ If<PropertiesOfT<Prof>::is_copy_constructible>::Invoke(
+ ExpectCopyConstructOneGenerator<T, Prof>{errors}, generator);
+
+ If<PropertiesOfT<Prof>::is_default_constructible &&
+ PropertiesOfT<Prof>::is_move_assignable>::
+ Invoke(ExpectDefaultConstructWithMoveAssign<T, Prof>{errors},
+ generator);
+
+ If<PropertiesOfT<Prof>::is_default_constructible &&
+ PropertiesOfT<Prof>::is_copy_assignable>::
+ Invoke(ExpectDefaultConstructWithCopyAssign<T, Prof>{errors},
+ generator);
+
+ If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+ ExpectSelfMoveAssign<T, Prof>{errors}, generator);
+
+ If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+ ExpectSelfCopyAssign<T, Prof>{errors}, generator);
+
+ If<PropertiesOfT<Prof>::is_swappable>::Invoke(
+ ExpectSelfSwap<T, Prof>{errors}, generator);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Check move-assign with two different values.
+template <class T, class Prof>
+struct ExpectMoveAssign {
+ template <class Fun0, class Fun1>
+ void operator()(const Fun0& generator0, const Fun1& generator1) const {
+ const T source_of_truth1 = generator1();
+ T object = generator0();
+ object = generator1();
+
+ (ExpectEquality<T, Prof>)(errors, "Move assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth1",
+ generator1.description},
+ GivenDeclaration{"_T object",
+ generator0.description},
+ GivenDeclaration{"object",
+ generator1.description}),
+ object, source_of_truth1, "std::as_const(object)",
+ "source_of_truth1");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Check copy-assign with two different values.
+template <class T, class Prof>
+struct ExpectCopyAssign {
+ template <class Fun0, class Fun1>
+ void operator()(const Fun0& generator0, const Fun1& generator1) const {
+ const T source_of_truth1 = generator1();
+ T object = generator0();
+ object = static_cast<const T&>(generator1());
+
+ (ExpectEquality<T, Prof>)(errors, "Copy assignment",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth1",
+ generator1.description},
+ GivenDeclaration{"_T object",
+ generator0.description},
+ GivenDeclaration{
+ "object",
+ std::string("static_cast<const _T&>(") +
+ generator1.description + ")"}),
+ object, source_of_truth1, "std::as_const(object)",
+ "source_of_truth1");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Check swap with two different values.
+template <class T, class Prof>
+struct ExpectSwap {
+ template <class Fun0, class Fun1>
+ void operator()(const Fun0& generator0, const Fun1& generator1) const {
+ const T source_of_truth0 = generator0();
+ const T source_of_truth1 = generator1();
+ T object0 = generator0();
+ T object1 = generator1();
+
+ type_traits_internal::Swap(object0, object1);
+
+ const std::string context =
+ PrepareGivenContext(
+ GivenDeclaration{"const _T source_of_truth0",
+ generator0.description},
+ GivenDeclaration{"const _T source_of_truth1",
+ generator1.description},
+ GivenDeclaration{"_T object0", generator0.description},
+ GivenDeclaration{"_T object1", generator1.description}) +
+ "After performing a swap:\n"
+ " using std::swap;\n"
+ " swap(object0, object1);\n"
+ "\n";
+
+ (ExpectEquality<T, Prof>)(errors, "Swap", context, object0,
+ source_of_truth1, "std::as_const(object0)",
+ "source_of_truth1");
+ (ExpectEquality<T, Prof>)(errors, "Swap", context, object1,
+ source_of_truth0, "std::as_const(object1)",
+ "source_of_truth0");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Validate that `generator0` and `generator1` produce values that are equal.
+template <class T, class Prof>
+struct ExpectEquivalenceClassComparison {
+ template <class Fun0, class Fun1>
+ void operator()(const Fun0& generator0, const Fun1& generator1) const {
+ const T object0 = generator0();
+ const T object1 = generator1();
+
+ (ExpectEquality<T, Prof>)(errors, "Comparison",
+ PrepareGivenContext(
+ GivenDeclaration{"const _T object0",
+ generator0.description},
+ GivenDeclaration{"const _T object1",
+ generator1.description}),
+ object0, object1, "object0", "object1");
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Validate that all objects in the same equivalence-class have the same value.
+template <class T, class Prof>
+struct ExpectEquivalenceClassConsistency {
+ template <class Fun0, class Fun1>
+ void operator()(const Fun0& generator0, const Fun1& generator1) const {
+ If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+ ExpectMoveAssign<T, Prof>{errors}, generator0, generator1);
+
+ If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+ ExpectCopyAssign<T, Prof>{errors}, generator0, generator1);
+
+ If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
+ generator0, generator1);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Given a "lesser" object and a "greater" object, perform every combination of
+// comparison operators supported for the type, expecting consistent results.
+template <class T, class Prof>
+void ExpectOrdered(ConformanceErrors* errors, absl::string_view context,
+ const T& small, const T& big, absl::string_view small_name,
+ absl::string_view big_name) {
+ const absl::string_view test_name = "Comparison";
+
+ If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+ ExpectNotEq{errors}, test_name, context, small, big, small_name,
+ big_name);
+ If<PropertiesOfT<Prof>::is_equality_comparable>::Invoke(
+ ExpectNotEq{errors}, test_name, context, big, small, big_name,
+ small_name);
+
+ If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+ ExpectNe{errors}, test_name, context, small, big, small_name, big_name);
+ If<PropertiesOfT<Prof>::is_inequality_comparable>::Invoke(
+ ExpectNe{errors}, test_name, context, big, small, big_name, small_name);
+
+ If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+ ExpectLt{errors}, test_name, context, small, big, small_name, big_name);
+ If<PropertiesOfT<Prof>::is_less_than_comparable>::Invoke(
+ ExpectNotLt{errors}, test_name, context, big, small, big_name,
+ small_name);
+
+ If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+ ExpectLe{errors}, test_name, context, small, big, small_name, big_name);
+ If<PropertiesOfT<Prof>::is_less_equal_comparable>::Invoke(
+ ExpectNotLe{errors}, test_name, context, big, small, big_name,
+ small_name);
+
+ If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+ ExpectNotGe{errors}, test_name, context, small, big, small_name,
+ big_name);
+ If<PropertiesOfT<Prof>::is_greater_equal_comparable>::Invoke(
+ ExpectGe{errors}, test_name, context, big, small, big_name, small_name);
+
+ If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+ ExpectNotGt{errors}, test_name, context, small, big, small_name,
+ big_name);
+ If<PropertiesOfT<Prof>::is_greater_than_comparable>::Invoke(
+ ExpectGt{errors}, test_name, context, big, small, big_name, small_name);
+}
+
+// For every two elements of an equivalence class, makes sure that those two
+// elements compare equal, including checks with the same argument passed as
+// both operands.
+template <class T, class Prof>
+struct ExpectEquivalenceClassComparisons {
+ template <class... Funs>
+ void operator()(EquivalenceClassType<Funs...> eq_class) const {
+ (ForEachTupleElement)(ExpectSelfComparison<T, Prof>{errors},
+ eq_class.generators);
+
+ (ForEveryTwo)(ExpectEquivalenceClassComparison<T, Prof>{errors},
+ eq_class.generators);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// For every element of an equivalence class, makes sure that the element is
+// self-consistent (in other words, if any of move/copy/swap are defined,
+// perform those operations and make such that results and operands still
+// compare equal to known values whenever it is required for that operation.
+template <class T, class Prof>
+struct ExpectEquivalenceClass {
+ template <class... Funs>
+ void operator()(EquivalenceClassType<Funs...> eq_class) const {
+ (ForEachTupleElement)(ExpectConsistency<T, Prof>{errors},
+ eq_class.generators);
+
+ (ForEveryTwo)(ExpectEquivalenceClassConsistency<T, Prof>{errors},
+ eq_class.generators);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Validate that the passed-in argument is a generator of a greater value than
+// the one produced by the "small_gen" datamember with respect to all of the
+// comparison operators that Prof requires, with both argument orders to test.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanComparisons {
+ template <class BigGenerator>
+ void operator()(BigGenerator big_gen) const {
+ const T small = small_gen();
+ const T big = big_gen();
+
+ (ExpectOrdered<T, Prof>)(errors,
+ PrepareGivenContext(
+ GivenDeclaration{"const _T small",
+ small_gen.description},
+ GivenDeclaration{"const _T big",
+ big_gen.description}),
+ small, big, "small", "big");
+ }
+
+ SmallGenerator small_gen;
+ ConformanceErrors* errors;
+};
+
+// Perform all of the move, copy, and swap checks on the value generated by
+// `small_gen` and the value generated by `big_gen`.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThan {
+ template <class BigGenerator>
+ void operator()(BigGenerator big_gen) const {
+ If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+ ExpectMoveAssign<T, Prof>{errors}, small_gen, big_gen);
+ If<PropertiesOfT<Prof>::is_move_assignable>::Invoke(
+ ExpectMoveAssign<T, Prof>{errors}, big_gen, small_gen);
+
+ If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+ ExpectCopyAssign<T, Prof>{errors}, small_gen, big_gen);
+ If<PropertiesOfT<Prof>::is_copy_assignable>::Invoke(
+ ExpectCopyAssign<T, Prof>{errors}, big_gen, small_gen);
+
+ If<PropertiesOfT<Prof>::is_swappable>::Invoke(ExpectSwap<T, Prof>{errors},
+ small_gen, big_gen);
+ }
+
+ SmallGenerator small_gen;
+ ConformanceErrors* errors;
+};
+
+// Validate that the result of a generator is greater than the results of all
+// generators in an equivalence class with respect to comparisons.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanEqClassesComparisons {
+ template <class BigEqClass>
+ void operator()(BigEqClass big_eq_class) const {
+ (ForEachTupleElement)(
+ ExpectBiggerGeneratorThanComparisons<T, Prof, SmallGenerator>{small_gen,
+ errors},
+ big_eq_class.generators);
+ }
+
+ SmallGenerator small_gen;
+ ConformanceErrors* errors;
+};
+
+// Validate that the non-comparison binary operations required by Prof are
+// correct for the result of each generator of big_eq_class and a generator of
+// the logically smaller value returned by small_gen.
+template <class T, class Prof, class SmallGenerator>
+struct ExpectBiggerGeneratorThanEqClasses {
+ template <class BigEqClass>
+ void operator()(BigEqClass big_eq_class) const {
+ (ForEachTupleElement)(
+ ExpectBiggerGeneratorThan<T, Prof, SmallGenerator>{small_gen, errors},
+ big_eq_class.generators);
+ }
+
+ SmallGenerator small_gen;
+ ConformanceErrors* errors;
+};
+
+// Validate that each equivalence class that is passed is logically less than
+// the equivalence classes that comes later on in the argument list.
+template <class T, class Prof>
+struct ExpectOrderedEquivalenceClassesComparisons {
+ template <class... BigEqClasses>
+ struct Impl {
+ // Validate that the value produced by `small_gen` is less than all of the
+ // values generated by those of the logically larger equivalence classes.
+ template <class SmallGenerator>
+ void operator()(SmallGenerator small_gen) const {
+ (ForEachTupleElement)(ExpectBiggerGeneratorThanEqClassesComparisons<
+ T, Prof, SmallGenerator>{small_gen, errors},
+ big_eq_classes);
+ }
+
+ std::tuple<BigEqClasses...> big_eq_classes;
+ ConformanceErrors* errors;
+ };
+
+ // When given no equivalence classes, no validation is necessary.
+ void operator()() const {}
+
+ template <class SmallEqClass, class... BigEqClasses>
+ void operator()(SmallEqClass small_eq_class,
+ BigEqClasses... big_eq_classes) const {
+ // For each generator in the first equivalence class, make sure that it is
+ // less than each of those in the logically greater equivalence classes.
+ (ForEachTupleElement)(
+ Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
+ errors},
+ small_eq_class.generators);
+
+ // Recurse so that all equivalence class combinations are checked.
+ (*this)(absl::move(big_eq_classes)...);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Validate that the non-comparison binary operations required by Prof are
+// correct for the result of each generator of big_eq_classes and a generator of
+// the logically smaller value returned by small_gen.
+template <class T, class Prof>
+struct ExpectOrderedEquivalenceClasses {
+ template <class... BigEqClasses>
+ struct Impl {
+ template <class SmallGenerator>
+ void operator()(SmallGenerator small_gen) const {
+ (ForEachTupleElement)(
+ ExpectBiggerGeneratorThanEqClasses<T, Prof, SmallGenerator>{small_gen,
+ errors},
+ big_eq_classes);
+ }
+
+ std::tuple<BigEqClasses...> big_eq_classes;
+ ConformanceErrors* errors;
+ };
+
+ // Check that small_eq_class is logically consistent and also is logically
+ // less than all values in big_eq_classes.
+ template <class SmallEqClass, class... BigEqClasses>
+ void operator()(SmallEqClass small_eq_class,
+ BigEqClasses... big_eq_classes) const {
+ (ForEachTupleElement)(
+ Impl<BigEqClasses...>{std::make_tuple(absl::move(big_eq_classes)...),
+ errors},
+ small_eq_class.generators);
+
+ (*this)(absl::move(big_eq_classes)...);
+ }
+
+ // Terminating case of operator().
+ void operator()() const {}
+
+ ConformanceErrors* errors;
+};
+
+// Validate that a type meets the syntactic requirements of std::hash if the
+// range of profiles requires it.
+template <class T, class MinProf, class MaxProf>
+struct ExpectHashable {
+ void operator()() const {
+ ExpectModelOfHashable<T, MinProf, MaxProf>(errors);
+ }
+
+ ConformanceErrors* errors;
+};
+
+// Validate that the type `T` meets all of the requirements associated with
+// `MinProf` and without going beyond the syntactic properties of `MaxProf`.
+template <class T, class MinProf, class MaxProf>
+struct ExpectModels {
+ void operator()(ConformanceErrors* errors) const {
+ ExpectModelOfDefaultConstructible<T, MinProf, MaxProf>(errors);
+ ExpectModelOfMoveConstructible<T, MinProf, MaxProf>(errors);
+ ExpectModelOfCopyConstructible<T, MinProf, MaxProf>(errors);
+ ExpectModelOfMoveAssignable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfCopyAssignable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfDestructible<T, MinProf, MaxProf>(errors);
+ ExpectModelOfEqualityComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfInequalityComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfLessThanComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfLessEqualComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfGreaterEqualComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfGreaterThanComparable<T, MinProf, MaxProf>(errors);
+ ExpectModelOfSwappable<T, MinProf, MaxProf>(errors);
+
+ // Only check hashability on compilers that have a compliant default-hash.
+ If<!poisoned_hash_fails_instantiation()>::Invoke(
+ ExpectHashable<T, MinProf, MaxProf>{errors});
+ }
+};
+
+// A metafunction that yields a Profile matching the set of properties that are
+// safe to be checked (lack-of-hashability is only checked on standard library
+// implementations that are standards compliant in that they provide a std::hash
+// primary template that is SFINAE-friendly)
+template <class LogicalProf, class T>
+struct MinimalCheckableProfile {
+ using type =
+ MinimalProfiles<PropertiesOfT<LogicalProf>,
+ PropertiesOfT<SyntacticConformanceProfileOf<
+ T, !PropertiesOfT<LogicalProf>::is_hashable &&
+ poisoned_hash_fails_instantiation()
+ ? CheckHashability::no
+ : CheckHashability::yes>>>;
+};
+
+// An identity metafunction
+template <class T>
+struct Always {
+ using type = T;
+};
+
+// Validate the T meets all of the necessary requirements of LogicalProf, with
+// syntactic requirements defined by the profile range [MinProf, MaxProf].
+template <class T, class LogicalProf, class MinProf, class MaxProf,
+ class... EqClasses>
+ConformanceErrors ExpectRegularityImpl(
+ OrderedEquivalenceClasses<EqClasses...> vals) {
+ ConformanceErrors errors((NameOf<T>()));
+
+ If<!constexpr_instantiation_when_unevaluated()>::Invoke(
+ ExpectModels<T, MinProf, MaxProf>(), &errors);
+
+ using minimal_profile = typename absl::conditional_t<
+ constexpr_instantiation_when_unevaluated(), Always<LogicalProf>,
+ MinimalCheckableProfile<LogicalProf, T>>::type;
+
+ If<PropertiesOfT<minimal_profile>::is_default_constructible>::Invoke(
+ ExpectDefaultConstructWithDestruct<T>{&errors});
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Perform all comparison checks first, since later checks depend on their
+ // correctness.
+ //
+ // Check all of the comparisons for all values in the same equivalence
+ // class (equal with respect to comparison operators and hash the same).
+ (ForEachTupleElement)(
+ ExpectEquivalenceClassComparisons<T, minimal_profile>{&errors},
+ vals.eq_classes);
+
+ // Check all of the comparisons for each combination of values that are in
+ // different equivalence classes (not equal with respect to comparison
+ // operators).
+ absl::apply(
+ ExpectOrderedEquivalenceClassesComparisons<T, minimal_profile>{&errors},
+ vals.eq_classes);
+ //
+ //////////////////////////////////////////////////////////////////////////////
+
+ // Perform remaining checks, relying on comparisons.
+ // TODO(calabrese) short circuit if any comparisons above failed.
+ (ForEachTupleElement)(ExpectEquivalenceClass<T, minimal_profile>{&errors},
+ vals.eq_classes);
+
+ absl::apply(ExpectOrderedEquivalenceClasses<T, minimal_profile>{&errors},
+ vals.eq_classes);
+
+ return errors;
+}
+
+// A type that represents a range of profiles that are acceptable to be matched.
+//
+// `MinProf` is the minimum set of syntactic requirements that must be met.
+//
+// `MaxProf` is the maximum set of syntactic requirements that must be met.
+// This maximum is particularly useful for certain "strictness" checking. Some
+// examples for when this is useful:
+//
+// * Making sure that a type is move-only (rather than simply movable)
+//
+// * Making sure that a member function is *not* noexcept in cases where it
+// cannot be noexcept, such as if a dependent datamember has certain
+// operations that are not noexcept.
+//
+// * Making sure that a type tightly matches a spec, such as the standard.
+//
+// `LogicalProf` is the Profile for which run-time testing is to take place.
+//
+// Note: The reason for `LogicalProf` is because it is often the case, when
+// dealing with templates, that a declaration of a given operation is specified,
+// but whose body would fail to instantiate. Examples include the
+// copy-constructor of a standard container when the element-type is move-only,
+// or the comparison operators of a standard container when the element-type
+// does not have the necessary comparison operations defined. The `LogicalProf`
+// parameter allows us to capture the intent of what should be tested at
+// run-time, even in the cases where syntactically it might otherwise appear as
+// though the type undergoing testing supports more than it actually does.
+template <class LogicalProf, class MinProf = LogicalProf,
+ class MaxProf = MinProf>
+struct ProfileRange {
+ using logical_profile = LogicalProf;
+ using min_profile = MinProf;
+ using max_profile = MaxProf;
+};
+
+// Similar to ProfileRange except that it creates a profile range that is
+// coupled with a Domain and is used when testing that a type matches exactly
+// the "minimum" requirements of LogicalProf.
+template <class StrictnessDomain, class LogicalProf,
+ class MinProf = LogicalProf, class MaxProf = MinProf>
+struct StrictProfileRange {
+ // We do not yet support extension.
+ static_assert(
+ std::is_same<StrictnessDomain, RegularityDomain>::value,
+ "Currently, the only valid StrictnessDomain is RegularityDomain.");
+ using strictness_domain = StrictnessDomain;
+ using logical_profile = LogicalProf;
+ using min_profile = MinProf;
+ using max_profile = MaxProf;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that creates a StrictProfileRange from a Domain and either a
+// Profile or ProfileRange.
+template <class StrictnessDomain, class ProfOrRange>
+struct MakeStrictProfileRange;
+
+template <class StrictnessDomain, class LogicalProf>
+struct MakeStrictProfileRange {
+ using type = StrictProfileRange<StrictnessDomain, LogicalProf>;
+};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+ class MaxProf>
+struct MakeStrictProfileRange<StrictnessDomain,
+ ProfileRange<LogicalProf, MinProf, MaxProf>> {
+ using type =
+ StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
+};
+
+template <class StrictnessDomain, class ProfOrRange>
+using MakeStrictProfileRangeT =
+ typename MakeStrictProfileRange<StrictnessDomain, ProfOrRange>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A profile in the RegularityDomain with the strongest possible requirements.
+using MostStrictProfile =
+ CombineProfiles<TriviallyCompleteProfile, NothrowComparableProfile>;
+
+// Forms a ProfileRange that treats the Profile as the bare minimum requirements
+// of a type.
+template <class LogicalProf, class MinProf = LogicalProf>
+using LooseProfileRange = StrictProfileRange<RegularityDomain, LogicalProf,
+ MinProf, MostStrictProfile>;
+
+template <class Prof>
+using MakeLooseProfileRangeT = Prof;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// The following classes implement the metafunction ProfileRangeOfT<T> that
+// takes either a Profile or ProfileRange and yields the ProfileRange to be
+// used during testing.
+//
+template <class T, class /*Enabler*/ = void>
+struct ProfileRangeOfImpl;
+
+template <class T>
+struct ProfileRangeOfImpl<T, absl::void_t<PropertiesOfT<T>>> {
+ using type = LooseProfileRange<T>;
+};
+
+template <class T>
+struct ProfileRangeOf : ProfileRangeOfImpl<T> {};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+ class MaxProf>
+struct ProfileRangeOf<
+ StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>> {
+ using type =
+ StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>;
+};
+
+template <class T>
+using ProfileRangeOfT = typename ProfileRangeOf<T>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Extract the logical profile of a range (what will be runtime tested).
+template <class T>
+using LogicalProfileOfT = typename ProfileRangeOfT<T>::logical_profile;
+
+// Extract the minimal syntactic profile of a range (error if not at least).
+template <class T>
+using MinProfileOfT = typename ProfileRangeOfT<T>::min_profile;
+
+// Extract the maximum syntactic profile of a range (error if more than).
+template <class T>
+using MaxProfileOfT = typename ProfileRangeOfT<T>::max_profile;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+template <class T>
+struct IsProfileOrProfileRange : IsProfile<T>::type {};
+
+template <class StrictnessDomain, class LogicalProf, class MinProf,
+ class MaxProf>
+struct IsProfileOrProfileRange<
+ StrictProfileRange<StrictnessDomain, LogicalProf, MinProf, MaxProf>>
+ : std::true_type {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// TODO(calabrese): Consider naming the functions in this class the same as
+// the macros (defined later on) so that auto-complete leads to the correct name
+// and so that a user cannot accidentally call a function rather than the macro
+// form.
+template <bool ExpectSuccess, class T, class... EqClasses>
+struct ExpectConformanceOf {
+ // Add a value to be tested. Subsequent calls to this function on the same
+ // object must specify logically "larger" values with respect to the
+ // comparison operators of the type, if any.
+ //
+ // NOTE: This function should not be called directly. A stateless lambda is
+ // implicitly formed and passed when using the INITIALIZER macro at the bottom
+ // of this file.
+ template <class Fun,
+ absl::enable_if_t<std::is_same<
+ ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
+ ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+ EquivalenceClassType<Fun>>
+ initializer(GeneratorType<Fun> fun) && {
+ return {
+ {std::tuple_cat(absl::move(ordered_vals.eq_classes),
+ std::make_tuple((EquivalenceClass)(absl::move(fun))))},
+ std::move(expected_failed_tests)};
+ }
+
+ template <class... TestNames,
+ absl::enable_if_t<!ExpectSuccess && sizeof...(EqClasses) == 0 &&
+ absl::conjunction<std::is_convertible<
+ TestNames, absl::string_view>...>::value>** =
+ nullptr>
+ ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
+ due_to(TestNames&&... test_names) && {
+ (InsertEach)(&expected_failed_tests,
+ absl::AsciiStrToLower(absl::string_view(test_names))...);
+
+ return {absl::move(ordered_vals), std::move(expected_failed_tests)};
+ }
+
+ template <class... TestNames, int = 0, // MSVC disambiguator
+ absl::enable_if_t<ExpectSuccess && sizeof...(EqClasses) == 0 &&
+ absl::conjunction<std::is_convertible<
+ TestNames, absl::string_view>...>::value>** =
+ nullptr>
+ ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...>
+ due_to(TestNames&&... test_names) && {
+ // TODO(calabrese) Instead have DUE_TO only exist via a CRTP base.
+ // This would produce better errors messages than the static_assert.
+ static_assert(!ExpectSuccess,
+ "DUE_TO cannot be called when conformance is expected -- did "
+ "you mean to use ASSERT_NONCONFORMANCE_OF?");
+ }
+
+ // Add a value to be tested. Subsequent calls to this function on the same
+ // object must specify logically "larger" values with respect to the
+ // comparison operators of the type, if any.
+ //
+ // NOTE: This function should not be called directly. A stateful lambda is
+ // implicitly formed and passed when using the INITIALIZER macro at the bottom
+ // of this file.
+ template <class Fun,
+ absl::enable_if_t<std::is_same<
+ ResultOfGeneratorT<GeneratorType<Fun>>, T>::value>** = nullptr>
+ ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+ EquivalenceClassType<Fun>>
+ dont_class_directly_stateful_initializer(GeneratorType<Fun> fun) && {
+ return {
+ {std::tuple_cat(absl::move(ordered_vals.eq_classes),
+ std::make_tuple((EquivalenceClass)(absl::move(fun))))},
+ std::move(expected_failed_tests)};
+ }
+
+ // Add a set of value to be tested, where each value is equal with respect to
+ // the comparison operators and std::hash specialization, if defined.
+ template <
+ class... Funs,
+ absl::void_t<absl::enable_if_t<std::is_same<
+ ResultOfGeneratorT<GeneratorType<Funs>>, T>::value>...>** = nullptr>
+ ABSL_MUST_USE_RESULT ExpectConformanceOf<ExpectSuccess, T, EqClasses...,
+ EquivalenceClassType<Funs...>>
+ equivalence_class(GeneratorType<Funs>... funs) && {
+ return {{std::tuple_cat(
+ absl::move(ordered_vals.eq_classes),
+ std::make_tuple((EquivalenceClass)(absl::move(funs)...)))},
+ std::move(expected_failed_tests)};
+ }
+
+ // Execute the tests for the captured set of values, strictly matching a range
+ // of expected profiles in a given domain.
+ template <
+ class ProfRange,
+ absl::enable_if_t<IsProfileOrProfileRange<ProfRange>::value>** = nullptr>
+ ABSL_MUST_USE_RESULT ::testing::AssertionResult with_strict_profile(
+ ProfRange /*profile*/) {
+ ConformanceErrors test_result =
+ (ExpectRegularityImpl<
+ T, LogicalProfileOfT<ProfRange>, MinProfileOfT<ProfRange>,
+ MaxProfileOfT<ProfRange>>)(absl::move(ordered_vals));
+
+ return ExpectSuccess ? test_result.assertionResult()
+ : test_result.expectFailedTests(expected_failed_tests);
+ }
+
+ // Execute the tests for the captured set of values, loosely matching a range
+ // of expected profiles (loose in that an interface is allowed to be more
+ // refined that a profile suggests, such as a type having a noexcept copy
+ // constructor when all that is required is that the copy constructor exists).
+ template <class Prof, absl::enable_if_t<IsProfile<Prof>::value>** = nullptr>
+ ABSL_MUST_USE_RESULT ::testing::AssertionResult with_loose_profile(
+ Prof /*profile*/) {
+ ConformanceErrors test_result =
+ (ExpectRegularityImpl<
+ T, Prof, Prof,
+ CombineProfiles<TriviallyCompleteProfile,
+ NothrowComparableProfile>>)(absl::
+ move(ordered_vals));
+
+ return ExpectSuccess ? test_result.assertionResult()
+ : test_result.expectFailedTests(expected_failed_tests);
+ }
+
+ OrderedEquivalenceClasses<EqClasses...> ordered_vals;
+ std::set<std::string> expected_failed_tests;
+};
+
+template <class T>
+using ExpectConformanceOfType = ExpectConformanceOf</*ExpectSuccess=*/true, T>;
+
+template <class T>
+using ExpectNonconformanceOfType =
+ ExpectConformanceOf</*ExpectSuccess=*/false, T>;
+
+struct EquivalenceClassMaker {
+ // TODO(calabrese) Constrain to callable
+ template <class Fun>
+ static GeneratorType<Fun> initializer(GeneratorType<Fun> fun) {
+ return fun;
+ }
+};
+
+// A top-level macro that begins the builder pattern.
+//
+// The argument here takes the datatype to be tested.
+#define ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(...) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if ABSL_INTERNAL_LPAREN \
+ const ::testing::AssertionResult gtest_ar = \
+ ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectConformanceOfType< \
+ __VA_ARGS__>()
+
+// Akin to ASSERT_CONFORMANCE_OF except that it expects failure and tries to
+// match text.
+#define ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(...) \
+ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \
+ if ABSL_INTERNAL_LPAREN \
+ const ::testing::AssertionResult gtest_ar = \
+ ABSL_INTERNAL_LPAREN ::absl::types_internal::ExpectNonconformanceOfType< \
+ __VA_ARGS__>()
+
+////////////////////////////////////////////////////////////////////////////////
+// NOTE: The following macros look like they are recursive, but are not (macros
+// cannot recurse). These actually refer to member functions of the same name.
+// This is done intentionally so that a user cannot accidentally invoke a
+// member function of the conformance-testing suite without going through the
+// macro.
+////////////////////////////////////////////////////////////////////////////////
+
+// Specify expected test failures as comma-separated strings.
+#define DUE_TO(...) due_to(__VA_ARGS__)
+
+// Specify a value to be tested.
+//
+// Note: Internally, this takes an expression and turns it into the return value
+// of lambda that captures no data. The expression is stringized during
+// preprocessing so that it can be used in error reports.
+#define INITIALIZER(...) \
+ initializer(::absl::types_internal::Generator( \
+ [] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
+
+// Specify a value to be tested.
+//
+// Note: Internally, this takes an expression and turns it into the return value
+// of lambda that captures data by reference. The expression is stringized
+// during preprocessing so that it can be used in error reports.
+#define STATEFUL_INITIALIZER(...) \
+ stateful_initializer(::absl::types_internal::Generator( \
+ [&] { return __VA_ARGS__; }, ABSL_INTERNAL_STRINGIZE(__VA_ARGS__)))
+
+// Used in the builder-pattern.
+//
+// Takes a series of INITIALIZER and/or STATEFUL_INITIALIZER invocations and
+// forwards them along to be tested, grouping them such that the testing suite
+// knows that they are supposed to represent the same logical value (the values
+// compare the same, hash the same, etc.).
+#define EQUIVALENCE_CLASS(...) \
+ equivalence_class(ABSL_INTERNAL_TRANSFORM_ARGS( \
+ ABSL_INTERNAL_PREPEND_EQ_MAKER, __VA_ARGS__))
+
+// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
+// It takes a Profile as its argument.
+//
+// This executes the tests and allows types that are "more referined" than the
+// profile specifies, but not less. For instance, if the Profile specifies
+// noexcept copy-constructiblity, the test will fail if the copy-constructor is
+// not noexcept, however, it will succeed if the copy constructor is trivial.
+//
+// This is useful for testing that a type meets some minimum set of
+// requirements.
+#define WITH_LOOSE_PROFILE(...) \
+ with_loose_profile( \
+ ::absl::types_internal::MakeLooseProfileRangeT<__VA_ARGS__>()) \
+ ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \
+ else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT
+
+// An invocation of this or WITH_STRICT_PROFILE must end the builder-pattern.
+// It takes a Domain and a Profile as its arguments.
+//
+// This executes the tests and disallows types that differ at all from the
+// properties of the Profile. For instance, if the Profile specifies noexcept
+// copy-constructiblity, the test will fail if the copy constructor is trivial.
+//
+// This is useful for testing that a type does not do anything more than a
+// specification requires, such as to minimize things like Hyrum's Law, or more
+// commonly, to prevent a type from being "accidentally" copy-constructible in
+// a way that may produce incorrect results, simply because the user forget to
+// delete that operation.
+#define WITH_STRICT_PROFILE(...) \
+ with_strict_profile( \
+ ::absl::types_internal::MakeStrictProfileRangeT<__VA_ARGS__>()) \
+ ABSL_INTERNAL_RPAREN ABSL_INTERNAL_RPAREN; \
+ else GTEST_FATAL_FAILURE_(gtest_ar.failure_message()) // NOLINT
+
+// Internal macro that is used in the internals of the EDSL when forming
+// equivalence classes.
+#define ABSL_INTERNAL_PREPEND_EQ_MAKER(arg) \
+ ::absl::types_internal::EquivalenceClassMaker().arg
+
+} // namespace types_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_helpers.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
new file mode 100644
index 00000000000..00775f960c3
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
@@ -0,0 +1,391 @@
+// 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_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+#define ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
+
+// Checks to determine whether or not we can use abi::__cxa_demangle
+#if (defined(__ANDROID__) || defined(ANDROID)) && !defined(OS_ANDROID)
+#define ABSL_INTERNAL_OS_ANDROID
+#endif
+
+// We support certain compilers only. See demangle.h for details.
+#if defined(OS_ANDROID) && (defined(__i386__) || defined(__x86_64__))
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#elif (__GNUC__ >= 4 || (__GNUC__ >= 3 && __GNUC_MINOR__ >= 4)) && \
+ !defined(__mips__)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#elif defined(__clang__) && !defined(_MSC_VER)
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 1
+#else
+#define ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE 0
+#endif
+
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/meta/type_traits.h"
+#include "absl/strings/string_view.h"
+#include "absl/utility/utility.h"
+
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+#include <cxxabi.h>
+
+#include <cstdlib>
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace types_internal {
+
+// Return a readable name for type T.
+template <class T>
+absl::string_view NameOfImpl() {
+// TODO(calabrese) Investigate using debugging:internal_demangle as a fallback.
+#if ABSL_TYPES_INTERNAL_HAS_CXA_DEMANGLE
+ int status = 0;
+ char* demangled_name = nullptr;
+
+ demangled_name =
+ abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &status);
+
+ if (status == 0 && demangled_name != nullptr) {
+ return demangled_name;
+ } else {
+ return typeid(T).name();
+ }
+#else
+ return typeid(T).name();
+#endif
+ // NOTE: We intentionally leak demangled_name so that it remains valid
+ // throughout the remainder of the program.
+}
+
+// Given a type, returns as nice of a type name as we can produce (demangled).
+//
+// Note: This currently strips cv-qualifiers and references, but that is okay
+// because we only use this internally with unqualified object types.
+template <class T>
+std::string NameOf() {
+ static const absl::string_view result = NameOfImpl<T>();
+ return std::string(result);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Metafunction to check if a type is callable with no explicit arguments
+template <class Fun, class /*Enabler*/ = void>
+struct IsNullaryCallableImpl : std::false_type {};
+
+template <class Fun>
+struct IsNullaryCallableImpl<
+ Fun, absl::void_t<decltype(std::declval<const Fun&>()())>>
+ : std::true_type {
+ using result_type = decltype(std::declval<const Fun&>()());
+
+ template <class ValueType>
+ using for_type = std::is_same<ValueType, result_type>;
+
+ using void_if_true = void;
+};
+
+template <class Fun>
+struct IsNullaryCallable : IsNullaryCallableImpl<Fun> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains a function object that returns an instance of a type
+// that is undergoing conformance testing. This function is required to always
+// return the same value upon invocation.
+template <class Fun>
+struct GeneratorType;
+
+// A type that contains a tuple of GeneratorType<Fun> where each Fun has the
+// same return type. The result of each of the different generators should all
+// be equal values, though the underlying object representation may differ (such
+// as if one returns 0.0 and another return -0.0, or if one returns an empty
+// vector and another returns an empty vector with a different capacity.
+template <class... Funs>
+struct EquivalenceClassType;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to check if a type is a specialization of EquivalenceClassType
+template <class T>
+struct IsEquivalenceClass : std::false_type {};
+
+template <>
+struct IsEquivalenceClass<EquivalenceClassType<>> : std::true_type {
+ using self = IsEquivalenceClass;
+
+ // A metafunction to check if this EquivalenceClassType is a valid
+ // EquivalenceClassType for a type `ValueType` that is undergoing testing
+ template <class ValueType>
+ using for_type = std::true_type;
+};
+
+template <class Head, class... Tail>
+struct IsEquivalenceClass<EquivalenceClassType<Head, Tail...>>
+ : std::true_type {
+ using self = IsEquivalenceClass;
+
+ // The type undergoing conformance testing that this EquivalenceClass
+ // corresponds to
+ using result_type = typename IsNullaryCallable<Head>::result_type;
+
+ // A metafunction to check if this EquivalenceClassType is a valid
+ // EquivalenceClassType for a type `ValueType` that is undergoing testing
+ template <class ValueType>
+ using for_type = std::is_same<ValueType, result_type>;
+};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// A type that contains an ordered series of EquivalenceClassTypes, where the
+// the function object of each underlying GeneratorType has the same return type
+//
+// These equivalence classes are required to be in a logical ascending order
+// that is consistent with comparison operators that are defined for the return
+// type of each GeneratorType, if any.
+template <class... EqClasses>
+struct OrderedEquivalenceClasses;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction to determine the return type of the function object contained
+// in a GeneratorType specialization.
+template <class T>
+struct ResultOfGenerator {};
+
+template <class Fun>
+struct ResultOfGenerator<GeneratorType<Fun>> {
+ using type = decltype(std::declval<const Fun&>()());
+};
+
+template <class Fun>
+using ResultOfGeneratorT = typename ResultOfGenerator<GeneratorType<Fun>>::type;
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is a GeneratorType
+// specialization and they all contain functions with the same return type
+template <class /*Enabler*/, class... Funs>
+struct AreGeneratorsWithTheSameReturnTypeImpl : std::false_type {};
+
+template <>
+struct AreGeneratorsWithTheSameReturnTypeImpl<void> : std::true_type {};
+
+template <class Head, class... Tail>
+struct AreGeneratorsWithTheSameReturnTypeImpl<
+ typename std::enable_if<absl::conjunction<std::is_same<
+ ResultOfGeneratorT<Head>, ResultOfGeneratorT<Tail>>...>::value>::type,
+ Head, Tail...> : std::true_type {};
+
+template <class... Funs>
+struct AreGeneratorsWithTheSameReturnType
+ : AreGeneratorsWithTheSameReturnTypeImpl<void, Funs...>::type {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// A metafunction that yields true iff each of Funs is an EquivalenceClassType
+// specialization and they all contain GeneratorType specializations that have
+// the same return type
+template <class... EqClasses>
+struct AreEquivalenceClassesOfTheSameType {
+ static_assert(sizeof...(EqClasses) != sizeof...(EqClasses), "");
+};
+
+template <>
+struct AreEquivalenceClassesOfTheSameType<> : std::true_type {
+ using self = AreEquivalenceClassesOfTheSameType;
+
+ // Metafunction to check that a type is the same as all of the equivalence
+ // classes, if any.
+ // Note: In this specialization there are no equivalence classes, so the
+ // value type is always compatible.
+ template <class /*ValueType*/>
+ using for_type = std::true_type;
+};
+
+template <class... Funs>
+struct AreEquivalenceClassesOfTheSameType<EquivalenceClassType<Funs...>>
+ : std::true_type {
+ using self = AreEquivalenceClassesOfTheSameType;
+
+ // Metafunction to check that a type is the same as all of the equivalence
+ // classes, if any.
+ template <class ValueType>
+ using for_type = typename IsEquivalenceClass<
+ EquivalenceClassType<Funs...>>::template for_type<ValueType>;
+};
+
+template <class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<>, EquivalenceClassType<>, TailEqClasses...>
+ : AreEquivalenceClassesOfTheSameType<TailEqClasses...>::self {};
+
+template <class HeadNextFun, class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<>, EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+ TailEqClasses...>
+ : AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<HeadNextFun, TailNextFuns...>,
+ TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<HeadHeadFun, TailHeadFuns...>, EquivalenceClassType<>,
+ TailEqClasses...>
+ : AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+ TailEqClasses...>::self {};
+
+template <class HeadHeadFun, class... TailHeadFuns, class HeadNextFun,
+ class... TailNextFuns, class... TailEqClasses>
+struct AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+ EquivalenceClassType<HeadNextFun, TailNextFuns...>, TailEqClasses...>
+ : absl::conditional_t<
+ IsNullaryCallable<HeadNextFun>::template for_type<
+ typename IsNullaryCallable<HeadHeadFun>::result_type>::value,
+ AreEquivalenceClassesOfTheSameType<
+ EquivalenceClassType<HeadHeadFun, TailHeadFuns...>,
+ TailEqClasses...>,
+ std::false_type> {};
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// Execute a function for each passed-in parameter.
+template <class Fun, class... Cases>
+void ForEachParameter(const Fun& fun, const Cases&... cases) {
+ const std::initializer_list<bool> results = {
+ (static_cast<void>(fun(cases)), true)...};
+
+ (void)results;
+}
+
+// Execute a function on each passed-in parameter (using a bound function).
+template <class Fun>
+struct ForEachParameterFun {
+ template <class... T>
+ void operator()(const T&... cases) const {
+ (ForEachParameter)(fun, cases...);
+ }
+
+ Fun fun;
+};
+
+// Execute a function on each element of a tuple.
+template <class Fun, class Tup>
+void ForEachTupleElement(const Fun& fun, const Tup& tup) {
+ absl::apply(ForEachParameterFun<Fun>{fun}, tup);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Execute a function for each combination of two elements of a tuple, including
+// combinations of an element with itself.
+template <class Fun, class... T>
+struct ForEveryTwoImpl {
+ template <class Lhs>
+ struct WithBoundLhs {
+ template <class Rhs>
+ void operator()(const Rhs& rhs) const {
+ fun(lhs, rhs);
+ }
+
+ Fun fun;
+ Lhs lhs;
+ };
+
+ template <class Lhs>
+ void operator()(const Lhs& lhs) const {
+ (ForEachTupleElement)(WithBoundLhs<Lhs>{fun, lhs}, args);
+ }
+
+ Fun fun;
+ std::tuple<T...> args;
+};
+
+template <class Fun, class... T>
+void ForEveryTwo(const Fun& fun, std::tuple<T...> args) {
+ (ForEachTupleElement)(ForEveryTwoImpl<Fun, T...>{fun, args}, args);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// Insert all values into an associative container
+template<class Container>
+void InsertEach(Container* cont) {
+}
+
+template<class Container, class H, class... T>
+void InsertEach(Container* cont, H&& head, T&&... tail) {
+ cont->insert(head);
+ (InsertEach)(cont, tail...);
+}
+//
+////////////////////////////////////////////////////////////////////////////////
+// A template with a nested "Invoke" static-member-function that executes a
+// passed-in Callable when `Condition` is true, otherwise it ignores the
+// Callable. This is useful for executing a function object with a condition
+// that corresponds to whether or not the Callable can be safely instantiated.
+// It has some overlapping uses with C++17 `if constexpr`.
+template <bool Condition>
+struct If;
+
+template <>
+struct If</*Condition =*/false> {
+ template <class Fun, class... P>
+ static void Invoke(const Fun& /*fun*/, P&&... /*args*/) {}
+};
+
+template <>
+struct If</*Condition =*/true> {
+ template <class Fun, class... P>
+ static void Invoke(const Fun& fun, P&&... args) {
+ // TODO(calabrese) Use std::invoke equivalent instead of function-call.
+ fun(absl::forward<P>(args)...);
+ }
+};
+
+//
+// ABSL_INTERNAL_STRINGIZE(...)
+//
+// This variadic macro transforms its arguments into a c-string literal after
+// expansion.
+//
+// Example:
+//
+// ABSL_INTERNAL_STRINGIZE(std::array<int, 10>)
+//
+// Results in:
+//
+// "std::array<int, 10>"
+#define ABSL_INTERNAL_STRINGIZE(...) ABSL_INTERNAL_STRINGIZE_IMPL((__VA_ARGS__))
+#define ABSL_INTERNAL_STRINGIZE_IMPL(arg) ABSL_INTERNAL_STRINGIZE_IMPL2 arg
+#define ABSL_INTERNAL_STRINGIZE_IMPL2(...) #__VA_ARGS__
+
+} // namespace types_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TYPES_INTERNAL_CONFORMANCE_TESTING_HELPERS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_test.cc
new file mode 100644
index 00000000000..cf262fa6c22
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/conformance_testing_test.cc
@@ -0,0 +1,1556 @@
+// 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.
+
+#include "absl/types/internal/conformance_testing.h"
+
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "gtest/gtest.h"
+#include "absl/meta/type_traits.h"
+#include "absl/types/internal/conformance_aliases.h"
+#include "absl/types/internal/conformance_profile.h"
+
+namespace {
+
+namespace ti = absl::types_internal;
+
+template <class T>
+using DefaultConstructibleWithNewImpl = decltype(::new (std::nothrow) T);
+
+template <class T>
+using DefaultConstructibleWithNew =
+ absl::type_traits_internal::is_detected<DefaultConstructibleWithNewImpl, T>;
+
+template <class T>
+using MoveConstructibleWithNewImpl =
+ decltype(::new (std::nothrow) T(std::declval<T>()));
+
+template <class T>
+using MoveConstructibleWithNew =
+ absl::type_traits_internal::is_detected<MoveConstructibleWithNewImpl, T>;
+
+template <class T>
+using CopyConstructibleWithNewImpl =
+ decltype(::new (std::nothrow) T(std::declval<const T&>()));
+
+template <class T>
+using CopyConstructibleWithNew =
+ absl::type_traits_internal::is_detected<CopyConstructibleWithNewImpl, T>;
+
+template <class T,
+ class Result =
+ std::integral_constant<bool, noexcept(::new (std::nothrow) T)>>
+using NothrowDefaultConstructibleWithNewImpl =
+ typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowDefaultConstructibleWithNew =
+ absl::type_traits_internal::is_detected<
+ NothrowDefaultConstructibleWithNewImpl, T>;
+
+template <class T,
+ class Result = std::integral_constant<
+ bool, noexcept(::new (std::nothrow) T(std::declval<T>()))>>
+using NothrowMoveConstructibleWithNewImpl =
+ typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowMoveConstructibleWithNew =
+ absl::type_traits_internal::is_detected<NothrowMoveConstructibleWithNewImpl,
+ T>;
+
+template <class T,
+ class Result = std::integral_constant<
+ bool, noexcept(::new (std::nothrow) T(std::declval<const T&>()))>>
+using NothrowCopyConstructibleWithNewImpl =
+ typename std::enable_if<Result::value>::type;
+
+template <class T>
+using NothrowCopyConstructibleWithNew =
+ absl::type_traits_internal::is_detected<NothrowCopyConstructibleWithNewImpl,
+ T>;
+
+// NOTE: ?: is used to verify contextually-convertible to bool and not simply
+// implicit or explicit convertibility.
+#define ABSL_INTERNAL_COMPARISON_OP_EXPR(op) \
+ ((std::declval<const T&>() op std::declval<const T&>()) ? true : true)
+
+#define ABSL_INTERNAL_COMPARISON_OP_TRAIT(name, op) \
+ template <class T> \
+ using name##Impl = decltype(ABSL_INTERNAL_COMPARISON_OP_EXPR(op)); \
+ \
+ template <class T> \
+ using name = absl::type_traits_internal::is_detected<name##Impl, T>; \
+ \
+ template <class T, \
+ class Result = std::integral_constant< \
+ bool, noexcept(ABSL_INTERNAL_COMPARISON_OP_EXPR(op))>> \
+ using Nothrow##name##Impl = typename std::enable_if<Result::value>::type; \
+ \
+ template <class T> \
+ using Nothrow##name = \
+ absl::type_traits_internal::is_detected<Nothrow##name##Impl, T>
+
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(EqualityComparable, ==);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(InequalityComparable, !=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessThanComparable, <);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(LessEqualComparable, <=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterEqualComparable, >=);
+ABSL_INTERNAL_COMPARISON_OP_TRAIT(GreaterThanComparable, >);
+
+#undef ABSL_INTERNAL_COMPARISON_OP_TRAIT
+
+template <class T>
+class ProfileTest : public ::testing::Test {};
+
+TYPED_TEST_SUITE_P(ProfileTest);
+
+TYPED_TEST_P(ProfileTest, HasAppropriateConstructionProperties) {
+ using profile = typename TypeParam::profile;
+ using arch = typename TypeParam::arch;
+ using expected_profile = typename TypeParam::expected_profile;
+
+ using props = ti::PropertiesOfT<profile>;
+ using arch_props = ti::PropertiesOfArchetypeT<arch>;
+ using expected_props = ti::PropertiesOfT<expected_profile>;
+
+ // Make sure all of the properties are as expected.
+ // There are seemingly redundant tests here to make it easier to diagnose
+ // the specifics of the failure if something were to go wrong.
+ EXPECT_TRUE((std::is_same<props, arch_props>::value));
+ EXPECT_TRUE((std::is_same<props, expected_props>::value));
+ EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+ EXPECT_EQ(props::default_constructible_support,
+ expected_props::default_constructible_support);
+
+ EXPECT_EQ(props::move_constructible_support,
+ expected_props::move_constructible_support);
+
+ EXPECT_EQ(props::copy_constructible_support,
+ expected_props::copy_constructible_support);
+
+ EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
+
+ // Avoid additional error message noise when profile and archetype match with
+ // each other but were not what was expected.
+ if (!std::is_same<props, arch_props>::value) {
+ EXPECT_EQ(arch_props::default_constructible_support,
+ expected_props::default_constructible_support);
+
+ EXPECT_EQ(arch_props::move_constructible_support,
+ expected_props::move_constructible_support);
+
+ EXPECT_EQ(arch_props::copy_constructible_support,
+ expected_props::copy_constructible_support);
+
+ EXPECT_EQ(arch_props::destructible_support,
+ expected_props::destructible_support);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Default constructor checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::default_constructible_support,
+ expected_props::default_constructible_support);
+
+ switch (expected_props::default_constructible_support) {
+ case ti::default_constructible::maybe:
+ EXPECT_FALSE(DefaultConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_FALSE(std::is_default_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+ }
+ break;
+ case ti::default_constructible::yes:
+ EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_default_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_default_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+ }
+ break;
+ case ti::default_constructible::nothrow:
+ EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_default_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_default_constructible<arch>::value);
+
+ // Constructor traits also check the destructor.
+ if (std::is_nothrow_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+ }
+ }
+ break;
+ case ti::default_constructible::trivial:
+ EXPECT_TRUE(DefaultConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowDefaultConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_default_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_default_constructible<arch>::value);
+
+ // Constructor triviality traits require trivially destructible types.
+ if (absl::is_trivially_destructible<arch>::value) {
+ EXPECT_TRUE(absl::is_trivially_default_constructible<arch>::value);
+ }
+ }
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Move constructor checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::move_constructible_support,
+ expected_props::move_constructible_support);
+
+ switch (expected_props::move_constructible_support) {
+ case ti::move_constructible::maybe:
+ EXPECT_FALSE(MoveConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_FALSE(std::is_move_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+ }
+ break;
+ case ti::move_constructible::yes:
+ EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowMoveConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_move_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_move_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+ }
+ break;
+ case ti::move_constructible::nothrow:
+ EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_move_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_constructible<arch>::value);
+
+ // Constructor traits also check the destructor.
+ if (std::is_nothrow_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+ }
+ }
+ break;
+ case ti::move_constructible::trivial:
+ EXPECT_TRUE(MoveConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowMoveConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_move_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_move_constructible<arch>::value);
+
+ // Constructor triviality traits require trivially destructible types.
+ if (absl::is_trivially_destructible<arch>::value) {
+ EXPECT_TRUE(absl::is_trivially_move_constructible<arch>::value);
+ }
+ }
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Copy constructor checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::copy_constructible_support,
+ expected_props::copy_constructible_support);
+
+ switch (expected_props::copy_constructible_support) {
+ case ti::copy_constructible::maybe:
+ EXPECT_FALSE(CopyConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_FALSE(std::is_copy_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+ }
+ break;
+ case ti::copy_constructible::yes:
+ EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+ EXPECT_FALSE(NothrowCopyConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_copy_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+ }
+ break;
+ case ti::copy_constructible::nothrow:
+ EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_constructible<arch>::value);
+
+ // Constructor traits also check the destructor.
+ if (std::is_nothrow_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+ }
+ }
+ break;
+ case ti::copy_constructible::trivial:
+ EXPECT_TRUE(CopyConstructibleWithNew<arch>::value);
+ EXPECT_TRUE(NothrowCopyConstructibleWithNew<arch>::value);
+
+ // Standard constructible traits depend on the destructor.
+ if (std::is_destructible<arch>::value) {
+ EXPECT_TRUE(std::is_copy_constructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_copy_constructible<arch>::value);
+
+ // Constructor triviality traits require trivially destructible types.
+ if (absl::is_trivially_destructible<arch>::value) {
+ EXPECT_TRUE(absl::is_trivially_copy_constructible<arch>::value);
+ }
+ }
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Destructible checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::destructible_support, expected_props::destructible_support);
+
+ switch (expected_props::destructible_support) {
+ case ti::destructible::maybe:
+ EXPECT_FALSE(std::is_destructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+ break;
+ case ti::destructible::yes:
+ EXPECT_TRUE(std::is_destructible<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_destructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+ break;
+ case ti::destructible::nothrow:
+ EXPECT_TRUE(std::is_destructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_destructible<arch>::value);
+ break;
+ case ti::destructible::trivial:
+ EXPECT_TRUE(std::is_destructible<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_destructible<arch>::value);
+ EXPECT_TRUE(absl::is_trivially_destructible<arch>::value);
+ break;
+ }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateAssignmentProperties) {
+ using profile = typename TypeParam::profile;
+ using arch = typename TypeParam::arch;
+ using expected_profile = typename TypeParam::expected_profile;
+
+ using props = ti::PropertiesOfT<profile>;
+ using arch_props = ti::PropertiesOfArchetypeT<arch>;
+ using expected_props = ti::PropertiesOfT<expected_profile>;
+
+ // Make sure all of the properties are as expected.
+ // There are seemingly redundant tests here to make it easier to diagnose
+ // the specifics of the failure if something were to go wrong.
+ EXPECT_TRUE((std::is_same<props, arch_props>::value));
+ EXPECT_TRUE((std::is_same<props, expected_props>::value));
+ EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+ EXPECT_EQ(props::move_assignable_support,
+ expected_props::move_assignable_support);
+
+ EXPECT_EQ(props::copy_assignable_support,
+ expected_props::copy_assignable_support);
+
+ // Avoid additional error message noise when profile and archetype match with
+ // each other but were not what was expected.
+ if (!std::is_same<props, arch_props>::value) {
+ EXPECT_EQ(arch_props::move_assignable_support,
+ expected_props::move_assignable_support);
+
+ EXPECT_EQ(arch_props::copy_assignable_support,
+ expected_props::copy_assignable_support);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Move assignment checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::move_assignable_support,
+ expected_props::move_assignable_support);
+
+ switch (expected_props::move_assignable_support) {
+ case ti::move_assignable::maybe:
+ EXPECT_FALSE(std::is_move_assignable<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+ break;
+ case ti::move_assignable::yes:
+ EXPECT_TRUE(std::is_move_assignable<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_move_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+ break;
+ case ti::move_assignable::nothrow:
+ EXPECT_TRUE(std::is_move_assignable<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_move_assignable<arch>::value);
+ break;
+ case ti::move_assignable::trivial:
+ EXPECT_TRUE(std::is_move_assignable<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_move_assignable<arch>::value);
+ EXPECT_TRUE(absl::is_trivially_move_assignable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Copy assignment checks //
+ //////////////////////////////////////////////////////////////////////////////
+ EXPECT_EQ(props::copy_assignable_support,
+ expected_props::copy_assignable_support);
+
+ switch (expected_props::copy_assignable_support) {
+ case ti::copy_assignable::maybe:
+ EXPECT_FALSE(std::is_copy_assignable<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+ break;
+ case ti::copy_assignable::yes:
+ EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+ EXPECT_FALSE(std::is_nothrow_copy_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+ break;
+ case ti::copy_assignable::nothrow:
+ EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
+ EXPECT_FALSE(absl::is_trivially_copy_assignable<arch>::value);
+ break;
+ case ti::copy_assignable::trivial:
+ EXPECT_TRUE(std::is_copy_assignable<arch>::value);
+ EXPECT_TRUE(std::is_nothrow_copy_assignable<arch>::value);
+ EXPECT_TRUE(absl::is_trivially_copy_assignable<arch>::value);
+ break;
+ }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateComparisonProperties) {
+ using profile = typename TypeParam::profile;
+ using arch = typename TypeParam::arch;
+ using expected_profile = typename TypeParam::expected_profile;
+
+ using props = ti::PropertiesOfT<profile>;
+ using arch_props = ti::PropertiesOfArchetypeT<arch>;
+ using expected_props = ti::PropertiesOfT<expected_profile>;
+
+ // Make sure all of the properties are as expected.
+ // There are seemingly redundant tests here to make it easier to diagnose
+ // the specifics of the failure if something were to go wrong.
+ EXPECT_TRUE((std::is_same<props, arch_props>::value));
+ EXPECT_TRUE((std::is_same<props, expected_props>::value));
+ EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+ EXPECT_EQ(props::equality_comparable_support,
+ expected_props::equality_comparable_support);
+
+ EXPECT_EQ(props::inequality_comparable_support,
+ expected_props::inequality_comparable_support);
+
+ EXPECT_EQ(props::less_than_comparable_support,
+ expected_props::less_than_comparable_support);
+
+ EXPECT_EQ(props::less_equal_comparable_support,
+ expected_props::less_equal_comparable_support);
+
+ EXPECT_EQ(props::greater_equal_comparable_support,
+ expected_props::greater_equal_comparable_support);
+
+ EXPECT_EQ(props::greater_than_comparable_support,
+ expected_props::greater_than_comparable_support);
+
+ // Avoid additional error message noise when profile and archetype match with
+ // each other but were not what was expected.
+ if (!std::is_same<props, arch_props>::value) {
+ EXPECT_EQ(arch_props::equality_comparable_support,
+ expected_props::equality_comparable_support);
+
+ EXPECT_EQ(arch_props::inequality_comparable_support,
+ expected_props::inequality_comparable_support);
+
+ EXPECT_EQ(arch_props::less_than_comparable_support,
+ expected_props::less_than_comparable_support);
+
+ EXPECT_EQ(arch_props::less_equal_comparable_support,
+ expected_props::less_equal_comparable_support);
+
+ EXPECT_EQ(arch_props::greater_equal_comparable_support,
+ expected_props::greater_equal_comparable_support);
+
+ EXPECT_EQ(arch_props::greater_than_comparable_support,
+ expected_props::greater_than_comparable_support);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Equality comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::equality_comparable_support) {
+ case ti::equality_comparable::maybe:
+ EXPECT_FALSE(EqualityComparable<arch>::value);
+ EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
+ break;
+ case ti::equality_comparable::yes:
+ EXPECT_TRUE(EqualityComparable<arch>::value);
+ EXPECT_FALSE(NothrowEqualityComparable<arch>::value);
+ break;
+ case ti::equality_comparable::nothrow:
+ EXPECT_TRUE(EqualityComparable<arch>::value);
+ EXPECT_TRUE(NothrowEqualityComparable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Inequality comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::inequality_comparable_support) {
+ case ti::inequality_comparable::maybe:
+ EXPECT_FALSE(InequalityComparable<arch>::value);
+ EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
+ break;
+ case ti::inequality_comparable::yes:
+ EXPECT_TRUE(InequalityComparable<arch>::value);
+ EXPECT_FALSE(NothrowInequalityComparable<arch>::value);
+ break;
+ case ti::inequality_comparable::nothrow:
+ EXPECT_TRUE(InequalityComparable<arch>::value);
+ EXPECT_TRUE(NothrowInequalityComparable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Less than comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::less_than_comparable_support) {
+ case ti::less_than_comparable::maybe:
+ EXPECT_FALSE(LessThanComparable<arch>::value);
+ EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
+ break;
+ case ti::less_than_comparable::yes:
+ EXPECT_TRUE(LessThanComparable<arch>::value);
+ EXPECT_FALSE(NothrowLessThanComparable<arch>::value);
+ break;
+ case ti::less_than_comparable::nothrow:
+ EXPECT_TRUE(LessThanComparable<arch>::value);
+ EXPECT_TRUE(NothrowLessThanComparable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Less equal comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::less_equal_comparable_support) {
+ case ti::less_equal_comparable::maybe:
+ EXPECT_FALSE(LessEqualComparable<arch>::value);
+ EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
+ break;
+ case ti::less_equal_comparable::yes:
+ EXPECT_TRUE(LessEqualComparable<arch>::value);
+ EXPECT_FALSE(NothrowLessEqualComparable<arch>::value);
+ break;
+ case ti::less_equal_comparable::nothrow:
+ EXPECT_TRUE(LessEqualComparable<arch>::value);
+ EXPECT_TRUE(NothrowLessEqualComparable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Greater equal comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::greater_equal_comparable_support) {
+ case ti::greater_equal_comparable::maybe:
+ EXPECT_FALSE(GreaterEqualComparable<arch>::value);
+ EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
+ break;
+ case ti::greater_equal_comparable::yes:
+ EXPECT_TRUE(GreaterEqualComparable<arch>::value);
+ EXPECT_FALSE(NothrowGreaterEqualComparable<arch>::value);
+ break;
+ case ti::greater_equal_comparable::nothrow:
+ EXPECT_TRUE(GreaterEqualComparable<arch>::value);
+ EXPECT_TRUE(NothrowGreaterEqualComparable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Greater than comparable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::greater_than_comparable_support) {
+ case ti::greater_than_comparable::maybe:
+ EXPECT_FALSE(GreaterThanComparable<arch>::value);
+ EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
+ break;
+ case ti::greater_than_comparable::yes:
+ EXPECT_TRUE(GreaterThanComparable<arch>::value);
+ EXPECT_FALSE(NothrowGreaterThanComparable<arch>::value);
+ break;
+ case ti::greater_than_comparable::nothrow:
+ EXPECT_TRUE(GreaterThanComparable<arch>::value);
+ EXPECT_TRUE(NothrowGreaterThanComparable<arch>::value);
+ break;
+ }
+}
+
+TYPED_TEST_P(ProfileTest, HasAppropriateAuxilliaryProperties) {
+ using profile = typename TypeParam::profile;
+ using arch = typename TypeParam::arch;
+ using expected_profile = typename TypeParam::expected_profile;
+
+ using props = ti::PropertiesOfT<profile>;
+ using arch_props = ti::PropertiesOfArchetypeT<arch>;
+ using expected_props = ti::PropertiesOfT<expected_profile>;
+
+ // Make sure all of the properties are as expected.
+ // There are seemingly redundant tests here to make it easier to diagnose
+ // the specifics of the failure if something were to go wrong.
+ EXPECT_TRUE((std::is_same<props, arch_props>::value));
+ EXPECT_TRUE((std::is_same<props, expected_props>::value));
+ EXPECT_TRUE((std::is_same<arch_props, expected_props>::value));
+
+ EXPECT_EQ(props::swappable_support, expected_props::swappable_support);
+
+ EXPECT_EQ(props::hashable_support, expected_props::hashable_support);
+
+ // Avoid additional error message noise when profile and archetype match with
+ // each other but were not what was expected.
+ if (!std::is_same<props, arch_props>::value) {
+ EXPECT_EQ(arch_props::swappable_support, expected_props::swappable_support);
+
+ EXPECT_EQ(arch_props::hashable_support, expected_props::hashable_support);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Swappable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::swappable_support) {
+ case ti::swappable::maybe:
+ EXPECT_FALSE(absl::type_traits_internal::IsSwappable<arch>::value);
+ EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+ break;
+ case ti::swappable::yes:
+ EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
+ EXPECT_FALSE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+ break;
+ case ti::swappable::nothrow:
+ EXPECT_TRUE(absl::type_traits_internal::IsSwappable<arch>::value);
+ EXPECT_TRUE(absl::type_traits_internal::IsNothrowSwappable<arch>::value);
+ break;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+ // Hashable checks //
+ //////////////////////////////////////////////////////////////////////////////
+ switch (expected_props::hashable_support) {
+ case ti::hashable::maybe:
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+ EXPECT_FALSE(absl::type_traits_internal::IsHashable<arch>::value);
+#endif // ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+ break;
+ case ti::hashable::yes:
+ EXPECT_TRUE(absl::type_traits_internal::IsHashable<arch>::value);
+ break;
+ }
+}
+
+REGISTER_TYPED_TEST_SUITE_P(ProfileTest, HasAppropriateConstructionProperties,
+ HasAppropriateAssignmentProperties,
+ HasAppropriateComparisonProperties,
+ HasAppropriateAuxilliaryProperties);
+
+template <class Profile, class Arch, class ExpectedProfile>
+struct ProfileAndExpectation {
+ using profile = Profile;
+ using arch = Arch;
+ using expected_profile = ExpectedProfile;
+};
+
+using CoreProfilesToTest = ::testing::Types<
+ // The terminating case of combine (all properties are "maybe").
+ ProfileAndExpectation<ti::CombineProfiles<>,
+ ti::Archetype<ti::CombineProfiles<>>,
+ ti::ConformanceProfile<>>,
+
+ // Core default constructor profiles
+ ProfileAndExpectation<
+ ti::HasDefaultConstructorProfile, ti::HasDefaultConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowDefaultConstructorProfile,
+ ti::HasNothrowDefaultConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialDefaultConstructorProfile,
+ ti::HasTrivialDefaultConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::trivial>>,
+
+ // Core move constructor profiles
+ ProfileAndExpectation<
+ ti::HasMoveConstructorProfile, ti::HasMoveConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowMoveConstructorProfile,
+ ti::HasNothrowMoveConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialMoveConstructorProfile,
+ ti::HasTrivialMoveConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::trivial>>,
+
+ // Core copy constructor profiles
+ ProfileAndExpectation<
+ ti::HasCopyConstructorProfile, ti::HasCopyConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::maybe,
+ ti::copy_constructible::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowCopyConstructorProfile,
+ ti::HasNothrowCopyConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::maybe,
+ ti::copy_constructible::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialCopyConstructorProfile,
+ ti::HasTrivialCopyConstructorArchetype,
+ ti::ConformanceProfile<ti::default_constructible::maybe,
+ ti::move_constructible::maybe,
+ ti::copy_constructible::trivial>>,
+
+ // Core move assignment profiles
+ ProfileAndExpectation<
+ ti::HasMoveAssignProfile, ti::HasMoveAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowMoveAssignProfile, ti::HasNothrowMoveAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialMoveAssignProfile, ti::HasTrivialMoveAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::trivial>>,
+
+ // Core copy assignment profiles
+ ProfileAndExpectation<
+ ti::HasCopyAssignProfile, ti::HasCopyAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowCopyAssignProfile, ti::HasNothrowCopyAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialCopyAssignProfile, ti::HasTrivialCopyAssignArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::trivial>>,
+
+ // Core destructor profiles
+ ProfileAndExpectation<
+ ti::HasDestructorProfile, ti::HasDestructorArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowDestructorProfile, ti::HasNothrowDestructorArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+ ProfileAndExpectation<
+ ti::HasTrivialDestructorProfile, ti::HasTrivialDestructorArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::trivial>>,
+
+ // Core equality comparable profiles
+ ProfileAndExpectation<
+ ti::HasEqualityProfile, ti::HasEqualityArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowEqualityProfile, ti::HasNothrowEqualityArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::nothrow>>,
+
+ // Core inequality comparable profiles
+ ProfileAndExpectation<
+ ti::HasInequalityProfile, ti::HasInequalityArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowInequalityProfile, ti::HasNothrowInequalityArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe,
+ ti::inequality_comparable::nothrow>>,
+
+ // Core less than comparable profiles
+ ProfileAndExpectation<
+ ti::HasLessThanProfile, ti::HasLessThanArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowLessThanProfile, ti::HasNothrowLessThanArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::nothrow>>,
+
+ // Core less equal comparable profiles
+ ProfileAndExpectation<
+ ti::HasLessEqualProfile, ti::HasLessEqualArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowLessEqualProfile, ti::HasNothrowLessEqualArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe,
+ ti::less_equal_comparable::nothrow>>,
+
+ // Core greater equal comparable profiles
+ ProfileAndExpectation<
+ ti::HasGreaterEqualProfile, ti::HasGreaterEqualArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowGreaterEqualProfile, ti::HasNothrowGreaterEqualArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::nothrow>>,
+
+ // Core greater than comparable profiles
+ ProfileAndExpectation<
+ ti::HasGreaterThanProfile, ti::HasGreaterThanArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowGreaterThanProfile, ti::HasNothrowGreaterThanArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::nothrow>>,
+
+ // Core swappable profiles
+ ProfileAndExpectation<
+ ti::HasSwapProfile, ti::HasSwapArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::yes>>,
+ ProfileAndExpectation<
+ ti::HasNothrowSwapProfile, ti::HasNothrowSwapArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+ // Core hashable profiles
+ ProfileAndExpectation<
+ ti::HasStdHashSpecializationProfile,
+ ti::HasStdHashSpecializationArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::maybe,
+ ti::hashable::yes>>>;
+
+using CommonProfilesToTest = ::testing::Types<
+ // NothrowMoveConstructible
+ ProfileAndExpectation<
+ ti::NothrowMoveConstructibleProfile,
+ ti::NothrowMoveConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+ // CopyConstructible
+ ProfileAndExpectation<
+ ti::CopyConstructibleProfile, ti::CopyConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+ // NothrowMovable
+ ProfileAndExpectation<
+ ti::NothrowMovableProfile, ti::NothrowMovableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+ ti::copy_assignable::maybe, ti::destructible::nothrow,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+ // Value
+ ProfileAndExpectation<
+ ti::ValueProfile, ti::ValueArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::nothrow,
+ ti::copy_assignable::yes, ti::destructible::nothrow,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Common but also DefaultConstructible //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // DefaultConstructibleNothrowMoveConstructible
+ ProfileAndExpectation<
+ ti::DefaultConstructibleNothrowMoveConstructibleProfile,
+ ti::DefaultConstructibleNothrowMoveConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::yes, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+ // DefaultConstructibleCopyConstructible
+ ProfileAndExpectation<
+ ti::DefaultConstructibleCopyConstructibleProfile,
+ ti::DefaultConstructibleCopyConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::yes, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow>>,
+
+ // DefaultConstructibleNothrowMovable
+ ProfileAndExpectation<
+ ti::DefaultConstructibleNothrowMovableProfile,
+ ti::DefaultConstructibleNothrowMovableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::yes, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+ ti::copy_assignable::maybe, ti::destructible::nothrow,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+ // DefaultConstructibleValue
+ ProfileAndExpectation<
+ ti::DefaultConstructibleValueProfile,
+ ti::DefaultConstructibleValueArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::yes, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::nothrow,
+ ti::copy_assignable::yes, ti::destructible::nothrow,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>>;
+
+using ComparableHelpersProfilesToTest = ::testing::Types<
+ // Equatable
+ ProfileAndExpectation<
+ ti::EquatableProfile, ti::EquatableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes>>,
+
+ // Comparable
+ ProfileAndExpectation<
+ ti::ComparableProfile, ti::ComparableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes,
+ ti::greater_than_comparable::yes>>,
+
+ // NothrowEquatable
+ ProfileAndExpectation<
+ ti::NothrowEquatableProfile, ti::NothrowEquatableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::nothrow,
+ ti::inequality_comparable::nothrow>>,
+
+ // NothrowComparable
+ ProfileAndExpectation<
+ ti::NothrowComparableProfile, ti::NothrowComparableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::maybe,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::maybe,
+ ti::equality_comparable::nothrow,
+ ti::inequality_comparable::nothrow,
+ ti::less_than_comparable::nothrow,
+ ti::less_equal_comparable::nothrow,
+ ti::greater_equal_comparable::nothrow,
+ ti::greater_than_comparable::nothrow>>>;
+
+using CommonComparableProfilesToTest = ::testing::Types<
+ // ComparableNothrowMoveConstructible
+ ProfileAndExpectation<
+ ti::ComparableNothrowMoveConstructibleProfile,
+ ti::ComparableNothrowMoveConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes,
+ ti::greater_than_comparable::yes>>,
+
+ // ComparableCopyConstructible
+ ProfileAndExpectation<
+ ti::ComparableCopyConstructibleProfile,
+ ti::ComparableCopyConstructibleArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::maybe,
+ ti::copy_assignable::maybe, ti::destructible::nothrow,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes,
+ ti::greater_than_comparable::yes>>,
+
+ // ComparableNothrowMovable
+ ProfileAndExpectation<
+ ti::ComparableNothrowMovableProfile,
+ ti::ComparableNothrowMovableArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::maybe, ti::move_assignable::nothrow,
+ ti::copy_assignable::maybe, ti::destructible::nothrow,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+ ti::swappable::nothrow>>,
+
+ // ComparableValue
+ ProfileAndExpectation<
+ ti::ComparableValueProfile, ti::ComparableValueArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::maybe, ti::move_constructible::nothrow,
+ ti::copy_constructible::yes, ti::move_assignable::nothrow,
+ ti::copy_assignable::yes, ti::destructible::nothrow,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+ ti::swappable::nothrow>>>;
+
+using TrivialProfilesToTest = ::testing::Types<
+ ProfileAndExpectation<
+ ti::TrivialSpecialMemberFunctionsProfile,
+ ti::TrivialSpecialMemberFunctionsArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::trivial, ti::move_constructible::trivial,
+ ti::copy_constructible::trivial, ti::move_assignable::trivial,
+ ti::copy_assignable::trivial, ti::destructible::trivial,
+ ti::equality_comparable::maybe, ti::inequality_comparable::maybe,
+ ti::less_than_comparable::maybe, ti::less_equal_comparable::maybe,
+ ti::greater_equal_comparable::maybe,
+ ti::greater_than_comparable::maybe, ti::swappable::nothrow>>,
+
+ ProfileAndExpectation<
+ ti::TriviallyCompleteProfile, ti::TriviallyCompleteArchetype,
+ ti::ConformanceProfile<
+ ti::default_constructible::trivial, ti::move_constructible::trivial,
+ ti::copy_constructible::trivial, ti::move_assignable::trivial,
+ ti::copy_assignable::trivial, ti::destructible::trivial,
+ ti::equality_comparable::yes, ti::inequality_comparable::yes,
+ ti::less_than_comparable::yes, ti::less_equal_comparable::yes,
+ ti::greater_equal_comparable::yes, ti::greater_than_comparable::yes,
+ ti::swappable::nothrow, ti::hashable::yes>>>;
+
+INSTANTIATE_TYPED_TEST_SUITE_P(Core, ProfileTest, CoreProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(Common, ProfileTest, CommonProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(ComparableHelpers, ProfileTest,
+ ComparableHelpersProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(CommonComparable, ProfileTest,
+ CommonComparableProfilesToTest);
+INSTANTIATE_TYPED_TEST_SUITE_P(Trivial, ProfileTest, TrivialProfilesToTest);
+
+TEST(ConformanceTestingTest, Basic) {
+ using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
+ ti::NothrowComparableProfile>;
+
+ using lim = std::numeric_limits<float>;
+
+ ABSL_INTERNAL_ASSERT_CONFORMANCE_OF(float)
+ .INITIALIZER(-lim::infinity())
+ .INITIALIZER(lim::lowest())
+ .INITIALIZER(-1.f)
+ .INITIALIZER(-lim::min())
+ .EQUIVALENCE_CLASS(INITIALIZER(-0.f), INITIALIZER(0.f))
+ .INITIALIZER(lim::min())
+ .INITIALIZER(1.f)
+ .INITIALIZER(lim::max())
+ .INITIALIZER(lim::infinity())
+ .WITH_STRICT_PROFILE(absl::types_internal::RegularityDomain, profile);
+}
+
+struct BadMoveConstruct {
+ BadMoveConstruct() = default;
+ BadMoveConstruct(BadMoveConstruct&& other) noexcept
+ : value(other.value + 1) {}
+ BadMoveConstruct& operator=(BadMoveConstruct&& other) noexcept = default;
+ int value = 0;
+
+ friend bool operator==(BadMoveConstruct const& lhs,
+ BadMoveConstruct const& rhs) {
+ return lhs.value == rhs.value;
+ }
+ friend bool operator!=(BadMoveConstruct const& lhs,
+ BadMoveConstruct const& rhs) {
+ return lhs.value != rhs.value;
+ }
+};
+
+struct BadMoveAssign {
+ BadMoveAssign() = default;
+ BadMoveAssign(BadMoveAssign&& other) noexcept = default;
+ BadMoveAssign& operator=(BadMoveAssign&& other) noexcept {
+ int new_value = other.value + 1;
+ value = new_value;
+ return *this;
+ }
+ int value = 0;
+
+ friend bool operator==(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
+ return lhs.value == rhs.value;
+ }
+ friend bool operator!=(BadMoveAssign const& lhs, BadMoveAssign const& rhs) {
+ return lhs.value != rhs.value;
+ }
+};
+
+enum class WhichCompIsBad { eq, ne, lt, le, ge, gt };
+
+template <WhichCompIsBad Which>
+struct BadCompare {
+ int value;
+
+ friend bool operator==(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::eq ? lhs.value != rhs.value
+ : lhs.value == rhs.value;
+ }
+
+ friend bool operator!=(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::ne ? lhs.value == rhs.value
+ : lhs.value != rhs.value;
+ }
+
+ friend bool operator<(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::lt ? lhs.value >= rhs.value
+ : lhs.value < rhs.value;
+ }
+
+ friend bool operator<=(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::le ? lhs.value > rhs.value
+ : lhs.value <= rhs.value;
+ }
+
+ friend bool operator>=(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::ge ? lhs.value < rhs.value
+ : lhs.value >= rhs.value;
+ }
+
+ friend bool operator>(BadCompare const& lhs, BadCompare const& rhs) {
+ return Which == WhichCompIsBad::gt ? lhs.value <= rhs.value
+ : lhs.value > rhs.value;
+ }
+};
+
+TEST(ConformanceTestingDeathTest, Failures) {
+ {
+ using profile = ti::CombineProfiles<ti::TriviallyCompleteProfile,
+ ti::NothrowComparableProfile>;
+
+ // Note: The initializers are intentionally in the wrong order.
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(float)
+ .INITIALIZER(1.f)
+ .INITIALIZER(0.f)
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using profile =
+ ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveConstruct)
+ .DUE_TO("Move construction")
+ .INITIALIZER(BadMoveConstruct())
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using profile =
+ ti::CombineProfiles<ti::NothrowMovableProfile, ti::EquatableProfile>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadMoveAssign)
+ .DUE_TO("Move assignment")
+ .INITIALIZER(BadMoveAssign())
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+TEST(ConformanceTestingDeathTest, CompFailures) {
+ using profile = ti::ComparableProfile;
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::eq>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::ne>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::lt>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::le>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::ge>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+
+ {
+ using BadComp = BadCompare<WhichCompIsBad::gt>;
+
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadComp)
+ .DUE_TO("Comparison")
+ .INITIALIZER(BadComp{0})
+ .INITIALIZER(BadComp{1})
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+struct BadSelfMove {
+ BadSelfMove() = default;
+ BadSelfMove(BadSelfMove&&) = default;
+ BadSelfMove& operator=(BadSelfMove&& other) noexcept {
+ if (this == &other) {
+ broken_state = true;
+ }
+ return *this;
+ }
+
+ friend bool operator==(const BadSelfMove& lhs, const BadSelfMove& rhs) {
+ return !(lhs.broken_state || rhs.broken_state);
+ }
+
+ friend bool operator!=(const BadSelfMove& lhs, const BadSelfMove& rhs) {
+ return lhs.broken_state || rhs.broken_state;
+ }
+
+ bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfMoveFailure) {
+ using profile = ti::EquatableNothrowMovableProfile;
+
+ {
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfMove)
+ .DUE_TO("Move assignment")
+ .INITIALIZER(BadSelfMove())
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+struct BadSelfCopy {
+ BadSelfCopy() = default;
+ BadSelfCopy(BadSelfCopy&&) = default;
+ BadSelfCopy(const BadSelfCopy&) = default;
+ BadSelfCopy& operator=(BadSelfCopy&&) = default;
+ BadSelfCopy& operator=(BadSelfCopy const& other) {
+ if (this == &other) {
+ broken_state = true;
+ }
+ return *this;
+ }
+
+ friend bool operator==(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
+ return !(lhs.broken_state || rhs.broken_state);
+ }
+
+ friend bool operator!=(const BadSelfCopy& lhs, const BadSelfCopy& rhs) {
+ return lhs.broken_state || rhs.broken_state;
+ }
+
+ bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfCopyFailure) {
+ using profile = ti::EquatableValueProfile;
+
+ {
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfCopy)
+ .DUE_TO("Copy assignment")
+ .INITIALIZER(BadSelfCopy())
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+struct BadSelfSwap {
+ friend void swap(BadSelfSwap& lhs, BadSelfSwap& rhs) noexcept {
+ if (&lhs == &rhs) lhs.broken_state = true;
+ }
+
+ friend bool operator==(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
+ return !(lhs.broken_state || rhs.broken_state);
+ }
+
+ friend bool operator!=(const BadSelfSwap& lhs, const BadSelfSwap& rhs) {
+ return lhs.broken_state || rhs.broken_state;
+ }
+
+ bool broken_state = false;
+};
+
+TEST(ConformanceTestingDeathTest, SelfSwapFailure) {
+ using profile = ti::EquatableNothrowMovableProfile;
+
+ {
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadSelfSwap)
+ .DUE_TO("Swap")
+ .INITIALIZER(BadSelfSwap())
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+struct BadDefaultInitializedMoveAssign {
+ BadDefaultInitializedMoveAssign() : default_initialized(true) {}
+ explicit BadDefaultInitializedMoveAssign(int v) : value(v) {}
+ BadDefaultInitializedMoveAssign(
+ BadDefaultInitializedMoveAssign&& other) noexcept
+ : value(other.value) {}
+ BadDefaultInitializedMoveAssign& operator=(
+ BadDefaultInitializedMoveAssign&& other) noexcept {
+ value = other.value;
+ if (default_initialized) ++value; // Bad move if lhs is default initialized
+ return *this;
+ }
+
+ friend bool operator==(const BadDefaultInitializedMoveAssign& lhs,
+ const BadDefaultInitializedMoveAssign& rhs) {
+ return lhs.value == rhs.value;
+ }
+
+ friend bool operator!=(const BadDefaultInitializedMoveAssign& lhs,
+ const BadDefaultInitializedMoveAssign& rhs) {
+ return lhs.value != rhs.value;
+ }
+
+ bool default_initialized = false;
+ int value = 0;
+};
+
+TEST(ConformanceTestingDeathTest, DefaultInitializedMoveAssignFailure) {
+ using profile =
+ ti::CombineProfiles<ti::DefaultConstructibleNothrowMovableProfile,
+ ti::EquatableProfile>;
+
+ {
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedMoveAssign)
+ .DUE_TO("move assignment")
+ .INITIALIZER(BadDefaultInitializedMoveAssign(0))
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+struct BadDefaultInitializedCopyAssign {
+ BadDefaultInitializedCopyAssign() : default_initialized(true) {}
+ explicit BadDefaultInitializedCopyAssign(int v) : value(v) {}
+ BadDefaultInitializedCopyAssign(
+ BadDefaultInitializedCopyAssign&& other) noexcept
+ : value(other.value) {}
+ BadDefaultInitializedCopyAssign(const BadDefaultInitializedCopyAssign& other)
+ : value(other.value) {}
+
+ BadDefaultInitializedCopyAssign& operator=(
+ BadDefaultInitializedCopyAssign&& other) noexcept {
+ value = other.value;
+ return *this;
+ }
+
+ BadDefaultInitializedCopyAssign& operator=(
+ const BadDefaultInitializedCopyAssign& other) {
+ value = other.value;
+ if (default_initialized) ++value; // Bad move if lhs is default initialized
+ return *this;
+ }
+
+ friend bool operator==(const BadDefaultInitializedCopyAssign& lhs,
+ const BadDefaultInitializedCopyAssign& rhs) {
+ return lhs.value == rhs.value;
+ }
+
+ friend bool operator!=(const BadDefaultInitializedCopyAssign& lhs,
+ const BadDefaultInitializedCopyAssign& rhs) {
+ return lhs.value != rhs.value;
+ }
+
+ bool default_initialized = false;
+ int value = 0;
+};
+
+TEST(ConformanceTestingDeathTest, DefaultInitializedAssignFailure) {
+ using profile = ti::CombineProfiles<ti::DefaultConstructibleValueProfile,
+ ti::EquatableProfile>;
+
+ {
+ ABSL_INTERNAL_ASSERT_NONCONFORMANCE_OF(BadDefaultInitializedCopyAssign)
+ .DUE_TO("copy assignment")
+ .INITIALIZER(BadDefaultInitializedCopyAssign(0))
+ .WITH_LOOSE_PROFILE(profile);
+ }
+}
+
+} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/optional.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/optional.h
new file mode 100644
index 00000000000..92932b6001b
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/optional.h
@@ -0,0 +1,396 @@
+// 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_TYPES_INTERNAL_OPTIONAL_H_
+#define ABSL_TYPES_INTERNAL_OPTIONAL_H_
+
+#include <functional>
+#include <new>
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/internal/inline_variable.h"
+#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
+#include "absl/utility/utility.h"
+
+// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+//
+// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
+// __cpp_inheriting_constructors is a predefined macro and a recommended way to
+// check for this language feature, but GCC doesn't support it until 5.0 and
+// Clang doesn't support it until 3.6.
+// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
+// constructor. For example, the following code won't work on MSVC 2015 Update3:
+// struct Base {
+// int t;
+// template <typename T>
+// constexpr Base(T t_) : t(t_) {}
+// };
+// struct Foo : Base {
+// using Base::Base;
+// }
+// constexpr Foo foo(0); // doesn't work on MSVC 2015
+#if defined(__clang__)
+#if __has_feature(cxx_inheriting_constructors)
+#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
+#endif
+#elif (defined(__GNUC__) && \
+ (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
+ (__cpp_inheriting_constructors >= 200802) || \
+ (defined(_MSC_VER) && _MSC_VER >= 1910)
+#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
+#endif
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// Forward declaration
+template <typename T>
+class optional;
+
+namespace optional_internal {
+
+// This tag type is used as a constructor parameter type for `nullopt_t`.
+struct init_t {
+ explicit init_t() = default;
+};
+
+struct empty_struct {};
+
+// This class stores the data in optional<T>.
+// It is specialized based on whether T is trivially destructible.
+// This is the specialization for non trivially destructible type.
+template <typename T, bool unused = std::is_trivially_destructible<T>::value>
+class optional_data_dtor_base {
+ struct dummy_type {
+ static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
+ // Use an array to avoid GCC 6 placement-new warning.
+ empty_struct data[sizeof(T) / sizeof(empty_struct)];
+ };
+
+ protected:
+ // Whether there is data or not.
+ bool engaged_;
+ // Data storage
+ union {
+ T data_;
+ dummy_type dummy_;
+ };
+
+ void destruct() noexcept {
+ if (engaged_) {
+ data_.~T();
+ engaged_ = false;
+ }
+ }
+
+ // dummy_ must be initialized for constexpr constructor.
+ constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
+
+ template <typename... Args>
+ constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
+ : engaged_(true), data_(absl::forward<Args>(args)...) {}
+
+ ~optional_data_dtor_base() { destruct(); }
+};
+
+// Specialization for trivially destructible type.
+template <typename T>
+class optional_data_dtor_base<T, true> {
+ struct dummy_type {
+ static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
+ // Use array to avoid GCC 6 placement-new warning.
+ empty_struct data[sizeof(T) / sizeof(empty_struct)];
+ };
+
+ protected:
+ // Whether there is data or not.
+ bool engaged_;
+ // Data storage
+ union {
+ T data_;
+ dummy_type dummy_;
+ };
+ void destruct() noexcept { engaged_ = false; }
+
+ // dummy_ must be initialized for constexpr constructor.
+ constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
+
+ template <typename... Args>
+ constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
+ : engaged_(true), data_(absl::forward<Args>(args)...) {}
+};
+
+template <typename T>
+class optional_data_base : public optional_data_dtor_base<T> {
+ protected:
+ using base = optional_data_dtor_base<T>;
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using base::base;
+#else
+ optional_data_base() = default;
+
+ template <typename... Args>
+ constexpr explicit optional_data_base(in_place_t t, Args&&... args)
+ : base(t, absl::forward<Args>(args)...) {}
+#endif
+
+ template <typename... Args>
+ void construct(Args&&... args) {
+ // Use dummy_'s address to work around casting cv-qualified T* to void*.
+ ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
+ this->engaged_ = true;
+ }
+
+ template <typename U>
+ void assign(U&& u) {
+ if (this->engaged_) {
+ this->data_ = std::forward<U>(u);
+ } else {
+ construct(std::forward<U>(u));
+ }
+ }
+};
+
+// TODO(absl-team): Add another class using
+// std::is_trivially_move_constructible trait when available to match
+// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
+// have trivial move but nontrivial copy.
+// Also, we should be checking is_trivially_copyable here, which is not
+// supported now, so we use is_trivially_* traits instead.
+template <typename T,
+ bool unused = absl::is_trivially_copy_constructible<T>::value&&
+ absl::is_trivially_copy_assignable<typename std::remove_cv<
+ T>::type>::value&& std::is_trivially_destructible<T>::value>
+class optional_data;
+
+// Trivially copyable types
+template <typename T>
+class optional_data<T, true> : public optional_data_base<T> {
+ protected:
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using optional_data_base<T>::optional_data_base;
+#else
+ optional_data() = default;
+
+ template <typename... Args>
+ constexpr explicit optional_data(in_place_t t, Args&&... args)
+ : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
+#endif
+};
+
+template <typename T>
+class optional_data<T, false> : public optional_data_base<T> {
+ protected:
+#ifdef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+ using optional_data_base<T>::optional_data_base;
+#else
+ template <typename... Args>
+ constexpr explicit optional_data(in_place_t t, Args&&... args)
+ : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
+#endif
+
+ optional_data() = default;
+
+ optional_data(const optional_data& rhs) : optional_data_base<T>() {
+ if (rhs.engaged_) {
+ this->construct(rhs.data_);
+ }
+ }
+
+ optional_data(optional_data&& rhs) noexcept(
+ absl::default_allocator_is_nothrow::value ||
+ std::is_nothrow_move_constructible<T>::value)
+ : optional_data_base<T>() {
+ if (rhs.engaged_) {
+ this->construct(std::move(rhs.data_));
+ }
+ }
+
+ optional_data& operator=(const optional_data& rhs) {
+ if (rhs.engaged_) {
+ this->assign(rhs.data_);
+ } else {
+ this->destruct();
+ }
+ return *this;
+ }
+
+ optional_data& operator=(optional_data&& rhs) noexcept(
+ std::is_nothrow_move_assignable<T>::value&&
+ std::is_nothrow_move_constructible<T>::value) {
+ if (rhs.engaged_) {
+ this->assign(std::move(rhs.data_));
+ } else {
+ this->destruct();
+ }
+ return *this;
+ }
+};
+
+// Ordered by level of restriction, from low to high.
+// Copyable implies movable.
+enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
+
+// Base class for enabling/disabling copy/move constructor.
+template <copy_traits>
+class optional_ctor_base;
+
+template <>
+class optional_ctor_base<copy_traits::copyable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = default;
+ optional_ctor_base(optional_ctor_base&&) = default;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+template <>
+class optional_ctor_base<copy_traits::movable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = delete;
+ optional_ctor_base(optional_ctor_base&&) = default;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+template <>
+class optional_ctor_base<copy_traits::non_movable> {
+ public:
+ constexpr optional_ctor_base() = default;
+ optional_ctor_base(const optional_ctor_base&) = delete;
+ optional_ctor_base(optional_ctor_base&&) = delete;
+ optional_ctor_base& operator=(const optional_ctor_base&) = default;
+ optional_ctor_base& operator=(optional_ctor_base&&) = default;
+};
+
+// Base class for enabling/disabling copy/move assignment.
+template <copy_traits>
+class optional_assign_base;
+
+template <>
+class optional_assign_base<copy_traits::copyable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = default;
+ optional_assign_base& operator=(optional_assign_base&&) = default;
+};
+
+template <>
+class optional_assign_base<copy_traits::movable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = delete;
+ optional_assign_base& operator=(optional_assign_base&&) = default;
+};
+
+template <>
+class optional_assign_base<copy_traits::non_movable> {
+ public:
+ constexpr optional_assign_base() = default;
+ optional_assign_base(const optional_assign_base&) = default;
+ optional_assign_base(optional_assign_base&&) = default;
+ optional_assign_base& operator=(const optional_assign_base&) = delete;
+ optional_assign_base& operator=(optional_assign_base&&) = delete;
+};
+
+template <typename T>
+struct ctor_copy_traits {
+ static constexpr copy_traits traits =
+ std::is_copy_constructible<T>::value
+ ? copy_traits::copyable
+ : std::is_move_constructible<T>::value ? copy_traits::movable
+ : copy_traits::non_movable;
+};
+
+template <typename T>
+struct assign_copy_traits {
+ static constexpr copy_traits traits =
+ absl::is_copy_assignable<T>::value && std::is_copy_constructible<T>::value
+ ? copy_traits::copyable
+ : absl::is_move_assignable<T>::value &&
+ std::is_move_constructible<T>::value
+ ? copy_traits::movable
+ : copy_traits::non_movable;
+};
+
+// Whether T is constructible or convertible from optional<U>.
+template <typename T, typename U>
+struct is_constructible_convertible_from_optional
+ : std::integral_constant<
+ bool, std::is_constructible<T, optional<U>&>::value ||
+ std::is_constructible<T, optional<U>&&>::value ||
+ std::is_constructible<T, const optional<U>&>::value ||
+ std::is_constructible<T, const optional<U>&&>::value ||
+ std::is_convertible<optional<U>&, T>::value ||
+ std::is_convertible<optional<U>&&, T>::value ||
+ std::is_convertible<const optional<U>&, T>::value ||
+ std::is_convertible<const optional<U>&&, T>::value> {};
+
+// Whether T is constructible or convertible or assignable from optional<U>.
+template <typename T, typename U>
+struct is_constructible_convertible_assignable_from_optional
+ : std::integral_constant<
+ bool, is_constructible_convertible_from_optional<T, U>::value ||
+ std::is_assignable<T&, optional<U>&>::value ||
+ std::is_assignable<T&, optional<U>&&>::value ||
+ std::is_assignable<T&, const optional<U>&>::value ||
+ std::is_assignable<T&, const optional<U>&&>::value> {};
+
+// Helper function used by [optional.relops], [optional.comp_with_t],
+// for checking whether an expression is convertible to bool.
+bool convertible_to_bool(bool);
+
+// Base class for std::hash<absl::optional<T>>:
+// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
+// compute the hash; Otherwise, it is disabled.
+// Reference N4659 23.14.15 [unord.hash].
+template <typename T, typename = size_t>
+struct optional_hash_base {
+ optional_hash_base() = delete;
+ optional_hash_base(const optional_hash_base&) = delete;
+ optional_hash_base(optional_hash_base&&) = delete;
+ optional_hash_base& operator=(const optional_hash_base&) = delete;
+ optional_hash_base& operator=(optional_hash_base&&) = delete;
+};
+
+template <typename T>
+struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
+ std::declval<absl::remove_const_t<T> >()))> {
+ using argument_type = absl::optional<T>;
+ using result_type = size_t;
+ size_t operator()(const absl::optional<T>& opt) const {
+ absl::type_traits_internal::AssertHashEnabled<absl::remove_const_t<T>>();
+ if (opt) {
+ return std::hash<absl::remove_const_t<T> >()(*opt);
+ } else {
+ return static_cast<size_t>(0x297814aaad196e6dULL);
+ }
+ }
+};
+
+} // namespace optional_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+
+#endif // ABSL_TYPES_INTERNAL_OPTIONAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/parentheses.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/parentheses.h
new file mode 100644
index 00000000000..5aebee8fdeb
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/parentheses.h
@@ -0,0 +1,34 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// parentheses.h
+// -----------------------------------------------------------------------------
+//
+// This file contains macros that expand to a left parenthesis and a right
+// parenthesis. These are in their own file and are generated from macros
+// because otherwise clang-format gets confused and clang-format off directives
+// do not help.
+//
+// The parentheses macros are used when wanting to require a rescan before
+// expansion of parenthesized text appearing after a function-style macro name.
+
+#ifndef ABSL_TYPES_INTERNAL_PARENTHESES_H_
+#define ABSL_TYPES_INTERNAL_PARENTHESES_H_
+
+#define ABSL_INTERNAL_LPAREN (
+
+#define ABSL_INTERNAL_RPAREN )
+
+#endif // ABSL_TYPES_INTERNAL_PARENTHESES_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/span.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/span.h
new file mode 100644
index 00000000000..112612f4bda
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/span.h
@@ -0,0 +1,128 @@
+//
+// 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_TYPES_INTERNAL_SPAN_H_
+#define ABSL_TYPES_INTERNAL_SPAN_H_
+
+#include <algorithm>
+#include <cstddef>
+#include <string>
+#include <type_traits>
+
+#include "absl/algorithm/algorithm.h"
+#include "absl/base/internal/throw_delegate.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+namespace span_internal {
+// A constexpr min function
+constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
+
+// Wrappers for access to container data pointers.
+template <typename C>
+constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
+ -> decltype(c.data()) {
+ return c.data();
+}
+
+// Before C++17, std::string::data returns a const char* in all cases.
+inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
+ int) noexcept {
+ return &s[0];
+}
+
+template <typename C>
+constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
+ -> decltype(GetDataImpl(c, 0)) {
+ return GetDataImpl(c, 0);
+}
+
+// Detection idioms for size() and data().
+template <typename C>
+using HasSize =
+ std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
+
+// We want to enable conversion from vector<T*> to Span<const T* const> but
+// disable conversion from vector<Derived> to Span<Base>. Here we use
+// the fact that U** is convertible to Q* const* if and only if Q is the same
+// type or a more cv-qualified version of U. We also decay the result type of
+// data() to avoid problems with classes which have a member function data()
+// which returns a reference.
+template <typename T, typename C>
+using HasData =
+ std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
+ T* const*>;
+
+// Extracts value type from a Container
+template <typename C>
+struct ElementType {
+ using type = typename absl::remove_reference_t<C>::value_type;
+};
+
+template <typename T, size_t N>
+struct ElementType<T (&)[N]> {
+ using type = T;
+};
+
+template <typename C>
+using ElementT = typename ElementType<C>::type;
+
+template <typename T>
+using EnableIfMutable =
+ typename std::enable_if<!std::is_const<T>::value, int>::type;
+
+template <template <typename> class SpanT, typename T>
+bool EqualImpl(SpanT<T> a, SpanT<T> b) {
+ static_assert(std::is_const<T>::value, "");
+ return absl::equal(a.begin(), a.end(), b.begin(), b.end());
+}
+
+template <template <typename> class SpanT, typename T>
+bool LessThanImpl(SpanT<T> a, SpanT<T> b) {
+ // We can't use value_type since that is remove_cv_t<T>, so we go the long way
+ // around.
+ static_assert(std::is_const<T>::value, "");
+ return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
+}
+
+// The `IsConvertible` classes here are needed because of the
+// `std::is_convertible` bug in libcxx when compiled with GCC. This build
+// configuration is used by Android NDK toolchain. Reference link:
+// https://bugs.llvm.org/show_bug.cgi?id=27538.
+template <typename From, typename To>
+struct IsConvertibleHelper {
+ private:
+ static std::true_type testval(To);
+ static std::false_type testval(...);
+
+ public:
+ using type = decltype(testval(std::declval<From>()));
+};
+
+template <typename From, typename To>
+struct IsConvertible : IsConvertibleHelper<From, To>::type {};
+
+// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
+// older version of libcxx is not supported.
+template <typename From, typename To>
+using EnableIfConvertibleTo =
+ typename std::enable_if<IsConvertible<From, To>::value>::type;
+} // namespace span_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_TYPES_INTERNAL_SPAN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/transform_args.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/transform_args.h
new file mode 100644
index 00000000000..4a0ab42ac49
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/transform_args.h
@@ -0,0 +1,246 @@
+// 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.
+//
+// -----------------------------------------------------------------------------
+// transform_args.h
+// -----------------------------------------------------------------------------
+//
+// This file contains a higher-order macro that "transforms" each element of a
+// a variadic argument by a provided secondary macro.
+
+#ifndef ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
+#define ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
+
+//
+// ABSL_INTERNAL_CAT(a, b)
+//
+// This macro takes two arguments and concatenates them together via ## after
+// expansion.
+//
+// Example:
+//
+// ABSL_INTERNAL_CAT(foo_, bar)
+//
+// Results in:
+//
+// foo_bar
+#define ABSL_INTERNAL_CAT(a, b) ABSL_INTERNAL_CAT_IMPL(a, b)
+#define ABSL_INTERNAL_CAT_IMPL(a, b) a##b
+
+//
+// ABSL_INTERNAL_TRANSFORM_ARGS(m, ...)
+//
+// This macro takes another macro as an argument followed by a trailing series
+// of additional parameters (up to 32 additional arguments). It invokes the
+// passed-in macro once for each of the additional arguments, with the
+// expansions separated by commas.
+//
+// Example:
+//
+// ABSL_INTERNAL_TRANSFORM_ARGS(MY_MACRO, a, b, c)
+//
+// Results in:
+//
+// MY_MACRO(a), MY_MACRO(b), MY_MACRO(c)
+//
+// TODO(calabrese) Handle no arguments as a special case.
+#define ABSL_INTERNAL_TRANSFORM_ARGS(m, ...) \
+ ABSL_INTERNAL_CAT(ABSL_INTERNAL_TRANSFORM_ARGS, \
+ ABSL_INTERNAL_NUM_ARGS(__VA_ARGS__)) \
+ (m, __VA_ARGS__)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS1(m, a0) m(a0)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS2(m, a0, a1) m(a0), m(a1)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS3(m, a0, a1, a2) m(a0), m(a1), m(a2)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS4(m, a0, a1, a2, a3) \
+ m(a0), m(a1), m(a2), m(a3)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS5(m, a0, a1, a2, a3, a4) \
+ m(a0), m(a1), m(a2), m(a3), m(a4)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS6(m, a0, a1, a2, a3, a4, a5) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS7(m, a0, a1, a2, a3, a4, a5, a6) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS8(m, a0, a1, a2, a3, a4, a5, a6, a7) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS9(m, a0, a1, a2, a3, a4, a5, a6, a7, a8) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS10(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS11(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), m(a10)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS12(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS13(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS14(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS15(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS16(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS17(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS18(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS19(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS20(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS21(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS22(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20, a21) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS23(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20, a21, a22) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS24(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20, a21, a22, a23) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS25(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20, a21, a22, a23, a24) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS26( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS27( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS28( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS29( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+ m(a28)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS30( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+ m(a28), m(a29)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS31( \
+ m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, \
+ a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+ m(a28), m(a29), m(a30)
+
+#define ABSL_INTERNAL_TRANSFORM_ARGS32(m, a0, a1, a2, a3, a4, a5, a6, a7, a8, \
+ a9, a10, a11, a12, a13, a14, a15, a16, \
+ a17, a18, a19, a20, a21, a22, a23, a24, \
+ a25, a26, a27, a28, a29, a30, a31) \
+ m(a0), m(a1), m(a2), m(a3), m(a4), m(a5), m(a6), m(a7), m(a8), m(a9), \
+ m(a10), m(a11), m(a12), m(a13), m(a14), m(a15), m(a16), m(a17), m(a18), \
+ m(a19), m(a20), m(a21), m(a22), m(a23), m(a24), m(a25), m(a26), m(a27), \
+ m(a28), m(a29), m(a30), m(a31)
+
+#define ABSL_INTERNAL_NUM_ARGS_IMPL(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, \
+ a10, a11, a12, a13, a14, a15, a16, a17, \
+ a18, a19, a20, a21, a22, a23, a24, a25, \
+ a26, a27, a28, a29, a30, a31, result, ...) \
+ result
+
+#define ABSL_INTERNAL_FORCE_EXPANSION(...) __VA_ARGS__
+
+#define ABSL_INTERNAL_NUM_ARGS(...) \
+ ABSL_INTERNAL_FORCE_EXPANSION(ABSL_INTERNAL_NUM_ARGS_IMPL( \
+ __VA_ARGS__, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, \
+ 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, ))
+
+#endif // ABSL_TYPES_INTERNAL_TRANSFORM_ARGS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/variant.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/variant.h
index 477e5895ed7..772008c74e6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/variant.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/internal/variant.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -15,7 +15,6 @@
// Implementation details of absl/types/variant.h, pulled into a
// separate file to avoid cluttering the top of the API header with
// implementation details.
-//
#ifndef ABSL_TYPES_variant_internal_H_
#define ABSL_TYPES_variant_internal_H_
@@ -38,14 +37,15 @@
#include "absl/types/bad_variant_access.h"
#include "absl/utility/utility.h"
-#if !defined(ABSL_HAVE_STD_VARIANT)
+#if !defined(ABSL_USES_STD_VARIANT)
namespace absl {
+ABSL_NAMESPACE_BEGIN
template <class... Types>
class variant;
-ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
+ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
template <class T>
struct variant_size;
@@ -205,7 +205,7 @@ template <class Op, class... Vs>
using VisitIndicesResultT = typename VisitIndicesResultImpl<Op, Vs...>::type;
template <class ReturnType, class FunctionObject, class EndIndices,
- std::size_t... BoundIndices>
+ class BoundIndices>
struct MakeVisitationMatrix;
template <class ReturnType, class FunctionObject, std::size_t... Indices>
@@ -219,7 +219,7 @@ constexpr ReturnType call_with_indices(FunctionObject&& function) {
template <class ReturnType, class FunctionObject, std::size_t... BoundIndices>
struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
- BoundIndices...> {
+ index_sequence<BoundIndices...>> {
using ResultType = ReturnType (*)(FunctionObject&&);
static constexpr ResultType Run() {
return &call_with_indices<ReturnType, FunctionObject,
@@ -227,24 +227,34 @@ struct MakeVisitationMatrix<ReturnType, FunctionObject, index_sequence<>,
}
};
+template <typename Is, std::size_t J>
+struct AppendToIndexSequence;
+
+template <typename Is, std::size_t J>
+using AppendToIndexSequenceT = typename AppendToIndexSequence<Is, J>::type;
+
+template <std::size_t... Is, std::size_t J>
+struct AppendToIndexSequence<index_sequence<Is...>, J> {
+ using type = index_sequence<Is..., J>;
+};
+
template <class ReturnType, class FunctionObject, class EndIndices,
- class CurrIndices, std::size_t... BoundIndices>
+ class CurrIndices, class BoundIndices>
struct MakeVisitationMatrixImpl;
-template <class ReturnType, class FunctionObject, std::size_t... EndIndices,
- std::size_t... CurrIndices, std::size_t... BoundIndices>
-struct MakeVisitationMatrixImpl<
- ReturnType, FunctionObject, index_sequence<EndIndices...>,
- index_sequence<CurrIndices...>, BoundIndices...> {
+template <class ReturnType, class FunctionObject, class EndIndices,
+ std::size_t... CurrIndices, class BoundIndices>
+struct MakeVisitationMatrixImpl<ReturnType, FunctionObject, EndIndices,
+ index_sequence<CurrIndices...>, BoundIndices> {
using ResultType = SimpleArray<
- typename MakeVisitationMatrix<ReturnType, FunctionObject,
- index_sequence<EndIndices...>>::ResultType,
+ typename MakeVisitationMatrix<ReturnType, FunctionObject, EndIndices,
+ index_sequence<>>::ResultType,
sizeof...(CurrIndices)>;
static constexpr ResultType Run() {
- return {{MakeVisitationMatrix<ReturnType, FunctionObject,
- index_sequence<EndIndices...>,
- BoundIndices..., CurrIndices>::Run()...}};
+ return {{MakeVisitationMatrix<
+ ReturnType, FunctionObject, EndIndices,
+ AppendToIndexSequenceT<BoundIndices, CurrIndices>>::Run()...}};
}
};
@@ -252,10 +262,11 @@ template <class ReturnType, class FunctionObject, std::size_t HeadEndIndex,
std::size_t... TailEndIndices, std::size_t... BoundIndices>
struct MakeVisitationMatrix<ReturnType, FunctionObject,
index_sequence<HeadEndIndex, TailEndIndices...>,
- BoundIndices...>
- : MakeVisitationMatrixImpl<
- ReturnType, FunctionObject, index_sequence<TailEndIndices...>,
- absl::make_index_sequence<HeadEndIndex>, BoundIndices...> {};
+ index_sequence<BoundIndices...>>
+ : MakeVisitationMatrixImpl<ReturnType, FunctionObject,
+ index_sequence<TailEndIndices...>,
+ absl::make_index_sequence<HeadEndIndex>,
+ index_sequence<BoundIndices...>> {};
struct UnreachableSwitchCase {
template <class Op>
@@ -281,7 +292,7 @@ struct UnreachableSwitchCase {
template <class Op, std::size_t I>
struct ReachableSwitchCase {
static VisitIndicesResultT<Op, std::size_t> Run(Op&& op) {
- return absl::base_internal::Invoke(absl::forward<Op>(op), SizeT<I>());
+ return absl::base_internal::invoke(absl::forward<Op>(op), SizeT<I>());
}
};
@@ -413,7 +424,7 @@ struct VisitIndicesSwitch {
return PickCase<Op, 32, EndIndex>::Run(absl::forward<Op>(op));
default:
ABSL_ASSERT(i == variant_npos);
- return absl::base_internal::Invoke(absl::forward<Op>(op), NPos());
+ return absl::base_internal::invoke(absl::forward<Op>(op), NPos());
}
}
};
@@ -424,7 +435,8 @@ struct VisitIndicesFallback {
static VisitIndicesResultT<Op, SizeT...> Run(Op&& op, SizeT... indices) {
return AccessSimpleArray(
MakeVisitationMatrix<VisitIndicesResultT<Op, SizeT...>, Op,
- index_sequence<(EndIndices + 1)...>>::Run(),
+ index_sequence<(EndIndices + 1)...>,
+ index_sequence<>>::Run(),
(indices + 1)...)(absl::forward<Op>(op));
}
};
@@ -476,7 +488,7 @@ struct VisitIndicesVariadicImpl<absl::index_sequence<N...>, EndIndices...> {
template <std::size_t I>
VisitIndicesResultT<Op, decltype(EndIndices)...> operator()(
SizeT<I> /*index*/) && {
- return base_internal::Invoke(
+ return base_internal::invoke(
absl::forward<Op>(op),
SizeT<UnflattenIndex<I, N, (EndIndices + 1)...>::value -
std::size_t{1}>()...);
@@ -838,8 +850,8 @@ struct ImaginaryFun<variant<H, T...>, I> : ImaginaryFun<variant<T...>, I + 1> {
// NOTE: const& and && are used instead of by-value due to lack of guaranteed
// move elision of C++17. This may have other minor differences, but tests
// pass.
- static SizeT<I> Run(const H&);
- static SizeT<I> Run(H&&);
+ static SizeT<I> Run(const H&, SizeT<I>);
+ static SizeT<I> Run(H&&, SizeT<I>);
};
// The following metafunctions are used in constructor and assignment
@@ -861,7 +873,8 @@ struct ConversionIsPossibleImpl : std::false_type {};
template <class Variant, class T>
struct ConversionIsPossibleImpl<
- Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
+ Variant, T,
+ void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
: std::true_type {};
template <class Variant, class T>
@@ -869,8 +882,9 @@ struct ConversionIsPossible : ConversionIsPossibleImpl<Variant, T>::type {};
template <class Variant, class T>
struct IndexOfConstructedType<
- Variant, T, void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>()))>>
- : decltype(ImaginaryFun<Variant>::Run(std::declval<T>())) {};
+ Variant, T,
+ void_t<decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {}))>>
+ : decltype(ImaginaryFun<Variant>::Run(std::declval<T>(), {})) {};
template <std::size_t... Is>
struct ContainsVariantNPos
@@ -916,7 +930,7 @@ struct PerformVisitation {
absl::result_of_t<Op(VariantAccessResult<
Is, QualifiedVariants>...)>>::value,
"All visitation overloads must have the same return type.");
- return absl::base_internal::Invoke(
+ return absl::base_internal::invoke(
absl::forward<Op>(op),
VariantCoreAccess::Access<Is>(
absl::forward<QualifiedVariants>(std::get<TupIs>(variant_tup)))...);
@@ -1549,8 +1563,8 @@ struct SwapSameIndex {
variant<Types...>* w;
template <std::size_t I>
void operator()(SizeT<I>) const {
- using std::swap;
- swap(VariantCoreAccess::Access<I>(*v), VariantCoreAccess::Access<I>(*w));
+ type_traits_internal::Swap(VariantCoreAccess::Access<I>(*v),
+ VariantCoreAccess::Access<I>(*w));
}
void operator()(SizeT<variant_npos>) const {}
@@ -1605,11 +1619,12 @@ struct VariantHashVisitor {
template <typename Variant, typename... Ts>
struct VariantHashBase<Variant,
absl::enable_if_t<absl::conjunction<
- type_traits_internal::IsHashEnabled<Ts>...>::value>,
+ type_traits_internal::IsHashable<Ts>...>::value>,
Ts...> {
using argument_type = Variant;
using result_type = size_t;
size_t operator()(const Variant& var) const {
+ type_traits_internal::AssertHashEnabled<Ts...>();
if (var.valueless_by_exception()) {
return 239799884;
}
@@ -1624,7 +1639,8 @@ struct VariantHashBase<Variant,
};
} // namespace variant_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // !defined(ABSL_HAVE_STD_VARIANT)
+#endif // !defined(ABSL_USES_STD_VARIANT)
#endif // ABSL_TYPES_variant_internal_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.cc
index ef272904199..4482955c4cb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.cc
@@ -1,10 +1,11 @@
-// Copyright 2017 The Abseil Authors.
+//
+// Copyright 2020 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -12,13 +13,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/types/optional.h"
+#include "absl/flags/internal/commandlineflag.h"
-#ifndef ABSL_HAVE_STD_OPTIONAL
namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
-nullopt_t::init_t nullopt_t::init;
-extern const nullopt_t nullopt{nullopt_t::init};
+FlagStateInterface::~FlagStateInterface() {}
+} // namespace flags_internal
+ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_HAVE_STD_OPTIONAL
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.h
index 7677fe52c0e..61540cfdb26 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -35,64 +35,55 @@
#ifndef ABSL_TYPES_OPTIONAL_H_
#define ABSL_TYPES_OPTIONAL_H_
-#include "absl/base/config.h"
+#include "absl/base/config.h" // TODO(calabrese) IWYU removal?
#include "absl/utility/utility.h"
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
-#include <optional>
+#include <optional> // IWYU pragma: export
namespace absl {
+ABSL_NAMESPACE_BEGIN
using std::bad_optional_access;
using std::optional;
using std::make_optional;
using std::nullopt_t;
using std::nullopt;
+ABSL_NAMESPACE_END
} // namespace absl
-#else // ABSL_HAVE_STD_OPTIONAL
+#else // ABSL_USES_STD_OPTIONAL
#include <cassert>
#include <functional>
#include <initializer_list>
-#include <new>
#include <type_traits>
#include <utility>
#include "absl/base/attributes.h"
-#include "absl/memory/memory.h"
+#include "absl/base/internal/inline_variable.h"
#include "absl/meta/type_traits.h"
#include "absl/types/bad_optional_access.h"
+#include "absl/types/internal/optional.h"
-// ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// nullopt_t
//
-// Inheriting constructors is supported in GCC 4.8+, Clang 3.3+ and MSVC 2015.
-// __cpp_inheriting_constructors is a predefined macro and a recommended way to
-// check for this language feature, but GCC doesn't support it until 5.0 and
-// Clang doesn't support it until 3.6.
-// Also, MSVC 2015 has a bug: it doesn't inherit the constexpr template
-// constructor. For example, the following code won't work on MSVC 2015 Update3:
-// struct Base {
-// int t;
-// template <typename T>
-// constexpr Base(T t_) : t(t_) {}
-// };
-// struct Foo : Base {
-// using Base::Base;
-// }
-// constexpr Foo foo(0); // doesn't work on MSVC 2015
-#if defined(__clang__)
-#if __has_feature(cxx_inheriting_constructors)
-#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
-#endif
-#elif (defined(__GNUC__) && \
- (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 8)) || \
- (__cpp_inheriting_constructors >= 200802) || \
- (defined(_MSC_VER) && _MSC_VER >= 1910)
-#define ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS 1
-#endif
+// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
+// that does not contain a value.
+struct nullopt_t {
+ // It must not be default-constructible to avoid ambiguity for opt = {}.
+ explicit constexpr nullopt_t(optional_internal::init_t) noexcept {}
+};
-namespace absl {
+// nullopt
+//
+// A tag constant of type `absl::nullopt_t` used to indicate an empty
+// `absl::optional` in certain functions, such as construction or assignment.
+ABSL_INTERNAL_INLINE_CONSTEXPR(nullopt_t, nullopt,
+ nullopt_t(optional_internal::init_t()));
// -----------------------------------------------------------------------------
// absl::optional
@@ -114,10 +105,6 @@ namespace absl {
// need the inline variable support in C++17 for external linkage.
// * Throws `absl::bad_optional_access` instead of
// `std::bad_optional_access`.
-// * `optional::swap()` and `absl::swap()` relies on
-// `std::is_(nothrow_)swappable()`, which has been introduced in C++17.
-// As a workaround, we assume `is_swappable()` is always `true`
-// and `is_nothrow_swappable()` is the same as `std::is_trivial()`.
// * `make_optional()` cannot be declared `constexpr` due to the absence of
// guaranteed copy elision.
// * The move constructor's `noexcept` specification is stronger, i.e. if the
@@ -127,366 +114,13 @@ namespace absl {
// a) move constructors should only throw due to allocation failure and
// b) if T's move constructor allocates, it uses the same allocation
// function as the default allocator.
-template <typename T>
-class optional;
-
-// nullopt_t
-//
-// Class type for `absl::nullopt` used to indicate an `absl::optional<T>` type
-// that does not contain a value.
-struct nullopt_t {
- struct init_t {};
- static init_t init;
-
- // It must not be default-constructible to avoid ambiguity for opt = {}.
- // Note the non-const reference, which is to eliminate ambiguity for code
- // like:
- //
- // struct S { int value; };
- //
- // void Test() {
- // optional<S> opt;
- // opt = {{}};
- // }
- explicit constexpr nullopt_t(init_t& /*unused*/) {}
-};
-
-// nullopt
//
-// A tag constant of type `absl::nullopt_t` used to indicate an empty
-// `absl::optional` in certain functions, such as construction or assignment.
-extern const nullopt_t nullopt;
-
-namespace optional_internal {
-
-struct empty_struct {};
-// This class stores the data in optional<T>.
-// It is specialized based on whether T is trivially destructible.
-// This is the specialization for non trivially destructible type.
-template <typename T, bool unused = std::is_trivially_destructible<T>::value>
-class optional_data_dtor_base {
- struct dummy_type {
- static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
- // Use an array to avoid GCC 6 placement-new warning.
- empty_struct data[sizeof(T) / sizeof(empty_struct)];
- };
-
- protected:
- // Whether there is data or not.
- bool engaged_;
- // Data storage
- union {
- dummy_type dummy_;
- T data_;
- };
-
- void destruct() noexcept {
- if (engaged_) {
- data_.~T();
- engaged_ = false;
- }
- }
-
- // dummy_ must be initialized for constexpr constructor.
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(absl::forward<Args>(args)...) {}
-
- ~optional_data_dtor_base() { destruct(); }
-};
-
-// Specialization for trivially destructible type.
-template <typename T>
-class optional_data_dtor_base<T, true> {
- struct dummy_type {
- static_assert(sizeof(T) % sizeof(empty_struct) == 0, "");
- // Use array to avoid GCC 6 placement-new warning.
- empty_struct data[sizeof(T) / sizeof(empty_struct)];
- };
-
- protected:
- // Whether there is data or not.
- bool engaged_;
- // Data storage
- union {
- dummy_type dummy_;
- T data_;
- };
- void destruct() noexcept { engaged_ = false; }
-
- // dummy_ must be initialized for constexpr constructor.
- constexpr optional_data_dtor_base() noexcept : engaged_(false), dummy_{{}} {}
-
- template <typename... Args>
- constexpr explicit optional_data_dtor_base(in_place_t, Args&&... args)
- : engaged_(true), data_(absl::forward<Args>(args)...) {}
-};
-
-template <typename T>
-class optional_data_base : public optional_data_dtor_base<T> {
- protected:
- using base = optional_data_dtor_base<T>;
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using base::base;
-#else
- optional_data_base() = default;
-
- template <typename... Args>
- constexpr explicit optional_data_base(in_place_t t, Args&&... args)
- : base(t, absl::forward<Args>(args)...) {}
-#endif
-
- template <typename... Args>
- void construct(Args&&... args) {
- // Use dummy_'s address to work around casting cv-qualified T* to void*.
- ::new (static_cast<void*>(&this->dummy_)) T(std::forward<Args>(args)...);
- this->engaged_ = true;
- }
-
- template <typename U>
- void assign(U&& u) {
- if (this->engaged_) {
- this->data_ = std::forward<U>(u);
- } else {
- construct(std::forward<U>(u));
- }
- }
-};
-
-// TODO(absl-team): Add another class using
-// std::is_trivially_move_constructible trait when available to match
-// http://cplusplus.github.io/LWG/lwg-defects.html#2900, for types that
-// have trivial move but nontrivial copy.
-// Also, we should be checking is_trivially_copyable here, which is not
-// supported now, so we use is_trivially_* traits instead.
-template <typename T,
- bool unused = absl::is_trivially_copy_constructible<T>::value&&
- absl::is_trivially_copy_assignable<typename std::remove_cv<
- T>::type>::value&& std::is_trivially_destructible<T>::value>
-class optional_data;
-
-// Trivially copyable types
-template <typename T>
-class optional_data<T, true> : public optional_data_base<T> {
- protected:
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using optional_data_base<T>::optional_data_base;
-#else
- optional_data() = default;
-
- template <typename... Args>
- constexpr explicit optional_data(in_place_t t, Args&&... args)
- : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
-#endif
-};
-
-template <typename T>
-class optional_data<T, false> : public optional_data_base<T> {
- protected:
-#if ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
- using optional_data_base<T>::optional_data_base;
-#else
- template <typename... Args>
- constexpr explicit optional_data(in_place_t t, Args&&... args)
- : optional_data_base<T>(t, absl::forward<Args>(args)...) {}
-#endif
-
- optional_data() = default;
-
- optional_data(const optional_data& rhs) {
- if (rhs.engaged_) {
- this->construct(rhs.data_);
- }
- }
-
- optional_data(optional_data&& rhs) noexcept(
- absl::default_allocator_is_nothrow::value ||
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- this->construct(std::move(rhs.data_));
- }
- }
-
- optional_data& operator=(const optional_data& rhs) {
- if (rhs.engaged_) {
- this->assign(rhs.data_);
- } else {
- this->destruct();
- }
- return *this;
- }
-
- optional_data& operator=(optional_data&& rhs) noexcept(
- std::is_nothrow_move_assignable<T>::value&&
- std::is_nothrow_move_constructible<T>::value) {
- if (rhs.engaged_) {
- this->assign(std::move(rhs.data_));
- } else {
- this->destruct();
- }
- return *this;
- }
-};
-
-// Ordered by level of restriction, from low to high.
-// Copyable implies movable.
-enum class copy_traits { copyable = 0, movable = 1, non_movable = 2 };
-
-// Base class for enabling/disabling copy/move constructor.
-template <copy_traits>
-class optional_ctor_base;
-
-template <>
-class optional_ctor_base<copy_traits::copyable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = default;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = default;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-template <>
-class optional_ctor_base<copy_traits::non_movable> {
- public:
- constexpr optional_ctor_base() = default;
- optional_ctor_base(const optional_ctor_base&) = delete;
- optional_ctor_base(optional_ctor_base&&) = delete;
- optional_ctor_base& operator=(const optional_ctor_base&) = default;
- optional_ctor_base& operator=(optional_ctor_base&&) = default;
-};
-
-// Base class for enabling/disabling copy/move assignment.
-template <copy_traits>
-class optional_assign_base;
-
-template <>
-class optional_assign_base<copy_traits::copyable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = default;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = default;
-};
-
-template <>
-class optional_assign_base<copy_traits::non_movable> {
- public:
- constexpr optional_assign_base() = default;
- optional_assign_base(const optional_assign_base&) = default;
- optional_assign_base(optional_assign_base&&) = default;
- optional_assign_base& operator=(const optional_assign_base&) = delete;
- optional_assign_base& operator=(optional_assign_base&&) = delete;
-};
-
-template <typename T>
-constexpr copy_traits get_ctor_copy_traits() {
- return std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : std::is_move_constructible<T>::value ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-template <typename T>
-constexpr copy_traits get_assign_copy_traits() {
- return absl::is_copy_assignable<T>::value &&
- std::is_copy_constructible<T>::value
- ? copy_traits::copyable
- : absl::is_move_assignable<T>::value &&
- std::is_move_constructible<T>::value
- ? copy_traits::movable
- : copy_traits::non_movable;
-}
-
-// Whether T is constructible or convertible from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_from_optional
- : std::integral_constant<
- bool, std::is_constructible<T, optional<U>&>::value ||
- std::is_constructible<T, optional<U>&&>::value ||
- std::is_constructible<T, const optional<U>&>::value ||
- std::is_constructible<T, const optional<U>&&>::value ||
- std::is_convertible<optional<U>&, T>::value ||
- std::is_convertible<optional<U>&&, T>::value ||
- std::is_convertible<const optional<U>&, T>::value ||
- std::is_convertible<const optional<U>&&, T>::value> {};
-
-// Whether T is constructible or convertible or assignable from optional<U>.
-template <typename T, typename U>
-struct is_constructible_convertible_assignable_from_optional
- : std::integral_constant<
- bool, is_constructible_convertible_from_optional<T, U>::value ||
- std::is_assignable<T&, optional<U>&>::value ||
- std::is_assignable<T&, optional<U>&&>::value ||
- std::is_assignable<T&, const optional<U>&>::value ||
- std::is_assignable<T&, const optional<U>&&>::value> {};
-
-// Helper function used by [optional.relops], [optional.comp_with_t],
-// for checking whether an expression is convertible to bool.
-bool convertible_to_bool(bool);
-
-// Base class for std::hash<absl::optional<T>>:
-// If std::hash<std::remove_const_t<T>> is enabled, it provides operator() to
-// compute the hash; Otherwise, it is disabled.
-// Reference N4659 23.14.15 [unord.hash].
-template <typename T, typename = size_t>
-struct optional_hash_base {
- optional_hash_base() = delete;
- optional_hash_base(const optional_hash_base&) = delete;
- optional_hash_base(optional_hash_base&&) = delete;
- optional_hash_base& operator=(const optional_hash_base&) = delete;
- optional_hash_base& operator=(optional_hash_base&&) = delete;
-};
-
-template <typename T>
-struct optional_hash_base<T, decltype(std::hash<absl::remove_const_t<T> >()(
- std::declval<absl::remove_const_t<T> >()))> {
- using argument_type = absl::optional<T>;
- using result_type = size_t;
- size_t operator()(const absl::optional<T>& opt) const {
- if (opt) {
- return std::hash<absl::remove_const_t<T> >()(*opt);
- } else {
- return static_cast<size_t>(0x297814aaad196e6dULL);
- }
- }
-};
-
-} // namespace optional_internal
-
-// -----------------------------------------------------------------------------
-// absl::optional class definition
-// -----------------------------------------------------------------------------
-
template <typename T>
class optional : private optional_internal::optional_data<T>,
private optional_internal::optional_ctor_base<
- optional_internal::get_ctor_copy_traits<T>()>,
+ optional_internal::ctor_copy_traits<T>::traits>,
private optional_internal::optional_assign_base<
- optional_internal::get_assign_copy_traits<T>()> {
+ optional_internal::assign_copy_traits<T>::traits> {
using data_base = optional_internal::optional_data<T>;
public:
@@ -502,19 +136,20 @@ class optional : private optional_internal::optional_data<T>,
constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit)
// Copy constructor, standard semantics
- optional(const optional& src) = default;
+ optional(const optional&) = default;
// Move constructor, standard semantics
- optional(optional&& src) = default;
+ optional(optional&&) = default;
// Constructs a non-empty `optional` direct-initialized value of type `T` from
// the arguments `std::forward<Args>(args)...` within the `optional`.
// (The `in_place_t` is a tag used to indicate that the contained object
// should be constructed in-place.)
- //
- // TODO(absl-team): Add std::is_constructible<T, Args&&...> SFINAE.
- template <typename... Args>
- constexpr explicit optional(in_place_t, Args&&... args)
+ template <typename InPlaceT, typename... Args,
+ absl::enable_if_t<absl::conjunction<
+ std::is_same<InPlaceT, in_place_t>,
+ std::is_constructible<T, Args&&...> >::value>* = nullptr>
+ constexpr explicit optional(InPlaceT, Args&&... args)
: data_base(in_place_t(), absl::forward<Args>(args)...) {}
// Constructs a non-empty `optional` direct-initialized value of type `T` from
@@ -750,11 +385,10 @@ class optional : private optional_internal::optional_data<T>,
// Swap, standard semantics
void swap(optional& rhs) noexcept(
std::is_nothrow_move_constructible<T>::value&&
- std::is_trivial<T>::value) {
+ type_traits_internal::IsNothrowSwappable<T>::value) {
if (*this) {
if (rhs) {
- using std::swap;
- swap(**this, *rhs);
+ type_traits_internal::Swap(**this, *rhs);
} else {
rhs.construct(std::move(**this));
this->destruct();
@@ -778,11 +412,11 @@ class optional : private optional_internal::optional_data<T>,
//
// If you need myOpt->foo in constexpr, use (*myOpt).foo instead.
const T* operator->() const {
- assert(this->engaged_);
+ ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_);
}
T* operator->() {
- assert(this->engaged_);
+ ABSL_HARDENING_ASSERT(this->engaged_);
return std::addressof(this->data_);
}
@@ -790,16 +424,18 @@ class optional : private optional_internal::optional_data<T>,
//
// Accesses the underlying `T` value of an `optional`. If the `optional` is
// empty, behavior is undefined.
- constexpr const T& operator*() const & { return reference(); }
+ constexpr const T& operator*() const& {
+ return ABSL_HARDENING_ASSERT(this->engaged_), reference();
+ }
T& operator*() & {
- assert(this->engaged_);
+ ABSL_HARDENING_ASSERT(this->engaged_);
return reference();
}
constexpr const T&& operator*() const && {
- return absl::move(reference());
+ return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference());
}
T&& operator*() && {
- assert(this->engaged_);
+ ABSL_HARDENING_ASSERT(this->engaged_);
return std::move(reference());
}
@@ -808,7 +444,7 @@ class optional : private optional_internal::optional_data<T>,
// Returns false if and only if the `optional` is empty.
//
// if (opt) {
- // // do something with opt.value();
+ // // do something with *opt or opt->;
// } else {
// // opt is empty.
// }
@@ -866,7 +502,7 @@ class optional : private optional_internal::optional_data<T>,
template <typename U>
constexpr T value_or(U&& v) const& {
static_assert(std::is_copy_constructible<value_type>::value,
- "optional<T>::value_or: T must by copy constructible");
+ "optional<T>::value_or: T must be copy constructible");
static_assert(std::is_convertible<U&&, value_type>::value,
"optional<T>::value_or: U must be convertible to T");
return static_cast<bool>(*this)
@@ -876,7 +512,7 @@ class optional : private optional_internal::optional_data<T>,
template <typename U>
T value_or(U&& v) && { // NOLINT(build/c++11)
static_assert(std::is_move_constructible<value_type>::value,
- "optional<T>::value_or: T must by copy constructible");
+ "optional<T>::value_or: T must be move constructible");
static_assert(std::is_convertible<U&&, value_type>::value,
"optional<T>::value_or: U must be convertible to T");
return static_cast<bool>(*this) ? std::move(**this)
@@ -906,12 +542,10 @@ class optional : private optional_internal::optional_data<T>,
//
// Performs a swap between two `absl::optional` objects, using standard
// semantics.
-//
-// NOTE: we assume `is_swappable()` is always `true`. A compile error will
-// result if this is not the case.
-template <typename T,
- typename std::enable_if<std::is_move_constructible<T>::value,
- bool>::type = false>
+template <typename T, typename std::enable_if<
+ std::is_move_constructible<T>::value &&
+ type_traits_internal::IsSwappable<T>::value,
+ bool>::type = false>
void swap(optional<T>& a, optional<T>& b) noexcept(noexcept(a.swap(b))) {
a.swap(b);
}
@@ -1123,6 +757,7 @@ constexpr auto operator>=(const U& v, const optional<T>& x)
return static_cast<bool>(x) ? static_cast<bool>(v >= *x) : true;
}
+ABSL_NAMESPACE_END
} // namespace absl
namespace std {
@@ -1134,9 +769,8 @@ struct hash<absl::optional<T> >
} // namespace std
-#undef ABSL_OPTIONAL_USE_INHERITING_CONSTRUCTORS
#undef ABSL_MSVC_CONSTEXPR_BUG_IN_UNION_LIKE_CLASS
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
#endif // ABSL_TYPES_OPTIONAL_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_exception_safety_test.cc
index d117ee51849..8e5fe851dbb 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_exception_safety_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_exception_safety_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,10 +14,17 @@
#include "absl/types/optional.h"
+#include "absl/base/config.h"
+
+// This test is a no-op when absl::optional is an alias for std::optional and
+// when exceptions are not enabled.
+#if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
+
#include "gtest/gtest.h"
#include "absl/base/internal/exception_safety_testing.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
@@ -279,4 +286,7 @@ TEST(OptionalExceptionSafety, NothrowMoveAssign) {
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+
+#endif // #if !defined(ABSL_USES_STD_OPTIONAL) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_test.cc
index fc4f00a4f52..7ef142cb993 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/optional_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,9 @@
#include "absl/types/optional.h"
+// This test is a no-op when absl::optional is an alias for std::optional.
+#if !defined(ABSL_USES_STD_OPTIONAL)
+
#include <string>
#include <type_traits>
#include <utility>
@@ -157,6 +160,16 @@ struct NonMovable {
NonMovable& operator=(NonMovable&&) = delete;
};
+struct NoDefault {
+ NoDefault() = delete;
+ NoDefault(const NoDefault&) {}
+ NoDefault& operator=(const NoDefault&) { return *this; }
+};
+
+struct ConvertsFromInPlaceT {
+ ConvertsFromInPlaceT(absl::in_place_t) {} // NOLINT
+};
+
TEST(optionalTest, DefaultConstructor) {
absl::optional<int> empty;
EXPECT_FALSE(empty);
@@ -169,15 +182,7 @@ TEST(optionalTest, DefaultConstructor) {
TEST(optionalTest, nulloptConstructor) {
absl::optional<int> empty(absl::nullopt);
EXPECT_FALSE(empty);
-
-#ifdef ABSL_HAVE_STD_OPTIONAL
constexpr absl::optional<int> cempty{absl::nullopt};
-#else
- // Creating a temporary absl::nullopt_t object instead of using absl::nullopt
- // because absl::nullopt cannot be constexpr and have external linkage at the
- // same time.
- constexpr absl::optional<int> cempty{absl::nullopt_t(absl::nullopt_t::init)};
-#endif
static_assert(!cempty.has_value(), "");
EXPECT_TRUE((std::is_nothrow_constructible<absl::optional<int>,
absl::nullopt_t>::value));
@@ -219,7 +224,7 @@ TEST(optionalTest, CopyConstructor) {
EXPECT_FALSE(
absl::is_trivially_copy_constructible<absl::optional<Copyable>>::value);
-#if defined(ABSL_HAVE_STD_OPTIONAL) && defined(__GLIBCXX__)
+#if defined(ABSL_USES_STD_OPTIONAL) && defined(__GLIBCXX__)
// libstdc++ std::optional implementation (as of 7.2) has a bug: when T is
// trivially copyable, optional<T> is not trivially copyable (due to one of
// its base class is unconditionally nontrivial).
@@ -274,7 +279,7 @@ TEST(optionalTest, CopyConstructor) {
// std::optional when T is volatile-qualified. So skipping this test.
// Bug report:
// https://connect.microsoft.com/VisualStudio/feedback/details/3142534
-#if defined(ABSL_HAVE_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911
+#if defined(ABSL_USES_STD_OPTIONAL) && defined(_MSC_VER) && _MSC_VER >= 1911
#define ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG 1
#endif
#ifndef ABSL_MSVC_OPTIONAL_VOLATILE_COPY_BUG
@@ -300,7 +305,7 @@ TEST(optionalTest, MoveConstructor) {
EXPECT_FALSE(std::is_move_constructible<absl::optional<NonMovable>>::value);
// test noexcept
EXPECT_TRUE(std::is_nothrow_move_constructible<absl::optional<int>>::value);
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
EXPECT_EQ(
absl::default_allocator_is_nothrow::value,
std::is_nothrow_move_constructible<absl::optional<MoveableThrow>>::value);
@@ -337,16 +342,18 @@ TEST(optionalTest, InPlaceConstructor) {
static_assert((*opt2).x == ConstexprType::kCtorInitializerList, "");
#endif
- // TODO(absl-team): uncomment these when std::is_constructible<T, Args&&...>
- // SFINAE is added to optional::optional(absl::in_place_t, Args&&...).
- // struct I {
- // I(absl::in_place_t);
- // };
+ EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ absl::in_place_t>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ const absl::in_place_t&>::value));
+ EXPECT_TRUE(
+ (std::is_constructible<absl::optional<ConvertsFromInPlaceT>,
+ absl::in_place_t, absl::in_place_t>::value));
- // EXPECT_FALSE((std::is_constructible<absl::optional<I>,
- // absl::in_place_t>::value));
- // EXPECT_FALSE((std::is_constructible<absl::optional<I>, const
- // absl::in_place_t&>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+ absl::in_place_t>::value));
+ EXPECT_FALSE((std::is_constructible<absl::optional<NoDefault>,
+ absl::in_place_t&&>::value));
}
// template<U=T> optional(U&&);
@@ -632,7 +639,7 @@ TEST(optionalTest, CopyAssignment) {
EXPECT_FALSE(absl::is_trivially_copy_assignable<NonTrivial>::value);
// std::optional doesn't support volatile nontrivial types.
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
{
StructorListener listener;
Listenable::listener = &listener;
@@ -651,7 +658,7 @@ TEST(optionalTest, CopyAssignment) {
EXPECT_EQ(1, listener.destruct);
EXPECT_EQ(1, listener.volatile_copy_assign);
}
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
}
TEST(optionalTest, MoveAssignment) {
@@ -675,7 +682,7 @@ TEST(optionalTest, MoveAssignment) {
EXPECT_EQ(1, listener.move_assign);
}
// std::optional doesn't support volatile nontrivial types.
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
{
StructorListener listener;
Listenable::listener = &listener;
@@ -695,7 +702,7 @@ TEST(optionalTest, MoveAssignment) {
EXPECT_EQ(1, listener.destruct);
EXPECT_EQ(1, listener.volatile_move_assign);
}
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
EXPECT_FALSE(absl::is_move_assignable<absl::optional<const int>>::value);
EXPECT_TRUE(absl::is_move_assignable<absl::optional<Copyable>>::value);
EXPECT_TRUE(absl::is_move_assignable<absl::optional<MoveableThrow>>::value);
@@ -937,7 +944,7 @@ TEST(optionalTest, Swap) {
template <int v>
struct DeletedOpAddr {
- constexpr static const int value = v;
+ int value = v;
constexpr DeletedOpAddr() = default;
constexpr const DeletedOpAddr<v>* operator&() const = delete; // NOLINT
DeletedOpAddr<v>* operator&() = delete; // NOLINT
@@ -947,9 +954,9 @@ struct DeletedOpAddr {
// to document the fact that the current implementation of absl::optional<T>
// expects such usecases to be malformed and not compile.
TEST(optionalTest, OperatorAddr) {
- constexpr const int v = -1;
+ constexpr int v = -1;
{ // constexpr
- constexpr const absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
+ constexpr absl::optional<DeletedOpAddr<v>> opt(absl::in_place_t{});
static_assert(opt.has_value(), "");
// static_assert(opt->value == v, "");
static_assert((*opt).value == v, "");
@@ -1044,14 +1051,13 @@ TEST(optionalTest, Value) {
#ifdef ABSL_HAVE_EXCEPTIONS
EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
#else
- EXPECT_DEATH((void)empty.value(), "Bad optional access");
+ EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access");
#endif
// test constexpr value()
constexpr absl::optional<int> o1(1);
static_assert(1 == o1.value(), ""); // const &
-#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
- !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
using COI = const absl::optional<int>;
static_assert(2 == COI(2).value(), ""); // const &&
#endif
@@ -1091,8 +1097,7 @@ TEST(optionalTest, DerefOperator) {
constexpr absl::optional<int> opt1(1);
static_assert(*opt1 == 1, "");
-#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
- !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
using COI = const absl::optional<int>;
static_assert(*COI(2) == 2, "");
#endif
@@ -1476,8 +1481,8 @@ TEST(optionalTest, MoveAssignRegression) {
TEST(optionalTest, ValueType) {
EXPECT_TRUE((std::is_same<absl::optional<int>::value_type, int>::value));
- EXPECT_TRUE(
- (std::is_same<absl::optional<std::string>::value_type, std::string>::value));
+ EXPECT_TRUE((std::is_same<absl::optional<std::string>::value_type,
+ std::string>::value));
EXPECT_FALSE(
(std::is_same<absl::optional<int>::value_type, absl::nullopt_t>::value));
}
@@ -1504,18 +1509,19 @@ TEST(optionalTest, Hash) {
static_assert(is_hash_enabled_for<absl::optional<int>>::value, "");
static_assert(is_hash_enabled_for<absl::optional<Hashable>>::value, "");
+ static_assert(
+ absl::type_traits_internal::IsHashable<absl::optional<int>>::value, "");
+ static_assert(
+ absl::type_traits_internal::IsHashable<absl::optional<Hashable>>::value,
+ "");
+ absl::type_traits_internal::AssertHashEnabled<absl::optional<int>>();
+ absl::type_traits_internal::AssertHashEnabled<absl::optional<Hashable>>();
-#if defined(_MSC_VER) || (defined(_LIBCPP_VERSION) && \
- _LIBCPP_VERSION < 4000 && _LIBCPP_STD_VER > 11)
- // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
- // static_assert to catch any user-defined type that doesn't provide a hash
- // specialization. So instantiating std::hash<absl::optional<T>> will result
- // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
static_assert(!is_hash_enabled_for<absl::optional<NonHashable>>::value, "");
+ static_assert(!absl::type_traits_internal::IsHashable<
+ absl::optional<NonHashable>>::value,
+ "");
#endif
// libstdc++ std::optional is missing remove_const_t, i.e. it's using
@@ -1552,7 +1558,7 @@ TEST(optionalTest, NoExcept) {
static_assert(
std::is_nothrow_move_constructible<absl::optional<MoveMeNoThrow>>::value,
"");
-#ifndef ABSL_HAVE_STD_OPTIONAL
+#ifndef ABSL_USES_STD_OPTIONAL
static_assert(absl::default_allocator_is_nothrow::value ==
std::is_nothrow_move_constructible<
absl::optional<MoveMeThrow>>::value,
@@ -1623,4 +1629,31 @@ TEST(optionalTest, AssignmentConstraints) {
EXPECT_TRUE(absl::is_copy_assignable<absl::optional<AnyLike>>::value);
}
+#if !defined(__EMSCRIPTEN__)
+struct NestedClassBug {
+ struct Inner {
+ bool dummy = false;
+ };
+ absl::optional<Inner> value;
+};
+
+TEST(optionalTest, InPlaceTSFINAEBug) {
+ NestedClassBug b;
+ ((void)b);
+ using Inner = NestedClassBug::Inner;
+
+ EXPECT_TRUE((std::is_default_constructible<Inner>::value));
+ EXPECT_TRUE((std::is_constructible<Inner>::value));
+ EXPECT_TRUE(
+ (std::is_constructible<absl::optional<Inner>, absl::in_place_t>::value));
+
+ absl::optional<Inner> o(absl::in_place);
+ EXPECT_TRUE(o.has_value());
+ o.emplace();
+ EXPECT_TRUE(o.has_value());
+}
+#endif // !defined(__EMSCRIPTEN__)
+
} // namespace
+
+#endif // #if !defined(ABSL_USES_STD_OPTIONAL)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span.h
index 911af0c57a6..95fe79262d6 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span.h
@@ -5,7 +5,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -17,32 +17,30 @@
// span.h
// -----------------------------------------------------------------------------
//
-// This header file defines a `Span<T>` type for holding a view of an existing
-// array of data. The `Span` object, much like the `absl::string_view` object,
-// does not own such data itself. A span provides a lightweight way to pass
-// around view of such data.
+// This header file defines a `Span<T>` type for holding a reference to existing
+// array data. The `Span` object, much like the `absl::string_view` object,
+// does not own such data itself, and the data being referenced by the span must
+// outlive the span itself. Unlike `view` type references, a span can hold a
+// reference to mutable data (and can mutate it for underlying types of
+// non-const T.) A span provides a lightweight way to pass a reference to such
+// data.
//
// Additionally, this header file defines `MakeSpan()` and `MakeConstSpan()`
// factory functions, for clearly creating spans of type `Span<T>` or read-only
// `Span<const T>` when such types may be difficult to identify due to issues
// with implicit conversion.
//
-// The C++ standards committee currently has a proposal for a `std::span` type,
-// (http://wg21.link/p0122), which is not yet part of the standard (though may
-// become part of C++20). As of August 2017, the differences between
-// `absl::Span` and this proposal are:
-// * `absl::Span` uses `size_t` for `size_type`
-// * `absl::Span` has no `operator()`
-// * `absl::Span` has no constructors for `std::unique_ptr` or
-// `std::shared_ptr`
+// The C++20 draft standard includes a `std::span` type. As of June 2020, the
+// differences between `absl::Span` and `std::span` are:
+// * `absl::Span` has `operator==` (which is likely a design bug,
+// per https://abseil.io/blog/20180531-regular-types)
// * `absl::Span` has the factory functions `MakeSpan()` and
// `MakeConstSpan()`
-// * `absl::Span` has `front()` and `back()` methods
// * bounds-checked access to `absl::Span` is accomplished with `at()`
// * `absl::Span` has compiler-provided move and copy constructors and
// assignment. This is due to them being specified as `constexpr`, but that
// implies const in C++11.
-// * `absl::Span` has no `element_type` or `index_type` typedefs
+// * `absl::Span` has no `element_type` typedef
// * A read-only `absl::Span<const T>` can be implicitly constructed from an
// initializer list.
// * `absl::Span` has no `bytes()`, `size_bytes()`, `as_bytes()`, or
@@ -60,122 +58,26 @@
#include <cstddef>
#include <initializer_list>
#include <iterator>
-#include <string>
#include <type_traits>
#include <utility>
-#include "absl/algorithm/algorithm.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
#include "absl/base/optimization.h"
-#include "absl/base/port.h"
+#include "absl/base/port.h" // TODO(strel): remove this include
#include "absl/meta/type_traits.h"
+#include "absl/types/internal/span.h"
namespace absl {
-
-template <typename T>
-class Span;
-
-namespace span_internal {
-// A constexpr min function
-constexpr size_t Min(size_t a, size_t b) noexcept { return a < b ? a : b; }
-
-// Wrappers for access to container data pointers.
-template <typename C>
-constexpr auto GetDataImpl(C& c, char) noexcept // NOLINT(runtime/references)
- -> decltype(c.data()) {
- return c.data();
-}
-
-// Before C++17, string::data returns a const char* in all cases.
-inline char* GetDataImpl(std::string& s, // NOLINT(runtime/references)
- int) noexcept {
- return &s[0];
-}
-
-template <typename C>
-constexpr auto GetData(C& c) noexcept // NOLINT(runtime/references)
- -> decltype(GetDataImpl(c, 0)) {
- return GetDataImpl(c, 0);
-}
-
-// Detection idioms for size() and data().
-template <typename C>
-using HasSize =
- std::is_integral<absl::decay_t<decltype(std::declval<C&>().size())>>;
-
-// We want to enable conversion from vector<T*> to Span<const T* const> but
-// disable conversion from vector<Derived> to Span<Base>. Here we use
-// the fact that U** is convertible to Q* const* if and only if Q is the same
-// type or a more cv-qualified version of U. We also decay the result type of
-// data() to avoid problems with classes which have a member function data()
-// which returns a reference.
-template <typename T, typename C>
-using HasData =
- std::is_convertible<absl::decay_t<decltype(GetData(std::declval<C&>()))>*,
- T* const*>;
-
-// Extracts value type from a Container
-template <typename C>
-struct ElementType {
- using type = typename absl::remove_reference_t<C>::value_type;
-};
-
-template <typename T, size_t N>
-struct ElementType<T (&)[N]> {
- using type = T;
-};
-
-template <typename C>
-using ElementT = typename ElementType<C>::type;
-
-template <typename T>
-using EnableIfMutable =
- typename std::enable_if<!std::is_const<T>::value, int>::type;
-
-template <typename T>
-bool EqualImpl(Span<T> a, Span<T> b) {
- static_assert(std::is_const<T>::value, "");
- return absl::equal(a.begin(), a.end(), b.begin(), b.end());
-}
-
-template <typename T>
-bool LessThanImpl(Span<T> a, Span<T> b) {
- static_assert(std::is_const<T>::value, "");
- return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
-}
-
-// The `IsConvertible` classes here are needed because of the
-// `std::is_convertible` bug in libcxx when compiled with GCC. This build
-// configuration is used by Android NDK toolchain. Reference link:
-// https://bugs.llvm.org/show_bug.cgi?id=27538.
-template <typename From, typename To>
-struct IsConvertibleHelper {
- private:
- static std::true_type testval(To);
- static std::false_type testval(...);
-
- public:
- using type = decltype(testval(std::declval<From>()));
-};
-
-template <typename From, typename To>
-struct IsConvertible : IsConvertibleHelper<From, To>::type {};
-
-// TODO(zhangxy): replace `IsConvertible` with `std::is_convertible` once the
-// older version of libcxx is not supported.
-template <typename From, typename To>
-using EnableIfConvertibleToSpanConst =
- typename std::enable_if<IsConvertible<From, Span<const To>>::value>::type;
-} // namespace span_internal
+ABSL_NAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Span
//------------------------------------------------------------------------------
//
-// A `Span` is an "array view" type for holding a view of a contiguous data
-// array; the `Span` object does not and cannot own such data itself. A span
-// provides an easy way to provide overloads for anything operating on
+// A `Span` is an "array reference" type for holding a reference of contiguous
+// array data; the `Span` object does not and cannot own such data itself. A
+// span provides an easy way to provide overloads for anything operating on
// contiguous sequences without needing to manage pointers and array lengths
// manually.
@@ -193,7 +95,8 @@ using EnableIfConvertibleToSpanConst =
// constructors.
//
// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
-// of elements of type `T`. A user of `Span` must ensure that the data being
+// of elements of type `T`, and unlike an `absl::string_view`, a span can hold a
+// reference to mutable data. A user of `Span` must ensure that the data being
// pointed to outlives the `Span` itself.
//
// You can construct a `Span<T>` in several ways:
@@ -223,7 +126,7 @@ using EnableIfConvertibleToSpanConst =
// Note that `Span` objects, in addition to requiring that the memory they
// point to remains alive, must also ensure that such memory does not get
// reallocated. Therefore, to avoid undefined behavior, containers with
-// associated span views should not invoke operations that may reallocate memory
+// associated spans should not invoke operations that may reallocate memory
// (such as resizing) or invalidate iterators into the container.
//
// One common use for a `Span` is when passing arguments to a routine that can
@@ -372,7 +275,7 @@ class Span {
// Returns a reference to the i'th element of this span.
constexpr reference operator[](size_type i) const noexcept {
// MSVC 2015 accepts this as constexpr, but not ptr_[i]
- return *(data() + i);
+ return ABSL_HARDENING_ASSERT(i < size()), *(data() + i);
}
// Span::at()
@@ -388,60 +291,74 @@ class Span {
// Span::front()
//
- // Returns a reference to the first element of this span.
+ // Returns a reference to the first element of this span. The span must not
+ // be empty.
constexpr reference front() const noexcept {
- return ABSL_ASSERT(size() > 0), *data();
+ return ABSL_HARDENING_ASSERT(size() > 0), *data();
}
// Span::back()
//
- // Returns a reference to the last element of this span.
+ // Returns a reference to the last element of this span. The span must not
+ // be empty.
constexpr reference back() const noexcept {
- return ABSL_ASSERT(size() > 0), *(data() + size() - 1);
+ return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1);
}
// Span::begin()
//
- // Returns an iterator to the first element of this span.
+ // Returns an iterator pointing to the first element of this span, or `end()`
+ // if the span is empty.
constexpr iterator begin() const noexcept { return data(); }
// Span::cbegin()
//
- // Returns a const iterator to the first element of this span.
+ // Returns a const iterator pointing to the first element of this span, or
+ // `end()` if the span is empty.
constexpr const_iterator cbegin() const noexcept { return begin(); }
// Span::end()
//
- // Returns an iterator to the last element of this span.
+ // Returns an iterator pointing just beyond the last element at the
+ // end of this span. This iterator acts as a placeholder; attempting to
+ // access it results in undefined behavior.
constexpr iterator end() const noexcept { return data() + size(); }
// Span::cend()
//
- // Returns a const iterator to the last element of this span.
+ // Returns a const iterator pointing just beyond the last element at the
+ // end of this span. This iterator acts as a placeholder; attempting to
+ // access it results in undefined behavior.
constexpr const_iterator cend() const noexcept { return end(); }
// Span::rbegin()
//
- // Returns a reverse iterator starting at the last element of this span.
+ // Returns a reverse iterator pointing to the last element at the end of this
+ // span, or `rend()` if the span is empty.
constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
// Span::crbegin()
//
- // Returns a reverse const iterator starting at the last element of this span.
+ // Returns a const reverse iterator pointing to the last element at the end of
+ // this span, or `crend()` if the span is empty.
constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
// Span::rend()
//
- // Returns a reverse iterator starting at the first element of this span.
+ // Returns a reverse iterator pointing just before the first element
+ // at the beginning of this span. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
constexpr reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
// Span::crend()
//
- // Returns a reverse iterator starting at the first element of this span.
+ // Returns a reverse const iterator pointing just before the first element
+ // at the beginning of this span. This pointer acts as a placeholder;
+ // attempting to access its element results in undefined behavior.
constexpr const_reverse_iterator crend() const noexcept { return rend(); }
// Span mutations
@@ -450,7 +367,7 @@ class Span {
//
// Removes the first `n` elements from the span.
void remove_prefix(size_type n) noexcept {
- assert(size() >= n);
+ ABSL_HARDENING_ASSERT(size() >= n);
ptr_ += n;
len_ -= n;
}
@@ -459,7 +376,7 @@ class Span {
//
// Removes the last `n` elements from the span.
void remove_suffix(size_type n) noexcept {
- assert(size() >= n);
+ ABSL_HARDENING_ASSERT(size() >= n);
len_ -= n;
}
@@ -485,6 +402,40 @@ class Span {
: (base_internal::ThrowStdOutOfRange("pos > size()"), Span());
}
+ // Span::first()
+ //
+ // Returns a `Span` containing first `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).first(1); // {10}
+ // absl::MakeSpan(vec).first(3); // {10, 11, 12}
+ // absl::MakeSpan(vec).first(5); // throws std::out_of_range
+ constexpr Span first(size_type len) const {
+ return (len <= size())
+ ? Span(data(), len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
+ // Span::last()
+ //
+ // Returns a `Span` containing last `len` elements. Parameter `len` is of
+ // type `size_type` and thus non-negative. `len` value must be <= size().
+ //
+ // Examples:
+ //
+ // std::vector<int> vec = {10, 11, 12, 13};
+ // absl::MakeSpan(vec).last(1); // {13}
+ // absl::MakeSpan(vec).last(3); // {11, 12, 13}
+ // absl::MakeSpan(vec).last(5); // throws std::out_of_range
+ constexpr Span last(size_type len) const {
+ return (len <= size())
+ ? Span(size() - len + data(), len)
+ : (base_internal::ThrowStdOutOfRange("len > size()"), Span());
+ }
+
// Support for absl::Hash.
template <typename H>
friend H AbslHashValue(H h, Span v) {
@@ -517,25 +468,27 @@ const typename Span<T>::size_type Span<T>::npos;
// operator==
template <typename T>
bool operator==(Span<T> a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<const T> a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
template <typename T>
bool operator==(Span<T> a, Span<const T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(const U& a, Span<T> b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator==(Span<T> a, const U& b) {
- return span_internal::EqualImpl<const T>(a, b);
+ return span_internal::EqualImpl<Span, const T>(a, b);
}
// operator!=
@@ -551,13 +504,15 @@ template <typename T>
bool operator!=(Span<T> a, Span<const T> b) {
return !(a == b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(const U& a, Span<T> b) {
return !(a == b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator!=(Span<T> a, const U& b) {
return !(a == b);
}
@@ -565,25 +520,27 @@ bool operator!=(Span<T> a, const U& b) {
// operator<
template <typename T>
bool operator<(Span<T> a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<const T> a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
template <typename T>
bool operator<(Span<T> a, Span<const T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(const U& a, Span<T> b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<(Span<T> a, const U& b) {
- return span_internal::LessThanImpl<const T>(a, b);
+ return span_internal::LessThanImpl<Span, const T>(a, b);
}
// operator>
@@ -599,13 +556,15 @@ template <typename T>
bool operator>(Span<T> a, Span<const T> b) {
return b < a;
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(const U& a, Span<T> b) {
return b < a;
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>(Span<T> a, const U& b) {
return b < a;
}
@@ -623,13 +582,15 @@ template <typename T>
bool operator<=(Span<T> a, Span<const T> b) {
return !(b < a);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(const U& a, Span<T> b) {
return !(b < a);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator<=(Span<T> a, const U& b) {
return !(b < a);
}
@@ -647,13 +608,15 @@ template <typename T>
bool operator>=(Span<T> a, Span<const T> b) {
return !(a < b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(const U& a, Span<T> b) {
return !(a < b);
}
-template <typename T, typename U,
- typename = span_internal::EnableIfConvertibleToSpanConst<U, T>>
+template <
+ typename T, typename U,
+ typename = span_internal::EnableIfConvertibleTo<U, absl::Span<const T>>>
bool operator>=(Span<T> a, const U& b) {
return !(a < b);
}
@@ -701,7 +664,7 @@ constexpr Span<T> MakeSpan(T* ptr, size_t size) noexcept {
template <int&... ExplicitArgumentBarrier, typename T>
Span<T> MakeSpan(T* begin, T* end) noexcept {
- return ABSL_ASSERT(begin <= end), Span<T>(begin, end - begin);
+ return ABSL_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin);
}
template <int&... ExplicitArgumentBarrier, typename C>
@@ -746,7 +709,7 @@ constexpr Span<const T> MakeConstSpan(T* ptr, size_t size) noexcept {
template <int&... ExplicitArgumentBarrier, typename T>
Span<const T> MakeConstSpan(T* begin, T* end) noexcept {
- return ABSL_ASSERT(begin <= end), Span<const T>(begin, end - begin);
+ return ABSL_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
}
template <int&... ExplicitArgumentBarrier, typename C>
@@ -758,5 +721,6 @@ template <int&... ExplicitArgumentBarrier, typename T, size_t N>
constexpr Span<const T> MakeConstSpan(const T (&array)[N]) noexcept {
return Span<const T>(array, N);
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_SPAN_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span_test.cc
index bd739ff2a07..2584339bd30 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/span_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -27,6 +27,7 @@
#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/exception_testing.h"
+#include "absl/base/options.h"
#include "absl/container/fixed_array.h"
#include "absl/container/inlined_vector.h"
#include "absl/hash/hash_testing.h"
@@ -35,7 +36,7 @@
namespace {
MATCHER_P(DataIs, data,
- absl::StrCat("data() is ", negation ? "is " : "isn't ",
+ absl::StrCat("data() ", negation ? "isn't " : "is ",
testing::PrintToString(data))) {
return arg.data() == data;
}
@@ -139,8 +140,10 @@ TEST(CharSpan, StringCtor) {
EXPECT_THAT(s_const_abc, SpanIs(abc));
EXPECT_FALSE((std::is_constructible<absl::Span<int>, std::string>::value));
- EXPECT_FALSE((std::is_constructible<absl::Span<const int>, std::string>::value));
- EXPECT_TRUE((std::is_convertible<std::string, absl::Span<const char>>::value));
+ EXPECT_FALSE(
+ (std::is_constructible<absl::Span<const int>, std::string>::value));
+ EXPECT_TRUE(
+ (std::is_convertible<std::string, absl::Span<const char>>::value));
}
TEST(IntSpan, FromConstPointer) {
@@ -230,6 +233,11 @@ TEST(IntSpan, ElementAccess) {
EXPECT_EQ(s.front(), s[0]);
EXPECT_EQ(s.back(), s[9]);
+
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ EXPECT_DEATH_IF_SUPPORTED(s[-1], "");
+ EXPECT_DEATH_IF_SUPPORTED(s[10], "");
+#endif
}
TEST(IntSpan, AtThrows) {
@@ -266,6 +274,13 @@ TEST(IntSpan, RemovePrefixAndSuffix) {
EXPECT_EQ(s.size(), 0);
EXPECT_EQ(v, MakeRamp(20, 1));
+
+#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+ absl::Span<int> prefix_death(v);
+ EXPECT_DEATH_IF_SUPPORTED(prefix_death.remove_prefix(21), "");
+ absl::Span<int> suffix_death(v);
+ EXPECT_DEATH_IF_SUPPORTED(suffix_death.remove_suffix(21), "");
+#endif
}
TEST(IntSpan, Subspan) {
@@ -293,6 +308,38 @@ TEST(IntSpan, Subspan) {
#endif
}
+TEST(IntSpan, First) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).first(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).first(0), SpanIs(ramp.data(), 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).first(3), SpanIs(ramp.data(), 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).first(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).first(11), "");
+#endif
+}
+
+TEST(IntSpan, Last) {
+ std::vector<int> empty;
+ EXPECT_THAT(absl::MakeSpan(empty).last(0), SpanIs(empty));
+
+ auto ramp = MakeRamp(10);
+ EXPECT_THAT(absl::MakeSpan(ramp).last(0), SpanIs(ramp.data() + 10, 0));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(10), SpanIs(ramp));
+ EXPECT_THAT(absl::MakeSpan(ramp).last(3), SpanIs(ramp.data() + 7, 3));
+
+#ifdef ABSL_HAVE_EXCEPTIONS
+ EXPECT_THROW(absl::MakeSpan(ramp).last(11), std::out_of_range);
+#else
+ EXPECT_DEATH_IF_SUPPORTED(absl::MakeSpan(ramp).last(11), "");
+#endif
+}
+
TEST(IntSpan, MakeSpanPtrLength) {
std::vector<int> empty;
auto s_empty = absl::MakeSpan(empty.data(), empty.size());
@@ -767,6 +814,8 @@ TEST(ConstIntSpan, ConstexprTest) {
ABSL_TEST_CONSTEXPR(span.begin());
ABSL_TEST_CONSTEXPR(span.cbegin());
ABSL_TEST_CONSTEXPR(span.subspan(0, 0));
+ ABSL_TEST_CONSTEXPR(span.first(1));
+ ABSL_TEST_CONSTEXPR(span.last(1));
ABSL_TEST_CONSTEXPR(span[0]);
}
@@ -779,4 +828,19 @@ TEST(Span, SpanSize) {
EXPECT_LE(sizeof(absl::Span<BigStruct>), 2 * sizeof(void*));
}
+TEST(Span, Hash) {
+ int array[] = {1, 2, 3, 4};
+ int array2[] = {1, 2, 3};
+ using T = absl::Span<const int>;
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+ {// Empties
+ T(), T(nullptr, 0), T(array, 0), T(array2, 0),
+ // Different array with same value
+ T(array, 3), T(array2), T({1, 2, 3}),
+ // Same array, but different length
+ T(array, 1), T(array, 2),
+ // Same length, but different array
+ T(array + 1, 2), T(array + 2, 2)}));
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant.h
index 48c5d7bf2c2..ac93464bf8d 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -24,7 +24,7 @@
// should always hold a value of one of its alternative types (except in the
// "valueless by exception state" -- see below). A default-constructed
// `absl::variant` will hold the value of its first alternative type, provided
-// it is default-constructable.
+// it is default-constructible.
//
// In exceptional cases due to error, an `absl::variant` can hold no
// value (known as a "valueless by exception" state), though this is not the
@@ -45,11 +45,12 @@
#include "absl/base/config.h"
#include "absl/utility/utility.h"
-#ifdef ABSL_HAVE_STD_VARIANT
+#ifdef ABSL_USES_STD_VARIANT
-#include <variant>
+#include <variant> // IWYU pragma: export
namespace absl {
+ABSL_NAMESPACE_BEGIN
using std::bad_variant_access;
using std::get;
using std::get_if;
@@ -62,9 +63,10 @@ using std::variant_npos;
using std::variant_size;
using std::variant_size_v;
using std::visit;
+ABSL_NAMESPACE_END
} // namespace absl
-#else // ABSL_HAVE_STD_VARIANT
+#else // ABSL_USES_STD_VARIANT
#include <functional>
#include <new>
@@ -77,6 +79,7 @@ using std::visit;
#include "absl/types/internal/variant.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// -----------------------------------------------------------------------------
// absl::variant
@@ -92,7 +95,7 @@ namespace absl {
// // assign it to a std::string.
// absl::variant<int, std::string> v = std::string("abc");
//
-// // A default-contructed variant will hold a value-initialized value of
+// // A default-constructed variant will hold a value-initialized value of
// // the first alternative type.
// auto a = absl::variant<int, std::string>(); // Holds an int of value '0'.
//
@@ -129,7 +132,12 @@ class variant;
// type (in which case, they will be swapped) or to two different types (in
// which case the values will need to be moved).
//
-template <typename... Ts>
+template <
+ typename... Ts,
+ absl::enable_if_t<
+ absl::conjunction<std::is_move_constructible<Ts>...,
+ type_traits_internal::IsSwappable<Ts>...>::value,
+ int> = 0>
void swap(variant<Ts...>& v, variant<Ts...>& w) noexcept(noexcept(v.swap(w))) {
v.swap(w);
}
@@ -596,7 +604,10 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
// emplace() Functions
- // Constructs a value of the given alternative type T within the variant.
+ // Constructs a value of the given alternative type T within the variant. The
+ // existing value of the variant is destroyed first (provided that
+ // `absl::valueless_by_exception()` is false). Requires that T is unambiguous
+ // in the variant.
//
// Example:
//
@@ -616,7 +627,9 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
}
// Constructs a value of the given alternative type T within the variant using
- // an initializer list.
+ // an initializer list. The existing value of the variant is destroyed first
+ // (provided that `absl::valueless_by_exception()` is false). Requires that T
+ // is unambiguous in the variant.
//
// Example:
//
@@ -635,7 +648,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
}
// Destroys the current value of the variant (provided that
- // `absl::valueless_by_exception()` is false, and constructs a new value at
+ // `absl::valueless_by_exception()` is false) and constructs a new value at
// the given index.
//
// Example:
@@ -654,7 +667,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
}
// Destroys the current value of the variant (provided that
- // `absl::valueless_by_exception()` is false, and constructs a new value at
+ // `absl::valueless_by_exception()` is false) and constructs a new value at
// the given index using an initializer list and the provided arguments.
//
// Example:
@@ -688,12 +701,12 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
//
// Swaps the values of two variant objects.
//
- // TODO(calabrese)
- // `variant::swap()` and `swap()` rely on `std::is_(nothrow)_swappable()`
- // which is introduced in C++17. So we assume `is_swappable()` is always
- // true and `is_nothrow_swappable()` is same as `std::is_trivial()`.
void swap(variant& rhs) noexcept(
- absl::conjunction<std::is_trivial<T0>, std::is_trivial<Tn>...>::value) {
+ absl::conjunction<
+ std::is_nothrow_move_constructible<T0>,
+ std::is_nothrow_move_constructible<Tn>...,
+ type_traits_internal::IsNothrowSwappable<T0>,
+ type_traits_internal::IsNothrowSwappable<Tn>...>::value) {
return variant_internal::VisitIndices<sizeof...(Tn) + 1>::Run(
variant_internal::Swap<T0, Tn...>{this, &rhs}, rhs.index());
}
@@ -790,6 +803,7 @@ operator>=(const variant<Types...>& a, const variant<Types...>& b) {
a.index());
}
+ABSL_NAMESPACE_END
} // namespace absl
namespace std {
@@ -807,9 +821,10 @@ struct hash<absl::variant<T...>>
} // namespace std
-#endif // ABSL_HAVE_STD_VARIANT
+#endif // ABSL_USES_STD_VARIANT
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace variant_internal {
// Helper visitor for converting a variant<Ts...>` into another type (mostly
@@ -845,6 +860,7 @@ To ConvertVariantTo(Variant&& variant) {
std::forward<Variant>(variant));
}
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_TYPES_VARIANT_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_benchmark.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_benchmark.cc
index 99658ac70c4..350b1753641 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_benchmark.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_benchmark.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -28,6 +28,7 @@
#include "absl/utility/utility.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
template <std::size_t I>
@@ -217,4 +218,5 @@ BENCHMARK_TEMPLATE(BM_RedundantVisit, 4, 2)
->DenseRange(0, integral_pow(4, 2) - 1);
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_exception_safety_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_exception_safety_test.cc
index 82425dbd190..439c6e1df36 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_exception_safety_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_exception_safety_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -14,6 +14,12 @@
#include "absl/types/variant.h"
+#include "absl/base/config.h"
+
+// This test is a no-op when absl::variant is an alias for std::variant and when
+// exceptions are not enabled.
+#if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
+
#include <iostream>
#include <memory>
#include <utility>
@@ -21,13 +27,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/base/config.h"
#include "absl/base/internal/exception_safety_testing.h"
#include "absl/memory/memory.h"
+
// See comment in absl/base/config.h
#if !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
using ::testing::MakeExceptionSafetyTester;
@@ -231,7 +238,7 @@ TEST(VariantExceptionSafetyTest, CopyAssign) {
}
// libstdc++ std::variant has bugs on copy assignment regarding exception
// safety.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
// index() != j
// if is_nothrow_copy_constructible_v<Tj> or
// !is_nothrow_move_constructible<Tj> is true, equivalent to
@@ -262,7 +269,7 @@ TEST(VariantExceptionSafetyTest, CopyAssign) {
.Test());
EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
}
-#endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
{
// is_nothrow_copy_constructible_v<Tj> == false &&
// is_nothrow_move_constructible_v<Tj> == true
@@ -315,6 +322,12 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
EXPECT_FALSE(tester.WithContracts(strong_guarantee).Test());
}
{
+ // libstdc++ introduced a regression between 2018-09-25 and 2019-01-06.
+ // The fix is targeted for gcc-9.
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87431#c7
+ // https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=267614
+#if !(defined(ABSL_USES_STD_VARIANT) && \
+ defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
// - otherwise (index() != j), equivalent to
// emplace<j>(get<j>(std::move(rhs)))
// - If an exception is thrown during the call to Tj's move construction
@@ -330,6 +343,8 @@ TEST(VariantExceptionSafetyTest, MoveAssign) {
auto copy = rhs;
*lhs = std::move(copy);
}));
+#endif // !(defined(ABSL_USES_STD_VARIANT) &&
+ // defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE == 8)
}
}
@@ -431,7 +446,7 @@ TEST(VariantExceptionSafetyTest, ValueAssign) {
// and operator=(variant&&) invokes Tj's move ctor which doesn't throw.
// libstdc++ std::variant has bugs on conversion assignment regarding
// exception safety.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
{
MoveNothrow rhs;
EXPECT_TRUE(MakeExceptionSafetyTester()
@@ -439,7 +454,7 @@ TEST(VariantExceptionSafetyTest, ValueAssign) {
.WithContracts(VariantInvariants, strong_guarantee)
.Test([&rhs](ThrowingVariant* lhs) { *lhs = rhs; }));
}
-#endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
}
TEST(VariantExceptionSafetyTest, Emplace) {
@@ -509,6 +524,9 @@ TEST(VariantExceptionSafetyTest, Swap) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
#endif // !defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
+
+#endif // #if !defined(ABSL_USES_STD_VARIANT) && defined(ABSL_HAVE_EXCEPTIONS)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_test.cc
index f47f3a728dc..cf237334da0 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/types/variant_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -19,6 +19,9 @@
#include "absl/types/variant.h"
+// This test is a no-op when absl::variant is an alias for std::variant.
+#if !defined(ABSL_USES_STD_VARIANT)
+
#include <algorithm>
#include <cstddef>
#include <functional>
@@ -47,7 +50,7 @@
#else
#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
- EXPECT_DEATH(expr, text)
+ EXPECT_DEATH_IF_SUPPORTED(expr, text)
#endif // ABSL_HAVE_EXCEPTIONS
@@ -67,6 +70,7 @@ struct hash<Hashable> {
struct NonHashable {};
namespace absl {
+ABSL_NAMESPACE_BEGIN
namespace {
using ::testing::DoubleEq;
@@ -257,7 +261,7 @@ class NonCopyable {
// each type.
template <typename T>
class VariantTypesTest : public ::testing::Test {};
-TYPED_TEST_CASE(VariantTypesTest, VariantTypes);
+TYPED_TEST_SUITE(VariantTypesTest, VariantTypes);
////////////////////
// [variant.ctor] //
@@ -384,7 +388,7 @@ struct MoveOnly {
TEST(VariantTest, TestMoveConstruct) {
using V = variant<MoveOnly<class A>, MoveOnly<class B>, MoveOnly<class C>>;
- V v(in_place_index_t<1>{}, 10);
+ V v(in_place_index<1>, 10);
V v2 = absl::move(v);
EXPECT_EQ(10, absl::get<1>(v2).value);
}
@@ -460,6 +464,11 @@ TYPED_TEST(VariantTypesTest, TestValueCtor) {
EXPECT_EQ(value.value, mutable_valptr->value);
}
+TEST(VariantTest, AmbiguousValueConstructor) {
+ EXPECT_FALSE((std::is_convertible<int, absl::variant<int, int>>::value));
+ EXPECT_FALSE((std::is_constructible<absl::variant<int, int>, int>::value));
+}
+
TEST(VariantTest, InPlaceType) {
using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
@@ -483,14 +492,47 @@ TEST(VariantTest, InPlaceType) {
EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
}
+TEST(VariantTest, InPlaceTypeVariableTemplate) {
+ using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+ Var v1(in_place_type<int>, 7);
+ ASSERT_TRUE(absl::holds_alternative<int>(v1));
+ EXPECT_EQ(7, absl::get<int>(v1));
+
+ Var v2(in_place_type<std::string>, "ABC");
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+ EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+ Var v3(in_place_type<std::string>, "ABC", 2);
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+ EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+ Var v4(in_place_type<NonCopyable>);
+ ASSERT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+ Var v5(in_place_type<std::vector<int>>, {1, 2, 3});
+ ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+ EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
TEST(VariantTest, InPlaceTypeInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
Var v1(in_place_type_t<MoveOnlyWithListConstructor>(), {1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
}
+TEST(VariantTest, InPlaceTypeInitializerListVariabletemplate) {
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+ Var v1(in_place_type<MoveOnlyWithListConstructor>, {1, 2, 3, 4, 5}, 6);
+ ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+ EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
TEST(VariantTest, InPlaceIndex) {
using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
@@ -518,14 +560,51 @@ TEST(VariantTest, InPlaceIndex) {
EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
}
+TEST(VariantTest, InPlaceIndexVariableTemplate) {
+ using Var = variant<int, std::string, NonCopyable, std::vector<int>>;
+
+ Var v1(in_place_index<0>, 7);
+ ASSERT_TRUE(absl::holds_alternative<int>(v1));
+ EXPECT_EQ(7, absl::get<int>(v1));
+
+ Var v2(in_place_index<1>, "ABC");
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v2));
+ EXPECT_EQ("ABC", absl::get<std::string>(v2));
+
+ Var v3(in_place_index<1>, "ABC", 2);
+ ASSERT_TRUE(absl::holds_alternative<std::string>(v3));
+ EXPECT_EQ("AB", absl::get<std::string>(v3));
+
+ Var v4(in_place_index<2>);
+ EXPECT_TRUE(absl::holds_alternative<NonCopyable>(v4));
+
+ // Verify that a variant with only non-copyables can still be constructed.
+ EXPECT_TRUE(absl::holds_alternative<NonCopyable>(
+ variant<NonCopyable>(in_place_index<0>)));
+
+ Var v5(in_place_index<3>, {1, 2, 3});
+ ASSERT_TRUE(absl::holds_alternative<std::vector<int>>(v5));
+ EXPECT_THAT(absl::get<std::vector<int>>(v5), ::testing::ElementsAre(1, 2, 3));
+}
+
TEST(VariantTest, InPlaceIndexInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
Var v1(in_place_index_t<3>(), {1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
}
+TEST(VariantTest, InPlaceIndexInitializerListVariableTemplate) {
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+
+ Var v1(in_place_index<3>, {1, 2, 3, 4, 5}, 6);
+ ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
+ EXPECT_EQ(6, absl::get<MoveOnlyWithListConstructor>(v1).value);
+}
+
////////////////////
// [variant.dtor] //
////////////////////
@@ -559,6 +638,7 @@ TEST(VariantTest, TestDtor) {
}
#ifdef ABSL_HAVE_EXCEPTIONS
+
// See comment in absl/base/config.h
#if defined(ABSL_INTERNAL_MSVC_2017_DBG_MODE)
TEST(VariantTest, DISABLED_TestDtorValuelessByException)
@@ -573,7 +653,7 @@ TEST(VariantTest, TestDtorValuelessByException)
{
using Variant = VariantFactory<IncrementInDtor>::Type;
- Variant v(in_place_index_t<0>(), counter_adjuster);
+ Variant v(in_place_index<0>, counter_adjuster);
EXPECT_EQ(0, counter);
ToValuelessByException(v);
@@ -599,7 +679,7 @@ TEST(VariantTest, TestSelfAssignment) {
object.operator=(object);
EXPECT_EQ(0, counter);
- // A std::string long enough that it's likely to defeat any inline representation
+ // A string long enough that it's likely to defeat any inline representation
// optimization.
const std::string long_str(128, 'a');
@@ -763,7 +843,7 @@ TEST(VariantTest, TestBackupAssign) {
}
// libstdc++ doesn't pass this test
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
EXPECT_EQ(3, counter[0]);
EXPECT_EQ(2, counter[1]);
EXPECT_EQ(2, counter[2]);
@@ -807,7 +887,7 @@ TEST(VariantTest, TestBackupAssign) {
TEST(VariantTest, TestEmplaceBasic) {
using Variant = variant<int, char>;
- Variant v(absl::in_place_index_t<0>{}, 0);
+ Variant v(absl::in_place_index<0>, 0);
{
char& emplace_result = v.emplace<char>();
@@ -831,9 +911,10 @@ TEST(VariantTest, TestEmplaceBasic) {
}
TEST(VariantTest, TestEmplaceInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
- Var v1(absl::in_place_index_t<0>{}, 555);
+ Var v1(absl::in_place_index<0>, 555);
MoveOnlyWithListConstructor& emplace_result =
v1.emplace<MoveOnlyWithListConstructor>({1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -844,7 +925,7 @@ TEST(VariantTest, TestEmplaceInitializerList) {
TEST(VariantTest, TestEmplaceIndex) {
using Variant = variant<int, char>;
- Variant v(absl::in_place_index_t<0>{}, 555);
+ Variant v(absl::in_place_index<0>, 555);
{
char& emplace_result = v.emplace<1>();
@@ -868,9 +949,10 @@ TEST(VariantTest, TestEmplaceIndex) {
}
TEST(VariantTest, TestEmplaceIndexInitializerList) {
- using Var = variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
+ using Var =
+ variant<int, std::string, NonCopyable, MoveOnlyWithListConstructor>;
- Var v1(absl::in_place_index_t<0>{}, 555);
+ Var v1(absl::in_place_index<0>, 555);
MoveOnlyWithListConstructor& emplace_result =
v1.emplace<3>({1, 2, 3, 4, 5}, 6);
ASSERT_TRUE(absl::holds_alternative<MoveOnlyWithListConstructor>(v1));
@@ -919,7 +1001,7 @@ TEST(VariantTest, NotValuelessByException) {
TEST(VariantTest, IndexValuelessByException) {
using Var = variant<MoveCanThrow, std::string, double>;
- Var v(absl::in_place_index_t<0>{});
+ Var v(absl::in_place_index<0>);
EXPECT_EQ(0, v.index());
ToValuelessByException(v);
EXPECT_EQ(absl::variant_npos, v.index());
@@ -930,7 +1012,7 @@ TEST(VariantTest, IndexValuelessByException) {
TEST(VariantTest, ValuelessByException) {
using Var = variant<MoveCanThrow, std::string, double>;
- Var v(absl::in_place_index_t<0>{});
+ Var v(absl::in_place_index<0>);
EXPECT_FALSE(v.valueless_by_exception());
ToValuelessByException(v);
EXPECT_TRUE(v.valueless_by_exception());
@@ -961,8 +1043,6 @@ TEST(VariantTest, MemberSwap) {
using V = variant<MoveCanThrow, std::string, int>;
int i = 33;
std::string s = "abc";
- V valueless(in_place_index_t<0>{});
- ToValuelessByException(valueless);
{
// lhs and rhs holds different alternative
V lhs(i), rhs(s);
@@ -970,6 +1050,9 @@ TEST(VariantTest, MemberSwap) {
EXPECT_THAT(lhs, VariantWith<std::string>(s));
EXPECT_THAT(rhs, VariantWith<int>(i));
}
+#ifdef ABSL_HAVE_EXCEPTIONS
+ V valueless(in_place_index<0>);
+ ToValuelessByException(valueless);
{
// lhs is valueless
V lhs(valueless), rhs(i);
@@ -991,6 +1074,7 @@ TEST(VariantTest, MemberSwap) {
EXPECT_TRUE(lhs.valueless_by_exception());
EXPECT_TRUE(rhs.valueless_by_exception());
}
+#endif // ABSL_HAVE_EXCEPTIONS
}
//////////////////////
@@ -1122,7 +1206,7 @@ TEST(VariantTest, GetIndex) {
using Var = variant<int, std::string, double, int>;
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
using LValueGetType = decltype(absl::get<0>(v));
using RValueGetType = decltype(absl::get<0>(absl::move(v)));
@@ -1182,7 +1266,7 @@ TEST(VariantTest, GetIndex) {
}
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
v.emplace<3>(1);
using LValueGetType = decltype(absl::get<3>(v));
@@ -1306,7 +1390,8 @@ TEST(VariantTest, BadGetType) {
absl::get<std::string>(std::move(v)));
const Var& const_v = v;
- ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(absl::get<std::string>(const_v));
+ ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
+ absl::get<std::string>(const_v));
ABSL_VARIANT_TEST_EXPECT_BAD_VARIANT_ACCESS(
absl::get<std::string>(std::move(const_v))); // NOLINT
}
@@ -1328,7 +1413,7 @@ TEST(VariantTest, GetIfIndex) {
using Var = variant<int, std::string, double, int>;
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
EXPECT_TRUE(noexcept(absl::get_if<0>(&v)));
{
@@ -1363,7 +1448,8 @@ TEST(VariantTest, GetIfIndex) {
EXPECT_EQ(*elem, 0);
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1472,7 +1558,8 @@ TEST(VariantTest, GetIfIndex) {
}
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1484,7 +1571,7 @@ TEST(VariantTest, GetIfIndex) {
}
{
- Var v(absl::in_place_index_t<0>{}, 0);
+ Var v(absl::in_place_index<0>, 0);
v.emplace<3>(1);
EXPECT_TRUE(noexcept(absl::get_if<3>(&v)));
@@ -1525,7 +1612,8 @@ TEST(VariantTest, GetIfIndex) {
}
{
auto* bad_elem = absl::get_if<1>(&const_v);
- EXPECT_TRUE((std::is_same<decltype(bad_elem), const std::string*>::value));
+ EXPECT_TRUE(
+ (std::is_same<decltype(bad_elem), const std::string*>::value));
EXPECT_EQ(bad_elem, nullptr);
}
{
@@ -1629,8 +1717,8 @@ TEST(VariantTest, OperatorRelational) {
TEST(VariantTest, ValuelessOperatorEquals) {
variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
- valueless(absl::in_place_index_t<0>{}),
- other_valueless(absl::in_place_index_t<0>{});
+ valueless(absl::in_place_index<0>),
+ other_valueless(absl::in_place_index<0>);
ToValuelessByException(valueless);
ToValuelessByException(other_valueless);
@@ -1651,8 +1739,8 @@ TEST(VariantTest, ValuelessOperatorEquals) {
TEST(VariantTest, ValuelessOperatorRelational) {
variant<MoveCanThrow, std::string> int_v(1), string_v("Hello"),
- valueless(absl::in_place_index_t<0>{}),
- other_valueless(absl::in_place_index_t<0>{});
+ valueless(absl::in_place_index<0>),
+ other_valueless(absl::in_place_index<0>);
ToValuelessByException(valueless);
ToValuelessByException(other_valueless);
@@ -1711,8 +1799,8 @@ TEST(VariantTest, VisitSimple) {
EXPECT_EQ("B", piece);
struct StrLen {
- int operator()(const std::string& s) const { return s.size(); }
int operator()(const char* s) const { return strlen(s); }
+ int operator()(const std::string& s) const { return s.size(); }
};
v = "SomeStr";
@@ -1728,9 +1816,13 @@ TEST(VariantTest, VisitRValue) {
bool operator()(std::string&&) const { return true; } // NOLINT
int operator()(const std::string&, const std::string&) const { return 0; }
- int operator()(const std::string&, std::string&&) const { return 1; } // NOLINT
- int operator()(std::string&&, const std::string&) const { return 2; } // NOLINT
- int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT
+ int operator()(const std::string&, std::string&&) const {
+ return 1;
+ } // NOLINT
+ int operator()(std::string&&, const std::string&) const {
+ return 2;
+ } // NOLINT
+ int operator()(std::string&&, std::string&&) const { return 3; } // NOLINT
};
EXPECT_FALSE(absl::visit(Visitor{}, v));
EXPECT_TRUE(absl::visit(Visitor{}, absl::move(v)));
@@ -1806,9 +1898,9 @@ TEST(VariantTest, VisitVariadic) {
EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
B(std::unique_ptr<int>(new int(7)))),
::testing::Pair(5, 7));
- EXPECT_THAT(
- absl::visit(Visitor(), A(std::string("BBBBB")), B(absl::string_view("ABC"))),
- ::testing::Pair(5, 3));
+ EXPECT_THAT(absl::visit(Visitor(), A(std::string("BBBBB")),
+ B(absl::string_view("ABC"))),
+ ::testing::Pair(5, 3));
}
TEST(VariantTest, VisitNoArgs) {
@@ -1842,7 +1934,7 @@ TEST(VariantTest, VisitReferenceWrapper) {
}
// libstdc++ std::variant doesn't support the INVOKE semantics.
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
TEST(VariantTest, VisitMemberFunction) {
absl::variant<std::unique_ptr<Class>> p(absl::make_unique<Class>());
absl::variant<std::unique_ptr<const Class>> cp(
@@ -1866,7 +1958,7 @@ TEST(VariantTest, VisitDataMember) {
EXPECT_EQ(42, absl::visit(&Class::member, cp));
}
-#endif // !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#endif // !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
/////////////////////////
// [variant.monostate] //
@@ -1944,7 +2036,7 @@ TEST(VariantTest, NonmemberSwap) {
std::swap(a, b);
EXPECT_THAT(a, VariantWith<SpecialSwap>(v2));
EXPECT_THAT(b, VariantWith<SpecialSwap>(v1));
-#ifndef ABSL_HAVE_STD_VARIANT
+#ifndef ABSL_USES_STD_VARIANT
EXPECT_FALSE(absl::get<SpecialSwap>(a).special_swap);
#endif
@@ -1977,42 +2069,30 @@ TEST(VariantTest, MonostateHash) {
}
TEST(VariantTest, Hash) {
- static_assert(type_traits_internal::IsHashEnabled<variant<int>>::value, "");
- static_assert(type_traits_internal::IsHashEnabled<variant<Hashable>>::value,
+ static_assert(type_traits_internal::IsHashable<variant<int>>::value, "");
+ static_assert(type_traits_internal::IsHashable<variant<Hashable>>::value, "");
+ static_assert(type_traits_internal::IsHashable<variant<int, Hashable>>::value,
"");
- static_assert(
- type_traits_internal::IsHashEnabled<variant<int, Hashable>>::value, "");
-
-#if defined(_MSC_VER) || \
- (defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 4000 && \
- _LIBCPP_STD_VER > 11) || \
- defined(__APPLE__)
- // For MSVC and libc++ (< 4.0 and c++14), std::hash primary template has a
- // static_assert to catch any user-defined type T that doesn't provide a hash
- // specialization. So instantiating std::hash<variant<T>> will result
- // in a hard error which is not SFINAE friendly.
-#define ABSL_STD_HASH_NOT_SFINAE_FRIENDLY 1
-#endif
-#ifndef ABSL_STD_HASH_NOT_SFINAE_FRIENDLY
- static_assert(
- !type_traits_internal::IsHashEnabled<variant<NonHashable>>::value, "");
- static_assert(!type_traits_internal::IsHashEnabled<
- variant<Hashable, NonHashable>>::value,
+#if ABSL_META_INTERNAL_STD_HASH_SFINAE_FRIENDLY_
+ static_assert(!type_traits_internal::IsHashable<variant<NonHashable>>::value,
"");
+ static_assert(
+ !type_traits_internal::IsHashable<variant<Hashable, NonHashable>>::value,
+ "");
#endif
// MSVC std::hash<std::variant> does not use the index, thus produce the same
// result on the same value as different alternative.
-#if !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+#if !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
{
// same value as different alternative
- variant<int, int> v0(in_place_index_t<0>{}, 42);
- variant<int, int> v1(in_place_index_t<1>{}, 42);
+ variant<int, int> v0(in_place_index<0>, 42);
+ variant<int, int> v1(in_place_index<1>, 42);
std::hash<variant<int, int>> hash;
EXPECT_NE(hash(v0), hash(v1));
}
-#endif // !(defined(_MSC_VER) && defined(ABSL_HAVE_STD_VARIANT))
+#endif // !(defined(_MSC_VER) && defined(ABSL_USES_STD_VARIANT))
{
std::hash<variant<int>> hash;
@@ -2023,11 +2103,10 @@ TEST(VariantTest, Hash) {
EXPECT_GT(hashcodes.size(), 90);
// test const-qualified
+ static_assert(type_traits_internal::IsHashable<variant<const int>>::value,
+ "");
static_assert(
- type_traits_internal::IsHashEnabled<variant<const int>>::value, "");
- static_assert(
- type_traits_internal::IsHashEnabled<variant<const Hashable>>::value,
- "");
+ type_traits_internal::IsHashable<variant<const Hashable>>::value, "");
std::hash<absl::variant<const int>> c_hash;
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(hash(i), c_hash(i));
@@ -2039,7 +2118,8 @@ TEST(VariantTest, Hash) {
// Miscellaneous and deprecated tests //
////////////////////////////////////////
-// Test that a set requiring a basic type conversion works correctly.
+// Test that a set requiring a basic type conversion works correctly
+#if !defined(ABSL_USES_STD_VARIANT)
TEST(VariantTest, TestConvertingSet) {
typedef variant<double> Variant;
Variant v(1.0);
@@ -2049,6 +2129,7 @@ TEST(VariantTest, TestConvertingSet) {
ASSERT_TRUE(nullptr != absl::get_if<double>(&v));
EXPECT_DOUBLE_EQ(2, absl::get<double>(v));
}
+#endif // ABSL_USES_STD_VARIANT
// Test that a vector of variants behaves reasonably.
TEST(VariantTest, Container) {
@@ -2176,7 +2257,8 @@ TEST(VariantTest, TestImplicitConversion) {
// We still need the explicit cast for std::string, because C++ won't apply
// two user-defined implicit conversions in a row.
- EXPECT_TRUE(absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
+ EXPECT_TRUE(
+ absl::holds_alternative<std::string>(PassThrough(std::string("foo"))));
}
struct Convertible2;
@@ -2199,8 +2281,10 @@ struct Convertible2 {
};
TEST(VariantTest, TestRvalueConversion) {
+#if !defined(ABSL_USES_STD_VARIANT)
variant<double, std::string> var(
- ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(0)));
+ ConvertVariantTo<variant<double, std::string>>(
+ variant<std::string, int>(0)));
ASSERT_TRUE(absl::holds_alternative<double>(var));
EXPECT_EQ(0.0, absl::get<double>(var));
@@ -2227,9 +2311,11 @@ TEST(VariantTest, TestRvalueConversion) {
ASSERT_TRUE(absl::holds_alternative<int32_t>(variant2));
EXPECT_EQ(42, absl::get<int32_t>(variant2));
- variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+ variant2 =
+ ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+#endif // !ABSL_USES_STD_VARIANT
variant<Convertible1, Convertible2> variant3(
ConvertVariantTo<variant<Convertible1, Convertible2>>(
@@ -2242,6 +2328,7 @@ TEST(VariantTest, TestRvalueConversion) {
}
TEST(VariantTest, TestLvalueConversion) {
+#if !defined(ABSL_USES_STD_VARIANT)
variant<std::string, int> source1 = 0;
variant<double, std::string> destination(
ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2278,6 +2365,7 @@ TEST(VariantTest, TestLvalueConversion) {
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
ASSERT_TRUE(absl::holds_alternative<uint32_t>(variant2));
EXPECT_EQ(42, absl::get<uint32_t>(variant2));
+#endif
variant<Convertible2, Convertible1> source7((Convertible1()));
variant<Convertible1, Convertible2> variant3(
@@ -2292,7 +2380,8 @@ TEST(VariantTest, TestLvalueConversion) {
TEST(VariantTest, TestMoveConversion) {
using Variant =
variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
- using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
Variant var(
ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(0)}));
@@ -2300,8 +2389,8 @@ TEST(VariantTest, TestMoveConversion) {
ASSERT_NE(absl::get<std::unique_ptr<const int>>(var), nullptr);
EXPECT_EQ(0, *absl::get<std::unique_ptr<const int>>(var));
- var =
- ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+ var = ConvertVariantTo<Variant>(
+ OtherVariant(absl::make_unique<std::string>("foo")));
ASSERT_TRUE(absl::holds_alternative<std::unique_ptr<const std::string>>(var));
EXPECT_EQ("foo", *absl::get<std::unique_ptr<const std::string>>(var));
}
@@ -2312,7 +2401,8 @@ TEST(VariantTest, DoesNotMoveFromLvalues) {
// whether moving or copying has occurred.
using Variant =
variant<std::shared_ptr<const int>, std::shared_ptr<const std::string>>;
- using OtherVariant = variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::shared_ptr<int>, std::shared_ptr<std::string>>;
Variant v1(std::make_shared<const int>(0));
@@ -2340,8 +2430,10 @@ TEST(VariantTest, DoesNotMoveFromLvalues) {
}
TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
+#if !defined(ABSL_USES_STD_VARIANT)
variant<double, std::string> var(
- ConvertVariantTo<variant<double, std::string>>(variant<std::string, int>(3)));
+ ConvertVariantTo<variant<double, std::string>>(
+ variant<std::string, int>(3)));
EXPECT_THAT(absl::get_if<double>(&var), Pointee(3.0));
var = ConvertVariantTo<variant<double, std::string>>(
@@ -2362,8 +2454,10 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
ConvertVariantTo<variant<int32_t, uint32_t>>(variant<int32_t>(42)));
EXPECT_THAT(absl::get_if<int32_t>(&variant2), Pointee(42));
- variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
+ variant2 =
+ ConvertVariantTo<variant<int32_t, uint32_t>>(variant<uint32_t>(42));
EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+#endif
variant<Convertible1, Convertible2> variant3(
ConvertVariantTo<variant<Convertible1, Convertible2>>(
@@ -2376,6 +2470,7 @@ TEST(VariantTest, TestRvalueConversionViaConvertVariantTo) {
}
TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
+#if !defined(ABSL_USES_STD_VARIANT)
variant<std::string, int> source1 = 3;
variant<double, std::string> destination(
ConvertVariantTo<variant<double, std::string>>(source1));
@@ -2383,7 +2478,8 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
variant<const char*, float> source2 = "foo";
destination = ConvertVariantTo<variant<double, std::string>>(source2);
- EXPECT_THAT(absl::get_if<std::string>(&destination), Pointee(std::string("foo")));
+ EXPECT_THAT(absl::get_if<std::string>(&destination),
+ Pointee(std::string("foo")));
variant<int, float> source3(42);
variant<double> singleton(ConvertVariantTo<variant<double>>(source3));
@@ -2406,6 +2502,7 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
variant<uint32_t> source6(42);
variant2 = ConvertVariantTo<variant<int32_t, uint32_t>>(source6);
EXPECT_THAT(absl::get_if<uint32_t>(&variant2), Pointee(42));
+#endif // !ABSL_USES_STD_VARIANT
variant<Convertible2, Convertible1> source7((Convertible1()));
variant<Convertible1, Convertible2> variant3(
@@ -2420,15 +2517,16 @@ TEST(VariantTest, TestLvalueConversionViaConvertVariantTo) {
TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
using Variant =
variant<std::unique_ptr<const int>, std::unique_ptr<const std::string>>;
- using OtherVariant = variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
+ using OtherVariant =
+ variant<std::unique_ptr<int>, std::unique_ptr<std::string>>;
Variant var(
ConvertVariantTo<Variant>(OtherVariant{absl::make_unique<int>(3)}));
EXPECT_THAT(absl::get_if<std::unique_ptr<const int>>(&var),
Pointee(Pointee(3)));
- var =
- ConvertVariantTo<Variant>(OtherVariant(absl::make_unique<std::string>("foo")));
+ var = ConvertVariantTo<Variant>(
+ OtherVariant(absl::make_unique<std::string>("foo")));
EXPECT_THAT(absl::get_if<std::unique_ptr<const std::string>>(&var),
Pointee(Pointee(std::string("foo"))));
}
@@ -2438,7 +2536,7 @@ TEST(VariantTest, TestMoveConversionViaConvertVariantTo) {
// standard and we know that libstdc++ variant doesn't have this feature.
// For more details see the paper:
// http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0602r0.html
-#if !(defined(ABSL_HAVE_STD_VARIANT) && defined(__GLIBCXX__))
+#if !(defined(ABSL_USES_STD_VARIANT) && defined(__GLIBCXX__))
#define ABSL_VARIANT_PROPAGATE_COPY_MOVE_TRIVIALITY 1
#endif
@@ -2598,7 +2696,7 @@ TEST(VariantTest, MoveCtorBug) {
};
{
using V = absl::variant<TrivialCopyNontrivialMove, int>;
- V v1(absl::in_place_index_t<0>{});
+ V v1(absl::in_place_index<0>);
// this should invoke the move ctor, rather than the trivial copy ctor.
V v2(std::move(v1));
EXPECT_TRUE(absl::get<0>(v2).called);
@@ -2606,7 +2704,7 @@ TEST(VariantTest, MoveCtorBug) {
{
// this case failed to compile before our fix due to a GCC bug.
using V = absl::variant<int, TrivialCopyNontrivialMove>;
- V v1(absl::in_place_index_t<1>{});
+ V v1(absl::in_place_index<1>);
// this should invoke the move ctor, rather than the trivial copy ctor.
V v2(std::move(v1));
EXPECT_TRUE(absl::get<1>(v2).called);
@@ -2614,4 +2712,7 @@ TEST(VariantTest, MoveCtorBug) {
}
} // namespace
+ABSL_NAMESPACE_END
} // namespace absl
+
+#endif // #if !defined(ABSL_USES_STD_VARIANT)
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/BUILD.bazel b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/BUILD.bazel
index 5185ccd8421..02b2c407f84 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/BUILD.bazel
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/BUILD.bazel
@@ -1,17 +1,38 @@
+#
+# Copyright 2019 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
+ "ABSL_DEFAULT_LINKOPTS",
"ABSL_TEST_COPTS",
)
package(default_visibility = ["//visibility:public"])
-licenses(["notice"]) # Apache 2.0
+licenses(["notice"])
cc_library(
name = "utility",
- hdrs = ["utility.h"],
+ hdrs = [
+ "utility.h",
+ ],
copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:base_internal",
"//absl/base:config",
@@ -23,6 +44,7 @@ cc_test(
name = "utility_test",
srcs = ["utility_test.cc"],
copts = ABSL_TEST_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":utility",
"//absl/base:core_headers",
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility.h b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility.h
index aef4baa02dc..bf9232209a9 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility.h
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility.h
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -25,6 +25,7 @@
// * index_sequence_for<Ts...> == std::index_sequence_for<Ts...>
// * apply<Functor, Tuple> == std::apply<Functor, Tuple>
// * exchange<T> == std::exchange<T>
+// * make_from_tuple<T> == std::make_from_tuple<T>
//
// This header file also provides the tag types `in_place_t`, `in_place_type_t`,
// and `in_place_index_t`, as well as the constant `in_place`, and
@@ -32,10 +33,9 @@
//
// References:
//
-// http://en.cppreference.com/w/cpp/utility/integer_sequence
-// http://en.cppreference.com/w/cpp/utility/apply
+// https://en.cppreference.com/w/cpp/utility/integer_sequence
+// https://en.cppreference.com/w/cpp/utility/apply
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3658.html
-//
#ifndef ABSL_UTILITY_UTILITY_H_
#define ABSL_UTILITY_UTILITY_H_
@@ -51,6 +51,7 @@
#include "absl/meta/type_traits.h"
namespace absl {
+ABSL_NAMESPACE_BEGIN
// integer_sequence
//
@@ -114,6 +115,20 @@ struct Gen<T, 0> {
using type = integer_sequence<T>;
};
+template <typename T>
+struct InPlaceTypeTag {
+ explicit InPlaceTypeTag() = delete;
+ InPlaceTypeTag(const InPlaceTypeTag&) = delete;
+ InPlaceTypeTag& operator=(const InPlaceTypeTag&) = delete;
+};
+
+template <size_t I>
+struct InPlaceIndexTag {
+ explicit InPlaceIndexTag() = delete;
+ InPlaceIndexTag(const InPlaceIndexTag&) = delete;
+ InPlaceIndexTag& operator=(const InPlaceIndexTag&) = delete;
+};
+
} // namespace utility_internal
// Compile-time sequences of integers
@@ -144,12 +159,12 @@ using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
// Tag types
-#ifdef ABSL_HAVE_STD_OPTIONAL
+#ifdef ABSL_USES_STD_OPTIONAL
using std::in_place_t;
using std::in_place;
-#else // ABSL_HAVE_STD_OPTIONAL
+#else // ABSL_USES_STD_OPTIONAL
// in_place_t
//
@@ -160,9 +175,10 @@ struct in_place_t {};
ABSL_INTERNAL_INLINE_CONSTEXPR(in_place_t, in_place, {});
-#endif // ABSL_HAVE_STD_OPTIONAL
+#endif // ABSL_USES_STD_OPTIONAL
-#if defined(ABSL_HAVE_STD_ANY) || defined(ABSL_HAVE_STD_VARIANT)
+#if defined(ABSL_USES_STD_ANY) || defined(ABSL_USES_STD_VARIANT)
+using std::in_place_type;
using std::in_place_type_t;
#else
@@ -172,10 +188,14 @@ using std::in_place_type_t;
// be specified, such as with `absl::any`, designed to be a drop-in replacement
// for C++17's `std::in_place_type_t`.
template <typename T>
-struct in_place_type_t {};
-#endif // ABSL_HAVE_STD_ANY || ABSL_HAVE_STD_VARIANT
+using in_place_type_t = void (*)(utility_internal::InPlaceTypeTag<T>);
-#ifdef ABSL_HAVE_STD_VARIANT
+template <typename T>
+void in_place_type(utility_internal::InPlaceTypeTag<T>) {}
+#endif // ABSL_USES_STD_ANY || ABSL_USES_STD_VARIANT
+
+#ifdef ABSL_USES_STD_VARIANT
+using std::in_place_index;
using std::in_place_index_t;
#else
@@ -185,8 +205,11 @@ using std::in_place_index_t;
// be specified, such as with `absl::any`, designed to be a drop-in replacement
// for C++17's `std::in_place_index_t`.
template <size_t I>
-struct in_place_index_t {};
-#endif // ABSL_HAVE_STD_VARIANT
+using in_place_index_t = void (*)(utility_internal::InPlaceIndexTag<I>);
+
+template <size_t I>
+void in_place_index(utility_internal::InPlaceIndexTag<I>) {}
+#endif // ABSL_USES_STD_VARIANT
// Constexpr move and forward
@@ -213,10 +236,10 @@ namespace utility_internal {
// Helper method for expanding tuple into a called method.
template <typename Functor, typename Tuple, std::size_t... Indexes>
auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
- -> decltype(absl::base_internal::Invoke(
+ -> decltype(absl::base_internal::invoke(
absl::forward<Functor>(functor),
std::get<Indexes>(absl::forward<Tuple>(t))...)) {
- return absl::base_internal::Invoke(
+ return absl::base_internal::invoke(
absl::forward<Functor>(functor),
std::get<Indexes>(absl::forward<Tuple>(t))...);
}
@@ -234,25 +257,33 @@ auto apply_helper(Functor&& functor, Tuple&& t, index_sequence<Indexes...>)
//
// Example:
//
-// class Foo{void Bar(int);};
-// void user_function(int, string);
-// void user_function(std::unique_ptr<Foo>);
+// class Foo {
+// public:
+// void Bar(int);
+// };
+// void user_function1(int, std::string);
+// void user_function2(std::unique_ptr<Foo>);
+// auto user_lambda = [](int, int) {};
//
// int main()
// {
-// std::tuple<int, string> tuple1(42, "bar");
-// // Invokes the user function overload on int, string.
-// absl::apply(&user_function, tuple1);
+// std::tuple<int, std::string> tuple1(42, "bar");
+// // Invokes the first user function on int, std::string.
+// absl::apply(&user_function1, tuple1);
//
-// auto foo = absl::make_unique<Foo>();
-// std::tuple<Foo*, int> tuple2(foo.get(), 42);
-// // Invokes the method Bar on foo with one argument 42.
-// absl::apply(&Foo::Bar, foo.get(), 42);
-//
-// std::tuple<std::unique_ptr<Foo>> tuple3(absl::make_unique<Foo>());
+// std::tuple<std::unique_ptr<Foo>> tuple2(absl::make_unique<Foo>());
// // Invokes the user function that takes ownership of the unique
// // pointer.
-// absl::apply(&user_function, std::move(tuple));
+// absl::apply(&user_function2, std::move(tuple2));
+//
+// auto foo = absl::make_unique<Foo>();
+// std::tuple<Foo*, int> tuple3(foo.get(), 42);
+// // Invokes the method Bar on foo with one argument, 42.
+// absl::apply(&Foo::Bar, tuple3);
+//
+// std::tuple<int, int> tuple4(8, 9);
+// // Invokes a lambda.
+// absl::apply(user_lambda, tuple4);
// }
template <typename Functor, typename Tuple>
auto apply(Functor&& functor, Tuple&& t)
@@ -286,6 +317,34 @@ T exchange(T& obj, U&& new_value) {
return old_value;
}
+namespace utility_internal {
+template <typename T, typename Tuple, size_t... I>
+T make_from_tuple_impl(Tuple&& tup, absl::index_sequence<I...>) {
+ return T(std::get<I>(std::forward<Tuple>(tup))...);
+}
+} // namespace utility_internal
+
+// make_from_tuple
+//
+// Given the template parameter type `T` and a tuple of arguments
+// `std::tuple(arg0, arg1, ..., argN)` constructs an object of type `T` as if by
+// calling `T(arg0, arg1, ..., argN)`.
+//
+// Example:
+//
+// std::tuple<const char*, size_t> args("hello world", 5);
+// auto s = absl::make_from_tuple<std::string>(args);
+// assert(s == "hello");
+//
+template <typename T, typename Tuple>
+constexpr T make_from_tuple(Tuple&& tup) {
+ return utility_internal::make_from_tuple_impl<T>(
+ std::forward<Tuple>(tup),
+ absl::make_index_sequence<
+ std::tuple_size<absl::decay_t<Tuple>>::value>{});
+}
+
+ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_UTILITY_UTILITY_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility_test.cc b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility_test.cc
index 3c447b20bb0..f044ad644a4 100644
--- a/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility_test.cc
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/absl/utility/utility_test.cc
@@ -4,7 +4,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
-// http://www.apache.org/licenses/LICENSE-2.0
+// 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,
@@ -135,7 +135,7 @@ struct PoorStrCat {
template <typename Tup, size_t... Is>
std::vector<std::string> TupStringVecImpl(const Tup& tup,
- absl::index_sequence<Is...>) {
+ absl::index_sequence<Is...>) {
return {Fmt(std::get<Is>(tup))...};
}
@@ -341,5 +341,36 @@ TEST(ExchangeTest, MoveOnly) {
EXPECT_EQ(1, *b);
}
+TEST(MakeFromTupleTest, String) {
+ EXPECT_EQ(
+ absl::make_from_tuple<std::string>(std::make_tuple("hello world", 5)),
+ "hello");
+}
+
+TEST(MakeFromTupleTest, MoveOnlyParameter) {
+ struct S {
+ S(std::unique_ptr<int> n, std::unique_ptr<int> m) : value(*n + *m) {}
+ int value = 0;
+ };
+ auto tup =
+ std::make_tuple(absl::make_unique<int>(3), absl::make_unique<int>(4));
+ auto s = absl::make_from_tuple<S>(std::move(tup));
+ EXPECT_EQ(s.value, 7);
+}
+
+TEST(MakeFromTupleTest, NoParameters) {
+ struct S {
+ S() : value(1) {}
+ int value = 2;
+ };
+ EXPECT_EQ(absl::make_from_tuple<S>(std::make_tuple()).value, 1);
+}
+
+TEST(MakeFromTupleTest, Pair) {
+ EXPECT_EQ(
+ (absl::make_from_tuple<std::pair<bool, int>>(std::make_tuple(true, 17))),
+ std::make_pair(true, 17));
+}
+
} // namespace
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/absl_alternate_options.h b/src/third_party/abseil-cpp-master/abseil-cpp/ci/absl_alternate_options.h
new file mode 100644
index 00000000000..29b020d9fa6
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/absl_alternate_options.h
@@ -0,0 +1,29 @@
+// 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.
+
+// Alternate options.h file, used in continuous integration testing to exercise
+// option settings not used by default.
+
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
+#define ABSL_OPTION_USE_STD_ANY 0
+#define ABSL_OPTION_USE_STD_OPTIONAL 0
+#define ABSL_OPTION_USE_STD_STRING_VIEW 0
+#define ABSL_OPTION_USE_STD_VARIANT 0
+#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME ns
+#define ABSL_OPTION_HARDENED 1
+
+#endif // ABSL_BASE_OPTIONS_H_
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_common.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_common.sh
new file mode 100644
index 00000000000..aec8a117174
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_common.sh
@@ -0,0 +1,25 @@
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# The commit of GoogleTest to be used in the CMake tests in this directory.
+# Keep this in sync with the commit in the WORKSPACE file.
+readonly ABSL_GOOGLETEST_COMMIT="8567b09290fe402cf01923e2131c5635b8ed851b"
+
+# Avoid depending on GitHub by looking for a cached copy of the commit first.
+if [[ -r "${KOKORO_GFILE_DIR:-}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ ABSL_GOOGLETEST_DOWNLOAD_URL="file:///distdir/${ABSL_GOOGLETEST_COMMIT}.zip"
+else
+ ABSL_GOOGLETEST_DOWNLOAD_URL="https://github.com/google/googletest/archive/${ABSL_GOOGLETEST_COMMIT}.zip"
+fi
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_install_test.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_install_test.sh
new file mode 100644
index 00000000000..ffc6b5168d7
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/cmake_install_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+#
+# 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.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${LINK_TYPE:-} ]]; then
+ LINK_TYPE="STATIC DYNAMIC"
+fi
+
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
+
+for link_type in ${LINK_TYPE}; do
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
+ --tmpfs=/buildfs:exec \
+ --tmpfs=/abseil-cpp:exec \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ -e "LINK_TYPE=${link_type}" \
+ --rm \
+ ${DOCKER_CONTAINER} \
+ /bin/bash -c "cp -r /abseil-cpp-ro/* . && CMake/install_test_project/test.sh"
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh
new file mode 100644
index 00000000000..ffbb8327e73
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+#
+# 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.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14 c++17 c++20"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
+ -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
+ -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --compilation_mode="${compilation_mode}" \
+ --copt="${exceptions_mode}" \
+ --copt="-fsanitize=address" \
+ --copt="-fsanitize=float-divide-by-zero" \
+ --copt="-fsanitize=nullability" \
+ --copt="-fsanitize=undefined" \
+ --copt="-fno-sanitize-blacklist" \
+ --copt=-Werror \
+ --keep_going \
+ --linkopt="-fsanitize=address" \
+ --linkopt="-fsanitize-link-c++-runtime" \
+ --show_timestamps \
+ --test_env="ASAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \
+ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+ --test_env="UBSAN_OPTIONS=print_stacktrace=1" \
+ --test_env="UBSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \
+ --test_output=errors \
+ --test_tag_filters="-benchmark,-noasan" \
+ ${BAZEL_EXTRA_ARGS:-}
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh
new file mode 100644
index 00000000000..f6a2221e8a0
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh
@@ -0,0 +1,97 @@
+#!/bin/bash
+#
+# 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.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14 c++17 c++20"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
+ --tmpfs=/abseil-cpp \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
+ -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx/lib" \
+ -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx/include/c++/v1" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /bin/sh -c "
+ cp -r /abseil-cpp-ro/* /abseil-cpp/
+ if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
+ cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+ fi
+ /usr/local/bin/bazel test ... \
+ --compilation_mode=\"${compilation_mode}\" \
+ --copt=\"${exceptions_mode}\" \
+ --copt=-Werror \
+ --define=\"absl=1\" \
+ --keep_going \
+ --show_timestamps \
+ --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+ --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
+ --test_output=errors \
+ --test_tag_filters=-benchmark \
+ ${BAZEL_EXTRA_ARGS:-}"
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh
new file mode 100644
index 00000000000..e70e8214cd1
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+#
+# 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.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14 c++17 c++20"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_CXXOPTS="-std=${std}:-nostdinc++" \
+ -e BAZEL_LINKOPTS="-L/opt/llvm/libcxx-tsan/lib:-lc++:-lc++abi:-lm:-Wl,-rpath=/opt/llvm/libcxx-tsan/lib" \
+ -e CPLUS_INCLUDE_PATH="/opt/llvm/libcxx-tsan/include/c++/v1" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --build_tag_filters="-notsan" \
+ --compilation_mode="${compilation_mode}" \
+ --copt="${exceptions_mode}" \
+ --copt="-fsanitize=thread" \
+ --copt="-fno-sanitize-blacklist" \
+ --copt=-Werror \
+ --keep_going \
+ --linkopt="-fsanitize=thread" \
+ --show_timestamps \
+ --test_env="TSAN_OPTIONS=report_atomic_races=0" \
+ --test_env="TSAN_SYMBOLIZER_PATH=/opt/llvm/clang/bin/llvm-symbolizer" \
+ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+ --test_output=errors \
+ --test_tag_filters="-benchmark,-notsan" \
+ ${BAZEL_EXTRA_ARGS:-}
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
new file mode 100644
index 00000000000..0986ff40ccf
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+#
+# 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.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14 c++17 c++20"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_CLANG_LATEST_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_CXXOPTS="-std=${std}" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --compilation_mode="${compilation_mode}" \
+ --copt="--gcc-toolchain=/usr/local" \
+ --copt="${exceptions_mode}" \
+ --copt=-Werror \
+ --define="absl=1" \
+ --keep_going \
+ --linkopt="--gcc-toolchain=/usr/local" \
+ --show_timestamps \
+ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
+ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+ --test_output=errors \
+ --test_tag_filters=-benchmark \
+ ${BAZEL_EXTRA_ARGS:-}
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_docker_containers.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_docker_containers.sh
new file mode 100644
index 00000000000..1c29d9a1f17
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_docker_containers.sh
@@ -0,0 +1,21 @@
+# 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.
+
+# The file contains Docker container identifiers currently used by test scripts.
+# Test scripts should source this file to get the identifiers.
+
+readonly LINUX_ALPINE_CONTAINER="gcr.io/google.com/absl-177019/alpine:20201026"
+readonly LINUX_CLANG_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
+readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20201008"
+readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20201015"
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh
new file mode 100644
index 00000000000..224aef81cbe
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+#
+# Copyright 2020 The Abseil Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_FLOOR_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--volume=${KOKORO_KEYSTORE_DIR}:/keystore:ro ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--volume=${KOKORO_GFILE_DIR}/distdir:/distdir:ro ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/usr/local/bin/gcc" \
+ -e BAZEL_CXXOPTS="-std=${std}" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /usr/local/bin/bazel test ... \
+ --compilation_mode="${compilation_mode}" \
+ --copt="${exceptions_mode}" \
+ --copt=-Werror \
+ --define="absl=1" \
+ --keep_going \
+ --show_timestamps \
+ --test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
+ --test_env="TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo" \
+ --test_output=errors \
+ --test_tag_filters=-benchmark \
+ ${BAZEL_EXTRA_ARGS:-}
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh
new file mode 100644
index 00000000000..37d89d9f829
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -0,0 +1,95 @@
+#!/bin/bash
+#
+# 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.
+
+# This script that can be invoked to test abseil-cpp in a hermetic environment
+# using a Docker image on Linux. You must have Docker installed to use this
+# script.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+if [[ -z ${STD:-} ]]; then
+ STD="c++11 c++14 c++17 c++20"
+fi
+
+if [[ -z ${COMPILATION_MODE:-} ]]; then
+ COMPILATION_MODE="fastbuild opt"
+fi
+
+if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+ EXCEPTIONS_MODE="-fno-exceptions -fexceptions"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
+
+# USE_BAZEL_CACHE=1 only works on Kokoro.
+# Without access to the credentials this won't work.
+if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_KEYSTORE_DIR},target=/keystore,readonly ${DOCKER_EXTRA_ARGS:-}"
+ # Bazel doesn't track changes to tools outside of the workspace
+ # (e.g. /usr/bin/gcc), so by appending the docker container to the
+ # remote_http_cache url, we make changes to the container part of
+ # the cache key. Hashing the key is to make it shorter and url-safe.
+ container_key=$(echo ${DOCKER_CONTAINER} | sha256sum | head -c 16)
+ BAZEL_EXTRA_ARGS="--remote_http_cache=https://storage.googleapis.com/absl-bazel-remote-cache/${container_key} --google_credentials=/keystore/73103_absl-bazel-remote-cache ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+# Avoid depending on external sites like GitHub by checking --distdir for
+# external dependencies first.
+# https://docs.bazel.build/versions/master/guide.html#distdir
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -d "${KOKORO_GFILE_DIR}/distdir" ]]; then
+ DOCKER_EXTRA_ARGS="--mount type=bind,source=${KOKORO_GFILE_DIR}/distdir,target=/distdir,readonly ${DOCKER_EXTRA_ARGS:-}"
+ BAZEL_EXTRA_ARGS="--distdir=/distdir ${BAZEL_EXTRA_ARGS:-}"
+fi
+
+for std in ${STD}; do
+ for compilation_mode in ${COMPILATION_MODE}; do
+ for exceptions_mode in ${EXCEPTIONS_MODE}; do
+ echo "--------------------------------------------------------------------"
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp-ro,readonly \
+ --tmpfs=/abseil-cpp \
+ --workdir=/abseil-cpp \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CC="/usr/local/bin/gcc" \
+ -e BAZEL_CXXOPTS="-std=${std}" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ ${DOCKER_CONTAINER} \
+ /bin/sh -c "
+ cp -r /abseil-cpp-ro/* /abseil-cpp/
+ if [ -n \"${ALTERNATE_OPTIONS:-}\" ]; then
+ cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+ fi
+ /usr/local/bin/bazel test ... \
+ --compilation_mode=\"${compilation_mode}\" \
+ --copt=\"${exceptions_mode}\" \
+ --copt=-Werror \
+ --define=\"absl=1\" \
+ --keep_going \
+ --show_timestamps \
+ --test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
+ --test_env=\"TZDIR=/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo\" \
+ --test_output=errors \
+ --test_tag_filters=-benchmark \
+ ${BAZEL_EXTRA_ARGS:-}"
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh
new file mode 100644
index 00000000000..ab06aa05749
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh
@@ -0,0 +1,65 @@
+#!/bin/bash
+#
+# 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.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
+ ABSL_CMAKE_CXX_STANDARDS="11 14 17 20"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+ ABSL_CMAKE_BUILD_TYPES="Debug Release"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+ ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_GCC_LATEST_CONTAINER}
+
+for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
+ for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
+ for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+ --tmpfs=/buildfs:exec \
+ --workdir=/buildfs \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CFLAGS="-Werror" \
+ -e CXXFLAGS="-Werror" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ "${DOCKER_CONTAINER}" \
+ /bin/bash -c "
+ cmake /abseil-cpp \
+ -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \
+ -DBUILD_SHARED_LIBS=${build_shared} \
+ -DBUILD_TESTING=ON \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=${std} \
+ -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \
+ make -j$(nproc) && \
+ ctest -j$(nproc) --output-on-failure"
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc_alpine_cmake.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc_alpine_cmake.sh
new file mode 100644
index 00000000000..bce27d295f2
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/linux_gcc_alpine_cmake.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+# 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.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+if [[ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]]; then
+ ABSL_CMAKE_CXX_STANDARDS="11 14 17"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+ ABSL_CMAKE_BUILD_TYPES="Debug Release"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+ ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
+
+source "${ABSEIL_ROOT}/ci/linux_docker_containers.sh"
+readonly DOCKER_CONTAINER=${LINUX_ALPINE_CONTAINER}
+
+for std in ${ABSL_CMAKE_CXX_STANDARDS}; do
+ for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
+ for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+ time docker run \
+ --mount type=bind,source="${ABSEIL_ROOT}",target=/abseil-cpp,readonly \
+ --tmpfs=/buildfs:exec \
+ --workdir=/buildfs \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CFLAGS="-Werror" \
+ -e CXXFLAGS="-Werror" \
+ ${DOCKER_EXTRA_ARGS:-} \
+ "${DOCKER_CONTAINER}" \
+ /bin/sh -c "
+ cmake /abseil-cpp \
+ -DABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL} \
+ -DBUILD_TESTING=ON \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=${std} \
+ -DCMAKE_MODULE_LINKER_FLAGS=\"-Wl,--no-undefined\" && \
+ make -j$(nproc) && \
+ ctest -j$(nproc) --output-on-failure"
+ done
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_bazel.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_bazel.sh
new file mode 100644
index 00000000000..738adf94765
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_bazel.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+#
+# 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.
+
+# This script is invoked on Kokoro to test Abseil on macOS.
+# It is not hermetic and may break when Kokoro is updated.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
+fi
+
+# If we are running on Kokoro, check for a versioned Bazel binary.
+KOKORO_GFILE_BAZEL_BIN="bazel-2.0.0-darwin-x86_64"
+if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
+ BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}"
+ chmod +x ${BAZEL_BIN}
+else
+ BAZEL_BIN="bazel"
+fi
+
+# Print the compiler and Bazel versions.
+echo "---------------"
+gcc -v
+echo "---------------"
+${BAZEL_BIN} version
+echo "---------------"
+
+cd ${ABSEIL_ROOT}
+
+if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then
+ cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
+fi
+
+${BAZEL_BIN} test ... \
+ --copt=-Werror \
+ --keep_going \
+ --show_timestamps \
+ --test_env="TZDIR=${ABSEIL_ROOT}/absl/time/internal/cctz/testdata/zoneinfo" \
+ --test_output=errors \
+ --test_tag_filters=-benchmark
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_cmake.sh b/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_cmake.sh
new file mode 100644
index 00000000000..2a870cf4e9d
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/ci/macos_xcode_cmake.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# 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.
+
+set -euox pipefail
+
+if [[ -z ${ABSEIL_ROOT:-} ]]; then
+ ABSEIL_ROOT="$(dirname ${0})/.."
+fi
+ABSEIL_ROOT=$(realpath ${ABSEIL_ROOT})
+
+source "${ABSEIL_ROOT}/ci/cmake_common.sh"
+
+# The MacOS build doesn't run in a docker container, so we have to override ABSL_GOOGLETEST_DOWNLOAD_URL.
+if [[ -r "${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip" ]]; then
+ ABSL_GOOGLETEST_DOWNLOAD_URL="file://${KOKORO_GFILE_DIR}/distdir/${ABSL_GOOGLETEST_COMMIT}.zip"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+ ABSL_CMAKE_BUILD_TYPES="Debug"
+fi
+
+if [[ -z ${ABSL_CMAKE_BUILD_SHARED:-} ]]; then
+ ABSL_CMAKE_BUILD_SHARED="OFF ON"
+fi
+
+for compilation_mode in ${ABSL_CMAKE_BUILD_TYPES}; do
+ for build_shared in ${ABSL_CMAKE_BUILD_SHARED}; do
+ BUILD_DIR=$(mktemp -d ${compilation_mode}.XXXXXXXX)
+ cd ${BUILD_DIR}
+
+ # TODO(absl-team): Enable -Werror once all warnings are fixed.
+ time cmake ${ABSEIL_ROOT} \
+ -GXcode \
+ -DBUILD_SHARED_LIBS=${build_shared} \
+ -DBUILD_TESTING=ON \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=11 \
+ -DCMAKE_MODULE_LINKER_FLAGS="-Wl,--no-undefined" \
+ -DABSL_GOOGLETEST_DOWNLOAD_URL="${ABSL_GOOGLETEST_DOWNLOAD_URL}"
+ time cmake --build .
+ time ctest -C ${compilation_mode} --output-on-failure
+ done
+done
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/conanfile.py b/src/third_party/abseil-cpp-master/abseil-cpp/conanfile.py
new file mode 100644
index 00000000000..926ec5ccd64
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/conanfile.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# Note: Conan is supported on a best-effort basis. Abseil doesn't use Conan
+# internally, so we won't know if it stops working. We may ask community
+# members to help us debug any problems that arise.
+
+from conans import ConanFile, CMake, tools
+from conans.errors import ConanInvalidConfiguration
+from conans.model.version import Version
+
+
+class AbseilConan(ConanFile):
+ name = "abseil"
+ url = "https://github.com/abseil/abseil-cpp"
+ homepage = url
+ author = "Abseil <abseil-io@googlegroups.com>"
+ description = "Abseil Common Libraries (C++) from Google"
+ license = "Apache-2.0"
+ topics = ("conan", "abseil", "abseil-cpp", "google", "common-libraries")
+ exports = ["LICENSE"]
+ exports_sources = ["CMakeLists.txt", "CMake/*", "absl/*"]
+ generators = "cmake"
+ settings = "os", "arch", "compiler", "build_type"
+
+ def configure(self):
+ if self.settings.os == "Windows" and \
+ self.settings.compiler == "Visual Studio" and \
+ Version(self.settings.compiler.version.value) < "14":
+ raise ConanInvalidConfiguration("Abseil does not support MSVC < 14")
+
+ def build(self):
+ tools.replace_in_file("CMakeLists.txt", "project(absl CXX)", "project(absl CXX)\ninclude(conanbuildinfo.cmake)\nconan_basic_setup()")
+ cmake = CMake(self)
+ cmake.definitions["BUILD_TESTING"] = False
+ cmake.configure()
+ cmake.build()
+
+ def package(self):
+ self.copy("LICENSE", dst="licenses")
+ self.copy("*.h", dst="include", src=".")
+ self.copy("*.inc", dst="include", src=".")
+ self.copy("*.a", dst="lib", src=".", keep_path=False)
+ self.copy("*.lib", dst="lib", src=".", keep_path=False)
+
+ def package_info(self):
+ if self.settings.os == "Linux":
+ self.cpp_info.libs = ["-Wl,--start-group"]
+ self.cpp_info.libs.extend(tools.collect_libs(self))
+ if self.settings.os == "Linux":
+ self.cpp_info.libs.extend(["-Wl,--end-group", "pthread"])
diff --git a/src/third_party/abseil-cpp-master/abseil-cpp/create_lts.py b/src/third_party/abseil-cpp-master/abseil-cpp/create_lts.py
new file mode 100644
index 00000000000..a98c76b4b3f
--- /dev/null
+++ b/src/third_party/abseil-cpp-master/abseil-cpp/create_lts.py
@@ -0,0 +1,121 @@
+#!/usr/bin/env python
+#
+# 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.
+"""A script to do source transformations to create a new LTS release.
+
+ Usage: ./create_lts.py YYYYMMDD
+"""
+
+import sys
+
+
+def ReplaceStringsInFile(filename, replacement_dict):
+ """Performs textual replacements in a file.
+
+ Rewrites filename with the keys in replacement_dict replaced with
+ their values. This function assumes the file can fit in memory.
+
+ Args:
+ filename: the filename to perform the replacement on
+ replacement_dict: a dictionary of key strings to be replaced with their
+ values
+
+ Raises:
+ Exception: A failure occured
+ """
+ f = open(filename, 'r')
+ content = f.read()
+ f.close()
+
+ for key, value in replacement_dict.items():
+ original = content
+ content = content.replace(key, value)
+ if content == original:
+ raise Exception('Failed to find {} in {}'.format(key, filename))
+
+ f = open(filename, 'w')
+ f.write(content)
+ f.close()
+
+
+def StripContentBetweenTags(filename, strip_begin_tag, strip_end_tag):
+ """Strip contents from a file.
+
+ Rewrites filename with by removing all content between
+ strip_begin_tag and strip_end_tag, including the tags themselves.
+
+ Args:
+ filename: the filename to perform the replacement on
+ strip_begin_tag: the start of the content to be removed
+ strip_end_tag: the end of the content to be removed
+
+ Raises:
+ Exception: A failure occured
+ """
+ f = open(filename, 'r')
+ content = f.read()
+ f.close()
+
+ while True:
+ begin = content.find(strip_begin_tag)
+ if begin == -1:
+ break
+ end = content.find(strip_end_tag, begin + len(strip_begin_tag))
+ if end == -1:
+ raise Exception('{}: imbalanced strip begin ({}) and '
+ 'end ({}) tags'.format(filename, strip_begin_tag,
+ strip_end_tag))
+ content = content.replace(content[begin:end + len(strip_end_tag)], '')
+
+ f = open(filename, 'w')
+ f.write(content)
+ f.close()
+
+
+def main(argv):
+ if len(argv) != 2:
+ print('Usage: {} YYYYMMDD'.format(sys.argv[0], file=sys.stderr))
+ sys.exit(1)
+
+ datestamp = sys.argv[1]
+ if len(datestamp) != 8 or not datestamp.isdigit():
+ raise Exception(
+ 'datestamp={} is not in the YYYYMMDD format'.format(datestamp))
+
+ # Replacement directives go here.
+ ReplaceStringsInFile(
+ 'absl/base/options.h', {
+ '#define ABSL_OPTION_USE_INLINE_NAMESPACE 0':
+ '#define ABSL_OPTION_USE_INLINE_NAMESPACE 1',
+ '#define ABSL_OPTION_INLINE_NAMESPACE_NAME head':
+ '#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_{}'.format(
+ datestamp)
+ })
+ ReplaceStringsInFile(
+ 'CMakeLists.txt', {
+ 'project(absl LANGUAGES CXX)':
+ 'project(absl LANGUAGES CXX VERSION {})'.format(datestamp)
+ })
+ # Set the SOVERSION to YYYYMMDD.0.0 - The first 0 means we only have
+ # ABI compatible changes, and the second 0 means we can increment it
+ # to mark changes as ABI-compatible, for patch releases.
+ ReplaceStringsInFile('CMake/AbseilHelpers.cmake',
+ {'SOVERSION 0': 'SOVERSION "{}.0.0"'.format(datestamp)})
+ StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin',
+ '# absl:lts-remove-end')
+
+
+if __name__ == '__main__':
+ main(sys.argv)
diff --git a/src/third_party/abseil-cpp-master/scripts/import.sh b/src/third_party/abseil-cpp-master/scripts/import.sh
index f8e2b730e6a..1a6bb403e81 100755
--- a/src/third_party/abseil-cpp-master/scripts/import.sh
+++ b/src/third_party/abseil-cpp-master/scripts/import.sh
@@ -8,7 +8,7 @@ set -vx
NAME=abseil-cpp
-LIB_GIT_REVISION=mongodb-2018-12-16
+LIB_GIT_REVISION=20210324.1
LIB_GIT_REPO=git@github.com:mongodb-forks/abseil-cpp.git
# misnamed, we aren't actually taking their 'master' branch.