aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:47:18 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-06-15 21:47:18 +0000
commita32061b365b2d32963d08e27396cbf32e08c31cb (patch)
treecb306ffb64819f95c080c3cb6bfcdfb45a7b3a76
parent93534cddabc1dc3b7dfa5387784c6c7394f729c4 (diff)
parentb7c9dafe99969a4e9d5ffa101bb9a8d6e1df69df (diff)
downloadwebrtc-aml_tz3_314012010.tar.gz
Change-Id: Iab4fa0d9b620eddf41ca88e1eb5547f79c316203
-rw-r--r--Android.bp13
-rw-r--r--api/video/i010_buffer.cc12
-rw-r--r--third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md41
-rw-r--r--third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md7
-rw-r--r--third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml1
-rw-r--r--third_party/abseil-cpp/Android.bp29
-rw-r--r--third_party/abseil-cpp/BUILD.bazel25
-rw-r--r--third_party/abseil-cpp/CMake/AbseilDll.cmake73
-rw-r--r--third_party/abseil-cpp/CMake/AbseilHelpers.cmake135
-rw-r--r--third_party/abseil-cpp/CMake/AbseilInstallDirs.cmake20
-rw-r--r--third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in11
-rw-r--r--third_party/abseil-cpp/CMake/Googletest/DownloadGTest.cmake19
-rw-r--r--third_party/abseil-cpp/CMake/README.md96
-rw-r--r--third_party/abseil-cpp/CMake/abslConfig.cmake.in5
-rw-r--r--third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt4
-rw-r--r--third_party/abseil-cpp/CMake/install_test_project/simple.cc9
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/CMake/install_test_project/test.sh164
-rw-r--r--third_party/abseil-cpp/CMakeLists.txt135
-rw-r--r--third_party/abseil-cpp/FAQ.md5
-rw-r--r--third_party/abseil-cpp/LTS.md15
-rw-r--r--third_party/abseil-cpp/METADATA6
-rw-r--r--third_party/abseil-cpp/README.md42
-rw-r--r--third_party/abseil-cpp/WORKSPACE31
-rw-r--r--third_party/abseil-cpp/absl/BUILD.bazel51
-rw-r--r--third_party/abseil-cpp/absl/CMakeLists.txt2
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/absl/abseil.podspec.gen.py4
-rw-r--r--third_party/abseil-cpp/absl/algorithm/BUILD.bazel7
-rw-r--r--third_party/abseil-cpp/absl/algorithm/CMakeLists.txt4
-rw-r--r--third_party/abseil-cpp/absl/algorithm/container.h279
-rw-r--r--third_party/abseil-cpp/absl/algorithm/container_test.cc133
-rw-r--r--third_party/abseil-cpp/absl/base/BUILD.bazel141
-rw-r--r--third_party/abseil-cpp/absl/base/CMakeLists.txt156
-rw-r--r--third_party/abseil-cpp/absl/base/attributes.h224
-rw-r--r--third_party/abseil-cpp/absl/base/call_once.h13
-rw-r--r--third_party/abseil-cpp/absl/base/casts.h15
-rw-r--r--third_party/abseil-cpp/absl/base/config.h199
-rw-r--r--third_party/abseil-cpp/absl/base/dynamic_annotations.cc129
-rw-r--r--third_party/abseil-cpp/absl/base/dynamic_annotations.h752
-rw-r--r--third_party/abseil-cpp/absl/base/internal/bits.h218
-rw-r--r--third_party/abseil-cpp/absl/base/internal/bits_test.cc97
-rw-r--r--third_party/abseil-cpp/absl/base/internal/direct_mmap.h10
-rw-r--r--third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h398
-rw-r--r--third_party/abseil-cpp/absl/base/internal/endian.h61
-rw-r--r--third_party/abseil-cpp/absl/base/internal/endian_test.cc24
-rw-r--r--third_party/abseil-cpp/absl/base/internal/errno_saver_test.cc3
-rw-r--r--third_party/abseil-cpp/absl/base/internal/exception_safety_testing.h26
-rw-r--r--third_party/abseil-cpp/absl/base/internal/exponential_biased.cc (renamed from third_party/abseil-cpp/absl/profiling/internal/exponential_biased.cc)8
-rw-r--r--third_party/abseil-cpp/absl/base/internal/exponential_biased.h (renamed from third_party/abseil-cpp/absl/profiling/internal/exponential_biased.h)12
-rw-r--r--third_party/abseil-cpp/absl/base/internal/exponential_biased_test.cc (renamed from third_party/abseil-cpp/absl/profiling/internal/exponential_biased_test.cc)8
-rw-r--r--third_party/abseil-cpp/absl/base/internal/fast_type_id.h48
-rw-r--r--third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc123
-rw-r--r--third_party/abseil-cpp/absl/base/internal/invoke.h8
-rw-r--r--third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc2
-rw-r--r--third_party/abseil-cpp/absl/base/internal/low_level_alloc_test.cc23
-rw-r--r--third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h35
-rw-r--r--third_party/abseil-cpp/absl/base/internal/periodic_sampler.cc (renamed from third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.cc)8
-rw-r--r--third_party/abseil-cpp/absl/base/internal/periodic_sampler.h (renamed from third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.h)14
-rw-r--r--third_party/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc (renamed from third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_benchmark.cc)6
-rw-r--r--third_party/abseil-cpp/absl/base/internal/periodic_sampler_test.cc (renamed from third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_test.cc)6
-rw-r--r--third_party/abseil-cpp/absl/base/internal/raw_logging.cc68
-rw-r--r--third_party/abseil-cpp/absl/base/internal/raw_logging.h22
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock.cc76
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock.h67
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc4
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc14
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc4
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock_wait.h24
-rw-r--r--third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc10
-rw-r--r--third_party/abseil-cpp/absl/base/internal/strerror.cc88
-rw-r--r--third_party/abseil-cpp/absl/base/internal/strerror.h39
-rw-r--r--third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc29
-rw-r--r--third_party/abseil-cpp/absl/base/internal/strerror_test.cc88
-rw-r--r--third_party/abseil-cpp/absl/base/internal/sysinfo.cc102
-rw-r--r--third_party/abseil-cpp/absl/base/internal/sysinfo.h8
-rw-r--r--third_party/abseil-cpp/absl/base/internal/sysinfo_test.cc23
-rw-r--r--third_party/abseil-cpp/absl/base/internal/thread_identity.cc15
-rw-r--r--third_party/abseil-cpp/absl/base/internal/thread_identity.h110
-rw-r--r--third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc11
-rw-r--r--third_party/abseil-cpp/absl/base/internal/throw_delegate.cc118
-rw-r--r--third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h4
-rw-r--r--third_party/abseil-cpp/absl/base/internal/unaligned_access.h76
-rw-r--r--third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc77
-rw-r--r--third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc20
-rw-r--r--third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h14
-rw-r--r--third_party/abseil-cpp/absl/base/invoke_test.cc136
-rw-r--r--third_party/abseil-cpp/absl/base/log_severity.h8
-rw-r--r--third_party/abseil-cpp/absl/base/log_severity_test.cc6
-rw-r--r--third_party/abseil-cpp/absl/base/macros.h156
-rw-r--r--third_party/abseil-cpp/absl/base/optimization.h75
-rw-r--r--third_party/abseil-cpp/absl/base/optimization_test.cc129
-rw-r--r--third_party/abseil-cpp/absl/base/options.h35
-rw-r--r--third_party/abseil-cpp/absl/base/policy_checks.h2
-rw-r--r--third_party/abseil-cpp/absl/base/port.h1
-rw-r--r--third_party/abseil-cpp/absl/base/spinlock_test_common.cc21
-rw-r--r--third_party/abseil-cpp/absl/base/thread_annotations.h135
-rw-r--r--third_party/abseil-cpp/absl/cleanup/BUILD.bazel65
-rw-r--r--third_party/abseil-cpp/absl/cleanup/CMakeLists.txt55
-rw-r--r--third_party/abseil-cpp/absl/cleanup/cleanup.h140
-rw-r--r--third_party/abseil-cpp/absl/cleanup/cleanup_test.cc311
-rw-r--r--third_party/abseil-cpp/absl/cleanup/internal/cleanup.h100
-rw-r--r--third_party/abseil-cpp/absl/compiler_config_setting.bzl38
-rw-r--r--third_party/abseil-cpp/absl/container/BUILD.bazel100
-rw-r--r--third_party/abseil-cpp/absl/container/CMakeLists.txt104
-rw-r--r--third_party/abseil-cpp/absl/container/btree_benchmark.cc72
-rw-r--r--third_party/abseil-cpp/absl/container/btree_map.h100
-rw-r--r--third_party/abseil-cpp/absl/container/btree_set.h81
-rw-r--r--third_party/abseil-cpp/absl/container/btree_test.cc712
-rw-r--r--third_party/abseil-cpp/absl/container/btree_test.h11
-rw-r--r--third_party/abseil-cpp/absl/container/fixed_array.h76
-rw-r--r--third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc3
-rw-r--r--third_party/abseil-cpp/absl/container/fixed_array_test.cc119
-rw-r--r--third_party/abseil-cpp/absl/container/flat_hash_map.h8
-rw-r--r--third_party/abseil-cpp/absl/container/flat_hash_map_test.cc55
-rw-r--r--third_party/abseil-cpp/absl/container/flat_hash_set.h5
-rw-r--r--third_party/abseil-cpp/absl/container/flat_hash_set_test.cc12
-rw-r--r--third_party/abseil-cpp/absl/container/inlined_vector.h275
-rw-r--r--third_party/abseil-cpp/absl/container/inlined_vector_benchmark.cc24
-rw-r--r--third_party/abseil-cpp/absl/container/inlined_vector_test.cc53
-rw-r--r--third_party/abseil-cpp/absl/container/internal/btree.h1241
-rw-r--r--third_party/abseil-cpp/absl/container/internal/btree_container.h333
-rw-r--r--third_party/abseil-cpp/absl/container/internal/common.h8
-rw-r--r--third_party/abseil-cpp/absl/container/internal/compressed_tuple.h43
-rw-r--r--third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/container/internal/container_memory.h78
-rw-r--r--third_party/abseil-cpp/absl/container/internal/container_memory_test.cc71
-rw-r--r--third_party/abseil-cpp/absl/container/internal/counting_allocator.h69
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h29
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc90
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hash_generator_testing.cc6
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hash_generator_testing.h21
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h31
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc129
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h166
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc3
-rw-r--r--third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc65
-rw-r--r--third_party/abseil-cpp/absl/container/internal/have_sse.h19
-rw-r--r--third_party/abseil-cpp/absl/container/internal/inlined_vector.h898
-rw-r--r--third_party/abseil-cpp/absl/container/internal/layout.h20
-rw-r--r--third_party/abseil-cpp/absl/container/internal/layout_benchmark.cc122
-rw-r--r--third_party/abseil-cpp/absl/container/internal/layout_test.cc570
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_map.h5
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc23
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set.h696
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc75
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc431
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc590
-rw-r--r--third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc451
-rw-r--r--third_party/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h39
-rw-r--r--third_party/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h41
-rw-r--r--third_party/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h35
-rw-r--r--third_party/abseil-cpp/absl/container/node_hash_map.h14
-rw-r--r--third_party/abseil-cpp/absl/container/node_hash_map_test.cc15
-rw-r--r--third_party/abseil-cpp/absl/container/node_hash_set.h39
-rw-r--r--third_party/abseil-cpp/absl/container/sample_element_size_test.cc114
-rw-r--r--third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake27
-rw-r--r--third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake115
-rw-r--r--third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl115
-rw-r--r--third_party/abseil-cpp/absl/copts/configure_copts.bzl20
-rw-r--r--third_party/abseil-cpp/absl/copts/copts.py128
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/absl/copts/generate_copts.py2
-rw-r--r--third_party/abseil-cpp/absl/debugging/BUILD.bazel35
-rw-r--r--third_party/abseil-cpp/absl/debugging/CMakeLists.txt22
-rw-r--r--third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc44
-rw-r--r--third_party/abseil-cpp/absl/debugging/failure_signal_handler.h4
-rw-r--r--third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc12
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc9
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/demangle.cc122
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc38
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc23
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h8
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc48
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc3
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h5
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc11
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc17
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h65
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc110
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc15
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc7
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc234
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc12
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc32
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/symbolize.h41
-rw-r--r--third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc45
-rw-r--r--third_party/abseil-cpp/absl/debugging/leak_check.cc16
-rw-r--r--third_party/abseil-cpp/absl/debugging/leak_check.h22
-rw-r--r--third_party/abseil-cpp/absl/debugging/leak_check_fail_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/debugging/leak_check_test.cc8
-rw-r--r--third_party/abseil-cpp/absl/debugging/stacktrace.cc2
-rw-r--r--third_party/abseil-cpp/absl/debugging/symbolize.cc15
-rw-r--r--third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc101
-rw-r--r--third_party/abseil-cpp/absl/debugging/symbolize_elf.inc134
-rw-r--r--third_party/abseil-cpp/absl/debugging/symbolize_emscripten.inc72
-rw-r--r--third_party/abseil-cpp/absl/debugging/symbolize_test.cc80
-rw-r--r--third_party/abseil-cpp/absl/flags/BUILD.bazel222
-rw-r--r--third_party/abseil-cpp/absl/flags/CMakeLists.txt193
-rw-r--r--third_party/abseil-cpp/absl/flags/commandlineflag.cc34
-rw-r--r--third_party/abseil-cpp/absl/flags/commandlineflag.h200
-rw-r--r--third_party/abseil-cpp/absl/flags/commandlineflag_test.cc231
-rw-r--r--third_party/abseil-cpp/absl/flags/config.h31
-rw-r--r--third_party/abseil-cpp/absl/flags/declare.h1
-rw-r--r--third_party/abseil-cpp/absl/flags/flag.cc2
-rw-r--r--third_party/abseil-cpp/absl/flags/flag.h242
-rw-r--r--third_party/abseil-cpp/absl/flags/flag_benchmark.cc157
-rw-r--r--third_party/abseil-cpp/absl/flags/flag_benchmark.lds13
-rw-r--r--third_party/abseil-cpp/absl/flags/flag_test.cc737
-rw-r--r--third_party/abseil-cpp/absl/flags/flag_test_defs.cc4
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/commandlineflag.h157
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/commandlineflag_test.cc219
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/flag.cc380
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/flag.h825
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/flag_msvc.inc116
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/parse.h8
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/path_util.h1
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.cc65
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.h61
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/program_name_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/registry.cc351
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/registry.h55
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/sequence_lock.h187
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/sequence_lock_test.cc169
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/type_erased.cc90
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/type_erased.h90
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/type_erased_test.cc157
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/usage.cc351
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/usage.h47
-rw-r--r--third_party/abseil-cpp/absl/flags/internal/usage_test.cc138
-rw-r--r--third_party/abseil-cpp/absl/flags/marshalling.cc23
-rw-r--r--third_party/abseil-cpp/absl/flags/marshalling.h4
-rw-r--r--third_party/abseil-cpp/absl/flags/parse.cc117
-rw-r--r--third_party/abseil-cpp/absl/flags/parse.h1
-rw-r--r--third_party/abseil-cpp/absl/flags/parse_test.cc129
-rw-r--r--third_party/abseil-cpp/absl/flags/reflection.cc354
-rw-r--r--third_party/abseil-cpp/absl/flags/reflection.h90
-rw-r--r--third_party/abseil-cpp/absl/flags/reflection_test.cc265
-rw-r--r--third_party/abseil-cpp/absl/flags/usage_config.cc17
-rw-r--r--third_party/abseil-cpp/absl/flags/usage_config.h5
-rw-r--r--third_party/abseil-cpp/absl/flags/usage_config_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/functional/BUILD.bazel4
-rw-r--r--third_party/abseil-cpp/absl/functional/CMakeLists.txt5
-rw-r--r--third_party/abseil-cpp/absl/functional/function_ref.h7
-rw-r--r--third_party/abseil-cpp/absl/functional/internal/front_binder.h16
-rw-r--r--third_party/abseil-cpp/absl/functional/internal/function_ref.h4
-rw-r--r--third_party/abseil-cpp/absl/hash/BUILD.bazel53
-rw-r--r--third_party/abseil-cpp/absl/hash/CMakeLists.txt41
-rw-r--r--third_party/abseil-cpp/absl/hash/hash.h33
-rw-r--r--third_party/abseil-cpp/absl/hash/hash_benchmark.cc254
-rw-r--r--third_party/abseil-cpp/absl/hash/hash_test.cc118
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/city.cc27
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/city.h20
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/hash.cc40
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/hash.h328
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc123
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/low_level_hash.h50
-rw-r--r--third_party/abseil-cpp/absl/hash/internal/low_level_hash_test.cc580
-rw-r--r--third_party/abseil-cpp/absl/memory/BUILD.bazel3
-rw-r--r--third_party/abseil-cpp/absl/memory/CMakeLists.txt4
-rw-r--r--third_party/abseil-cpp/absl/memory/memory.h4
-rw-r--r--third_party/abseil-cpp/absl/memory/memory_test.cc38
-rw-r--r--third_party/abseil-cpp/absl/meta/BUILD.bazel3
-rw-r--r--third_party/abseil-cpp/absl/meta/CMakeLists.txt2
-rw-r--r--third_party/abseil-cpp/absl/meta/type_traits.h60
-rw-r--r--third_party/abseil-cpp/absl/meta/type_traits_test.cc28
-rw-r--r--third_party/abseil-cpp/absl/numeric/BUILD.bazel45
-rw-r--r--third_party/abseil-cpp/absl/numeric/CMakeLists.txt42
-rw-r--r--third_party/abseil-cpp/absl/numeric/bits.h177
-rw-r--r--third_party/abseil-cpp/absl/numeric/bits_test.cc573
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128.cc53
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128.h244
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128_benchmark.cc161
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc44
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc143
-rw-r--r--third_party/abseil-cpp/absl/numeric/int128_test.cc36
-rw-r--r--third_party/abseil-cpp/absl/numeric/internal/bits.h358
-rw-r--r--third_party/abseil-cpp/absl/numeric/internal/representation.h55
-rw-r--r--third_party/abseil-cpp/absl/profiling/BUILD.bazel126
-rw-r--r--third_party/abseil-cpp/absl/profiling/CMakeLists.txt93
-rw-r--r--third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h230
-rw-r--r--third_party/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc171
-rw-r--r--third_party/abseil-cpp/absl/random/BUILD.bazel35
-rw-r--r--third_party/abseil-cpp/absl/random/CMakeLists.txt200
-rw-r--r--third_party/abseil-cpp/absl/random/bernoulli_distribution_test.cc10
-rw-r--r--third_party/abseil-cpp/absl/random/beta_distribution_test.cc66
-rw-r--r--third_party/abseil-cpp/absl/random/bit_gen_ref.h108
-rw-r--r--third_party/abseil-cpp/absl/random/bit_gen_ref_test.cc25
-rw-r--r--third_party/abseil-cpp/absl/random/discrete_distribution_test.cc13
-rw-r--r--third_party/abseil-cpp/absl/random/distribution_format_traits.h278
-rw-r--r--third_party/abseil-cpp/absl/random/distributions.h49
-rw-r--r--third_party/abseil-cpp/absl/random/distributions_test.cc152
-rw-r--r--third_party/abseil-cpp/absl/random/exponential_distribution_test.cc48
-rw-r--r--third_party/abseil-cpp/absl/random/gaussian_distribution_test.cc40
-rw-r--r--third_party/abseil-cpp/absl/random/internal/BUILD.bazel107
-rw-r--r--third_party/abseil-cpp/absl/random/internal/distribution_caller.h66
-rw-r--r--third_party/abseil-cpp/absl/random/internal/distributions.h52
-rw-r--r--third_party/abseil-cpp/absl/random/internal/explicit_seed_seq.h1
-rw-r--r--third_party/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc49
-rw-r--r--third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h202
-rw-r--r--third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc318
-rw-r--r--third_party/abseil-cpp/absl/random/internal/fastmath.h23
-rw-r--r--third_party/abseil-cpp/absl/random/internal/fastmath_test.cc13
-rw-r--r--third_party/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc16
-rw-r--r--third_party/abseil-cpp/absl/random/internal/generate_real.h10
-rw-r--r--third_party/abseil-cpp/absl/random/internal/generate_real_test.cc9
-rw-r--r--third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h4
-rw-r--r--third_party/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc5
-rw-r--r--third_party/abseil-cpp/absl/random/internal/mock_helpers.h134
-rw-r--r--third_party/abseil-cpp/absl/random/internal/mock_overload_set.h39
-rw-r--r--third_party/abseil-cpp/absl/random/internal/mocking_bit_gen_base.h120
-rw-r--r--third_party/abseil-cpp/absl/random/internal/nanobenchmark.cc2
-rw-r--r--third_party/abseil-cpp/absl/random/internal/nanobenchmark_test.cc2
-rw-r--r--third_party/abseil-cpp/absl/random/internal/pcg_engine.h7
-rw-r--r--third_party/abseil-cpp/absl/random/internal/pool_urbg.cc7
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen-keys.inc207
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen.cc2
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen.h2
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_detect.cc4
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_engine.h15
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc458
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_hwaes.h2
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_hwaes_test.cc57
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc462
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_slow.cc669
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_slow.h9
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_slow_test.cc60
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_test.cc45
-rw-r--r--third_party/abseil-cpp/absl/random/internal/randen_traits.h33
-rw-r--r--third_party/abseil-cpp/absl/random/internal/seed_material.cc50
-rw-r--r--third_party/abseil-cpp/absl/random/internal/uniform_helper.h68
-rw-r--r--third_party/abseil-cpp/absl/random/internal/uniform_helper_test.cc279
-rw-r--r--third_party/abseil-cpp/absl/random/internal/wide_multiply.h12
-rw-r--r--third_party/abseil-cpp/absl/random/internal/wide_multiply_test.cc3
-rw-r--r--third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h7
-rw-r--r--third_party/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc7
-rw-r--r--third_party/abseil-cpp/absl/random/mock_distributions.h5
-rw-r--r--third_party/abseil-cpp/absl/random/mocking_bit_gen.cc (renamed from third_party/abseil-cpp/absl/flags/internal/commandlineflag.cc)14
-rw-r--r--third_party/abseil-cpp/absl/random/mocking_bit_gen.h204
-rw-r--r--third_party/abseil-cpp/absl/random/mocking_bit_gen_test.cc51
-rw-r--r--third_party/abseil-cpp/absl/random/poisson_distribution_test.cc12
-rw-r--r--third_party/abseil-cpp/absl/random/random.h2
-rw-r--r--third_party/abseil-cpp/absl/random/seed_sequences_test.cc1
-rw-r--r--third_party/abseil-cpp/absl/random/uniform_int_distribution.h2
-rw-r--r--third_party/abseil-cpp/absl/random/uniform_int_distribution_test.cc15
-rw-r--r--third_party/abseil-cpp/absl/random/uniform_real_distribution_test.cc38
-rw-r--r--third_party/abseil-cpp/absl/random/zipf_distribution_test.cc6
-rw-r--r--third_party/abseil-cpp/absl/status/BUILD.bazel44
-rw-r--r--third_party/abseil-cpp/absl/status/CMakeLists.txt40
-rw-r--r--third_party/abseil-cpp/absl/status/internal/status_internal.h69
-rw-r--r--third_party/abseil-cpp/absl/status/internal/statusor_internal.h396
-rw-r--r--third_party/abseil-cpp/absl/status/status.cc65
-rw-r--r--third_party/abseil-cpp/absl/status/status.h696
-rw-r--r--third_party/abseil-cpp/absl/status/status_payload_printer.cc15
-rw-r--r--third_party/abseil-cpp/absl/status/status_test.cc36
-rw-r--r--third_party/abseil-cpp/absl/status/statusor.cc103
-rw-r--r--third_party/abseil-cpp/absl/status/statusor.h770
-rw-r--r--third_party/abseil-cpp/absl/status/statusor_test.cc1847
-rw-r--r--third_party/abseil-cpp/absl/strings/BUILD.bazel486
-rw-r--r--third_party/abseil-cpp/absl/strings/CMakeLists.txt553
-rw-r--r--third_party/abseil-cpp/absl/strings/ascii_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/strings/charconv.cc20
-rw-r--r--third_party/abseil-cpp/absl/strings/charconv.h5
-rw-r--r--third_party/abseil-cpp/absl/strings/charconv_benchmark.cc2
-rw-r--r--third_party/abseil-cpp/absl/strings/charconv_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/strings/cord.cc1310
-rw-r--r--third_party/abseil-cpp/absl/strings/cord.h990
-rw-r--r--third_party/abseil-cpp/absl/strings/cord_ring_reader_test.cc180
-rw-r--r--third_party/abseil-cpp/absl/strings/cord_ring_test.cc1495
-rw-r--r--third_party/abseil-cpp/absl/strings/cord_test.cc609
-rw-r--r--third_party/abseil-cpp/absl/strings/cord_test_helpers.h62
-rw-r--r--third_party/abseil-cpp/absl/strings/cordz_test.cc466
-rw-r--r--third_party/abseil-cpp/absl/strings/cordz_test_helpers.h151
-rw-r--r--third_party/abseil-cpp/absl/strings/escaping.cc26
-rw-r--r--third_party/abseil-cpp/absl/strings/escaping_test.cc6
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/char_map.h2
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc2
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h4
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc55
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc18
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/charconv_parse_test.cc2
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_internal.cc89
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_internal.h577
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_internal_test.cc116
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc1128
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h939
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc185
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h265
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator_test.cc325
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc68
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h211
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc293
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc1489
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc129
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.h50
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_consume_test.cc173
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h146
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc771
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h607
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h118
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cord_rep_test_util.h220
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc96
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_functions.h85
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_functions_test.cc149
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc139
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_handle.h131
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_handle_test.cc265
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_info.cc445
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_info.h298
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_info_statistics_test.cc625
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_info_test.cc341
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.cc64
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.h97
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_sample_token_test.cc208
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h87
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_update_scope.h71
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_update_scope_test.cc49
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h121
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker_test.cc145
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h2
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h50
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc59
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc372
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/arg.h222
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc21
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc25
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/bind.h52
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/bind_test.cc14
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/checker.h35
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc28
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc700
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc50
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/extension.h336
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc34
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc1104
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h20
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/output.h16
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/output_test.cc8
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc159
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/parser.h78
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc72
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/str_split_internal.h123
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/string_constant.h64
-rw-r--r--third_party/abseil-cpp/absl/strings/internal/string_constant_test.cc60
-rw-r--r--third_party/abseil-cpp/absl/strings/match.cc9
-rw-r--r--third_party/abseil-cpp/absl/strings/match.h22
-rw-r--r--third_party/abseil-cpp/absl/strings/match_test.cc17
-rw-r--r--third_party/abseil-cpp/absl/strings/numbers.cc138
-rw-r--r--third_party/abseil-cpp/absl/strings/numbers.h54
-rw-r--r--third_party/abseil-cpp/absl/strings/numbers_test.cc256
-rw-r--r--third_party/abseil-cpp/absl/strings/str_cat.cc16
-rw-r--r--third_party/abseil-cpp/absl/strings/str_cat.h2
-rw-r--r--third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc49
-rw-r--r--third_party/abseil-cpp/absl/strings/str_cat_test.cc6
-rw-r--r--third_party/abseil-cpp/absl/strings/str_format.h305
-rw-r--r--third_party/abseil-cpp/absl/strings/str_format_test.cc175
-rw-r--r--third_party/abseil-cpp/absl/strings/str_join.h2
-rw-r--r--third_party/abseil-cpp/absl/strings/str_join_test.cc8
-rw-r--r--third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc2
-rw-r--r--third_party/abseil-cpp/absl/strings/str_replace_test.cc12
-rw-r--r--third_party/abseil-cpp/absl/strings/str_split.cc4
-rw-r--r--third_party/abseil-cpp/absl/strings/str_split.h43
-rw-r--r--third_party/abseil-cpp/absl/strings/str_split_test.cc80
-rw-r--r--third_party/abseil-cpp/absl/strings/string_view.cc37
-rw-r--r--third_party/abseil-cpp/absl/strings/string_view.h198
-rw-r--r--third_party/abseil-cpp/absl/strings/string_view_test.cc95
-rw-r--r--third_party/abseil-cpp/absl/strings/substitute.cc13
-rw-r--r--third_party/abseil-cpp/absl/strings/substitute.h190
-rw-r--r--third_party/abseil-cpp/absl/strings/substitute_test.cc8
-rw-r--r--third_party/abseil-cpp/absl/strings/testdata/getline-1.txt3
-rw-r--r--third_party/abseil-cpp/absl/strings/testdata/getline-2.txt1
-rw-r--r--third_party/abseil-cpp/absl/synchronization/BUILD.bazel32
-rw-r--r--third_party/abseil-cpp/absl/synchronization/CMakeLists.txt18
-rw-r--r--third_party/abseil-cpp/absl/synchronization/blocking_counter.cc40
-rw-r--r--third_party/abseil-cpp/absl/synchronization/blocking_counter.h8
-rw-r--r--third_party/abseil-cpp/absl/synchronization/blocking_counter_benchmark.cc83
-rw-r--r--third_party/abseil-cpp/absl/synchronization/blocking_counter_test.cc12
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc6
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/futex.h154
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc7
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h57
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc320
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc261
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc4
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h10
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc3
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/waiter.cc60
-rw-r--r--third_party/abseil-cpp/absl/synchronization/internal/waiter.h12
-rw-r--r--third_party/abseil-cpp/absl/synchronization/mutex.cc249
-rw-r--r--third_party/abseil-cpp/absl/synchronization/mutex.h152
-rw-r--r--third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc229
-rw-r--r--third_party/abseil-cpp/absl/synchronization/mutex_test.cc106
-rw-r--r--third_party/abseil-cpp/absl/time/BUILD.bazel5
-rw-r--r--third_party/abseil-cpp/absl/time/CMakeLists.txt5
-rw-r--r--third_party/abseil-cpp/absl/time/civil_time.cc20
-rw-r--r--third_party/abseil-cpp/absl/time/clock.cc276
-rw-r--r--third_party/abseil-cpp/absl/time/clock.h4
-rw-r--r--third_party/abseil-cpp/absl/time/clock_test.cc4
-rw-r--r--third_party/abseil-cpp/absl/time/duration.cc154
-rw-r--r--third_party/abseil-cpp/absl/time/duration_benchmark.cc16
-rw-r--r--third_party/abseil-cpp/absl/time/duration_test.cc31
-rw-r--r--third_party/abseil-cpp/absl/time/format.cc79
-rw-r--r--third_party/abseil-cpp/absl/time/format_benchmark.cc2
-rw-r--r--third_party/abseil-cpp/absl/time/format_test.cc6
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel13
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h60
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h119
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h2
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc18
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc10
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc2
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc165
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc198
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h3
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc34
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h2
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc369
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h9
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc23
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc49
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc36
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h6
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc2
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/version2
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjanbin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accrabin130 -> 816 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Abababin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiersbin470 -> 735 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmarabin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmerabin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamakobin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banguibin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjulbin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissaubin149 -> 194 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyrebin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzavillebin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumburabin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairobin1276 -> 1955 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablancabin1919 -> 2429 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceutabin562 -> 2036 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakrybin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakarbin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaambin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djiboutibin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Doualabin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiunbin1830 -> 2295 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetownbin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaboronebin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Hararebin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburgbin190 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Jubabin458 -> 653 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampalabin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoumbin458 -> 679 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigalibin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasabin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagosbin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Librevillebin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lomebin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luandabin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashibin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusakabin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabobin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputobin131 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maserubin190 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabanebin190 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishubin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monroviabin164 -> 208 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobibin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamenabin160 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niameybin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchottbin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougoubin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novobin180 -> 149 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tomebin173 -> 254 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktubin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripolibin431 -> 625 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunisbin449 -> 689 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoekbin638 -> 955 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adakbin969 -> 2356 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchoragebin977 -> 2371 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguillabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antiguabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguainabin592 -> 884 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Airesbin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarcabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadaviabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordobabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuybin690 -> 1048 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Riojabin717 -> 1090 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendozabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegosbin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Saltabin690 -> 1048 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juanbin717 -> 1090 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luisbin717 -> 1102 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucumanbin726 -> 1104 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaiabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Arubabin177 -> 186 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncionbin884 -> 2044 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokanbin149 -> 336 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atkabin969 -> 2356 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahiabin682 -> 1024 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderasbin530 -> 1546 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbadosbin278 -> 314 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belembin394 -> 576 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belizebin1045 -> 948 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablonbin177 -> 298 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vistabin430 -> 632 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogotabin179 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boisebin999 -> 2394 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Airesbin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Baybin768 -> 2084 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grandebin952 -> 1444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancunbin529 -> 782 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracasbin190 -> 264 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarcabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayennebin151 -> 198 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caymanbin149 -> 182 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicagobin1754 -> 3576 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahuabin340 -> 1484 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbourbin149 -> 336 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordobabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Ricabin232 -> 316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Crestonbin240 -> 208 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiababin934 -> 1416 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacaobin177 -> 186 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavnbin447 -> 698 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawsonbin1029 -> 2084 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creekbin683 -> 1050 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denverbin1042 -> 2444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroitbin899 -> 2230 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominicabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmontonbin970 -> 2332 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepebin436 -> 656 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvadorbin176 -> 224 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenadabin1025 -> 2342 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelsonbin1448 -> 2240 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Waynebin531 -> 1666 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortalezabin484 -> 716 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Baybin880 -> 2192 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthabbin465 -> 1878 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Baybin1580 -> 3210 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turkbin853 -> 1848 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenadabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupebin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemalabin212 -> 280 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquilbin179 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyanabin181 -> 236 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifaxbin1672 -> 3424 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havanabin1117 -> 2416 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillobin286 -> 416 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolisbin531 -> 1666 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knoxbin1016 -> 2428 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengobin567 -> 1722 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburgbin683 -> 1904 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_Citybin522 -> 1684 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevaybin369 -> 1414 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennesbin558 -> 1694 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamacbin612 -> 1778 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolisbin531 -> 1666 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvikbin701 -> 1894 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluitbin740 -> 2032 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaicabin339 -> 482 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuybin690 -> 1048 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneaubin966 -> 2353 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisvillebin1242 -> 2772 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticellobin972 -> 2352 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_INbin1016 -> 2428 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijkbin177 -> 186 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Pazbin170 -> 232 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Limabin283 -> 406 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angelesbin1294 -> 2836 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisvillebin1242 -> 2772 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princesbin177 -> 186 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceiobin502 -> 744 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managuabin295 -> 430 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manausbin412 -> 604 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigotbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martiniquebin178 -> 232 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamorosbin437 -> 1390 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlanbin367 -> 1526 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendozabin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menomineebin917 -> 2274 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Meridabin303 -> 1422 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatlabin595 -> 1423 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_Citybin412 -> 1584 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelonbin550 -> 1666 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monctonbin1493 -> 3154 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterreybin293 -> 1390 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideobin969 -> 1510 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montrealbin1717 -> 3494 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserratbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassaubin1717 -> 2258 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_Yorkbin1744 -> 3536 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigonbin835 -> 2122 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nomebin975 -> 2367 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronhabin484 -> 716 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulahbin1043 -> 2380 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Centerbin990 -> 2380 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salembin990 -> 2380 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nuukbin465 -> 0 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinagabin484 -> 1484 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panamabin149 -> 182 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtungbin769 -> 2094 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribobin187 -> 262 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenixbin240 -> 328 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Princebin565 -> 1434 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spainbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acrebin418 -> 628 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velhobin394 -> 576 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Ricobin177 -> 246 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenasbin1209 -> 1902 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_Riverbin835 -> 2122 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inletbin692 -> 1892 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recifebin484 -> 716 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Reginabin638 -> 980 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolutebin692 -> 1892 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Brancobin418 -> 628 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosariobin708 -> 1076 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabelbin1025 -> 2342 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarembin409 -> 602 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiagobin1282 -> 2529 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingobin317 -> 458 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulobin952 -> 1444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysundbin479 -> 1916 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprockbin1042 -> 2444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitkabin956 -> 2329 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemybin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johnsbin1878 -> 3655 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kittsbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Luciabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomasbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincentbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Currentbin368 -> 560 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpabin194 -> 252 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thulebin455 -> 1502 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Baybin881 -> 2202 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuanabin1025 -> 2342 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Torontobin1717 -> 3494 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortolabin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouverbin1330 -> 2892 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virginbin177 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorsebin1029 -> 2084 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipegbin1294 -> 2868 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutatbin946 -> 2305 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknifebin729 -> 1966 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Caseybin243 -> 297 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davisbin197 -> 297 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrvillebin154 -> 194 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquariebin976 -> 1520 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawsonbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdobin1043 -> 2437 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmerbin887 -> 1418 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rotherabin132 -> 164 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Polebin1043 -> 2437 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowabin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Trollbin177 -> 1162 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostokbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyenbin676 -> 2228 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Adenbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almatybin609 -> 997 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ammanbin922 -> 1853 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyrbin743 -> 1188 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtaubin606 -> 983 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobebin615 -> 1011 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabatbin375 -> 619 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabadbin375 -> 619 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyraubin616 -> 991 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdadbin630 -> 983 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrainbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bakubin744 -> 1227 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkokbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaulbin753 -> 1221 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirutbin732 -> 2154 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkekbin618 -> 983 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bruneibin154 -> 203 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcuttabin220 -> 285 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chitabin750 -> 1221 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsanbin619 -> 949 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqingbin393 -> 533 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungkingbin393 -> 533 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombobin247 -> 372 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Daccabin231 -> 337 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascusbin1047 -> 2294 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhakabin231 -> 337 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dilibin170 -> 227 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubaibin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbebin366 -> 591 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagustabin940 -> 2028 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gazabin1230 -> 2316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbinbin393 -> 533 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebronbin1248 -> 2344 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minhbin236 -> 351 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kongbin775 -> 1203 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovdbin594 -> 891 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutskbin760 -> 1243 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbulbin1200 -> 1947 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakartabin248 -> 355 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapurabin171 -> 221 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalembin1074 -> 2288 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabulbin159 -> 208 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatkabin727 -> 1166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachibin266 -> 379 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgarbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandubin161 -> 212 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandubin161 -> 212 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandygabin775 -> 1271 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkatabin220 -> 285 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarskbin741 -> 1207 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpurbin256 -> 383 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuchingbin320 -> 483 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwaitbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macaobin791 -> 1227 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macaubin791 -> 1227 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadanbin751 -> 1222 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassarbin190 -> 254 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manilabin238 -> 328 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscatbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosiabin597 -> 2002 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetskbin726 -> 1165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirskbin753 -> 1221 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omskbin741 -> 1207 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oralbin625 -> 1005 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penhbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianakbin247 -> 353 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyangbin183 -> 237 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatarbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanaybin615 -> 1011 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylordabin624 -> 1025 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoonbin187 -> 268 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadhbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigonbin236 -> 351 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalinbin755 -> 1202 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkandbin366 -> 577 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoulbin415 -> 617 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghaibin393 -> 533 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singaporebin256 -> 383 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymskbin742 -> 1208 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipeibin511 -> 761 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkentbin366 -> 591 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisibin629 -> 1035 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehranbin2004 -> 2582 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Avivbin1074 -> 2288 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbubin154 -> 203 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphubin154 -> 203 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyobin213 -> 309 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomskbin753 -> 1221 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandangbin190 -> 254 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatarbin594 -> 891 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Batorbin594 -> 891 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqibin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nerabin771 -> 1252 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientianebin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostokbin742 -> 1208 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutskbin741 -> 1207 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangonbin187 -> 268 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburgbin760 -> 1243 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevanbin708 -> 1151 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azoresbin1453 -> 3484 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermudabin1024 -> 1978 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canarybin478 -> 1897 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verdebin175 -> 270 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroebin441 -> 1815 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroebin441 -> 1815 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayenbin676 -> 2228 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeirabin1453 -> 3475 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavikbin753 -> 1162 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgiabin132 -> 164 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helenabin130 -> 148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanleybin789 -> 1214 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACTbin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaidebin921 -> 2222 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbanebin289 -> 433 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hillbin941 -> 2243 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberrabin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Curriebin1003 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwinbin234 -> 304 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Euclabin314 -> 484 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobartbin1003 -> 2316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHIbin692 -> 1860 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindemanbin325 -> 489 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howebin692 -> 1860 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbournebin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSWbin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Northbin234 -> 304 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perthbin306 -> 460 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queenslandbin289 -> 433 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Southbin921 -> 2222 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydneybin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmaniabin1003 -> 2316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoriabin904 -> 2204 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Westbin306 -> 460 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinnabin941 -> 2243 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acrebin418 -> 628 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronhabin484 -> 716 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Eastbin952 -> 1444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Westbin412 -> 604 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CETbin621 -> 2094 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDTbin951 -> 2310 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlanticbin1672 -> 3424 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Centralbin1294 -> 2868 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Easternbin1717 -> 3494 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountainbin970 -> 2332 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundlandbin1878 -> 3655 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacificbin1330 -> 2892 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewanbin638 -> 980 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukonbin1029 -> 2084 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continentalbin1282 -> 2529 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIslandbin1102 -> 2233 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Cubabin1117 -> 2416 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EETbin497 -> 1908 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ESTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDTbin951 -> 2310 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Egyptbin1276 -> 1955 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Eirebin1496 -> 3492 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9bin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10bin115 -> 118 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11bin115 -> 118 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12bin115 -> 118 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13bin115 -> 118 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14bin115 -> 118 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9bin114 -> 117 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwichbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTCbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universalbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulubin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdambin1071 -> 2910 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorrabin389 -> 1742 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhanbin726 -> 1165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athensbin682 -> 2262 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfastbin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgradebin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlinbin705 -> 2298 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislavabin723 -> 2301 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brusselsbin1103 -> 2933 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharestbin661 -> 2184 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapestbin766 -> 2368 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingenbin497 -> 1909 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinaubin755 -> 2390 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagenbin623 -> 2137 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublinbin1496 -> 3492 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltarbin1220 -> 3052 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernseybin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinkibin481 -> 1900 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Manbin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbulbin1200 -> 1947 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jerseybin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningradbin904 -> 1493 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kievbin549 -> 2088 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirovbin717 -> 1153 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbonbin1454 -> 3469 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljanabin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Londonbin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourgbin1087 -> 2946 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madridbin897 -> 2614 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Maltabin928 -> 2620 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamnbin481 -> 1900 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minskbin808 -> 1321 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monacobin1114 -> 2944 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscowbin908 -> 1535 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosiabin597 -> 2002 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslobin676 -> 2228 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Parisbin1105 -> 2962 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgoricabin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Praguebin723 -> 2301 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rigabin694 -> 2198 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Romebin947 -> 2641 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samarabin732 -> 1215 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marinobin947 -> 2641 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevobin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratovbin726 -> 1183 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopolbin865 -> 1453 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopjebin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofiabin592 -> 2077 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholmbin497 -> 1909 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinnbin675 -> 2148 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiranebin604 -> 2084 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspolbin755 -> 2390 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovskbin760 -> 1267 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorodbin530 -> 2050 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduzbin497 -> 1909 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaticanbin947 -> 2641 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Viennabin658 -> 2200 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilniusbin676 -> 2162 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgogradbin735 -> 1165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsawbin923 -> 2654 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagrebbin478 -> 1920 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhyebin560 -> 2106 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurichbin497 -> 1909 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Factorybin113 -> 116 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GBbin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eirebin1599 -> 3648 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0bin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwichbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/HSTbin112 -> 115 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkongbin775 -> 1203 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Icelandbin753 -> 1162 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivobin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagosbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmasbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocosbin140 -> 174 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comorobin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelenbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahebin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldivesbin152 -> 199 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritiusbin179 -> 241 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayottebin191 -> 251 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunionbin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iranbin2004 -> 2582 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Israelbin1074 -> 2288 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaicabin339 -> 482 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Japanbin213 -> 309 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajaleinbin219 -> 316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Libyabin431 -> 625 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/METbin621 -> 2094 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MSTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDTbin951 -> 2310 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNortebin1025 -> 2342 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSurbin367 -> 1526 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/Generalbin412 -> 1584 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZbin1043 -> 2437 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHATbin808 -> 2068 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajobin1042 -> 2444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PRCbin393 -> 533 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDTbin951 -> 2310 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apiabin407 -> 1097 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Aucklandbin1043 -> 2437 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainvillebin201 -> 268 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chathambin808 -> 2068 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuukbin195 -> 269 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easterbin1102 -> 2233 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efatebin342 -> 466 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderburybin172 -> 234 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofobin153 -> 200 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fijibin428 -> 1077 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafutibin134 -> 166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagosbin175 -> 238 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambierbin132 -> 164 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanalbin134 -> 166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guambin350 -> 494 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulubin221 -> 329 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnstonbin221 -> 329 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kantonbin172 -> 0 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimatibin174 -> 238 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosraebin242 -> 351 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajaleinbin219 -> 316 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majurobin218 -> 310 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesasbin139 -> 173 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midwaybin146 -> 175 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Naurubin183 -> 252 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niuebin154 -> 241 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolkbin247 -> 880 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumeabin198 -> 304 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pagobin146 -> 175 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palaubin148 -> 180 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairnbin153 -> 202 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpeibin214 -> 303 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponapebin214 -> 303 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresbybin154 -> 186 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotongabin406 -> 577 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipanbin350 -> 494 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoabin146 -> 175 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahitibin133 -> 165 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawabin134 -> 166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapubin237 -> 372 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Trukbin195 -> 269 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wakebin134 -> 166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallisbin134 -> 166 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yapbin195 -> 269 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Polandbin923 -> 2654 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugalbin1454 -> 3469 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROCbin511 -> 761 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROKbin415 -> 617 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Singaporebin256 -> 383 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkeybin1200 -> 1947 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UCTbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaskabin977 -> 2371 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutianbin969 -> 2356 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizonabin240 -> 328 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Centralbin1754 -> 3576 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indianabin531 -> 1666 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Easternbin1744 -> 3536 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaiibin221 -> 329 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starkebin1016 -> 2428 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michiganbin899 -> 2230 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountainbin1042 -> 2444 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacificbin1294 -> 2836 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoabin146 -> 175 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UTCbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Universalbin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SUbin908 -> 1535 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/WETbin494 -> 1905 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulubin111 -> 114 bytes
-rw-r--r--third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab46
-rw-r--r--third_party/abseil-cpp/absl/time/internal/test_util.cc1
-rw-r--r--third_party/abseil-cpp/absl/time/time.cc7
-rw-r--r--third_party/abseil-cpp/absl/time/time.h182
-rw-r--r--third_party/abseil-cpp/absl/time/time_test.cc56
-rw-r--r--third_party/abseil-cpp/absl/time/time_zone_test.cc2
-rw-r--r--third_party/abseil-cpp/absl/types/BUILD.bazel11
-rw-r--r--third_party/abseil-cpp/absl/types/CMakeLists.txt39
-rw-r--r--third_party/abseil-cpp/absl/types/any.h31
-rw-r--r--third_party/abseil-cpp/absl/types/bad_optional_access.h2
-rw-r--r--third_party/abseil-cpp/absl/types/bad_variant_access.h4
-rw-r--r--third_party/abseil-cpp/absl/types/compare.h6
-rw-r--r--third_party/abseil-cpp/absl/types/internal/conformance_profile.h599
-rw-r--r--third_party/abseil-cpp/absl/types/internal/conformance_testing.h1386
-rw-r--r--third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h391
-rw-r--r--third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc372
-rw-r--r--third_party/abseil-cpp/absl/types/internal/parentheses.h34
-rw-r--r--third_party/abseil-cpp/absl/types/internal/transform_args.h246
-rw-r--r--third_party/abseil-cpp/absl/types/internal/variant.h10
-rw-r--r--third_party/abseil-cpp/absl/types/optional.h18
-rw-r--r--third_party/abseil-cpp/absl/types/optional_test.cc8
-rw-r--r--third_party/abseil-cpp/absl/types/span.h89
-rw-r--r--third_party/abseil-cpp/absl/types/span_test.cc15
-rw-r--r--third_party/abseil-cpp/absl/types/variant.h13
-rw-r--r--third_party/abseil-cpp/absl/types/variant_test.cc10
-rw-r--r--third_party/abseil-cpp/absl/utility/BUILD.bazel3
-rw-r--r--third_party/abseil-cpp/absl/utility/CMakeLists.txt2
-rw-r--r--third_party/abseil-cpp/absl/utility/utility.h4
-rw-r--r--third_party/abseil-cpp/ci/absl_alternate_options.h7
-rw-r--r--third_party/abseil-cpp/ci/cmake_common.sh25
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/cmake_install_test.sh30
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh32
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh29
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh31
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh30
-rw-r--r--third_party/abseil-cpp/ci/linux_docker_containers.sh21
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_gcc-4.9_libstdcxx_bazel.sh (renamed from third_party/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh)26
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh28
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh66
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/linux_gcc_alpine_cmake.sh63
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/macos_xcode_bazel.sh8
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/ci/macos_xcode_cmake.sh46
-rw-r--r--[-rwxr-xr-x]third_party/abseil-cpp/conanfile.py0
-rwxr-xr-xthird_party/abseil-cpp/create_lts.py133
1160 files changed, 14681 insertions, 53165 deletions
diff --git a/Android.bp b/Android.bp
index 31b6a63252..204ee672ef 100644
--- a/Android.bp
+++ b/Android.bp
@@ -2919,6 +2919,19 @@ cc_library_static {
"modules/audio_device/audio_device_impl.cc",
"modules/audio_device/dummy/file_audio_device_factory.cc",
],
+ target: {
+ linux_glibc: {
+ srcs: [
+ "modules/audio_device/linux/alsasymboltable_linux.cc",
+ "modules/audio_device/linux/audio_device_alsa_linux.cc",
+ "modules/audio_device/linux/audio_mixer_manager_alsa_linux.cc",
+ "modules/audio_device/linux/latebindingsymboltable_linux.cc",
+ "modules/audio_device/linux/audio_device_pulse_linux.cc",
+ "modules/audio_device/linux/audio_mixer_manager_pulse_linux.cc",
+ "modules/audio_device/linux/pulseaudiosymboltable_linux.cc",
+ ],
+ },
+ },
host_supported: true,
cflags: ["-DWEBRTC_DUMMY_FILE_DEVICES"],
static_libs: [
diff --git a/api/video/i010_buffer.cc b/api/video/i010_buffer.cc
index 7286676ded..df43d78f2a 100644
--- a/api/video/i010_buffer.cc
+++ b/api/video/i010_buffer.cc
@@ -66,12 +66,16 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Copy(
const int width = source.width();
const int height = source.height();
rtc::scoped_refptr<I010Buffer> buffer = Create(width, height);
+#if 0
RTC_CHECK_EQ(
0, libyuv::I010Copy(
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
source.DataV(), source.StrideV(), buffer->MutableDataY(),
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
buffer->MutableDataV(), buffer->StrideV(), width, height));
+#else
+ abort();
+#endif
return buffer;
}
@@ -81,12 +85,16 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Copy(
const int width = source.width();
const int height = source.height();
rtc::scoped_refptr<I010Buffer> buffer = Create(width, height);
+#if 0
RTC_CHECK_EQ(
0, libyuv::I420ToI010(
source.DataY(), source.StrideY(), source.DataU(), source.StrideU(),
source.DataV(), source.StrideV(), buffer->MutableDataY(),
buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
buffer->MutableDataV(), buffer->StrideV(), width, height));
+#else
+ abort();
+#endif
return buffer;
}
@@ -150,11 +158,15 @@ rtc::scoped_refptr<I010Buffer> I010Buffer::Rotate(
rtc::scoped_refptr<I420BufferInterface> I010Buffer::ToI420() {
rtc::scoped_refptr<I420Buffer> i420_buffer =
I420Buffer::Create(width(), height());
+#if 0
libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
i420_buffer->MutableDataY(), i420_buffer->StrideY(),
i420_buffer->MutableDataU(), i420_buffer->StrideU(),
i420_buffer->MutableDataV(), i420_buffer->StrideV(),
width(), height());
+#else
+ abort();
+#endif
return i420_buffer;
}
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md
deleted file mode 100644
index 1edf3de0ba..0000000000
--- a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/00-bug_report.md
+++ /dev/null
@@ -1,41 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: 'bug'
-assignees: ''
----
-
-**Describe the bug**
-
-Include a clear and concise description of what the problem is, including what
-you expected to happen, and what actually happened.
-
-**Steps to reproduce the bug**
-
-It's important that we are able to reproduce the problem that you are
-experiencing. Please provide all code and relevant steps to reproduce the
-problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links
-to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the
-problem are also helpful.
-
-**What version of Abseil are you using?**
-
-**What operating system and version are you using**
-
-If you are using a Linux distribution please include the name and version of the
-distribution as well.
-
-**What compiler and version are you using?**
-
-Please include the output of `gcc -v` or `clang -v`, or the equivalent for your
-compiler.
-
-**What build system are you using?**
-
-Please include the output of `bazel --version` or `cmake --version`, or the
-equivalent for your build system.
-
-**Additional context**
-
-Add any other context about the problem here.
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md
deleted file mode 100644
index 84cf349189..0000000000
--- a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/90-question.md
+++ /dev/null
@@ -1,7 +0,0 @@
----
-name: Question
-about: Have a question? Ask us anything! :-)
-title: ''
-labels: 'question'
-assignees: ''
----
diff --git a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml b/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index 0086358db1..0000000000
--- a/third_party/abseil-cpp/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1 +0,0 @@
-blank_issues_enabled: true
diff --git a/third_party/abseil-cpp/Android.bp b/third_party/abseil-cpp/Android.bp
index f1a577f680..6e8578dea8 100644
--- a/third_party/abseil-cpp/Android.bp
+++ b/third_party/abseil-cpp/Android.bp
@@ -54,12 +54,14 @@ cc_library_host_static {
name: "libwebrtc_absl_base",
defaults: ["libwebrtc_absl_defaults"],
srcs: [
+ "absl/base/dynamic_annotations.cc",
"absl/base/internal/cycleclock.cc",
+ "absl/base/internal/exponential_biased.cc",
"absl/base/internal/low_level_alloc.cc",
+ "absl/base/internal/periodic_sampler.cc",
"absl/base/internal/raw_logging.cc",
"absl/base/internal/spinlock.cc",
"absl/base/internal/spinlock_wait.cc",
- "absl/base/internal/strerror.cc",
"absl/base/internal/sysinfo.cc",
"absl/base/internal/thread_identity.cc",
"absl/base/internal/throw_delegate.cc",
@@ -100,19 +102,17 @@ cc_library_host_static {
name: "libwebrtc_absl_flags",
defaults: ["libwebrtc_absl_defaults"],
srcs: [
- "absl/flags/commandlineflag.cc",
"absl/flags/usage_config.cc",
"absl/flags/marshalling.cc",
"absl/flags/usage.cc",
"absl/flags/flag.cc",
"absl/flags/parse.cc",
- "absl/flags/internal/commandlineflag.cc",
"absl/flags/internal/flag.cc",
- "absl/flags/internal/private_handle_accessor.cc",
"absl/flags/internal/program_name.cc",
+ "absl/flags/internal/registry.cc",
"absl/flags/internal/usage.cc",
+ "absl/flags/internal/type_erased.cc",
"absl/flags/flag_test_defs.cc",
- "absl/flags/reflection.cc",
],
}
@@ -122,7 +122,6 @@ cc_library_host_static {
srcs: [
"absl/hash/internal/city.cc",
"absl/hash/internal/hash.cc",
- "absl/hash/internal/low_level_hash.cc",
],
}
@@ -133,20 +132,11 @@ cc_library_host_static {
}
cc_library_host_static {
- name: "libwebrtc_absl_profiling",
- srcs: [
- "absl/profiling/internal/exponential_biased.cc",
- "absl/profiling/internal/periodic_sampler.cc",
- ],
-}
-
-cc_library_host_static {
name: "libwebrtc_absl_status",
defaults: ["libwebrtc_absl_defaults"],
srcs: [
"absl/status/status.cc",
"absl/status/status_payload_printer.cc",
- "absl/status/statusor.cc",
],
}
@@ -160,15 +150,6 @@ cc_library_host_static {
"absl/strings/escaping.cc",
"absl/strings/internal/charconv_bigint.cc",
"absl/strings/internal/charconv_parse.cc",
- "absl/strings/internal/cord_internal.cc",
- "absl/strings/internal/cord_rep_btree.cc",
- "absl/strings/internal/cord_rep_btree_navigator.cc",
- "absl/strings/internal/cord_rep_btree_reader.cc",
- "absl/strings/internal/cord_rep_consume.cc",
- "absl/strings/internal/cord_rep_ring.cc",
- "absl/strings/internal/cordz_functions.cc",
- "absl/strings/internal/cordz_handle.cc",
- "absl/strings/internal/cordz_info.cc",
"absl/strings/internal/escaping.cc",
"absl/strings/internal/memutil.cc",
"absl/strings/internal/ostringstream.cc",
diff --git a/third_party/abseil-cpp/BUILD.bazel b/third_party/abseil-cpp/BUILD.bazel
deleted file mode 100644
index 79fb0ecd73..0000000000
--- a/third_party/abseil-cpp/BUILD.bazel
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# 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/third_party/abseil-cpp/CMake/AbseilDll.cmake b/third_party/abseil-cpp/CMake/AbseilDll.cmake
index fa323ff84b..90c9f1f642 100644
--- a/third_party/abseil-cpp/CMake/AbseilDll.cmake
+++ b/third_party/abseil-cpp/CMake/AbseilDll.cmake
@@ -1,5 +1,4 @@
include(CMakeParseArguments)
-include(GNUInstallDirs)
set(ABSL_INTERNAL_DLL_FILES
"algorithm/algorithm.h"
@@ -9,15 +8,17 @@ set(ABSL_INTERNAL_DLL_FILES
"base/casts.h"
"base/config.h"
"base/const_init.h"
+ "base/dynamic_annotations.cc"
"base/dynamic_annotations.h"
"base/internal/atomic_hook.h"
+ "base/internal/bits.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/fast_type_id.h"
+ "base/internal/exponential_biased.cc"
+ "base/internal/exponential_biased.h"
"base/internal/hide_ptr.h"
"base/internal/identity.h"
"base/internal/invoke.h"
@@ -26,14 +27,14 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -57,8 +58,6 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -120,35 +119,27 @@ set(ABSL_INTERNAL_DLL_FILES
"hash/internal/hash.h"
"hash/internal/hash.cc"
"hash/internal/spy_hash_state.h"
- "hash/internal/low_level_hash.h"
- "hash/internal/low_level_hash.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"
- "profiling/internal/exponential_biased.cc"
- "profiling/internal/exponential_biased.h"
- "profiling/internal/periodic_sampler.cc"
- "profiling/internal/periodic_sampler.h"
- "profiling/internal/sample_recorder.h"
"random/bernoulli_distribution.h"
"random/beta_distribution.h"
"random/bit_gen_ref.h"
"random/discrete_distribution.cc"
"random/discrete_distribution.h"
+ "random/distribution_format_traits.h"
"random/distributions.h"
"random/exponential_distribution.h"
"random/gaussian_distribution.cc"
"random/gaussian_distribution.h"
+ "random/internal/distributions.h"
"random/internal/distribution_caller.h"
- "random/internal/fastmath.h"
"random/internal/fast_uniform_bits.h"
+ "random/internal/fastmath.h"
+ "random/internal/gaussian_distribution_gentables.cc"
"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"
@@ -161,7 +152,6 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -182,12 +172,8 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -198,37 +184,12 @@ set(ABSL_INTERNAL_DLL_FILES
"strings/cord.h"
"strings/escaping.cc"
"strings/escaping.h"
+ "strings/internal/cord_internal.h"
"strings/internal/charconv_bigint.cc"
"strings/internal/charconv_bigint.h"
"strings/internal/charconv_parse.cc"
"strings/internal/charconv_parse.h"
- "strings/internal/cord_internal.cc"
- "strings/internal/cord_internal.h"
- "strings/internal/cord_rep_consume.h"
- "strings/internal/cord_rep_consume.cc"
- "strings/internal/cord_rep_btree.cc"
- "strings/internal/cord_rep_btree.h"
- "strings/internal/cord_rep_btree_navigator.cc"
- "strings/internal/cord_rep_btree_navigator.h"
- "strings/internal/cord_rep_btree_reader.cc"
- "strings/internal/cord_rep_btree_reader.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/cordz_functions.cc"
- "strings/internal/cordz_functions.h"
- "strings/internal/cordz_handle.cc"
- "strings/internal/cordz_handle.h"
- "strings/internal/cordz_info.cc"
- "strings/internal/cordz_info.h"
- "strings/internal/cordz_sample_token.cc"
- "strings/internal/cordz_sample_token.h"
- "strings/internal/cordz_statistics.h"
- "strings/internal/cordz_update_scope.h"
- "strings/internal/cordz_update_tracker.h"
"strings/internal/stl_type_traits.h"
- "strings/internal/string_constant.h"
"strings/match.cc"
"strings/match.h"
"strings/numbers.cc"
@@ -283,7 +244,6 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -332,8 +292,6 @@ set(ABSL_INTERNAL_DLL_FILES
"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"
@@ -458,7 +416,6 @@ set(ABSL_INTERNAL_DLL_TARGETS
"raw_hash_set"
"layout"
"tracked"
- "sample_recorder"
)
function(absl_internal_dll_contains)
@@ -522,7 +479,7 @@ function(absl_make_dll)
abseil_dll
PUBLIC
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
)
target_compile_options(
@@ -540,8 +497,8 @@ function(absl_make_dll)
${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}
+ RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
)
endfunction()
diff --git a/third_party/abseil-cpp/CMake/AbseilHelpers.cmake b/third_party/abseil-cpp/CMake/AbseilHelpers.cmake
index f2ce567511..86ff9eba2a 100644
--- a/third_party/abseil-cpp/CMake/AbseilHelpers.cmake
+++ b/third_party/abseil-cpp/CMake/AbseilHelpers.cmake
@@ -17,14 +17,13 @@
include(CMakeParseArguments)
include(AbseilConfigureCopts)
include(AbseilDll)
+include(AbseilInstallDirs)
# 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.
-if(NOT DEFINED ABSL_IDE_FOLDER)
- set(ABSL_IDE_FOLDER Abseil)
-endif()
+set(ABSL_IDE_FOLDER Abseil)
# absl_cc_library()
#
@@ -40,7 +39,7 @@ endif()
# LINKOPTS: List of link options
# 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 BUILD_TESTING=ON.
+# TESTONLY: When added, this target will only be built if user passes -DABSL_RUN_TESTS=ON to CMake.
#
# Note:
# By default, absl_cc_library will always create a library named absl_${NAME},
@@ -82,7 +81,7 @@ function(absl_cc_library)
${ARGN}
)
- if(ABSL_CC_LIB_TESTONLY AND NOT BUILD_TESTING)
+ if(ABSL_CC_LIB_TESTONLY AND NOT ABSL_RUN_TESTS)
return()
endif()
@@ -103,7 +102,7 @@ function(absl_cc_library)
endif()
endforeach()
- if(ABSL_CC_SRCS STREQUAL "")
+ if("${ABSL_CC_SRCS}" STREQUAL "")
set(ABSL_CC_LIB_IS_INTERFACE 1)
else()
set(ABSL_CC_LIB_IS_INTERFACE 0)
@@ -121,11 +120,7 @@ function(absl_cc_library)
# 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()
+ absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll)
if (${_in_dll})
# This target should be replaced by the DLL
set(_build_type "dll")
@@ -140,54 +135,8 @@ function(absl_cc_library)
set(_build_type "static")
endif()
- # Generate a pkg-config file for every library:
- if((_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
- AND ABSL_ENABLE_INSTALL)
- 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=${CMAKE_INSTALL_FULL_LIBDIR}\n\
-includedir=${CMAKE_INSTALL_FULL_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(_build_type STREQUAL "dll_dep")
+ 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.
@@ -216,7 +165,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
"${_gtest_link_define}"
)
- elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared")
+ 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}
@@ -239,7 +188,7 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
target_include_directories(${_NAME}
PUBLIC
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
)
target_compile_options(${_NAME}
PRIVATE ${ABSL_CC_LIB_COPTS})
@@ -254,23 +203,9 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal)
endif()
- if(ABSL_PROPAGATE_CXX_STD)
- # Abseil libraries require C++11 as the current minimum standard.
- # Top-level application CMake projects should ensure a consistent C++
- # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
- target_compile_features(${_NAME} PUBLIC cxx_std_11)
- else()
- # Note: This is legacy (before CMake 3.8) behavior. Setting the
- # target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
- # initialized by CMAKE_CXX_STANDARD) should have no real effect, since
- # that is the default value anyway.
- #
- # CXX_STANDARD_REQUIRED does guard against the top-level CMake project
- # not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
- # "decaying" to an older standard if the requested one isn't available).
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
- 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
@@ -278,7 +213,6 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
if(ABSL_ENABLE_INSTALL)
set_target_properties(${_NAME} PROPERTIES
OUTPUT_NAME "absl_${_NAME}"
- SOVERSION "2111.0.0"
)
endif()
else()
@@ -287,10 +221,10 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
target_include_directories(${_NAME}
INTERFACE
"$<BUILD_INTERFACE:${ABSL_COMMON_INCLUDE_DIRS}>"
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+ $<INSTALL_INTERFACE:${ABSL_INSTALL_INCLUDEDIR}>
)
- if (_build_type STREQUAL "dll")
+ if (${_build_type} STREQUAL "dll")
set(ABSL_CC_LIB_DEPS abseil_dll)
endif()
@@ -301,25 +235,15 @@ Cflags: -I\${includedir}${PC_CFLAGS}\n")
${ABSL_DEFAULT_LINKOPTS}
)
target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES})
-
- if(ABSL_PROPAGATE_CXX_STD)
- # Abseil libraries require C++11 as the current minimum standard.
- # Top-level application CMake projects should ensure a consistent C++
- # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
- target_compile_features(${_NAME} INTERFACE cxx_std_11)
-
- # (INTERFACE libraries can't have the CXX_STANDARD property set, so there
- # is no legacy behavior else case).
- endif()
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}
+ RUNTIME DESTINATION ${ABSL_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${ABSL_INSTALL_LIBDIR}
+ ARCHIVE DESTINATION ${ABSL_INSTALL_LIBDIR}
)
endif()
@@ -360,11 +284,11 @@ endfunction()
# "awesome_test.cc"
# DEPS
# absl::awesome
-# GTest::gmock
-# GTest::gtest_main
+# gmock
+# gtest_main
# )
function(absl_cc_test)
- if(NOT BUILD_TESTING)
+ if(NOT ABSL_RUN_TESTS)
return()
endif()
@@ -414,23 +338,8 @@ function(absl_cc_test)
# Add all Abseil targets to a folder in the IDE for organization.
set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test)
- if(ABSL_PROPAGATE_CXX_STD)
- # Abseil libraries require C++11 as the current minimum standard.
- # Top-level application CMake projects should ensure a consistent C++
- # standard for all compiled sources by setting CMAKE_CXX_STANDARD.
- target_compile_features(${_NAME} PUBLIC cxx_std_11)
- else()
- # Note: This is legacy (before CMake 3.8) behavior. Setting the
- # target-level CXX_STANDARD property to ABSL_CXX_STANDARD (which is
- # initialized by CMAKE_CXX_STANDARD) should have no real effect, since
- # that is the default value anyway.
- #
- # CXX_STANDARD_REQUIRED does guard against the top-level CMake project
- # not having enabled CMAKE_CXX_STANDARD_REQUIRED (which prevents
- # "decaying" to an older standard if the requested one isn't available).
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${ABSL_CXX_STANDARD})
- set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
- endif()
+ 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})
endfunction()
diff --git a/third_party/abseil-cpp/CMake/AbseilInstallDirs.cmake b/third_party/abseil-cpp/CMake/AbseilInstallDirs.cmake
new file mode 100644
index 0000000000..b67272f830
--- /dev/null
+++ b/third_party/abseil-cpp/CMake/AbseilInstallDirs.cmake
@@ -0,0 +1,20 @@
+include(GNUInstallDirs)
+
+# absl_VERSION is only set if we are an LTS release being installed, in which
+# case it may be into a system directory and so we need to make subdirectories
+# for each installed version of Abseil. This mechanism is implemented in
+# Abseil's internal Copybara (https://github.com/google/copybara) workflows and
+# isn't visible in the CMake buildsystem itself.
+
+if(absl_VERSION)
+ set(ABSL_SUBDIR "${PROJECT_NAME}_${PROJECT_VERSION}")
+ set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}/${ABSL_SUBDIR}")
+ set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${ABSL_SUBDIR}")
+ set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/{ABSL_SUBDIR}")
+ set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}/${ABSL_SUBDIR}")
+else()
+ set(ABSL_INSTALL_BINDIR "${CMAKE_INSTALL_BINDIR}")
+ set(ABSL_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
+ set(ABSL_INSTALL_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}")
+ set(ABSL_INSTALL_LIBDIR "${CMAKE_INSTALL_LIBDIR}")
+endif() \ No newline at end of file
diff --git a/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in b/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in
index 5769e3a97b..d60a33e9ac 100644
--- a/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in
+++ b/third_party/abseil-cpp/CMake/Googletest/CMakeLists.txt.in
@@ -1,14 +1,15 @@
cmake_minimum_required(VERSION 2.8.2)
-project(googletest-external NONE)
+project(googletest-download 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}"
+ 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/third_party/abseil-cpp/CMake/Googletest/DownloadGTest.cmake b/third_party/abseil-cpp/CMake/Googletest/DownloadGTest.cmake
index 9d071c9170..8a00b4550c 100644
--- a/third_party/abseil-cpp/CMake/Googletest/DownloadGTest.cmake
+++ b/third_party/abseil-cpp/CMake/Googletest/DownloadGTest.cmake
@@ -1,11 +1,10 @@
-# Integrates googletest at configure time. Based on the instructions at
-# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
+# 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
-# Set up the external googletest project, downloading the latest from Github
-# master if requested.
+# Download the latest googletest from Github master
configure_file(
${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in
- ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt
+ ${CMAKE_BINARY_DIR}/googletest-download/CMakeLists.txt
)
set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
@@ -15,17 +14,17 @@ if (BUILD_SHARED_LIBS)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1")
endif()
-# Configure and build the googletest source.
+# Configure and build the downloaded googletest source
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
- WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external )
+ 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-external)
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
@@ -38,4 +37,6 @@ 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)
+add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
+ ${CMAKE_BINARY_DIR}/googletest-build
+ EXCLUDE_FROM_ALL)
diff --git a/third_party/abseil-cpp/CMake/README.md b/third_party/abseil-cpp/CMake/README.md
index f8b27e63f6..04d5df3ab0 100644
--- a/third_party/abseil-cpp/CMake/README.md
+++ b/third_party/abseil-cpp/CMake/README.md
@@ -34,16 +34,15 @@ to include Abseil directly in your CMake project.
4. Add the **absl::** target you wish to use to the
[`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html)
section of your executable or of your library.<br>
-Here is a short CMakeLists.txt example of an application project using Abseil.
+Here is a short CMakeLists.txt example of a project file using Abseil.
```cmake
-cmake_minimum_required(VERSION 3.8.2)
-project(my_app_project)
+cmake_minimum_required(VERSION 3.5)
+project(my_project)
# Pick the C++ standard to compile with.
# Abseil currently supports C++11, C++14, and C++17.
set(CMAKE_CXX_STANDARD 11)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_subdirectory(abseil-cpp)
@@ -51,47 +50,9 @@ add_executable(my_exe source.cpp)
target_link_libraries(my_exe absl::base absl::synchronization absl::strings)
```
-Note that if you are developing a library designed for use by other clients, you
-should instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as
-the current top-level CMake project) and configure the minimum required C++
-standard at the target level. If you require a later minimum C++ standard than
-Abseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which
-will control Abseil library targets) is set to at least that minimum. For
-example:
-
-```cmake
-cmake_minimum_required(VERSION 3.8.2)
-project(my_lib_project)
-
-# Leave C++ standard up to the root application, so set it only if this is the
-# current top-level CMake project.
-if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR)
- set(CMAKE_CXX_STANDARD 17)
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
-endif()
-
-add_subdirectory(abseil-cpp)
-
-add_library(my_lib source.cpp)
-target_link_libraries(my_lib absl::base absl::synchronization absl::strings)
-
-# Enforce that my_lib requires C++17. Important to document for clients that they
-# must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility
-# (since otherwise, Abseil library targets could be compiled with a lower C++
-# standard than my_lib).
-target_compile_features(my_lib PUBLIC cxx_std_17)
-if(CMAKE_CXX_STANDARD LESS 17)
- message(FATAL_ERROR
- "my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})")
-endif()
-```
-
-Then the top-level application project that uses your library is responsible for
-setting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high.
-
### Running Abseil Tests with CMake
-Use the `-DBUILD_TESTING=ON` flag to run Abseil tests.
+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.
You will need to provide Abseil with a Googletest dependency. There are two
options for how to do this:
@@ -109,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 -DBUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON ..
+cmake -DABSL_USE_GOOGLETEST_HEAD=ON -DABSL_RUN_TESTS=ON ..
make -j
ctest
```
@@ -132,54 +93,9 @@ absl::flags
absl::memory
absl::meta
absl::numeric
-absl::random_random
+absl::random
absl::strings
absl::synchronization
absl::time
absl::utility
```
-
-## Traditional CMake Set-Up
-
-For larger projects, it may make sense to use the traditional CMake set-up where you build and install projects separately.
-
-First, you'd need to build and install Google Test:
-```
-cmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON
-cmake --build /build/googletest --target install
-```
-
-Then you need to configure and build Abseil. Make sure you enable `ABSL_USE_EXTERNAL_GOOGLETEST` and `ABSL_FIND_GOOGLETEST`. You also need to enable `ABSL_ENABLE_INSTALL` so that you can install Abseil itself.
-```
-cmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON
-cmake --build /temporary/build/abseil-cpp
-```
-
-(`CMAKE_PREFIX_PATH` is where you already have Google Test installed; `CMAKE_INSTALL_PREFIX` is where you want to have Abseil installed; they can be different.)
-
-Run the tests:
-```
-ctest --test-dir /temporary/build/abseil-cpp
-```
-
-And finally install:
-```
-cmake --build /temporary/build/abseil-cpp --target install
-```
-
-# CMake Option Synposis
-
-## Enable Standard CMake Installation
-
-`-DABSL_ENABLE_INSTALL=ON`
-
-## Google Test Options
-
-`-DBUILD_TESTING=ON` must be set to enable testing
-
-- Have Abseil download and build Google Test for you: `-DABSL_USE_EXTERNAL_GOOGLETEST=OFF` (default)
- - Download and build latest Google Test: `-DABSL_USE_GOOGLETEST_HEAD=ON`
- - Download specific Google Test version (ZIP archive): `-DABSL_GOOGLETEST_DOWNLOAD_URL=https://.../version.zip`
- - Use Google Test from specific local directory: `-DABSL_LOCAL_GOOGLETEST_DIR=/path/to/googletest`
-- Use Google Test included elsewhere in your project: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON`
-- Use standard CMake `find_package(CTest)` to find installed Google Test: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON`
diff --git a/third_party/abseil-cpp/CMake/abslConfig.cmake.in b/third_party/abseil-cpp/CMake/abslConfig.cmake.in
index 62d246d01e..60847fa772 100644
--- a/third_party/abseil-cpp/CMake/abslConfig.cmake.in
+++ b/third_party/abseil-cpp/CMake/abslConfig.cmake.in
@@ -1,8 +1,7 @@
# absl CMake configuration file.
-include(CMakeFindDependencyMacro)
-find_dependency(Threads)
+include(FindThreads)
@PACKAGE_INIT@
-include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake")
+include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") \ No newline at end of file
diff --git a/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt b/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt
index b865b2ec50..06b797e9ed 100644
--- a/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt
+++ b/third_party/abseil-cpp/CMake/install_test_project/CMakeLists.txt
@@ -18,8 +18,10 @@
cmake_minimum_required(VERSION 3.5)
project(absl_cmake_testing CXX)
+set(CMAKE_CXX_STANDARD 11)
+
add_executable(simple simple.cc)
find_package(absl REQUIRED)
-target_link_libraries(simple absl::strings absl::config)
+target_link_libraries(simple absl::strings)
diff --git a/third_party/abseil-cpp/CMake/install_test_project/simple.cc b/third_party/abseil-cpp/CMake/install_test_project/simple.cc
index 7daa7f0901..e9e352912b 100644
--- a/third_party/abseil-cpp/CMake/install_test_project/simple.cc
+++ b/third_party/abseil-cpp/CMake/install_test_project/simple.cc
@@ -14,17 +14,8 @@
// limitations under the License.
#include <iostream>
-#include "absl/base/config.h"
#include "absl/strings/substitute.h"
-#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION != 99998877
-#error ABSL_LTS_RELEASE_VERSION is not set correctly.
-#endif
-
-#if !defined(ABSL_LTS_RELEASE_PATCH_LEVEL) || ABSL_LTS_RELEASE_PATCH_LEVEL != 0
-#error ABSL_LTS_RELEASE_PATCH_LEVEL is not set correctly.
-#endif
-
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/third_party/abseil-cpp/CMake/install_test_project/test.sh b/third_party/abseil-cpp/CMake/install_test_project/test.sh
index 5a78c92cd1..99989b031d 100755..100644
--- a/third_party/abseil-cpp/CMake/install_test_project/test.sh
+++ b/third_party/abseil-cpp/CMake/install_test_project/test.sh
@@ -13,60 +13,70 @@
# WITHOUT 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
+
+# "Unit" and integration tests for Absl CMake installation
+
+# TODO(absl-team): This script isn't fully hermetic because
+# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
+# version of GoogleTest. This means that an upstream change to GoogleTest could
+# break this test. Fix this by allowing this script to pin to a known-good
+# version of GoogleTest.
# Fail on any error. Treat unset variables an error. Print commands as executed.
set -euox pipefail
+install_absl() {
+ pushd "${absl_build_dir}"
+ if [[ "${#}" -eq 1 ]]; then
+ cmake -DCMAKE_INSTALL_PREFIX="${1}" "${absl_dir}"
+ else
+ cmake "${absl_dir}"
+ fi
+ cmake --build . --target install -- -j
+ popd
+}
+
+uninstall_absl() {
+ xargs rm < "${absl_build_dir}"/install_manifest.txt
+ rm -rf "${absl_build_dir}"
+ mkdir -p "${absl_build_dir}"
+}
+
+lts_install=""
+
+while getopts ":l" lts; do
+ case "${lts}" in
+ l )
+ lts_install="true"
+ ;;
+ esac
+done
+
absl_dir=/abseil-cpp
-absl_build_dir=/buildfs
-googletest_builddir=/googletest_builddir
+absl_build_dir=/buildfs/absl-build
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
-
-# Build and install GoogleTest
-mkdir "${googletest_builddir}"
-pushd "${googletest_builddir}"
-curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${ABSL_GOOGLETEST_COMMIT}".zip
-unzip "${ABSL_GOOGLETEST_COMMIT}".zip
-pushd "googletest-${ABSL_GOOGLETEST_COMMIT}"
-mkdir build
-pushd build
-cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" ..
-make -j $(nproc)
-make install
-ldconfig
-popd
-popd
-popd
+mkdir -p "${absl_build_dir}"
+mkdir -p "${project_build_dir}"
-# Run the LTS transformations
-./create_lts.py 99998877
-
-# Build and install Abseil
-pushd "${absl_build_dir}"
-cmake "${absl_dir}" \
- -DABSL_USE_EXTERNAL_GOOGLETEST=ON \
- -DABSL_FIND_GOOGLETEST=ON \
- -DCMAKE_BUILD_TYPE=Release \
- -DBUILD_TESTING=ON \
- -DBUILD_SHARED_LIBS="${build_shared_libs}"
-make -j $(nproc)
-ctest -j $(nproc)
-make install
-ldconfig
-popd
+if [[ "${lts_install}" ]]; then
+ install_dir="/usr/local"
+else
+ install_dir="${project_build_dir}"/install
+fi
+mkdir -p "${install_dir}"
-# Test the project against the installed Abseil
-mkdir -p "${project_build_dir}"
+# Test build, install, and link against installed abseil
pushd "${project_build_dir}"
-cmake "${project_dir}"
+if [[ "${lts_install}" ]]; then
+ install_absl
+ cmake "${project_dir}"
+else
+ install_absl "${install_dir}"
+ cmake "${project_dir}" -DCMAKE_PREFIX_PATH="${install_dir}"
+fi
+
cmake --build . --target simple
output="$(${project_build_dir}/simple "printme" 2>&1)"
@@ -78,35 +88,57 @@ 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"
+# Test that we haven't accidentally made absl::abslblah
+pushd "${install_dir}"
-int main(int argc, char **argv) {
- absl::PrintF("Hello Abseil!\n");
- return EXIT_SUCCESS;
-}
-EOF
+# Starting in CMake 3.12 the default install dir is lib$bit_width
+if [[ -d lib64 ]]; then
+ libdir="lib64"
+elif [[ -d lib ]]; then
+ libdir="lib"
+else
+ echo "ls *, */*, */*/*:"
+ ls *
+ ls */*
+ ls */*/*
+ echo "unknown lib dir"
+fi
-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[@]}"
+if [[ "${lts_install}" ]]; then
+ # LTS versions append the date of the release to the subdir.
+ # 9999/99/99 is the dummy date used in the local_lts workflow.
+ absl_subdir="absl_99999999"
else
- pc_args=($(pkg-config --cflags --libs absl_str_format))
- g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}"
+ absl_subdir="absl"
fi
-hello="$(./hello-abseil)"
-[[ "${hello}" == "Hello Abseil!" ]]
+if ! grep absl::strings "${libdir}/cmake/${absl_subdir}/abslTargets.cmake"; then
+ cat "${libdir}"/cmake/absl/abslTargets.cmake
+ echo "CMake targets named incorrectly"
+ exit 1
+fi
+
+uninstall_absl
popd
+if [[ ! "${lts_install}" ]]; then
+ # Test that we warn if installed without a prefix or a system prefix
+ output="$(install_absl 2>&1)"
+ if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
+ echo "Install without prefix didn't warn as expected. Output:"
+ echo "${output}"
+ exit 1
+ fi
+ uninstall_absl
+
+ output="$(install_absl /usr 2>&1)"
+ if [[ "${output}" != *"Please set CMAKE_INSTALL_PREFIX"* ]]; then
+ echo "Install with /usr didn't warn as expected. Output:"
+ echo "${output}"
+ exit 1
+ fi
+ uninstall_absl
+fi
+
echo "Install test complete!"
exit 0
diff --git a/third_party/abseil-cpp/CMakeLists.txt b/third_party/abseil-cpp/CMakeLists.txt
index 750a47557d..48cb6eb5cf 100644
--- a/third_party/abseil-cpp/CMakeLists.txt
+++ b/third_party/abseil-cpp/CMakeLists.txt
@@ -22,36 +22,15 @@
cmake_minimum_required(VERSION 3.5)
# Compiler id for Apple Clang is now AppleClang.
-if (POLICY CMP0025)
- cmake_policy(SET CMP0025 NEW)
-endif (POLICY CMP0025)
+cmake_policy(SET CMP0025 NEW)
# if command can use IN_LIST
-if (POLICY CMP0057)
- cmake_policy(SET CMP0057 NEW)
-endif (POLICY CMP0057)
+cmake_policy(SET CMP0057 NEW)
-# Project version variables are the empty string if version is unspecified
-if (POLICY CMP0048)
- cmake_policy(SET CMP0048 NEW)
-endif (POLICY CMP0048)
+# Project version variables are the empty std::string if version is unspecified
+cmake_policy(SET CMP0048 NEW)
-# option() honor variables
-if (POLICY CMP0077)
- cmake_policy(SET CMP0077 NEW)
-endif (POLICY CMP0077)
-
-# Allow the user to specify the MSVC runtime
-if (POLICY CMP0091)
- cmake_policy(SET CMP0091 NEW)
-endif (POLICY CMP0091)
-
-# Set BUILD_TESTING to OFF by default.
-# This must come before the project() and include(CTest) lines.
-OPTION(BUILD_TESTING "Build tests" OFF)
-
-project(absl LANGUAGES CXX VERSION 20211102)
-include(CTest)
+project(absl CXX)
# Output directory is correct by default for most build setups. However, when
# building Abseil as a DLL, it is important to have the DLL in the same
@@ -61,17 +40,10 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp))
# in the source tree of a project that uses it, install rules are disabled.
-if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
- option(ABSL_ENABLE_INSTALL "Enable install rule" OFF)
+if(NOT "^${CMAKE_SOURCE_DIR}$" STREQUAL "^${PROJECT_SOURCE_DIR}$")
+ set(ABSL_ENABLE_INSTALL FALSE)
else()
- option(ABSL_ENABLE_INSTALL "Enable install rule" ON)
-endif()
-
-option(ABSL_PROPAGATE_CXX_STD
- "Use CMake C++ standard meta features (e.g. cxx_std_11) that propagate to targets that link to Abseil"
- OFF) # TODO: Default to ON for CMake 3.8 and greater.
-if((${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.8) AND (NOT ABSL_PROPAGATE_CXX_STD))
- message(WARNING "A future Abseil release will default ABSL_PROPAGATE_CXX_STD to ON for CMake 3.8 and up. We recommend enabling this option to ensure your project still builds correctly.")
+ set(ABSL_ENABLE_INSTALL TRUE)
endif()
list(APPEND CMAKE_MODULE_PATH
@@ -79,8 +51,8 @@ list(APPEND CMAKE_MODULE_PATH
${CMAKE_CURRENT_LIST_DIR}/absl/copts
)
+include(AbseilInstallDirs)
include(CMakePackageConfigHelpers)
-include(GNUInstallDirs)
include(AbseilDll)
include(AbseilHelpers)
@@ -109,87 +81,56 @@ endif()
## pthread
find_package(Threads REQUIRED)
-include(CMakeDependentOption)
-
-option(ABSL_USE_EXTERNAL_GOOGLETEST
- "If ON, Abseil will assume that the targets for GoogleTest are already provided by the including project. This makes sense when Abseil is used with add_subproject." OFF)
-
-cmake_dependent_option(ABSL_FIND_GOOGLETEST
- "If ON, Abseil will use find_package(GTest) rather than assuming that GoogleTest is already provided by the including project."
- ON
- "ABSL_USE_EXTERNAL_GOOGLETEST"
- OFF)
-
-
option(ABSL_USE_GOOGLETEST_HEAD
- "If ON, abseil will download HEAD from GoogleTest at config time." OFF)
+ "If ON, abseil will download HEAD from googletest at config time." OFF)
-set(ABSL_GOOGLETEST_DOWNLOAD_URL "" CACHE STRING "If set, download GoogleTest from this URL")
+option(ABSL_RUN_TESTS "If ON, Abseil tests will be run." OFF)
-set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH
- "If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout."
- )
+if(${ABSL_RUN_TESTS})
+ # enable CTest. This will set BUILD_TESTING to ON unless otherwise specified
+ # on the command line
+ include(CTest)
+ enable_testing()
+endif()
+## check targets
if(BUILD_TESTING)
- ## check targets
- if (ABSL_USE_EXTERNAL_GOOGLETEST)
- if (ABSL_FIND_GOOGLETEST)
- find_package(GTest REQUIRED)
- else()
- if (NOT TARGET gtest AND NOT TARGET GTest::gtest)
- message(FATAL_ERROR "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.")
- endif()
- endif()
- else()
- set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build)
- if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL)
- message(FATAL_ERROR "Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL")
- endif()
- if(ABSL_USE_GOOGLETEST_HEAD)
- set(absl_gtest_download_url "https://github.com/google/googletest/archive/master.zip")
- elseif(ABSL_GOOGLETEST_DOWNLOAD_URL)
- set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL})
- endif()
- if(absl_gtest_download_url)
- set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
- else()
- set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR})
- endif()
+
+ if(${ABSL_USE_GOOGLETEST_HEAD})
include(CMake/Googletest/DownloadGTest.cmake)
+ set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src)
+ set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build)
endif()
- if (NOT ABSL_FIND_GOOGLETEST)
- # When Google Test is included directly rather than through find_package, the aliases are missing.
- add_library(GTest::gtest ALIAS gtest)
- add_library(GTest::gtest_main ALIAS gtest_main)
- add_library(GTest::gmock ALIAS gmock)
- add_library(GTest::gmock_main ALIAS gmock_main)
- endif()
+ check_target(gtest)
+ check_target(gtest_main)
+ check_target(gmock)
- check_target(GTest::gtest)
- check_target(GTest::gtest_main)
- check_target(GTest::gmock)
- check_target(GTest::gmock_main)
+ list(APPEND ABSL_TEST_COMMON_LIBRARIES
+ gtest_main
+ gtest
+ gmock
+ ${CMAKE_THREAD_LIBS_INIT}
+ )
endif()
add_subdirectory(absl)
if(ABSL_ENABLE_INSTALL)
-
# install as a subdirectory only
install(EXPORT ${PROJECT_NAME}Targets
NAMESPACE absl::
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
)
configure_package_config_file(
CMake/abslConfig.cmake.in
"${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
- INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ INSTALL_DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ DESTINATION "${ABSL_INSTALL_CONFIGDIR}"
)
# Abseil only has a version in LTS releases. This mechanism is accomplished
@@ -202,16 +143,14 @@ if(ABSL_ENABLE_INSTALL)
)
install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake"
- DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}"
+ DESTINATION ${ABSL_INSTALL_CONFIGDIR}
)
endif() # absl_VERSION
install(DIRECTORY absl
- DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+ DESTINATION ${ABSL_INSTALL_INCLUDEDIR}
FILES_MATCHING
PATTERN "*.inc"
PATTERN "*.h"
- PATTERN "copts" EXCLUDE
- PATTERN "testdata" EXCLUDE
- )
+ )
endif() # ABSL_ENABLE_INSTALL
diff --git a/third_party/abseil-cpp/FAQ.md b/third_party/abseil-cpp/FAQ.md
index fbd92ce975..78028fc09f 100644
--- a/third_party/abseil-cpp/FAQ.md
+++ b/third_party/abseil-cpp/FAQ.md
@@ -27,10 +27,7 @@ compiler, there several ways to do this:
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. If you
-are developing a library designed to be used by other clients, you should
-instead leave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard
-required by each of your library targets via `target_compile_features`. See the
+`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.
diff --git a/third_party/abseil-cpp/LTS.md b/third_party/abseil-cpp/LTS.md
new file mode 100644
index 0000000000..94363b6a36
--- /dev/null
+++ b/third_party/abseil-cpp/LTS.md
@@ -0,0 +1,15 @@
+# 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 December 18, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_12_18/)
+* [LTS Branch June 20, 2018](https://github.com/abseil/abseil-cpp/tree/lts_2018_06_20/)
+* [LTS Branch August 8, 2019](https://github.com/abseil/abseil-cpp/tree/lts_2019_08_08/)
diff --git a/third_party/abseil-cpp/METADATA b/third_party/abseil-cpp/METADATA
index a36d767ad7..7ce40fff58 100644
--- a/third_party/abseil-cpp/METADATA
+++ b/third_party/abseil-cpp/METADATA
@@ -10,9 +10,9 @@ third_party {
}
url {
type: GIT
- value: "https://github.com/abseil/abseil-cpp"
+ value: "https://github.googlesource.com/abseil/abseil-cpp/+/refs/heads/lts_2020_02_25"
}
- version: "20211102.0"
- last_upgrade_date { year: 2021 month: 12 day: 21 }
+ version: "fcb104594b0bb4b8ac306cb2f55ecdad40974683"
+ last_upgrade_date { year: 2020 month: 04 day: 27 }
}
diff --git a/third_party/abseil-cpp/README.md b/third_party/abseil-cpp/README.md
index db3a7b447a..85de569658 100644
--- a/third_party/abseil-cpp/README.md
+++ b/third_party/abseil-cpp/README.md
@@ -9,9 +9,7 @@ standard library.
- [About Abseil](#about)
- [Quickstart](#quickstart)
- [Building Abseil](#build)
-- [Support](#support)
- [Codemap](#codemap)
-- [Releases](#releases)
- [License](#license)
- [Links](#links)
@@ -44,22 +42,14 @@ the Abseil code, running tests, and getting a simple binary working.
<a name="build"></a>
## Building Abseil
-[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official
-build systems for Abseil.
+[Bazel](https://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.
-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.
+<a name="cmake"></a>
+If you require CMake support, please check the
+[CMake build instructions](CMake/README.md).
## Codemap
@@ -72,9 +62,6 @@ 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.
@@ -92,12 +79,6 @@ 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.
-* [`profiling`](absl/profiling/)
- <br /> The `profiling` library contains utility code for profiling C++
- entities. It is currently a private dependency of other Abseil libraries.
-* [`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
@@ -116,15 +97,6 @@ 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
diff --git a/third_party/abseil-cpp/WORKSPACE b/third_party/abseil-cpp/WORKSPACE
index c9aa8cafa0..f2b1046446 100644
--- a/third_party/abseil-cpp/WORKSPACE
+++ b/third_party/abseil-cpp/WORKSPACE
@@ -15,30 +15,31 @@
#
workspace(name = "com_google_absl")
-
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# GoogleTest/GoogleMock framework. Used by most unit-tests.
http_archive(
- name = "com_google_googletest", # 2021-07-09T13:28:13Z
- sha256 = "12ef65654dc01ab40f6f33f9d02c04f2097d2cd9fbe48dc6001b29543583b0ad",
- strip_prefix = "googletest-8d51ffdfab10b3fba636ae69bc03da4b54f8c235",
- # Keep this URL in sync with ABSL_GOOGLETEST_COMMIT in ci/cmake_common.sh.
- urls = ["https://github.com/google/googletest/archive/8d51ffdfab10b3fba636ae69bc03da4b54f8c235.zip"],
+ name = "com_google_googletest",
+ urls = ["https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip"], # 2019-01-07
+ strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb",
+ sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86",
)
# Google benchmark.
http_archive(
- name = "com_github_google_benchmark", # 2021-09-20T09:19:51Z
- sha256 = "62e2f2e6d8a744d67e4bbc212fcfd06647080de4253c97ad5c6749e09faf2cb0",
- strip_prefix = "benchmark-0baacde3618ca617da95375e0af13ce1baadea47",
- urls = ["https://github.com/google/benchmark/archive/0baacde3618ca617da95375e0af13ce1baadea47.zip"],
+ name = "com_github_google_benchmark",
+ urls = ["https://github.com/google/benchmark/archive/16703ff83c1ae6d53e5155df3bb3ab0bc96083be.zip"],
+ strip_prefix = "benchmark-16703ff83c1ae6d53e5155df3bb3ab0bc96083be",
+ sha256 = "59f918c8ccd4d74b6ac43484467b500f1d64b40cc1010daa055375b322a43ba3",
)
-# Bazel platform rules.
+# C++ rules for Bazel.
http_archive(
- name = "platforms",
- sha256 = "b601beaf841244de5c5a50d2b2eddd34839788000fa1be4260ce6603ca0d8eb7",
- strip_prefix = "platforms-98939346da932eef0b54cf808622f5bb0928f00b",
- urls = ["https://github.com/bazelbuild/platforms/archive/98939346da932eef0b54cf808622f5bb0928f00b.zip"],
+ name = "rules_cc",
+ sha256 = "9a446e9dd9c1bb180c86977a8dc1e9e659550ae732ae58bd2e8fd51e15b2c91d",
+ strip_prefix = "rules_cc-262ebec3c2296296526740db4aefce68c80de7fa",
+ urls = [
+ "https://mirror.bazel.build/github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
+ "https://github.com/bazelbuild/rules_cc/archive/262ebec3c2296296526740db4aefce68c80de7fa.zip",
+ ],
)
diff --git a/third_party/abseil-cpp/absl/BUILD.bazel b/third_party/abseil-cpp/absl/BUILD.bazel
index d799b7fe51..5a03acf87c 100644
--- a/third_party/abseil-cpp/absl/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/BUILD.bazel
@@ -12,69 +12,48 @@
# WITHOUT 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"])
-
-config_setting(
- name = "clang_compiler",
- flag_values = {
- "@bazel_tools//tools/cpp:compiler": "clang",
- },
- visibility = [":__subpackages__"],
+load(
+ ":compiler_config_setting.bzl",
+ "create_llvm_config",
)
-config_setting(
- name = "msvc_compiler",
- flag_values = {
- "@bazel_tools//tools/cpp:compiler": "msvc-cl",
- },
- visibility = [":__subpackages__"],
-)
+package(default_visibility = ["//visibility:public"])
-config_setting(
- name = "clang-cl_compiler",
- flag_values = {
- "@bazel_tools//tools/cpp:compiler": "clang-cl",
- },
+licenses(["notice"]) # Apache 2.0
+
+create_llvm_config(
+ name = "llvm_compiler",
visibility = [":__subpackages__"],
)
config_setting(
name = "osx",
constraint_values = [
- "@platforms//os:osx",
+ "@bazel_tools//platforms:osx",
],
)
config_setting(
name = "ios",
constraint_values = [
- "@platforms//os:ios",
+ "@bazel_tools//platforms:ios",
],
)
config_setting(
- name = "ppc",
- values = {
- "cpu": "ppc",
- },
- visibility = [":__subpackages__"],
-)
-
-config_setting(
- name = "wasm",
+ name = "windows",
values = {
- "cpu": "wasm32",
+ "cpu": "x64_windows",
},
visibility = [":__subpackages__"],
)
config_setting(
- name = "fuchsia",
+ name = "ppc",
values = {
- "cpu": "fuchsia",
+ "cpu": "ppc",
},
visibility = [":__subpackages__"],
)
diff --git a/third_party/abseil-cpp/absl/CMakeLists.txt b/third_party/abseil-cpp/absl/CMakeLists.txt
index b1715846f0..fbfa7822b5 100644
--- a/third_party/abseil-cpp/absl/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/CMakeLists.txt
@@ -16,7 +16,6 @@
add_subdirectory(base)
add_subdirectory(algorithm)
-add_subdirectory(cleanup)
add_subdirectory(container)
add_subdirectory(debugging)
add_subdirectory(flags)
@@ -25,7 +24,6 @@ add_subdirectory(hash)
add_subdirectory(memory)
add_subdirectory(meta)
add_subdirectory(numeric)
-add_subdirectory(profiling)
add_subdirectory(random)
add_subdirectory(status)
add_subdirectory(strings)
diff --git a/third_party/abseil-cpp/absl/abseil.podspec.gen.py b/third_party/abseil-cpp/absl/abseil.podspec.gen.py
index 63752980d0..6aefb794df 100755..100644
--- a/third_party/abseil-cpp/absl/abseil.podspec.gen.py
+++ b/third_party/abseil-cpp/absl/abseil.podspec.gen.py
@@ -40,8 +40,8 @@ Pod::Spec.new do |s|
'USE_HEADERMAP' => 'NO',
'ALWAYS_SEARCH_USER_PATHS' => 'NO',
}
- s.ios.deployment_target = '9.0'
- s.osx.deployment_target = '10.10'
+ s.ios.deployment_target = '7.0'
+ s.osx.deployment_target = '10.9'
s.tvos.deployment_target = '9.0'
s.watchos.deployment_target = '2.0'
"""
diff --git a/third_party/abseil-cpp/absl/algorithm/BUILD.bazel b/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
index afc5263998..6a96420b96 100644
--- a/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/algorithm/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,16 +24,14 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "algorithm",
hdrs = ["algorithm.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- "//absl/base:config",
- ],
+ deps = ["//absl/base:config"],
)
cc_test(
diff --git a/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt b/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt
index 609d858946..56cd0fb85b 100644
--- a/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/algorithm/CMakeLists.txt
@@ -35,7 +35,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::algorithm
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -65,5 +65,5 @@ absl_cc_test(
absl::core_headers
absl::memory
absl::span
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/algorithm/container.h b/third_party/abseil-cpp/absl/algorithm/container.h
index c38a4a63db..d72532decf 100644
--- a/third_party/abseil-cpp/absl/algorithm/container.h
+++ b/third_party/abseil-cpp/absl/algorithm/container.h
@@ -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>
@@ -188,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 fulfill a condition.
+// test if no elements in a container fulfil 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),
@@ -340,45 +340,24 @@ 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. Applies `==` to
-// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
+// return the first element where two ordered containers differ.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIterPairType<C1, C2>
c_mismatch(C1& c1, C2& c2) {
- auto first1 = container_algorithm_internal::c_begin(c1);
- auto last1 = container_algorithm_internal::c_end(c1);
- auto first2 = container_algorithm_internal::c_begin(c2);
- 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);
+ return std::mismatch(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2));
}
// Overload of c_mismatch() for using a predicate evaluation other than `==` as
-// the function's test condition. Applies `pred`to the first N elements of `c1`
-// and `c2`, where N = min(size(c1), size(c2)).
+// the function's test condition.
template <typename C1, typename C2, typename BinaryPredicate>
container_algorithm_internal::ContainerIterPairType<C1, C2>
-c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) {
- auto first1 = container_algorithm_internal::c_begin(c1);
- auto last1 = container_algorithm_internal::c_end(c1);
- auto first2 = container_algorithm_internal::c_begin(c2);
- 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_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_equal()
@@ -560,20 +539,12 @@ BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator 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. Swaps the
-// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)).
+// swap a container's elements with another container's elements.
template <typename C1, typename C2>
container_algorithm_internal::ContainerIter<C2> c_swap_ranges(C1& c1, C2& c2) {
- auto first1 = container_algorithm_internal::c_begin(c1);
- auto last1 = container_algorithm_internal::c_end(c1);
- auto first2 = container_algorithm_internal::c_begin(c2);
- auto last2 = container_algorithm_internal::c_end(c2);
-
- using std::swap;
- for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) {
- swap(*first1, *first2);
- }
- return first2;
+ return std::swap_ranges(container_algorithm_internal::c_begin(c1),
+ container_algorithm_internal::c_end(c1),
+ container_algorithm_internal::c_begin(c2));
}
// c_transform()
@@ -591,23 +562,16 @@ OutputIterator c_transform(const InputSequence& input, OutputIterator output,
}
// Overload of c_transform() for performing a transformation using a binary
-// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`,
-// where N = min(size(c1), size(c2)).
+// predicate.
template <typename InputSequence1, typename InputSequence2,
typename OutputIterator, typename BinaryOp>
OutputIterator c_transform(const InputSequence1& input1,
const InputSequence2& input2, OutputIterator output,
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;
+ 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));
}
// c_replace()
@@ -905,11 +869,11 @@ void c_sort(C& c) {
// Overload of c_sort() for performing a `comp` comparison other than the
// default `operator<`.
-template <typename C, typename LessThan>
-void c_sort(C& c, LessThan&& comp) {
+template <typename C, typename Compare>
+void c_sort(C& c, Compare&& comp) {
std::sort(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_stable_sort()
@@ -925,11 +889,11 @@ void c_stable_sort(C& c) {
// Overload of c_stable_sort() for performing a `comp` comparison other than the
// default `operator<`.
-template <typename C, typename LessThan>
-void c_stable_sort(C& c, LessThan&& comp) {
+template <typename C, typename Compare>
+void c_stable_sort(C& c, Compare&& comp) {
std::stable_sort(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_is_sorted()
@@ -944,11 +908,11 @@ bool c_is_sorted(const C& c) {
// c_is_sorted() overload for performing a `comp` comparison other than the
// default `operator<`.
-template <typename C, typename LessThan>
-bool c_is_sorted(const C& c, LessThan&& comp) {
+template <typename C, typename Compare>
+bool c_is_sorted(const C& c, Compare&& comp) {
return std::is_sorted(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_partial_sort()
@@ -966,23 +930,22 @@ void c_partial_sort(
// Overload of c_partial_sort() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename RandomAccessContainer, typename LessThan>
+template <typename RandomAccessContainer, typename Compare>
void c_partial_sort(
RandomAccessContainer& sequence,
container_algorithm_internal::ContainerIter<RandomAccessContainer> middle,
- LessThan&& comp) {
+ Compare&& comp) {
std::partial_sort(container_algorithm_internal::c_begin(sequence), middle,
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_partial_sort_copy()
//
// Container-based version of the <algorithm> `std::partial_sort_copy()`
-// 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.
+// function to sort elements within a container such that elements before
+// `middle` are sorted in ascending order, and return the result within an
+// iterator.
template <typename C, typename RandomAccessContainer>
container_algorithm_internal::ContainerIter<RandomAccessContainer>
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
@@ -994,15 +957,15 @@ c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) {
// Overload of c_partial_sort_copy() for performing a `comp` comparison other
// than the default `operator<`.
-template <typename C, typename RandomAccessContainer, typename LessThan>
+template <typename C, typename RandomAccessContainer, typename Compare>
container_algorithm_internal::ContainerIter<RandomAccessContainer>
c_partial_sort_copy(const C& sequence, RandomAccessContainer& result,
- LessThan&& comp) {
+ Compare&& comp) {
return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
container_algorithm_internal::c_begin(result),
container_algorithm_internal::c_end(result),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_is_sorted_until()
@@ -1018,12 +981,12 @@ container_algorithm_internal::ContainerIter<C> c_is_sorted_until(C& c) {
// Overload of c_is_sorted_until() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename C, typename LessThan>
+template <typename C, typename Compare>
container_algorithm_internal::ContainerIter<C> c_is_sorted_until(
- C& c, LessThan&& comp) {
+ C& c, Compare&& comp) {
return std::is_sorted_until(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_nth_element()
@@ -1043,14 +1006,14 @@ void c_nth_element(
// Overload of c_nth_element() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename RandomAccessContainer, typename LessThan>
+template <typename RandomAccessContainer, typename Compare>
void c_nth_element(
RandomAccessContainer& sequence,
container_algorithm_internal::ContainerIter<RandomAccessContainer> nth,
- LessThan&& comp) {
+ Compare&& comp) {
std::nth_element(container_algorithm_internal::c_begin(sequence), nth,
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
@@ -1072,12 +1035,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
// Overload of c_lower_bound() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename Sequence, typename T, typename LessThan>
+template <typename Sequence, typename T, typename Compare>
container_algorithm_internal::ContainerIter<Sequence> c_lower_bound(
- Sequence& sequence, T&& value, LessThan&& comp) {
+ Sequence& sequence, T&& value, Compare&& comp) {
return std::lower_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ std::forward<T>(value), std::forward<Compare>(comp));
}
// c_upper_bound()
@@ -1095,12 +1058,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
// Overload of c_upper_bound() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename Sequence, typename T, typename LessThan>
+template <typename Sequence, typename T, typename Compare>
container_algorithm_internal::ContainerIter<Sequence> c_upper_bound(
- Sequence& sequence, T&& value, LessThan&& comp) {
+ Sequence& sequence, T&& value, Compare&& comp) {
return std::upper_bound(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ std::forward<T>(value), std::forward<Compare>(comp));
}
// c_equal_range()
@@ -1118,12 +1081,12 @@ c_equal_range(Sequence& sequence, T&& value) {
// Overload of c_equal_range() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename Sequence, typename T, typename LessThan>
+template <typename Sequence, typename T, typename Compare>
container_algorithm_internal::ContainerIterPairType<Sequence, Sequence>
-c_equal_range(Sequence& sequence, T&& value, LessThan&& comp) {
+c_equal_range(Sequence& sequence, T&& value, Compare&& comp) {
return std::equal_range(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<T>(value), std::forward<LessThan>(comp));
+ std::forward<T>(value), std::forward<Compare>(comp));
}
// c_binary_search()
@@ -1140,12 +1103,12 @@ bool c_binary_search(Sequence&& sequence, T&& value) {
// Overload of c_binary_search() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename Sequence, typename T, typename LessThan>
-bool c_binary_search(Sequence&& sequence, T&& value, LessThan&& comp) {
+template <typename Sequence, typename T, typename Compare>
+bool c_binary_search(Sequence&& sequence, T&& value, Compare&& comp) {
return std::binary_search(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
std::forward<T>(value),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
@@ -1166,14 +1129,14 @@ OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) {
// Overload of c_merge() for performing a `comp` comparison other than
// the default `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename LessThan>
+template <typename C1, typename C2, typename OutputIterator, typename Compare>
OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result,
- LessThan&& comp) {
+ Compare&& comp) {
return std::merge(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2), result,
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_inplace_merge()
@@ -1189,13 +1152,13 @@ void c_inplace_merge(C& c,
// Overload of c_inplace_merge() for performing a merge using a `comp` other
// than `operator<`.
-template <typename C, typename LessThan>
+template <typename C, typename Compare>
void c_inplace_merge(C& c,
container_algorithm_internal::ContainerIter<C> middle,
- LessThan&& comp) {
+ Compare&& comp) {
std::inplace_merge(container_algorithm_internal::c_begin(c), middle,
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_includes()
@@ -1213,13 +1176,13 @@ bool c_includes(const C1& c1, const C2& c2) {
// Overload of c_includes() for performing a merge using a `comp` other than
// `operator<`.
-template <typename C1, typename C2, typename LessThan>
-bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) {
+template <typename C1, typename C2, typename Compare>
+bool c_includes(const C1& c1, const C2& c2, Compare&& comp) {
return std::includes(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_set_union()
@@ -1243,7 +1206,7 @@ OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) {
// Overload of c_set_union() for performing a merge using a `comp` other than
// `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename LessThan,
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
@@ -1251,18 +1214,18 @@ template <typename C1, typename C2, typename OutputIterator, typename LessThan,
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output,
- LessThan&& comp) {
+ Compare&& comp) {
return std::set_union(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2), output,
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_set_intersection()
//
// Container-based version of the <algorithm> `std::set_intersection()` function
-// to return an iterator containing the intersection of two sorted containers.
+// to return an iterator containing the intersection of two containers.
template <typename C1, typename C2, typename OutputIterator,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
@@ -1272,11 +1235,6 @@ template <typename C1, typename C2, typename OutputIterator,
void>::type>
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
OutputIterator output) {
- // In debug builds, ensure that both containers are sorted with respect to the
- // default comparator. std::set_intersection requires the containers be sorted
- // using operator<.
- assert(absl::c_is_sorted(c1));
- assert(absl::c_is_sorted(c2));
return std::set_intersection(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
@@ -1285,7 +1243,7 @@ OutputIterator c_set_intersection(const C1& c1, const C2& c2,
// Overload of c_set_intersection() for performing a merge using a `comp` other
// than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename LessThan,
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
@@ -1293,17 +1251,12 @@ template <typename C1, typename C2, typename OutputIterator, typename LessThan,
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_intersection(const C1& c1, const C2& c2,
- OutputIterator output, LessThan&& comp) {
- // In debug builds, ensure that both containers are sorted with respect to the
- // default comparator. std::set_intersection requires the containers be sorted
- // using the same comparator.
- assert(absl::c_is_sorted(c1, comp));
- assert(absl::c_is_sorted(c2, comp));
+ OutputIterator output, Compare&& comp) {
return std::set_intersection(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2), output,
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_set_difference()
@@ -1328,7 +1281,7 @@ OutputIterator c_set_difference(const C1& c1, const C2& c2,
// Overload of c_set_difference() for performing a merge using a `comp` other
// than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename LessThan,
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
@@ -1336,12 +1289,12 @@ template <typename C1, typename C2, typename OutputIterator, typename LessThan,
!container_algorithm_internal::IsUnorderedContainer<C2>::value,
void>::type>
OutputIterator c_set_difference(const C1& c1, const C2& c2,
- OutputIterator output, LessThan&& comp) {
+ OutputIterator output, Compare&& comp) {
return std::set_difference(container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2), output,
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_set_symmetric_difference()
@@ -1367,7 +1320,7 @@ OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
// Overload of c_set_symmetric_difference() for performing a merge using a
// `comp` other than `operator<`.
-template <typename C1, typename C2, typename OutputIterator, typename LessThan,
+template <typename C1, typename C2, typename OutputIterator, typename Compare,
typename = typename std::enable_if<
!container_algorithm_internal::IsUnorderedContainer<C1>::value,
void>::type,
@@ -1376,13 +1329,13 @@ template <typename C1, typename C2, typename OutputIterator, typename LessThan,
void>::type>
OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2,
OutputIterator output,
- LessThan&& comp) {
+ Compare&& comp) {
return std::set_symmetric_difference(
container_algorithm_internal::c_begin(c1),
container_algorithm_internal::c_end(c1),
container_algorithm_internal::c_begin(c2),
container_algorithm_internal::c_end(c2), output,
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
@@ -1401,11 +1354,11 @@ void c_push_heap(RandomAccessContainer& sequence) {
// Overload of c_push_heap() for performing a push operation on a heap using a
// `comp` other than `operator<`.
-template <typename RandomAccessContainer, typename LessThan>
-void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) {
+template <typename RandomAccessContainer, typename Compare>
+void c_push_heap(RandomAccessContainer& sequence, Compare&& comp) {
std::push_heap(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_pop_heap()
@@ -1420,11 +1373,11 @@ void c_pop_heap(RandomAccessContainer& sequence) {
// Overload of c_pop_heap() for performing a pop operation on a heap using a
// `comp` other than `operator<`.
-template <typename RandomAccessContainer, typename LessThan>
-void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) {
+template <typename RandomAccessContainer, typename Compare>
+void c_pop_heap(RandomAccessContainer& sequence, Compare&& comp) {
std::pop_heap(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_make_heap()
@@ -1439,11 +1392,11 @@ void c_make_heap(RandomAccessContainer& sequence) {
// Overload of c_make_heap() for performing heap comparisons using a
// `comp` other than `operator<`
-template <typename RandomAccessContainer, typename LessThan>
-void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) {
+template <typename RandomAccessContainer, typename Compare>
+void c_make_heap(RandomAccessContainer& sequence, Compare&& comp) {
std::make_heap(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_sort_heap()
@@ -1458,11 +1411,11 @@ void c_sort_heap(RandomAccessContainer& sequence) {
// Overload of c_sort_heap() for performing heap comparisons using a
// `comp` other than `operator<`
-template <typename RandomAccessContainer, typename LessThan>
-void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) {
+template <typename RandomAccessContainer, typename Compare>
+void c_sort_heap(RandomAccessContainer& sequence, Compare&& comp) {
std::sort_heap(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_is_heap()
@@ -1477,11 +1430,11 @@ bool c_is_heap(const RandomAccessContainer& sequence) {
// Overload of c_is_heap() for performing heap comparisons using a
// `comp` other than `operator<`
-template <typename RandomAccessContainer, typename LessThan>
-bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) {
+template <typename RandomAccessContainer, typename Compare>
+bool c_is_heap(const RandomAccessContainer& sequence, Compare&& comp) {
return std::is_heap(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_is_heap_until()
@@ -1497,12 +1450,12 @@ c_is_heap_until(RandomAccessContainer& sequence) {
// Overload of c_is_heap_until() for performing heap comparisons using a
// `comp` other than `operator<`
-template <typename RandomAccessContainer, typename LessThan>
+template <typename RandomAccessContainer, typename Compare>
container_algorithm_internal::ContainerIter<RandomAccessContainer>
-c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) {
+c_is_heap_until(RandomAccessContainer& sequence, Compare&& comp) {
return std::is_heap_until(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
@@ -1523,12 +1476,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_min_element(
// Overload of c_min_element() for performing a `comp` comparison other than
// `operator<`.
-template <typename Sequence, typename LessThan>
+template <typename Sequence, typename Compare>
container_algorithm_internal::ContainerIter<Sequence> c_min_element(
- Sequence& sequence, LessThan&& comp) {
+ Sequence& sequence, Compare&& comp) {
return std::min_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_max_element()
@@ -1545,12 +1498,12 @@ container_algorithm_internal::ContainerIter<Sequence> c_max_element(
// Overload of c_max_element() for performing a `comp` comparison other than
// `operator<`.
-template <typename Sequence, typename LessThan>
+template <typename Sequence, typename Compare>
container_algorithm_internal::ContainerIter<Sequence> c_max_element(
- Sequence& sequence, LessThan&& comp) {
+ Sequence& sequence, Compare&& comp) {
return std::max_element(container_algorithm_internal::c_begin(sequence),
container_algorithm_internal::c_end(sequence),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_minmax_element()
@@ -1568,12 +1521,12 @@ c_minmax_element(C& c) {
// Overload of c_minmax_element() for performing `comp` comparisons other than
// `operator<`.
-template <typename C, typename LessThan>
+template <typename C, typename Compare>
container_algorithm_internal::ContainerIterPairType<C, C>
-c_minmax_element(C& c, LessThan&& comp) {
+c_minmax_element(C& c, Compare&& comp) {
return std::minmax_element(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
@@ -1598,15 +1551,15 @@ bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2) {
// Overload of c_lexicographical_compare() for performing a lexicographical
// comparison using a `comp` operator instead of `operator<`.
-template <typename Sequence1, typename Sequence2, typename LessThan>
+template <typename Sequence1, typename Sequence2, typename Compare>
bool c_lexicographical_compare(Sequence1&& sequence1, Sequence2&& sequence2,
- LessThan&& comp) {
+ Compare&& comp) {
return std::lexicographical_compare(
container_algorithm_internal::c_begin(sequence1),
container_algorithm_internal::c_end(sequence1),
container_algorithm_internal::c_begin(sequence2),
container_algorithm_internal::c_end(sequence2),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_next_permutation()
@@ -1622,11 +1575,11 @@ bool c_next_permutation(C& c) {
// Overload of c_next_permutation() for performing a lexicographical
// comparison using a `comp` operator instead of `operator<`.
-template <typename C, typename LessThan>
-bool c_next_permutation(C& c, LessThan&& comp) {
+template <typename C, typename Compare>
+bool c_next_permutation(C& c, Compare&& comp) {
return std::next_permutation(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
// c_prev_permutation()
@@ -1642,11 +1595,11 @@ bool c_prev_permutation(C& c) {
// Overload of c_prev_permutation() for performing a lexicographical
// comparison using a `comp` operator instead of `operator<`.
-template <typename C, typename LessThan>
-bool c_prev_permutation(C& c, LessThan&& comp) {
+template <typename C, typename Compare>
+bool c_prev_permutation(C& c, Compare&& comp) {
return std::prev_permutation(container_algorithm_internal::c_begin(c),
container_algorithm_internal::c_end(c),
- std::forward<LessThan>(comp));
+ std::forward<Compare>(comp));
}
//------------------------------------------------------------------------------
diff --git a/third_party/abseil-cpp/absl/algorithm/container_test.cc b/third_party/abseil-cpp/absl/algorithm/container_test.cc
index 605afc8040..0a4abe9462 100644
--- a/third_party/abseil-cpp/absl/algorithm/container_test.cc
+++ b/third_party/abseil-cpp/absl/algorithm/container_test.cc
@@ -57,7 +57,9 @@ 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;
};
@@ -66,6 +68,7 @@ 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_));
@@ -148,90 +151,13 @@ TEST_F(NonMutatingTest, CountIf) {
}
TEST_F(NonMutatingTest, Mismatch) {
- // 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);
- }
+ absl::c_mismatch(container_, sequence_);
+ absl::c_mismatch(sequence_, container_);
}
TEST_F(NonMutatingTest, MismatchWithPredicate) {
- // 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());
- }
+ absl::c_mismatch(container_, sequence_, BinPredicate);
+ absl::c_mismatch(sequence_, container_, BinPredicate);
}
TEST_F(NonMutatingTest, Equal) {
@@ -593,9 +519,11 @@ 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) {
@@ -748,15 +676,6 @@ 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) {
@@ -771,20 +690,6 @@ 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) {
@@ -850,9 +755,10 @@ 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) {
@@ -860,9 +766,10 @@ 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/third_party/abseil-cpp/absl/base/BUILD.bazel b/third_party/abseil-cpp/absl/base/BUILD.bazel
index 4769efda0a..bae79427ac 100644
--- a/third_party/abseil-cpp/absl/base/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/base/BUILD.bazel
@@ -14,6 +14,7 @@
# 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",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "atomic_hook",
@@ -114,18 +115,11 @@ cc_library(
cc_library(
name = "dynamic_annotations",
- srcs = [
- "internal/dynamic_annotations.h",
- ],
- hdrs = [
- "dynamic_annotations.h",
- ],
+ srcs = ["dynamic_annotations.cc"],
+ hdrs = ["dynamic_annotations.h"],
copts = ABSL_DEFAULT_COPTS,
+ defines = ["__CLANG_SUPPORT_DYN_ANNOTATION__"],
linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- ":config",
- ":core_headers",
- ],
)
cc_library(
@@ -159,9 +153,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
- "//absl:msvc_compiler": [],
- "//absl:clang-cl_compiler": [],
- "//absl:wasm": [],
+ "//absl:windows": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
visibility = [
@@ -220,13 +212,9 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
- "//absl:msvc_compiler": [
- "-DEFAULTLIB:advapi32.lib",
- ],
- "//absl:clang-cl_compiler": [
+ "//absl:windows": [
"-DEFAULTLIB:advapi32.lib",
],
- "//absl:wasm": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -319,7 +307,6 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":errno_saver",
- ":strerror",
"@com_google_googletest//:gtest_main",
],
)
@@ -418,7 +405,6 @@ cc_library(
deps = [
":base",
":base_internal",
- ":config",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest",
@@ -435,7 +421,6 @@ cc_test(
deps = [
":base",
":base_internal",
- ":config",
":core_headers",
"//absl/synchronization",
"@com_google_googletest//:gtest_main",
@@ -466,7 +451,6 @@ cc_binary(
testonly = 1,
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
":spinlock_benchmark_common",
@@ -482,7 +466,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":base",
":config",
":core_headers",
],
@@ -555,13 +538,8 @@ cc_test(
srcs = ["internal/low_level_alloc_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = [
- "no_test_ios_x86_64",
- ],
- deps = [
- ":malloc_internal",
- "//absl/container:node_hash_map",
- ],
+ tags = ["no_test_ios_x86_64"],
+ deps = [":malloc_internal"],
)
cc_test(
@@ -593,138 +571,137 @@ cc_test(
)
cc_library(
- name = "scoped_set_env",
- testonly = 1,
- srcs = ["internal/scoped_set_env.cc"],
- hdrs = ["internal/scoped_set_env.h"],
+ name = "bits",
+ hdrs = ["internal/bits.h"],
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = [
"//absl:__subpackages__",
],
deps = [
":config",
- ":raw_logging_internal",
+ ":core_headers",
],
)
cc_test(
- name = "scoped_set_env_test",
+ name = "bits_test",
size = "small",
- srcs = ["internal/scoped_set_env_test.cc"],
+ srcs = ["internal/bits_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":scoped_set_env",
+ ":bits",
"@com_google_googletest//:gtest_main",
],
)
+cc_library(
+ name = "exponential_biased",
+ srcs = ["internal/exponential_biased.cc"],
+ hdrs = ["internal/exponential_biased.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl:__subpackages__",
+ ],
+ deps = [
+ ":config",
+ ":core_headers",
+ ],
+)
+
cc_test(
- name = "log_severity_test",
+ name = "exponential_biased_test",
size = "small",
- srcs = ["log_severity_test.cc"],
+ srcs = ["internal/exponential_biased_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
deps = [
- ":log_severity",
- "//absl/flags:flag_internal",
- "//absl/flags:marshalling",
+ ":exponential_biased",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
- name = "strerror",
- srcs = ["internal/strerror.cc"],
- hdrs = ["internal/strerror.h"],
+ name = "periodic_sampler",
+ srcs = ["internal/periodic_sampler.cc"],
+ hdrs = ["internal/periodic_sampler.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
deps = [
- ":config",
":core_headers",
- ":errno_saver",
+ ":exponential_biased",
],
)
cc_test(
- name = "strerror_test",
+ name = "periodic_sampler_test",
size = "small",
- srcs = ["internal/strerror_test.cc"],
+ srcs = ["internal/periodic_sampler_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = ["//visibility:private"],
deps = [
- ":strerror",
- "//absl/strings",
+ ":core_headers",
+ ":periodic_sampler",
"@com_google_googletest//:gtest_main",
],
)
cc_binary(
- name = "strerror_benchmark",
+ name = "periodic_sampler_benchmark",
testonly = 1,
- srcs = ["internal/strerror_benchmark.cc"],
+ srcs = ["internal/periodic_sampler_benchmark.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ["benchmark"],
visibility = ["//visibility:private"],
deps = [
- ":strerror",
+ ":core_headers",
+ ":periodic_sampler",
"@com_github_google_benchmark//:benchmark_main",
],
)
cc_library(
- name = "fast_type_id",
- hdrs = ["internal/fast_type_id.h"],
- copts = ABSL_DEFAULT_COPTS,
+ 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 = "fast_type_id_test",
+ name = "scoped_set_env_test",
size = "small",
- srcs = ["internal/fast_type_id_test.cc"],
+ srcs = ["internal/scoped_set_env_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":fast_type_id",
+ ":scoped_set_env",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
- name = "unique_small_name_test",
+ name = "log_severity_test",
size = "small",
- srcs = ["internal/unique_small_name_test.cc"],
+ srcs = ["log_severity_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- linkstatic = 1,
deps = [
- ":core_headers",
+ ":log_severity",
+ "//absl/flags:flag_internal",
+ "//absl/flags:marshalling",
"//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/third_party/abseil-cpp/absl/base/CMakeLists.txt b/third_party/abseil-cpp/absl/base/CMakeLists.txt
index c7233cb36c..14c52eabdf 100644
--- a/third_party/abseil-cpp/absl/base/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/base/CMakeLists.txt
@@ -105,11 +105,11 @@ absl_cc_library(
HDRS
"dynamic_annotations.h"
SRCS
- "internal/dynamic_annotations.h"
+ "dynamic_annotations.cc"
COPTS
${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
+ DEFINES
+ "__CLANG_SUPPORT_DYN_ANNOTATION__"
PUBLIC
)
@@ -191,7 +191,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
- $<$<BOOL:${LIBRT}>:-lrt>
+ $<$<BOOL:${LIBRT}>:${LIBRT}>
$<$<BOOL:${MINGW}>:"advapi32">
DEPS
absl::atomic_hook
@@ -230,7 +230,7 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::config
- GTest::gtest
+ gtest
TESTONLY
)
@@ -259,7 +259,7 @@ absl_cc_library(
absl::meta
absl::strings
absl::utility
- GTest::gtest
+ gtest
TESTONLY
)
@@ -273,7 +273,7 @@ absl_cc_test(
DEPS
absl::exception_safety_testing
absl::memory
- GTest::gtest_main
+ gtest_main
)
absl_cc_library(
@@ -300,8 +300,8 @@ absl_cc_test(
absl::atomic_hook_test_helper
absl::atomic_hook
absl::core_headers
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -314,7 +314,7 @@ absl_cc_test(
DEPS
absl::base
absl::core_headers
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -326,9 +326,8 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::errno_saver
- absl::strerror
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -342,7 +341,7 @@ absl_cc_test(
absl::base
absl::config
absl::throw_delegate
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -357,7 +356,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::base_internal
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -371,8 +370,8 @@ absl_cc_test(
absl::base_internal
absl::memory
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_library(
@@ -384,11 +383,10 @@ absl_cc_library(
${ABSL_TEST_COPTS}
DEPS
absl::base
- absl::config
absl::base_internal
absl::core_headers
absl::synchronization
- GTest::gtest
+ gtest
TESTONLY
)
@@ -403,10 +401,9 @@ absl_cc_test(
DEPS
absl::base
absl::base_internal
- absl::config
absl::core_headers
absl::synchronization
- GTest::gtest_main
+ gtest_main
)
absl_cc_library(
@@ -418,7 +415,6 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::base
absl::config
absl::core_headers
PUBLIC
@@ -435,7 +431,7 @@ absl_cc_test(
absl::base
absl::config
absl::endian
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -448,7 +444,7 @@ absl_cc_test(
DEPS
absl::config
absl::synchronization
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -462,7 +458,7 @@ absl_cc_test(
absl::base
absl::core_headers
absl::synchronization
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -475,7 +471,7 @@ absl_cc_test(
DEPS
absl::raw_logging_internal
absl::strings
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -488,7 +484,7 @@ absl_cc_test(
DEPS
absl::base
absl::synchronization
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -500,7 +496,6 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::malloc_internal
- absl::node_hash_map
Threads::Threads
)
@@ -516,125 +511,134 @@ absl_cc_test(
absl::core_headers
absl::synchronization
Threads::Threads
- GTest::gtest_main
+ gtest_main
)
absl_cc_library(
NAME
- scoped_set_env
- SRCS
- "internal/scoped_set_env.cc"
+ bits
HDRS
- "internal/scoped_set_env.h"
+ "internal/bits.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
absl::config
- absl::raw_logging_internal
+ absl::core_headers
)
absl_cc_test(
NAME
- scoped_set_env_test
+ bits_test
SRCS
- "internal/scoped_set_env_test.cc"
+ "internal/bits_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::scoped_set_env
- GTest::gtest_main
+ absl::bits
+ gtest_main
)
-absl_cc_test(
+absl_cc_library(
NAME
- cmake_thread_test
+ exponential_biased
SRCS
- "internal/cmake_thread_test.cc"
+ "internal/exponential_biased.cc"
+ HDRS
+ "internal/exponential_biased.h"
COPTS
- ${ABSL_TEST_COPTS}
+ ${ABSL_DEFAULT_COPTS}
DEPS
- absl::base
+ absl::config
+ absl::core_headers
)
absl_cc_test(
NAME
- log_severity_test
+ exponential_biased_test
SRCS
- "log_severity_test.cc"
+ "internal/exponential_biased_test.cc"
+ COPTS
+ ${ABSL_TEST_COPTS}
DEPS
- absl::flags_internal
- absl::flags_marshalling
- absl::log_severity
+ absl::exponential_biased
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock_main
)
absl_cc_library(
NAME
- strerror
+ periodic_sampler
SRCS
- "internal/strerror.cc"
+ "internal/periodic_sampler.cc"
HDRS
- "internal/strerror.h"
+ "internal/periodic_sampler.h"
COPTS
${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::config
absl::core_headers
- absl::errno_saver
+ absl::exponential_biased
)
absl_cc_test(
NAME
- strerror_test
+ periodic_sampler_test
SRCS
- "internal/strerror_test.cc"
+ "internal/periodic_sampler_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::strerror
- absl::strings
- GTest::gmock
- GTest::gtest_main
+ absl::core_headers
+ absl::periodic_sampler
+ gmock_main
)
absl_cc_library(
NAME
- fast_type_id
+ scoped_set_env
+ SRCS
+ "internal/scoped_set_env.cc"
HDRS
- "internal/fast_type_id.h"
+ "internal/scoped_set_env.h"
COPTS
${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
+ absl::raw_logging_internal
)
absl_cc_test(
NAME
- fast_type_id_test
+ scoped_set_env_test
SRCS
- "internal/fast_type_id_test.cc"
+ "internal/scoped_set_env_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::fast_type_id
- GTest::gtest_main
+ absl::scoped_set_env
+ gtest_main
)
absl_cc_test(
NAME
- optimization_test
+ cmake_thread_test
SRCS
- "optimization_test.cc"
+ "internal/cmake_thread_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::core_headers
- absl::optional
- GTest::gtest_main
+ absl::base
+)
+
+absl_cc_test(
+ NAME
+ log_severity_test
+ SRCS
+ "log_severity_test.cc"
+ DEPS
+ absl::flags_internal
+ absl::flags_marshalling
+ absl::log_severity
+ absl::strings
+ gmock
+ gtest_main
)
diff --git a/third_party/abseil-cpp/absl/base/attributes.h b/third_party/abseil-cpp/absl/base/attributes.h
index e3907827d6..ff138629d1 100644
--- a/third_party/abseil-cpp/absl/base/attributes.h
+++ b/third_party/abseil-cpp/absl/base/attributes.h
@@ -18,6 +18,8 @@
// 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.
//
@@ -30,12 +32,34 @@
// 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
@@ -119,7 +143,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__) && !defined(__e2k__)
+#elif defined(__GNUC__) && !defined(__clang__)
#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1
#define ABSL_ATTRIBUTE_NO_TAIL_CALL \
__attribute__((optimize("no-optimize-sibling-calls")))
@@ -131,14 +155,14 @@
// ABSL_ATTRIBUTE_WEAK
//
// Tags a function as weak for the purposes of compilation and linking.
-// Weak attributes did not work properly in LLVM's Windows backend before
-// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598
+// 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 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(_WIN32) || __clang_major__ < 9) && !defined(__MINGW32__)
+ !(defined(__llvm__) && defined(_WIN32)) && !defined(__MINGW32__)
#undef ABSL_ATTRIBUTE_WEAK
#define ABSL_ATTRIBUTE_WEAK __attribute__((weak))
#define ABSL_HAVE_ATTRIBUTE_WEAK 1
@@ -210,7 +234,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 ABSL_HAVE_ATTRIBUTE(no_sanitize_address)
+#if defined(__GNUC__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS
@@ -218,13 +242,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 ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS 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 ADDRESS_SANITIZER attribute above, but deals
+// with initialized-ness rather than addressability issues.
// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC.
-#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory)
+#if defined(__clang__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY
@@ -235,7 +259,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 ABSL_HAVE_ATTRIBUTE(no_sanitize_thread)
+#if defined(__GNUC__)
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD
@@ -247,10 +271,8 @@
// 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 ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined)
-#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
- __attribute__((no_sanitize_undefined))
-#elif ABSL_HAVE_ATTRIBUTE(no_sanitize)
+#if defined(__GNUC__) && \
+ (defined(UNDEFINED_BEHAVIOR_SANITIZER) || defined(ADDRESS_SANITIZER))
#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \
__attribute__((no_sanitize("undefined")))
#else
@@ -261,7 +283,7 @@
//
// Tells the ControlFlowIntegrity sanitizer to not instrument a given function.
// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details.
-#if ABSL_HAVE_ATTRIBUTE(no_sanitize)
+#if defined(__GNUC__) && defined(CONTROL_FLOW_INTEGRITY)
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi")))
#else
#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI
@@ -271,7 +293,7 @@
//
// 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)
+#if defined(__GNUC__) && defined(SAFESTACK_SANITIZER)
#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \
__attribute__((no_sanitize("safe-stack")))
#else
@@ -281,7 +303,10 @@
// ABSL_ATTRIBUTE_RETURNS_NONNULL
//
// Tells the compiler that a particular function never returns a null pointer.
-#if ABSL_HAVE_ATTRIBUTE(returns_nonnull)
+#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) || \
+ (defined(__GNUC__) && \
+ (__GNUC__ > 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) && \
+ !defined(__clang__))
#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull))
#else
#define ABSL_ATTRIBUTE_RETURNS_NONNULL
@@ -318,16 +343,8 @@
// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section.
// This functionality is supported by GNU linker.
#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE
-#ifdef _AIX
-// __attribute__((section(#name))) on AIX is achived by using the `.csect` psudo
-// op which includes an additional integer as part of its syntax indcating
-// alignment. If data fall under different alignments then you might get a
-// compilation error indicating a `Section type conflict`.
-#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name)
-#else
#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name)))
#endif
-#endif
// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS
//
@@ -490,10 +507,8 @@
// 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(__ANDROID__)
+ !defined(ABSL_NO_XRAY_ATTRIBUTES)
#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)
@@ -529,13 +544,6 @@
// ABSL_ATTRIBUTE_UNUSED
//
// Prevents the compiler from complaining about variables that appear unused.
-//
-// For code or headers that are assured to only build with C++17 and up, prefer
-// just using the standard '[[maybe_unused]]' directly over this macro.
-//
-// Due to differences in positioning requirements between the old, compiler
-// specific __attribute__ syntax and the now standard [[maybe_unused]], this
-// macro does not attempt to take advantage of '[[maybe_unused]]'.
#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__))
#undef ABSL_ATTRIBUTE_UNUSED
#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__))
@@ -556,19 +564,13 @@
// ABSL_ATTRIBUTE_PACKED
//
// Instructs the compiler not to use natural alignment for a tagged data
-// structure, but instead to reduce its alignment to 1.
-//
-// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing
-// so can cause atomic variables to be mis-aligned and silently violate
-// atomicity on x86.
-//
-// 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.
+// 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
@@ -590,79 +592,6 @@
#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 supported, GCC and Clang can issue a warning on switch labels
-// with unannotated fallthrough using the warning `-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."
-#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough)
-#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]]
-#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough)
-#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]]
-#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough)
-#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]]
-#else
-#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
@@ -689,47 +618,4 @@
#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
-
-// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
-// parameter or implicit object parameter is retained by the return value of the
-// annotated function (or, for a parameter of a constructor, in the value of the
-// constructed object). This attribute causes warnings to be produced if a
-// temporary object does not live long enough.
-//
-// When applied to a reference parameter, the referenced object is assumed to be
-// retained by the return value of the function. When applied to a non-reference
-// parameter (for example, a pointer or a class type), all temporaries
-// referenced by the parameter are assumed to be retained by the return value of
-// the function.
-//
-// See also the upstream documentation:
-// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
-#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
-#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
-#elif ABSL_HAVE_ATTRIBUTE(lifetimebound)
-#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
-#else
-#define ABSL_ATTRIBUTE_LIFETIME_BOUND
-#endif
-
#endif // ABSL_BASE_ATTRIBUTES_H_
diff --git a/third_party/abseil-cpp/absl/base/call_once.h b/third_party/abseil-cpp/absl/base/call_once.h
index 96109f537c..bc5ec93704 100644
--- a/third_party/abseil-cpp/absl/base/call_once.h
+++ b/third_party/abseil-cpp/absl/base/call_once.h
@@ -175,10 +175,17 @@ void CallOnceImpl(std::atomic<uint32_t>* control,
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->exchange(base_internal::kOnceDone, std::memory_order_release);
+ // The call to SpinLockWake below is an optimization, because the waiter
+ // in SpinLockWait is waiting with a short timeout. The atomic load/store
+ // sequence is slightly faster than an atomic exchange:
+ // old_control = control->exchange(base_internal::kOnceDone,
+ // std::memory_order_release);
+ // We opt for a slightly faster case when there are no waiters, in spite
+ // of longer tail latency when there are waiters.
+ old_control = control->load(std::memory_order_relaxed);
+ control->store(base_internal::kOnceDone, std::memory_order_release);
if (old_control == base_internal::kOnceWaiter) {
base_internal::SpinLockWake(control, true);
}
diff --git a/third_party/abseil-cpp/absl/base/casts.h b/third_party/abseil-cpp/absl/base/casts.h
index 83c691265f..322cc1d243 100644
--- a/third_party/abseil-cpp/absl/base/casts.h
+++ b/third_party/abseil-cpp/absl/base/casts.h
@@ -159,19 +159,16 @@ 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.");
diff --git a/third_party/abseil-cpp/absl/base/config.h b/third_party/abseil-cpp/absl/base/config.h
index 585485c359..ee99f94629 100644
--- a/third_party/abseil-cpp/absl/base/config.h
+++ b/third_party/abseil-cpp/absl/base/config.h
@@ -66,35 +66,6 @@
#include "absl/base/options.h"
#include "absl/base/policy_checks.h"
-// Abseil long-term support (LTS) releases will define
-// `ABSL_LTS_RELEASE_VERSION` to the integer representing the date string of the
-// LTS release version, and will define `ABSL_LTS_RELEASE_PATCH_LEVEL` to the
-// integer representing the patch-level for that release.
-//
-// For example, for LTS release version "20300401.2", this would give us
-// ABSL_LTS_RELEASE_VERSION == 20300401 && ABSL_LTS_RELEASE_PATCH_LEVEL == 2
-//
-// These symbols will not be defined in non-LTS code.
-//
-// Abseil recommends that clients live-at-head. Therefore, if you are using
-// these symbols to assert a minimum version requirement, we recommend you do it
-// as
-//
-// #if defined(ABSL_LTS_RELEASE_VERSION) && ABSL_LTS_RELEASE_VERSION < 20300401
-// #error Project foo requires Abseil LTS version >= 20300401
-// #endif
-//
-// The `defined(ABSL_LTS_RELEASE_VERSION)` part of the check excludes
-// live-at-head clients from the minimum version assertion.
-//
-// See https://abseil.io/about/releases for more information on Abseil release
-// management.
-//
-// LTS releases can be obtained from
-// https://github.com/abseil/abseil-cpp/releases.
-#define ABSL_LTS_RELEASE_VERSION 20211102
-#define ABSL_LTS_RELEASE_PATCH_LEVEL 0
-
// Helper macro to convert a CPP variable to a string literal.
#define ABSL_INTERNAL_DO_TOKEN_STR(x) #x
#define ABSL_INTERNAL_TOKEN_STR(x) ABSL_INTERNAL_DO_TOKEN_STR(x)
@@ -150,16 +121,10 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#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
@@ -189,28 +154,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#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
-
-// Portable check for GCC minimum version:
-// https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
-#if defined(__GNUC__) && defined(__GNUC_MINOR__)
-#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) \
- (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
-#else
-#define ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(x, y) 0
-#endif
-
-#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
-#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) \
- (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))
-#else
-#define ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(x, y) 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.
@@ -228,9 +171,10 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// gcc >= 4.8.1 using libstdc++, and Visual Studio.
#ifdef ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE
#error ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE cannot be directly set
-#elif defined(_LIBCPP_VERSION) || defined(_MSC_VER) || \
- (!defined(__clang__) && defined(__GLIBCXX__) && \
- ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(4, 8))
+#elif defined(_LIBCPP_VERSION) || \
+ (!defined(__clang__) && defined(__GNUC__) && defined(__GLIBCXX__) && \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \
+ defined(_MSC_VER)
#define ABSL_HAVE_STD_IS_TRIVIALLY_DESTRUCTIBLE 1
#endif
@@ -243,17 +187,16 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
//
// Checks whether `std::is_trivially_copy_assignable<T>` is supported.
-// Notes: Clang with libc++ supports these features, as does gcc >= 7.4 with
-// libstdc++, or gcc >= 8.2 with libc++, and Visual Studio (but not NVCC).
+// Notes: Clang with libc++ supports these features, as does gcc >= 5.1 with
+// 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__) && \
- ((ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(7, 4) && defined(__GLIBCXX__)) || \
- (ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(8, 2) && \
- defined(_LIBCPP_VERSION)))) || \
+#elif (defined(__clang__) && defined(_LIBCPP_VERSION)) || \
+ (!defined(__clang__) && defined(__GNUC__) && \
+ (__GNUC__ > 7 || (__GNUC__ == 7 && __GNUC_MINOR__ >= 4)) && \
+ (defined(_LIBCPP_VERSION) || defined(__GLIBCXX__))) || \
(defined(_MSC_VER) && !defined(__NVCC__))
#define ABSL_HAVE_STD_IS_TRIVIALLY_CONSTRUCTIBLE 1
#define ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE 1
@@ -267,8 +210,6 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#if ABSL_INTERNAL_HAS_KEYWORD(__builtin_LINE) && \
ABSL_INTERNAL_HAS_KEYWORD(__builtin_FILE)
#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
-#elif ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0)
-#define ABSL_HAVE_SOURCE_LOCATION_CURRENT 1
#endif
#endif
@@ -285,9 +226,11 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// * 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 ABSL_HAVE_FEATURE unreliable there.
+// making __has_feature unreliable there.
//
-#if ABSL_HAVE_FEATURE(cxx_thread_local) && \
+// Otherwise, `__has_feature` is only supported by Clang so it has be inside
+// `defined(__APPLE__)` check.
+#if __has_feature(cxx_thread_local) && \
!(TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0)
#define ABSL_HAVE_THREAD_LOCAL 1
#endif
@@ -319,6 +262,13 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#endif // defined(__ANDROID__) && defined(__clang__)
+// Emscripten doesn't yet support `thread_local` or `__thread`.
+// https://github.com/emscripten-core/emscripten/issues/3502
+#if defined(__EMSCRIPTEN__)
+#undef ABSL_HAVE_TLS
+#undef ABSL_HAVE_THREAD_LOCAL
+#endif // defined(__EMSCRIPTEN__)
+
// ABSL_HAVE_INTRINSIC_INT128
//
// Checks whether the __int128 compiler extension for a 128-bit integral type is
@@ -364,21 +314,25 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// For further details, consult the compiler's documentation.
#ifdef ABSL_HAVE_EXCEPTIONS
#error ABSL_HAVE_EXCEPTIONS cannot be directly set.
-#elif ABSL_INTERNAL_HAVE_MIN_CLANG_VERSION(3, 6)
+
+#elif defined(__clang__)
+
+#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
// Clang >= 3.6
-#if ABSL_HAVE_FEATURE(cxx_exceptions)
+#if __has_feature(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
-#endif // ABSL_HAVE_FEATURE(cxx_exceptions)
-#elif defined(__clang__)
+#endif // __has_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)
+#if defined(__EXCEPTIONS) && __has_feature(cxx_exceptions)
#define ABSL_HAVE_EXCEPTIONS 1
-#endif // defined(__EXCEPTIONS) && ABSL_HAVE_FEATURE(cxx_exceptions)
+#endif // defined(__EXCEPTIONS) && __has_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)) && \
- !(ABSL_INTERNAL_HAVE_MIN_GNUC_VERSION(5, 0) && \
- !defined(__cpp_exceptions)) && \
+#elif !(defined(__GNUC__) && (__GNUC__ < 5) && !defined(__EXCEPTIONS)) && \
+ !(defined(__GNUC__) && (__GNUC__ >= 5) && !defined(__cpp_exceptions)) && \
!(defined(_MSC_VER) && !defined(_CPPUNWIND))
#define ABSL_HAVE_EXCEPTIONS 1
#endif
@@ -410,11 +364,10 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// POSIX.1-2001.
#ifdef ABSL_HAVE_MMAP
#error ABSL_HAVE_MMAP cannot be directly set
-#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(_AIX) || defined(__ros__) || defined(__native_client__) || \
- defined(__asmjs__) || defined(__wasm__) || defined(__Fuchsia__) || \
- defined(__sun) || defined(__ASYLO__) || defined(__myriad2__) || \
- defined(__HAIKU__)
+#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
+ defined(__ros__) || defined(__native_client__) || defined(__asmjs__) || \
+ defined(__wasm__) || defined(__Fuchsia__) || defined(__sun) || \
+ defined(__ASYLO__)
#define ABSL_HAVE_MMAP 1
#endif
@@ -425,19 +378,10 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#ifdef ABSL_HAVE_PTHREAD_GETSCHEDPARAM
#error ABSL_HAVE_PTHREAD_GETSCHEDPARAM cannot be directly set
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || \
- defined(_AIX) || defined(__ros__)
+ defined(__ros__)
#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
@@ -533,9 +477,9 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
(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) || \
+ __ENVIRONMENT_WATCH_OS_VERSION_MIN_REQUIRED__ < 120000) || \
(defined(__ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__) && \
- __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 120000))
+ __ENVIRONMENT_TV_OS_VERSION_MIN_REQUIRED__ < 50000))
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 1
#else
#define ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE 0
@@ -549,7 +493,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#ifdef __has_include
-#if __has_include(<any>) && defined(__cplusplus) && __cplusplus >= 201703L && \
+#if __has_include(<any>) && __cplusplus >= 201703L && \
!ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_ANY 1
#endif
@@ -563,8 +507,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#ifdef __has_include
-#if __has_include(<optional>) && defined(__cplusplus) && \
- __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
+#if __has_include(<optional>) && __cplusplus >= 201703L && \
+ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_OPTIONAL 1
#endif
#endif
@@ -577,8 +521,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#ifdef __has_include
-#if __has_include(<variant>) && defined(__cplusplus) && \
- __cplusplus >= 201703L && !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
+#if __has_include(<variant>) && __cplusplus >= 201703L && \
+ !ABSL_INTERNAL_APPLE_CXX17_TYPES_UNAVAILABLE
#define ABSL_HAVE_STD_VARIANT 1
#endif
#endif
@@ -591,8 +535,7 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#endif
#ifdef __has_include
-#if __has_include(<string_view>) && defined(__cplusplus) && \
- __cplusplus >= 201703L
+#if __has_include(<string_view>) && __cplusplus >= 201703L
#define ABSL_HAVE_STD_STRING_VIEW 1
#endif
#endif
@@ -604,9 +547,8 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
// 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) || \
- (defined(__cplusplus) && __cplusplus > 201402))
+#if defined(_MSC_VER) && _MSC_VER >= 1910 && \
+ ((defined(_MSVC_LANG) && _MSVC_LANG > 201402) || __cplusplus > 201402)
// #define ABSL_HAVE_STD_ANY 1
#define ABSL_HAVE_STD_OPTIONAL 1
#define ABSL_HAVE_STD_VARIANT 1
@@ -726,47 +668,4 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#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(__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(__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(__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/third_party/abseil-cpp/absl/base/dynamic_annotations.cc b/third_party/abseil-cpp/absl/base/dynamic_annotations.cc
new file mode 100644
index 0000000000..21e822e53c
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.cc
@@ -0,0 +1,129 @@
+// 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 <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/third_party/abseil-cpp/absl/base/dynamic_annotations.h b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
index 3ea7c1568c..65a54b447f 100644
--- a/third_party/abseil-cpp/absl/base/dynamic_annotations.h
+++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
@@ -1,471 +1,389 @@
-// 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.
+/*
+ * 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_DYNAMIC_ANNOTATIONS_H_
#define ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
-#include <stddef.h>
-
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#ifdef __cplusplus
-#include "absl/base/macros.h"
+#ifndef DYNAMIC_ANNOTATIONS_ENABLED
+# define DYNAMIC_ANNOTATIONS_ENABLED 0
#endif
-// TODO(rogeeff): Remove after the backward compatibility period.
-#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export
-
-// -------------------------------------------------------------------------
-// Decide which features are enabled.
-
-#ifdef ABSL_HAVE_THREAD_SANITIZER
-
-#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
-
+#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)
+#endif
-#define ABSL_INTERNAL_RACE_ANNOTATIONS_ENABLED 0
-#define ABSL_INTERNAL_READS_ANNOTATIONS_ENABLED 0
-#define ABSL_INTERNAL_WRITES_ANNOTATIONS_ENABLED 0
+ /* Report that the lock at address "lock" is about to be destroyed. */
+ #define ANNOTATE_RWLOCK_DESTROY(lock) \
+ AnnotateRWLockDestroy(__FILE__, __LINE__, lock)
-// 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.
+ /* 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)
-#if defined(__clang__)
-#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 1
-#if !defined(SWIG)
-#define ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED 1
-#endif
-#else
-#define ABSL_INTERNAL_ANNOTALYSIS_ENABLED 0
-#endif
+ /* 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)
-// Read/write annotations are enabled in Annotalysis mode; disabled otherwise.
-#define ABSL_INTERNAL_READS_WRITES_ANNOTATIONS_ENABLED \
- ABSL_INTERNAL_ANNOTALYSIS_ENABLED
+#else /* DYNAMIC_ANNOTATIONS_ENABLED == 0 */
-#endif // ABSL_HAVE_THREAD_SANITIZER
+ #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 */
-#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
+#endif /* DYNAMIC_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
+/* 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)
-// 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)
+ #define ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) \
+ AnnotateMemoryIsUninitialized(__FILE__, __LINE__, address, size)
#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("*")))
+#else
+ #define ATTRIBUTE_IGNORE_READS_BEGIN /* empty */
+ #define ATTRIBUTE_IGNORE_READS_END /* empty */
+#endif /* defined(__clang__) && ... */
-#define ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(address, size) // empty
-#define ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(address, size) // empty
-
+#if (DYNAMIC_ANNOTATIONS_ENABLED != 0) || defined(ANNOTALYSIS_ENABLED)
+ #define ANNOTATIONS_ENABLED
#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
-
-#endif // defined(ABSL_INTERNAL_IGNORE_READS_ATTRIBUTE_ENABLED)
-
-// -------------------------------------------------------------------------
-// Define IGNORE_READS_BEGIN/_END annotations.
+#if (DYNAMIC_ANNOTATIONS_ENABLED != 0)
-#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.
+ /* 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__)
-// 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__)
+ /* Stop ignoring reads. */
+ #define ANNOTATE_IGNORE_READS_END() \
+ AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-// Stop ignoring reads.
-#define ABSL_ANNOTATE_IGNORE_READS_END() \
- ABSL_INTERNAL_GLOBAL_SCOPED(AnnotateIgnoreReadsEnd) \
- (__FILE__, __LINE__)
+ /* Similar to ANNOTATE_IGNORE_READS_BEGIN, but ignore writes instead. */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ AnnotateIgnoreWritesBegin(__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
+ /* Stop ignoring writes. */
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
-#elif defined(ABSL_INTERNAL_ANNOTALYSIS_ENABLED)
+/* 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)
-// 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() \
+ StaticAnnotateIgnoreReadsBegin(__FILE__, __LINE__)
-#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() \
- ABSL_INTERNAL_GLOBAL_SCOPED( \
- ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsBegin)) \
- ()
+ #define ANNOTATE_IGNORE_READS_END() \
+ StaticAnnotateIgnoreReadsEnd(__FILE__, __LINE__)
-#define ABSL_ANNOTATE_IGNORE_READS_END() \
- ABSL_INTERNAL_GLOBAL_SCOPED( \
- ABSL_INTERNAL_C_SYMBOL(AbslInternalAnnotateIgnoreReadsEnd)) \
- ()
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() \
+ StaticAnnotateIgnoreWritesBegin(__FILE__, __LINE__)
-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 {}
+ #define ANNOTATE_IGNORE_WRITES_END() \
+ StaticAnnotateIgnoreWritesEnd(__FILE__, __LINE__)
#else
-
-#define ABSL_ANNOTATE_IGNORE_READS_BEGIN() // empty
-#define ABSL_ANNOTATE_IGNORE_READS_END() // empty
-
+ #define ANNOTATE_IGNORE_READS_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_END() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_WRITES_END() /* empty */
#endif
-// -------------------------------------------------------------------------
-// Define IGNORE_WRITES_BEGIN/_END annotations.
+/* Implement the ANNOTATE_IGNORE_READS_AND_WRITES_* annotations using the more
+ primitive annotations defined above. */
+#if defined(ANNOTATIONS_ENABLED)
-#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 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
+ /* Stop ignoring both reads and writes. */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() \
+ do { \
+ ANNOTATE_IGNORE_WRITES_END(); \
+ ANNOTATE_IGNORE_READS_END(); \
+ }while (0)
#else
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN() /* empty */
+ #define ANNOTATE_IGNORE_READS_AND_WRITES_END() /* empty */
+#endif
-#define ABSL_ANNOTATE_IGNORE_WRITES_BEGIN() // empty
-#define ABSL_ANNOTATE_IGNORE_WRITES_END() // empty
-
+/* 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
#endif
-// -------------------------------------------------------------------------
-// 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)
+/* 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);
#ifdef __cplusplus
-// ABSL_ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
-#define ABSL_ANNOTATE_UNPROTECTED_READ(x) \
- absl::base_internal::AnnotateUnprotectedRead(x)
+}
+#endif
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace base_internal {
+/* ANNOTATE_UNPROTECTED_READ is the preferred way to annotate racey reads.
+ 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 AnnotateUnprotectedRead(const volatile T& x) { // NOLINT
- ABSL_ANNOTATE_IGNORE_READS_BEGIN();
+inline T ANNOTATE_UNPROTECTED_READ(const volatile T &x) { /* NOLINT */
+ ANNOTATE_IGNORE_READS_BEGIN();
T res = x;
- ABSL_ANNOTATE_IGNORE_READS_END();
+ ANNOTATE_IGNORE_READS_END();
return res;
-}
-
-} // namespace base_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-#endif
-
+ }
#else
-
-#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)
-
+ #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.
+#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. */
#include <sanitizer/common_interface_defs.h>
-
-#define ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
+#define ANNOTATE_CONTIGUOUS_CONTAINER(beg, end, old_mid, new_mid) \
__sanitizer_annotate_contiguous_container(beg, end, old_mid, new_mid)
-#define ABSL_ADDRESS_SANITIZER_REDZONE(name) \
- struct { \
- alignas(8) char x[8]; \
- } name
-
+#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 // ADDRESS_SANITIZER
-#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
+/* Undefine the macros intended only in this file. */
+#undef ANNOTALYSIS_ENABLED
+#undef ANNOTATIONS_ENABLED
+#undef ATTRIBUTE_IGNORE_READS_BEGIN
+#undef ATTRIBUTE_IGNORE_READS_END
-#endif // ABSL_BASE_DYNAMIC_ANNOTATIONS_H_
+#endif /* ABSL_BASE_DYNAMIC_ANNOTATIONS_H_ */
diff --git a/third_party/abseil-cpp/absl/base/internal/bits.h b/third_party/abseil-cpp/absl/base/internal/bits.h
new file mode 100644
index 0000000000..8b03453c18
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/internal/bits.h
@@ -0,0 +1,218 @@
+// 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_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>
+
+#include "absl/base/config.h"
+
+// 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 {
+ABSL_NAMESPACE_BEGIN
+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
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_BASE_INTERNAL_BITS_H_
diff --git a/third_party/abseil-cpp/absl/base/internal/bits_test.cc b/third_party/abseil-cpp/absl/base/internal/bits_test.cc
new file mode 100644
index 0000000000..7855fa6297
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/internal/bits_test.cc
@@ -0,0 +1,97 @@
+// 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/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/third_party/abseil-cpp/absl/base/internal/direct_mmap.h b/third_party/abseil-cpp/absl/base/internal/direct_mmap.h
index 274054cd5a..5618867ba0 100644
--- a/third_party/abseil-cpp/absl/base/internal/direct_mmap.h
+++ b/third_party/abseil-cpp/absl/base/internal/direct_mmap.h
@@ -61,10 +61,6 @@ 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 {
@@ -74,13 +70,9 @@ 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(__riscv) && __riscv_xlen == 32) || \
- (defined(__s390__) && !defined(__s390x__)) || \
- (defined(__sparc__) && !defined(__arch64__))
+ (defined(__s390__) && !defined(__s390x__))
// On these architectures, implement mmap with mmap2.
static int pagesize = 0;
if (pagesize == 0) {
diff --git a/third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h b/third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h
deleted file mode 100644
index b23c5ec1c4..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/dynamic_annotations.h
+++ /dev/null
@@ -1,398 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/base/internal/endian.h b/third_party/abseil-cpp/absl/base/internal/endian.h
index dad0e9aeb0..9677530e8d 100644
--- a/third_party/abseil-cpp/absl/base/internal/endian.h
+++ b/third_party/abseil-cpp/absl/base/internal/endian.h
@@ -26,7 +26,6 @@
#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"
@@ -174,36 +173,6 @@ 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));
@@ -264,36 +233,6 @@ 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));
diff --git a/third_party/abseil-cpp/absl/base/internal/endian_test.cc b/third_party/abseil-cpp/absl/base/internal/endian_test.cc
index a1691b1f82..aa6b849690 100644
--- a/third_party/abseil-cpp/absl/base/internal/endian_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/endian_test.cc
@@ -54,22 +54,24 @@ const uint32_t k32ValueBE{0x67452301};
const uint16_t k16ValueBE{0x2301};
#endif
-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));
+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;
}
- return result;
}
template<typename T>
-std::vector<T> GenerateRandomIntegers(size_t num_values_to_test) {
+std::vector<T> GenerateRandomIntegers(size_t numValuesToTest) {
std::vector<T> result;
- result.reserve(num_values_to_test);
std::mt19937_64 rng(kRandomSeed);
- for (size_t i = 0; i < num_values_to_test; ++i) {
+ for (size_t i = 0; i < numValuesToTest; ++i) {
result.push_back(rng());
}
return result;
@@ -146,7 +148,7 @@ void Swap64(char* bytes) {
}
TEST(EndianessTest, Uint16) {
- GBSwapHelper(GenerateAllUint16Values(), &Swap16);
+ GBSwapHelper(GenerateAllValuesForType<uint16_t>(), &Swap16);
}
TEST(EndianessTest, Uint32) {
diff --git a/third_party/abseil-cpp/absl/base/internal/errno_saver_test.cc b/third_party/abseil-cpp/absl/base/internal/errno_saver_test.cc
index e9b742c588..b845e2dd1a 100644
--- a/third_party/abseil-cpp/absl/base/internal/errno_saver_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/errno_saver_test.cc
@@ -18,7 +18,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/base/internal/strerror.h"
namespace {
using ::testing::Eq;
@@ -27,7 +26,7 @@ struct ErrnoPrinter {
int no;
};
std::ostream &operator<<(std::ostream &os, ErrnoPrinter ep) {
- return os << absl::base_internal::StrError(ep.no) << " [" << ep.no << "]";
+ return os << strerror(ep.no) << " [" << ep.no << "]";
}
bool operator==(ErrnoPrinter one, ErrnoPrinter two) { return one.no == two.no; }
diff --git a/third_party/abseil-cpp/absl/base/internal/exception_safety_testing.h b/third_party/abseil-cpp/absl/base/internal/exception_safety_testing.h
index 77a5aec642..6ba89d05df 100644
--- a/third_party/abseil-cpp/absl/base/internal/exception_safety_testing.h
+++ b/third_party/abseil-cpp/absl/base/internal/exception_safety_testing.h
@@ -536,22 +536,7 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
}
// Memory management operators
- static void* operator new(size_t s) noexcept(
- IsSpecified(TypeSpec::kNoThrowNew)) {
- if (!IsSpecified(TypeSpec::kNoThrowNew)) {
- exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
- }
- return ::operator new(s);
- }
-
- static void* operator new[](size_t s) noexcept(
- IsSpecified(TypeSpec::kNoThrowNew)) {
- if (!IsSpecified(TypeSpec::kNoThrowNew)) {
- exceptions_internal::MaybeThrow(ABSL_PRETTY_FUNCTION, true);
- }
- return ::operator new[](s);
- }
-
+ // Args.. allows us to overload regular and placement new in one shot
template <typename... Args>
static void* operator new(size_t s, Args&&... args) noexcept(
IsSpecified(TypeSpec::kNoThrowNew)) {
@@ -572,6 +557,12 @@ class ThrowingValue : private exceptions_internal::TrackedObject {
// Abseil doesn't support throwing overloaded operator delete. These are
// provided so a throwing operator-new can clean up after itself.
+ //
+ // 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
+ // 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>
@@ -735,8 +726,9 @@ class ThrowingAllocator : private exceptions_internal::TrackedObject {
ThrowingAllocator select_on_container_copy_construction() noexcept(
IsSpecified(AllocSpec::kNoThrowAllocate)) {
+ auto& out = *this;
ReadStateAndMaybeThrow(ABSL_PRETTY_FUNCTION);
- return *this;
+ return out;
}
template <typename U>
diff --git a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased.cc b/third_party/abseil-cpp/absl/base/internal/exponential_biased.cc
index 81d9a75765..1b30c061e3 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased.cc
+++ b/third_party/abseil-cpp/absl/base/internal/exponential_biased.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/profiling/internal/exponential_biased.h"
+#include "absl/base/internal/exponential_biased.h"
#include <stdint.h>
@@ -26,7 +26,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
// The algorithm generates a random number between 0 and 1 and applies the
// inverse cumulative distribution function for an exponential. Specifically:
@@ -64,7 +64,7 @@ int64_t ExponentialBiased::GetSkipCount(int64_t mean) {
// Assume huge values are bias neutral, retain bias for next call.
return std::numeric_limits<int64_t>::max() / 2;
}
- double value = std::rint(interval);
+ double value = std::round(interval);
bias_ = interval - value;
return value;
}
@@ -88,6 +88,6 @@ void ExponentialBiased::Initialize() {
initialized_ = true;
}
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased.h b/third_party/abseil-cpp/absl/base/internal/exponential_biased.h
index d31f7782e8..94f79a3378 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased.h
+++ b/third_party/abseil-cpp/absl/base/internal/exponential_biased.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_
-#define ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_
+#ifndef ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
+#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
#include <stdint.h>
@@ -22,7 +22,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
// ExponentialBiased provides a small and fast random number generator for a
// rounded exponential distribution. This generator manages very little state,
@@ -66,7 +66,7 @@ namespace profiling_internal {
// Adjusting with rounding bias is relatively trivial:
//
// double value = bias_ + exponential_distribution(mean)();
-// double rounded_value = std::rint(value);
+// double rounded_value = std::round(value);
// bias_ = value - rounded_value;
// return rounded_value;
//
@@ -123,8 +123,8 @@ inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) {
return (prng_mult * rnd + prng_add) & prng_mod_mask;
}
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_PROFILING_INTERNAL_EXPONENTIAL_BIASED_H_
+#endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_
diff --git a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased_test.cc b/third_party/abseil-cpp/absl/base/internal/exponential_biased_test.cc
index 5675001dd3..90a482d2a9 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/exponential_biased_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/exponential_biased_test.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/profiling/internal/exponential_biased.h"
+#include "absl/base/internal/exponential_biased.h"
#include <stddef.h>
@@ -28,7 +28,7 @@ using ::testing::Ge;
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
MATCHER_P2(IsBetween, a, b,
absl::StrCat(std::string(negation ? "isn't" : "is"), " between ", a,
@@ -185,7 +185,7 @@ TEST(ExponentialBiasedTest, InitializationModes) {
ABSL_CONST_INIT static ExponentialBiased eb_static;
EXPECT_THAT(eb_static.GetSkipCount(2), Ge(0));
-#ifdef ABSL_HAVE_THREAD_LOCAL
+#if ABSL_HAVE_THREAD_LOCAL
thread_local ExponentialBiased eb_thread;
EXPECT_THAT(eb_thread.GetSkipCount(2), Ge(0));
#endif
@@ -194,6 +194,6 @@ TEST(ExponentialBiasedTest, InitializationModes) {
EXPECT_THAT(eb_stack.GetSkipCount(2), Ge(0));
}
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/base/internal/fast_type_id.h b/third_party/abseil-cpp/absl/base/internal/fast_type_id.h
deleted file mode 100644
index 3db59e8374..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/fast_type_id.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc b/third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc
deleted file mode 100644
index 16f3c1458b..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/fast_type_id_test.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/invoke.h b/third_party/abseil-cpp/absl/base/internal/invoke.h
index 5c71f32823..c4eceebd7c 100644
--- a/third_party/abseil-cpp/absl/base/internal/invoke.h
+++ b/third_party/abseil-cpp/absl/base/internal/invoke.h
@@ -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_
@@ -170,13 +170,13 @@ struct Invoker {
// The result type of Invoke<F, Args...>.
template <typename F, typename... Args>
-using invoke_result_t = decltype(Invoker<F, Args...>::type::Invoke(
+using InvokeT = 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>
-invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) {
+InvokeT<F, Args...> Invoke(F&& f, Args&&... args) {
return Invoker<F, Args...>::type::Invoke(std::forward<F>(f),
std::forward<Args>(args)...);
}
diff --git a/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc b/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc
index 229ab9162d..1bf94438d6 100644
--- a/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc
+++ b/third_party/abseil-cpp/absl/base/internal/low_level_alloc.cc
@@ -598,7 +598,7 @@ static void *DoAllocWithArena(size_t request, LowLevelAlloc::Arena *arena) {
section.Leave();
result = &s->levels;
}
- ABSL_ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
+ ANNOTATE_MEMORY_IS_UNINITIALIZED(result, request);
return result;
}
diff --git a/third_party/abseil-cpp/absl/base/internal/low_level_alloc_test.cc b/third_party/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
index 31abb888a6..7abbbf9c59 100644
--- a/third_party/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/low_level_alloc_test.cc
@@ -21,12 +21,6 @@
#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 {
@@ -81,7 +75,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 absl::node_hash_map<int, BlockDesc> AllocMap;
+ typedef std::unordered_map<int, BlockDesc> AllocMap;
AllocMap allocated;
AllocMap::iterator it;
BlockDesc block_desc;
@@ -162,20 +156,5 @@ ABSL_NAMESPACE_END
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/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h b/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
index 9baccc0659..961cc981b8 100644
--- a/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
+++ b/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h
@@ -18,7 +18,6 @@
#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"
@@ -30,13 +29,6 @@ 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.
@@ -61,8 +53,6 @@ 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
@@ -86,23 +76,12 @@ class SchedulingGuard {
bool disabled;
};
- // 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;
+ // Access to SchedulingGuard is explicitly white-listed.
friend class SchedulingHelper;
friend class SpinLock;
- friend int absl::synchronization_internal::MutexDelay(int32_t c, int mode);
+
+ SchedulingGuard(const SchedulingGuard&) = delete;
+ SchedulingGuard& operator=(const SchedulingGuard&) = delete;
};
//------------------------------------------------------------------------------
@@ -121,12 +100,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.cc b/third_party/abseil-cpp/absl/base/internal/periodic_sampler.cc
index a738a82c86..520dabbaa0 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.cc
+++ b/third_party/abseil-cpp/absl/base/internal/periodic_sampler.cc
@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/profiling/internal/periodic_sampler.h"
+#include "absl/base/internal/periodic_sampler.h"
#include <atomic>
-#include "absl/profiling/internal/exponential_biased.h"
+#include "absl/base/internal/exponential_biased.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
int64_t PeriodicSamplerBase::GetExponentialBiased(int period) noexcept {
return rng_.GetStride(period);
@@ -48,6 +48,6 @@ bool PeriodicSamplerBase::SubtleConfirmSample() noexcept {
return true;
}
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.h b/third_party/abseil-cpp/absl/base/internal/periodic_sampler.h
index 54f0af452b..f8a86796b1 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler.h
+++ b/third_party/abseil-cpp/absl/base/internal/periodic_sampler.h
@@ -12,19 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_
-#define ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_
+#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"
-#include "absl/profiling/internal/exponential_biased.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
// PeriodicSamplerBase provides the basic period sampler implementation.
//
@@ -149,7 +149,7 @@ class PeriodicSamplerBase {
// ICC x64 (OK) : https://gcc.godbolt.org/z/ptTNfD
// MSVC x64 (OK) : https://gcc.godbolt.org/z/76j4-5
uint64_t stride_ = 0;
- absl::profiling_internal::ExponentialBiased rng_;
+ ExponentialBiased rng_;
};
inline bool PeriodicSamplerBase::SubtleMaybeSample() noexcept {
@@ -204,8 +204,8 @@ class PeriodicSampler final : public PeriodicSamplerBase {
template <typename Tag, int default_period>
std::atomic<int> PeriodicSampler<Tag, default_period>::period_(default_period);
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_PROFILING_INTERNAL_PERIODIC_SAMPLER_H_
+#endif // ABSL_BASE_INTERNAL_PERIODIC_SAMPLER_H_
diff --git a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_benchmark.cc b/third_party/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
index 8f0e5574c3..5ad469ce79 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_benchmark.cc
+++ b/third_party/abseil-cpp/absl/base/internal/periodic_sampler_benchmark.cc
@@ -12,12 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/profiling/internal/periodic_sampler.h"
#include "benchmark/benchmark.h"
+#include "absl/base/internal/periodic_sampler.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
namespace {
template <typename Sampler>
@@ -74,6 +74,6 @@ void BM_PeriodicSampler_Disabled(benchmark::State& state) {
BENCHMARK(BM_PeriodicSampler_Disabled);
} // namespace
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_test.cc b/third_party/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
index ef986f3878..3b301e37ab 100644
--- a/third_party/abseil-cpp/absl/profiling/internal/periodic_sampler_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/periodic_sampler_test.cc
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include "absl/profiling/internal/periodic_sampler.h"
+#include "absl/base/internal/periodic_sampler.h"
#include <thread> // NOLINT(build/c++11)
@@ -23,7 +23,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
+namespace base_internal {
namespace {
using testing::Eq;
@@ -172,6 +172,6 @@ TEST(PeriodicSamplerTest, SetGlobalPeriod) {
}
} // namespace
-} // namespace profiling_internal
+} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/base/internal/raw_logging.cc b/third_party/abseil-cpp/absl/base/internal/raw_logging.cc
index 074e026adb..40cea55061 100644
--- a/third_party/abseil-cpp/absl/base/internal/raw_logging.cc
+++ b/third_party/abseil-cpp/absl/base/internal/raw_logging.cc
@@ -67,32 +67,28 @@
#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 selected 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
+// whitelisted set of platforms for which we expect not to be able to raw log.
-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;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+ absl::raw_logging_internal::LogPrefixHook>
+ log_prefix_hook;
+ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES static absl::base_internal::AtomicHook<
+ absl::raw_logging_internal::AbortHook>
+ abort_hook;
#ifdef ABSL_LOW_LEVEL_WRITE_SUPPORTED
-constexpr char kTruncated[] = " ... (message truncated)\n";
+static const 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[].
-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) {
+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) {
int n = vsnprintf(*buf, *size, format, ap);
bool result = true;
if (n < 0 || n > *size) {
@@ -100,7 +96,7 @@ bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
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;
@@ -109,7 +105,9 @@ bool VADoRawLog(char** buf, int* size, const char* format, va_list ap) {
}
#endif // ABSL_LOW_LEVEL_WRITE_SUPPORTED
-constexpr int kLogBufSize = 3000;
+static constexpr int kLogBufSize = 3000;
+
+namespace {
// CAVEAT: vsnprintf called from *DoRawLog below has some (exotic) code paths
// that invoke malloc() and getenv() that might acquire some locks.
@@ -168,7 +166,7 @@ void RawLogVA(absl::LogSeverity severity, const char* file, int line,
} else {
DoRawLog(&buf, &size, "%s", kTruncated);
}
- SafeWriteToStderr(buffer, strlen(buffer));
+ absl::raw_logging_internal::SafeWriteToStderr(buffer, strlen(buffer));
}
#else
static_cast<void>(format);
@@ -183,18 +181,11 @@ 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 {
+ABSL_NAMESPACE_BEGIN
+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);
@@ -210,6 +201,8 @@ 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);
@@ -217,6 +210,15 @@ 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;
@@ -225,14 +227,10 @@ bool RawLoggingFullySupported() {
#endif // !ABSL_LOW_LEVEL_WRITE_SUPPORTED
}
-ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL
+ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
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);
}
diff --git a/third_party/abseil-cpp/absl/base/internal/raw_logging.h b/third_party/abseil-cpp/absl/base/internal/raw_logging.h
index 2bf7aabac1..418d6c856f 100644
--- a/third_party/abseil-cpp/absl/base/internal/raw_logging.h
+++ b/third_party/abseil-cpp/absl/base/internal/raw_logging.h
@@ -72,14 +72,10 @@
//
// The API is a subset of the above: each macro only takes two arguments. Use
// StrCat if you need to build a richer message.
-#define ABSL_INTERNAL_LOG(severity, message) \
- do { \
- constexpr const char* absl_raw_logging_internal_filename = __FILE__; \
- ::absl::raw_logging_internal::internal_log_function( \
- ABSL_RAW_LOGGING_INTERNAL_##severity, \
- absl_raw_logging_internal_filename, __LINE__, message); \
- if (ABSL_RAW_LOGGING_INTERNAL_##severity == ::absl::LogSeverity::kFatal) \
- ABSL_INTERNAL_UNREACHABLE; \
+#define ABSL_INTERNAL_LOG(severity, message) \
+ do { \
+ ::absl::raw_logging_internal::internal_log_function( \
+ ABSL_RAW_LOGGING_INTERNAL_##severity, __FILE__, __LINE__, message); \
} while (0)
#define ABSL_INTERNAL_CHECK(condition, message) \
@@ -174,18 +170,10 @@ using InternalLogFunction = void (*)(absl::LogSeverity severity,
const char* file, int line,
const std::string& message);
-ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES ABSL_DLL extern base_internal::AtomicHook<
+ABSL_DLL ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES 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
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock.cc b/third_party/abseil-cpp/absl/base/internal/spinlock.cc
index 35c0696a34..830d4729af 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock.cc
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock.cc
@@ -66,19 +66,35 @@ 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.
@@ -105,14 +121,6 @@ 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
@@ -125,9 +133,8 @@ 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 -- 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.
+ // lock wait time in the lock as that will cause the current lock
+ // owner to think it experienced contention.
if (lockword_.compare_exchange_strong(
lock_value, lock_value | kSpinLockSleeper,
std::memory_order_relaxed, std::memory_order_relaxed)) {
@@ -141,17 +148,15 @@ 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);
@@ -185,32 +190,30 @@ 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^kProfileTimestampShift
+// processors we divide to reduce the granularity to 2^PROFILE_TIMESTAMP_SHIFT
// 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.
-static constexpr int kProfileTimestampShift = 7;
-
-// We currently reserve the lower 3 bits.
-static constexpr int kLockwordReservedShift = 3;
+enum { PROFILE_TIMESTAMP_SHIFT = 7 };
+enum { LOCKWORD_RESERVED_SHIFT = 3 }; // We currently reserve the lower 3 bits.
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() >> kLockwordReservedShift;
+ std::numeric_limits<uint32_t>::max() >> LOCKWORD_RESERVED_SHIFT;
int64_t scaled_wait_time =
- (wait_end_time - wait_start_time) >> kProfileTimestampShift;
+ (wait_end_time - wait_start_time) >> PROFILE_TIMESTAMP_SHIFT;
// 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) << kLockwordReservedShift);
+ std::min(scaled_wait_time, kMaxWaitTime) << LOCKWORD_RESERVED_SHIFT);
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 << kLockwordReservedShift);
+ kSpinLockSleeper + (1 << LOCKWORD_RESERVED_SHIFT);
if (clamped == kSpinLockSleeper) {
return kMinWaitTime;
}
@@ -221,7 +224,8 @@ 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 << (kProfileTimestampShift - kLockwordReservedShift);
+ return scaled_wait_time
+ << (PROFILE_TIMESTAMP_SHIFT - LOCKWORD_RESERVED_SHIFT);
}
} // namespace base_internal
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock.h b/third_party/abseil-cpp/absl/base/internal/spinlock.h
index ac40daff12..24e2e9a6f8 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock.h
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock.h
@@ -15,16 +15,17 @@
//
// Most users requiring mutual exclusion should use Mutex.
-// SpinLock is provided for use in two situations:
-// - for use by Abseil internal code that Mutex itself depends on
+// SpinLock is provided for use in three 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
// handler, all code that acquires the lock must ensure that the signal cannot
// arrive while they are holding the lock. Typically, this is done by blocking
// the signal.
-//
-// Threads waiting on a SpinLock may be woken in an arbitrary order.
#ifndef ABSL_BASE_INTERNAL_SPINLOCK_H_
#define ABSL_BASE_INTERNAL_SPINLOCK_H_
@@ -35,7 +36,6 @@
#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"
@@ -55,22 +55,29 @@ class ABSL_LOCKABLE SpinLock {
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 initialized using this constructor, we depend on the fact
+ // that the linker has already initialized the memory appropriately. The lock
+ // is initialized in non-cooperative mode.
+ //
+ // 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() ABSL_EXCLUSIVE_LOCK_FUNCTION() {
@@ -139,27 +146,14 @@ class ABSL_LOCKABLE SpinLock {
//
// bit[0] encodes whether a lock is being held.
// bit[1] encodes whether a lock uses cooperative scheduling.
- // bit[2] encodes whether the current lock holder disabled scheduling when
- // acquiring the lock. Only set when kSpinLockHeld is also set.
+ // bit[2] encodes whether a lock disables scheduling.
// bit[3:31] encodes time a lock spent on waiting as a 29-bit unsigned int.
- // 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);
+ enum { kSpinLockHeld = 1 };
+ enum { kSpinLockCooperative = 2 };
+ enum { kSpinLockDisabledScheduling = 4 };
+ enum { kSpinLockSleeper = 8 };
+ enum { kWaitTimeMask = // Includes kSpinLockSleeper.
+ ~(kSpinLockHeld | kSpinLockCooperative | kSpinLockDisabledScheduling) };
// Returns true if the provided scheduling mode is cooperative.
static constexpr bool IsCooperative(
@@ -168,6 +162,7 @@ class ABSL_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();
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc b/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc
index 7b0cada4f1..bc468940fc 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc
@@ -20,7 +20,7 @@
extern "C" {
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ABSL_ATTRIBUTE_WEAK void 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 ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
// arbitrary code.
}
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc b/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc
index 202f7cdfc8..323edd62f4 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc
@@ -46,17 +46,9 @@ 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 ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t> *w, uint32_t value, int loop,
absl::base_internal::SchedulingMode) {
absl::base_internal::ErrnoSaver errno_saver;
@@ -66,8 +58,8 @@ ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
syscall(SYS_futex, w, FUTEX_WAIT | FUTEX_PRIVATE_FLAG, value, &tm);
}
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
- std::atomic<uint32_t> *w, bool all) {
+ABSL_ATTRIBUTE_WEAK void 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/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc b/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc
index 4f6f887d99..fcd21b151b 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc
@@ -25,7 +25,7 @@
extern "C" {
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockDelay(
std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
absl::base_internal::SchedulingMode /* mode */) {
absl::base_internal::ErrnoSaver errno_saver;
@@ -40,7 +40,7 @@ ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
}
}
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
+ABSL_ATTRIBUTE_WEAK void AbslInternalSpinLockWake(
std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
} // extern "C"
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h b/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h
index 9a1adcda5e..169bc749fb 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h
@@ -39,22 +39,22 @@ struct SpinLockWaitTransition {
// satisfying 0<=i<n && trans[i].done, atomically make the transition,
// then return the old value of *w. Make any other atomic transitions
// where !trans[i].done, but continue waiting.
-//
-// Wakeups for threads blocked on SpinLockWait do not respect priorities.
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. 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.
+// 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.
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 call to SpinLockWake(w).
+// 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.
void SpinLockDelay(std::atomic<uint32_t> *w, uint32_t value, int loop,
base_internal::SchedulingMode scheduling_mode);
@@ -73,23 +73,21 @@ ABSL_NAMESPACE_END
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(std::atomic<uint32_t> *w,
- bool all);
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
+void AbslInternalSpinLockWake(std::atomic<uint32_t> *w, bool all);
+void 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) {
- ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(w, all);
+ 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) {
- ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)
- (w, value, loop, scheduling_mode);
+ AbslInternalSpinLockDelay(w, value, loop, scheduling_mode);
}
#endif // ABSL_BASE_INTERNAL_SPINLOCK_WAIT_H_
diff --git a/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc b/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc
index 9d224813a5..78654b5b59 100644
--- a/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc
+++ b/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc
@@ -20,9 +20,9 @@
extern "C" {
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
- std::atomic<uint32_t>* /* lock_word */, uint32_t /* value */, int loop,
- absl::base_internal::SchedulingMode /* mode */) {
+void 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 ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockDelay)(
}
}
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalSpinLockWake)(
- std::atomic<uint32_t>* /* lock_word */, bool /* all */) {}
+void AbslInternalSpinLockWake(std::atomic<uint32_t>* /* lock_word */,
+ bool /* all */) {}
} // extern "C"
diff --git a/third_party/abseil-cpp/absl/base/internal/strerror.cc b/third_party/abseil-cpp/absl/base/internal/strerror.cc
deleted file mode 100644
index 0d6226fd0a..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/strerror.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/strerror.h b/third_party/abseil-cpp/absl/base/internal/strerror.h
deleted file mode 100644
index 350097366e..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/strerror.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc b/third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc
deleted file mode 100644
index c9ab14a89d..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/strerror_benchmark.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/strerror_test.cc b/third_party/abseil-cpp/absl/base/internal/strerror_test.cc
deleted file mode 100644
index e32d5b5c9b..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/strerror_test.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/sysinfo.cc b/third_party/abseil-cpp/absl/base/internal/sysinfo.cc
index a7cfb461f3..a0930e9781 100644
--- a/third_party/abseil-cpp/absl/base/internal/sysinfo.cc
+++ b/third_party/abseil-cpp/absl/base/internal/sysinfo.cc
@@ -39,7 +39,6 @@
#endif
#include <string.h>
-
#include <cassert>
#include <cstdint>
#include <cstdio>
@@ -51,88 +50,17 @@
#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 {
-namespace {
-
-#if defined(_WIN32)
-
-// Returns number of bits set in `bitMask`
-DWORD Win32CountSetBits(ULONG_PTR bitMask) {
- for (DWORD bitSetCount = 0; ; ++bitSetCount) {
- if (bitMask == 0) return bitSetCount;
- bitMask &= bitMask - 1;
- }
-}
-
-// Returns the number of logical CPUs using GetLogicalProcessorInformation(), or
-// 0 if the number of processors is not available or can not be computed.
-// https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation
-int Win32NumCPUs() {
-#pragma comment(lib, "kernel32.lib")
- using Info = SYSTEM_LOGICAL_PROCESSOR_INFORMATION;
-
- DWORD info_size = sizeof(Info);
- Info* info(static_cast<Info*>(malloc(info_size)));
- if (info == nullptr) return 0;
-
- bool success = GetLogicalProcessorInformation(info, &info_size);
- if (!success && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
- free(info);
- info = static_cast<Info*>(malloc(info_size));
- if (info == nullptr) return 0;
- success = GetLogicalProcessorInformation(info, &info_size);
- }
-
- DWORD logicalProcessorCount = 0;
- if (success) {
- Info* ptr = info;
- DWORD byteOffset = 0;
- while (byteOffset + sizeof(Info) <= info_size) {
- switch (ptr->Relationship) {
- case RelationProcessorCore:
- logicalProcessorCount += Win32CountSetBits(ptr->ProcessorMask);
- break;
-
- case RelationNumaNode:
- case RelationCache:
- case RelationProcessorPackage:
- // Ignore other entries
- break;
-
- default:
- // Ignore unknown entries
- break;
- }
- byteOffset += sizeof(Info);
- ptr++;
- }
- }
- free(info);
- return logicalProcessorCount;
-}
-
-#endif
-
-} // namespace
-
-
static int GetNumCPUs() {
#if defined(__myriad2__)
return 1;
-#elif defined(_WIN32)
- const unsigned hardware_concurrency = Win32NumCPUs();
- return hardware_concurrency ? hardware_concurrency : 1;
-#elif defined(_AIX)
- return sysconf(_SC_NPROCESSORS_ONLN);
#else
// Other possibilities:
// - Read /sys/devices/system/cpu/online and use cpumask_parse()
@@ -144,12 +72,6 @@ static int GetNumCPUs() {
#if defined(_WIN32)
static double GetNominalCPUFrequency() {
-#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
@@ -169,7 +91,6 @@ static double GetNominalCPUFrequency() {
}
}
return 1.0;
-#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
}
#elif defined(CTL_HW) && defined(HW_CPU_FREQ)
@@ -415,16 +336,15 @@ pid_t GetTID() {
#else
// Fallback implementation of GetTID using pthread_getspecific.
-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);
+static once_flag tid_once;
+static pthread_key_t tid_key;
+static absl::base_internal::SpinLock tid_lock(
+ absl::base_internal::kLinkerInitialized);
// 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().
-ABSL_CONST_INIT static std::vector<uint32_t> *tid_array
- ABSL_GUARDED_BY(tid_lock) = nullptr;
+static std::vector<uint32_t>* tid_array GUARDED_BY(tid_lock) = nullptr;
static constexpr int kBitsPerWord = 32; // tid_array is uint32_t.
// Returns the TID to tid_array.
@@ -491,18 +411,6 @@ 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/third_party/abseil-cpp/absl/base/internal/sysinfo.h b/third_party/abseil-cpp/absl/base/internal/sysinfo.h
index 119cf1f0e8..7246d5dd95 100644
--- a/third_party/abseil-cpp/absl/base/internal/sysinfo.h
+++ b/third_party/abseil-cpp/absl/base/internal/sysinfo.h
@@ -30,7 +30,6 @@
#include <cstdint>
-#include "absl/base/config.h"
#include "absl/base/port.h"
namespace absl {
@@ -60,13 +59,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/base/internal/sysinfo_test.cc b/third_party/abseil-cpp/absl/base/internal/sysinfo_test.cc
index 5f9e45f6aa..fa8b88b1dc 100644
--- a/third_party/abseil-cpp/absl/base/internal/sysinfo_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/sysinfo_test.cc
@@ -37,28 +37,17 @@ 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) {
- // 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
+#if !(defined(__aarch64__) && defined(__linux__)) && !defined(__EMSCRIPTEN__)
EXPECT_GE(NominalCPUFrequency(), 1000.0)
<< "NominalCPUFrequency() did not return a reasonable value";
+#else
+ // Aarch64 cannot read the CPU frequency from sysfs, so we get back 1.0.
+ // Emscripten does not have a sysfs to read from at all.
+ EXPECT_EQ(NominalCPUFrequency(), 1.0)
+ << "CPU frequency detection was fixed! Please update unittest.";
#endif
}
-#endif
TEST(SysinfoTest, GetTID) {
EXPECT_EQ(GetTID(), GetTID()); // Basic compile and equality test.
diff --git a/third_party/abseil-cpp/absl/base/internal/thread_identity.cc b/third_party/abseil-cpp/absl/base/internal/thread_identity.cc
index 9950e63a79..d63a04ae91 100644
--- a/third_party/abseil-cpp/absl/base/internal/thread_identity.cc
+++ b/third_party/abseil-cpp/absl/base/internal/thread_identity.cc
@@ -23,7 +23,6 @@
#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"
@@ -54,11 +53,9 @@ 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.
-// Apple platforms have the visibility attribute, but issue a compile warning
-// that protected visibility is unsupported.
-#if ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
+#ifdef __GNUC__
__attribute__((visibility("protected")))
-#endif // ABSL_HAVE_ATTRIBUTE(visibility) && !defined(__APPLE__)
+#endif // __GNUC__
#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;
@@ -120,10 +117,10 @@ void SetCurrentThreadIdentity(
ABSL_THREAD_IDENTITY_MODE == ABSL_THREAD_IDENTITY_MODE_USE_CPP11
// Please see the comment on `CurrentThreadIdentityIfPresent` in
-// thread_identity.h. When we cannot expose thread_local variables in
-// headers, we opt for the correct-but-slower option of not inlining this
-// function.
-#ifndef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
+// 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
diff --git a/third_party/abseil-cpp/absl/base/internal/thread_identity.h b/third_party/abseil-cpp/absl/base/internal/thread_identity.h
index 659694b326..ceb109b41c 100644
--- a/third_party/abseil-cpp/absl/base/internal/thread_identity.h
+++ b/third_party/abseil-cpp/absl/base/internal/thread_identity.h
@@ -32,7 +32,6 @@
#include "absl/base/config.h"
#include "absl/base/internal/per_thread_tls.h"
-#include "absl/base/optimization.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -70,28 +69,30 @@ 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.
- 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).
+
+ // 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;
// State values:
// kAvailable: This PerThreadSynch is available.
@@ -110,30 +111,30 @@ struct PerThreadSynch {
};
std::atomic<State> state;
- // 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 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
- intptr_t readers; // Number of readers in mutex.
+ bool wake; // This thread is to be woken from a Mutex.
- // When priority will next be read (cycles).
- int64_t next_priority_read_cycles;
+ // 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;
// 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
@@ -143,7 +144,7 @@ struct ThreadIdentity {
// Private: Reserved for absl::synchronization_internal::Waiter.
struct WaiterState {
- alignas(void*) char data[128];
+ char data[128];
} waiter_state;
// Used by PerThreadSem::{Get,Set}ThreadBlockedCounter().
@@ -188,32 +189,30 @@ void ClearCurrentThreadIdentity();
// May be chosen at compile time via: -DABSL_FORCE_THREAD_IDENTITY_MODE=<mode
// index>
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC
-#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be directly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC cannot be direcly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_POSIX_SETSPECIFIC 0
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_TLS
-#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be directly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_TLS cannot be direcly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_TLS 1
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be directly set
+#error ABSL_THREAD_IDENTITY_MODE_USE_CPP11 cannot be direcly set
#else
#define ABSL_THREAD_IDENTITY_MODE_USE_CPP11 2
#endif
#ifdef ABSL_THREAD_IDENTITY_MODE
-#error ABSL_THREAD_IDENTITY_MODE cannot be directly set
+#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) && !defined(__MINGW32__)
#define ABSL_THREAD_IDENTITY_MODE ABSL_THREAD_IDENTITY_MODE_USE_CPP11
-#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__) && \
+#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.
@@ -236,18 +235,13 @@ ABSL_CONST_INIT extern thread_local ThreadIdentity* thread_identity_ptr;
#error Thread-local storage not detected on this platform
#endif
-// thread_local variables cannot be in headers exposed by DLLs or in certain
-// build configurations on Apple platforms. However, it is important for
-// performance reasons in general that `CurrentThreadIdentityIfPresent` be
-// inlined. In the other cases we opt to have the function not be inlined. Note
+// 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.
-#if !defined(__APPLE__) && !defined(ABSL_BUILD_DLL) && \
- !defined(ABSL_CONSUME_DLL)
-#define ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT 1
-#endif
-
-#ifdef ABSL_INTERNAL_INLINE_CURRENT_THREAD_IDENTITY_IF_PRESENT
+// 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;
}
diff --git a/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc b/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
index 46a6f74346..3685779ce8 100644
--- a/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
+++ b/third_party/abseil-cpp/absl/base/internal/thread_identity_test.cc
@@ -21,7 +21,6 @@
#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"
@@ -30,9 +29,10 @@ ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
-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);
+// protects num_identities_reused
+static absl::base_internal::SpinLock map_lock(
+ absl::base_internal::kLinkerInitialized);
+static int num_identities_reused;
static const void* const kCheckNoIdentity = reinterpret_cast<void*>(1);
@@ -75,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 = 32;
+ static const int kNumThreads = 400;
for (int iter = 0; iter < kNumLoops; iter++) {
std::vector<std::thread> threads;
for (int i = 0; i < kNumThreads; ++i) {
@@ -90,7 +90,6 @@ 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);
}
diff --git a/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc b/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc
index c260ff1eed..c055f75d9d 100644
--- a/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc
+++ b/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc
@@ -18,7 +18,6 @@
#include <functional>
#include <new>
#include <stdexcept>
-
#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
@@ -26,186 +25,83 @@ 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
+}
} // 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() {
-#ifdef ABSL_HAVE_EXCEPTIONS
- Throw(std::bad_function_call());
-#else
- std::abort();
-#endif
-}
+void ThrowStdBadFunctionCall() { Throw(std::bad_function_call()); }
-void ThrowStdBadAlloc() {
-#ifdef ABSL_HAVE_EXCEPTIONS
- Throw(std::bad_alloc());
-#else
- std::abort();
-#endif
-}
+void ThrowStdBadAlloc() { Throw(std::bad_alloc()); }
} // namespace base_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h b/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
index 39207d8a5c..2a510603bc 100644
--- a/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
+++ b/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h
@@ -19,8 +19,6 @@
#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.
//
@@ -30,7 +28,7 @@
#error "ABSL_INTERNAL_HAVE_TSAN_INTERFACE cannot be directly set."
#endif
-#if defined(ABSL_HAVE_THREAD_SANITIZER) && defined(__has_include)
+#if defined(THREAD_SANITIZER) && defined(__has_include)
#if __has_include(<sanitizer/tsan_interface.h>)
#define ABSL_INTERNAL_HAVE_TSAN_INTERFACE 1
#endif
diff --git a/third_party/abseil-cpp/absl/base/internal/unaligned_access.h b/third_party/abseil-cpp/absl/base/internal/unaligned_access.h
index 093dd9b499..6be56c865b 100644
--- a/third_party/abseil-cpp/absl/base/internal/unaligned_access.h
+++ b/third_party/abseil-cpp/absl/base/internal/unaligned_access.h
@@ -31,6 +31,80 @@
// 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 {
+ABSL_NAMESPACE_BEGIN
+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
+ABSL_NAMESPACE_END
+} // 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))
+
+#else
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
@@ -77,6 +151,8 @@ ABSL_NAMESPACE_END
#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/third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc b/third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc
deleted file mode 100644
index ff8c2b3fb4..0000000000
--- a/third_party/abseil-cpp/absl/base/internal/unique_small_name_test.cc
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
index 4d352bd110..f1e7bbef84 100644
--- a/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
+++ b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc
@@ -87,10 +87,6 @@ int64_t UnscaledCycleClock::Now() {
double UnscaledCycleClock::Frequency() {
#ifdef __GLIBC__
return __ppc_get_timebase_freq();
-#elif defined(_AIX)
- // This is the same constant value as returned by
- // __ppc_get_timebase_freq().
- return static_cast<double>(512000000);
#elif defined(__FreeBSD__)
static once_flag init_timebase_frequency_once;
static double timebase_frequency = 0.0;
@@ -123,23 +119,13 @@ double UnscaledCycleClock::Frequency() {
return aarch64_timer_frequency;
}
-#elif defined(__riscv)
-
-int64_t UnscaledCycleClock::Now() {
- int64_t virtual_timer_value;
- asm volatile("rdcycle %0" : "=r"(virtual_timer_value));
- return virtual_timer_value;
-}
-
-double UnscaledCycleClock::Frequency() {
- return base_internal::NominalCPUFrequency();
-}
-
#elif defined(_M_IX86) || defined(_M_X64)
#pragma intrinsic(__rdtsc)
-int64_t UnscaledCycleClock::Now() { return __rdtsc(); }
+int64_t UnscaledCycleClock::Now() {
+ return __rdtsc();
+}
double UnscaledCycleClock::Frequency() {
return base_internal::NominalCPUFrequency();
diff --git a/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
index 681ff8f996..cdce9bf8a8 100644
--- a/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
+++ b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
@@ -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 use only, you should consider using CycleClock
-// instead.
+// This class is for internal / whitelisted use only, you should consider
+// using CycleClock instead.
//
// Notes:
// The cycle counter frequency is not necessarily the core clock frequency.
@@ -46,8 +46,8 @@
// The following platforms have an implementation of a hardware counter.
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || \
- defined(__powerpc__) || defined(__ppc__) || defined(__riscv) || \
- defined(_M_IX86) || defined(_M_X64)
+ defined(__powerpc__) || defined(__ppc__) || \
+ defined(_M_IX86) || defined(_M_X64)
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 1
#else
#define ABSL_HAVE_UNSCALED_CYCLECLOCK_IMPLEMENTATION 0
@@ -80,8 +80,8 @@
// This macro can be used to test if UnscaledCycleClock::Frequency()
// is NominalCPUFrequency() on a particular platform.
-#if (defined(__i386__) || defined(__x86_64__) || defined(__riscv) || \
- defined(_M_IX86) || defined(_M_X64))
+#if (defined(__i386__) || defined(__x86_64__) || \
+ defined(_M_IX86) || defined(_M_X64))
#define ABSL_INTERNAL_UNSCALED_CYCLECLOCK_FREQUENCY_IS_CPU_FREQUENCY
#endif
@@ -109,7 +109,7 @@ class UnscaledCycleClock {
// value.
static double Frequency();
- // Allowed users
+ // Whitelisted friends.
friend class base_internal::CycleClock;
friend class time_internal::UnscaledCycleClockWrapperForGetCurrentTime;
friend class base_internal::UnscaledCycleClockWrapperForInitializeFrequency;
diff --git a/third_party/abseil-cpp/absl/base/invoke_test.cc b/third_party/abseil-cpp/absl/base/invoke_test.cc
index bcdef36c3b..6aa613c913 100644
--- a/third_party/abseil-cpp/absl/base/invoke_test.cc
+++ b/third_party/abseil-cpp/absl/base/invoke_test.cc
@@ -86,73 +86,71 @@ 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(base_internal::invoke(std::declval<const F&>())) CallMaybeWithArg(
- const F& f) {
- return base_internal::invoke(f);
+decltype(Invoke(std::declval<const F&>())) CallMaybeWithArg(const F& f) {
+ return Invoke(f);
}
template <typename F>
-decltype(base_internal::invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(
- const F& f) {
- return base_internal::invoke(f, 42);
+decltype(Invoke(std::declval<const F&>(), 42)) CallMaybeWithArg(const F& f) {
+ return Invoke(f, 42);
}
TEST(InvokeTest, Function) {
- EXPECT_EQ(1, base_internal::invoke(Function, 3, 2));
- EXPECT_EQ(1, base_internal::invoke(&Function, 3, 2));
+ EXPECT_EQ(1, Invoke(Function, 3, 2));
+ EXPECT_EQ(1, Invoke(&Function, 3, 2));
}
TEST(InvokeTest, NonCopyableArgument) {
- EXPECT_EQ(42, base_internal::invoke(Sink, make_unique<int>(42)));
+ EXPECT_EQ(42, Invoke(Sink, make_unique<int>(42)));
}
TEST(InvokeTest, NonCopyableResult) {
- EXPECT_THAT(base_internal::invoke(Factory, 42), ::testing::Pointee(42));
+ EXPECT_THAT(Invoke(Factory, 42), ::testing::Pointee(42));
}
-TEST(InvokeTest, VoidResult) { base_internal::invoke(NoOp); }
+TEST(InvokeTest, VoidResult) {
+ Invoke(NoOp);
+}
TEST(InvokeTest, ConstFunctor) {
- EXPECT_EQ(1, base_internal::invoke(ConstFunctor(), 3, 2));
+ EXPECT_EQ(1, Invoke(ConstFunctor(), 3, 2));
}
TEST(InvokeTest, MutableFunctor) {
MutableFunctor f;
- EXPECT_EQ(1, base_internal::invoke(f, 3, 2));
- EXPECT_EQ(1, base_internal::invoke(MutableFunctor(), 3, 2));
+ EXPECT_EQ(1, Invoke(f, 3, 2));
+ EXPECT_EQ(1, Invoke(MutableFunctor(), 3, 2));
}
TEST(InvokeTest, EphemeralFunctor) {
EphemeralFunctor f;
- EXPECT_EQ(1, base_internal::invoke(std::move(f), 3, 2));
- EXPECT_EQ(1, base_internal::invoke(EphemeralFunctor(), 3, 2));
+ EXPECT_EQ(1, Invoke(std::move(f), 3, 2));
+ EXPECT_EQ(1, Invoke(EphemeralFunctor(), 3, 2));
}
TEST(InvokeTest, OverloadedFunctor) {
OverloadedFunctor f;
const OverloadedFunctor& cf = f;
- 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("&", Invoke(f));
+ EXPECT_EQ("& 42", Invoke(f, " 42"));
- EXPECT_EQ("&&", base_internal::invoke(std::move(f)));
+ EXPECT_EQ("const&", Invoke(cf));
+ EXPECT_EQ("const& 42", Invoke(cf, " 42"));
- OverloadedFunctor f2;
- EXPECT_EQ("&& 42", base_internal::invoke(std::move(f2), " 42"));
+ EXPECT_EQ("&&", Invoke(std::move(f)));
+ EXPECT_EQ("&& 42", Invoke(std::move(f), " 42"));
}
TEST(InvokeTest, ReferenceWrapper) {
ConstFunctor cf;
MutableFunctor mf;
- 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));
+ 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));
}
TEST(InvokeTest, MemberFunction) {
@@ -160,62 +158,58 @@ TEST(InvokeTest, MemberFunction) {
std::unique_ptr<const Class> cp(new Class);
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));
+ EXPECT_EQ(1, Invoke(&Class::Method, p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::Method, p.get(), 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::Method, *p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::RefMethod, p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::RefMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::RefMethod, *p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::RefRefMethod, std::move(*p), 3, 2)); // NOLINT
+ EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::NoExceptMethod, *p, 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::VolatileMethod, p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::VolatileMethod, p.get(), 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *p, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp, 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::VolatileMethod, vp.get(), 3, 2));
+ EXPECT_EQ(1, Invoke(&Class::VolatileMethod, *vp, 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));
}
TEST(InvokeTest, DataMember) {
std::unique_ptr<Class> p(new Class{42});
std::unique_ptr<const Class> cp(new Class{42});
- 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()));
+ EXPECT_EQ(42, Invoke(&Class::member, p));
+ EXPECT_EQ(42, Invoke(&Class::member, *p));
+ EXPECT_EQ(42, Invoke(&Class::member, p.get()));
- base_internal::invoke(&Class::member, p) = 42;
- base_internal::invoke(&Class::member, p.get()) = 42;
+ Invoke(&Class::member, p) = 42;
+ Invoke(&Class::member, p.get()) = 42;
- 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()));
+ EXPECT_EQ(42, Invoke(&Class::member, cp));
+ EXPECT_EQ(42, Invoke(&Class::member, *cp));
+ EXPECT_EQ(42, 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, base_internal::invoke(&FlipFlop::ConstMethod, obj));
- EXPECT_EQ(42, base_internal::invoke(&FlipFlop::member, obj));
+ EXPECT_EQ(42, Invoke(&FlipFlop::ConstMethod, obj));
+ EXPECT_EQ(42, Invoke(&FlipFlop::member, obj));
}
TEST(InvokeTest, SfinaeFriendly) {
diff --git a/third_party/abseil-cpp/absl/base/log_severity.h b/third_party/abseil-cpp/absl/base/log_severity.h
index 2236422462..65a3b16672 100644
--- a/third_party/abseil-cpp/absl/base/log_severity.h
+++ b/third_party/abseil-cpp/absl/base/log_severity.h
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#ifndef ABSL_BASE_LOG_SEVERITY_H_
-#define ABSL_BASE_LOG_SEVERITY_H_
+#ifndef ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
+#define ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
#include <array>
#include <ostream>
@@ -36,7 +36,7 @@ ABSL_NAMESPACE_BEGIN
// such values to a defined severity level, however in some cases values other
// than the defined levels are useful for comparison.
//
-// Example:
+// Exmaple:
//
// // Effectively disables all logging:
// SetMinLogLevel(static_cast<absl::LogSeverity>(100));
@@ -118,4 +118,4 @@ std::ostream& operator<<(std::ostream& os, absl::LogSeverity s);
ABSL_NAMESPACE_END
} // namespace absl
-#endif // ABSL_BASE_LOG_SEVERITY_H_
+#endif // ABSL_BASE_INTERNAL_LOG_SEVERITY_H_
diff --git a/third_party/abseil-cpp/absl/base/log_severity_test.cc b/third_party/abseil-cpp/absl/base/log_severity_test.cc
index 55b26d1774..2302aa1208 100644
--- a/third_party/abseil-cpp/absl/base/log_severity_test.cc
+++ b/third_party/abseil-cpp/absl/base/log_severity_test.cc
@@ -52,9 +52,9 @@ TEST(StreamTest, Works) {
Eq("absl::LogSeverity(4)"));
}
-static_assert(absl::flags_internal::FlagUseValueAndInitBitStorage<
- absl::LogSeverity>::value,
- "Flags of type absl::LogSeverity ought to be lock-free.");
+static_assert(
+ absl::flags_internal::IsAtomicFlagTypeTrait<absl::LogSeverity>::value,
+ "Flags of type absl::LogSeverity ought to be lock-free.");
using ParseFlagFromOutOfRangeIntegerTest = TestWithParam<int64_t>;
INSTANTIATE_TEST_SUITE_P(
diff --git a/third_party/abseil-cpp/absl/base/macros.h b/third_party/abseil-cpp/absl/base/macros.h
index 3e085a916b..547f93bafb 100644
--- a/third_party/abseil-cpp/absl/base/macros.h
+++ b/third_party/abseil-cpp/absl/base/macros.h
@@ -32,7 +32,6 @@
#include <cstddef>
#include "absl/base/attributes.h"
-#include "absl/base/config.h"
#include "absl/base/optimization.h"
#include "absl/base/port.h"
@@ -55,6 +54,115 @@ auto ArraySizeHelper(const T (&array)[N]) -> char (&)[N];
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 {
+ABSL_NAMESPACE_BEGIN
+namespace base_internal {
+enum LinkerInitialized {
+ kLinkerInitialized = 0,
+};
+} // namespace base_internal
+ABSL_NAMESPACE_END
+} // 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:
+// 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__) && __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
@@ -99,41 +207,6 @@ ABSL_NAMESPACE_END
: [] { 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 (...)
@@ -144,15 +217,4 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_RETHROW do {} while (false)
#endif // ABSL_HAVE_EXCEPTIONS
-// `ABSL_INTERNAL_UNREACHABLE` is an unreachable statement. A program which
-// reaches one has undefined behavior, and the compiler may optimize
-// accordingly.
-#if defined(__GNUC__) || ABSL_HAVE_BUILTIN(__builtin_unreachable)
-#define ABSL_INTERNAL_UNREACHABLE __builtin_unreachable()
-#elif defined(_MSC_VER)
-#define ABSL_INTERNAL_UNREACHABLE __assume(0)
-#else
-#define ABSL_INTERNAL_UNREACHABLE
-#endif
-
#endif // ABSL_BASE_MACROS_H_
diff --git a/third_party/abseil-cpp/absl/base/optimization.h b/third_party/abseil-cpp/absl/base/optimization.h
index d090be1286..646523b346 100644
--- a/third_party/abseil-cpp/absl/base/optimization.h
+++ b/third_party/abseil-cpp/absl/base/optimization.h
@@ -22,15 +22,13 @@
#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. 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. 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.
//
// Example:
//
@@ -106,10 +104,9 @@
// Cacheline aligning objects properly allows constructive memory sharing and
// prevents destructive (or "false") memory sharing.
//
-// NOTE: callers should replace uses of this macro with `alignas()` using
+// NOTE: this macro should be replaced with usage of `alignas()` using
// `std::hardware_constructive_interference_size` and/or
-// `std::hardware_destructive_interference_size` when C++17 becomes available to
-// them.
+// `std::hardware_destructive_interference_size` when available within C++17.
//
// See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0154r1.html
// for more information.
@@ -174,71 +171,11 @@
// to yield performance improvements.
#if ABSL_HAVE_BUILTIN(__builtin_expect) || \
(defined(__GNUC__) && !defined(__clang__))
-#define ABSL_PREDICT_FALSE(x) (__builtin_expect(false || (x), false))
+#define ABSL_PREDICT_FALSE(x) (__builtin_expect(x, 0))
#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/third_party/abseil-cpp/absl/base/optimization_test.cc b/third_party/abseil-cpp/absl/base/optimization_test.cc
deleted file mode 100644
index e83369f322..0000000000
--- a/third_party/abseil-cpp/absl/base/optimization_test.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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/third_party/abseil-cpp/absl/base/options.h b/third_party/abseil-cpp/absl/base/options.h
index 56b4e36ee0..50f26e24b4 100644
--- a/third_party/abseil-cpp/absl/base/options.h
+++ b/third_party/abseil-cpp/absl/base/options.h
@@ -1,3 +1,6 @@
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -64,9 +67,6 @@
// 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
@@ -206,33 +206,6 @@
// allowed.
#define ABSL_OPTION_USE_INLINE_NAMESPACE 1
-#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_20211102
-
-// 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
+#define ABSL_OPTION_INLINE_NAMESPACE_NAME lts_2020_02_25
#endif // ABSL_BASE_OPTIONS_H_
diff --git a/third_party/abseil-cpp/absl/base/policy_checks.h b/third_party/abseil-cpp/absl/base/policy_checks.h
index 06b3243916..4dfa49e54a 100644
--- a/third_party/abseil-cpp/absl/base/policy_checks.h
+++ b/third_party/abseil-cpp/absl/base/policy_checks.h
@@ -41,7 +41,7 @@
#endif
// -----------------------------------------------------------------------------
-// Toolchain Check
+// Compiler Check
// -----------------------------------------------------------------------------
// We support MSVC++ 14.0 update 2 and later.
diff --git a/third_party/abseil-cpp/absl/base/port.h b/third_party/abseil-cpp/absl/base/port.h
index 5bc4d6cd95..6c28068d4f 100644
--- a/third_party/abseil-cpp/absl/base/port.h
+++ b/third_party/abseil-cpp/absl/base/port.h
@@ -14,6 +14,7 @@
//
// 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/third_party/abseil-cpp/absl/base/spinlock_test_common.cc b/third_party/abseil-cpp/absl/base/spinlock_test_common.cc
index 2b572c5b3f..08f61ba86a 100644
--- a/third_party/abseil-cpp/absl/base/spinlock_test_common.cc
+++ b/third_party/abseil-cpp/absl/base/spinlock_test_common.cc
@@ -20,12 +20,10 @@
#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"
@@ -58,10 +56,12 @@ namespace {
static constexpr int kArrayLength = 10;
static uint32_t values[kArrayLength];
-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);
+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);
// Simple integer hash function based on the public domain lookup2 hash.
// http://burtleburtle.net/bob/c/lookup2.c
@@ -92,7 +92,6 @@ 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));
}
@@ -106,10 +105,6 @@ 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();
@@ -196,6 +191,10 @@ TEST(SpinLock, WaitCyclesEncoding) {
EXPECT_GT(expected_max_value_decoded, before_max_value_decoded);
}
+TEST(SpinLockWithThreads, StaticSpinLock) {
+ ThreadedTest(&static_spinlock);
+}
+
TEST(SpinLockWithThreads, StackSpinLock) {
SpinLock spinlock;
ThreadedTest(&spinlock);
diff --git a/third_party/abseil-cpp/absl/base/thread_annotations.h b/third_party/abseil-cpp/absl/base/thread_annotations.h
index 9695f6de67..5f51c0c2d2 100644
--- a/third_party/abseil-cpp/absl/base/thread_annotations.h
+++ b/third_party/abseil-cpp/absl/base/thread_annotations.h
@@ -34,11 +34,16 @@
#ifndef ABSL_BASE_THREAD_ANNOTATIONS_H_
#define ABSL_BASE_THREAD_ANNOTATIONS_H_
-#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
+#if defined(__clang__)
+#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
+#else
+#define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) // no-op
+#endif
+
// ABSL_GUARDED_BY()
//
// Documents if a shared field or global variable needs to be protected by a
@@ -56,11 +61,8 @@
// int p1_ ABSL_GUARDED_BY(mu_);
// ...
// };
-#if ABSL_HAVE_ATTRIBUTE(guarded_by)
-#define ABSL_GUARDED_BY(x) __attribute__((guarded_by(x)))
-#else
-#define ABSL_GUARDED_BY(x)
-#endif
+#define ABSL_GUARDED_BY(x) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(guarded_by(x))
// ABSL_PT_GUARDED_BY()
//
@@ -82,11 +84,8 @@
// // `q_`, guarded by `mu1_`, points to a shared memory location that is
// // guarded by `mu2_`:
// 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
+#define ABSL_PT_GUARDED_BY(x) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(pt_guarded_by(x))
// ABSL_ACQUIRED_AFTER() / ABSL_ACQUIRED_BEFORE()
//
@@ -103,17 +102,11 @@
//
// Mutex m1_;
// 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 ABSL_ACQUIRED_AFTER(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_after(__VA_ARGS__))
-#if ABSL_HAVE_ATTRIBUTE(acquired_before)
-#define ABSL_ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__)))
-#else
-#define ABSL_ACQUIRED_BEFORE(...)
-#endif
+#define ABSL_ACQUIRED_BEFORE(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(acquired_before(__VA_ARGS__))
// ABSL_EXCLUSIVE_LOCKS_REQUIRED() / ABSL_SHARED_LOCKS_REQUIRED()
//
@@ -138,50 +131,33 @@
//
// 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 ABSL_EXCLUSIVE_LOCKS_REQUIRED(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
+ exclusive_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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_locks_required(__VA_ARGS__))
// 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).
-#if ABSL_HAVE_ATTRIBUTE(locks_excluded)
-#define ABSL_LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__)))
-#else
-#define ABSL_LOCKS_EXCLUDED(...)
-#endif
+#define ABSL_LOCKS_EXCLUDED(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(locks_excluded(__VA_ARGS__))
// 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 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
+#define ABSL_LOCK_RETURNED(x) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lock_returned(x))
// ABSL_LOCKABLE
//
// Documents if a class/type is a lockable type (such as the `Mutex` class).
-#if ABSL_HAVE_ATTRIBUTE(lockable)
-#define ABSL_LOCKABLE __attribute__((lockable))
-#else
-#define ABSL_LOCKABLE
-#endif
+#define ABSL_LOCKABLE ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(lockable)
// ABSL_SCOPED_LOCKABLE
//
@@ -190,43 +166,30 @@
// acquired, and the destructor should use `UNLOCK_FUNCTION()` with no
// arguments; the analysis will assume that the destructor unlocks whatever the
// constructor locked.
-#if ABSL_HAVE_ATTRIBUTE(scoped_lockable)
-#define ABSL_SCOPED_LOCKABLE __attribute__((scoped_lockable))
-#else
-#define ABSL_SCOPED_LOCKABLE
-#endif
+#define ABSL_SCOPED_LOCKABLE \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(scoped_lockable)
// ABSL_EXCLUSIVE_LOCK_FUNCTION()
//
// Documents functions that acquire a lock in the body of a function, and do
// not release it.
-#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
+#define ABSL_EXCLUSIVE_LOCK_FUNCTION(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
+ exclusive_lock_function(__VA_ARGS__))
// ABSL_SHARED_LOCK_FUNCTION()
//
// Documents functions that acquire a shared (reader) lock in the body of a
// function, and do not release it.
-#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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(shared_lock_function(__VA_ARGS__))
// 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.
-#if ABSL_HAVE_ATTRIBUTE(unlock_function)
-#define ABSL_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__)))
-#else
-#define ABSL_UNLOCK_FUNCTION(...)
-#endif
+#define ABSL_UNLOCK_FUNCTION(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(unlock_function(__VA_ARGS__))
// ABSL_EXCLUSIVE_TRYLOCK_FUNCTION() / ABSL_SHARED_TRYLOCK_FUNCTION()
//
@@ -236,49 +199,31 @@
// 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`.
-#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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
+ exclusive_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
+#define ABSL_SHARED_TRYLOCK_FUNCTION(...) \
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE( \
+ shared_trylock_function(__VA_ARGS__))
// 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.
-#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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_exclusive_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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(assert_shared_lock(__VA_ARGS__))
// 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.
-#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
+ ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(no_thread_safety_analysis)
//------------------------------------------------------------------------------
// Tool-Supplied Annotations
@@ -317,7 +262,7 @@ 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.
+// Do not used this function directly, use ABSL_TS_UNCHECKED_READ instead.
template <typename T>
inline const T& ts_unchecked_read(const T& v) ABSL_NO_THREAD_SAFETY_ANALYSIS {
return v;
diff --git a/third_party/abseil-cpp/absl/cleanup/BUILD.bazel b/third_party/abseil-cpp/absl/cleanup/BUILD.bazel
deleted file mode 100644
index 2154d9f1a3..0000000000
--- a/third_party/abseil-cpp/absl/cleanup/BUILD.bazel
+++ /dev/null
@@ -1,65 +0,0 @@
-# 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(
- "//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/third_party/abseil-cpp/absl/cleanup/CMakeLists.txt b/third_party/abseil-cpp/absl/cleanup/CMakeLists.txt
deleted file mode 100644
index 26a6d0dce3..0000000000
--- a/third_party/abseil-cpp/absl/cleanup/CMakeLists.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.
-
-absl_cc_library(
- NAME
- cleanup_internal
- HDRS
- "internal/cleanup.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base_internal
- absl::core_headers
- absl::utility
- PUBLIC
-)
-
-absl_cc_library(
- NAME
- cleanup
- HDRS
- "cleanup.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::cleanup_internal
- absl::config
- absl::core_headers
- PUBLIC
-)
-
-absl_cc_test(
- NAME
- cleanup_test
- SRCS
- "cleanup_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::cleanup
- absl::config
- absl::utility
- GTest::gmock_main
-)
diff --git a/third_party/abseil-cpp/absl/cleanup/cleanup.h b/third_party/abseil-cpp/absl/cleanup/cleanup.h
deleted file mode 100644
index 960ccd080e..0000000000
--- a/third_party/abseil-cpp/absl/cleanup/cleanup.h
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2021 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-// -----------------------------------------------------------------------------
-// File: cleanup.h
-// -----------------------------------------------------------------------------
-//
-// `absl::Cleanup` implements the scope guard idiom, invoking the contained
-// callback's `operator()() &&` on scope exit.
-//
-// Example:
-//
-// ```
-// absl::Status CopyGoodData(const char* source_path, const char* sink_path) {
-// FILE* source_file = fopen(source_path, "r");
-// if (source_file == nullptr) {
-// return absl::NotFoundError("No source file"); // No cleanups execute
-// }
-//
-// // C++17 style cleanup using class template argument deduction
-// absl::Cleanup source_closer = [source_file] { fclose(source_file); };
-//
-// FILE* sink_file = fopen(sink_path, "w");
-// if (sink_file == nullptr) {
-// return absl::NotFoundError("No sink file"); // First cleanup executes
-// }
-//
-// // C++11 style cleanup using the factory function
-// auto sink_closer = absl::MakeCleanup([sink_file] { fclose(sink_file); });
-//
-// Data data;
-// while (ReadData(source_file, &data)) {
-// if (!data.IsGood()) {
-// absl::Status result = absl::FailedPreconditionError("Read bad data");
-// return result; // Both cleanups execute
-// }
-// SaveData(sink_file, &data);
-// }
-//
-// return absl::OkStatus(); // Both cleanups execute
-// }
-// ```
-//
-// Methods:
-//
-// `std::move(cleanup).Cancel()` will prevent the callback from executing.
-//
-// `std::move(cleanup).Invoke()` will execute the callback early, before
-// destruction, and prevent the callback from executing in the destructor.
-//
-// Usage:
-//
-// `absl::Cleanup` is not an interface type. It is only intended to be used
-// within the body of a function. It is not a value type and instead models a
-// control flow construct. Check out `defer` in Golang for something similar.
-
-#ifndef ABSL_CLEANUP_CLEANUP_H_
-#define ABSL_CLEANUP_CLEANUP_H_
-
-#include <utility>
-
-#include "absl/base/config.h"
-#include "absl/base/macros.h"
-#include "absl/cleanup/internal/cleanup.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-template <typename Arg, typename Callback = void()>
-class ABSL_MUST_USE_RESULT Cleanup final {
- static_assert(cleanup_internal::WasDeduced<Arg>(),
- "Explicit template parameters are not supported.");
-
- static_assert(cleanup_internal::ReturnsVoid<Callback>(),
- "Callbacks that return values are not supported.");
-
- public:
- Cleanup(Callback callback) : storage_(std::move(callback)) {} // NOLINT
-
- Cleanup(Cleanup&& other) = default;
-
- void Cancel() && {
- ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
- storage_.DestroyCallback();
- }
-
- void Invoke() && {
- ABSL_HARDENING_ASSERT(storage_.IsCallbackEngaged());
- storage_.InvokeCallback();
- storage_.DestroyCallback();
- }
-
- ~Cleanup() {
- if (storage_.IsCallbackEngaged()) {
- storage_.InvokeCallback();
- storage_.DestroyCallback();
- }
- }
-
- private:
- cleanup_internal::Storage<Callback> storage_;
-};
-
-// `absl::Cleanup c = /* callback */;`
-//
-// C++17 type deduction API for creating an instance of `absl::Cleanup`
-#if defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
-template <typename Callback>
-Cleanup(Callback callback) -> Cleanup<cleanup_internal::Tag, Callback>;
-#endif // defined(ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION)
-
-// `auto c = absl::MakeCleanup(/* callback */);`
-//
-// C++11 type deduction API for creating an instance of `absl::Cleanup`
-template <typename... Args, typename Callback>
-absl::Cleanup<cleanup_internal::Tag, Callback> MakeCleanup(Callback callback) {
- static_assert(cleanup_internal::WasDeduced<cleanup_internal::Tag, Args...>(),
- "Explicit template parameters are not supported.");
-
- static_assert(cleanup_internal::ReturnsVoid<Callback>(),
- "Callbacks that return values are not supported.");
-
- return {std::move(callback)};
-}
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_CLEANUP_CLEANUP_H_
diff --git a/third_party/abseil-cpp/absl/cleanup/cleanup_test.cc b/third_party/abseil-cpp/absl/cleanup/cleanup_test.cc
deleted file mode 100644
index 46b885899c..0000000000
--- a/third_party/abseil-cpp/absl/cleanup/cleanup_test.cc
+++ /dev/null
@@ -1,311 +0,0 @@
-// 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
-}
-
-int DestructionCount = 0;
-
-struct DestructionCounter {
- void operator()() {}
-
- ~DestructionCounter() { ++DestructionCount; }
-};
-
-TYPED_TEST(CleanupTest, DestructorDestroys) {
- {
- auto cleanup =
- absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
- DestructionCount = 0;
- }
-
- EXPECT_EQ(DestructionCount, 1); // Engaged cleanup destroys
-}
-
-TYPED_TEST(CleanupTest, CancelDestroys) {
- {
- auto cleanup =
- absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
- DestructionCount = 0;
-
- std::move(cleanup).Cancel();
- EXPECT_EQ(DestructionCount, 1); // Cancel destroys
- }
-
- EXPECT_EQ(DestructionCount, 1); // Canceled cleanup does not double destroy
-}
-
-TYPED_TEST(CleanupTest, InvokeDestroys) {
- {
- auto cleanup =
- absl::MakeCleanup(TypeParam::AsCallback(DestructionCounter()));
- DestructionCount = 0;
-
- std::move(cleanup).Invoke();
- EXPECT_EQ(DestructionCount, 1); // Invoke destroys
- }
-
- EXPECT_EQ(DestructionCount, 1); // Invoked cleanup does not double destroy
-}
-
-} // namespace
diff --git a/third_party/abseil-cpp/absl/cleanup/internal/cleanup.h b/third_party/abseil-cpp/absl/cleanup/internal/cleanup.h
deleted file mode 100644
index 2783fcb7c1..0000000000
--- a/third_party/abseil-cpp/absl/cleanup/internal/cleanup.h
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright 2021 The Abseil Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_CLEANUP_INTERNAL_CLEANUP_H_
-#define ABSL_CLEANUP_INTERNAL_CLEANUP_H_
-
-#include <new>
-#include <type_traits>
-#include <utility>
-
-#include "absl/base/internal/invoke.h"
-#include "absl/base/macros.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/utility/utility.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-namespace cleanup_internal {
-
-struct Tag {};
-
-template <typename Arg, typename... Args>
-constexpr bool WasDeduced() {
- return (std::is_same<cleanup_internal::Tag, Arg>::value) &&
- (sizeof...(Args) == 0);
-}
-
-template <typename Callback>
-constexpr bool ReturnsVoid() {
- return (std::is_same<base_internal::invoke_result_t<Callback>, void>::value);
-}
-
-template <typename Callback>
-class Storage {
- public:
- Storage() = delete;
-
- explicit Storage(Callback callback) {
- // Placement-new into a character buffer is used for eager destruction when
- // the cleanup is invoked or cancelled. To ensure this optimizes well, the
- // behavior is implemented locally instead of using an absl::optional.
- ::new (GetCallbackBuffer()) Callback(std::move(callback));
- is_callback_engaged_ = true;
- }
-
- Storage(Storage&& other) {
- ABSL_HARDENING_ASSERT(other.IsCallbackEngaged());
-
- ::new (GetCallbackBuffer()) Callback(std::move(other.GetCallback()));
- is_callback_engaged_ = true;
-
- other.DestroyCallback();
- }
-
- Storage(const Storage& other) = delete;
-
- Storage& operator=(Storage&& other) = delete;
-
- Storage& operator=(const Storage& other) = delete;
-
- void* GetCallbackBuffer() { return static_cast<void*>(+callback_buffer_); }
-
- Callback& GetCallback() {
- return *reinterpret_cast<Callback*>(GetCallbackBuffer());
- }
-
- bool IsCallbackEngaged() const { return is_callback_engaged_; }
-
- void DestroyCallback() {
- is_callback_engaged_ = false;
- GetCallback().~Callback();
- }
-
- void InvokeCallback() ABSL_NO_THREAD_SAFETY_ANALYSIS {
- std::move(GetCallback())();
- }
-
- private:
- bool is_callback_engaged_;
- alignas(Callback) char callback_buffer_[sizeof(Callback)];
-};
-
-} // namespace cleanup_internal
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_CLEANUP_INTERNAL_CLEANUP_H_
diff --git a/third_party/abseil-cpp/absl/compiler_config_setting.bzl b/third_party/abseil-cpp/absl/compiler_config_setting.bzl
new file mode 100644
index 0000000000..66962294d0
--- /dev/null
+++ b/third_party/abseil-cpp/absl/compiler_config_setting.bzl
@@ -0,0 +1,38 @@
+#
+# 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.
+
+"""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/third_party/abseil-cpp/absl/container/BUILD.bazel b/third_party/abseil-cpp/absl/container/BUILD.bazel
index ffaee19cdb..f221714027 100644
--- a/third_party/abseil-cpp/absl/container/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/container/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "compressed_tuple",
@@ -59,7 +60,6 @@ cc_library(
deps = [
":compressed_tuple",
"//absl/algorithm",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
"//absl/base:throw_delegate",
@@ -73,9 +73,7 @@ cc_test(
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",
@@ -155,7 +153,6 @@ cc_test(
":counting_allocator",
":inlined_vector",
":test_instance_tracker",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:exception_testing",
"//absl/base:raw_logging_internal",
@@ -258,7 +255,6 @@ cc_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",
],
@@ -292,7 +288,6 @@ cc_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",
@@ -368,9 +363,7 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base:config",
"//absl/memory",
- "//absl/meta:type_traits",
"//absl/utility",
],
)
@@ -383,7 +376,6 @@ cc_test(
tags = NOTEST_TAGS_NONMOBILE,
deps = [
":container_memory",
- ":test_instance_tracker",
"//absl/strings",
"@com_google_googletest//:gtest_main",
],
@@ -398,7 +390,6 @@ cc_library(
"//absl/base:config",
"//absl/hash",
"//absl/strings",
- "//absl/strings:cord",
],
)
@@ -411,10 +402,7 @@ cc_test(
deps = [
":hash_function_defaults",
"//absl/hash",
- "//absl/random",
"//absl/strings",
- "//absl/strings:cord",
- "//absl/strings:cord_test_helpers",
"@com_google_googletest//:gtest_main",
],
)
@@ -509,10 +497,9 @@ cc_library(
":have_sse",
"//absl/base",
"//absl/base:core_headers",
+ "//absl/base:exponential_biased",
"//absl/debugging:stacktrace",
"//absl/memory",
- "//absl/profiling:exponential_biased",
- "//absl/profiling:sample_recorder",
"//absl/synchronization",
"//absl/utility",
],
@@ -526,7 +513,6 @@ cc_test(
":hashtablez_sampler",
":have_sse",
"//absl/base:core_headers",
- "//absl/profiling:sample_recorder",
"//absl/synchronization",
"//absl/synchronization:thread_pool",
"//absl/time",
@@ -599,12 +585,13 @@ cc_library(
":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/numeric:bits",
"//absl/utility",
],
)
@@ -622,7 +609,6 @@ cc_test(
":hashtable_debug",
":raw_hash_set",
"//absl/base",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/strings",
@@ -630,45 +616,6 @@ cc_test(
],
)
-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",
@@ -689,7 +636,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
"//absl/strings",
@@ -708,7 +654,6 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":layout",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/types:span",
@@ -716,22 +661,6 @@ cc_test(
],
)
-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,
@@ -876,22 +805,6 @@ cc_test(
],
)
-cc_test(
- name = "sample_element_size_test",
- srcs = ["sample_element_size_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = NOTEST_TAGS_NONMOBILE,
- visibility = ["//visibility:private"],
- deps = [
- ":flat_hash_map",
- ":flat_hash_set",
- ":node_hash_map",
- ":node_hash_set",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
cc_library(
name = "btree",
srcs = [
@@ -915,7 +828,6 @@ cc_library(
"//absl/memory",
"//absl/meta:type_traits",
"//absl/strings",
- "//absl/strings:cord",
"//absl/types:compare",
"//absl/utility",
],
@@ -932,7 +844,6 @@ cc_library(
":btree",
":flat_hash_set",
"//absl/strings",
- "//absl/strings:cord",
"//absl/time",
],
)
@@ -984,7 +895,6 @@ cc_binary(
"//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/third_party/abseil-cpp/absl/container/CMakeLists.txt b/third_party/abseil-cpp/absl/container/CMakeLists.txt
index 78584d2cef..e702ba8576 100644
--- a/third_party/abseil-cpp/absl/container/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/container/CMakeLists.txt
@@ -14,6 +14,15 @@
# limitations under the License.
#
+# This is deprecated and will be removed in the future. It also doesn't do
+# anything anyways. Prefer to use the library associated with the API you are
+# using.
+absl_cc_library(
+ NAME
+ container
+ PUBLIC
+)
+
absl_cc_library(
NAME
btree
@@ -31,7 +40,6 @@ absl_cc_library(
absl::compare
absl::compressed_tuple
absl::container_memory
- absl::cord
absl::core_headers
absl::layout
absl::memory
@@ -52,7 +60,6 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::btree
- absl::cord
absl::flat_hash_set
absl::strings
absl::time
@@ -80,7 +87,7 @@ absl_cc_test(
absl::strings
absl::test_instance_tracker
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -109,7 +116,7 @@ absl_cc_test(
absl::optional
absl::test_instance_tracker
absl::utility
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -122,7 +129,6 @@ absl_cc_library(
DEPS
absl::compressed_tuple
absl::algorithm
- absl::config
absl::core_headers
absl::dynamic_annotations
absl::throw_delegate
@@ -139,12 +145,10 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::fixed_array
- absl::counting_allocator
- absl::config
absl::exception_testing
absl::hash_testing
absl::memory
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -158,7 +162,7 @@ absl_cc_test(
absl::fixed_array
absl::config
absl::exception_safety_testing
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -215,14 +219,13 @@ absl_cc_test(
absl::counting_allocator
absl::inlined_vector
absl::test_instance_tracker
- absl::config
absl::core_headers
absl::exception_testing
absl::hash_testing
absl::memory
absl::raw_logging_internal
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -236,7 +239,7 @@ absl_cc_test(
absl::inlined_vector
absl::config
absl::exception_safety_testing
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -262,7 +265,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::test_instance_tracker
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -296,8 +299,7 @@ absl_cc_test(
absl::unordered_map_members_test
absl::unordered_map_modifiers_test
absl::any
- absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -333,9 +335,8 @@ absl_cc_test(
absl::unordered_set_members_test
absl::unordered_set_modifiers_test
absl::memory
- absl::raw_logging_internal
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -370,7 +371,7 @@ absl_cc_test(
absl::unordered_map_lookup_test
absl::unordered_map_members_test
absl::unordered_map_modifiers_test
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -404,7 +405,7 @@ absl_cc_test(
absl::unordered_set_lookup_test
absl::unordered_set_members_test
absl::unordered_set_modifiers_test
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -415,9 +416,7 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::config
absl::memory
- absl::type_traits
absl::utility
PUBLIC
)
@@ -432,8 +431,7 @@ absl_cc_test(
DEPS
absl::container_memory
absl::strings
- absl::test_instance_tracker
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -445,7 +443,6 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::config
- absl::cord
absl::hash
absl::strings
PUBLIC
@@ -459,13 +456,10 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::cord
- absl::cord_test_helpers
absl::hash_function_defaults
absl::hash
- absl::random_random
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -507,7 +501,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::hash_policy_testing
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -531,7 +525,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::hash_policy_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -548,7 +542,6 @@ absl_cc_library(
absl::base
absl::exponential_biased
absl::have_sse
- absl::sample_recorder
absl::synchronization
)
@@ -562,7 +555,7 @@ absl_cc_test(
DEPS
absl::hashtablez_sampler
absl::have_sse
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -619,7 +612,7 @@ absl_cc_test(
DEPS
absl::hash_policy_traits
absl::node_hash_policy
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -667,6 +660,7 @@ absl_cc_library(
absl::hash_policy_traits
absl::hashtable_debug_hooks
absl::have_sse
+ absl::layout
absl::memory
absl::meta
absl::optional
@@ -689,11 +683,10 @@ absl_cc_test(
absl::hashtable_debug
absl::raw_hash_set
absl::base
- absl::config
absl::core_headers
absl::raw_logging_internal
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -707,7 +700,7 @@ absl_cc_test(
absl::raw_hash_set
absl::tracked
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -718,7 +711,6 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::config
absl::core_headers
absl::meta
absl::strings
@@ -736,11 +728,10 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::layout
- absl::config
absl::core_headers
absl::raw_logging_internal
absl::span
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -765,7 +756,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -779,7 +770,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -792,7 +783,7 @@ absl_cc_library(
${ABSL_TEST_COPTS}
DEPS
absl::type_traits
- GTest::gmock
+ gmock
TESTONLY
)
@@ -806,7 +797,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -820,7 +811,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -834,7 +825,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -847,7 +838,7 @@ absl_cc_library(
${ABSL_TEST_COPTS}
DEPS
absl::type_traits
- GTest::gmock
+ gmock
TESTONLY
)
@@ -861,7 +852,7 @@ absl_cc_library(
DEPS
absl::hash_generator_testing
absl::hash_policy_testing
- GTest::gmock
+ gmock
TESTONLY
)
@@ -877,7 +868,7 @@ absl_cc_test(
absl::unordered_set_lookup_test
absl::unordered_set_members_test
absl::unordered_set_modifiers_test
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -892,20 +883,5 @@ absl_cc_test(
absl::unordered_map_lookup_test
absl::unordered_map_members_test
absl::unordered_map_modifiers_test
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- sample_element_size_test
- SRCS
- "sample_element_size_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::flat_hash_map
- absl::flat_hash_set
- absl::node_hash_map
- absl::node_hash_set
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/container/btree_benchmark.cc b/third_party/abseil-cpp/absl/container/btree_benchmark.cc
index 65b6790b71..4af92f9fd8 100644
--- a/third_party/abseil-cpp/absl/container/btree_benchmark.cc
+++ b/third_party/abseil-cpp/absl/container/btree_benchmark.cc
@@ -26,7 +26,6 @@
#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"
@@ -37,9 +36,9 @@
#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"
+#include "benchmark/benchmark.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -101,24 +100,36 @@ 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.
+// container::insert sometimes returns a pair<iterator, bool> and sometimes
+// returns an iterator (for multi- containers).
+template <typename Iter>
+Iter GetIterFromInsert(const std::pair<Iter, bool>& pair) {
+ return pair.first;
+}
+template <typename Iter>
+Iter GetIterFromInsert(const Iter iter) {
+ return iter;
+}
+
+// Benchmark insertion of values into a container at the end.
template <typename T>
-void BM_InsertSmall(benchmark::State& state) {
+void BM_InsertEnd(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;
- const int kSize = 8;
- std::vector<V> values = GenerateValues<V>(kSize);
T container;
+ const int kSize = 10000;
+ for (int i = 0; i < kSize; ++i) {
+ container.insert(Generator<V>(kSize)(i));
+ }
+ V v = Generator<V>(kSize)(kSize - 1);
+ typename T::key_type k = key_of_value(v);
- 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();
+ auto it = container.find(k);
+ while (state.KeepRunning()) {
+ // Repeatedly removing then adding v.
+ container.erase(it);
+ it = GetIterFromInsert(container.insert(v));
}
}
@@ -427,7 +438,6 @@ 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) \
@@ -448,8 +458,6 @@ STL_ORDERED_TYPES(Time);
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);
@@ -470,7 +478,6 @@ STL_UNORDERED_TYPES_CUSTOM_HASH(Time, absl::Hash<absl::Time>);
BTREE_TYPES(int32_t);
BTREE_TYPES(int64_t);
BTREE_TYPES(StdString);
-BTREE_TYPES(Cord);
BTREE_TYPES(Time);
#define MY_BENCHMARK4(type, func) \
@@ -480,7 +487,7 @@ BTREE_TYPES(Time);
#define MY_BENCHMARK3(type) \
MY_BENCHMARK4(type, Insert); \
MY_BENCHMARK4(type, InsertSorted); \
- MY_BENCHMARK4(type, InsertSmall); \
+ MY_BENCHMARK4(type, InsertEnd); \
MY_BENCHMARK4(type, Lookup); \
MY_BENCHMARK4(type, FullLookup); \
MY_BENCHMARK4(type, Delete); \
@@ -519,7 +526,6 @@ BTREE_TYPES(Time);
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.
@@ -532,19 +538,19 @@ 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];
+ void Copy(const BigType& x) {
+ for (int i = 0; i < Size && i < Copies; ++i) values[i] = x.values[i];
// If Copies > Size, do extra copies.
for (int i = Size, idx = 0; i < Copies; ++i) {
- int64_t tmp = other.values[idx];
+ int64_t tmp = x.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);
+ BigType(const BigType& x) { Copy(x); }
+ BigType& operator=(const BigType& x) {
+ Copy(x);
return *this;
}
@@ -635,14 +641,14 @@ struct BigTypePtr {
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(const BigTypePtr& x) {
+ ptr = absl::make_unique<BigType<Size, Size>>(*x.ptr);
}
- BigTypePtr(BigTypePtr&& other) noexcept = default;
- BigTypePtr& operator=(const BigTypePtr& other) {
- ptr = absl::make_unique<BigType<Size, Size>>(*other.ptr);
+ BigTypePtr(BigTypePtr&& x) noexcept = default;
+ BigTypePtr& operator=(const BigTypePtr& x) {
+ ptr = absl::make_unique<BigType<Size, Size>>(*x.ptr);
}
- BigTypePtr& operator=(BigTypePtr&& other) noexcept = default;
+ BigTypePtr& operator=(BigTypePtr&& x) noexcept = default;
bool operator<(const BigTypePtr& other) const { return *ptr < *other.ptr; }
bool operator==(const BigTypePtr& other) const { return *ptr == *other.ptr; }
diff --git a/third_party/abseil-cpp/absl/container/btree_map.h b/third_party/abseil-cpp/absl/container/btree_map.h
index f0a8d4a6a4..d23f4ee5e6 100644
--- a/third_party/abseil-cpp/absl/container/btree_map.h
+++ b/third_party/abseil-cpp/absl/container/btree_map.h
@@ -185,7 +185,7 @@ class btree_map
// 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).
+ // number of elements erased.
using Base::erase;
// btree_map::insert()
@@ -318,18 +318,13 @@ class btree_map
// 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):
+ // template <typename K> node_type extract(const K& x):
//
// 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).
@@ -366,8 +361,8 @@ class btree_map
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_map`, returning `true` if so or `false` otherwise.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the map is provided a
+ // compatible heterogeneous comparator.
using Base::contains;
// btree_map::count()
@@ -378,14 +373,15 @@ class btree_map
// the `btree_map`. Note that this function will return either `1` or `0`
// since duplicate elements are not allowed within a `btree_map`.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // 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`.
+ // Returns a closed 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()
@@ -395,34 +391,10 @@ class btree_map
//
// Finds an element with the passed `key` within the `btree_map`.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the map is provided a
+ // compatible heterogeneous comparator.
using Base::find;
- // btree_map::lower_bound()
- //
- // template <typename K> iterator lower_bound(const K& key):
- // template <typename K> const_iterator lower_bound(const K& key) const:
- //
- // Finds the first element with a key that is not less than `key` within the
- // `btree_map`.
- //
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
- using Base::lower_bound;
-
- // btree_map::upper_bound()
- //
- // template <typename K> iterator upper_bound(const K& key):
- // template <typename K> const_iterator upper_bound(const K& key) const:
- //
- // Finds the first element with a key that is greater than `key` within the
- // `btree_map`.
- //
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
- using Base::upper_bound;
-
// btree_map::operator[]()
//
// Returns a reference to the value mapped to the passed key within the
@@ -673,18 +645,13 @@ class btree_multimap
// 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):
+ // template <typename K> node_type extract(const K& x):
//
// 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).
@@ -693,8 +660,9 @@ class btree_multimap
// btree_multimap::merge()
//
- // Extracts all elements from a given `source` btree_multimap into this
- // `btree_multimap`.
+ // 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)
@@ -714,8 +682,8 @@ class btree_multimap
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_multimap`, returning `true` if so or `false` otherwise.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the map is provided a
+ // compatible heterogeneous comparator.
using Base::contains;
// btree_multimap::count()
@@ -725,13 +693,13 @@ class btree_multimap
// Returns the number of elements comparing equal to the given `key` within
// the `btree_multimap`.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // 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
+ // Returns a closed 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;
@@ -743,34 +711,10 @@ class btree_multimap
//
// Finds an element with the passed `key` within the `btree_multimap`.
//
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the map is provided a
+ // compatible heterogeneous comparator.
using Base::find;
- // btree_multimap::lower_bound()
- //
- // template <typename K> iterator lower_bound(const K& key):
- // template <typename K> const_iterator lower_bound(const K& key) const:
- //
- // Finds the first element with a key that is not less than `key` within the
- // `btree_multimap`.
- //
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
- using Base::lower_bound;
-
- // btree_multimap::upper_bound()
- //
- // template <typename K> iterator upper_bound(const K& key):
- // template <typename K> const_iterator upper_bound(const K& key) const:
- //
- // Finds the first element with a key that is greater than `key` within the
- // `btree_multimap`.
- //
- // Supports heterogeneous lookup, provided that the map has a compatible
- // heterogeneous comparator.
- using Base::upper_bound;
-
// btree_multimap::get_allocator()
//
// Returns the allocator function associated with this `btree_multimap`.
diff --git a/third_party/abseil-cpp/absl/container/btree_set.h b/third_party/abseil-cpp/absl/container/btree_set.h
index 8973900693..127fb940d4 100644
--- a/third_party/abseil-cpp/absl/container/btree_set.h
+++ b/third_party/abseil-cpp/absl/container/btree_set.h
@@ -183,7 +183,7 @@ class btree_set
// 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).
+ // number of elements erased.
using Base::erase;
// btree_set::insert()
@@ -263,7 +263,7 @@ class btree_set
// 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):
+ // template <typename K> node_type extract(const K& x):
//
// Extracts the element with the key matching the passed key value and
// returns a node handle owning that extracted data. If the `btree_set`
@@ -300,8 +300,8 @@ class btree_set
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_set`, returning `true` if so or `false` otherwise.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::contains;
// btree_set::count()
@@ -312,8 +312,8 @@ class btree_set
// the `btree_set`. Note that this function will return either `1` or `0`
// since duplicate elements are not allowed within a `btree_set`.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::count;
// btree_set::equal_range()
@@ -330,32 +330,10 @@ class btree_set
//
// Finds an element with the passed `key` within the `btree_set`.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::find;
- // btree_set::lower_bound()
- //
- // template <typename K> iterator lower_bound(const K& key):
- // template <typename K> const_iterator lower_bound(const K& key) const:
- //
- // Finds the first element that is not less than `key` within the `btree_set`.
- //
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
- using Base::lower_bound;
-
- // btree_set::upper_bound()
- //
- // template <typename K> iterator upper_bound(const K& key):
- // template <typename K> const_iterator upper_bound(const K& key) const:
- //
- // Finds the first element that is greater than `key` within the `btree_set`.
- //
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
- using Base::upper_bound;
-
// btree_set::get_allocator()
//
// Returns the allocator function associated with this `btree_set`.
@@ -589,7 +567,7 @@ class btree_multiset
// 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):
+ // template <typename K> node_type extract(const K& x):
//
// Extracts the element with the key matching the passed key value and
// returns a node handle owning that extracted data. If the `btree_multiset`
@@ -604,8 +582,9 @@ class btree_multiset
// btree_multiset::merge()
//
- // Extracts all elements from a given `source` btree_multiset into this
- // `btree_multiset`.
+ // 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)
@@ -625,8 +604,8 @@ class btree_multiset
// Determines whether an element comparing equal to the given `key` exists
// within the `btree_multiset`, returning `true` if so or `false` otherwise.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::contains;
// btree_multiset::count()
@@ -636,8 +615,8 @@ class btree_multiset
// Returns the number of elements comparing equal to the given `key` within
// the `btree_multiset`.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::count;
// btree_multiset::equal_range()
@@ -654,34 +633,10 @@ class btree_multiset
//
// Finds an element with the passed `key` within the `btree_multiset`.
//
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
+ // Supports heterogeneous lookup, provided that the set is provided a
+ // compatible heterogeneous comparator.
using Base::find;
- // btree_multiset::lower_bound()
- //
- // template <typename K> iterator lower_bound(const K& key):
- // template <typename K> const_iterator lower_bound(const K& key) const:
- //
- // Finds the first element that is not less than `key` within the
- // `btree_multiset`.
- //
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
- using Base::lower_bound;
-
- // btree_multiset::upper_bound()
- //
- // template <typename K> iterator upper_bound(const K& key):
- // template <typename K> const_iterator upper_bound(const K& key) const:
- //
- // Finds the first element that is greater than `key` within the
- // `btree_multiset`.
- //
- // Supports heterogeneous lookup, provided that the set has a compatible
- // heterogeneous comparator.
- using Base::upper_bound;
-
// btree_multiset::get_allocator()
//
// Returns the allocator function associated with this `btree_multiset`.
diff --git a/third_party/abseil-cpp/absl/container/btree_test.cc b/third_party/abseil-cpp/absl/container/btree_test.cc
index d27cf27105..9edf38f9d0 100644
--- a/third_party/abseil-cpp/absl/container/btree_test.cc
+++ b/third_party/abseil-cpp/absl/container/btree_test.cc
@@ -15,7 +15,6 @@
#include "absl/container/btree_test.h"
#include <cstdint>
-#include <limits>
#include <map>
#include <memory>
#include <stdexcept>
@@ -53,9 +52,7 @@ 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) {
@@ -92,8 +89,8 @@ class base_checker {
public:
base_checker() : const_tree_(tree_) {}
- base_checker(const base_checker &other)
- : tree_(other.tree_), const_tree_(tree_), checker_(other.checker_) {}
+ base_checker(const base_checker &x)
+ : tree_(x.tree_), const_tree_(tree_), checker_(x.checker_) {}
template <typename InputIterator>
base_checker(InputIterator b, InputIterator e)
: tree_(b, e), const_tree_(tree_), checker_(b, e) {}
@@ -127,11 +124,11 @@ class base_checker {
}
return tree_iter;
}
- void value_check(const value_type &v) {
+ void value_check(const value_type &x) {
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);
+ const key_type &key = key_of_value(x);
+ CheckPairEquals(*find(key), x);
lower_bound(key);
upper_bound(key);
equal_range(key);
@@ -190,9 +187,9 @@ class base_checker {
return res;
}
- base_checker &operator=(const base_checker &other) {
- tree_ = other.tree_;
- checker_ = other.checker_;
+ base_checker &operator=(const base_checker &x) {
+ tree_ = x.tree_;
+ checker_ = x.checker_;
return *this;
}
@@ -253,9 +250,9 @@ class base_checker {
tree_.clear();
checker_.clear();
}
- void swap(base_checker &other) {
- tree_.swap(other.tree_);
- checker_.swap(other.checker_);
+ void swap(base_checker &x) {
+ tree_.swap(x.tree_);
+ checker_.swap(x.checker_);
}
void verify() const {
@@ -326,28 +323,28 @@ class unique_checker : public base_checker<TreeType, CheckerType> {
public:
unique_checker() : super_type() {}
- unique_checker(const unique_checker &other) : super_type(other) {}
+ unique_checker(const unique_checker &x) : super_type(x) {}
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) {
+ std::pair<iterator, bool> insert(const value_type &x) {
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);
+ this->checker_.insert(x);
+ std::pair<iterator, bool> tree_res = this->tree_.insert(x);
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) {
+ iterator insert(iterator position, const value_type &x) {
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);
+ this->checker_.insert(x);
+ iterator tree_res = this->tree_.insert(position, x);
CheckPairEquals(*tree_res, *checker_res.first);
EXPECT_EQ(this->tree_.size(), this->checker_.size());
EXPECT_EQ(this->tree_.size(), size + checker_res.second);
@@ -374,25 +371,25 @@ class multi_checker : public base_checker<TreeType, CheckerType> {
public:
multi_checker() : super_type() {}
- multi_checker(const multi_checker &other) : super_type(other) {}
+ multi_checker(const multi_checker &x) : super_type(x) {}
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) {
+ iterator insert(const value_type &x) {
int size = this->tree_.size();
- auto checker_res = this->checker_.insert(v);
- iterator tree_res = this->tree_.insert(v);
+ auto checker_res = this->checker_.insert(x);
+ iterator tree_res = this->tree_.insert(x);
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) {
+ iterator insert(iterator position, const value_type &x) {
int size = this->tree_.size();
- auto checker_res = this->checker_.insert(v);
- iterator tree_res = this->tree_.insert(position, v);
+ auto checker_res = this->checker_.insert(x);
+ iterator tree_res = this->tree_.insert(position, x);
CheckPairEquals(*tree_res, *checker_res);
EXPECT_EQ(this->tree_.size(), this->checker_.size());
EXPECT_EQ(this->tree_.size(), size + 1);
@@ -595,7 +592,7 @@ void BtreeTest() {
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),
- GTEST_FLAG_GET(random_seed));
+ testing::GTEST_FLAG(random_seed));
unique_checker<T, C> container;
@@ -619,7 +616,7 @@ void BtreeMultiTest() {
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),
- GTEST_FLAG_GET(random_seed));
+ testing::GTEST_FLAG(random_seed));
multi_checker<T, C> container;
@@ -815,12 +812,10 @@ void MapTest() {
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>
@@ -852,12 +847,10 @@ void MultiMapTest() {
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 {
@@ -1183,103 +1176,6 @@ TEST(Btree, RangeCtorSanity) {
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;
@@ -1372,8 +1268,6 @@ TEST(Btree, KeyCompareToAdapter) {
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>();
}
@@ -1425,6 +1319,28 @@ TEST(Btree, RValueInsert) {
EXPECT_EQ(tracker.swaps(), 0);
}
+} // 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>>::SizeWithNValues(target_values_per_node);
+ }
+
+ // Yields the number of values in a (non-root) leaf node for this set.
+ template <typename Set>
+ constexpr static size_t GetNumValuesPerNode() {
+ return btree_node<typename Set::params_type>::kNodeValues;
+ }
+};
+
+namespace {
+
// A btree set with a specific number of values per node.
template <typename Key, int TargetValuesPerNode, typename Cmp = std::less<Key>>
class SizedBtreeSet
@@ -1458,7 +1374,7 @@ void ExpectOperationCounts(const int expected_moves,
TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
InstanceTracker tracker;
// Note: this is minimum number of values per node.
- SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4> set4;
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3> set3;
// Note: this is the default number of values per node for a set of int32s
// (with 64-bit pointers).
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61> set61;
@@ -1469,28 +1385,28 @@ TEST(Btree, MovesComparisonsCopiesSwapsTracking) {
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);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
if (sizeof(void *) == 8) {
- EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
- BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
+ BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
}
// Test key insertion/deletion in random order.
- ExpectOperationCounts(56540, 134212, values, &tracker, &set4);
+ ExpectOperationCounts(45281, 132551, values, &tracker, &set3);
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(26638, 92134, values, &tracker, &set3);
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(49951, 119325, values, &tracker, &set3);
ExpectOperationCounts(338813, 118266, values, &tracker, &set61);
ExpectOperationCounts(534529, 125279, values, &tracker, &set100);
}
@@ -1507,9 +1423,9 @@ struct MovableOnlyInstanceThreeWayCompare {
TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
InstanceTracker tracker;
// Note: this is minimum number of values per node.
- SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/4,
+ SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/3,
MovableOnlyInstanceThreeWayCompare>
- set4;
+ set3;
// Note: this is the default number of values per node for a set of int32s
// (with 64-bit pointers).
SizedBtreeSet<MovableOnlyInstance, /*TargetValuesPerNode=*/61,
@@ -1524,28 +1440,28 @@ TEST(Btree, MovesComparisonsCopiesSwapsTrackingThreeWayCompare) {
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);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set3)>(), 3);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>(), 61);
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<decltype(set100)>(), 100);
if (sizeof(void *) == 8) {
- EXPECT_EQ(BtreeNodePeer::GetNumSlotsPerNode<absl::btree_set<int32_t>>(),
- BtreeNodePeer::GetNumSlotsPerNode<decltype(set61)>());
+ EXPECT_EQ(BtreeNodePeer::GetNumValuesPerNode<absl::btree_set<int32_t>>(),
+ BtreeNodePeer::GetNumValuesPerNode<decltype(set61)>());
}
// Test key insertion/deletion in random order.
- ExpectOperationCounts(56540, 124221, values, &tracker, &set4);
+ ExpectOperationCounts(45281, 122560, values, &tracker, &set3);
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(26638, 92134, values, &tracker, &set3);
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(49951, 109326, values, &tracker, &set3);
ExpectOperationCounts(338813, 108267, values, &tracker, &set61);
ExpectOperationCounts(534529, 115280, values, &tracker, &set100);
}
@@ -1621,7 +1537,7 @@ TEST(Btree, MapAt) {
#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");
+ EXPECT_DEATH(map.at(3), "absl::btree_map::at");
#endif
}
@@ -1708,25 +1624,10 @@ TEST(Btree, StrSplitCompatible) {
EXPECT_EQ(split_set, expected_set);
}
-TEST(Btree, KeyComp) {
- absl::btree_set<int> s;
- EXPECT_TRUE(s.key_comp()(1, 2));
- EXPECT_FALSE(s.key_comp()(2, 2));
- EXPECT_FALSE(s.key_comp()(2, 1));
-
- absl::btree_map<int, int> m1;
- EXPECT_TRUE(m1.key_comp()(1, 2));
- EXPECT_FALSE(m1.key_comp()(2, 2));
- EXPECT_FALSE(m1.key_comp()(2, 1));
-
- // Even though we internally adapt the comparator of `m2` to be three-way and
- // heterogeneous, the comparator we expose through key_comp() is the original
- // unadapted comparator.
- absl::btree_map<std::string, int> m2;
- EXPECT_TRUE(m2.key_comp()("a", "b"));
- EXPECT_FALSE(m2.key_comp()("b", "b"));
- EXPECT_FALSE(m2.key_comp()("b", "a"));
-}
+// 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;
@@ -1739,13 +1640,13 @@ TEST(Btree, ValueComp) {
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)));
- // Even though we internally adapt the comparator of `m2` to be three-way and
- // heterogeneous, the comparator we expose through value_comp() is based on
- // the original unadapted comparator.
absl::btree_map<std::string, int> m2;
- EXPECT_TRUE(m2.value_comp()(std::make_pair("a", 0), std::make_pair("b", 0)));
- EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("b", 0)));
- EXPECT_FALSE(m2.value_comp()(std::make_pair("b", 0), std::make_pair("a", 0)));
+ 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) {
@@ -2053,30 +1954,6 @@ TEST(Btree, ExtractAndInsertNodeHandleMultiMap) {
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 {
@@ -2218,31 +2095,6 @@ TEST(Btree, MergeIntoMultiMapsWithDifferentComparators) {
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 {
@@ -2274,11 +2126,11 @@ TEST(Btree, UserProvidedKeyCompareToComparators) {
TEST(Btree, TryEmplaceBasicTest) {
absl::btree_map<int, std::string> m;
- // Should construct a string from the literal.
+ // Should construct a std::string from the literal.
m.try_emplace(1, "one");
EXPECT_EQ(1, m.size());
- // Try other string constructors and const lvalue key.
+ // Try other std::string constructors and const lvalue key.
const int key(42);
m.try_emplace(key, 3, 'a');
m.try_emplace(2, std::string("two"));
@@ -2546,408 +2398,6 @@ TEST(Btree, BitfieldArgument) {
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);
-}
-
-bool IntCmp(const int a, const int b) { return a < b; }
-
-TEST(Btree, SupportsFunctionPtrComparator) {
- absl::btree_set<int, decltype(IntCmp) *> set(IntCmp);
- set.insert({1, 2, 3});
- EXPECT_THAT(set, ElementsAre(1, 2, 3));
- EXPECT_TRUE(set.key_comp()(1, 2));
- EXPECT_TRUE(set.value_comp()(1, 2));
-
- absl::btree_map<int, int, decltype(IntCmp) *> map(&IntCmp);
- map[1] = 1;
- EXPECT_THAT(map, ElementsAre(Pair(1, 1)));
- EXPECT_TRUE(map.key_comp()(1, 2));
- EXPECT_TRUE(map.value_comp()(std::make_pair(1, 1), std::make_pair(2, 2)));
-}
-
-template <typename Compare>
-struct TransparentPassThroughComp {
- using is_transparent = void;
-
- // This will fail compilation if we attempt a comparison that Compare does not
- // support, and the failure will happen inside the function implementation so
- // it can't be avoided by using SFINAE on this comparator.
- template <typename T, typename U>
- bool operator()(const T &lhs, const U &rhs) const {
- return Compare()(lhs, rhs);
- }
-};
-
-TEST(Btree,
- SupportsTransparentComparatorThatDoesNotImplementAllVisibleOperators) {
- absl::btree_set<MultiKey, TransparentPassThroughComp<MultiKeyComp>> set;
- set.insert(MultiKey{1, 2});
- EXPECT_TRUE(set.contains(1));
-}
-
-TEST(Btree, ConstructImplicitlyWithUnadaptedComparator) {
- absl::btree_set<MultiKey, MultiKeyComp> set = {{}, MultiKeyComp{}};
-}
-
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/btree_test.h b/third_party/abseil-cpp/absl/container/btree_test.h
index 624908072d..218ba41dc2 100644
--- a/third_party/abseil-cpp/absl/container/btree_test.h
+++ b/third_party/abseil-cpp/absl/container/btree_test.h
@@ -25,7 +25,6 @@
#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 {
@@ -101,16 +100,6 @@ struct Generator<std::string> {
}
};
-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;
diff --git a/third_party/abseil-cpp/absl/container/fixed_array.h b/third_party/abseil-cpp/absl/container/fixed_array.h
index 839ba0bc16..a9ce99bafd 100644
--- a/third_party/abseil-cpp/absl/container/fixed_array.h
+++ b/third_party/abseil-cpp/absl/container/fixed_array.h
@@ -41,7 +41,6 @@
#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"
@@ -73,6 +72,11 @@ constexpr static auto kFixedArrayUseDefault = static_cast<size_t>(-1);
// uninitialized (e.g. int, int[4], double), and others default-constructed.
// This matches the behavior of c-style arrays and `std::array`, but not
// `std::vector`.
+//
+// Note that `FixedArray` does not provide a public allocator; if it requires a
+// heap allocation, it will do so with global `::operator new[]()` and
+// `::operator delete[]()`, even if T provides class-scope overrides for these
+// operators.
template <typename T, size_t N = kFixedArrayUseDefault,
typename A = std::allocator<T>>
class FixedArray {
@@ -102,13 +106,13 @@ class FixedArray {
public:
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 reference = value_type&;
- using const_reference = const value_type&;
- using size_type = typename AllocatorTraits::size_type;
- using difference_type = typename AllocatorTraits::difference_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 iterator = pointer;
using const_iterator = const_pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
@@ -213,7 +217,7 @@ class FixedArray {
// Returns a reference the ith element of the fixed array.
// REQUIRES: 0 <= i < size()
reference operator[](size_type i) {
- ABSL_HARDENING_ASSERT(i < size());
+ assert(i < size());
return data()[i];
}
@@ -221,14 +225,14 @@ class FixedArray {
// ith element of the fixed array.
// REQUIRES: 0 <= i < size()
const_reference operator[](size_type i) const {
- ABSL_HARDENING_ASSERT(i < size());
+ assert(i < size());
return data()[i];
}
// FixedArray::at
//
- // Bounds-checked access. Returns a reference to the ith element of the fixed
- // array, or throws std::out_of_range
+ // Bounds-checked access. Returns a reference to the ith element of the
+ // fiexed 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");
@@ -248,32 +252,20 @@ class FixedArray {
// FixedArray::front()
//
// Returns a reference to the first element of the fixed array.
- reference front() {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[0];
- }
+ reference front() { return *begin(); }
// Overload of FixedArray::front() to return a reference to the first element
// of a fixed array of const values.
- const_reference front() const {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[0];
- }
+ const_reference front() const { return *begin(); }
// FixedArray::back()
//
// Returns a reference to the last element of the fixed array.
- reference back() {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[size() - 1];
- }
+ reference back() { return *(end() - 1); }
// Overload of FixedArray::back() to return a reference to the last element
// of a fixed array of const values.
- const_reference back() const {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[size() - 1];
- }
+ const_reference back() const { return *(end() - 1); }
// FixedArray::begin()
//
@@ -418,15 +410,15 @@ class FixedArray {
void AnnotateConstruct(size_type n);
void AnnotateDestruct(size_type n);
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
void* RedzoneBegin() { return &redzone_begin_; }
void* RedzoneEnd() { return &redzone_end_ + 1; }
-#endif // ABSL_HAVE_ADDRESS_SANITIZER
+#endif // ADDRESS_SANITIZER
private:
- ABSL_ADDRESS_SANITIZER_REDZONE(redzone_begin_);
+ ADDRESS_SANITIZER_REDZONE(redzone_begin_);
alignas(StorageElement) char buff_[sizeof(StorageElement[inline_elements])];
- ABSL_ADDRESS_SANITIZER_REDZONE(redzone_end_);
+ ADDRESS_SANITIZER_REDZONE(redzone_end_);
};
class EmptyInlinedStorage {
@@ -499,26 +491,22 @@ 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 ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
if (!n) return;
- ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(),
- data() + n);
- ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(),
- RedzoneBegin());
-#endif // ABSL_HAVE_ADDRESS_SANITIZER
+ ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), RedzoneEnd(), data() + n);
+ ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), data(), RedzoneBegin());
+#endif // 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 ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
if (!n) return;
- ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n,
- RedzoneEnd());
- ABSL_ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(),
- data());
-#endif // ABSL_HAVE_ADDRESS_SANITIZER
+ ANNOTATE_CONTIGUOUS_CONTAINER(data(), RedzoneEnd(), data() + n, RedzoneEnd());
+ ANNOTATE_CONTIGUOUS_CONTAINER(RedzoneBegin(), data(), RedzoneBegin(), data());
+#endif // ADDRESS_SANITIZER
static_cast<void>(n); // Mark used when not in asan mode
}
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc b/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
index e5f59299b3..a5bb009d98 100644
--- a/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
+++ b/third_party/abseil-cpp/absl/container/fixed_array_exception_safety_test.cc
@@ -150,7 +150,8 @@ TEST(FixedArrayExceptionSafety, InitListConstructorWithAlloc) {
template <typename FixedArrT>
testing::AssertionResult ReadMemory(FixedArrT* fixed_arr) {
- int sum = 0;
+ // Marked volatile to prevent optimization. Used for running asan tests.
+ volatile int sum = 0;
for (const auto& thrower : *fixed_arr) {
sum += thrower.Get();
}
diff --git a/third_party/abseil-cpp/absl/container/fixed_array_test.cc b/third_party/abseil-cpp/absl/container/fixed_array_test.cc
index 49598e7a05..c960fe51c1 100644
--- a/third_party/abseil-cpp/absl/container/fixed_array_test.cc
+++ b/third_party/abseil-cpp/absl/container/fixed_array_test.cc
@@ -27,10 +27,7 @@
#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"
@@ -191,21 +188,6 @@ 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);
@@ -640,9 +622,70 @@ 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 = absl::container_internal::CountingAllocator<int>;
+ using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
@@ -663,7 +706,7 @@ TEST(AllocatorSupportTest, CountInlineAllocations) {
TEST(AllocatorSupportTest, CountOutoflineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = absl::container_internal::CountingAllocator<int>;
+ using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated = 0;
@@ -684,7 +727,7 @@ TEST(AllocatorSupportTest, CountOutoflineAllocations) {
TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = absl::container_internal::CountingAllocator<int>;
+ using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
@@ -712,7 +755,7 @@ TEST(AllocatorSupportTest, CountCopyInlineAllocations) {
TEST(AllocatorSupportTest, CountCopyOutoflineAllocations) {
constexpr size_t inlined_size = 4;
- using Alloc = absl::container_internal::CountingAllocator<int>;
+ using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
int64_t allocated1 = 0;
@@ -744,7 +787,7 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) {
using testing::SizeIs;
constexpr size_t inlined_size = 4;
- using Alloc = absl::container_internal::CountingAllocator<int>;
+ using Alloc = CountingAllocator<int>;
using AllocFxdArr = absl::FixedArray<int, inlined_size, Alloc>;
{
@@ -768,16 +811,16 @@ TEST(AllocatorSupportTest, SizeValAllocConstructor) {
}
}
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
TEST(FixedArrayTest, AddressSanitizerAnnotations1) {
absl::FixedArray<int, 32> a(10);
int* raw = a.data();
raw[0] = 0;
raw[9] = 0;
- 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");
+ 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");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
@@ -785,10 +828,10 @@ TEST(FixedArrayTest, AddressSanitizerAnnotations2) {
char* raw = a.data();
raw[0] = 0;
raw[11] = 0;
- 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");
+ 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");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
@@ -796,8 +839,8 @@ TEST(FixedArrayTest, AddressSanitizerAnnotations3) {
uint64_t* raw = a.data();
raw[0] = 0;
raw[19] = 0;
- EXPECT_DEATH_IF_SUPPORTED(raw[-1] = 0, "container-overflow");
- EXPECT_DEATH_IF_SUPPORTED(raw[20] = 0, "container-overflow");
+ EXPECT_DEATH(raw[-1] = 0, "container-overflow");
+ EXPECT_DEATH(raw[20] = 0, "container-overflow");
}
TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
@@ -809,13 +852,13 @@ TEST(FixedArrayTest, AddressSanitizerAnnotations4) {
// 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_IF_SUPPORTED(raw[-1].z_ = 0, "container-overflow");
- EXPECT_DEATH_IF_SUPPORTED(raw[10] = ThreeInts(), "container-overflow");
+ EXPECT_DEATH(raw[-1].z_ = 0, "container-overflow");
+ EXPECT_DEATH(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_IF_SUPPORTED(raw[21] = ThreeInts(), "container-overflow");
+ EXPECT_DEATH(raw[21] = ThreeInts(), "container-overflow");
}
-#endif // ABSL_HAVE_ADDRESS_SANITIZER
+#endif // ADDRESS_SANITIZER
TEST(FixedArrayTest, AbslHashValueWorks) {
using V = absl::FixedArray<int>;
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_map.h b/third_party/abseil-cpp/absl/container/flat_hash_map.h
index 74def0df0e..fcb70d861f 100644
--- a/third_party/abseil-cpp/absl/container/flat_hash_map.h
+++ b/third_party/abseil-cpp/absl/container/flat_hash_map.h
@@ -234,8 +234,7 @@ 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, returning the
- // number of elements erased (0 or 1).
+ // Erases the element with the matching key, if it exists.
using Base::erase;
// flat_hash_map::insert()
@@ -384,11 +383,6 @@ 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()
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_map_test.cc b/third_party/abseil-cpp/absl/container/flat_hash_map_test.cc
index 8dda1d3539..728b693a07 100644
--- a/third_party/abseil-cpp/absl/container/flat_hash_map_test.cc
+++ b/third_party/abseil-cpp/absl/container/flat_hash_map_test.cc
@@ -16,7 +16,6 @@
#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"
@@ -35,19 +34,6 @@ 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<std::pair<const K, V>>>;
@@ -267,47 +253,6 @@ TEST(FlatHashMap, EraseIf) {
}
}
-// 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
-
-TEST(FlatHashMap, Reserve) {
- // Verify that if we reserve(size() + n) then we can perform n insertions
- // without a rehash, i.e., without invalidating any references.
- for (size_t trial = 0; trial < 20; ++trial) {
- for (size_t initial = 3; initial < 100; ++initial) {
- // Fill in `initial` entries, then erase 2 of them, then reserve space for
- // two inserts and check for reference stability while doing the inserts.
- flat_hash_map<size_t, size_t> map;
- for (size_t i = 0; i < initial; ++i) {
- map[i] = i;
- }
- map.erase(0);
- map.erase(1);
- map.reserve(map.size() + 2);
- size_t& a2 = map[2];
- // In the event of a failure, asan will complain in one of these two
- // assignments.
- map[initial] = a2;
- map[initial + 1] = a2;
- // Fail even when not under asan:
- size_t& a2new = map[2];
- EXPECT_EQ(&a2, &a2new);
- }
- }
-}
-
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_set.h b/third_party/abseil-cpp/absl/container/flat_hash_set.h
index 6b89da6571..94be6e3d13 100644
--- a/third_party/abseil-cpp/absl/container/flat_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/flat_hash_set.h
@@ -227,8 +227,7 @@ class flat_hash_set
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists, returning the
- // number of elements erased (0 or 1).
+ // Erases the element with the matching key, if it exists.
using Base::erase;
// flat_hash_set::insert()
@@ -324,7 +323,7 @@ class flat_hash_set
// flat_hash_set::merge()
//
- // Extracts elements from a given `source` flat hash set into this
+ // Extracts elements from a given `source` flat hash map 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;
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_set_test.cc b/third_party/abseil-cpp/absl/container/flat_hash_set_test.cc
index 8f6f9944ca..40d7f85c5d 100644
--- a/third_party/abseil-cpp/absl/container/flat_hash_set_test.cc
+++ b/third_party/abseil-cpp/absl/container/flat_hash_set_test.cc
@@ -16,7 +16,6 @@
#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"
@@ -37,17 +36,6 @@ 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>>;
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector.h b/third_party/abseil-cpp/absl/container/inlined_vector.h
index df9e09917d..2388d471dc 100644
--- a/third_party/abseil-cpp/absl/container/inlined_vector.h
+++ b/third_party/abseil-cpp/absl/container/inlined_vector.h
@@ -48,7 +48,6 @@
#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"
@@ -64,7 +63,7 @@ ABSL_NAMESPACE_BEGIN
// `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 {
@@ -72,43 +71,37 @@ class InlinedVector {
using Storage = inlined_vector_internal::Storage<T, N, A>;
- template <typename TheA>
- using AllocatorTraits = inlined_vector_internal::AllocatorTraits<TheA>;
- template <typename TheA>
- using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;
- template <typename TheA>
- using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<TheA>;
+ using AllocatorTraits = typename Storage::AllocatorTraits;
+ using RValueReference = typename Storage::RValueReference;
+ using MoveIterator = typename Storage::MoveIterator;
+ using IsMemcpyOk = typename Storage::IsMemcpyOk;
- template <typename TheA, typename Iterator>
+ template <typename Iterator>
using IteratorValueAdapter =
- inlined_vector_internal::IteratorValueAdapter<TheA, Iterator>;
- template <typename TheA>
- using CopyValueAdapter = inlined_vector_internal::CopyValueAdapter<TheA>;
- template <typename TheA>
- using DefaultValueAdapter =
- inlined_vector_internal::DefaultValueAdapter<TheA>;
+ typename Storage::template IteratorValueAdapter<Iterator>;
+ using CopyValueAdapter = typename Storage::CopyValueAdapter;
+ using DefaultValueAdapter = typename Storage::DefaultValueAdapter;
template <typename Iterator>
using EnableIfAtLeastForwardIterator = absl::enable_if_t<
- inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+ inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
template <typename Iterator>
using DisableIfAtLeastForwardIterator = absl::enable_if_t<
- !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+ !inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value>;
public:
- using allocator_type = A;
- using value_type = inlined_vector_internal::ValueType<A>;
- using pointer = inlined_vector_internal::Pointer<A>;
- using const_pointer = inlined_vector_internal::ConstPointer<A>;
- using size_type = inlined_vector_internal::SizeType<A>;
- using difference_type = inlined_vector_internal::DifferenceType<A>;
- using reference = inlined_vector_internal::Reference<A>;
- using const_reference = inlined_vector_internal::ConstReference<A>;
- using iterator = inlined_vector_internal::Iterator<A>;
- using const_iterator = inlined_vector_internal::ConstIterator<A>;
- using reverse_iterator = inlined_vector_internal::ReverseIterator<A>;
- using const_reverse_iterator =
- inlined_vector_internal::ConstReverseIterator<A>;
+ 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
@@ -117,28 +110,28 @@ class InlinedVector {
// Creates an empty inlined vector with a value-initialized allocator.
InlinedVector() noexcept(noexcept(allocator_type())) : storage_() {}
- // Creates an empty inlined vector with a copy of `allocator`.
- explicit InlinedVector(const allocator_type& allocator) noexcept
- : storage_(allocator) {}
+ // Creates an empty inlined vector with a copy of `alloc`.
+ explicit InlinedVector(const allocator_type& alloc) noexcept
+ : storage_(alloc) {}
// Creates an inlined vector with `n` copies of `value_type()`.
explicit InlinedVector(size_type n,
- const allocator_type& allocator = allocator_type())
- : storage_(allocator) {
- storage_.Initialize(DefaultValueAdapter<A>(), n);
+ const allocator_type& alloc = allocator_type())
+ : 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& allocator = allocator_type())
- : storage_(allocator) {
- storage_.Initialize(CopyValueAdapter<A>(std::addressof(v)), n);
+ const allocator_type& alloc = allocator_type())
+ : storage_(alloc) {
+ storage_.Initialize(CopyValueAdapter(v), n);
}
// Creates an inlined vector with copies of the elements of `list`.
InlinedVector(std::initializer_list<value_type> list,
- const allocator_type& allocator = allocator_type())
- : InlinedVector(list.begin(), list.end(), allocator) {}
+ const allocator_type& alloc = allocator_type())
+ : InlinedVector(list.begin(), list.end(), alloc) {}
// Creates an inlined vector with elements constructed from the provided
// forward iterator range [`first`, `last`).
@@ -147,40 +140,37 @@ class InlinedVector {
// this constructor with two integral arguments and a call to the above
// `InlinedVector(size_type, const_reference)` constructor.
template <typename ForwardIterator,
- EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
InlinedVector(ForwardIterator first, ForwardIterator last,
- const allocator_type& allocator = allocator_type())
- : storage_(allocator) {
- storage_.Initialize(IteratorValueAdapter<A, ForwardIterator>(first),
+ 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> = 0>
+ DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
InlinedVector(InputIterator first, InputIterator last,
- const allocator_type& allocator = allocator_type())
- : storage_(allocator) {
+ const allocator_type& alloc = allocator_type())
+ : storage_(alloc) {
std::copy(first, last, std::back_inserter(*this));
}
// Creates an inlined vector by copying the contents of `other` using
// `other`'s allocator.
InlinedVector(const InlinedVector& other)
- : InlinedVector(other, other.storage_.GetAllocator()) {}
-
- // Creates an inlined vector by copying the contents of `other` using the
- // provided `allocator`.
- InlinedVector(const InlinedVector& other, const allocator_type& allocator)
- : storage_(allocator) {
- if (other.empty()) {
- // Empty; nothing to do.
- } else if (IsMemcpyOk<A>::value && !other.storage_.GetIsAllocated()) {
- // Memcpy-able and do not need allocation.
+ : InlinedVector(other, *other.storage_.GetAllocPtr()) {}
+
+ // Creates an inlined vector by copying the contents of `other` using `alloc`.
+ InlinedVector(const InlinedVector& other, const allocator_type& alloc)
+ : storage_(alloc) {
+ if (IsMemcpyOk::value && !other.storage_.GetIsAllocated()) {
storage_.MemcpyFrom(other.storage_);
} else {
- storage_.InitFrom(other.storage_);
+ storage_.Initialize(IteratorValueAdapter<const_pointer>(other.data()),
+ other.size());
}
}
@@ -201,23 +191,23 @@ class InlinedVector {
InlinedVector(InlinedVector&& other) noexcept(
absl::allocator_is_nothrow<allocator_type>::value ||
std::is_nothrow_move_constructible<value_type>::value)
- : storage_(other.storage_.GetAllocator()) {
- if (IsMemcpyOk<A>::value) {
+ : storage_(*other.storage_.GetAllocPtr()) {
+ if (IsMemcpyOk::value) {
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
} else if (other.storage_.GetIsAllocated()) {
- storage_.SetAllocation({other.storage_.GetAllocatedData(),
- other.storage_.GetAllocatedCapacity()});
+ storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
+ other.storage_.GetAllocatedCapacity());
storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0);
} else {
- IteratorValueAdapter<A, MoveIterator<A>> other_values(
- MoveIterator<A>(other.storage_.GetInlinedData()));
+ IteratorValueAdapter<MoveIterator> other_values(
+ MoveIterator(other.storage_.GetInlinedData()));
- inlined_vector_internal::ConstructElements<A>(
- storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
+ inlined_vector_internal::ConstructElements(
+ storage_.GetAllocPtr(), storage_.GetInlinedData(), &other_values,
other.storage_.GetSize());
storage_.SetInlinedSize(other.storage_.GetSize());
@@ -225,32 +215,30 @@ class InlinedVector {
}
// Creates an inlined vector by moving in the contents of `other` with a copy
- // of `allocator`.
+ // of `alloc`.
//
- // NOTE: if `other`'s allocator is not equal to `allocator`, even if `other`
+ // 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& allocator)
- noexcept(absl::allocator_is_nothrow<allocator_type>::value)
- : storage_(allocator) {
- if (IsMemcpyOk<A>::value) {
+ InlinedVector(InlinedVector&& other, const allocator_type& alloc) noexcept(
+ absl::allocator_is_nothrow<allocator_type>::value)
+ : storage_(alloc) {
+ if (IsMemcpyOk::value) {
storage_.MemcpyFrom(other.storage_);
other.storage_.SetInlinedSize(0);
- } else if ((storage_.GetAllocator() == other.storage_.GetAllocator()) &&
+ } else if ((*storage_.GetAllocPtr() == *other.storage_.GetAllocPtr()) &&
other.storage_.GetIsAllocated()) {
- storage_.SetAllocation({other.storage_.GetAllocatedData(),
- other.storage_.GetAllocatedCapacity()});
+ storage_.SetAllocatedData(other.storage_.GetAllocatedData(),
+ other.storage_.GetAllocatedCapacity());
storage_.SetAllocatedSize(other.storage_.GetSize());
other.storage_.SetInlinedSize(0);
} else {
- storage_.Initialize(IteratorValueAdapter<A, MoveIterator<A>>(
- MoveIterator<A>(other.data())),
- other.size());
+ storage_.Initialize(
+ IteratorValueAdapter<MoveIterator>(MoveIterator(other.data())),
+ other.size());
}
}
@@ -319,14 +307,16 @@ class InlinedVector {
//
// Returns a `reference` to the `i`th element of the inlined vector.
reference operator[](size_type i) {
- ABSL_HARDENING_ASSERT(i < size());
+ assert(i < size());
+
return data()[i];
}
// 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 {
- ABSL_HARDENING_ASSERT(i < size());
+ assert(i < size());
+
return data()[i];
}
@@ -341,6 +331,7 @@ class InlinedVector {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type)` failed bounds check");
}
+
return data()[i];
}
@@ -354,6 +345,7 @@ class InlinedVector {
base_internal::ThrowStdOutOfRange(
"`InlinedVector::at(size_type) const` failed bounds check");
}
+
return data()[i];
}
@@ -361,30 +353,34 @@ class InlinedVector {
//
// Returns a `reference` to the first element of the inlined vector.
reference front() {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[0];
+ assert(!empty());
+
+ return at(0);
}
// Overload of `InlinedVector::front()` that returns a `const_reference` to
// the first element of the inlined vector.
const_reference front() const {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[0];
+ assert(!empty());
+
+ return at(0);
}
// `InlinedVector::back()`
//
// Returns a `reference` to the last element of the inlined vector.
reference back() {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[size() - 1];
+ assert(!empty());
+
+ return at(size() - 1);
}
// Overload of `InlinedVector::back()` that returns a `const_reference` to the
// last element of the inlined vector.
const_reference back() const {
- ABSL_HARDENING_ASSERT(!empty());
- return data()[size() - 1];
+ assert(!empty());
+
+ return at(size() - 1);
}
// `InlinedVector::begin()`
@@ -451,7 +447,7 @@ class InlinedVector {
// `InlinedVector::get_allocator()`
//
// Returns a copy of the inlined vector's allocator.
- allocator_type get_allocator() const { return storage_.GetAllocator(); }
+ allocator_type get_allocator() const { return *storage_.GetAllocPtr(); }
// ---------------------------------------------------------------------------
// InlinedVector Member Mutators
@@ -485,16 +481,16 @@ class InlinedVector {
// unspecified state.
InlinedVector& operator=(InlinedVector&& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
- if (IsMemcpyOk<A>::value || other.storage_.GetIsAllocated()) {
- inlined_vector_internal::DestroyElements<A>(storage_.GetAllocator(),
- data(), size());
+ 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 {
- storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
- MoveIterator<A>(other.storage_.GetInlinedData())),
+ storage_.Assign(IteratorValueAdapter<MoveIterator>(
+ MoveIterator(other.storage_.GetInlinedData())),
other.size());
}
}
@@ -506,7 +502,7 @@ class InlinedVector {
//
// Replaces the contents of the inlined vector with `n` copies of `v`.
void assign(size_type n, const_reference v) {
- storage_.Assign(CopyValueAdapter<A>(std::addressof(v)), n);
+ storage_.Assign(CopyValueAdapter(v), n);
}
// Overload of `InlinedVector::assign(...)` that replaces the contents of the
@@ -520,9 +516,9 @@ class InlinedVector {
//
// NOTE: this overload is for iterators that are "forward" category or better.
template <typename ForwardIterator,
- EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
void assign(ForwardIterator first, ForwardIterator last) {
- storage_.Assign(IteratorValueAdapter<A, ForwardIterator>(first),
+ storage_.Assign(IteratorValueAdapter<ForwardIterator>(first),
std::distance(first, last));
}
@@ -531,11 +527,11 @@ class InlinedVector {
//
// NOTE: this overload is for iterators that are "input" category.
template <typename InputIterator,
- DisableIfAtLeastForwardIterator<InputIterator> = 0>
+ 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;
+ at(i) = *first;
}
erase(data() + i, data() + size());
@@ -546,12 +542,9 @@ class InlinedVector {
//
// Resizes the inlined vector to contain `n` elements.
//
- // NOTE: If `n` is smaller than `size()`, extra elements are destroyed. If `n`
+ // 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<A>(), n);
- }
+ void resize(size_type n) { storage_.Resize(DefaultValueAdapter(), n); }
// Overload of `InlinedVector::resize(...)` that resizes the inlined vector to
// contain `n` elements.
@@ -559,8 +552,7 @@ class InlinedVector {
// 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<A>(std::addressof(v)), n);
+ storage_.Resize(CopyValueAdapter(v), n);
}
// `InlinedVector::insert(...)`
@@ -573,7 +565,7 @@ class InlinedVector {
// 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, value_type&& v) {
+ iterator insert(const_iterator pos, RValueReference v) {
return emplace(pos, std::move(v));
}
@@ -581,13 +573,12 @@ class InlinedVector {
// 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());
+ assert(pos >= begin());
+ assert(pos <= end());
if (ABSL_PREDICT_TRUE(n != 0)) {
value_type dealias = v;
- return storage_.Insert(pos, CopyValueAdapter<A>(std::addressof(dealias)),
- n);
+ return storage_.Insert(pos, CopyValueAdapter(dealias), n);
} else {
return const_cast<iterator>(pos);
}
@@ -606,15 +597,14 @@ class InlinedVector {
//
// NOTE: this overload is for iterators that are "forward" category or better.
template <typename ForwardIterator,
- EnableIfAtLeastForwardIterator<ForwardIterator> = 0>
+ EnableIfAtLeastForwardIterator<ForwardIterator>* = nullptr>
iterator insert(const_iterator pos, ForwardIterator first,
ForwardIterator last) {
- ABSL_HARDENING_ASSERT(pos >= begin());
- ABSL_HARDENING_ASSERT(pos <= end());
+ assert(pos >= begin());
+ assert(pos <= end());
if (ABSL_PREDICT_TRUE(first != last)) {
- return storage_.Insert(pos,
- IteratorValueAdapter<A, ForwardIterator>(first),
+ return storage_.Insert(pos, IteratorValueAdapter<ForwardIterator>(first),
std::distance(first, last));
} else {
return const_cast<iterator>(pos);
@@ -627,10 +617,10 @@ class InlinedVector {
//
// NOTE: this overload is for iterators that are "input" category.
template <typename InputIterator,
- DisableIfAtLeastForwardIterator<InputIterator> = 0>
+ DisableIfAtLeastForwardIterator<InputIterator>* = nullptr>
iterator insert(const_iterator pos, InputIterator first, InputIterator last) {
- ABSL_HARDENING_ASSERT(pos >= begin());
- ABSL_HARDENING_ASSERT(pos <= end());
+ assert(pos >= begin());
+ assert(pos <= end());
size_type index = std::distance(cbegin(), pos);
for (size_type i = index; first != last; ++i, static_cast<void>(++first)) {
@@ -646,13 +636,13 @@ class InlinedVector {
// `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());
+ assert(pos >= begin());
+ assert(pos <= end());
value_type dealias(std::forward<Args>(args)...);
return storage_.Insert(pos,
- IteratorValueAdapter<A, MoveIterator<A>>(
- MoveIterator<A>(std::addressof(dealias))),
+ IteratorValueAdapter<MoveIterator>(
+ MoveIterator(std::addressof(dealias))),
1);
}
@@ -672,7 +662,7 @@ class InlinedVector {
// Overload of `InlinedVector::push_back(...)` for inserting `v` at `end()`
// using move semantics.
- void push_back(value_type&& v) {
+ void push_back(RValueReference v) {
static_cast<void>(emplace_back(std::move(v)));
}
@@ -680,9 +670,9 @@ class InlinedVector {
//
// Destroys the element at `back()`, reducing the size by `1`.
void pop_back() noexcept {
- ABSL_HARDENING_ASSERT(!empty());
+ assert(!empty());
- AllocatorTraits<A>::destroy(storage_.GetAllocator(), data() + (size() - 1));
+ AllocatorTraits::destroy(*storage_.GetAllocPtr(), data() + (size() - 1));
storage_.SubtractSize(1);
}
@@ -693,8 +683,8 @@ class InlinedVector {
//
// NOTE: may return `end()`, which is not dereferencable.
iterator erase(const_iterator pos) {
- ABSL_HARDENING_ASSERT(pos >= begin());
- ABSL_HARDENING_ASSERT(pos < end());
+ assert(pos >= begin());
+ assert(pos < end());
return storage_.Erase(pos, pos + 1);
}
@@ -705,9 +695,9 @@ class InlinedVector {
//
// NOTE: may return `end()`, which is not dereferencable.
iterator erase(const_iterator from, const_iterator to) {
- ABSL_HARDENING_ASSERT(from >= begin());
- ABSL_HARDENING_ASSERT(from <= to);
- ABSL_HARDENING_ASSERT(to <= end());
+ assert(from >= begin());
+ assert(from <= to);
+ assert(to <= end());
if (ABSL_PREDICT_TRUE(from != to)) {
return storage_.Erase(from, to);
@@ -721,8 +711,8 @@ class InlinedVector {
// Destroys all elements in the inlined vector, setting the size to `0` and
// deallocating any held memory.
void clear() noexcept {
- inlined_vector_internal::DestroyElements<A>(storage_.GetAllocator(), data(),
- size());
+ inlined_vector_internal::DestroyElements(storage_.GetAllocPtr(), data(),
+ size());
storage_.DeallocateIfAllocated();
storage_.SetInlinedSize(0);
@@ -735,12 +725,15 @@ class InlinedVector {
// `InlinedVector::shrink_to_fit()`
//
- // Attempts to reduce memory usage by moving elements to (or keeping elements
- // in) the smallest available buffer sufficient for containing `size()`
- // elements.
+ // Reduces memory usage by freeing unused memory. After being called, calls to
+ // `capacity()` will be equal to `max(N, size())`.
+ //
+ // 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()` is sufficiently small, the elements will be moved into (or kept
- // in) the inlined space.
+ // If `size() > N` and `size() < capacity()`, the elements will be moved to a
+ // smaller allocation.
void shrink_to_fit() {
if (storage_.GetIsAllocated()) {
storage_.ShrinkToFit();
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector_benchmark.cc b/third_party/abseil-cpp/absl/container/inlined_vector_benchmark.cc
index e256fad60f..3f2b4ed28a 100644
--- a/third_party/abseil-cpp/absl/container/inlined_vector_benchmark.cc
+++ b/third_party/abseil-cpp/absl/container/inlined_vector_benchmark.cc
@@ -83,7 +83,7 @@ int GetNonShortStringOptimizationSize() {
}
ABSL_RAW_LOG(
FATAL,
- "Failed to find a string larger than the short string optimization");
+ "Failed to find a std::string larger than the short std::string optimization");
return -1;
}
@@ -534,28 +534,6 @@ void BM_ConstructFromMove(benchmark::State& state) {
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;
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector_test.cc b/third_party/abseil-cpp/absl/container/inlined_vector_test.cc
index 98aff33498..2c9b0d0e03 100644
--- a/third_party/abseil-cpp/absl/container/inlined_vector_test.cc
+++ b/third_party/abseil-cpp/absl/container/inlined_vector_test.cc
@@ -30,7 +30,6 @@
#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"
@@ -248,16 +247,6 @@ 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.
@@ -736,26 +725,22 @@ 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.
-
- 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]));
+ 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*));
}
TEST(IntVec, Clear) {
@@ -795,7 +780,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 string to ensure heap.";
+ const std::string s = "A quite long std::string to ensure heap.";
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
@@ -810,7 +795,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 string to ensure heap.";
+ const std::string s = "A quite long std::string to ensure heap.";
std_v.push_back(s);
v.push_back(s);
for (int i = 0; i < 20; ++i) {
@@ -823,7 +808,7 @@ TEST(StringVec, SelfRefPushBackWithMove) {
}
TEST(StringVec, SelfMove) {
- const std::string s = "A quite long string to ensure heap.";
+ const std::string s = "A quite long std::string to ensure heap.";
for (int len = 0; len < 20; len++) {
SCOPED_TRACE(len);
absl::InlinedVector<std::string, 8> v;
diff --git a/third_party/abseil-cpp/absl/container/internal/btree.h b/third_party/abseil-cpp/absl/container/internal/btree.h
index f636c5fc73..fd5c0e7aba 100644
--- a/third_party/abseil-cpp/absl/container/internal/btree.h
+++ b/third_party/abseil-cpp/absl/container/internal/btree.h
@@ -65,7 +65,6 @@
#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"
@@ -88,30 +87,12 @@ struct StringBtreeDefaultLess {
// Compatibility constructor.
StringBtreeDefaultLess(std::less<std::string>) {} // NOLINT
- StringBtreeDefaultLess(std::less<absl::string_view>) {} // NOLINT
-
- // Allow converting to std::less for use in key_comp()/value_comp().
- explicit operator std::less<std::string>() const { return {}; }
- explicit operator std::less<absl::string_view>() const { return {}; }
- explicit operator std::less<absl::Cord>() const { return {}; }
+ 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 {
@@ -120,41 +101,23 @@ struct StringBtreeDefaultGreater {
StringBtreeDefaultGreater() = default;
StringBtreeDefaultGreater(std::greater<std::string>) {} // NOLINT
- StringBtreeDefaultGreater(std::greater<absl::string_view>) {} // NOLINT
-
- // Allow converting to std::greater for use in key_comp()/value_comp().
- explicit operator std::greater<std::string>() const { return {}; }
- explicit operator std::greater<absl::string_view>() const { return {}; }
- explicit operator std::greater<absl::Cord>() const { return {}; }
+ 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
+// comparison that returns a negative value to indicate less-than, zero to
+// indicate equality and a positive value to indicate greater-than. 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>.
+// less<string_view>, and greater<string_view>.
//
// 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.
+// google string types with common comparison functors.
// These string-like specializations also turn on heterogeneous lookup by
// default.
template <typename Compare>
@@ -182,54 +145,10 @@ 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 {
- using original_key_compare = Compare;
-
- // If Compare is a common comparator for a string-like type, then we adapt it
+ // If Compare is a common comparator for a std::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
@@ -241,6 +160,9 @@ struct common_params {
using size_type = std::make_signed<size_t>::type;
using difference_type = ptrdiff_t;
+ // True if this is a multiset or multimap.
+ using is_multi_container = std::integral_constant<bool, Multi>;
+
using slot_policy = SlotPolicy;
using slot_type = typename slot_policy::slot_type;
using value_type = typename slot_policy::value_type;
@@ -250,23 +172,6 @@ struct common_params {
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,
@@ -312,6 +217,10 @@ struct common_params {
static void move(Alloc *alloc, slot_type *src, slot_type *dest) {
slot_policy::move(alloc, src, dest);
}
+ static void move(Alloc *alloc, slot_type *first, slot_type *last,
+ slot_type *result) {
+ slot_policy::move(alloc, first, last, result);
+ }
};
// A parameters structure for holding the type parameters for a btree_map.
@@ -329,36 +238,23 @@ struct map_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
using value_type = typename super_type::value_type;
using init_type = typename super_type::init_type;
- using original_key_compare = typename super_type::original_key_compare;
- // Reference: https://en.cppreference.com/w/cpp/container/map/value_compare
- class value_compare {
- template <typename Params>
- friend class btree;
-
- protected:
- explicit value_compare(original_key_compare c) : comp(std::move(c)) {}
+ 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) {}
- original_key_compare comp; // NOLINT
-
- public:
- auto operator()(const value_type &lhs, const value_type &rhs) const
- -> decltype(comp(lhs.first, rhs.first)) {
- return comp(lhs.first, rhs.first);
+ template <typename 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 const Key &key(const value_type &x) { return x.first; }
+ static const Key &key(const init_type &x) { return x.first; }
+ static const Key &key(const slot_type *x) { return slot_policy::key(x); }
static mapped_type &value(value_type *value) { return value->second; }
};
@@ -399,6 +295,13 @@ struct set_slot_policy {
static void move(Alloc * /*alloc*/, slot_type *src, slot_type *dest) {
*dest = std::move(*src);
}
+
+ template <typename Alloc>
+ static void move(Alloc *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);
+ }
};
// A parameters structure for holding the type parameters for a btree_set.
@@ -409,14 +312,11 @@ 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::original_key_compare;
+ 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; }
+ static const Key &key(const value_type &x) { return x; }
+ static const Key &key(const slot_type *x) { return *x; }
};
// An adapter class that converts a lower-bound compare into an upper-bound
@@ -426,8 +326,8 @@ struct set_params : common_params<Key, Compare, Alloc, TargetNodeSize, Multi,
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 {
+ template <typename K, typename LK>
+ bool operator()(const K &a, const LK &b) const {
// Returns true when a is not greater than b.
return !compare_internal::compare_result_as_less_than(comp(b, a));
}
@@ -452,10 +352,6 @@ struct SearchResult {
// 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; }
@@ -468,6 +364,7 @@ struct SearchResult<V, false> {
template <typename Params>
class btree_node {
using is_key_compare_to = typename Params::is_key_compare_to;
+ using is_multi_container = typename Params::is_multi_container;
using field_type = typename Params::node_count_type;
using allocator_type = typename Params::allocator_type;
using slot_type = typename Params::slot_type;
@@ -485,25 +382,18 @@ class btree_node {
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 absl::container_internal::Layout as if it had
- // the following structure:
+ 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;
//
@@ -517,23 +407,23 @@ class btree_node {
// // 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
+ // // [1, kNodeValues] for root leaf nodes, kNodeValues for non-root leaf
// // nodes, and kInternalNodeMaxCount (as a sentinel value) for internal
- // // nodes (even though there are still kNodeSlots values in the node).
+ // // nodes (even though there are still kNodeValues 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
+ // // kNodeValues 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
+ // // There are 0 children for leaf nodes and kNodeValues + 1 children for
// // internal nodes.
- // btree_node *children[kNodeSlots + 1];
+ // btree_node *children[kNodeValues + 1];
//
// This class is only constructed by EmptyNodeType. Normally, pointers to the
// layout above are allocated, cast to btree_node*, and de-allocated within
@@ -555,62 +445,57 @@ class btree_node {
private:
using layout_type = absl::container_internal::Layout<btree_node *, field_type,
slot_type, btree_node *>;
- constexpr static size_type SizeWithNSlots(size_type n) {
+ constexpr static size_type SizeWithNValues(size_type n) {
return layout_type(/*parent*/ 1,
/*position, start, finish, max_count*/ 4,
- /*slots*/ n,
+ /*values*/ 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);
+ return SizeWithNValues(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) {
+ constexpr static size_type NodeTargetValues(const int begin, const int end) {
return begin == end ? begin
- : SizeWithNSlots((begin + end) / 2 + 1) >
+ : SizeWithNValues((begin + end) / 2 + 1) >
params_type::kTargetNodeSize
- ? NodeTargetSlots(begin, (begin + end) / 2)
- : NodeTargetSlots((begin + end) / 2 + 1, end);
+ ? NodeTargetValues(begin, (begin + end) / 2)
+ : NodeTargetValues((begin + end) / 2 + 1, end);
}
enum {
kTargetNodeSize = params_type::kTargetNodeSize,
- kNodeTargetSlots = NodeTargetSlots(0, params_type::kTargetNodeSize),
+ kNodeTargetValues = NodeTargetValues(0, params_type::kTargetNodeSize),
- // We need a minimum of 3 slots per internal node in order to perform
+ // We need a minimum of 3 values 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,
+ // propagated to the parent as the delimiter for the split).
+ kNodeValues = kNodeTargetValues >= 3 ? kNodeTargetValues : 3,
// 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) {
+ // Leaves can have less than kNodeValues values.
+ constexpr static layout_type LeafLayout(const int max_values = kNodeValues) {
return layout_type(/*parent*/ 1,
/*position, start, finish, max_count*/ 4,
- /*slots*/ slot_count,
+ /*values*/ max_values,
/*children*/ 0);
}
constexpr static layout_type InternalLayout() {
return layout_type(/*parent*/ 1,
/*position, start, finish, max_count*/ 4,
- /*slots*/ kNodeSlots,
- /*children*/ kNodeSlots + 1);
+ /*values*/ kNodeValues,
+ /*children*/ kNodeValues + 1);
}
- constexpr static size_type LeafSize(const int slot_count = kNodeSlots) {
- return LeafLayout(slot_count).AllocSize();
+ constexpr static size_type LeafSize(const int max_values = kNodeValues) {
+ return LeafLayout(max_values).AllocSize();
}
constexpr static size_type InternalSize() {
return InternalLayout().AllocSize();
@@ -667,10 +552,10 @@ class btree_node {
}
field_type max_count() const {
// Internal nodes have max_count==kInternalNodeMaxCount.
- // Leaf nodes have max_count in [1, kNodeSlots].
+ // Leaf nodes have max_count in [1, kNodeValues].
const field_type max_count = GetField<1>()[3];
return max_count == field_type{kInternalNodeMaxCount}
- ? field_type{kNodeSlots}
+ ? field_type{kNodeValues}
: max_count;
}
@@ -748,7 +633,7 @@ class btree_node {
}
++s;
}
- return SearchResult<int, false>{s};
+ return {s};
}
// Returns the position of the first value whose key is not less than k using
@@ -783,7 +668,7 @@ class btree_node {
e = mid;
}
}
- return SearchResult<int, false>{s};
+ return {s};
}
// Returns the position of the first value whose key is not less than k using
@@ -792,7 +677,7 @@ class btree_node {
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>()) {
+ if (is_multi_container::value) {
MatchKind exact_match = MatchKind::kNe;
while (s != e) {
const int mid = (s + e) >> 1;
@@ -803,14 +688,14 @@ class btree_node {
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.
+ // which requires continuing the binary search if this is a
+ // multi-container.
exact_match = MatchKind::kEq;
}
}
}
return {s, exact_match};
- } else { // Can't have multiple equivalent keys.
+ } else { // Not a multi-container.
while (s != e) {
const int mid = (s + e) >> 1;
const absl::weak_ordering c = comp(key(mid), k);
@@ -831,10 +716,14 @@ class btree_node {
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);
+ // Removes the value at position i, shifting all existing values and children
+ // at positions > i to the left by 1.
+ void remove_value(int i, allocator_type *alloc);
+
+ // Removes the values at positions [i, i + to_erase), shifting all values
+ // after that range to the left by to_erase. Does not change children at all.
+ void remove_values_ignore_children(int i, int to_erase,
+ allocator_type *alloc);
// Rebalances a node with its right sibling.
void rebalance_right_to_left(int to_move, btree_node *right,
@@ -846,87 +735,75 @@ class btree_node {
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);
+ // delimiting key in the parent node onto itself.
+ void merge(btree_node *sibling, allocator_type *alloc);
+
+ // Swap the contents of "this" and "src".
+ void swap(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);
+ static btree_node *init_leaf(btree_node *n, btree_node *parent,
+ int max_count) {
+ n->set_parent(parent);
+ n->set_position(0);
+ n->set_start(0);
+ n->set_finish(0);
+ n->set_max_count(max_count);
absl::container_internal::SanitizerPoisonMemoryRegion(
- start_slot(), max_count * sizeof(slot_type));
+ n->start_slot(), max_count * sizeof(slot_type));
+ return n;
}
- void init_internal(btree_node *parent) {
- init_leaf(parent, kNodeSlots);
+ static btree_node *init_internal(btree_node *n, btree_node *parent) {
+ init_leaf(n, parent, kNodeValues);
// Set `max_count` to a sentinel value to indicate that this node is
// internal.
- set_max_count(kInternalNodeMaxCount);
+ n->set_max_count(kInternalNodeMaxCount);
absl::container_internal::SanitizerPoisonMemoryRegion(
- &mutable_child(start()), (kNodeSlots + 1) * sizeof(btree_node *));
+ &n->mutable_child(n->start()),
+ (kNodeValues + 1) * sizeof(btree_node *));
+ return n;
}
-
- static void deallocate(const size_type size, btree_node *node,
- allocator_type *alloc) {
- absl::container_internal::Deallocate<Alignment()>(alloc, node, size);
+ void destroy(allocator_type *alloc) {
+ for (int i = start(); i < finish(); ++i) {
+ value_destroy(i, alloc);
+ }
}
- // Deletes a node and all of its children.
- static void clear_and_delete(btree_node *node, allocator_type *alloc);
+ public:
+ // Exposed only for tests.
+ static bool testonly_uses_linear_node_search() {
+ return use_linear_search::value;
+ }
private:
template <typename... Args>
- void value_init(const field_type i, allocator_type *alloc, Args &&... args) {
+ void value_init(const size_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) {
+ void value_destroy(const size_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);
+ // Move n values starting at value i in this node into the values starting at
+ // value j in node x.
+ void uninitialized_move_n(const size_type n, const size_type i,
+ const size_type j, btree_node *x,
+ allocator_type *alloc) {
+ absl::container_internal::SanitizerUnpoisonMemoryRegion(
+ x->slot(j), n * sizeof(slot_type));
+ for (slot_type *src = slot(i), *end = src + n, *dest = x->slot(j);
src != end; ++src, ++dest) {
- transfer(dest, src, alloc);
+ params_type::construct(alloc, dest, src);
}
}
- // 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);
+ // Destroys a range of n values, starting at index i.
+ void value_destroy_n(const size_type i, const size_type n,
+ allocator_type *alloc) {
+ for (int j = 0; j < n; ++j) {
+ value_destroy(i + j, alloc);
}
}
@@ -943,7 +820,6 @@ struct btree_iterator {
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;
@@ -955,7 +831,7 @@ struct btree_iterator {
using slot_type = typename params_type::slot_type;
using iterator =
- btree_iterator<normal_node, normal_reference, normal_pointer>;
+ btree_iterator<normal_node, normal_reference, normal_pointer>;
using const_iterator =
btree_iterator<const_node, const_reference, const_pointer>;
@@ -972,19 +848,20 @@ struct btree_iterator {
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.
+ // const_iterator, but it specifically avoids defining copy constructors so
+ // that btree_iterator can be trivially copyable. This is for performance and
+ // binary size reasons.
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) {}
+ btree_iterator(const btree_iterator<N, R, P> &x) // NOLINT
+ : node(x.node), position(x.position) {}
private:
// This SFINAE allows explicit conversions from const_iterator to
- // iterator, but also avoids hiding the copy constructor.
+ // iterator, but also avoids defining a 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,
@@ -992,8 +869,8 @@ struct btree_iterator {
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) {}
+ explicit btree_iterator(const btree_iterator<N, R, P> &x)
+ : node(const_cast<node_type *>(x.node)), position(x.position) {}
// Increment/decrement the iterator.
void increment() {
@@ -1013,27 +890,16 @@ struct btree_iterator {
void decrement_slow();
public:
- bool operator==(const iterator &other) const {
- return node == other.node && position == other.position;
+ bool operator==(const const_iterator &x) const {
+ return node == x.node && position == x.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;
+ bool operator!=(const const_iterator &x) const {
+ return node != x.node || position != x.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*(); }
+ reference operator*() const { return node->value(position); }
+ pointer operator->() const { return &node->value(position); }
btree_iterator &operator++() {
increment();
@@ -1055,8 +921,6 @@ struct btree_iterator {
}
private:
- friend iterator;
- friend const_iterator;
template <typename Params>
friend class btree;
template <typename Tree>
@@ -1067,6 +931,8 @@ struct btree_iterator {
friend class btree_map_container;
template <typename Tree>
friend class btree_multiset_container;
+ template <typename N, typename R, typename P>
+ friend struct btree_iterator;
template <typename TreeType, typename CheckerType>
friend class base_checker;
@@ -1076,8 +942,7 @@ struct btree_iterator {
// 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.
+ // TODO(ezb): make this a field_type
int position;
};
@@ -1085,8 +950,6 @@ 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().
@@ -1121,9 +984,9 @@ class btree {
#endif
}
- enum : uint32_t {
- kNodeSlots = node_type::kNodeSlots,
- kMinNodeValues = kNodeSlots / 2,
+ enum {
+ kNodeValues = node_type::kNodeValues,
+ kMinNodeValues = kNodeValues / 2,
};
struct node_stats {
@@ -1131,9 +994,9 @@ class btree {
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;
+ node_stats &operator+=(const node_stats &x) {
+ leaf_nodes += x.leaf_nodes;
+ internal_nodes += x.internal_nodes;
return *this;
}
@@ -1147,15 +1010,13 @@ class btree {
using size_type = typename Params::size_type;
using difference_type = typename Params::difference_type;
using key_compare = typename Params::key_compare;
- using original_key_compare = typename Params::original_key_compare;
using value_compare = typename Params::value_compare;
using allocator_type = typename Params::allocator_type;
using reference = typename Params::reference;
using const_reference = typename Params::const_reference;
using pointer = typename Params::pointer;
using const_pointer = typename Params::const_pointer;
- using iterator =
- typename btree_iterator<node_type, reference, pointer>::iterator;
+ using iterator = btree_iterator<node_type, reference, pointer>;
using const_iterator = typename iterator::const_iterator;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
@@ -1167,46 +1028,28 @@ class btree {
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));
- }
+ const value_type &maybe_move_from_iterator(const_iterator x) { return *x; }
+ value_type &&maybe_move_from_iterator(iterator x) { return std::move(*x); }
// 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.
+ // x into this btree in their order in x. 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);
+ void copy_or_move_values_in_order(Btree *x);
// 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(const key_compare &comp, const allocator_type &alloc);
+
+ btree(const btree &x);
+ btree(btree &&x) noexcept
+ : root_(std::move(x.root_)),
+ rightmost_(absl::exchange(x.rightmost_, EmptyNode())),
+ size_(absl::exchange(x.size_, 0)) {
+ x.mutable_root() = EmptyNode();
}
~btree() {
@@ -1216,9 +1059,9 @@ class btree {
clear();
}
- // Assign the contents of other to *this.
- btree &operator=(const btree &other);
- btree &operator=(btree &&other) noexcept;
+ // Assign the contents of x to *this.
+ btree &operator=(const btree &x);
+ btree &operator=(btree &&x) noexcept;
iterator begin() { return iterator(leftmost()); }
const_iterator begin() const { return const_iterator(leftmost()); }
@@ -1235,22 +1078,17 @@ class btree {
return const_reverse_iterator(begin());
}
- // Finds the first element whose key is not less than `key`.
+ // 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);
+ return internal_end(internal_lower_bound(key));
}
template <typename K>
const_iterator lower_bound(const K &key) const {
- return internal_end(internal_lower_bound(key).value);
+ return internal_end(internal_lower_bound(key));
}
- // 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`.
+ // 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));
@@ -1261,21 +1099,23 @@ class btree {
}
// 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).
+ // the returned pair is equal to lower_bound(key). The second member pair of
+ // the pair is equal to upper_bound(key).
template <typename K>
- std::pair<iterator, iterator> equal_range(const K &key);
+ std::pair<iterator, iterator> equal_range(const K &key) {
+ return {lower_bound(key), upper_bound(key)};
+ }
template <typename K>
std::pair<const_iterator, const_iterator> equal_range(const K &key) const {
- return const_cast<btree *>(this)->equal_range(key);
+ return {lower_bound(key), upper_bound(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);
+ template <typename... Args>
+ std::pair<iterator, bool> insert_unique(const key_type &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
@@ -1283,23 +1123,14 @@ class btree {
// 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>
+ template <typename... Args>
std::pair<iterator, bool> insert_hint_unique(iterator position,
- const K &key,
+ const key_type &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);
+ void insert_iterator_unique(InputIterator b, InputIterator e);
// Inserts a value into the btree.
template <typename ValueType>
@@ -1332,8 +1163,18 @@ class btree {
// 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.
+ // Erases the specified key from the btree. Returns 1 if an element was
+ // erased and 0 otherwise.
+ template <typename K>
+ size_type erase_unique(const K &key);
+
+ // Erases all of the entries matching the specified key from the
+ // btree. Returns the number of elements erased.
+ template <typename K>
+ size_type erase_multi(const K &key);
+
+ // Finds the iterator corresponding to a key or returns end() if the key is
+ // not present.
template <typename K>
iterator find(const K &key) {
return internal_end(internal_find(key));
@@ -1343,23 +1184,38 @@ class btree {
return internal_end(internal_find(key));
}
+ // Returns a count of the number of times the key appears in the btree.
+ template <typename K>
+ size_type count_unique(const K &key) const {
+ const iterator begin = internal_find(key);
+ if (begin.node == nullptr) {
+ // The key doesn't exist in the tree.
+ return 0;
+ }
+ return 1;
+ }
+ // Returns a count of the number of times the key appears in the btree.
+ template <typename K>
+ size_type count_multi(const K &key) const {
+ const auto range = equal_range(key);
+ return std::distance(range.first, range.second);
+ }
+
// Clear the btree, deleting all of the values it contains.
void clear();
- // Swaps the contents of `this` and `other`.
- void swap(btree &other);
+ // Swap the contents of *this and x.
+ void swap(btree &x);
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));
+ template <typename K, typename LK>
+ bool compare_keys(const K &x, const LK &y) const {
+ return compare_internal::compare_result_as_less_than(key_comp()(x, y));
}
- value_compare value_comp() const {
- return value_compare(original_key_compare(key_comp()));
- }
+ value_compare value_comp() const { return value_compare(key_comp()); }
// Verifies the structure of the btree.
void verify() const;
@@ -1407,14 +1263,12 @@ class btree {
}
}
- // The average number of bytes used per value stored in the btree assuming
- // random insertion order.
+ // The average number of bytes used per value stored in the btree.
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;
+ // Returns the number of bytes per value on a leaf node that is 75%
+ // full. Experimentally, this matches up nicely with the computed number of
+ // bytes per value in trees that had their values inserted in random order.
+ return node_type::LeafSize() / (kNodeValues * 0.75);
}
// The fullness of the btree. Computed as the number of elements in the btree
@@ -1424,7 +1278,7 @@ class btree {
// Returns 0 for empty trees.
double fullness() const {
if (empty()) return 0.0;
- return static_cast<double>(size()) / (nodes() * kNodeSlots);
+ return static_cast<double>(size()) / (nodes() * kNodeValues);
}
// 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
@@ -1468,24 +1322,38 @@ class btree {
// 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 *p = allocate(node_type::InternalSize());
+ return node_type::init_internal(p, parent);
}
node_type *new_leaf_node(node_type *parent) {
- node_type *n = allocate(node_type::LeafSize());
- n->init_leaf(parent, kNodeSlots);
- return n;
+ node_type *p = allocate(node_type::LeafSize());
+ return node_type::init_leaf(p, parent, kNodeValues);
}
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;
+ node_type *p = allocate(node_type::LeafSize(max_count));
+ return node_type::init_leaf(p, p, max_count);
}
// Deletion helper routines.
+ void erase_same_node(iterator begin, iterator end);
+ iterator erase_from_leaf_node(iterator begin, size_type to_erase);
iterator rebalance_after_delete(iterator iter);
+ // Deallocates a node of a certain size in bytes using the allocator.
+ void deallocate(const size_type size, node_type *node) {
+ absl::container_internal::Deallocate<node_type::Alignment()>(
+ mutable_allocator(), node, size);
+ }
+
+ void delete_internal_node(node_type *node) {
+ node->destroy(mutable_allocator());
+ deallocate(node_type::InternalSize(), node);
+ }
+ void delete_leaf_node(node_type *node) {
+ node->destroy(mutable_allocator());
+ deallocate(node_type::LeafSize(node->max_count()), node);
+ }
+
// Rebalances or splits the node iter points to.
void rebalance_or_split(iterator *iter);
@@ -1523,19 +1391,28 @@ class btree {
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.
+ // reside in the tree. We provide 2 versions of internal_locate. The first
+ // version uses a less-than comparator and is incapable of distinguishing when
+ // there is an exact match. The second version is for the key-compare-to
+ // specialization and distinguishes exact matches. The key-compare-to
+ // specialization 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;
+ template <typename K>
+ SearchResult<iterator, false> internal_locate_impl(
+ const K &key, std::false_type /* IsCompareTo */) const;
+
+ template <typename K>
+ SearchResult<iterator, true> internal_locate_impl(
+ const K &key, std::true_type /* IsCompareTo */) const;
+
// Internal routine which implements lower_bound().
template <typename K>
- SearchResult<iterator, is_key_compare_to::value> internal_lower_bound(
- const K &key) const;
+ iterator internal_lower_bound(const K &key) const;
// Internal routine which implements upper_bound().
template <typename K>
@@ -1545,6 +1422,9 @@ class btree {
template <typename K>
iterator internal_find(const K &key) const;
+ // Deletes a node and all of its children.
+ void internal_clear(node_type *node);
+
// Verifies the tree structure of node.
int internal_verify(const node_type *node, const key_type *lo,
const key_type *hi) const;
@@ -1564,6 +1444,13 @@ class btree {
return res;
}
+ public:
+ // Exposed only for tests.
+ static bool testonly_uses_linear_node_search() {
+ return node_type::testonly_uses_linear_node_search();
+ }
+
+ private:
// 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,
@@ -1590,8 +1477,10 @@ inline void btree_node<P>::emplace_value(const size_type i,
// 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(finish(), alloc, slot(finish() - 1));
+ for (size_type j = finish() - 1; j > i; --j)
+ params_type::move(alloc, slot(j - 1), slot(j));
+ value_destroy(i, alloc);
}
value_init(i, alloc, std::forward<Args>(args)...);
set_finish(finish() + 1);
@@ -1605,27 +1494,24 @@ inline void btree_node<P>::emplace_value(const size_type i,
}
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);
+inline void btree_node<P>::remove_value(const int i, allocator_type *alloc) {
+ if (!leaf() && finish() > i + 1) {
+ assert(child(i + 1)->count() == 0);
+ for (size_type j = i + 1; j < finish(); ++j) {
+ set_child(j, child(j + 1));
}
+ clear_child(finish());
}
- set_finish(orig_finish - to_erase);
+
+ remove_values_ignore_children(i, /*to_erase=*/1, alloc);
+}
+
+template <typename P>
+inline void btree_node<P>::remove_values_ignore_children(
+ const int i, const int to_erase, allocator_type *alloc) {
+ params_type::move(alloc, slot(i + to_erase), finish_slot(), slot(i));
+ value_destroy_n(finish() - to_erase, to_erase, alloc);
+ set_finish(finish() - to_erase);
}
template <typename P>
@@ -1639,17 +1525,22 @@ void btree_node<P>::rebalance_right_to_left(const int to_move,
assert(to_move <= right->count());
// 1) Move the delimiting value in the parent to the left node.
- transfer(finish(), position(), parent(), alloc);
+ value_init(finish(), alloc, parent()->slot(position()));
// 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);
+ right->uninitialized_move_n(to_move - 1, right->start(), finish() + 1, this,
+ alloc);
// 3) Move the new delimiting value to the parent from the right node.
- parent()->transfer(position(), right->start() + to_move - 1, right, alloc);
+ params_type::move(alloc, right->slot(to_move - 1),
+ parent()->slot(position()));
- // 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);
+ // 4) Shift the values in the right node to their correct position.
+ params_type::move(alloc, right->slot(to_move), right->finish_slot(),
+ right->start_slot());
+
+ // 5) Destroy the now-empty to_move entries in the right node.
+ right->value_destroy_n(right->finish() - to_move, to_move, alloc);
if (!leaf()) {
// Move the child pointers from the right to the left node.
@@ -1684,19 +1575,54 @@ void btree_node<P>::rebalance_left_to_right(const int to_move,
// 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);
+ if (right->count() >= to_move) {
+ // The original location of the right->count() values are sufficient to hold
+ // the new to_move entries from the parent and left node.
+
+ // 1) Shift existing values in the right node to their correct positions.
+ right->uninitialized_move_n(to_move, right->finish() - to_move,
+ right->finish(), right, alloc);
+ for (slot_type *src = right->slot(right->finish() - to_move - 1),
+ *dest = right->slot(right->finish() - 1),
+ *end = right->start_slot();
+ src >= end; --src, --dest) {
+ params_type::move(alloc, src, dest);
+ }
+
+ // 2) Move the delimiting value in the parent to the right node.
+ params_type::move(alloc, parent()->slot(position()),
+ right->slot(to_move - 1));
+
+ // 3) Move the (to_move - 1) values from the left node to the right node.
+ params_type::move(alloc, slot(finish() - (to_move - 1)), finish_slot(),
+ right->start_slot());
+ } else {
+ // The right node does not have enough initialized space to hold the new
+ // to_move entries, so part of them will move to uninitialized space.
- // 2) Move the delimiting value in the parent to the right node.
- right->transfer(right->start() + to_move - 1, position(), parent(), alloc);
+ // 1) Shift existing values in the right node to their correct positions.
+ right->uninitialized_move_n(right->count(), right->start(),
+ right->start() + to_move, right, 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);
+ // 2) Move the delimiting value in the parent to the right node.
+ right->value_init(to_move - 1, alloc, parent()->slot(position()));
+
+ // 3) Move the (to_move - 1) values from the left node to the right node.
+ const size_type uninitialized_remaining = to_move - right->count() - 1;
+ uninitialized_move_n(uninitialized_remaining,
+ finish() - uninitialized_remaining, right->finish(),
+ right, alloc);
+ params_type::move(alloc, slot(finish() - (to_move - 1)),
+ slot(finish() - uninitialized_remaining),
+ right->start_slot());
+ }
// 4) Move the new delimiting value to the parent from the left node.
- parent()->transfer(position(), finish() - to_move, this, alloc);
+ params_type::move(alloc, slot(finish() - to_move),
+ parent()->slot(position()));
+
+ // 5) Destroy the now-empty to_move entries in the left node.
+ value_destroy_n(finish() - to_move, to_move, alloc);
if (!leaf()) {
// Move the child pointers from the left to the right node.
@@ -1719,7 +1645,7 @@ template <typename P>
void btree_node<P>::split(const int insert_position, btree_node *dest,
allocator_type *alloc) {
assert(dest->count() == 0);
- assert(max_count() == kNodeSlots);
+ assert(max_count() == kNodeValues);
// 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
@@ -1727,7 +1653,7 @@ void btree_node<P>::split(const int insert_position, btree_node *dest,
// 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) {
+ } else if (insert_position == kNodeValues) {
dest->set_finish(dest->start());
} else {
dest->set_finish(dest->start() + count() / 2);
@@ -1736,7 +1662,10 @@ void btree_node<P>::split(const int insert_position, btree_node *dest,
assert(count() >= 1);
// Move values from the left sibling to the right sibling.
- dest->transfer_n(dest->count(), dest->start(), finish(), this, alloc);
+ uninitialized_move_n(dest->count(), finish(), dest->start(), dest, alloc);
+
+ // Destroy the now-empty entries in the left node.
+ value_destroy_n(finish(), dest->count(), alloc);
// The split key is the largest value in the left sibling.
--mutable_finish();
@@ -1763,7 +1692,11 @@ void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
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);
+ src->uninitialized_move_n(src->count(), src->start(), finish() + 1, this,
+ alloc);
+
+ // Destroy the now-empty entries in the right node.
+ src->value_destroy_n(src->start(), src->count(), alloc);
if (!leaf()) {
// Move the child pointers from the right to the left node.
@@ -1777,59 +1710,56 @@ void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
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);
+ // Remove the value on the parent node.
+ parent()->remove_value(position(), 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;
+void btree_node<P>::swap(btree_node *x, allocator_type *alloc) {
+ using std::swap;
+ assert(leaf() == x->leaf());
+
+ // Determine which is the smaller/larger node.
+ btree_node *smaller = this, *larger = x;
+ if (smaller->count() > larger->count()) {
+ swap(smaller, larger);
}
- if (node->count() == 0) {
- deallocate(InternalSize(), node, alloc);
- return;
+
+ // Swap the values.
+ for (slot_type *a = smaller->start_slot(), *b = larger->start_slot(),
+ *end = smaller->finish_slot();
+ a != end; ++a, ++b) {
+ params_type::swap(alloc, a, b);
}
- // The parent of the root of the subtree we are deleting.
- btree_node *delete_root_parent = node->parent();
+ // Move values that can't be swapped.
+ const size_type to_move = larger->count() - smaller->count();
+ larger->uninitialized_move_n(to_move, smaller->finish(), smaller->finish(),
+ smaller, alloc);
+ larger->value_destroy_n(smaller->finish(), to_move, alloc);
- // 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());
+ if (!leaf()) {
+ // Swap the child pointers.
+ std::swap_ranges(&smaller->mutable_child(smaller->start()),
+ &smaller->mutable_child(smaller->finish() + 1),
+ &larger->mutable_child(larger->start()));
+ // Update swapped children's parent pointers.
+ int i = smaller->start();
+ int j = larger->start();
+ for (; i <= smaller->finish(); ++i, ++j) {
+ smaller->child(i)->set_parent(smaller);
+ larger->child(j)->set_parent(larger);
+ }
+ // Move the child pointers that couldn't be swapped.
+ for (; j <= larger->finish(); ++i, ++j) {
+ smaller->init_child(i, larger->child(j));
+ larger->clear_child(j);
+ }
}
+
+ // Swap the `finish`s.
+ // TODO(ezb): with floating storage, will also need to swap starts.
+ swap(mutable_finish(), x->mutable_finish());
}
////
@@ -1844,7 +1774,6 @@ void btree_iterator<N, R, P>::increment_slow() {
position = node->position();
node = node->parent();
}
- // TODO(ezb): assert we aren't incrementing end() instead of handling.
if (position == node->finish()) {
*this = save;
}
@@ -1868,7 +1797,6 @@ void btree_iterator<N, R, P>::decrement_slow() {
position = node->position() - 1;
node = node->parent();
}
- // TODO(ezb): assert we aren't decrementing begin() instead of handling.
if (position < node->start()) {
*this = save;
}
@@ -1886,7 +1814,7 @@ void btree_iterator<N, R, P>::decrement_slow() {
// btree methods
template <typename P>
template <typename Btree>
-void btree<P>::copy_or_move_values_in_order(Btree &other) {
+void btree<P>::copy_or_move_values_in_order(Btree *x) {
static_assert(std::is_same<btree, Btree>::value ||
std::is_same<const btree, Btree>::value,
"Btree type must be same or const.");
@@ -1894,11 +1822,11 @@ void btree<P>::copy_or_move_values_in_order(Btree &other) {
// 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;
+ auto iter = x->begin();
+ if (iter == x->end()) return;
insert_multi(maybe_move_from_iterator(iter));
++iter;
- for (; iter != other.end(); ++iter) {
+ for (; iter != x->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));
@@ -1917,7 +1845,7 @@ constexpr bool btree<P>::static_assert_validation() {
// 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))),
+ kNodeValues < (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.
@@ -1937,57 +1865,24 @@ constexpr bool btree<P>::static_assert_validation() {
}
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};
-}
+btree<P>::btree(const key_compare &comp, const allocator_type &alloc)
+ : root_(comp, alloc, EmptyNode()), rightmost_(EmptyNode()), size_(0) {}
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)};
+btree<P>::btree(const btree &x) : btree(x.key_comp(), x.allocator()) {
+ copy_or_move_values_in_order(&x);
}
template <typename P>
-template <typename K, typename... Args>
-auto btree<P>::insert_unique(const K &key, Args &&... args)
+template <typename... Args>
+auto btree<P>::insert_unique(const key_type &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;
+ auto res = internal_locate(key);
+ iterator &iter = res.value;
if (res.HasMatch()) {
if (res.IsEq()) {
@@ -2005,8 +1900,8 @@ auto btree<P>::insert_unique(const K &key, Args &&... args)
}
template <typename P>
-template <typename K, typename... Args>
-inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
+template <typename... Args>
+inline auto btree<P>::insert_hint_unique(iterator position, const key_type &key,
Args &&... args)
-> std::pair<iterator, bool> {
if (!empty()) {
@@ -2030,19 +1925,10 @@ inline auto btree<P>::insert_hint_unique(iterator position, const K &key,
}
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) {
+void btree<P>::insert_iterator_unique(InputIterator b, InputIterator e) {
for (; b != e; ++b) {
- init_type value(*b);
- insert_hint_unique(end(), params_type::key(value), std::move(value));
+ insert_hint_unique(end(), params_type::key(*b), *b);
}
}
@@ -2091,47 +1977,46 @@ void btree<P>::insert_iterator_multi(InputIterator b, InputIterator e) {
}
template <typename P>
-auto btree<P>::operator=(const btree &other) -> btree & {
- if (this != &other) {
+auto btree<P>::operator=(const btree &x) -> btree & {
+ if (this != &x) {
clear();
- *mutable_key_comp() = other.key_comp();
+ *mutable_key_comp() = x.key_comp();
if (absl::allocator_traits<
allocator_type>::propagate_on_container_copy_assignment::value) {
- *mutable_allocator() = other.allocator();
+ *mutable_allocator() = x.allocator();
}
- copy_or_move_values_in_order(other);
+ copy_or_move_values_in_order(&x);
}
return *this;
}
template <typename P>
-auto btree<P>::operator=(btree &&other) noexcept -> btree & {
- if (this != &other) {
+auto btree<P>::operator=(btree &&x) noexcept -> btree & {
+ if (this != &x) {
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_);
+ swap(root_, x.root_);
+ swap(rightmost_, x.rightmost_);
+ swap(size_, x.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_);
+ if (allocator() == x.allocator()) {
+ swap(mutable_root(), x.mutable_root());
+ swap(*mutable_key_comp(), *x.mutable_key_comp());
+ swap(rightmost_, x.rightmost_);
+ swap(size_, x.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);
+ // individually. We need both `x` and `this` to have `x`s key comparator
+ // while moving the values so we can't swap the key comparators.
+ *mutable_key_comp() = x.key_comp();
+ copy_or_move_values_in_order(&x);
}
}
}
@@ -2143,7 +2028,7 @@ 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()
+ // from our left child here, then delete that position (in remove_value()
// below). We can get to the largest value from our left child by
// decrementing iter.
iterator internal_iter(iter);
@@ -2155,7 +2040,7 @@ auto btree<P>::erase(iterator iter) -> iterator {
}
// Delete the key from the leaf.
- iter.node->remove_values(iter.position, /*to_erase=*/1, mutable_allocator());
+ iter.node->remove_value(iter.position, mutable_allocator());
--size_;
// We want to return the next value after the one we just erased. If we
@@ -2230,9 +2115,7 @@ auto btree<P>::erase_range(iterator begin, iterator end)
}
if (begin.node == end.node) {
- assert(end.position > begin.position);
- begin.node->remove_values(begin.position, end.position - begin.position,
- mutable_allocator());
+ erase_same_node(begin, end);
size_ -= count;
return {count, rebalance_after_delete(begin)};
}
@@ -2242,11 +2125,8 @@ auto btree<P>::erase_range(iterator begin, iterator end)
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);
+ begin = erase_from_leaf_node(
+ begin, (std::min)(remaining_to_erase, remaining_in_node));
} else {
begin = erase(begin);
}
@@ -2255,9 +2135,79 @@ auto btree<P>::erase_range(iterator begin, iterator end)
}
template <typename P>
+void btree<P>::erase_same_node(iterator begin, iterator end) {
+ assert(begin.node == end.node);
+ assert(end.position > begin.position);
+
+ node_type *node = begin.node;
+ size_type to_erase = end.position - begin.position;
+ if (!node->leaf()) {
+ // Delete all children between begin and end.
+ for (size_type i = 0; i < to_erase; ++i) {
+ internal_clear(node->child(begin.position + i + 1));
+ }
+ // Rotate children after end into new positions.
+ for (size_type i = begin.position + to_erase + 1; i <= node->finish();
+ ++i) {
+ node->set_child(i - to_erase, node->child(i));
+ node->clear_child(i);
+ }
+ }
+ node->remove_values_ignore_children(begin.position, to_erase,
+ mutable_allocator());
+
+ // Do not need to update rightmost_, because
+ // * either end == this->end(), and therefore node == rightmost_, and still
+ // exists
+ // * or end != this->end(), and therefore rightmost_ hasn't been erased, since
+ // it wasn't covered in [begin, end)
+}
+
+template <typename P>
+auto btree<P>::erase_from_leaf_node(iterator begin, size_type to_erase)
+ -> iterator {
+ node_type *node = begin.node;
+ assert(node->leaf());
+ assert(node->finish() > begin.position);
+ assert(begin.position + to_erase <= node->finish());
+
+ node->remove_values_ignore_children(begin.position, to_erase,
+ mutable_allocator());
+
+ size_ -= to_erase;
+
+ return rebalance_after_delete(begin);
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::erase_unique(const K &key) -> size_type {
+ const iterator iter = internal_find(key);
+ if (iter.node == nullptr) {
+ // The key doesn't exist in the tree, return nothing done.
+ return 0;
+ }
+ erase(iter);
+ return 1;
+}
+
+template <typename P>
+template <typename K>
+auto btree<P>::erase_multi(const K &key) -> size_type {
+ const iterator begin = internal_lower_bound(key);
+ if (begin.node == nullptr) {
+ // The key doesn't exist in the tree, return nothing done.
+ return 0;
+ }
+ // Delete all of the keys between begin and upper_bound(key).
+ const iterator end = internal_end(internal_upper_bound(key));
+ return erase_range(begin, end).first;
+}
+
+template <typename P>
void btree<P>::clear() {
if (!empty()) {
- node_type::clear_and_delete(root(), mutable_allocator());
+ internal_clear(root());
}
mutable_root() = EmptyNode();
rightmost_ = EmptyNode();
@@ -2265,20 +2215,20 @@ void btree<P>::clear() {
}
template <typename P>
-void btree<P>::swap(btree &other) {
+void btree<P>::swap(btree &x) {
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_);
+ swap(root_, x.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());
+ assert(allocator() == x.allocator());
+ swap(mutable_root(), x.mutable_root());
+ swap(*mutable_key_comp(), *x.mutable_key_comp());
}
- swap(rightmost_, other.rightmost_);
- swap(size_, other.size_);
+ swap(rightmost_, x.rightmost_);
+ swap(size_, x.size_);
}
template <typename P>
@@ -2298,7 +2248,7 @@ 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());
+ assert(kNodeValues == node->max_count());
// First try to make room on the node by rebalancing.
node_type *parent = node->parent();
@@ -2306,17 +2256,17 @@ void btree<P>::rebalance_or_split(iterator *iter) {
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) {
+ assert(left->max_count() == kNodeValues);
+ if (left->count() < kNodeValues) {
// 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)));
+ int to_move = (kNodeValues - left->count()) /
+ (1 + (insert_position < kNodeValues));
to_move = (std::max)(1, to_move);
if (insert_position - to_move >= node->start() ||
- left->count() + to_move < static_cast<int>(kNodeSlots)) {
+ left->count() + to_move < kNodeValues) {
left->rebalance_right_to_left(to_move, node, mutable_allocator());
assert(node->max_count() - node->count() == to_move);
@@ -2335,17 +2285,17 @@ void btree<P>::rebalance_or_split(iterator *iter) {
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) {
+ assert(right->max_count() == kNodeValues);
+ if (right->count() < kNodeValues) {
// 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()) /
+ int to_move = (kNodeValues - 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)) {
+ right->count() + to_move < kNodeValues) {
node->rebalance_left_to_right(to_move, right, mutable_allocator());
if (insert_position > node->finish()) {
@@ -2361,8 +2311,8 @@ void btree<P>::rebalance_or_split(iterator *iter) {
// Rebalancing failed, make sure there is room on the parent node for a new
// value.
- assert(parent->max_count() == kNodeSlots);
- if (parent->count() == kNodeSlots) {
+ assert(parent->max_count() == kNodeValues);
+ if (parent->count() == kNodeValues) {
iterator parent_iter(node->parent(), node->position());
rebalance_or_split(&parent_iter);
}
@@ -2398,7 +2348,12 @@ void btree<P>::rebalance_or_split(iterator *iter) {
template <typename P>
void btree<P>::merge_nodes(node_type *left, node_type *right) {
left->merge(right, mutable_allocator());
- if (rightmost_ == right) rightmost_ = left;
+ if (right->leaf()) {
+ if (rightmost_ == right) rightmost_ = left;
+ delete_leaf_node(right);
+ } else {
+ delete_internal_node(right);
+ }
}
template <typename P>
@@ -2407,8 +2362,8 @@ bool btree<P>::try_merge_or_rebalance(iterator *iter) {
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) {
+ assert(left->max_count() == kNodeValues);
+ if (1 + left->count() + iter->node->count() <= kNodeValues) {
iter->position += 1 + left->count();
merge_nodes(left, iter->node);
iter->node = left;
@@ -2418,8 +2373,8 @@ bool btree<P>::try_merge_or_rebalance(iterator *iter) {
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) {
+ assert(right->max_count() == kNodeValues);
+ if (1 + iter->node->count() + right->count() <= kNodeValues) {
merge_nodes(iter->node, right);
return true;
}
@@ -2455,20 +2410,21 @@ bool btree<P>::try_merge_or_rebalance(iterator *iter) {
template <typename P>
void btree<P>::try_shrink() {
- node_type *orig_root = root();
- if (orig_root->count() > 0) {
+ if (root()->count() > 0) {
return;
}
// Deleted the last item on the root node, shrink the height of the tree.
- if (orig_root->leaf()) {
+ if (root()->leaf()) {
assert(size() == 0);
- mutable_root() = rightmost_ = EmptyNode();
+ delete_leaf_node(root());
+ mutable_root() = EmptyNode();
+ rightmost_ = EmptyNode();
} else {
- node_type *child = orig_root->start_child();
+ node_type *child = root()->start_child();
child->make_root();
+ delete_internal_node(root());
mutable_root() = child;
}
- node_type::clear_and_delete(orig_root, mutable_allocator());
}
template <typename P>
@@ -2496,30 +2452,25 @@ inline auto btree<P>::internal_emplace(iterator iter, Args &&... args)
--iter;
++iter.position;
}
- const field_type max_count = iter.node->max_count();
- allocator_type *alloc = mutable_allocator();
+ const int max_count = iter.node->max_count();
if (iter.node->count() == max_count) {
// Make room in the leaf for the new item.
- if (max_count < kNodeSlots) {
+ if (max_count < kNodeValues) {
// 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;
+ new_leaf_root_node((std::min<int>)(kNodeValues, 2 * max_count));
+ iter.node->swap(root(), mutable_allocator());
+ delete_leaf_node(root());
+ mutable_root() = iter.node;
+ rightmost_ = iter.node;
} else {
rebalance_or_split(&iter);
}
}
- iter.node->emplace_value(iter.position, alloc, std::forward<Args>(args)...);
+ iter.node->emplace_value(iter.position, mutable_allocator(),
+ std::forward<Args>(args)...);
++size_;
return iter;
}
@@ -2528,51 +2479,61 @@ template <typename P>
template <typename K>
inline auto btree<P>::internal_locate(const K &key) const
-> SearchResult<iterator, is_key_compare_to::value> {
+ return internal_locate_impl(key, is_key_compare_to());
+}
+
+template <typename P>
+template <typename K>
+inline auto btree<P>::internal_locate_impl(
+ const K &key, std::false_type /* IsCompareTo */) const
+ -> SearchResult<iterator, false> {
+ iterator iter(const_cast<node_type *>(root()));
+ for (;;) {
+ iter.position = iter.node->lower_bound(key, key_comp()).value;
+ // NOTE: 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);
+ }
+ return {iter};
+}
+
+template <typename P>
+template <typename K>
+inline auto btree<P>::internal_locate_impl(
+ const K &key, std::true_type /* IsCompareTo */) const
+ -> SearchResult<iterator, true> {
iterator iter(const_cast<node_type *>(root()));
for (;;) {
- SearchResult<int, is_key_compare_to::value> res =
- iter.node->lower_bound(key, key_comp());
+ SearchResult<int, true> res = iter.node->lower_bound(key, key_comp());
iter.position = res.value;
- if (res.IsEq()) {
+ if (res.match == MatchKind::kEq) {
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;
- }
+auto btree<P>::internal_lower_bound(const K &key) const -> iterator {
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;
+ iter.position = iter.node->lower_bound(key, key_comp()).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};
+ return internal_last(iter);
}
template <typename P>
@@ -2592,7 +2553,7 @@ auto btree<P>::internal_upper_bound(const K &key) const -> iterator {
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);
+ auto res = internal_locate(key);
if (res.HasMatch()) {
if (res.IsEq()) {
return res.value;
@@ -2607,6 +2568,18 @@ auto btree<P>::internal_find(const K &key) const -> iterator {
}
template <typename P>
+void btree<P>::internal_clear(node_type *node) {
+ if (!node->leaf()) {
+ for (int i = node->start(); i <= node->finish(); ++i) {
+ internal_clear(node->child(i));
+ }
+ delete_internal_node(node);
+ } else {
+ delete_leaf_node(node);
+ }
+}
+
+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);
diff --git a/third_party/abseil-cpp/absl/container/internal/btree_container.h b/third_party/abseil-cpp/absl/container/internal/btree_container.h
index a99668c713..f2e4c3a535 100644
--- a/third_party/abseil-cpp/absl/container/internal/btree_container.h
+++ b/third_party/abseil-cpp/absl/container/internal/btree_container.h
@@ -20,11 +20,9 @@
#include <iterator>
#include <utility>
-#include "absl/base/attributes.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/container/internal/btree.h" // IWYU pragma: export
#include "absl/container/internal/common.h"
-#include "absl/memory/memory.h"
#include "absl/meta/type_traits.h"
namespace absl {
@@ -52,7 +50,7 @@ class btree_container {
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
using difference_type = typename Tree::difference_type;
- using key_compare = typename Tree::original_key_compare;
+ using 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;
@@ -70,23 +68,10 @@ class btree_container {
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(
+ btree_container(const btree_container &x) = default;
+ btree_container(btree_container &&x) noexcept = default;
+ btree_container &operator=(const btree_container &x) = default;
+ btree_container &operator=(btree_container &&x) noexcept(
std::is_nothrow_move_assignable<Tree>::value) = default;
// Iterator routines.
@@ -105,11 +90,6 @@ class btree_container {
// 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);
}
@@ -158,11 +138,6 @@ class btree_container {
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) {
@@ -176,9 +151,10 @@ class btree_container {
return extract(iterator(position));
}
+ public:
// Utility routines.
- ABSL_ATTRIBUTE_REINITIALIZES void clear() { tree_.clear(); }
- void swap(btree_container &other) { tree_.swap(other.tree_); }
+ void clear() { tree_.clear(); }
+ void swap(btree_container &x) { tree_.swap(x.tree_); }
void verify() const { tree_.verify(); }
// Size routines.
@@ -215,7 +191,7 @@ class btree_container {
allocator_type get_allocator() const { return tree_.get_allocator(); }
// The key comparator used by the btree.
- key_compare key_comp() const { return key_compare(tree_.key_comp()); }
+ key_compare key_comp() const { return tree_.key_comp(); }
value_compare value_comp() const { return tree_.value_comp(); }
// Support absl::Hash.
@@ -248,7 +224,7 @@ class btree_set_container : public btree_container<Tree> {
using key_type = typename Tree::key_type;
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
- using key_compare = typename Tree::original_key_compare;
+ using 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;
@@ -259,7 +235,7 @@ class btree_set_container : public btree_container<Tree> {
using super_type::super_type;
btree_set_container() {}
- // Range constructors.
+ // Range constructor.
template <class InputIterator>
btree_set_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
@@ -267,55 +243,56 @@ class btree_set_container : public btree_container<Tree> {
: 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.
+ // Initializer list constructor.
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) {}
+
+ // Lookup routines.
+ template <typename K = key_type>
+ size_type count(const key_arg<K> &key) const {
+ return this->tree_.count_unique(key);
+ }
// 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(const value_type &x) {
+ return this->tree_.insert_unique(params_type::key(x), x);
}
- std::pair<iterator, bool> insert(value_type &&v) {
- return this->tree_.insert_unique(params_type::key(v), std::move(v));
+ std::pair<iterator, bool> insert(value_type &&x) {
+ return this->tree_.insert_unique(params_type::key(x), std::move(x));
}
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) {
+ iterator insert(const_iterator position, const value_type &x) {
return this->tree_
- .insert_hint_unique(iterator(hint), params_type::key(v), v)
+ .insert_hint_unique(iterator(position), params_type::key(x), x)
.first;
}
- iterator insert(const_iterator hint, value_type &&v) {
+ iterator insert(const_iterator position, value_type &&x) {
return this->tree_
- .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
+ .insert_hint_unique(iterator(position), params_type::key(x),
+ std::move(x))
.first;
}
template <typename... Args>
- iterator emplace_hint(const_iterator hint, Args &&... args) {
+ iterator emplace_hint(const_iterator position, Args &&... args) {
init_type v(std::forward<Args>(args)...);
return this->tree_
- .insert_hint_unique(iterator(hint), params_type::key(v), std::move(v))
+ .insert_hint_unique(iterator(position), 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);
+ this->tree_.insert_iterator_unique(b, e);
}
void insert(std::initializer_list<init_type> init) {
- this->tree_.insert_iterator_unique(init.begin(), init.end(), 0);
+ this->tree_.insert_iterator_unique(init.begin(), init.end());
}
insert_return_type insert(node_type &&node) {
if (!node) return {this->end(), false, node_type()};
@@ -338,13 +315,18 @@ class btree_set_container : public btree_container<Tree> {
return res.first;
}
+ // Deletion routines.
+ template <typename K = key_type>
+ size_type erase(const key_arg<K> &key) {
+ return this->tree_.erase_unique(key);
+ }
+ using super_type::erase;
+
// 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();
+ auto it = this->find(key);
+ return it == this->end() ? node_type() : extract(it);
}
using super_type::extract;
@@ -362,7 +344,7 @@ class btree_set_container : public btree_container<Tree> {
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) {
+ if (insert(std::move(*src_it)).second) {
src_it = src.erase(src_it);
} else {
++src_it;
@@ -389,7 +371,6 @@ 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>
@@ -399,7 +380,7 @@ class btree_map_container : public btree_set_container<Tree> {
using key_type = typename Tree::key_type;
using mapped_type = typename params_type::mapped_type;
using value_type = typename Tree::value_type;
- using key_compare = typename Tree::original_key_compare;
+ using 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;
@@ -411,72 +392,111 @@ class btree_map_container : public btree_set_container<Tree> {
// 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);
+ // 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 M>
+ std::pair<iterator, bool> insert_or_assign(const key_type &k, const M &obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_unique(k, k, obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret;
}
- 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 <class M, key_type * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_type &&k, const M &obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, std::move(k), obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret;
}
- 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 <class M, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(const key_type &k, M &&obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, k, std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret;
}
- 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 <class M, key_type * = nullptr, M * = nullptr>
+ std::pair<iterator, bool> insert_or_assign(key_type &&k, M &&obj) {
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_unique(k, std::move(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret;
}
- template <typename K = key_type, class M>
- iterator insert_or_assign(const_iterator hint, const key_arg<K> &k,
+ template <class M>
+ iterator insert_or_assign(const_iterator position, const key_type &k,
const M &obj) {
- return insert_or_assign_hint_impl(hint, k, obj);
+ const std::pair<iterator, bool> ret =
+ this->tree_.insert_hint_unique(iterator(position), k, k, obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret.first;
}
- 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 <class M, key_type * = nullptr>
+ iterator insert_or_assign(const_iterator position, key_type &&k,
+ const M &obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, std::move(k), obj);
+ if (!ret.second) ret.first->second = obj;
+ return ret.first;
}
- 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 <class M, M * = nullptr>
+ iterator insert_or_assign(const_iterator position, const key_type &k,
+ M &&obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, k, std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret.first;
}
- 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 <class M, key_type * = nullptr, M * = nullptr>
+ iterator insert_or_assign(const_iterator position, key_type &&k, M &&obj) {
+ const std::pair<iterator, bool> ret = this->tree_.insert_hint_unique(
+ iterator(position), k, std::move(k), std::forward<M>(obj));
+ if (!ret.second) ret.first->second = std::forward<M>(obj);
+ return ret.first;
}
-
- 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... Args>
+ std::pair<iterator, bool> try_emplace(const key_type &k, Args &&... args) {
+ return this->tree_.insert_unique(
+ k, std::piecewise_construct, std::forward_as_tuple(k),
+ std::forward_as_tuple(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... Args>
+ std::pair<iterator, bool> try_emplace(key_type &&k, Args &&... args) {
+ // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
+ // and then using `k` unsequenced. This is safe because the move is into a
+ // forwarding reference and insert_unique guarantees that `key` is never
+ // referenced after consuming `args`.
+ const key_type &key_ref = k;
+ return this->tree_.insert_unique(
+ key_ref, std::piecewise_construct, std::forward_as_tuple(std::move(k)),
+ std::forward_as_tuple(std::forward<Args>(args)...));
}
- template <typename K = key_type, typename... Args>
- iterator try_emplace(const_iterator hint, const key_arg<K> &k,
+ template <typename... Args>
+ iterator try_emplace(const_iterator hint, const key_type &k,
Args &&... args) {
- return try_emplace_hint_impl(hint, k, std::forward<Args>(args)...);
+ return this->tree_
+ .insert_hint_unique(iterator(hint), k, std::piecewise_construct,
+ std::forward_as_tuple(k),
+ std::forward_as_tuple(std::forward<Args>(args)...))
+ .first;
}
- 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... Args>
+ iterator try_emplace(const_iterator hint, key_type &&k, Args &&... args) {
+ // Note: `key_ref` exists to avoid a ClangTidy warning about moving from `k`
+ // and then using `k` unsequenced. This is safe because the move is into a
+ // forwarding reference and insert_hint_unique guarantees that `key` is
+ // never referenced after consuming `args`.
+ const key_type &key_ref = k;
+ return this->tree_
+ .insert_hint_unique(iterator(hint), key_ref, std::piecewise_construct,
+ std::forward_as_tuple(std::move(k)),
+ std::forward_as_tuple(std::forward<Args>(args)...))
+ .first;
}
-
- template <typename K = key_type>
- mapped_type &operator[](const key_arg<K> &k) {
+ mapped_type &operator[](const key_type &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;
+ mapped_type &operator[](key_type &&k) {
+ return try_emplace(std::move(k)).first->second;
}
template <typename K = key_type>
@@ -493,40 +513,6 @@ class btree_map_container : public btree_set_container<Tree> {
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.
@@ -544,7 +530,7 @@ class btree_multiset_container : public btree_container<Tree> {
using key_type = typename Tree::key_type;
using value_type = typename Tree::value_type;
using size_type = typename Tree::size_type;
- using key_compare = typename Tree::original_key_compare;
+ using 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;
@@ -554,7 +540,7 @@ class btree_multiset_container : public btree_container<Tree> {
using super_type::super_type;
btree_multiset_container() {}
- // Range constructors.
+ // Range constructor.
template <class InputIterator>
btree_multiset_container(InputIterator b, InputIterator e,
const key_compare &comp = key_compare(),
@@ -562,30 +548,29 @@ class btree_multiset_container : public btree_container<Tree> {
: 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.
+ // Initializer list constructor.
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) {}
+
+ // Lookup routines.
+ template <typename K = key_type>
+ size_type count(const key_arg<K> &key) const {
+ return this->tree_.count_multi(key);
+ }
// 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 value_type &x) { return this->tree_.insert_multi(x); }
+ iterator insert(value_type &&x) {
+ return this->tree_.insert_multi(std::move(x));
}
- iterator insert(const_iterator hint, const value_type &v) {
- return this->tree_.insert_hint_multi(iterator(hint), v);
+ iterator insert(const_iterator position, const value_type &x) {
+ return this->tree_.insert_hint_multi(iterator(position), x);
}
- iterator insert(const_iterator hint, value_type &&v) {
- return this->tree_.insert_hint_multi(iterator(hint), std::move(v));
+ iterator insert(const_iterator position, value_type &&x) {
+ return this->tree_.insert_hint_multi(iterator(position), std::move(x));
}
template <typename InputIterator>
void insert(InputIterator b, InputIterator e) {
@@ -599,9 +584,9 @@ class btree_multiset_container : public btree_container<Tree> {
return this->tree_.insert_multi(init_type(std::forward<Args>(args)...));
}
template <typename... Args>
- iterator emplace_hint(const_iterator hint, Args &&... args) {
+ iterator emplace_hint(const_iterator position, Args &&... args) {
return this->tree_.insert_hint_multi(
- iterator(hint), init_type(std::forward<Args>(args)...));
+ iterator(position), init_type(std::forward<Args>(args)...));
}
iterator insert(node_type &&node) {
if (!node) return this->end();
@@ -620,13 +605,18 @@ class btree_multiset_container : public btree_container<Tree> {
return res;
}
+ // Deletion routines.
+ template <typename K = key_type>
+ size_type erase(const key_arg<K> &key) {
+ return this->tree_.erase_multi(key);
+ }
+ using super_type::erase;
+
// 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();
+ auto it = this->find(key);
+ return it == this->end() ? node_type() : extract(it);
}
using super_type::extract;
@@ -642,9 +632,8 @@ class btree_multiset_container : public btree_container<Tree> {
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())));
- }
+ insert(std::make_move_iterator(src.begin()),
+ std::make_move_iterator(src.end()));
src.clear();
}
diff --git a/third_party/abseil-cpp/absl/container/internal/common.h b/third_party/abseil-cpp/absl/container/internal/common.h
index 030e9d4ab0..5037d80316 100644
--- a/third_party/abseil-cpp/absl/container/internal/common.h
+++ b/third_party/abseil-cpp/absl/container/internal/common.h
@@ -138,7 +138,6 @@ 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;
@@ -146,11 +145,8 @@ class node_handle<Policy, PolicyTraits, Alloc,
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());
+ auto key() const -> decltype(PolicyTraits::key(this->slot())) {
+ return PolicyTraits::key(this->slot());
}
mapped_type& mapped() const {
diff --git a/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h b/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h
index 5ebe164942..4bfe92fd99 100644
--- a/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h
+++ b/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h
@@ -169,33 +169,9 @@ constexpr bool ShouldAnyUseBase() {
}
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> {};
+using TupleMoveConstructible = typename std::conditional<
+ std::is_reference<T>::value, std::is_convertible<V, T>,
+ std::is_constructible<T, V&&>>::type;
} // namespace internal_compressed_tuple
@@ -241,23 +217,22 @@ class ABSL_INTERNAL_COMPRESSED_TUPLE_DECLSPEC CompressedTuple
explicit constexpr CompressedTuple(const Ts&... base)
: CompressedTuple::CompressedTupleImpl(absl::in_place, base...) {}
- template <typename First, typename... Vs,
+ template <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,
+ void(absl::decay_t<Vs>...)>>,
+ internal_compressed_tuple::TupleMoveConstructible<
+ Ts, Vs&&>...>::value,
bool> = true>
- explicit constexpr CompressedTuple(First&& first, Vs&&... base)
+ explicit constexpr CompressedTuple(Vs&&... base)
: CompressedTuple::CompressedTupleImpl(absl::in_place,
- absl::forward<First>(first),
absl::forward<Vs>(base)...) {}
template <int I>
ElemT<I>& get() & {
- return StorageT<I>::get();
+ return internal_compressed_tuple::Storage<ElemT<I>, I>::get();
}
template <int I>
diff --git a/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc b/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
index 62a7483ee3..1dae12db81 100644
--- a/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/compressed_tuple_test.cc
@@ -277,11 +277,11 @@ TEST(CompressedTupleTest, Nested) {
TEST(CompressedTupleTest, Reference) {
int i = 7;
- std::string s = "Very long string that goes in the heap";
+ std::string s = "Very long std::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 string that goes in the heap");
+ EXPECT_EQ(s, "Very long std::string that goes in the heap");
EXPECT_EQ(x.get<0>(), x.get<1>());
EXPECT_NE(&x.get<0>(), &x.get<1>());
diff --git a/third_party/abseil-cpp/absl/container/internal/container_memory.h b/third_party/abseil-cpp/absl/container/internal/container_memory.h
index e67529ecb6..d24b0f8413 100644
--- a/third_party/abseil-cpp/absl/container/internal/container_memory.h
+++ b/third_party/abseil-cpp/absl/container/internal/container_memory.h
@@ -15,34 +15,28 @@
#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.
//
@@ -54,14 +48,11 @@ template <size_t Alignment, class Alloc>
void* Allocate(Alloc* alloc, size_t n) {
static_assert(Alignment > 0, "");
assert(n && "n must be positive");
- using M = AlignedType<Alignment>;
+ struct alignas(Alignment) M {};
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<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));
+ A mem_alloc(*alloc);
+ void* p = AT::allocate(mem_alloc, (n + sizeof(M) - 1) / sizeof(M));
assert(reinterpret_cast<uintptr_t>(p) % Alignment == 0 &&
"allocator does not respect alignment");
return p;
@@ -73,14 +64,11 @@ 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");
- using M = AlignedType<Alignment>;
+ struct alignas(Alignment) M {};
using A = typename absl::allocator_traits<Alloc>::template rebind_alloc<M>;
using AT = typename absl::allocator_traits<Alloc>::template rebind_traits<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);
- AT::deallocate(my_mem_alloc, static_cast<M*>(p),
+ A mem_alloc(*alloc);
+ AT::deallocate(mem_alloc, static_cast<M*>(p),
(n + sizeof(M) - 1) / sizeof(M));
}
@@ -217,10 +205,10 @@ DecomposeValue(F&& f, Arg&& arg) {
// Helper functions for asan and msan.
inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
ASAN_POISON_MEMORY_REGION(m, s);
#endif
-#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#ifdef MEMORY_SANITIZER
__msan_poison(m, s);
#endif
(void)m;
@@ -228,10 +216,10 @@ inline void SanitizerPoisonMemoryRegion(const void* m, size_t s) {
}
inline void SanitizerUnpoisonMemoryRegion(const void* m, size_t s) {
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
ASAN_UNPOISON_MEMORY_REGION(m, s);
#endif
-#ifdef ABSL_HAVE_MEMORY_SANITIZER
+#ifdef MEMORY_SANITIZER
__msan_unpoison(m, s);
#endif
(void)m;
@@ -258,8 +246,8 @@ namespace memory_internal {
// type, which is non-portable.
template <class Pair, class = std::true_type>
struct OffsetOf {
- static constexpr size_t kFirst = static_cast<size_t>(-1);
- static constexpr size_t kSecond = static_cast<size_t>(-1);
+ static constexpr size_t kFirst = -1;
+ static constexpr size_t kSecond = -1;
};
template <class Pair>
@@ -328,12 +316,11 @@ 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>>;
+ using mutable_value_type = std::pair<K, V>;
value_type value;
mutable_value_type mutable_value;
- absl::remove_const_t<K> key;
+ K key;
};
template <class K, class V>
@@ -359,20 +346,6 @@ struct map_slot_policy {
return slot->value;
}
- // 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;
}
@@ -451,6 +424,13 @@ struct map_slot_policy {
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
diff --git a/third_party/abseil-cpp/absl/container/internal/container_memory_test.cc b/third_party/abseil-cpp/absl/container/internal/container_memory_test.cc
index fb9c4ddede..7942c7be48 100644
--- a/third_party/abseil-cpp/absl/container/internal/container_memory_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/container_memory_test.cc
@@ -16,13 +16,10 @@
#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 {
@@ -30,11 +27,6 @@ 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) {
@@ -53,39 +45,6 @@ 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>;
@@ -166,7 +125,7 @@ TryDecomposeValue(F&& f, Arg&& arg) {
}
TEST(DecomposeValue, Decomposable) {
- auto f = [](const int& x, int&& y) { // NOLINT
+ auto f = [](const int& x, int&& y) {
EXPECT_EQ(&x, &y);
EXPECT_EQ(42, x);
return 'A';
@@ -200,8 +159,7 @@ TryDecomposePair(F&& f, Args&&... args) {
}
TEST(DecomposePair, Decomposable) {
- auto f = [](const int& x, // NOLINT
- std::piecewise_construct_t, std::tuple<int&&> k,
+ auto f = [](const int& x, std::piecewise_construct_t, std::tuple<int&&> k,
std::tuple<double>&& v) {
EXPECT_EQ(&x, &std::get<0>(k));
EXPECT_EQ(42, x);
@@ -226,31 +184,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/container/internal/counting_allocator.h b/third_party/abseil-cpp/absl/container/internal/counting_allocator.h
index 927cf08255..9efdc66213 100644
--- a/third_party/abseil-cpp/absl/container/internal/counting_allocator.h
+++ b/third_party/abseil-cpp/absl/container/internal/counting_allocator.h
@@ -15,6 +15,7 @@
#ifndef ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
#define ABSL_CONTAINER_INTERNAL_COUNTING_ALLOCATOR_H_
+#include <cassert>
#include <cstdint>
#include <memory>
@@ -30,63 +31,33 @@ namespace container_internal {
// containers - that chain of allocators uses the same state and is
// thus easier to query for aggregate allocation information.
template <typename T>
-class CountingAllocator {
+class CountingAllocator : public std::allocator<T> {
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;
+ using Alloc = std::allocator<T>;
+ using pointer = typename Alloc::pointer;
+ using size_type = typename Alloc::size_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) {}
+ CountingAllocator() : bytes_used_(nullptr) {}
+ explicit CountingAllocator(int64_t* b) : bytes_used_(b) {}
template <typename U>
CountingAllocator(const CountingAllocator<U>& x)
- : bytes_used_(x.bytes_used_), instance_count_(x.instance_count_) {}
+ : Alloc(x), bytes_used_(x.bytes_used_) {}
- 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;
+ 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) {
- Allocator allocator;
- AllocatorTraits::deallocate(allocator, p, n);
- if (bytes_used_ != nullptr) {
- *bytes_used_ -= n * sizeof(T);
- }
+ Alloc::deallocate(p, n);
+ assert(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>
+ template<typename U>
class rebind {
public:
using other = CountingAllocator<U>;
@@ -94,8 +65,7 @@ class CountingAllocator {
friend bool operator==(const CountingAllocator& a,
const CountingAllocator& b) {
- return a.bytes_used_ == b.bytes_used_ &&
- a.instance_count_ == b.instance_count_;
+ return a.bytes_used_ == b.bytes_used_;
}
friend bool operator!=(const CountingAllocator& a,
@@ -103,8 +73,7 @@ class CountingAllocator {
return !(a == b);
}
- int64_t* bytes_used_ = nullptr;
- int64_t* instance_count_ = nullptr;
+ int64_t* bytes_used_;
};
} // namespace container_internal
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h b/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h
index 250e662c9d..401ddf4d83 100644
--- a/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h
+++ b/third_party/abseil-cpp/absl/container/internal/hash_function_defaults.h
@@ -53,7 +53,6 @@
#include "absl/base/config.h"
#include "absl/hash/hash.h"
-#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
namespace absl {
@@ -73,39 +72,23 @@ 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);
- }
-};
-
-struct StringEq {
- using is_transparent = void;
- 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;
- }
};
// Supports heterogeneous lookup for string-like elements.
struct StringHashEq {
using Hash = StringHash;
- using Eq = StringEq;
+ struct Eq {
+ using is_transparent = void;
+ bool operator()(absl::string_view lhs, absl::string_view 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>
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc b/third_party/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
index 59576b8ede..2eefc7e0de 100644
--- a/third_party/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hash_function_defaults_test.cc
@@ -19,9 +19,6 @@
#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 {
@@ -206,91 +203,10 @@ TYPED_TEST(HashPointer, Works) {
EXPECT_NE(hash(&dummy), hash(cuptr));
}
-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).
+// with (std::string, absl::string_view, const char*).
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, absl::Cord>,
- std::pair<absl::string_view, absl::Cord>,
std::pair<absl::string_view, std::string>,
std::pair<absl::string_view, absl::string_view>,
@@ -337,11 +253,11 @@ ABSL_NAMESPACE_END
} // namespace absl
enum Hash : size_t {
- kStd = 0x1, // std::hash
+ kStd = 0x2, // std::hash
#ifdef _MSC_VER
kExtension = kStd, // In MSVC, std::hash == ::hash
#else // _MSC_VER
- kExtension = 0x2, // ::hash (GCC extension)
+ kExtension = 0x4, // ::hash (GCC extension)
#endif // _MSC_VER
};
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.cc b/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.cc
index 59cc5aac7a..75c4db6c36 100644
--- a/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.cc
@@ -41,10 +41,8 @@ class RandomDeviceSeedSeq {
} // namespace
std::mt19937_64* GetSharedRng() {
- static auto* rng = [] {
- RandomDeviceSeedSeq seed_seq;
- return new std::mt19937_64(seed_seq);
- }();
+ RandomDeviceSeedSeq seed_seq;
+ static auto* rng = new std::mt19937_64(seed_seq);
return rng;
}
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.h b/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.h
index f1f555a5c1..6869fe45e8 100644
--- a/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.h
+++ b/third_party/abseil-cpp/absl/container/internal/hash_generator_testing.h
@@ -21,13 +21,11 @@
#include <stdint.h>
#include <algorithm>
-#include <cassert>
#include <iosfwd>
#include <random>
#include <tuple>
#include <type_traits>
#include <utility>
-#include <vector>
#include "absl/container/internal/hash_policy_testing.h"
#include "absl/memory/memory.h"
@@ -155,25 +153,6 @@ using GeneratedType = decltype(
typename Container::value_type,
typename Container::key_type>::type>&>()());
-// Naive wrapper that performs a linear search of previous values.
-// Beware this is O(SQR), which is reasonable for smaller kMaxValues.
-template <class T, size_t kMaxValues = 64, class E = void>
-struct UniqueGenerator {
- Generator<T, E> gen;
- std::vector<T> values;
-
- T operator()() {
- assert(values.size() < kMaxValues);
- for (;;) {
- T value = gen();
- if (std::find(values.begin(), values.end(), value) == values.end()) {
- values.push_back(value);
- return value;
- }
- }
- }
-};
-
} // namespace hash_internal
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h b/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h
index 46c97b18a2..3e1209c6eb 100644
--- a/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h
+++ b/third_party/abseil-cpp/absl/container/internal/hash_policy_traits.h
@@ -17,7 +17,6 @@
#include <cstddef>
#include <memory>
-#include <new>
#include <type_traits>
#include <utility>
@@ -30,34 +29,15 @@ 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 {
- // 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);
- }
-
+ // We return `Key` here.
// 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>
- auto operator()(Key&& k, const Args&...) const
- -> decltype(Impl(std::forward<Key>(k), 0)) {
- return Impl(std::forward<Key>(k), 0);
+ Key operator()(Key&& k, const Args&...) const {
+ return std::forward<Key>(k);
}
};
@@ -72,6 +52,9 @@ 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.
@@ -173,7 +156,7 @@ struct hash_policy_traits {
// Returns the "key" portion of the slot.
// Used for node handle manipulation.
template <class P = Policy>
- static auto mutable_key(slot_type* slot)
+ static auto key(slot_type* slot)
-> decltype(P::apply(ReturnKey(), element(slot))) {
return P::apply(ReturnKey(), element(slot));
}
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
index 40cce0479e..5644725178 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.cc
@@ -21,11 +21,10 @@
#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/profiling/internal/exponential_biased.h"
-#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/mutex.h"
namespace absl {
@@ -38,9 +37,10 @@ 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::profiling_internal::ExponentialBiased
+ABSL_PER_THREAD_TLS_KEYWORD absl::base_internal::ExponentialBiased
g_exponential_biased_generator;
#endif
@@ -50,14 +50,16 @@ ABSL_PER_THREAD_TLS_KEYWORD absl::profiling_internal::ExponentialBiased
ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample = 0;
#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
-HashtablezSampler& GlobalHashtablezSampler() {
+HashtablezSampler& HashtablezSampler::Global() {
static auto* sampler = new HashtablezSampler();
return *sampler;
}
-// TODO(bradleybear): The comments at this constructors declaration say that the
-// fields are not initialized, but this definition does initialize the fields.
-// Something needs to be cleaned up.
+HashtablezSampler::DisposeCallback HashtablezSampler::SetDisposeCallback(
+ DisposeCallback f) {
+ return dispose_.exchange(f, std::memory_order_relaxed);
+}
+
HashtablezInfo::HashtablezInfo() { PrepareForSampling(); }
HashtablezInfo::~HashtablezInfo() = default;
@@ -65,13 +67,10 @@ 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);
- max_reserve.store(0, std::memory_order_relaxed);
create_time = absl::Now();
// The inliner makes hardcoded skip_count difficult (especially when combined
@@ -79,6 +78,93 @@ void HashtablezInfo::PrepareForSampling() {
// 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() {
@@ -93,20 +179,16 @@ static bool ShouldForceSampling() {
if (ABSL_PREDICT_TRUE(state == kDontForce)) return false;
if (state == kUninitialized) {
- state = ABSL_INTERNAL_C_SYMBOL(AbslContainerInternalSampleEverything)()
- ? kForce
- : kDontForce;
+ state = AbslContainerInternalSampleEverything() ? kForce : kDontForce;
global_state.store(state, std::memory_order_relaxed);
}
return state == kForce;
}
-HashtablezInfo* SampleSlow(int64_t* next_sample, size_t inline_element_size) {
+HashtablezInfo* SampleSlow(int64_t* next_sample) {
if (ABSL_PREDICT_FALSE(ShouldForceSampling())) {
*next_sample = 1;
- HashtablezInfo* result = GlobalHashtablezSampler().Register();
- result->inline_element_size = inline_element_size;
- return result;
+ return HashtablezSampler::Global().Register();
}
#if !defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
@@ -128,17 +210,15 @@ HashtablezInfo* SampleSlow(int64_t* next_sample, size_t inline_element_size) {
// that case.
if (first) {
if (ABSL_PREDICT_TRUE(--*next_sample > 0)) return nullptr;
- return SampleSlow(next_sample, inline_element_size);
+ return SampleSlow(next_sample);
}
- HashtablezInfo* result = GlobalHashtablezSampler().Register();
- result->inline_element_size = inline_element_size;
- return result;
+ return HashtablezSampler::Global().Register();
#endif
}
void UnsampleSlow(HashtablezInfo* info) {
- GlobalHashtablezSampler().Unregister(info);
+ HashtablezSampler::Global().Unregister(info);
}
void RecordInsertSlow(HashtablezInfo* info, size_t hash,
@@ -146,7 +226,7 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
// 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
+#if SWISSTABLE_HAVE_SSE2
probe_length /= 16;
#else
probe_length /= 8;
@@ -154,7 +234,6 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
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),
@@ -178,7 +257,7 @@ void SetHashtablezSampleParameter(int32_t rate) {
void SetHashtablezMaxSamples(int32_t max) {
if (max > 0) {
- GlobalHashtablezSampler().SetMaxSamples(max);
+ 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)
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
index 91fcdb34a3..34d5e5723c 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler.h
@@ -47,7 +47,6 @@
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/optimization.h"
#include "absl/container/internal/have_sse.h"
-#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/mutex.h"
#include "absl/utility/utility.h"
@@ -58,7 +57,7 @@ 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 : public profiling_internal::Sample<HashtablezInfo> {
+struct HashtablezInfo {
// Constructs the object but does not fill in any fields.
HashtablezInfo();
~HashtablezInfo();
@@ -74,13 +73,18 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
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;
- std::atomic<size_t> max_reserve;
+
+ // `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.
@@ -91,34 +95,16 @@ struct HashtablezInfo : public profiling_internal::Sample<HashtablezInfo> {
absl::Time create_time;
int32_t depth;
void* stack[kMaxStackDepth];
- size_t inline_element_size;
};
inline void RecordRehashSlow(HashtablezInfo* info, size_t total_probe_length) {
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_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 RecordReservationSlow(HashtablezInfo* info,
- size_t target_capacity) {
- info->max_reserve.store(
- (std::max)(info->max_reserve.load(std::memory_order_relaxed),
- target_capacity),
- std::memory_order_relaxed);
-}
-
-inline void RecordClearedReservationSlow(HashtablezInfo* info) {
- info->max_reserve.store(0, std::memory_order_relaxed);
}
inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
@@ -127,8 +113,7 @@ inline void RecordStorageChangedSlow(HashtablezInfo* info, size_t size,
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);
+ RecordRehashSlow(info, 0);
}
}
@@ -137,21 +122,12 @@ void RecordInsertSlow(HashtablezInfo* info, size_t hash,
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);
+ info->num_erases.fetch_add(1, std::memory_order_relaxed);
}
-HashtablezInfo* SampleSlow(int64_t* next_sample, size_t inline_element_size);
+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) {}
@@ -184,16 +160,6 @@ class HashtablezInfoHandle {
RecordRehashSlow(info_, total_probe_length);
}
- inline void RecordReservation(size_t target_capacity) {
- if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
- RecordReservationSlow(info_, target_capacity);
- }
-
- inline void RecordClearedReservation() {
- if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
- RecordClearedReservationSlow(info_);
- }
-
inline void RecordInsert(size_t hash, size_t distance_from_desired) {
if (ABSL_PREDICT_TRUE(info_ == nullptr)) return;
RecordInsertSlow(info_, hash, distance_from_desired);
@@ -213,50 +179,100 @@ class HashtablezInfoHandle {
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 RecordReservation(size_t /*target_capacity*/) {}
- inline void RecordClearedReservation() {}
- inline void RecordInsert(size_t /*hash*/, size_t /*distance_from_desired*/) {}
- inline void RecordErase() {}
-
- friend inline void swap(HashtablezInfoHandle& /*lhs*/,
- HashtablezInfoHandle& /*rhs*/) {}
-};
+
+#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#error ABSL_INTERNAL_HASHTABLEZ_SAMPLE cannot be directly set
#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#if (ABSL_PER_THREAD_TLS == 1) && !defined(ABSL_BUILD_DLL) && \
+ !defined(ABSL_CONSUME_DLL)
+#define ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+#endif
+
#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
extern ABSL_PER_THREAD_TLS_KEYWORD int64_t global_next_sample;
-#endif // defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#endif // ABSL_PER_THREAD_TLS
// Returns an RAII sampling handle that manages registration and unregistation
// with the global sampler.
-inline HashtablezInfoHandle Sample(
- size_t inline_element_size ABSL_ATTRIBUTE_UNUSED) {
+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, inline_element_size));
+ return HashtablezInfoHandle(SampleSlow(&global_next_sample));
#else
return HashtablezInfoHandle(nullptr);
#endif // !ABSL_PER_THREAD_TLS
}
-using HashtablezSampler =
- ::absl::profiling_internal::SampleRecorder<HashtablezInfo>;
+// 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);
-// Returns a global Sampler.
-HashtablezSampler& GlobalHashtablezSampler();
+ // 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);
@@ -272,7 +288,7 @@ void SetHashtablezMaxSamples(int32_t max);
// 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)();
+extern "C" bool AbslContainerInternalSampleEverything();
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
index ed35a7eec3..78b9d362ac 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_force_weak_definition.cc
@@ -21,8 +21,7 @@ ABSL_NAMESPACE_BEGIN
namespace container_internal {
// See hashtablez_sampler.h for details.
-extern "C" ABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(
- AbslContainerInternalSampleEverything)() {
+extern "C" ABSL_ATTRIBUTE_WEAK bool AbslContainerInternalSampleEverything() {
return false;
}
diff --git a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
index 449619a32c..36f5ccdd02 100644
--- a/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/hashtablez_sampler_test.cc
@@ -22,7 +22,6 @@
#include "gtest/gtest.h"
#include "absl/base/attributes.h"
#include "absl/container/internal/have_sse.h"
-#include "absl/profiling/internal/sample_recorder.h"
#include "absl/synchronization/blocking_counter.h"
#include "absl/synchronization/internal/thread_pool.h"
#include "absl/synchronization/mutex.h"
@@ -30,7 +29,7 @@
#include "absl/time/clock.h"
#include "absl/time/time.h"
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_HAVE_SSE2
constexpr int kProbeLength = 16;
#else
constexpr int kProbeLength = 8;
@@ -39,7 +38,6 @@ constexpr int kProbeLength = 8;
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
class HashtablezInfoHandlePeer {
public:
static bool IsSampled(const HashtablezInfoHandle& h) {
@@ -48,13 +46,6 @@ class HashtablezInfoHandlePeer {
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;
@@ -78,24 +69,18 @@ HashtablezInfo* Register(HashtablezSampler* s, size_t size) {
TEST(HashtablezInfoTest, PrepareForSampling) {
absl::Time test_start = absl::Now();
- const size_t test_element_size = 17;
HashtablezInfo info;
absl::MutexLock l(&info.init_mu);
info.PrepareForSampling();
- info.inline_element_size = test_element_size;
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_EQ(info.max_reserve.load(), 0);
EXPECT_GE(info.create_time, test_start);
- EXPECT_EQ(info.inline_element_size, test_element_size);
info.capacity.store(1, std::memory_order_relaxed);
info.size.store(1, std::memory_order_relaxed);
@@ -104,22 +89,16 @@ TEST(HashtablezInfoTest, PrepareForSampling) {
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.max_reserve.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_EQ(info.max_reserve.load(), 0);
- EXPECT_EQ(info.inline_element_size, test_element_size);
EXPECT_GE(info.create_time, test_start);
}
@@ -144,25 +123,20 @@ TEST(HashtablezInfoTest, RecordInsert) {
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) {
- const size_t test_element_size = 29;
HashtablezInfo info;
absl::MutexLock l(&info.init_mu);
info.PrepareForSampling();
- info.inline_element_size = test_element_size;
EXPECT_EQ(info.num_erases.load(), 0);
EXPECT_EQ(info.size.load(), 0);
RecordInsertSlow(&info, 0x0000FF00, 6 * kProbeLength);
@@ -170,15 +144,12 @@ TEST(HashtablezInfoTest, RecordErase) {
RecordEraseSlow(&info);
EXPECT_EQ(info.size.load(), 0);
EXPECT_EQ(info.num_erases.load(), 1);
- EXPECT_EQ(info.inline_element_size, test_element_size);
}
TEST(HashtablezInfoTest, RecordRehash) {
- const size_t test_element_size = 31;
HashtablezInfo info;
absl::MutexLock l(&info.init_mu);
info.PrepareForSampling();
- info.inline_element_size = test_element_size;
RecordInsertSlow(&info, 0x1, 0);
RecordInsertSlow(&info, 0x2, kProbeLength);
RecordInsertSlow(&info, 0x4, kProbeLength);
@@ -196,35 +167,16 @@ TEST(HashtablezInfoTest, RecordRehash) {
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);
- EXPECT_EQ(info.inline_element_size, test_element_size);
-}
-
-TEST(HashtablezInfoTest, RecordReservation) {
- HashtablezInfo info;
- absl::MutexLock l(&info.init_mu);
- info.PrepareForSampling();
- RecordReservationSlow(&info, 3);
- EXPECT_EQ(info.max_reserve.load(), 3);
-
- RecordReservationSlow(&info, 2);
- // High watermark does not change
- EXPECT_EQ(info.max_reserve.load(), 3);
-
- RecordReservationSlow(&info, 10);
- // High watermark does change
- EXPECT_EQ(info.max_reserve.load(), 10);
}
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_HASHTABLEZ_SAMPLE)
TEST(HashtablezSamplerTest, SmallSampleParameter) {
- const size_t test_element_size = 31;
SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100);
for (int i = 0; i < 1000; ++i) {
int64_t next_sample = 0;
- HashtablezInfo* sample = SampleSlow(&next_sample, test_element_size);
+ HashtablezInfo* sample = SampleSlow(&next_sample);
EXPECT_GT(next_sample, 0);
EXPECT_NE(sample, nullptr);
UnsampleSlow(sample);
@@ -232,13 +184,12 @@ TEST(HashtablezSamplerTest, SmallSampleParameter) {
}
TEST(HashtablezSamplerTest, LargeSampleParameter) {
- const size_t test_element_size = 31;
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, test_element_size);
+ HashtablezInfo* sample = SampleSlow(&next_sample);
EXPECT_GT(next_sample, 0);
EXPECT_NE(sample, nullptr);
UnsampleSlow(sample);
@@ -246,14 +197,13 @@ TEST(HashtablezSamplerTest, LargeSampleParameter) {
}
TEST(HashtablezSamplerTest, Sample) {
- const size_t test_element_size = 31;
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(test_element_size);
+ HashtablezInfoHandle h = Sample();
++total;
if (HashtablezInfoHandlePeer::IsSampled(h)) {
++num_sampled;
@@ -263,9 +213,10 @@ TEST(HashtablezSamplerTest, Sample) {
}
EXPECT_NEAR(sample_rate, 0.01, 0.005);
}
+#endif
TEST(HashtablezSamplerTest, Handle) {
- auto& sampler = GlobalHashtablezSampler();
+ auto& sampler = HashtablezSampler::Global();
HashtablezInfoHandle h(sampler.Register());
auto* info = HashtablezInfoHandlePeer::GetInfo(&h);
info->hashes_bitwise_and.store(0x12345678, std::memory_order_relaxed);
@@ -292,8 +243,6 @@ TEST(HashtablezSamplerTest, Handle) {
});
EXPECT_FALSE(found);
}
-#endif
-
TEST(HashtablezSamplerTest, Registration) {
HashtablezSampler sampler;
diff --git a/third_party/abseil-cpp/absl/container/internal/have_sse.h b/third_party/abseil-cpp/absl/container/internal/have_sse.h
index e75e1a16d3..43414418db 100644
--- a/third_party/abseil-cpp/absl/container/internal/have_sse.h
+++ b/third_party/abseil-cpp/absl/container/internal/have_sse.h
@@ -16,34 +16,33 @@
#ifndef ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
#define ABSL_CONTAINER_INTERNAL_HAVE_SSE_H_
-#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#ifndef SWISSTABLE_HAVE_SSE2
#if defined(__SSE2__) || \
(defined(_MSC_VER) && \
(defined(_M_X64) || (defined(_M_IX86) && _M_IX86_FP >= 2)))
-#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 1
+#define SWISSTABLE_HAVE_SSE2 1
#else
-#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2 0
+#define SWISSTABLE_HAVE_SSE2 0
#endif
#endif
-#ifndef ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
+#ifndef SWISSTABLE_HAVE_SSSE3
#ifdef __SSSE3__
-#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 1
+#define SWISSTABLE_HAVE_SSSE3 1
#else
-#define ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 0
+#define SWISSTABLE_HAVE_SSSE3 0
#endif
#endif
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3 && \
- !ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_HAVE_SSSE3 && !SWISSTABLE_HAVE_SSE2
#error "Bad configuration!"
#endif
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_HAVE_SSE2
#include <emmintrin.h>
#endif
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
+#if SWISSTABLE_HAVE_SSSE3
#include <tmmintrin.h>
#endif
diff --git a/third_party/abseil-cpp/absl/container/internal/inlined_vector.h b/third_party/abseil-cpp/absl/container/internal/inlined_vector.h
index 1d7d6cda72..4d80b727bf 100644
--- a/third_party/abseil-cpp/absl/container/internal/inlined_vector.h
+++ b/third_party/abseil-cpp/absl/container/internal/inlined_vector.h
@@ -21,11 +21,8 @@
#include <iterator>
#include <limits>
#include <memory>
-#include <new>
-#include <type_traits>
#include <utility>
-#include "absl/base/attributes.h"
#include "absl/base/macros.h"
#include "absl/container/internal/compressed_tuple.h"
#include "absl/memory/memory.h"
@@ -36,135 +33,96 @@ 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 "-Warray-bounds"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
-#endif
-
-template <typename A>
-using AllocatorTraits = std::allocator_traits<A>;
-template <typename A>
-using ValueType = typename AllocatorTraits<A>::value_type;
-template <typename A>
-using SizeType = typename AllocatorTraits<A>::size_type;
-template <typename A>
-using Pointer = typename AllocatorTraits<A>::pointer;
-template <typename A>
-using ConstPointer = typename AllocatorTraits<A>::const_pointer;
-template <typename A>
-using SizeType = typename AllocatorTraits<A>::size_type;
-template <typename A>
-using DifferenceType = typename AllocatorTraits<A>::difference_type;
-template <typename A>
-using Reference = ValueType<A>&;
-template <typename A>
-using ConstReference = const ValueType<A>&;
-template <typename A>
-using Iterator = Pointer<A>;
-template <typename A>
-using ConstIterator = ConstPointer<A>;
-template <typename A>
-using ReverseIterator = typename std::reverse_iterator<Iterator<A>>;
-template <typename A>
-using ConstReverseIterator = typename std::reverse_iterator<ConstIterator<A>>;
-template <typename A>
-using MoveIterator = typename std::move_iterator<Iterator<A>>;
-
template <typename Iterator>
using IsAtLeastForwardIterator = std::is_convertible<
typename std::iterator_traits<Iterator>::iterator_category,
std::forward_iterator_tag>;
-template <typename A>
+template <typename AllocatorType,
+ typename ValueType =
+ typename absl::allocator_traits<AllocatorType>::value_type>
using IsMemcpyOk =
- absl::conjunction<std::is_same<A, std::allocator<ValueType<A>>>,
- absl::is_trivially_copy_constructible<ValueType<A>>,
- absl::is_trivially_copy_assignable<ValueType<A>>,
- absl::is_trivially_destructible<ValueType<A>>>;
-
-template <typename T>
-struct TypeIdentity {
- using type = T;
-};
+ 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>>;
-// Used for function arguments in template functions to prevent ADL by forcing
-// callers to explicitly specify the template parameter.
-template <typename T>
-using NoTypeDeduction = typename TypeIdentity<T>::type;
+template <typename AllocatorType, typename Pointer, typename SizeType>
+void DestroyElements(AllocatorType* alloc_ptr, Pointer destroy_first,
+ SizeType destroy_size) {
+ using AllocatorTraits = absl::allocator_traits<AllocatorType>;
-template <typename A>
-void DestroyElements(NoTypeDeduction<A>& allocator, Pointer<A> destroy_first,
- SizeType<A> destroy_size) {
if (destroy_first != nullptr) {
- for (SizeType<A> i = destroy_size; i != 0;) {
+ for (auto i = destroy_size; i != 0;) {
--i;
- AllocatorTraits<A>::destroy(allocator, destroy_first + i);
+ AllocatorTraits::destroy(*alloc_ptr, destroy_first + i);
}
- }
-}
-
-template <typename A>
-struct Allocation {
- Pointer<A> data;
- SizeType<A> capacity;
-};
-template <typename A,
- bool IsOverAligned =
- (alignof(ValueType<A>) > ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT)>
-struct MallocAdapter {
- static Allocation<A> Allocate(A& allocator, SizeType<A> requested_capacity) {
- return {AllocatorTraits<A>::allocate(allocator, requested_capacity),
- requested_capacity};
- }
-
- static void Deallocate(A& allocator, Pointer<A> pointer,
- SizeType<A> capacity) {
- AllocatorTraits<A>::deallocate(allocator, pointer, capacity);
+#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)
}
-};
+}
-template <typename A, typename ValueAdapter>
-void ConstructElements(NoTypeDeduction<A>& allocator,
- Pointer<A> construct_first, ValueAdapter& values,
- SizeType<A> construct_size) {
- for (SizeType<A> i = 0; i < construct_size; ++i) {
- ABSL_INTERNAL_TRY { values.ConstructNext(allocator, construct_first + i); }
+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 {
- DestroyElements<A>(allocator, construct_first, i);
+ inlined_vector_internal::DestroyElements(alloc_ptr, construct_first, i);
ABSL_INTERNAL_RETHROW;
}
}
}
-template <typename A, typename ValueAdapter>
-void AssignElements(Pointer<A> assign_first, ValueAdapter& values,
- SizeType<A> assign_size) {
- for (SizeType<A> i = 0; i < assign_size; ++i) {
- values.AssignNext(assign_first + i);
+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 A>
+template <typename AllocatorType>
struct StorageView {
- Pointer<A> data;
- SizeType<A> size;
- SizeType<A> capacity;
+ 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 A, typename Iterator>
+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(A& allocator, Pointer<A> construct_at) {
- AllocatorTraits<A>::construct(allocator, construct_at, *it_);
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at, *it_);
++it_;
}
- void AssignNext(Pointer<A> assign_at) {
+ void AssignNext(Pointer assign_at) {
*assign_at = *it_;
++it_;
}
@@ -173,123 +131,166 @@ class IteratorValueAdapter {
Iterator it_;
};
-template <typename A>
+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(ConstPointer<A> p) : ptr_(p) {}
+ explicit CopyValueAdapter(const ValueType& v) : ptr_(std::addressof(v)) {}
- void ConstructNext(A& allocator, Pointer<A> construct_at) {
- AllocatorTraits<A>::construct(allocator, construct_at, *ptr_);
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at, *ptr_);
}
- void AssignNext(Pointer<A> assign_at) { *assign_at = *ptr_; }
+ void AssignNext(Pointer assign_at) { *assign_at = *ptr_; }
private:
- ConstPointer<A> ptr_;
+ ConstPointer ptr_;
};
-template <typename A>
+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(A& allocator, Pointer<A> construct_at) {
- AllocatorTraits<A>::construct(allocator, construct_at);
+ void ConstructNext(AllocatorType* alloc_ptr, Pointer construct_at) {
+ AllocatorTraits::construct(*alloc_ptr, construct_at);
}
- void AssignNext(Pointer<A> assign_at) { *assign_at = ValueType<A>(); }
+ void AssignNext(Pointer assign_at) { *assign_at = ValueType(); }
};
-template <typename A>
+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(A& allocator)
- : allocator_data_(allocator, nullptr), capacity_(0) {}
+ explicit AllocationTransaction(AllocatorType* alloc_ptr)
+ : alloc_data_(*alloc_ptr, nullptr) {}
~AllocationTransaction() {
if (DidAllocate()) {
- MallocAdapter<A>::Deallocate(GetAllocator(), GetData(), GetCapacity());
+ AllocatorTraits::deallocate(GetAllocator(), GetData(), GetCapacity());
}
}
AllocationTransaction(const AllocationTransaction&) = delete;
void operator=(const AllocationTransaction&) = delete;
- A& GetAllocator() { return allocator_data_.template get<0>(); }
- Pointer<A>& GetData() { return allocator_data_.template get<1>(); }
- SizeType<A>& GetCapacity() { return capacity_; }
+ 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<A> Allocate(SizeType<A> requested_capacity) {
- Allocation<A> result =
- MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
- GetData() = result.data;
- GetCapacity() = result.capacity;
- return result.data;
- }
-
- ABSL_MUST_USE_RESULT Allocation<A> Release() && {
- Allocation<A> result = {GetData(), GetCapacity()};
- Reset();
- return result;
+ Pointer Allocate(SizeType capacity) {
+ GetData() = AllocatorTraits::allocate(GetAllocator(), capacity);
+ GetCapacity() = capacity;
+ return GetData();
}
- private:
void Reset() {
GetData() = nullptr;
GetCapacity() = 0;
}
- container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;
- SizeType<A> capacity_;
+ private:
+ container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+ SizeType capacity_ = 0;
};
-template <typename A>
+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(A& allocator)
- : allocator_data_(allocator, nullptr), size_(0) {}
+ explicit ConstructionTransaction(AllocatorType* alloc_ptr)
+ : alloc_data_(*alloc_ptr, nullptr) {}
~ConstructionTransaction() {
if (DidConstruct()) {
- DestroyElements<A>(GetAllocator(), GetData(), GetSize());
+ inlined_vector_internal::DestroyElements(std::addressof(GetAllocator()),
+ GetData(), GetSize());
}
}
ConstructionTransaction(const ConstructionTransaction&) = delete;
void operator=(const ConstructionTransaction&) = delete;
- A& GetAllocator() { return allocator_data_.template get<0>(); }
- Pointer<A>& GetData() { return allocator_data_.template get<1>(); }
- SizeType<A>& GetSize() { return size_; }
+ 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<A> data, ValueAdapter& values, SizeType<A> size) {
- ConstructElements<A>(GetAllocator(), data, values, size);
+ 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() && {
+ void Commit() {
GetData() = nullptr;
GetSize() = 0;
}
private:
- container_internal::CompressedTuple<A, Pointer<A>> allocator_data_;
- SizeType<A> size_;
+ container_internal::CompressedTuple<AllocatorType, Pointer> alloc_data_;
+ SizeType size_ = 0;
};
template <typename T, size_t N, typename A>
class Storage {
public:
- static SizeType<A> NextCapacity(SizeType<A> current_capacity) {
+ 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 SizeType<A> ComputeCapacity(SizeType<A> current_capacity,
- SizeType<A> requested_capacity) {
+ static size_type ComputeCapacity(size_type current_capacity,
+ size_type requested_capacity) {
return (std::max)(NextCapacity(current_capacity), requested_capacity);
}
@@ -297,137 +298,140 @@ class Storage {
// Storage Constructors and Destructor
// ---------------------------------------------------------------------------
- Storage() : metadata_(A(), /* size and is_allocated */ 0) {}
+ Storage() : metadata_() {}
- explicit Storage(const A& allocator)
- : metadata_(allocator, /* size and is_allocated */ 0) {}
+ explicit Storage(const allocator_type& alloc) : metadata_(alloc, {}) {}
~Storage() {
- if (GetSizeAndIsAllocated() == 0) {
- // Empty and not allocated; nothing to do.
- } else if (IsMemcpyOk<A>::value) {
- // No destructors need to be run; just deallocate if necessary.
- DeallocateIfAllocated();
- } else {
- DestroyContents();
- }
+ pointer data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), data, GetSize());
+ DeallocateIfAllocated();
}
// ---------------------------------------------------------------------------
// Storage Member Accessors
// ---------------------------------------------------------------------------
- SizeType<A>& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
+ size_type& GetSizeAndIsAllocated() { return metadata_.template get<1>(); }
- const SizeType<A>& GetSizeAndIsAllocated() const {
+ const size_type& GetSizeAndIsAllocated() const {
return metadata_.template get<1>();
}
- SizeType<A> GetSize() const { return GetSizeAndIsAllocated() >> 1; }
+ size_type GetSize() const { return GetSizeAndIsAllocated() >> 1; }
bool GetIsAllocated() const { return GetSizeAndIsAllocated() & 1; }
- Pointer<A> GetAllocatedData() { return data_.allocated.allocated_data; }
+ pointer GetAllocatedData() { return data_.allocated.allocated_data; }
- ConstPointer<A> GetAllocatedData() const {
+ const_pointer GetAllocatedData() const {
return data_.allocated.allocated_data;
}
- Pointer<A> GetInlinedData() {
- return reinterpret_cast<Pointer<A>>(
+ pointer GetInlinedData() {
+ return reinterpret_cast<pointer>(
std::addressof(data_.inlined.inlined_data[0]));
}
- ConstPointer<A> GetInlinedData() const {
- return reinterpret_cast<ConstPointer<A>>(
+ const_pointer GetInlinedData() const {
+ return reinterpret_cast<const_pointer>(
std::addressof(data_.inlined.inlined_data[0]));
}
- SizeType<A> GetAllocatedCapacity() const {
+ size_type GetAllocatedCapacity() const {
return data_.allocated.allocated_capacity;
}
- SizeType<A> GetInlinedCapacity() const { return static_cast<SizeType<A>>(N); }
+ size_type GetInlinedCapacity() const { return static_cast<size_type>(N); }
- StorageView<A> MakeStorageView() {
- return GetIsAllocated() ? StorageView<A>{GetAllocatedData(), GetSize(),
- GetAllocatedCapacity()}
- : StorageView<A>{GetInlinedData(), GetSize(),
- GetInlinedCapacity()};
+ StorageView MakeStorageView() {
+ return GetIsAllocated()
+ ? StorageView{GetAllocatedData(), GetSize(),
+ GetAllocatedCapacity()}
+ : StorageView{GetInlinedData(), GetSize(), GetInlinedCapacity()};
}
- A& GetAllocator() { return metadata_.template get<0>(); }
+ allocator_type* GetAllocPtr() {
+ return std::addressof(metadata_.template get<0>());
+ }
- const A& GetAllocator() const { return 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, SizeType<A> new_size);
+ void Initialize(ValueAdapter values, size_type new_size);
template <typename ValueAdapter>
- void Assign(ValueAdapter values, SizeType<A> new_size);
+ void Assign(ValueAdapter values, size_type new_size);
template <typename ValueAdapter>
- void Resize(ValueAdapter values, SizeType<A> new_size);
+ void Resize(ValueAdapter values, size_type new_size);
template <typename ValueAdapter>
- Iterator<A> Insert(ConstIterator<A> pos, ValueAdapter values,
- SizeType<A> insert_count);
+ iterator Insert(const_iterator pos, ValueAdapter values,
+ size_type insert_count);
template <typename... Args>
- Reference<A> EmplaceBack(Args&&... args);
+ reference EmplaceBack(Args&&... args);
- Iterator<A> Erase(ConstIterator<A> from, ConstIterator<A> to);
+ iterator Erase(const_iterator from, const_iterator to);
- void Reserve(SizeType<A> requested_capacity);
+ void Reserve(size_type requested_capacity);
void ShrinkToFit();
void Swap(Storage* other_storage_ptr);
void SetIsAllocated() {
- GetSizeAndIsAllocated() |= static_cast<SizeType<A>>(1);
+ GetSizeAndIsAllocated() |= static_cast<size_type>(1);
}
void UnsetIsAllocated() {
- GetSizeAndIsAllocated() &= ((std::numeric_limits<SizeType<A>>::max)() - 1);
+ GetSizeAndIsAllocated() &= ((std::numeric_limits<size_type>::max)() - 1);
}
- void SetSize(SizeType<A> size) {
+ void SetSize(size_type size) {
GetSizeAndIsAllocated() =
- (size << 1) | static_cast<SizeType<A>>(GetIsAllocated());
+ (size << 1) | static_cast<size_type>(GetIsAllocated());
}
- void SetAllocatedSize(SizeType<A> size) {
- GetSizeAndIsAllocated() = (size << 1) | static_cast<SizeType<A>>(1);
+ void SetAllocatedSize(size_type size) {
+ GetSizeAndIsAllocated() = (size << 1) | static_cast<size_type>(1);
}
- void SetInlinedSize(SizeType<A> size) {
- GetSizeAndIsAllocated() = size << static_cast<SizeType<A>>(1);
+ void SetInlinedSize(size_type size) {
+ GetSizeAndIsAllocated() = size << static_cast<size_type>(1);
}
- void AddSize(SizeType<A> count) {
- GetSizeAndIsAllocated() += count << static_cast<SizeType<A>>(1);
+ void AddSize(size_type count) {
+ GetSizeAndIsAllocated() += count << static_cast<size_type>(1);
}
- void SubtractSize(SizeType<A> count) {
+ void SubtractSize(size_type count) {
assert(count <= GetSize());
- GetSizeAndIsAllocated() -= count << static_cast<SizeType<A>>(1);
+ 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 SetAllocation(Allocation<A> allocation) {
- data_.allocated.allocated_data = allocation.data;
- data_.allocated.allocated_capacity = allocation.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<A>::value || other_storage.GetIsAllocated());
+ assert(IsMemcpyOk::value || other_storage.GetIsAllocated());
GetSizeAndIsAllocated() = other_storage.GetSizeAndIsAllocated();
data_ = other_storage.data_;
@@ -435,23 +439,22 @@ class Storage {
void DeallocateIfAllocated() {
if (GetIsAllocated()) {
- MallocAdapter<A>::Deallocate(GetAllocator(), GetAllocatedData(),
- GetAllocatedCapacity());
+ AllocatorTraits::deallocate(*GetAllocPtr(), GetAllocatedData(),
+ GetAllocatedCapacity());
}
}
private:
- ABSL_ATTRIBUTE_NOINLINE void DestroyContents();
-
- using Metadata = container_internal::CompressedTuple<A, SizeType<A>>;
+ using Metadata =
+ container_internal::CompressedTuple<allocator_type, size_type>;
struct Allocated {
- Pointer<A> allocated_data;
- SizeType<A> allocated_capacity;
+ pointer allocated_data;
+ size_type allocated_capacity;
};
struct Inlined {
- alignas(ValueType<A>) char inlined_data[sizeof(ValueType<A>[N])];
+ alignas(value_type) char inlined_data[sizeof(value_type[N])];
};
union Data {
@@ -459,75 +462,33 @@ class Storage {
Inlined inlined;
};
- template <typename... Args>
- ABSL_ATTRIBUTE_NOINLINE Reference<A> EmplaceBackSlow(Args&&... args);
-
Metadata metadata_;
Data data_;
};
template <typename T, size_t N, typename A>
-void Storage<T, N, A>::DestroyContents() {
- Pointer<A> data = GetIsAllocated() ? GetAllocatedData() : GetInlinedData();
- DestroyElements<A>(GetAllocator(), data, GetSize());
- DeallocateIfAllocated();
-}
-
-template <typename T, size_t N, typename A>
-void Storage<T, N, A>::InitFrom(const Storage& other) {
- const SizeType<A> n = other.GetSize();
- assert(n > 0); // Empty sources handled handled in caller.
- ConstPointer<A> src;
- Pointer<A> 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()`.
- SizeType<A> requested_capacity = ComputeCapacity(GetInlinedCapacity(), n);
- Allocation<A> allocation =
- MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
- SetAllocation(allocation);
- dst = allocation.data;
- src = other.GetAllocatedData();
- }
- if (IsMemcpyOk<A>::value) {
- std::memcpy(reinterpret_cast<char*>(dst),
- reinterpret_cast<const char*>(src), n * sizeof(ValueType<A>));
- } else {
- auto values = IteratorValueAdapter<A, ConstPointer<A>>(src);
- ConstructElements<A>(GetAllocator(), 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, SizeType<A> new_size)
+auto Storage<T, N, A>::Initialize(ValueAdapter values, size_type new_size)
-> void {
// Only callable from constructors!
assert(!GetIsAllocated());
assert(GetSize() == 0);
- Pointer<A> construct_data;
+ 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()`.
- SizeType<A> requested_capacity =
- ComputeCapacity(GetInlinedCapacity(), new_size);
- Allocation<A> allocation =
- MallocAdapter<A>::Allocate(GetAllocator(), requested_capacity);
- construct_data = allocation.data;
- SetAllocation(allocation);
+ 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();
}
- ConstructElements<A>(GetAllocator(), construct_data, values, new_size);
+ 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
@@ -537,20 +498,18 @@ auto Storage<T, N, A>::Initialize(ValueAdapter values, SizeType<A> new_size)
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
-auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size)
- -> void {
- StorageView<A> storage_view = MakeStorageView();
+auto Storage<T, N, A>::Assign(ValueAdapter values, size_type new_size) -> void {
+ StorageView storage_view = MakeStorageView();
- AllocationTransaction<A> allocation_tx(GetAllocator());
+ AllocationTransaction allocation_tx(GetAllocPtr());
- absl::Span<ValueType<A>> assign_loop;
- absl::Span<ValueType<A>> construct_loop;
- absl::Span<ValueType<A>> destroy_loop;
+ absl::Span<value_type> assign_loop;
+ absl::Span<value_type> construct_loop;
+ absl::Span<value_type> destroy_loop;
if (new_size > storage_view.capacity) {
- SizeType<A> requested_capacity =
- ComputeCapacity(storage_view.capacity, new_size);
- construct_loop = {allocation_tx.Allocate(requested_capacity), new_size};
+ 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};
@@ -561,16 +520,18 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size)
destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};
}
- AssignElements<A>(assign_loop.data(), values, assign_loop.size());
+ inlined_vector_internal::AssignElements(assign_loop.data(), &values,
+ assign_loop.size());
- ConstructElements<A>(GetAllocator(), construct_loop.data(), values,
- construct_loop.size());
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), construct_loop.data(), &values, construct_loop.size());
- DestroyElements<A>(GetAllocator(), destroy_loop.data(), destroy_loop.size());
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), destroy_loop.data(),
+ destroy_loop.size());
if (allocation_tx.DidAllocate()) {
DeallocateIfAllocated();
- SetAllocation(std::move(allocation_tx).Release());
+ AcquireAllocatedData(&allocation_tx);
SetIsAllocated();
}
@@ -579,119 +540,125 @@ auto Storage<T, N, A>::Assign(ValueAdapter values, SizeType<A> new_size)
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
-auto Storage<T, N, A>::Resize(ValueAdapter values, SizeType<A> new_size)
- -> void {
- StorageView<A> storage_view = MakeStorageView();
- Pointer<A> const base = storage_view.data;
- const SizeType<A> size = storage_view.size;
- A& alloc = GetAllocator();
- if (new_size <= size) {
- // Destroy extra old elements.
- DestroyElements<A>(alloc, base + new_size, size - new_size);
- } else if (new_size <= storage_view.capacity) {
- // Construct new elements in place.
- ConstructElements<A>(alloc, base + size, values, new_size - size);
+auto Storage<T, N, A>::Resize(ValueAdapter values, size_type new_size) -> void {
+ StorageView storage_view = MakeStorageView();
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+
+ AllocationTransaction allocation_tx(GetAllocPtr());
+ ConstructionTransaction construction_tx(GetAllocPtr());
+
+ absl::Span<value_type> construct_loop;
+ absl::Span<value_type> move_construct_loop;
+ absl::Span<value_type> destroy_loop;
+
+ if (new_size > storage_view.capacity) {
+ size_type new_capacity = ComputeCapacity(storage_view.capacity, new_size);
+ pointer new_data = allocation_tx.Allocate(new_capacity);
+ construct_loop = {new_data + storage_view.size,
+ new_size - storage_view.size};
+ move_construct_loop = {new_data, storage_view.size};
+ destroy_loop = {storage_view.data, storage_view.size};
+ } else if (new_size > storage_view.size) {
+ construct_loop = {storage_view.data + storage_view.size,
+ new_size - storage_view.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<A> allocation_tx(alloc);
- SizeType<A> requested_capacity =
- ComputeCapacity(storage_view.capacity, new_size);
- Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
-
- ConstructionTransaction<A> construction_tx(alloc);
- construction_tx.Construct(new_data + size, values, new_size - size);
-
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- (MoveIterator<A>(base)));
- ConstructElements<A>(alloc, new_data, move_values, size);
-
- DestroyElements<A>(alloc, base, size);
- std::move(construction_tx).Commit();
+ destroy_loop = {storage_view.data + new_size, storage_view.size - new_size};
+ }
+
+ construction_tx.Construct(construct_loop.data(), &values,
+ construct_loop.size());
+
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), move_construct_loop.data(), &move_values,
+ move_construct_loop.size());
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), destroy_loop.data(),
+ destroy_loop.size());
+
+ construction_tx.Commit();
+ if (allocation_tx.DidAllocate()) {
DeallocateIfAllocated();
- SetAllocation(std::move(allocation_tx).Release());
+ AcquireAllocatedData(&allocation_tx);
SetIsAllocated();
}
+
SetSize(new_size);
}
template <typename T, size_t N, typename A>
template <typename ValueAdapter>
-auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
- SizeType<A> insert_count) -> Iterator<A> {
- StorageView<A> storage_view = MakeStorageView();
+auto Storage<T, N, A>::Insert(const_iterator pos, ValueAdapter values,
+ size_type insert_count) -> iterator {
+ StorageView storage_view = MakeStorageView();
- SizeType<A> insert_index =
- std::distance(ConstIterator<A>(storage_view.data), pos);
- SizeType<A> insert_end_index = insert_index + insert_count;
- SizeType<A> new_size = storage_view.size + insert_count;
+ 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<A> allocation_tx(GetAllocator());
- ConstructionTransaction<A> construction_tx(GetAllocator());
- ConstructionTransaction<A> move_construction_tx(GetAllocator());
+ AllocationTransaction allocation_tx(GetAllocPtr());
+ ConstructionTransaction construction_tx(GetAllocPtr());
+ ConstructionTransaction move_construciton_tx(GetAllocPtr());
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
- SizeType<A> requested_capacity =
- ComputeCapacity(storage_view.capacity, new_size);
- Pointer<A> new_data = allocation_tx.Allocate(requested_capacity);
+ 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);
+ construction_tx.Construct(new_data + insert_index, &values, insert_count);
- move_construction_tx.Construct(new_data, move_values, insert_index);
+ move_construciton_tx.Construct(new_data, &move_values, insert_index);
- ConstructElements<A>(GetAllocator(), new_data + insert_end_index,
- move_values, storage_view.size - insert_index);
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), new_data + insert_end_index, &move_values,
+ storage_view.size - insert_index);
- DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
- std::move(construction_tx).Commit();
- std::move(move_construction_tx).Commit();
+ construction_tx.Commit();
+ move_construciton_tx.Commit();
DeallocateIfAllocated();
- SetAllocation(std::move(allocation_tx).Release());
+ AcquireAllocatedData(&allocation_tx);
SetAllocatedSize(new_size);
- return Iterator<A>(new_data + insert_index);
+ return iterator(new_data + insert_index);
} else {
- SizeType<A> move_construction_destination_index =
+ size_type move_construction_destination_index =
(std::max)(insert_end_index, storage_view.size);
- ConstructionTransaction<A> move_construction_tx(GetAllocator());
+ ConstructionTransaction move_construction_tx(GetAllocPtr());
- IteratorValueAdapter<A, MoveIterator<A>> move_construction_values(
- MoveIterator<A>(storage_view.data +
- (move_construction_destination_index - insert_count)));
- absl::Span<ValueType<A>> move_construction = {
+ 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<A> move_assignment_values = storage_view.data + insert_index;
- absl::Span<ValueType<A>> move_assignment = {
+ 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<ValueType<A>> insert_assignment = {move_assignment_values,
- move_construction.size()};
+ absl::Span<value_type> insert_assignment = {move_assignment_values,
+ move_construction.size()};
- absl::Span<ValueType<A>> insert_construction = {
+ 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_values,
move_construction.size());
- for (Pointer<A>
- destination = move_assignment.data() + move_assignment.size(),
- last_destination = move_assignment.data(),
- source = move_assignment_values + move_assignment.size();
+ for (pointer destination = move_assignment.data() + move_assignment.size(),
+ last_destination = move_assignment.data(),
+ source = move_assignment_values + move_assignment.size();
;) {
--destination;
--source;
@@ -699,115 +666,114 @@ auto Storage<T, N, A>::Insert(ConstIterator<A> pos, ValueAdapter values,
*destination = std::move(*source);
}
- AssignElements<A>(insert_assignment.data(), values,
- insert_assignment.size());
+ inlined_vector_internal::AssignElements(insert_assignment.data(), &values,
+ insert_assignment.size());
- ConstructElements<A>(GetAllocator(), insert_construction.data(), values,
- insert_construction.size());
+ inlined_vector_internal::ConstructElements(
+ GetAllocPtr(), insert_construction.data(), &values,
+ insert_construction.size());
- std::move(move_construction_tx).Commit();
+ move_construction_tx.Commit();
AddSize(insert_count);
- return Iterator<A>(storage_view.data + insert_index);
+ 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<A> {
- StorageView<A> storage_view = MakeStorageView();
- const SizeType<A> n = storage_view.size;
- if (ABSL_PREDICT_TRUE(n != storage_view.capacity)) {
- // Fast path; new element fits.
- Pointer<A> last_ptr = storage_view.data + n;
- AllocatorTraits<A>::construct(GetAllocator(), 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)...);
-}
+auto Storage<T, N, A>::EmplaceBack(Args&&... args) -> reference {
+ StorageView storage_view = MakeStorageView();
-template <typename T, size_t N, typename A>
-template <typename... Args>
-auto Storage<T, N, A>::EmplaceBackSlow(Args&&... args) -> Reference<A> {
- StorageView<A> storage_view = MakeStorageView();
- AllocationTransaction<A> allocation_tx(GetAllocator());
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data));
- SizeType<A> requested_capacity = NextCapacity(storage_view.capacity);
- Pointer<A> construct_data = allocation_tx.Allocate(requested_capacity);
- Pointer<A> last_ptr = construct_data + storage_view.size;
-
- // Construct new element.
- AllocatorTraits<A>::construct(GetAllocator(), last_ptr,
- std::forward<Args>(args)...);
- // Move elements from old backing store to new backing store.
- ABSL_INTERNAL_TRY {
- ConstructElements<A>(GetAllocator(), allocation_tx.GetData(), move_values,
- storage_view.size);
+ AllocationTransaction allocation_tx(GetAllocPtr());
+
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
+
+ pointer construct_data;
+ if (storage_view.size == storage_view.capacity) {
+ size_type new_capacity = NextCapacity(storage_view.capacity);
+ construct_data = allocation_tx.Allocate(new_capacity);
+ } else {
+ construct_data = storage_view.data;
}
- ABSL_INTERNAL_CATCH_ANY {
- AllocatorTraits<A>::destroy(GetAllocator(), last_ptr);
- ABSL_INTERNAL_RETHROW;
+
+ pointer last_ptr = construct_data + storage_view.size;
+
+ AllocatorTraits::construct(*GetAllocPtr(), last_ptr,
+ std::forward<Args>(args)...);
+
+ if (allocation_tx.DidAllocate()) {
+ 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;
+ }
+
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
+
+ DeallocateIfAllocated();
+ AcquireAllocatedData(&allocation_tx);
+ SetIsAllocated();
}
- // Destroy elements in old backing store.
- DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
- DeallocateIfAllocated();
- SetAllocation(std::move(allocation_tx).Release());
- SetIsAllocated();
AddSize(1);
return *last_ptr;
}
template <typename T, size_t N, typename A>
-auto Storage<T, N, A>::Erase(ConstIterator<A> from, ConstIterator<A> to)
- -> Iterator<A> {
- StorageView<A> storage_view = MakeStorageView();
+auto Storage<T, N, A>::Erase(const_iterator from, const_iterator to)
+ -> iterator {
+ StorageView storage_view = MakeStorageView();
- SizeType<A> erase_size = std::distance(from, to);
- SizeType<A> erase_index =
- std::distance(ConstIterator<A>(storage_view.data), from);
- SizeType<A> erase_end_index = erase_index + erase_size;
+ 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<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data + erase_end_index));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data + erase_end_index));
- AssignElements<A>(storage_view.data + erase_index, move_values,
- storage_view.size - erase_end_index);
+ inlined_vector_internal::AssignElements(storage_view.data + erase_index,
+ &move_values,
+ storage_view.size - erase_end_index);
- DestroyElements<A>(GetAllocator(),
- storage_view.data + (storage_view.size - erase_size),
- erase_size);
+ inlined_vector_internal::DestroyElements(
+ GetAllocPtr(), storage_view.data + (storage_view.size - erase_size),
+ erase_size);
SubtractSize(erase_size);
- return Iterator<A>(storage_view.data + erase_index);
+ return iterator(storage_view.data + erase_index);
}
template <typename T, size_t N, typename A>
-auto Storage<T, N, A>::Reserve(SizeType<A> requested_capacity) -> void {
- StorageView<A> storage_view = MakeStorageView();
+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<A> allocation_tx(GetAllocator());
+ AllocationTransaction allocation_tx(GetAllocPtr());
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
- SizeType<A> new_requested_capacity =
+ size_type new_capacity =
ComputeCapacity(storage_view.capacity, requested_capacity);
- Pointer<A> new_data = allocation_tx.Allocate(new_requested_capacity);
+ pointer new_data = allocation_tx.Allocate(new_capacity);
- ConstructElements<A>(GetAllocator(), new_data, move_values,
- storage_view.size);
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), new_data,
+ &move_values, storage_view.size);
- DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
DeallocateIfAllocated();
- SetAllocation(std::move(allocation_tx).Release());
+ AcquireAllocatedData(&allocation_tx);
SetIsAllocated();
}
@@ -816,44 +782,41 @@ auto Storage<T, N, A>::ShrinkToFit() -> void {
// May only be called on allocated instances!
assert(GetIsAllocated());
- StorageView<A> storage_view{GetAllocatedData(), GetSize(),
- GetAllocatedCapacity()};
+ StorageView storage_view{GetAllocatedData(), GetSize(),
+ GetAllocatedCapacity()};
if (ABSL_PREDICT_FALSE(storage_view.size == storage_view.capacity)) return;
- AllocationTransaction<A> allocation_tx(GetAllocator());
+ AllocationTransaction allocation_tx(GetAllocPtr());
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(storage_view.data));
- Pointer<A> construct_data;
+ pointer construct_data;
if (storage_view.size > GetInlinedCapacity()) {
- SizeType<A> requested_capacity = storage_view.size;
- construct_data = allocation_tx.Allocate(requested_capacity);
- if (allocation_tx.GetCapacity() >= storage_view.capacity) {
- // Already using the smallest available heap allocation.
- return;
- }
+ size_type new_capacity = storage_view.size;
+ construct_data = allocation_tx.Allocate(new_capacity);
} else {
construct_data = GetInlinedData();
}
ABSL_INTERNAL_TRY {
- ConstructElements<A>(GetAllocator(), construct_data, move_values,
- storage_view.size);
+ inlined_vector_internal::ConstructElements(GetAllocPtr(), construct_data,
+ &move_values, storage_view.size);
}
ABSL_INTERNAL_CATCH_ANY {
- SetAllocation({storage_view.data, storage_view.capacity});
+ SetAllocatedData(storage_view.data, storage_view.capacity);
ABSL_INTERNAL_RETHROW;
}
- DestroyElements<A>(GetAllocator(), storage_view.data, storage_view.size);
+ inlined_vector_internal::DestroyElements(GetAllocPtr(), storage_view.data,
+ storage_view.size);
- MallocAdapter<A>::Deallocate(GetAllocator(), storage_view.data,
- storage_view.capacity);
+ AllocatorTraits::deallocate(*GetAllocPtr(), storage_view.data,
+ storage_view.capacity);
if (allocation_tx.DidAllocate()) {
- SetAllocation(std::move(allocation_tx).Release());
+ AcquireAllocatedData(&allocation_tx);
} else {
UnsetIsAllocated();
}
@@ -871,60 +834,57 @@ auto Storage<T, N, A>::Swap(Storage* other_storage_ptr) -> void {
Storage* large_ptr = other_storage_ptr;
if (small_ptr->GetSize() > large_ptr->GetSize()) swap(small_ptr, large_ptr);
- for (SizeType<A> i = 0; i < small_ptr->GetSize(); ++i) {
+ for (size_type i = 0; i < small_ptr->GetSize(); ++i) {
swap(small_ptr->GetInlinedData()[i], large_ptr->GetInlinedData()[i]);
}
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(large_ptr->GetInlinedData() + small_ptr->GetSize()));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(large_ptr->GetInlinedData() + small_ptr->GetSize()));
- ConstructElements<A>(large_ptr->GetAllocator(),
- small_ptr->GetInlinedData() + small_ptr->GetSize(),
- move_values,
- large_ptr->GetSize() - small_ptr->GetSize());
+ inlined_vector_internal::ConstructElements(
+ large_ptr->GetAllocPtr(),
+ small_ptr->GetInlinedData() + small_ptr->GetSize(), &move_values,
+ large_ptr->GetSize() - small_ptr->GetSize());
- DestroyElements<A>(large_ptr->GetAllocator(),
- large_ptr->GetInlinedData() + small_ptr->GetSize(),
- 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<A> allocated_storage_view{
- allocated_ptr->GetAllocatedData(), allocated_ptr->GetSize(),
- allocated_ptr->GetAllocatedCapacity()};
+ StorageView allocated_storage_view{allocated_ptr->GetAllocatedData(),
+ allocated_ptr->GetSize(),
+ allocated_ptr->GetAllocatedCapacity()};
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(inlined_ptr->GetInlinedData()));
+ IteratorValueAdapter<MoveIterator> move_values(
+ MoveIterator(inlined_ptr->GetInlinedData()));
ABSL_INTERNAL_TRY {
- ConstructElements<A>(inlined_ptr->GetAllocator(),
- allocated_ptr->GetInlinedData(), move_values,
- inlined_ptr->GetSize());
+ inlined_vector_internal::ConstructElements(
+ inlined_ptr->GetAllocPtr(), allocated_ptr->GetInlinedData(),
+ &move_values, inlined_ptr->GetSize());
}
ABSL_INTERNAL_CATCH_ANY {
- allocated_ptr->SetAllocation(
- {allocated_storage_view.data, allocated_storage_view.capacity});
+ allocated_ptr->SetAllocatedData(allocated_storage_view.data,
+ allocated_storage_view.capacity);
ABSL_INTERNAL_RETHROW;
}
- DestroyElements<A>(inlined_ptr->GetAllocator(),
- inlined_ptr->GetInlinedData(), inlined_ptr->GetSize());
+ inlined_vector_internal::DestroyElements(inlined_ptr->GetAllocPtr(),
+ inlined_ptr->GetInlinedData(),
+ inlined_ptr->GetSize());
- inlined_ptr->SetAllocation(
- {allocated_storage_view.data, allocated_storage_view.capacity});
+ inlined_ptr->SetAllocatedData(allocated_storage_view.data,
+ allocated_storage_view.capacity);
}
swap(GetSizeAndIsAllocated(), other_storage_ptr->GetSizeAndIsAllocated());
- swap(GetAllocator(), other_storage_ptr->GetAllocator());
+ swap(*GetAllocPtr(), *other_storage_ptr->GetAllocPtr());
}
-// End ignore "array-bounds" and "maybe-uninitialized"
-#if !defined(__clang__) && defined(__GNUC__)
-#pragma GCC diagnostic pop
-#endif
-
} // namespace inlined_vector_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/container/internal/layout.h b/third_party/abseil-cpp/absl/container/internal/layout.h
index a59a243059..69cc85dd66 100644
--- a/third_party/abseil-cpp/absl/container/internal/layout.h
+++ b/third_party/abseil-cpp/absl/container/internal/layout.h
@@ -163,7 +163,6 @@
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
-
#include <ostream>
#include <string>
#include <tuple>
@@ -171,16 +170,15 @@
#include <typeinfo>
#include <utility>
-#include "absl/base/config.h"
+#ifdef ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#endif
+
#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
@@ -404,7 +402,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>>::value * size_[N - 1],
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1],
ElementAlignment<N>::value);
}
@@ -597,7 +595,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>>::value * size_[NumTypes - 1];
+ SizeOf<ElementType<NumTypes - 1>>() * size_[NumTypes - 1];
}
// If built with --config=asan, poisons padding bytes (if any) in the
@@ -616,12 +614,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 ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
PoisonPadding<Char, N - 1>(p);
// The `if` is an optimization. It doesn't affect the observable behaviour.
if (ElementAlignment<N - 1>::value % ElementAlignment<N>::value) {
size_t start =
- Offset<N - 1>() + SizeOf<ElementType<N - 1>>::value * size_[N - 1];
+ Offset<N - 1>() + SizeOf<ElementType<N - 1>>() * size_[N - 1];
ASAN_POISON_MEMORY_REGION(p + start, Offset<N>() - start);
}
#endif
@@ -645,7 +643,7 @@ 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>>::value...};
+ const size_t sizes[] = {SizeOf<ElementType<OffsetSeq>>()...};
const std::string types[] = {
adl_barrier::TypeName<ElementType<OffsetSeq>>()...};
std::string res = absl::StrCat("@0", types[0], "(", sizes[0], ")");
diff --git a/third_party/abseil-cpp/absl/container/internal/layout_benchmark.cc b/third_party/abseil-cpp/absl/container/internal/layout_benchmark.cc
deleted file mode 100644
index d8636e8d5a..0000000000
--- a/third_party/abseil-cpp/absl/container/internal/layout_benchmark.cc
+++ /dev/null
@@ -1,122 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/container/internal/layout_test.cc b/third_party/abseil-cpp/absl/container/internal/layout_test.cc
index 54e5d5bbb8..8f3628a1f1 100644
--- a/third_party/abseil-cpp/absl/container/internal/layout_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/layout_test.cc
@@ -17,7 +17,6 @@
// 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>
@@ -25,7 +24,6 @@
#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"
@@ -128,10 +126,8 @@ 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>;
@@ -370,21 +366,18 @@ 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).Pointer<0>(p))));
+ 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).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))));
+ 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))));
}
@@ -392,44 +385,39 @@ 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(
@@ -438,8 +426,7 @@ 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))));
@@ -450,78 +437,75 @@ 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().Pointer<int8_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
+ 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_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))));
+ Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
EXPECT_EQ(
- 4,
- Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
EXPECT_EQ(
- 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
+ 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_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))));
- EXPECT_EQ(0, Distance(p, Type<const int32_t*>(
- L::Partial(0, 0).Pointer<int32_t>(p))));
+ Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
EXPECT_EQ(
- 0,
- Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
+ 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
EXPECT_EQ(
- 0,
- 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))));
+ 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
EXPECT_EQ(
- 8,
- Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(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(5, 3).Pointer<int8_t>(p))));
- EXPECT_EQ(8, Distance(p, Type<const int32_t*>(
- L::Partial(5, 3).Pointer<int32_t>(p))));
+ Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
EXPECT_EQ(
- 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))));
+ 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(
+ 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))));
}
}
@@ -562,18 +546,15 @@ 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))));
@@ -585,61 +566,48 @@ 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))));
@@ -820,72 +788,67 @@ 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()));
- 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(0).Slice<0>(p)).data()));
EXPECT_EQ(
0,
- Distance(
- p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+ Distance(p, Type<Span<const int8_t>>(L::Partial(1).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(5).Slice<0>(p)).data()));
+ EXPECT_EQ(
+ 0, 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()));
+ 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(
@@ -899,8 +862,7 @@ 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(
@@ -914,8 +876,7 @@ 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(
@@ -927,14 +888,12 @@ 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()));
}
}
@@ -945,94 +904,98 @@ 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).Slice<int8_t>(p)).data()));
+ p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
EXPECT_EQ(
0,
Distance(
p,
- Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
+ Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_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 int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
+ 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(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()));
+ 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(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()));
+ 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 int8_t>>(L::Partial(5, 3).Slice<int8_t>(p))
+ Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_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(
+ 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()));
}
}
@@ -1040,19 +1003,18 @@ 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).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, 5).Slice<0>(p)).data()));
EXPECT_EQ(
12,
Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
@@ -1061,63 +1023,55 @@ 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).Slice<0>(p)).data()));
+ 0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(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(5).Slice<0>(p)).data()));
+ 0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
EXPECT_EQ(
- 0,
- Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
+ 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).Slice<1>(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(5, 3).Slice<0>(p)).data()));
EXPECT_EQ(
- 4,
- Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
+ 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(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()));
+ 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()));
+ 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()));
}
}
@@ -1126,84 +1080,66 @@ 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(
@@ -1212,16 +1148,14 @@ 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()));
}
}
@@ -1320,17 +1254,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))));
}
}
@@ -1350,13 +1284,7 @@ TEST(Layout, CustomAlignment) {
TEST(Layout, OverAligned) {
constexpr size_t M = alignof(max_align_t);
constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
-#ifdef __GNUC__
- // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug:
- // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357
- __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()];
-#else
alignas(2 * M) unsigned char p[x.AllocSize()];
-#endif
EXPECT_EQ(2 * M + 3, x.AllocSize());
EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
}
@@ -1386,7 +1314,7 @@ struct Region {
};
void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
for (size_t i = 0; i != n; ++i) {
EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
}
@@ -1468,8 +1396,7 @@ 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" +
@@ -1477,8 +1404,7 @@ 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" +
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_map.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_map.h
index c7df2efc62..0a02757ddf 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_map.h
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_map.h
@@ -51,9 +51,8 @@ class raw_hash_map : public raw_hash_set<Policy, Hash, Eq, Alloc> {
using key_arg = typename KeyArgImpl::template type<K, key_type>;
static_assert(!std::is_reference<key_type>::value, "");
-
- // TODO(b/187807849): Evaluate whether to support reference mapped_type and
- // remove this assertion if/when it is supported.
+ // TODO(alkis): remove this assertion and verify that reference mapped_type is
+ // supported.
static_assert(!std::is_reference<mapped_type>::value, "");
using iterator = typename raw_hash_map::raw_hash_set::iterator;
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc
index 687bcb8a4d..919ac07405 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.cc
@@ -23,17 +23,11 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
-alignas(16) ABSL_CONST_INIT ABSL_DLL const ctrl_t kEmptyGroup[16] = {
- ctrl_t::kSentinel, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
- ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
- ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty,
- ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty, ctrl_t::kEmpty};
-
constexpr size_t Group::kWidth;
// Returns "random" seed.
inline size_t RandomSeed() {
-#ifdef ABSL_HAVE_THREAD_LOCAL
+#if ABSL_HAVE_THREAD_LOCAL
static thread_local size_t counter = 0;
size_t value = ++counter;
#else // ABSL_HAVE_THREAD_LOCAL
@@ -43,25 +37,12 @@ inline size_t RandomSeed() {
return value ^ static_cast<size_t>(reinterpret_cast<uintptr_t>(&counter));
}
-bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl) {
+bool ShouldInsertBackwards(size_t hash, ctrl_t* ctrl) {
// To avoid problems with weak hashes and single bit tests, we use % 13.
// TODO(kfm,sbenza): revisit after we do unconditional mixing
return (H1(hash, ctrl) ^ RandomSeed()) % 13 > 6;
}
-void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity) {
- assert(ctrl[capacity] == ctrl_t::kSentinel);
- assert(IsValidCapacity(capacity));
- for (ctrl_t* pos = ctrl; pos < ctrl + capacity; pos += Group::kWidth) {
- Group{pos}.ConvertSpecialToEmptyAndFullToDeleted(pos);
- }
- // Copy the cloned ctrl bytes.
- std::memcpy(ctrl + capacity + 1, ctrl, NumClonedBytes());
- ctrl[capacity] = ctrl_t::kSentinel;
-}
-// Extern template instantiotion for inline function.
-template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
-
} // namespace container_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
index 12682b3532..ca7be8d868 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -87,17 +87,6 @@
//
// This probing function guarantees that after N probes, all the groups of the
// table will be probed exactly once.
-//
-// The control state and slot array are stored contiguously in a shared heap
-// allocation. The layout of this allocation is: `capacity()` control bytes,
-// one sentinel control byte, `Group::kWidth - 1` cloned control bytes,
-// <possible padding>, `capacity()` slots. The sentinel control byte is used in
-// iteration so we know when we reach the end of the table. The cloned control
-// bytes at the end of the table are cloned from the beginning of the table so
-// groups that begin near the end of the table can see a full group. In cases in
-// which there are more than `capacity()` cloned control bytes, the extra bytes
-// are `kEmpty`, and these ensure that we always see at least one empty slot and
-// can stop an unsuccessful search.
#ifndef ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
#define ABSL_CONTAINER_INTERNAL_RAW_HASH_SET_H_
@@ -113,8 +102,8 @@
#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"
@@ -123,25 +112,15 @@
#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/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:
@@ -189,19 +168,24 @@ struct IsDecomposable<
// TODO(alkis): Switch to std::is_nothrow_swappable when gcc/clang supports it.
template <class T>
-constexpr bool IsNoThrowSwappable(std::true_type = {} /* is_swappable */) {
+constexpr bool IsNoThrowSwappable() {
using std::swap;
return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
}
-template <class T>
-constexpr bool IsNoThrowSwappable(std::false_type /* is_swappable */) {
- return false;
+
+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 <typename T>
-uint32_t TrailingZeros(T x) {
- ABSL_INTERNAL_ASSUME(x != 0);
- return countr_zero(x);
+int LeadingZeros(T x) {
+ return sizeof(T) == 8
+ ? base_internal::CountLeadingZeros64(static_cast<uint64_t>(x))
+ : base_internal::CountLeadingZeros32(static_cast<uint32_t>(x));
}
// An abstraction over a bitmask. It provides an easy way to iterate through the
@@ -231,24 +215,26 @@ class BitMask {
}
explicit operator bool() const { return mask_ != 0; }
int operator*() const { return LowestBitSet(); }
- uint32_t LowestBitSet() const {
+ int LowestBitSet() const {
return container_internal::TrailingZeros(mask_) >> Shift;
}
- uint32_t HighestBitSet() const {
- return static_cast<uint32_t>((bit_width(mask_) - 1) >> Shift);
+ int HighestBitSet() const {
+ return (sizeof(T) * CHAR_BIT - container_internal::LeadingZeros(mask_) -
+ 1) >>
+ Shift;
}
BitMask begin() const { return *this; }
BitMask end() const { return BitMask(0); }
- uint32_t TrailingZeros() const {
+ int TrailingZeros() const {
return container_internal::TrailingZeros(mask_) >> Shift;
}
- uint32_t LeadingZeros() const {
+ int LeadingZeros() const {
constexpr int total_significant_bits = SignificantBits << Shift;
constexpr int extra_bits = sizeof(T) * 8 - total_significant_bits;
- return countl_zero(mask_ << extra_bits) >> Shift;
+ return container_internal::LeadingZeros(mask_ << extra_bits) >> Shift;
}
private:
@@ -262,53 +248,48 @@ class BitMask {
T mask_;
};
+using ctrl_t = signed char;
using h2_t = uint8_t;
// The values here are selected for maximum performance. See the static asserts
-// below for details. We use an enum class so that when strict aliasing is
-// enabled, the compiler knows ctrl_t doesn't alias other types.
-enum class ctrl_t : int8_t {
+// below for details.
+enum Ctrl : ctrl_t {
kEmpty = -128, // 0b10000000
kDeleted = -2, // 0b11111110
kSentinel = -1, // 0b11111111
};
static_assert(
- (static_cast<int8_t>(ctrl_t::kEmpty) &
- static_cast<int8_t>(ctrl_t::kDeleted) &
- static_cast<int8_t>(ctrl_t::kSentinel) & 0x80) != 0,
+ kEmpty & kDeleted & kSentinel & 0x80,
"Special markers need to have the MSB to make checking for them efficient");
-static_assert(
- ctrl_t::kEmpty < ctrl_t::kSentinel && ctrl_t::kDeleted < ctrl_t::kSentinel,
- "ctrl_t::kEmpty and ctrl_t::kDeleted must be smaller than "
- "ctrl_t::kSentinel to make the SIMD test of IsEmptyOrDeleted() efficient");
-static_assert(
- ctrl_t::kSentinel == static_cast<ctrl_t>(-1),
- "ctrl_t::kSentinel must be -1 to elide loading it from memory into SIMD "
- "registers (pcmpeqd xmm, xmm)");
-static_assert(ctrl_t::kEmpty == static_cast<ctrl_t>(-128),
- "ctrl_t::kEmpty must be -128 to make the SIMD check for its "
+static_assert(kEmpty < kSentinel && kDeleted < kSentinel,
+ "kEmpty and kDeleted must be smaller than kSentinel to make the "
+ "SIMD test of IsEmptyOrDeleted() efficient");
+static_assert(kSentinel == -1,
+ "kSentinel must be -1 to elide loading it from memory into SIMD "
+ "registers (pcmpeqd xmm, xmm)");
+static_assert(kEmpty == -128,
+ "kEmpty must be -128 to make the SIMD check for its "
"existence efficient (psignb xmm, xmm)");
-static_assert(
- (~static_cast<int8_t>(ctrl_t::kEmpty) &
- ~static_cast<int8_t>(ctrl_t::kDeleted) &
- static_cast<int8_t>(ctrl_t::kSentinel) & 0x7F) != 0,
- "ctrl_t::kEmpty and ctrl_t::kDeleted must share an unset bit that is not "
- "shared by ctrl_t::kSentinel to make the scalar test for "
- "MatchEmptyOrDeleted() efficient");
-static_assert(ctrl_t::kDeleted == static_cast<ctrl_t>(-2),
- "ctrl_t::kDeleted must be -2 to make the implementation of "
+static_assert(~kEmpty & ~kDeleted & kSentinel & 0x7F,
+ "kEmpty and kDeleted must share an unset bit that is not shared "
+ "by kSentinel to make the scalar test for MatchEmptyOrDeleted() "
+ "efficient");
+static_assert(kDeleted == -2,
+ "kDeleted must be -2 to make the implementation of "
"ConvertSpecialToEmptyAndFullToDeleted efficient");
// A single block of empty control bytes for tables without any slots allocated.
// This enables removing a branch in the hot path of find().
-ABSL_DLL extern const ctrl_t kEmptyGroup[16];
inline ctrl_t* EmptyGroup() {
- return const_cast<ctrl_t*>(kEmptyGroup);
+ alignas(16) static constexpr ctrl_t empty_group[] = {
+ kSentinel, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty,
+ kEmpty, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty, kEmpty};
+ return const_cast<ctrl_t*>(empty_group);
}
// Mixes a randomly generated per-process seed with `hash` and `ctrl` to
// randomize insertion order within groups.
-bool ShouldInsertBackwards(size_t hash, const ctrl_t* ctrl);
+bool ShouldInsertBackwards(size_t hash, ctrl_t* ctrl);
// Returns a hash seed.
//
@@ -324,14 +305,14 @@ inline size_t HashSeed(const ctrl_t* ctrl) {
inline size_t H1(size_t hash, const ctrl_t* ctrl) {
return (hash >> 7) ^ HashSeed(ctrl);
}
-inline h2_t H2(size_t hash) { return hash & 0x7F; }
+inline ctrl_t H2(size_t hash) { return hash & 0x7F; }
-inline bool IsEmpty(ctrl_t c) { return c == ctrl_t::kEmpty; }
-inline bool IsFull(ctrl_t c) { return c >= static_cast<ctrl_t>(0); }
-inline bool IsDeleted(ctrl_t c) { return c == ctrl_t::kDeleted; }
-inline bool IsEmptyOrDeleted(ctrl_t c) { return c < ctrl_t::kSentinel; }
+inline bool IsEmpty(ctrl_t c) { return c == kEmpty; }
+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 ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_HAVE_SSE2
// https://github.com/abseil/abseil-cpp/issues/209
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87853
@@ -365,33 +346,33 @@ struct GroupSse2Impl {
// Returns a bitmask representing the positions of empty slots.
BitMask<uint32_t, kWidth> MatchEmpty() const {
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
- // This only works because ctrl_t::kEmpty is -128.
+#if SWISSTABLE_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(static_cast<h2_t>(ctrl_t::kEmpty));
+ return Match(static_cast<h2_t>(kEmpty));
#endif
}
// Returns a bitmask representing the positions of empty or deleted slots.
BitMask<uint32_t, kWidth> MatchEmptyOrDeleted() const {
- auto special = _mm_set1_epi8(static_cast<int8_t>(ctrl_t::kSentinel));
+ auto special = _mm_set1_epi8(kSentinel);
return BitMask<uint32_t, kWidth>(
_mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)));
}
// Returns the number of trailing empty or deleted elements in the group.
uint32_t CountLeadingEmptyOrDeleted() const {
- auto special = _mm_set1_epi8(static_cast<int8_t>(ctrl_t::kSentinel));
- return TrailingZeros(static_cast<uint32_t>(
- _mm_movemask_epi8(_mm_cmpgt_epi8_fixed(special, ctrl)) + 1));
+ auto special = _mm_set1_epi8(kSentinel);
+ return TrailingZeros(
+ _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 ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSSE3
+#if SWISSTABLE_HAVE_SSSE3
auto res = _mm_or_si128(_mm_shuffle_epi8(x126, ctrl), msbs);
#else
auto zero = _mm_setzero_si128();
@@ -403,7 +384,7 @@ struct GroupSse2Impl {
__m128i ctrl;
};
-#endif // ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#endif // SWISSTABLE_HAVE_SSE2
struct GroupPortableImpl {
static constexpr size_t kWidth = 8;
@@ -418,7 +399,7 @@ struct GroupPortableImpl {
//
// Caveat: there are false positives but:
// - they only occur if there is a real match
- // - they never occur on ctrl_t::kEmpty, ctrl_t::kDeleted, ctrl_t::kSentinel
+ // - they never occur on kEmpty, kDeleted, kSentinel
// - they will be handled gracefully by subsequent checks in code
//
// Example:
@@ -457,16 +438,12 @@ struct GroupPortableImpl {
uint64_t ctrl;
};
-#if ABSL_INTERNAL_RAW_HASH_SET_HAVE_SSE2
+#if SWISSTABLE_HAVE_SSE2
using Group = GroupSse2Impl;
#else
using Group = GroupPortableImpl;
#endif
-// The number of cloned control bytes that we copy from the beginning to the
-// end of the control bytes array.
-constexpr size_t NumClonedBytes() { return Group::kWidth - 1; }
-
template <class Policy, class Hash, class Eq, class Alloc>
class raw_hash_set;
@@ -474,29 +451,31 @@ inline bool IsValidCapacity(size_t n) { return ((n + 1) & n) == 0 && n > 0; }
// PRECONDITION:
// IsValidCapacity(capacity)
-// ctrl[capacity] == ctrl_t::kSentinel
-// ctrl[i] != ctrl_t::kSentinel for all i < capacity
+// ctrl[capacity] == kSentinel
+// ctrl[i] != kSentinel for all i < capacity
// Applies mapping for every byte in ctrl:
// DELETED -> EMPTY
// EMPTY -> EMPTY
// FULL -> DELETED
-void ConvertDeletedToEmptyAndFullToDeleted(ctrl_t* ctrl, size_t capacity);
+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;
+}
// Rounds up the capacity to the next power of 2 minus 1, with a minimum of 1.
inline size_t NormalizeCapacity(size_t n) {
- return n ? ~size_t{} >> countl_zero(n) : 1;
+ return n ? ~size_t{} >> LeadingZeros(n) : 1;
}
-// 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.
+// We use 7/8th as maximum load factor.
+// For 16-wide groups, that gives an average of two empty slots per group.
inline size_t CapacityToGrowth(size_t capacity) {
assert(IsValidCapacity(capacity));
// `capacity*7/8`
@@ -507,7 +486,7 @@ inline size_t CapacityToGrowth(size_t capacity) {
return capacity - capacity / 8;
}
// From desired "growth" to a lowerbound of the necessary capacity.
-// Might not be a valid one and requires NormalizeCapacity().
+// Might not be a valid one and required NormalizeCapacity().
inline size_t GrowthToLowerboundCapacity(size_t growth) {
// `growth*8/7`
if (Group::kWidth == 8 && growth == 7) {
@@ -517,144 +496,6 @@ inline size_t GrowthToLowerboundCapacity(size_t growth) {
return growth + static_cast<size_t>((static_cast<int64_t>(growth) - 1) / 7);
}
-template <class InputIter>
-size_t SelectBucketCountForIterRange(InputIter first, InputIter last,
- size_t bucket_count) {
- if (bucket_count != 0) {
- return bucket_count;
- }
- using InputIterCategory =
- typename std::iterator_traits<InputIter>::iterator_category;
- if (std::is_base_of<std::random_access_iterator_tag,
- InputIterCategory>::value) {
- return GrowthToLowerboundCapacity(
- static_cast<size_t>(std::distance(first, last)));
- }
- return 0;
-}
-
-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.");
-}
-
-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.");
-}
-
-struct FindInfo {
- size_t offset;
- size_t probe_length;
-};
-
-// 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 ctrl_t::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(const ctrl_t* ctrl, size_t hash,
- size_t capacity) {
- return probe_seq<Group::kWidth>(H1(hash, ctrl), capacity);
-}
-
-// 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 ctrl_t::kEmpty and
-// ctrl_t::kDeleted 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
-template <typename = void>
-inline FindInfo find_first_non_full(const ctrl_t* ctrl, size_t hash,
- size_t capacity) {
- auto seq = probe(ctrl, hash, capacity);
- 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!");
- }
-}
-
-// Extern template for inline function keep possibility of inlining.
-// When compiler decided to not inline, no symbols will be added to the
-// corresponding translation unit.
-extern template FindInfo find_first_non_full(const ctrl_t*, size_t, size_t);
-
-// Reset all ctrl bytes back to ctrl_t::kEmpty, except the sentinel.
-inline void ResetCtrl(size_t capacity, ctrl_t* ctrl, const void* slot,
- size_t slot_size) {
- std::memset(ctrl, static_cast<int8_t>(ctrl_t::kEmpty),
- capacity + 1 + NumClonedBytes());
- ctrl[capacity] = ctrl_t::kSentinel;
- SanitizerPoisonMemoryRegion(slot, slot_size * capacity);
-}
-
-// Sets the control byte, and if `i < NumClonedBytes()`, set the cloned byte
-// at the end too.
-inline void SetCtrl(size_t i, ctrl_t h, size_t capacity, ctrl_t* ctrl,
- const void* slot, size_t slot_size) {
- assert(i < capacity);
-
- auto* slot_i = static_cast<const char*>(slot) + i * slot_size;
- if (IsFull(h)) {
- SanitizerUnpoisonMemoryRegion(slot_i, slot_size);
- } else {
- SanitizerPoisonMemoryRegion(slot_i, slot_size);
- }
-
- ctrl[i] = h;
- ctrl[((i - NumClonedBytes()) & capacity) + (NumClonedBytes() & capacity)] = h;
-}
-
-inline void SetCtrl(size_t i, h2_t h, size_t capacity, ctrl_t* ctrl,
- const void* slot, size_t slot_size) {
- SetCtrl(i, static_cast<ctrl_t>(h), capacity, ctrl, slot, slot_size);
-}
-
-// The allocated block consists of `capacity + 1 + NumClonedBytes()` control
-// bytes followed by `capacity` slots, which must be aligned to `slot_align`.
-// SlotOffset returns the offset of the slots into the allocated block.
-inline size_t SlotOffset(size_t capacity, size_t slot_align) {
- assert(IsValidCapacity(capacity));
- const size_t num_control_bytes = capacity + 1 + NumClonedBytes();
- return (num_control_bytes + slot_align - 1) & (~slot_align + 1);
-}
-
-// Returns the size of the allocated block. See also above comment.
-inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) {
- return SlotOffset(capacity, slot_align) + capacity * slot_size;
-}
-
// Policy: a policy defines how to perform different operations on
// the slots of the hashtable (see hash_policy_traits.h for the full interface
// of policy).
@@ -669,8 +510,7 @@ inline size_t AllocSize(size_t capacity, size_t slot_size, size_t slot_align) {
// 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
-// [https://en.cppreference.com/w/cpp/named_req/Allocator] with which
+// Allocator: an Allocator [https://devdocs.io/cpp/concept/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>
@@ -711,6 +551,13 @@ class raw_hash_set {
auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
+ using Layout = absl::container_internal::Layout<ctrl_t, slot_type>;
+
+ static Layout MakeLayout(size_t capacity) {
+ assert(IsValidCapacity(capacity));
+ return Layout(capacity + Group::kWidth + 1, capacity);
+ }
+
using AllocTraits = absl::allocator_traits<allocator_type>;
using SlotAlloc = typename absl::allocator_traits<
allocator_type>::template rebind_alloc<slot_type>;
@@ -769,7 +616,7 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator.
reference operator*() const {
- AssertIsFull(ctrl_);
+ assert_is_full();
return PolicyTraits::element(slot_);
}
@@ -778,7 +625,7 @@ class raw_hash_set {
// PRECONDITION: not an end() iterator.
iterator& operator++() {
- AssertIsFull(ctrl_);
+ assert_is_full();
++ctrl_;
++slot_;
skip_empty_or_deleted();
@@ -792,8 +639,8 @@ class raw_hash_set {
}
friend bool operator==(const iterator& a, const iterator& b) {
- AssertIsValid(a.ctrl_);
- AssertIsValid(b.ctrl_);
+ a.assert_is_valid();
+ b.assert_is_valid();
return a.ctrl_ == b.ctrl_;
}
friend bool operator!=(const iterator& a, const iterator& b) {
@@ -801,19 +648,24 @@ class raw_hash_set {
}
private:
- 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);
+ iterator(ctrl_t* ctrl) : ctrl_(ctrl) {} // for end()
+ iterator(ctrl_t* ctrl, slot_type* slot) : ctrl_(ctrl), slot_(slot) {}
+
+ void assert_is_full() const { assert(IsFull(*ctrl_)); }
+ void assert_is_valid() const {
+ assert(!ctrl_ || IsFull(*ctrl_) || *ctrl_ == kSentinel);
}
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_ == ctrl_t::kSentinel)) ctrl_ = nullptr;
}
ctrl_t* ctrl_ = nullptr;
@@ -872,10 +724,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, HashtablezInfoHandle(), hash, eq, alloc) {
+ : ctrl_(EmptyGroup()), settings_(0, hash, eq, alloc) {
if (bucket_count) {
capacity_ = NormalizeCapacity(bucket_count);
+ reset_growth_left();
initialize_slots();
}
}
@@ -894,8 +746,7 @@ class raw_hash_set {
raw_hash_set(InputIter first, InputIter last, size_t bucket_count = 0,
const hasher& hash = hasher(), const key_equal& eq = key_equal(),
const allocator_type& alloc = allocator_type())
- : raw_hash_set(SelectBucketCountForIterRange(first, last, bucket_count),
- hash, eq, alloc) {
+ : raw_hash_set(bucket_count, hash, eq, alloc) {
insert(first, last);
}
@@ -982,11 +833,10 @@ class raw_hash_set {
// than a full `insert`.
for (const auto& v : that) {
const size_t hash = PolicyTraits::apply(HashElement{hash_ref()}, v);
- auto target = find_first_non_full(ctrl_, hash, capacity_);
- SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
- sizeof(slot_type));
+ auto target = find_first_non_full(hash);
+ set_ctrl(target.offset, H2(hash));
emplace_at(target.offset, v);
- infoz().RecordInsert(hash, target.probe_length);
+ infoz_.RecordInsert(hash, target.probe_length);
}
size_ = that.size();
growth_left() -= that.size();
@@ -1000,27 +850,28 @@ class raw_hash_set {
slots_(absl::exchange(that.slots_, nullptr)),
size_(absl::exchange(that.size_, 0)),
capacity_(absl::exchange(that.capacity_, 0)),
+ infoz_(absl::exchange(that.infoz_, HashtablezInfoHandle())),
// Hash, equality and allocator are copied instead of moved because
// `that` must be left valid. If Hash is std::function<Key>, moving it
// would create a nullptr functor that cannot be called.
- settings_(absl::exchange(that.growth_left(), 0),
- absl::exchange(that.infoz(), HashtablezInfoHandle()),
- that.hash_ref(), that.eq_ref(), that.alloc_ref()) {}
+ settings_(that.settings_) {
+ // growth_left was copied above, reset the one from `that`.
+ that.growth_left() = 0;
+ }
raw_hash_set(raw_hash_set&& that, const allocator_type& a)
: ctrl_(EmptyGroup()),
slots_(nullptr),
size_(0),
capacity_(0),
- settings_(0, HashtablezInfoHandle(), that.hash_ref(), that.eq_ref(),
- a) {
+ settings_(0, that.hash_ref(), that.eq_ref(), a) {
if (a == that.alloc_ref()) {
std::swap(ctrl_, that.ctrl_);
std::swap(slots_, that.slots_);
std::swap(size_, that.size_);
std::swap(capacity_, that.capacity_);
std::swap(growth_left(), that.growth_left());
- std::swap(infoz(), that.infoz());
+ std::swap(infoz_, that.infoz_);
} else {
reserve(that.size());
// Note: this will copy elements of dense_set and unordered_set instead of
@@ -1056,12 +907,12 @@ class raw_hash_set {
it.skip_empty_or_deleted();
return it;
}
- iterator end() { return {}; }
+ iterator end() { return {ctrl_ + capacity_}; }
const_iterator begin() const {
return const_cast<raw_hash_set*>(this)->begin();
}
- const_iterator end() const { return {}; }
+ const_iterator end() const { return const_cast<raw_hash_set*>(this)->end(); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
@@ -1080,8 +931,6 @@ class raw_hash_set {
// past that we simply deallocate the array.
if (capacity_ > 127) {
destroy_slots();
-
- infoz().RecordClearedReservation();
} else if (capacity_) {
for (size_t i = 0; i != capacity_; ++i) {
if (IsFull(ctrl_[i])) {
@@ -1089,11 +938,11 @@ class raw_hash_set {
}
}
size_ = 0;
- ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
+ reset_ctrl();
reset_growth_left();
}
assert(empty());
- infoz().RecordStorageChanged(0, capacity_);
+ infoz_.RecordStorageChanged(0, capacity_);
}
// This overload kicks in when the argument is an rvalue of insertable and
@@ -1166,7 +1015,7 @@ class raw_hash_set {
template <class InputIt>
void insert(InputIt first, InputIt last) {
- for (; first != last; ++first) emplace(*first);
+ for (; first != last; ++first) insert(*first);
}
template <class T, RequiresNotInit<T> = 0, RequiresInsertable<const T&> = 0>
@@ -1193,9 +1042,7 @@ class raw_hash_set {
}
iterator insert(const_iterator, node_type&& node) {
- auto res = insert(std::move(node));
- node = std::move(res.node);
- return res.position;
+ return insert(std::move(node)).first;
}
// This overload kicks in if we can deduce the key from args. This enables us
@@ -1324,7 +1171,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) {
- AssertIsFull(it.ctrl_);
+ it.assert_is_full();
PolicyTraits::destroy(&alloc_ref(), it.slot_);
erase_meta_only(it);
}
@@ -1358,7 +1205,7 @@ class raw_hash_set {
}
node_type extract(const_iterator position) {
- AssertIsFull(position.inner_.ctrl_);
+ position.inner_.assert_is_full();
auto node =
CommonAccess::Transfer<node_type>(alloc_ref(), position.inner_.slot_);
erase_meta_only(position);
@@ -1375,8 +1222,8 @@ class raw_hash_set {
void swap(raw_hash_set& that) noexcept(
IsNoThrowSwappable<hasher>() && IsNoThrowSwappable<key_equal>() &&
- IsNoThrowSwappable<allocator_type>(
- typename AllocTraits::propagate_on_container_swap{})) {
+ (!AllocTraits::propagate_on_container_swap::value ||
+ IsNoThrowSwappable<allocator_type>())) {
using std::swap;
swap(ctrl_, that.ctrl_);
swap(slots_, that.slots_);
@@ -1385,43 +1232,32 @@ class raw_hash_set {
swap(growth_left(), that.growth_left());
swap(hash_ref(), that.hash_ref());
swap(eq_ref(), that.eq_ref());
- swap(infoz(), that.infoz());
- SwapAlloc(alloc_ref(), that.alloc_ref(),
- typename AllocTraits::propagate_on_container_swap{});
+ swap(infoz_, that.infoz_);
+ 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.
+ }
}
void rehash(size_t n) {
if (n == 0 && capacity_ == 0) return;
if (n == 0 && size_ == 0) {
destroy_slots();
- infoz().RecordStorageChanged(0, 0);
- infoz().RecordClearedReservation();
+ 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);
-
- // This is after resize, to ensure that we have completed the allocation
- // and have potentially sampled the hashtable.
- infoz().RecordReservation(n);
}
}
- void reserve(size_t n) {
- if (n > size() + growth_left()) {
- size_t m = GrowthToLowerboundCapacity(n);
- resize(NormalizeCapacity(m));
-
- // This is after resize, to ensure that we have completed the allocation
- // and have potentially sampled the hashtable.
- infoz().RecordReservation(n);
- }
- }
+ void reserve(size_t n) { rehash(GrowthToLowerboundCapacity(n)); }
// Extension API: support for heterogeneous keys.
//
@@ -1446,8 +1282,7 @@ class raw_hash_set {
void prefetch(const key_arg<K>& key) const {
(void)key;
#if defined(__GNUC__)
- prefetch_heap_block();
- auto seq = probe(ctrl_, hash_ref()(key), capacity_);
+ auto seq = probe(hash_ref()(key));
__builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset()));
__builtin_prefetch(static_cast<const void*>(slots_ + seq.offset()));
#endif // __GNUC__
@@ -1462,7 +1297,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(ctrl_, hash, capacity_);
+ auto seq = probe(hash);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1473,12 +1308,10 @@ 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>
iterator find(const key_arg<K>& key) {
- prefetch_heap_block();
return find(key, hash_ref()(key));
}
@@ -1488,7 +1321,6 @@ class raw_hash_set {
}
template <class K = key_type>
const_iterator find(const key_arg<K>& key) const {
- prefetch_heap_block();
return find(key, hash_ref()(key));
}
@@ -1623,10 +1455,9 @@ class raw_hash_set {
static_cast<size_t>(empty_after.TrailingZeros() +
empty_before.LeadingZeros()) < Group::kWidth;
- SetCtrl(index, was_never_full ? ctrl_t::kEmpty : ctrl_t::kDeleted,
- capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(index, was_never_full ? kEmpty : kDeleted);
growth_left() += was_never_full;
- infoz().RecordErase();
+ infoz_.RecordErase();
}
void initialize_slots() {
@@ -1643,18 +1474,17 @@ class raw_hash_set {
// bound more carefully.
if (std::is_same<SlotAlloc, std::allocator<slot_type>>::value &&
slots_ == nullptr) {
- infoz() = Sample(sizeof(slot_type));
+ infoz_ = Sample();
}
- char* mem = static_cast<char*>(Allocate<alignof(slot_type)>(
- &alloc_ref(),
- AllocSize(capacity_, sizeof(slot_type), alignof(slot_type))));
- ctrl_ = reinterpret_cast<ctrl_t*>(mem);
- slots_ = reinterpret_cast<slot_type*>(
- mem + SlotOffset(capacity_, alignof(slot_type)));
- ResetCtrl(capacity_, ctrl_, slots_, sizeof(slot_type));
+ 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();
reset_growth_left();
- infoz().RecordStorageChanged(size_, capacity_);
+ infoz_.RecordStorageChanged(size_, capacity_);
}
void destroy_slots() {
@@ -1664,12 +1494,10 @@ class raw_hash_set {
PolicyTraits::destroy(&alloc_ref(), slots_ + i);
}
}
-
+ auto layout = MakeLayout(capacity_);
// Unpoison before returning the memory to the allocator.
SanitizerUnpoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
- Deallocate<alignof(slot_type)>(
- &alloc_ref(), ctrl_,
- AllocSize(capacity_, sizeof(slot_type), alignof(slot_type)));
+ Deallocate<Layout::Alignment()>(&alloc_ref(), ctrl_, layout.AllocSize());
ctrl_ = EmptyGroup();
slots_ = nullptr;
size_ = 0;
@@ -1690,26 +1518,26 @@ class raw_hash_set {
if (IsFull(old_ctrl[i])) {
size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
PolicyTraits::element(old_slots + i));
- auto target = find_first_non_full(ctrl_, hash, capacity_);
+ auto target = find_first_non_full(hash);
size_t new_i = target.offset;
total_probe_length += target.probe_length;
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(new_i, H2(hash));
PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, old_slots + i);
}
}
if (old_capacity) {
SanitizerUnpoisonMemoryRegion(old_slots,
sizeof(slot_type) * old_capacity);
- Deallocate<alignof(slot_type)>(
- &alloc_ref(), old_ctrl,
- AllocSize(old_capacity, sizeof(slot_type), alignof(slot_type)));
+ auto layout = MakeLayout(old_capacity);
+ Deallocate<Layout::Alignment()>(&alloc_ref(), old_ctrl,
+ layout.AllocSize());
}
- infoz().RecordRehash(total_probe_length);
+ infoz_.RecordRehash(total_probe_length);
}
void drop_deletes_without_resize() ABSL_ATTRIBUTE_NOINLINE {
assert(IsValidCapacity(capacity_));
- assert(!is_small(capacity_));
+ assert(!is_small());
// Algorithm:
// - mark all DELETED slots as EMPTY
// - mark all FULL slots as DELETED
@@ -1732,35 +1560,34 @@ class raw_hash_set {
slot_type* slot = reinterpret_cast<slot_type*>(&raw);
for (size_t i = 0; i != capacity_; ++i) {
if (!IsDeleted(ctrl_[i])) continue;
- const size_t hash = PolicyTraits::apply(
- HashElement{hash_ref()}, PolicyTraits::element(slots_ + i));
- const FindInfo target = find_first_non_full(ctrl_, hash, capacity_);
- const size_t new_i = target.offset;
+ size_t hash = PolicyTraits::apply(HashElement{hash_ref()},
+ PolicyTraits::element(slots_ + i));
+ auto target = find_first_non_full(hash);
+ size_t new_i = target.offset;
total_probe_length += target.probe_length;
// Verify if the old and new i fall within the same group wrt the hash.
// If they do, we don't need to move the object as it falls already in the
// best probe we can.
- const size_t probe_offset = probe(ctrl_, hash, capacity_).offset();
- const auto probe_index = [probe_offset, this](size_t pos) {
- return ((pos - probe_offset) & capacity_) / Group::kWidth;
+ const auto probe_index = [&](size_t pos) {
+ return ((pos - probe(hash).offset()) & capacity_) / Group::kWidth;
};
// Element doesn't move.
if (ABSL_PREDICT_TRUE(probe_index(new_i) == probe_index(i))) {
- SetCtrl(i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(i, H2(hash));
continue;
}
if (IsEmpty(ctrl_[new_i])) {
// Transfer element to the empty spot.
- // SetCtrl poisons/unpoisons the slots so we have to call it at the
+ // set_ctrl poisons/unpoisons the slots so we have to call it at the
// right time.
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(new_i, H2(hash));
PolicyTraits::transfer(&alloc_ref(), slots_ + new_i, slots_ + i);
- SetCtrl(i, ctrl_t::kEmpty, capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(i, kEmpty);
} else {
assert(IsDeleted(ctrl_[new_i]));
- SetCtrl(new_i, H2(hash), capacity_, ctrl_, slots_, sizeof(slot_type));
+ set_ctrl(new_i, H2(hash));
// Until we are done rehashing, DELETED marks previously FULL slots.
// Swap i and new_i elements.
PolicyTraits::transfer(&alloc_ref(), slot, slots_ + i);
@@ -1770,56 +1597,14 @@ class raw_hash_set {
}
}
reset_growth_left();
- infoz().RecordRehash(total_probe_length);
+ infoz_.RecordRehash(total_probe_length);
}
void rehash_and_grow_if_necessary() {
if (capacity_ == 0) {
resize(1);
- } else if (capacity_ > Group::kWidth &&
- // Do these calcuations in 64-bit to avoid overflow.
- size() * uint64_t{32} <= capacity_ * uint64_t{25}) {
+ } else if (size() <= CapacityToGrowth(capacity()) / 2) {
// Squash DELETED without growing if there is enough capacity.
- //
- // Rehash in place if the current size is <= 25/32 of capacity_.
- // Rationale for such a high factor: 1) drop_deletes_without_resize() is
- // faster than resize, and 2) it takes quite a bit of work to add
- // tombstones. In the worst case, seems to take approximately 4
- // insert/erase pairs to create a single tombstone and so if we are
- // rehashing because of tombstones, we can afford to rehash-in-place as
- // long as we are reclaiming at least 1/8 the capacity without doing more
- // than 2X the work. (Where "work" is defined to be size() for rehashing
- // or rehashing in place, and 1 for an insert or erase.) But rehashing in
- // place is faster per operation than inserting or even doubling the size
- // of the table, so we actually afford to reclaim even less space from a
- // resize-in-place. The decision is to rehash in place if we can reclaim
- // at about 1/8th of the usable capacity (specifically 3/28 of the
- // capacity) which means that the total cost of rehashing will be a small
- // fraction of the total work.
- //
- // Here is output of an experiment using the BM_CacheInSteadyState
- // benchmark running the old case (where we rehash-in-place only if we can
- // reclaim at least 7/16*capacity_) vs. this code (which rehashes in place
- // if we can recover 3/32*capacity_).
- //
- // Note that although in the worst-case number of rehashes jumped up from
- // 15 to 190, but the number of operations per second is almost the same.
- //
- // Abridged output of running BM_CacheInSteadyState benchmark from
- // raw_hash_set_benchmark. N is the number of insert/erase operations.
- //
- // | OLD (recover >= 7/16 | NEW (recover >= 3/32)
- // size | N/s LoadFactor NRehashes | N/s LoadFactor NRehashes
- // 448 | 145284 0.44 18 | 140118 0.44 19
- // 493 | 152546 0.24 11 | 151417 0.48 28
- // 538 | 151439 0.26 11 | 151152 0.53 38
- // 583 | 151765 0.28 11 | 150572 0.57 50
- // 628 | 150241 0.31 11 | 150853 0.61 66
- // 672 | 149602 0.33 12 | 150110 0.66 90
- // 717 | 149998 0.35 12 | 149531 0.70 129
- // 762 | 149836 0.37 13 | 148559 0.74 190
- // 807 | 149736 0.39 14 | 151107 0.39 14
- // 852 | 150204 0.42 15 | 151019 0.42 15
drop_deletes_without_resize();
} else {
// Otherwise grow the container.
@@ -1829,7 +1614,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(ctrl_, hash, capacity_);
+ auto seq = probe(hash);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1839,11 +1624,46 @@ class raw_hash_set {
}
if (ABSL_PREDICT_TRUE(g.MatchEmpty())) return false;
seq.next();
- assert(seq.index() <= capacity_ && "full table!");
+ assert(seq.index() < capacity_ && "full table!");
}
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
+ struct FindInfo {
+ size_t offset;
+ size_t probe_length;
+ };
+ FindInfo 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 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() && ShouldInsertBackwards(hash, ctrl_)) {
+ return {seq.offset(mask.HighestBitSet()), seq.index()};
+ }
+#endif
+ return {seq.offset(mask.LowestBitSet()), seq.index()};
+ }
+ 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));
@@ -1859,9 +1679,8 @@ class raw_hash_set {
protected:
template <class K>
std::pair<size_t, bool> find_or_prepare_insert(const K& key) {
- prefetch_heap_block();
auto hash = hash_ref()(key);
- auto seq = probe(ctrl_, hash, capacity_);
+ auto seq = probe(hash);
while (true) {
Group g{ctrl_ + seq.offset()};
for (int i : g.Match(H2(hash))) {
@@ -1872,23 +1691,21 @@ 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 {
- auto target = find_first_non_full(ctrl_, hash, capacity_);
+ auto target = find_first_non_full(hash);
if (ABSL_PREDICT_FALSE(growth_left() == 0 &&
!IsDeleted(ctrl_[target.offset]))) {
rehash_and_grow_if_necessary();
- target = find_first_non_full(ctrl_, hash, capacity_);
+ target = find_first_non_full(hash);
}
++size_;
growth_left() -= IsEmpty(ctrl_[target.offset]);
- SetCtrl(target.offset, H2(hash), capacity_, ctrl_, slots_,
- sizeof(slot_type));
- infoz().RecordInsert(hash, target.probe_length);
+ set_ctrl(target.offset, H2(hash));
+ infoz_.RecordInsert(hash, target.probe_length);
return target.offset;
}
@@ -1916,54 +1733,84 @@ 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);
+ ctrl_[capacity_] = kSentinel;
+ SanitizerPoisonMemoryRegion(slots_, sizeof(slot_type) * capacity_);
+ }
+
void reset_growth_left() {
growth_left() = CapacityToGrowth(capacity()) - size_;
}
- size_t& growth_left() { return settings_.template get<0>(); }
+ // 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) {
+ assert(i < capacity_);
- void prefetch_heap_block() const {
- // Prefetch the heap-allocated memory region to resolve potential TLB
- // misses. This is intended to overlap with execution of calculating the
- // hash for a key.
-#if defined(__GNUC__)
- __builtin_prefetch(static_cast<const void*>(ctrl_), 0, 1);
-#endif // __GNUC__
+ if (IsFull(h)) {
+ SanitizerUnpoisonObject(slots_ + i);
+ } else {
+ SanitizerPoisonObject(slots_ + i);
+ }
+
+ ctrl_[i] = h;
+ ctrl_[((i - Group::kWidth) & capacity_) + 1 +
+ ((Group::kWidth - 1) & capacity_)] = h;
}
- HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
+ size_t& growth_left() { return settings_.template get<0>(); }
- 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>(); }
+ // 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.
+ bool is_small() const { return capacity_ < Group::kWidth - 1; }
+
+ hasher& hash_ref() { return settings_.template get<1>(); }
+ const hasher& hash_ref() const { return settings_.template get<1>(); }
+ key_equal& eq_ref() { return settings_.template get<2>(); }
+ const key_equal& eq_ref() const { return settings_.template get<2>(); }
+ allocator_type& alloc_ref() { return settings_.template get<3>(); }
const allocator_type& alloc_ref() const {
- return settings_.template get<4>();
+ return settings_.template get<3>();
}
// TODO(alkis): Investigate removing some of these fields:
// - ctrl/slots can be derived from each other
// - size can be moved into the slot array
- ctrl_t* ctrl_ = EmptyGroup(); // [(capacity + 1 + NumClonedBytes()) * ctrl_t]
- 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 */,
- HashtablezInfoHandle, hasher,
+ ctrl_t* ctrl_ = EmptyGroup(); // [(capacity + 1) * ctrl_t]
+ slot_type* slots_ = nullptr; // [capacity * slot_type]
+ size_t size_ = 0; // number of full slots
+ size_t capacity_ = 0; // total number of slots
+ HashtablezInfoHandle infoz_;
+ absl::container_internal::CompressedTuple<size_t /* growth_left */, hasher,
key_equal, allocator_type>
- settings_{0, HashtablezInfoHandle{}, hasher{}, key_equal{},
- allocator_type{}};
+ settings_{0, 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) {
+void EraseIf(Predicate pred, raw_hash_set<P, H, E, A>* c) {
for (auto it = c->begin(), last = c->end(); it != last;) {
- if (pred(*it)) {
- c->erase(it++);
- } else {
- ++it;
+ auto copy_it = it++;
+ if (pred(*copy_it)) {
+ c->erase(copy_it);
}
}
}
@@ -1978,7 +1825,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 = probe(set.ctrl_, hash, set.capacity_);
+ auto seq = set.probe(hash);
while (true) {
container_internal::Group g{set.ctrl_ + seq.offset()};
for (int i : g.Match(container_internal::H2(hash))) {
@@ -1998,7 +1845,8 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
static size_t AllocatedByteSize(const Set& c) {
size_t capacity = c.capacity_;
if (capacity == 0) return 0;
- size_t m = AllocSize(capacity, sizeof(Slot), alignof(Slot));
+ auto layout = Set::MakeLayout(capacity);
+ size_t m = layout.AllocSize();
size_t per_slot = Traits::space_used(static_cast<const Slot*>(nullptr));
if (per_slot != ~size_t{}) {
@@ -2016,8 +1864,8 @@ struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> {
static size_t LowerBoundAllocatedByteSize(size_t size) {
size_t capacity = GrowthToLowerboundCapacity(size);
if (capacity == 0) return 0;
- size_t m =
- AllocSize(NormalizeCapacity(capacity), sizeof(Slot), alignof(Slot));
+ 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{}) {
m += per_slot * size;
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
index e73f53fd63..7ac4b9f7df 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_allocator_test.cc
@@ -424,81 +424,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc
deleted file mode 100644
index c886d3ad43..0000000000
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_benchmark.cc
+++ /dev/null
@@ -1,431 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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_RangeCtor(benchmark::State& state) {
- std::random_device rd;
- std::mt19937 rng(rd());
- std::uniform_int_distribution<uint64_t> dist(0, ~uint64_t{});
- std::vector<int> values;
- const size_t desired_size = state.range(0);
- while (values.size() < desired_size) {
- values.emplace_back(dist(rng));
- }
-
- for (auto unused : state) {
- IntTable t{values.begin(), values.end()};
- benchmark::DoNotOptimize(t);
- }
-}
-BENCHMARK(BM_RangeCtor)->Range(128, 65536);
-
-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);
-
-// Like std::iota, except that ctrl_t doesn't support operator++.
-template <typename CtrlIter>
-void Iota(CtrlIter begin, CtrlIter end, int value) {
- for (; begin != end; ++begin, ++value) {
- *begin = static_cast<ctrl_t>(value);
- }
-}
-
-void BM_Group_Match(benchmark::State& state) {
- std::array<ctrl_t, Group::kWidth> group;
- 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;
- 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;
- 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;
- 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;
- 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] = ctrl_t::kSentinel;
- std::vector<ctrl_t> pattern = {ctrl_t::kEmpty, static_cast<ctrl_t>(2),
- ctrl_t::kDeleted, static_cast<ctrl_t>(2),
- ctrl_t::kEmpty, static_cast<ctrl_t>(1),
- ctrl_t::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();
-}
-
-auto CodegenAbslRawHashSetInt64Insert(absl::container_internal::IntTable* table,
- int64_t key)
- -> decltype(table->insert(key)) {
- return table->insert(key);
-}
-
-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,
- &CodegenAbslRawHashSetInt64Insert,
- &CodegenAbslRawHashSetInt64Contains,
- &CodegenAbslRawHashSetInt64Iterate)),
- 1);
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc
deleted file mode 100644
index 7169a2e206..0000000000
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_probe_benchmark.cc
+++ /dev/null
@@ -1,590 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
index 362b3caec3..a96ae68ac7 100644
--- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
+++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
@@ -14,7 +14,6 @@
#include "absl/container/internal/raw_hash_set.h"
-#include <atomic>
#include <cmath>
#include <cstdint>
#include <deque>
@@ -23,13 +22,10 @@
#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"
@@ -51,16 +47,14 @@ struct RawHashSetTestOnlyAccess {
namespace {
+using ::testing::DoubleNear;
using ::testing::ElementsAre;
-using ::testing::Eq;
using ::testing::Ge;
using ::testing::Lt;
+using ::testing::Optional;
using ::testing::Pair;
using ::testing::UnorderedElementsAre;
-// Convenience function to static cast to ctrl_t.
-ctrl_t CtrlT(int i) { return static_cast<ctrl_t>(i); }
-
TEST(Util, NormalizeCapacity) {
EXPECT_EQ(1, NormalizeCapacity(0));
EXPECT_EQ(1, NormalizeCapacity(1));
@@ -80,14 +74,8 @@ TEST(Util, GrowthAndCapacity) {
for (size_t growth = 0; growth < 10000; ++growth) {
SCOPED_TRACE(growth);
size_t capacity = NormalizeCapacity(GrowthToLowerboundCapacity(growth));
- // The capacity is large enough for `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));
@@ -173,19 +161,15 @@ TEST(Group, EmptyGroup) {
TEST(Group, Match) {
if (Group::kWidth == 16) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
- ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
- CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
- CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+ 7, 5, 3, 1, 1, 1, 1, 1};
EXPECT_THAT(Group{group}.Match(0), ElementsAre());
EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 11, 12, 13, 14, 15));
EXPECT_THAT(Group{group}.Match(3), ElementsAre(3, 10));
EXPECT_THAT(Group{group}.Match(5), ElementsAre(5, 9));
EXPECT_THAT(Group{group}.Match(7), ElementsAre(7, 8));
} else if (Group::kWidth == 8) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
- ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
- ctrl_t::kSentinel, CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
EXPECT_THAT(Group{group}.Match(0), ElementsAre());
EXPECT_THAT(Group{group}.Match(1), ElementsAre(1, 5, 7));
EXPECT_THAT(Group{group}.Match(2), ElementsAre(2, 4));
@@ -196,15 +180,11 @@ TEST(Group, Match) {
TEST(Group, MatchEmpty) {
if (Group::kWidth == 16) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
- ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
- CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
- CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+ 7, 5, 3, 1, 1, 1, 1, 1};
EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0, 4));
} else if (Group::kWidth == 8) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
- ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
- ctrl_t::kSentinel, CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
EXPECT_THAT(Group{group}.MatchEmpty(), ElementsAre(0));
} else {
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
@@ -213,15 +193,11 @@ TEST(Group, MatchEmpty) {
TEST(Group, MatchEmptyOrDeleted) {
if (Group::kWidth == 16) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted, CtrlT(3),
- ctrl_t::kEmpty, CtrlT(5), ctrl_t::kSentinel, CtrlT(7),
- CtrlT(7), CtrlT(5), CtrlT(3), CtrlT(1),
- CtrlT(1), CtrlT(1), CtrlT(1), CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, kDeleted, 3, kEmpty, 5, kSentinel, 7,
+ 7, 5, 3, 1, 1, 1, 1, 1};
EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 2, 4));
} else if (Group::kWidth == 8) {
- ctrl_t group[] = {ctrl_t::kEmpty, CtrlT(1), CtrlT(2),
- ctrl_t::kDeleted, CtrlT(2), CtrlT(1),
- ctrl_t::kSentinel, CtrlT(1)};
+ ctrl_t group[] = {kEmpty, 1, 2, kDeleted, 2, 1, kSentinel, 1};
EXPECT_THAT(Group{group}.MatchEmptyOrDeleted(), ElementsAre(0, 3));
} else {
FAIL() << "No test coverage for Group::kWidth==" << Group::kWidth;
@@ -232,32 +208,28 @@ TEST(Batch, DropDeletes) {
constexpr size_t kCapacity = 63;
constexpr size_t kGroupWidth = container_internal::Group::kWidth;
std::vector<ctrl_t> ctrl(kCapacity + 1 + kGroupWidth);
- ctrl[kCapacity] = ctrl_t::kSentinel;
- std::vector<ctrl_t> pattern = {
- ctrl_t::kEmpty, CtrlT(2), ctrl_t::kDeleted, CtrlT(2),
- ctrl_t::kEmpty, CtrlT(1), ctrl_t::kDeleted};
+ ctrl[kCapacity] = kSentinel;
+ std::vector<ctrl_t> pattern = {kEmpty, 2, kDeleted, 2, kEmpty, 1, kDeleted};
for (size_t i = 0; i != kCapacity; ++i) {
ctrl[i] = pattern[i % pattern.size()];
if (i < kGroupWidth - 1)
ctrl[i + kCapacity + 1] = pattern[i % pattern.size()];
}
ConvertDeletedToEmptyAndFullToDeleted(ctrl.data(), kCapacity);
- ASSERT_EQ(ctrl[kCapacity], ctrl_t::kSentinel);
- for (size_t i = 0; i < kCapacity + kGroupWidth; ++i) {
+ ASSERT_EQ(ctrl[kCapacity], kSentinel);
+ for (size_t i = 0; i < kCapacity + 1 + kGroupWidth; ++i) {
ctrl_t expected = pattern[i % (kCapacity + 1) % pattern.size()];
- if (i == kCapacity) expected = ctrl_t::kSentinel;
- if (expected == ctrl_t::kDeleted) expected = ctrl_t::kEmpty;
- if (IsFull(expected)) expected = ctrl_t::kDeleted;
+ if (i == kCapacity) expected = kSentinel;
+ if (expected == kDeleted) expected = kEmpty;
+ if (IsFull(expected)) expected = kDeleted;
EXPECT_EQ(ctrl[i], expected)
- << i << " " << static_cast<int>(pattern[i % pattern.size()]);
+ << i << " " << int{pattern[i % pattern.size()]};
}
}
TEST(Group, CountLeadingEmptyOrDeleted) {
- const std::vector<ctrl_t> empty_examples = {ctrl_t::kEmpty, ctrl_t::kDeleted};
- const std::vector<ctrl_t> full_examples = {
- CtrlT(0), CtrlT(1), CtrlT(2), CtrlT(3),
- CtrlT(5), CtrlT(9), CtrlT(127), ctrl_t::kSentinel};
+ const std::vector<ctrl_t> empty_examples = {kEmpty, kDeleted};
+ const std::vector<ctrl_t> full_examples = {0, 1, 2, 3, 5, 9, 127, kSentinel};
for (ctrl_t empty : empty_examples) {
std::vector<ctrl_t> e(Group::kWidth, empty);
@@ -277,44 +249,25 @@ TEST(Group, CountLeadingEmptyOrDeleted) {
}
}
-template <class T>
-struct ValuePolicy {
- using slot_type = T;
- using key_type = T;
- using init_type = T;
-
- 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)...);
- }
-
- template <class Allocator>
- static void destroy(Allocator* alloc, slot_type* slot) {
- absl::allocator_traits<Allocator>::destroy(*alloc, slot);
- }
+struct IntPolicy {
+ using slot_type = int64_t;
+ using key_type = int64_t;
+ using init_type = int64_t;
- 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 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 T& element(slot_type* slot) { return *slot; }
+ static int64_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)...);
+ 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);
}
};
-using IntPolicy = ValuePolicy<int64_t>;
-using Uint8Policy = ValuePolicy<uint8_t>;
-
class StringPolicy {
template <class F, class K, class V,
class = typename std::enable_if<
@@ -394,13 +347,6 @@ struct IntTable
using Base::Base;
};
-struct Uint8Table
- : raw_hash_set<Uint8Policy, container_internal::hash_default_hash<uint8_t>,
- std::equal_to<uint8_t>, std::allocator<uint8_t>> {
- using Base = typename Uint8Table::raw_hash_set;
- using Base::Base;
-};
-
template <typename T>
struct CustomAlloc : std::allocator<T> {
CustomAlloc() {}
@@ -446,13 +392,6 @@ TEST(Table, EmptyFunctorOptimization) {
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; }
};
@@ -460,27 +399,17 @@ TEST(Table, EmptyFunctorOptimization) {
size_t dummy;
};
- 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(
+ raw_hash_set<StringPolicy, StatelessHash,
+ 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>>));
- }
+ EXPECT_EQ(
+ sizeof(MockTable) + sizeof(StatefulHash),
+ sizeof(
+ raw_hash_set<StringPolicy, StatefulHash,
+ std::equal_to<absl::string_view>, std::allocator<int>>));
}
TEST(Table, Empty) {
@@ -568,37 +497,6 @@ TEST(Table, InsertCollisionAndFindAfterDelete) {
EXPECT_TRUE(t.empty());
}
-TEST(Table, InsertWithinCapacity) {
- IntTable t;
- t.reserve(10);
- const size_t original_capacity = t.capacity();
- const auto addr = [&](int i) {
- return reinterpret_cast<uintptr_t>(&*t.find(i));
- };
- // Inserting an element does not change capacity.
- t.insert(0);
- EXPECT_THAT(t.capacity(), original_capacity);
- const uintptr_t original_addr_0 = addr(0);
- // Inserting another element does not rehash.
- t.insert(1);
- EXPECT_THAT(t.capacity(), original_capacity);
- EXPECT_THAT(addr(0), original_addr_0);
- // Inserting lots of duplicate elements does not rehash.
- for (int i = 0; i < 100; ++i) {
- t.insert(i % 10);
- }
- EXPECT_THAT(t.capacity(), original_capacity);
- EXPECT_THAT(addr(0), original_addr_0);
- // Inserting a range of duplicate elements does not rehash.
- std::vector<int> dup_range;
- for (int i = 0; i < 100; ++i) {
- dup_range.push_back(i % 10);
- }
- t.insert(dup_range.begin(), dup_range.end());
- EXPECT_THAT(t.capacity(), original_capacity);
- EXPECT_THAT(addr(0), original_addr_0);
-}
-
TEST(Table, LazyEmplace) {
StringTable t;
bool called = false;
@@ -646,53 +544,28 @@ TEST(Table, Contains2) {
}
int decompose_constructed;
-int decompose_copy_constructed;
-int decompose_copy_assigned;
-int decompose_move_constructed;
-int decompose_move_assigned;
struct DecomposeType {
- DecomposeType(int i = 0) : i(i) { // NOLINT
+ DecomposeType(int i) : i(i) { // NOLINT
++decompose_constructed;
}
explicit DecomposeType(const char* d) : DecomposeType(*d) {}
- DecomposeType(const DecomposeType& other) : i(other.i) {
- ++decompose_copy_constructed;
- }
- DecomposeType& operator=(const DecomposeType& other) {
- ++decompose_copy_assigned;
- i = other.i;
- return *this;
- }
- DecomposeType(DecomposeType&& other) : i(other.i) {
- ++decompose_move_constructed;
- }
- DecomposeType& operator=(DecomposeType&& other) {
- ++decompose_move_assigned;
- i = other.i;
- return *this;
- }
-
int i;
};
struct DecomposeHash {
using is_transparent = void;
- size_t operator()(const DecomposeType& a) const { return a.i; }
+ size_t operator()(DecomposeType a) const { return a.i; }
size_t operator()(int a) const { return a; }
size_t operator()(const char* a) const { return *a; }
};
struct DecomposeEq {
using is_transparent = void;
- bool operator()(const DecomposeType& a, const DecomposeType& b) const {
- return a.i == b.i;
- }
- bool operator()(const DecomposeType& a, int b) const { return a.i == b; }
- bool operator()(const DecomposeType& a, const char* b) const {
- return a.i == *b;
- }
+ bool operator()(DecomposeType a, DecomposeType b) const { return a.i == b.i; }
+ bool operator()(DecomposeType a, int b) const { return a.i == b; }
+ bool operator()(DecomposeType a, const char* b) const { return a.i == *b; }
};
struct DecomposePolicy {
@@ -702,9 +575,9 @@ struct DecomposePolicy {
template <typename T>
static void construct(void*, DecomposeType* slot, T&& v) {
- ::new (slot) DecomposeType(std::forward<T>(v));
+ *slot = DecomposeType(std::forward<T>(v));
}
- static void destroy(void*, DecomposeType* slot) { slot->~DecomposeType(); }
+ static void destroy(void*, DecomposeType*) {}
static DecomposeType& element(slot_type* slot) { return *slot; }
template <class F, class T>
@@ -719,13 +592,8 @@ void TestDecompose(bool construct_three) {
const int one = 1;
const char* three_p = "3";
const auto& three = three_p;
- const int elem_vector_count = 256;
- std::vector<DecomposeType> elem_vector(elem_vector_count, DecomposeType{0});
- std::iota(elem_vector.begin(), elem_vector.end(), 0);
- using DecomposeSet =
- raw_hash_set<DecomposePolicy, Hash, Eq, std::allocator<int>>;
- DecomposeSet set1;
+ raw_hash_set<DecomposePolicy, Hash, Eq, std::allocator<int>> set1;
decompose_constructed = 0;
int expected_constructed = 0;
@@ -783,72 +651,20 @@ void TestDecompose(bool construct_three) {
expected_constructed += construct_three;
EXPECT_EQ(expected_constructed, decompose_constructed);
}
-
- decompose_copy_constructed = 0;
- decompose_copy_assigned = 0;
- decompose_move_constructed = 0;
- decompose_move_assigned = 0;
- int expected_copy_constructed = 0;
- int expected_move_constructed = 0;
- { // raw_hash_set(first, last) with random-access iterators
- DecomposeSet set2(elem_vector.begin(), elem_vector.end());
- // Expect exactly one copy-constructor call for each element if no
- // rehashing is done.
- expected_copy_constructed += elem_vector_count;
- EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);
- EXPECT_EQ(expected_move_constructed, decompose_move_constructed);
- EXPECT_EQ(0, decompose_move_assigned);
- EXPECT_EQ(0, decompose_copy_assigned);
- }
-
- { // raw_hash_set(first, last) with forward iterators
- std::list<DecomposeType> elem_list(elem_vector.begin(), elem_vector.end());
- expected_copy_constructed = decompose_copy_constructed;
- DecomposeSet set2(elem_list.begin(), elem_list.end());
- // Expect exactly N elements copied into set, expect at most 2*N elements
- // moving internally for all resizing needed (for a growth factor of 2).
- expected_copy_constructed += elem_vector_count;
- EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);
- expected_move_constructed += elem_vector_count;
- EXPECT_LT(expected_move_constructed, decompose_move_constructed);
- expected_move_constructed += elem_vector_count;
- EXPECT_GE(expected_move_constructed, decompose_move_constructed);
- EXPECT_EQ(0, decompose_move_assigned);
- EXPECT_EQ(0, decompose_copy_assigned);
- expected_copy_constructed = decompose_copy_constructed;
- expected_move_constructed = decompose_move_constructed;
- }
-
- { // insert(first, last)
- DecomposeSet set2;
- set2.insert(elem_vector.begin(), elem_vector.end());
- // Expect exactly N elements copied into set, expect at most 2*N elements
- // moving internally for all resizing needed (for a growth factor of 2).
- const int expected_new_elements = elem_vector_count;
- const int expected_max_element_moves = 2 * elem_vector_count;
- expected_copy_constructed += expected_new_elements;
- EXPECT_EQ(expected_copy_constructed, decompose_copy_constructed);
- expected_move_constructed += expected_max_element_moves;
- EXPECT_GE(expected_move_constructed, decompose_move_constructed);
- EXPECT_EQ(0, decompose_move_assigned);
- EXPECT_EQ(0, decompose_copy_assigned);
- expected_copy_constructed = decompose_copy_constructed;
- expected_move_constructed = decompose_move_constructed;
- }
}
TEST(Table, Decompose) {
TestDecompose<DecomposeHash, DecomposeEq>(false);
struct TransparentHashIntOverload {
- size_t operator()(const DecomposeType& a) const { return a.i; }
+ size_t operator()(DecomposeType a) const { return a.i; }
size_t operator()(int a) const { return a; }
};
struct TransparentEqIntOverload {
- bool operator()(const DecomposeType& a, const DecomposeType& b) const {
+ bool operator()(DecomposeType a, DecomposeType b) const {
return a.i == b.i;
}
- bool operator()(const DecomposeType& a, int b) const { return a.i == b; }
+ bool operator()(DecomposeType a, int b) const { return a.i == b; }
};
TestDecompose<TransparentHashIntOverload, DecomposeEq>(true);
TestDecompose<TransparentHashIntOverload, TransparentEqIntOverload>(true);
@@ -890,7 +706,7 @@ TEST(Table, RehashWithNoResize) {
const size_t capacity = t.capacity();
// Remove elements from all groups except the first and the last one.
- // All elements removed from full groups will be marked as ctrl_t::kDeleted.
+ // All elements removed from full groups will be marked as kDeleted.
const size_t erase_begin = Group::kWidth / 2;
const size_t erase_end = (t.size() / Group::kWidth - 1) * Group::kWidth;
for (size_t i = erase_begin; i < erase_end; ++i) {
@@ -1030,8 +846,7 @@ TEST(Table, EraseMaintainsValidIterator) {
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);
}
@@ -1185,8 +1000,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;
@@ -1840,38 +1655,6 @@ 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;
@@ -1883,9 +1666,9 @@ TEST(Nodes, EmptyNodeType) {
}
TEST(Nodes, ExtractInsert) {
- constexpr char k0[] = "Very long string zero.";
- constexpr char k1[] = "Very long string one.";
- constexpr char k2[] = "Very long string two.";
+ constexpr char k0[] = "Very long std::string zero.";
+ constexpr char k1[] = "Very long std::string one.";
+ constexpr char k2[] = "Very long std::string two.";
StringTable t = {{k0, ""}, {k1, ""}, {k2, ""}};
EXPECT_THAT(t,
UnorderedElementsAre(Pair(k0, ""), Pair(k1, ""), Pair(k2, "")));
@@ -1926,26 +1709,6 @@ TEST(Nodes, ExtractInsert) {
EXPECT_FALSE(node);
}
-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());
@@ -2028,81 +1791,39 @@ TEST(TableDeathTest, EraseOfEndAsserts) {
IntTable t;
// Extra simple "regexp" as regexp support is highly varied across platforms.
- constexpr char kDeathMsg[] = "Invalid operation on iterator";
+ constexpr char kDeathMsg[] = "IsFull";
EXPECT_DEATH_IF_SUPPORTED(t.erase(t.end()), kDeathMsg);
}
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
+#if defined(ABSL_HASHTABLEZ_SAMPLE)
TEST(RawHashSamplerTest, Sample) {
// Enable the feature even if the prod default is off.
SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100);
- auto& sampler = GlobalHashtablezSampler();
+ 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;
- });
+ start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
std::vector<IntTable> tables;
for (int i = 0; i < 1000000; ++i) {
tables.emplace_back();
-
- const bool do_reserve = (i % 10 > 5);
- const bool do_rehash = !do_reserve && (i % 10 > 0);
-
- if (do_reserve) {
- // Don't reserve on all tables.
- tables.back().reserve(10 * (i % 10));
- }
-
tables.back().insert(1);
- tables.back().insert(i % 5);
-
- if (do_rehash) {
- // Rehash some other tables.
- tables.back().rehash(10 * (i % 10));
- }
}
size_t end_size = 0;
- std::unordered_map<size_t, int> observed_checksums;
- std::unordered_map<ssize_t, int> reservations;
- end_size += sampler.Iterate([&](const HashtablezInfo& info) {
- if (preexisting_info.count(&info) == 0) {
- observed_checksums[info.hashes_bitwise_xor.load(
- std::memory_order_relaxed)]++;
- reservations[info.max_reserve.load(std::memory_order_relaxed)]++;
- }
- EXPECT_EQ(info.inline_element_size, sizeof(int64_t));
- ++end_size;
- });
+ end_size += sampler.Iterate([&](const HashtablezInfo&) { ++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);
- }
-
- EXPECT_EQ(reservations.size(), 10);
- for (const auto& [reservation, count] : reservations) {
- EXPECT_GE(reservation, 0);
- EXPECT_LT(reservation, 100);
-
- EXPECT_NEAR((100 * count) / static_cast<double>(tables.size()), 0.1, 0.05)
- << reservation;
- }
}
-#endif // ABSL_INTERNAL_HASHTABLEZ_SAMPLE
+#endif // ABSL_HASHTABLEZ_SAMPLER
TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
// Enable the feature even if the prod default is off.
SetHashtablezEnabled(true);
SetHashtablezSampleParameter(100);
- auto& sampler = GlobalHashtablezSampler();
+ auto& sampler = HashtablezSampler::Global();
size_t start_size = 0;
start_size += sampler.Iterate([&](const HashtablezInfo&) { ++start_size; });
@@ -2118,7 +1839,7 @@ TEST(RawHashSamplerTest, DoNotSampleCustomAllocators) {
0.00, 0.001);
}
-#ifdef ABSL_HAVE_ADDRESS_SANITIZER
+#ifdef ADDRESS_SANITIZER
TEST(Sanitizer, PoisoningUnused) {
IntTable t;
t.reserve(5);
@@ -2142,37 +1863,7 @@ TEST(Sanitizer, PoisoningOnErase) {
t.erase(0);
EXPECT_TRUE(__asan_address_is_poisoned(&v));
}
-#endif // ABSL_HAVE_ADDRESS_SANITIZER
-
-TEST(Table, AlignOne) {
- // We previously had a bug in which we were copying a control byte over the
- // first slot when alignof(value_type) is 1. We test repeated
- // insertions/erases and verify that the behavior is correct.
- Uint8Table t;
- std::unordered_set<uint8_t> verifier; // NOLINT
-
- // Do repeated insertions/erases from the table.
- for (int64_t i = 0; i < 100000; ++i) {
- SCOPED_TRACE(i);
- const uint8_t u = (i * -i) & 0xFF;
- auto it = t.find(u);
- auto verifier_it = verifier.find(u);
- if (it == t.end()) {
- ASSERT_EQ(verifier_it, verifier.end());
- t.insert(u);
- verifier.insert(u);
- } else {
- ASSERT_NE(verifier_it, verifier.end());
- t.erase(it);
- verifier.erase(verifier_it);
- }
- }
-
- EXPECT_EQ(t.size(), verifier.size());
- for (uint8_t u : t) {
- EXPECT_EQ(verifier.count(u), 1);
- }
-}
+#endif // ADDRESS_SANITIZER
} // namespace
} // namespace container_internal
diff --git a/third_party/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h b/third_party/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
index c1d20f3c52..76ee95e6ab 100644
--- a/third_party/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
+++ b/third_party/abseil-cpp/absl/container/internal/unordered_map_constructor_test.h
@@ -16,7 +16,6 @@
#define ABSL_CONTAINER_INTERNAL_UNORDERED_MAP_CONSTRUCTOR_TEST_H_
#include <algorithm>
-#include <unordered_map>
#include <vector>
#include "gmock/gmock.h"
@@ -179,7 +178,7 @@ TYPED_TEST_P(ConstructorTest, InputIteratorBucketHashEqualAlloc) {
A alloc(0);
std::vector<T> values;
std::generate_n(std::back_inserter(values), 10,
- hash_internal::UniqueGenerator<T>());
+ hash_internal::Generator<T>());
TypeParam m(values.begin(), values.end(), 123, hasher, equal, alloc);
EXPECT_EQ(m.hash_function(), hasher);
EXPECT_EQ(m.key_eq(), equal);
@@ -198,7 +197,7 @@ void InputIteratorBucketAllocTest(std::true_type) {
A alloc(0);
std::vector<T> values;
std::generate_n(std::back_inserter(values), 10,
- hash_internal::UniqueGenerator<T>());
+ hash_internal::Generator<T>());
TypeParam m(values.begin(), values.end(), 123, alloc);
EXPECT_EQ(m.get_allocator(), alloc);
EXPECT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
@@ -221,7 +220,7 @@ void InputIteratorBucketHashAllocTest(std::true_type) {
A alloc(0);
std::vector<T> values;
std::generate_n(std::back_inserter(values), 10,
- hash_internal::UniqueGenerator<T>());
+ hash_internal::Generator<T>());
TypeParam m(values.begin(), values.end(), 123, hasher, alloc);
EXPECT_EQ(m.hash_function(), hasher);
EXPECT_EQ(m.get_allocator(), alloc);
@@ -241,9 +240,8 @@ TYPED_TEST_P(ConstructorTest, CopyConstructor) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
TypeParam m(123, hasher, equal, alloc);
- for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
TypeParam n(m);
EXPECT_EQ(m.hash_function(), n.hash_function());
EXPECT_EQ(m.key_eq(), n.key_eq());
@@ -263,9 +261,8 @@ void CopyConstructorAllocTest(std::true_type) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
TypeParam m(123, hasher, equal, alloc);
- for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
TypeParam n(m, A(11));
EXPECT_EQ(m.hash_function(), n.hash_function());
EXPECT_EQ(m.key_eq(), n.key_eq());
@@ -287,9 +284,8 @@ TYPED_TEST_P(ConstructorTest, MoveConstructor) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
TypeParam m(123, hasher, equal, alloc);
- for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
TypeParam t(m);
TypeParam n(std::move(t));
EXPECT_EQ(m.hash_function(), n.hash_function());
@@ -310,9 +306,8 @@ void MoveConstructorAllocTest(std::true_type) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
TypeParam m(123, hasher, equal, alloc);
- for (size_t i = 0; i != 10; ++i) m.insert(gen());
+ for (size_t i = 0; i != 10; ++i) m.insert(hash_internal::Generator<T>()());
TypeParam t(m);
TypeParam n(std::move(t), A(1));
EXPECT_EQ(m.hash_function(), n.hash_function());
@@ -329,7 +324,7 @@ TYPED_TEST_P(ConstructorTest, MoveConstructorAlloc) {
TYPED_TEST_P(ConstructorTest, InitializerListBucketHashEqualAlloc) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
using H = typename TypeParam::hasher;
using E = typename TypeParam::key_equal;
@@ -352,7 +347,7 @@ template <typename TypeParam>
void InitializerListBucketAllocTest(std::true_type) {
using T = hash_internal::GeneratedType<TypeParam>;
using A = typename TypeParam::allocator_type;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
A alloc(0);
TypeParam m(values, 123, alloc);
@@ -375,7 +370,7 @@ void InitializerListBucketHashAllocTest(std::true_type) {
using A = typename TypeParam::allocator_type;
H hasher;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
TypeParam m(values, 123, hasher, alloc);
EXPECT_EQ(m.hash_function(), hasher);
@@ -396,7 +391,7 @@ TYPED_TEST_P(ConstructorTest, Assignment) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
TypeParam n;
n = m;
@@ -416,7 +411,7 @@ TYPED_TEST_P(ConstructorTest, MoveAssignment) {
H hasher;
E equal;
A alloc(0);
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
TypeParam m({gen(), gen(), gen()}, 123, hasher, equal, alloc);
TypeParam t(m);
TypeParam n;
@@ -428,7 +423,7 @@ TYPED_TEST_P(ConstructorTest, MoveAssignment) {
TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
TypeParam m;
m = values;
@@ -437,7 +432,7 @@ TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerList) {
TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
TypeParam m({gen(), gen(), gen()});
TypeParam n({gen()});
n = m;
@@ -446,7 +441,7 @@ TYPED_TEST_P(ConstructorTest, AssignmentOverwritesExisting) {
TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
TypeParam m({gen(), gen(), gen()});
TypeParam t(m);
TypeParam n({gen()});
@@ -456,7 +451,7 @@ TYPED_TEST_P(ConstructorTest, MoveAssignmentOverwritesExisting) {
TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
TypeParam m;
m = values;
@@ -465,7 +460,7 @@ TYPED_TEST_P(ConstructorTest, AssignmentFromInitializerListOverwritesExisting) {
TYPED_TEST_P(ConstructorTest, AssignmentOnSelf) {
using T = hash_internal::GeneratedType<TypeParam>;
- hash_internal::UniqueGenerator<T> gen;
+ hash_internal::Generator<T> gen;
std::initializer_list<T> values = {gen(), gen(), gen(), gen(), gen()};
TypeParam m(values);
m = *&m; // Avoid -Wself-assign
diff --git a/third_party/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h b/third_party/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
index d3543936f7..b8c513f157 100644
--- a/third_party/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
+++ b/third_party/abseil-cpp/absl/container/internal/unordered_map_modifiers_test.h
@@ -81,38 +81,6 @@ TYPED_TEST_P(ModifiersTest, InsertRange) {
ASSERT_THAT(items(m), ::testing::UnorderedElementsAreArray(values));
}
-TYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {
- using T = hash_internal::GeneratedType<TypeParam>;
- using V = typename TypeParam::mapped_type;
- T val = hash_internal::Generator<T>()();
- TypeParam m;
- m.reserve(10);
- const size_t original_capacity = m.bucket_count();
- m.insert(val);
- EXPECT_EQ(m.bucket_count(), original_capacity);
- T val2 = {val.first, hash_internal::Generator<V>()()};
- m.insert(val2);
- EXPECT_EQ(m.bucket_count(), original_capacity);
-}
-
-TYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {
-#if !defined(__GLIBCXX__)
- using T = hash_internal::GeneratedType<TypeParam>;
- std::vector<T> base_values;
- std::generate_n(std::back_inserter(base_values), 10,
- hash_internal::Generator<T>());
- std::vector<T> values;
- while (values.size() != 100) {
- std::copy_n(base_values.begin(), 10, std::back_inserter(values));
- }
- TypeParam m;
- m.reserve(10);
- const size_t original_capacity = m.bucket_count();
- m.insert(values.begin(), values.end());
- EXPECT_EQ(m.bucket_count(), original_capacity);
-#endif
-}
-
TYPED_TEST_P(ModifiersTest, InsertOrAssign) {
#ifdef UNORDERED_MAP_CXX17
using std::get;
@@ -298,10 +266,9 @@ TYPED_TEST_P(ModifiersTest, Swap) {
// TODO(alkis): Write tests for merge.
REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
- InsertRange, InsertWithinCapacity,
- InsertRangeWithinCapacity, InsertOrAssign,
- InsertOrAssignHint, Emplace, EmplaceHint, TryEmplace,
- TryEmplaceHint, Erase, EraseRange, EraseKey, Swap);
+ InsertRange, InsertOrAssign, InsertOrAssignHint,
+ Emplace, EmplaceHint, TryEmplace, TryEmplaceHint,
+ Erase, EraseRange, EraseKey, Swap);
template <typename Type>
struct is_unique_ptr : std::false_type {};
@@ -319,8 +286,6 @@ class UniquePtrModifiersTest : public ::testing::Test {
}
};
-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
diff --git a/third_party/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h b/third_party/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
index 6e473e45da..26be58d99f 100644
--- a/third_party/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
+++ b/third_party/abseil-cpp/absl/container/internal/unordered_set_modifiers_test.h
@@ -74,36 +74,6 @@ TYPED_TEST_P(ModifiersTest, InsertRange) {
ASSERT_THAT(keys(m), ::testing::UnorderedElementsAreArray(values));
}
-TYPED_TEST_P(ModifiersTest, InsertWithinCapacity) {
- using T = hash_internal::GeneratedType<TypeParam>;
- T val = hash_internal::Generator<T>()();
- TypeParam m;
- m.reserve(10);
- const size_t original_capacity = m.bucket_count();
- m.insert(val);
- EXPECT_EQ(m.bucket_count(), original_capacity);
- m.insert(val);
- EXPECT_EQ(m.bucket_count(), original_capacity);
-}
-
-TYPED_TEST_P(ModifiersTest, InsertRangeWithinCapacity) {
-#if !defined(__GLIBCXX__)
- using T = hash_internal::GeneratedType<TypeParam>;
- std::vector<T> base_values;
- std::generate_n(std::back_inserter(base_values), 10,
- hash_internal::Generator<T>());
- std::vector<T> values;
- while (values.size() != 100) {
- values.insert(values.end(), base_values.begin(), base_values.end());
- }
- TypeParam m;
- m.reserve(10);
- const size_t original_capacity = m.bucket_count();
- m.insert(values.begin(), values.end());
- EXPECT_EQ(m.bucket_count(), original_capacity);
-#endif
-}
-
TYPED_TEST_P(ModifiersTest, Emplace) {
using T = hash_internal::GeneratedType<TypeParam>;
T val = hash_internal::Generator<T>()();
@@ -210,9 +180,8 @@ TYPED_TEST_P(ModifiersTest, Swap) {
// TODO(alkis): Write tests for merge.
REGISTER_TYPED_TEST_CASE_P(ModifiersTest, Clear, Insert, InsertHint,
- InsertRange, InsertWithinCapacity,
- InsertRangeWithinCapacity, Emplace, EmplaceHint,
- Erase, EraseRange, EraseKey, Swap);
+ InsertRange, Emplace, EmplaceHint, Erase, EraseRange,
+ EraseKey, Swap);
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/container/node_hash_map.h b/third_party/abseil-cpp/absl/container/node_hash_map.h
index 7a39f6284c..fccea1841c 100644
--- a/third_party/abseil-cpp/absl/container/node_hash_map.h
+++ b/third_party/abseil-cpp/absl/container/node_hash_map.h
@@ -225,8 +225,7 @@ class node_hash_map
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists, returning the
- // number of elements erased (0 or 1).
+ // Erases the element with the matching key, if it exists.
using Base::erase;
// node_hash_map::insert()
@@ -375,11 +374,6 @@ 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()
@@ -520,6 +514,12 @@ 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)
diff --git a/third_party/abseil-cpp/absl/container/node_hash_map_test.cc b/third_party/abseil-cpp/absl/container/node_hash_map_test.cc
index 8f59a1e4a2..5d74b814b5 100644
--- a/third_party/abseil-cpp/absl/container/node_hash_map_test.cc
+++ b/third_party/abseil-cpp/absl/container/node_hash_map_test.cc
@@ -254,21 +254,6 @@ TEST(NodeHashMap, EraseIf) {
}
}
-// 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
diff --git a/third_party/abseil-cpp/absl/container/node_hash_set.h b/third_party/abseil-cpp/absl/container/node_hash_set.h
index 93b15f4681..ad54b6dccb 100644
--- a/third_party/abseil-cpp/absl/container/node_hash_set.h
+++ b/third_party/abseil-cpp/absl/container/node_hash_set.h
@@ -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 set elements can be done
+// `unordered_set`, search, insertion, and deletion of map 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
@@ -60,7 +60,7 @@ struct NodeHashSetPolicy;
// following notable differences:
//
// * Supports heterogeneous lookup, through `find()`, `operator[]()` and
-// `insert()`, provided that the set is provided a compatible heterogeneous
+// `insert()`, provided that the map 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.
@@ -76,13 +76,13 @@ struct NodeHashSetPolicy;
// Example:
//
// // Create a node hash set of three strings
-// absl::node_hash_set<std::string> ducks =
+// absl::node_hash_map<std::string, std::string> ducks =
// {"huey", "dewey", "louie"};
//
-// // Insert a new element into the node hash set
-// ducks.insert("donald");
+// // Insert a new element into the node hash map
+// ducks.insert("donald"};
//
-// // Force a rehash of the node hash set
+// // Force a rehash of the node hash map
// ducks.rehash(0);
//
// // See if "dewey" is present
@@ -100,7 +100,7 @@ class node_hash_set
public:
// Constructors and Assignment Operators
//
- // A node_hash_set supports the same overload set as `std::unordered_set`
+ // A node_hash_set supports the same overload set as `std::unordered_map`
// for construction and assignment:
//
// * Default constructor
@@ -167,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_set` API.
+ // not provided in the `std::unordered_map` API.
using Base::capacity;
// node_hash_set::empty()
@@ -208,7 +208,7 @@ class node_hash_set
// `void`.
//
// NOTE: this return behavior is different than that of STL containers in
- // general and `std::unordered_set` in particular.
+ // general and `std::unordered_map` in particular.
//
// iterator erase(const_iterator first, const_iterator last):
//
@@ -217,8 +217,7 @@ class node_hash_set
//
// size_type erase(const key_type& key):
//
- // Erases the element with the matching key, if it exists, returning the
- // number of elements erased (0 or 1).
+ // Erases the element with the matching key, if it exists.
using Base::erase;
// node_hash_set::insert()
@@ -314,7 +313,7 @@ class node_hash_set
// node_hash_set::merge()
//
- // Extracts elements from a given `source` node hash set into this
+ // Extracts elements from a given `source` flat hash map 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;
@@ -322,15 +321,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`
- // node hash set, avoiding invocation of any move, copy, or swap operations on
+ // flat hash map, avoiding invocation of any move, copy, or swap operations on
// individual elements.
//
// All iterators and references on the `node_hash_set` remain valid, excepting
// for the past-the-end iterator, which is invalidated.
//
- // `swap()` requires that the node hash set's hashing and key equivalence
+ // `swap()` requires that the flat hash set's hashing and key equivalence
// functions be Swappable, and are exchaged using unqualified calls to
- // non-member `swap()`. If the set's allocator has
+ // non-member `swap()`. If the map's allocator has
// `std::allocator_traits<allocator_type>::propagate_on_container_swap::value`
// set to `true`, the allocators are also exchanged using an unqualified call
// to non-member `swap()`; otherwise, the allocators are not swapped.
@@ -385,14 +384,14 @@ class node_hash_set
// node_hash_set::bucket_count()
//
// Returns the number of "buckets" within the `node_hash_set`. Note that
- // because a node hash set contains all elements within its internal storage,
+ // because a flat hash map contains all elements within its internal storage,
// this value simply equals the current capacity of the `node_hash_set`.
using Base::bucket_count;
// node_hash_set::load_factor()
//
// Returns the current load factor of the `node_hash_set` (the average number
- // of slots occupied with a value within the hash set).
+ // of slots occupied with a value within the hash map).
using Base::load_factor;
// node_hash_set::max_load_factor()
@@ -428,6 +427,12 @@ 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)
diff --git a/third_party/abseil-cpp/absl/container/sample_element_size_test.cc b/third_party/abseil-cpp/absl/container/sample_element_size_test.cc
deleted file mode 100644
index b23626b409..0000000000
--- a/third_party/abseil-cpp/absl/container/sample_element_size_test.cc
+++ /dev/null
@@ -1,114 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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 "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/container/flat_hash_map.h"
-#include "absl/container/flat_hash_set.h"
-#include "absl/container/node_hash_map.h"
-#include "absl/container/node_hash_set.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace container_internal {
-namespace {
-
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
-// Create some tables of type `Table`, then look at all the new
-// `HashtablezInfo`s to make sure that the `inline_element_size ==
-// expected_element_size`. The `inline_element_size` is the amount of memory
-// allocated for each slot of a hash table, that is `sizeof(slot_type)`. Add
-// the new `HashtablezInfo`s to `preexisting_info`. Store all the new tables
-// into `tables`.
-template <class Table>
-void TestInlineElementSize(
- HashtablezSampler& sampler,
- // clang-tidy gives a false positive on this declaration. This unordered
- // set cannot be flat_hash_set, however, since that would introduce a mutex
- // deadlock.
- std::unordered_set<const HashtablezInfo*>& preexisting_info, // NOLINT
- std::vector<Table>& tables, const typename Table::value_type& elt,
- size_t expected_element_size) {
- for (int i = 0; i < 10; ++i) {
- // We create a new table and must store it somewhere so that when we store
- // a pointer to the resulting `HashtablezInfo` into `preexisting_info`
- // that we aren't storing a dangling pointer.
- tables.emplace_back();
- // We must insert an element to get a hashtablez to instantiate.
- tables.back().insert(elt);
- }
- size_t new_count = 0;
- sampler.Iterate([&](const HashtablezInfo& info) {
- if (preexisting_info.insert(&info).second) {
- EXPECT_EQ(info.inline_element_size, expected_element_size);
- ++new_count;
- }
- });
- // Make sure we actually did get a new hashtablez.
- EXPECT_GT(new_count, 0);
-}
-
-struct bigstruct {
- char a[1000];
- friend bool operator==(const bigstruct& x, const bigstruct& y) {
- return memcmp(x.a, y.a, sizeof(x.a)) == 0;
- }
- template <typename H>
- friend H AbslHashValue(H h, const bigstruct& c) {
- return H::combine_contiguous(std::move(h), c.a, sizeof(c.a));
- }
-};
-#endif
-
-TEST(FlatHashMap, SampleElementSize) {
-#if defined(ABSL_INTERNAL_HASHTABLEZ_SAMPLE)
- // Enable sampling even if the prod default is off.
- SetHashtablezEnabled(true);
- SetHashtablezSampleParameter(1);
-
- auto& sampler = GlobalHashtablezSampler();
- std::vector<flat_hash_map<int, bigstruct>> flat_map_tables;
- std::vector<flat_hash_set<bigstruct>> flat_set_tables;
- std::vector<node_hash_map<int, bigstruct>> node_map_tables;
- std::vector<node_hash_set<bigstruct>> node_set_tables;
-
- // It takes thousands of new tables after changing the sampling parameters
- // before you actually get some instrumentation. And if you must actually
- // put something into those tables.
- for (int i = 0; i < 10000; ++i) {
- flat_map_tables.emplace_back();
- flat_map_tables.back()[i] = bigstruct{};
- }
-
- // clang-tidy gives a false positive on this declaration. This unordered set
- // cannot be a flat_hash_set, however, since that would introduce a mutex
- // deadlock.
- std::unordered_set<const HashtablezInfo*> preexisting_info; // NOLINT
- sampler.Iterate(
- [&](const HashtablezInfo& info) { preexisting_info.insert(&info); });
- TestInlineElementSize(sampler, preexisting_info, flat_map_tables,
- {0, bigstruct{}}, sizeof(int) + sizeof(bigstruct));
- TestInlineElementSize(sampler, preexisting_info, node_map_tables,
- {0, bigstruct{}}, sizeof(void*));
- TestInlineElementSize(sampler, preexisting_info, flat_set_tables, //
- bigstruct{}, sizeof(bigstruct));
- TestInlineElementSize(sampler, preexisting_info, node_set_tables, //
- bigstruct{}, sizeof(void*));
-#endif
-}
-
-} // namespace
-} // namespace container_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake b/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
index 942ce90a4d..77d4ace8be 100644
--- a/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
+++ b/third_party/abseil-cpp/absl/copts/AbseilConfigureCopts.cmake
@@ -12,16 +12,16 @@ else()
set(ABSL_BUILD_DLL FALSE)
endif()
-if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|amd64|AMD64")
+if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" OR "${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "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")
+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")
+ 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.")
@@ -32,18 +32,20 @@ else()
endif()
-if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+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
+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}")
+ set(ABSL_DEFAULT_LINKOPTS "${ABSL_MSVC_LINKOPTS}")
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")
+ 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)
@@ -52,7 +54,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # MATCHES so we get both Clang an
endif()
endif()
endif()
-elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+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}")
@@ -62,4 +64,11 @@ else()
set(ABSL_TEST_COPTS "")
endif()
-set(ABSL_CXX_STANDARD "${CMAKE_CXX_STANDARD}")
+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()
diff --git a/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake b/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
index a4ab1aa204..7ef6339be2 100644
--- a/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
+++ b/third_party/abseil-cpp/absl/copts/GENERATED_AbseilCopts.cmake
@@ -5,6 +5,47 @@
list(APPEND ABSL_CLANG_CL_FLAGS
"/W3"
+ "-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"
+ "-Wno-float-conversion"
+ "-Wno-float-equal"
+ "-Wno-format-nonliteral"
+ "-Wno-gcc-compat"
+ "-Wno-global-constructors"
+ "-Wno-exit-time-destructors"
+ "-Wno-non-modular-include-in-module"
+ "-Wno-old-style-cast"
+ "-Wno-range-loop-analysis"
+ "-Wno-reserved-id-macro"
+ "-Wno-shorten-64-to-32"
+ "-Wno-switch-enum"
+ "-Wno-thread-safety-negative"
+ "-Wno-unknown-warning-option"
+ "-Wno-unreachable-code"
+ "-Wno-unused-macros"
+ "-Wno-weak-vtables"
+ "-Wno-zero-as-null-pointer-constant"
+ "-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"
"/DWIN32_LEAN_AND_MEAN"
"/D_CRT_SECURE_NO_WARNINGS"
@@ -37,17 +78,16 @@ list(APPEND ABSL_GCC_FLAGS
"-Wextra"
"-Wcast-qual"
"-Wconversion-null"
- "-Wformat-security"
"-Wmissing-declarations"
"-Woverlength-strings"
"-Wpointer-arith"
- "-Wundef"
"-Wunused-local-typedefs"
"-Wunused-result"
"-Wvarargs"
"-Wvla"
"-Wwrite-strings"
- "-DNOMINMAX"
+ "-Wno-missing-field-initializers"
+ "-Wno-sign-compare"
)
list(APPEND ABSL_GCC_TEST_FLAGS
@@ -63,39 +103,48 @@ list(APPEND ABSL_GCC_TEST_FLAGS
list(APPEND ABSL_LLVM_FLAGS
"-Wall"
"-Wextra"
- "-Wcast-qual"
- "-Wconversion"
- "-Wfloat-overflow-conversion"
- "-Wfloat-zero-conversion"
- "-Wfor-loop-analysis"
- "-Wformat-security"
- "-Wgnu-redeclared-enum"
- "-Winfinite-recursion"
- "-Winvalid-constexpr"
- "-Wliteral-conversion"
- "-Wmissing-declarations"
- "-Woverlength-strings"
- "-Wpointer-arith"
- "-Wself-assign"
- "-Wshadow-all"
- "-Wstring-conversion"
- "-Wtautological-overlap-compare"
- "-Wundef"
- "-Wuninitialized"
- "-Wunreachable-code"
- "-Wunused-comparison"
- "-Wunused-local-typedefs"
- "-Wunused-result"
- "-Wvla"
- "-Wwrite-strings"
+ "-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"
"-Wno-float-conversion"
- "-Wno-implicit-float-conversion"
- "-Wno-implicit-int-float-conversion"
- "-Wno-implicit-int-conversion"
+ "-Wno-float-equal"
+ "-Wno-format-nonliteral"
+ "-Wno-gcc-compat"
+ "-Wno-global-constructors"
+ "-Wno-exit-time-destructors"
+ "-Wno-non-modular-include-in-module"
+ "-Wno-old-style-cast"
+ "-Wno-range-loop-analysis"
+ "-Wno-reserved-id-macro"
"-Wno-shorten-64-to-32"
- "-Wno-sign-conversion"
+ "-Wno-switch-enum"
+ "-Wno-thread-safety-negative"
"-Wno-unknown-warning-option"
- "-DNOMINMAX"
+ "-Wno-unreachable-code"
+ "-Wno-unused-macros"
+ "-Wno-weak-vtables"
+ "-Wno-zero-as-null-pointer-constant"
+ "-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"
)
list(APPEND ABSL_LLVM_TEST_FLAGS
diff --git a/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl b/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl
index a6efc98e11..3cc487845c 100644
--- a/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl
+++ b/third_party/abseil-cpp/absl/copts/GENERATED_copts.bzl
@@ -6,6 +6,47 @@
ABSL_CLANG_CL_FLAGS = [
"/W3",
+ "-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",
+ "-Wno-float-conversion",
+ "-Wno-float-equal",
+ "-Wno-format-nonliteral",
+ "-Wno-gcc-compat",
+ "-Wno-global-constructors",
+ "-Wno-exit-time-destructors",
+ "-Wno-non-modular-include-in-module",
+ "-Wno-old-style-cast",
+ "-Wno-range-loop-analysis",
+ "-Wno-reserved-id-macro",
+ "-Wno-shorten-64-to-32",
+ "-Wno-switch-enum",
+ "-Wno-thread-safety-negative",
+ "-Wno-unknown-warning-option",
+ "-Wno-unreachable-code",
+ "-Wno-unused-macros",
+ "-Wno-weak-vtables",
+ "-Wno-zero-as-null-pointer-constant",
+ "-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",
"/DWIN32_LEAN_AND_MEAN",
"/D_CRT_SECURE_NO_WARNINGS",
@@ -38,17 +79,16 @@ ABSL_GCC_FLAGS = [
"-Wextra",
"-Wcast-qual",
"-Wconversion-null",
- "-Wformat-security",
"-Wmissing-declarations",
"-Woverlength-strings",
"-Wpointer-arith",
- "-Wundef",
"-Wunused-local-typedefs",
"-Wunused-result",
"-Wvarargs",
"-Wvla",
"-Wwrite-strings",
- "-DNOMINMAX",
+ "-Wno-missing-field-initializers",
+ "-Wno-sign-compare",
]
ABSL_GCC_TEST_FLAGS = [
@@ -64,39 +104,48 @@ ABSL_GCC_TEST_FLAGS = [
ABSL_LLVM_FLAGS = [
"-Wall",
"-Wextra",
- "-Wcast-qual",
- "-Wconversion",
- "-Wfloat-overflow-conversion",
- "-Wfloat-zero-conversion",
- "-Wfor-loop-analysis",
- "-Wformat-security",
- "-Wgnu-redeclared-enum",
- "-Winfinite-recursion",
- "-Winvalid-constexpr",
- "-Wliteral-conversion",
- "-Wmissing-declarations",
- "-Woverlength-strings",
- "-Wpointer-arith",
- "-Wself-assign",
- "-Wshadow-all",
- "-Wstring-conversion",
- "-Wtautological-overlap-compare",
- "-Wundef",
- "-Wuninitialized",
- "-Wunreachable-code",
- "-Wunused-comparison",
- "-Wunused-local-typedefs",
- "-Wunused-result",
- "-Wvla",
- "-Wwrite-strings",
+ "-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",
"-Wno-float-conversion",
- "-Wno-implicit-float-conversion",
- "-Wno-implicit-int-float-conversion",
- "-Wno-implicit-int-conversion",
+ "-Wno-float-equal",
+ "-Wno-format-nonliteral",
+ "-Wno-gcc-compat",
+ "-Wno-global-constructors",
+ "-Wno-exit-time-destructors",
+ "-Wno-non-modular-include-in-module",
+ "-Wno-old-style-cast",
+ "-Wno-range-loop-analysis",
+ "-Wno-reserved-id-macro",
"-Wno-shorten-64-to-32",
- "-Wno-sign-conversion",
+ "-Wno-switch-enum",
+ "-Wno-thread-safety-negative",
"-Wno-unknown-warning-option",
- "-DNOMINMAX",
+ "-Wno-unreachable-code",
+ "-Wno-unused-macros",
+ "-Wno-weak-vtables",
+ "-Wno-zero-as-null-pointer-constant",
+ "-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",
]
ABSL_LLVM_TEST_FLAGS = [
diff --git a/third_party/abseil-cpp/absl/copts/configure_copts.bzl b/third_party/abseil-cpp/absl/copts/configure_copts.bzl
index 40d5849a3a..9dd6bd0ae4 100644
--- a/third_party/abseil-cpp/absl/copts/configure_copts.bzl
+++ b/third_party/abseil-cpp/absl/copts/configure_copts.bzl
@@ -22,21 +22,21 @@ load(
)
ABSL_DEFAULT_COPTS = select({
- "//absl:msvc_compiler": ABSL_MSVC_FLAGS,
- "//absl:clang-cl_compiler": ABSL_CLANG_CL_FLAGS,
- "//absl:clang_compiler": ABSL_LLVM_FLAGS,
+ "//absl:windows": ABSL_MSVC_FLAGS,
+ "//absl:llvm_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:msvc_compiler": ABSL_MSVC_TEST_FLAGS,
- "//absl:clang-cl_compiler": ABSL_CLANG_CL_TEST_FLAGS,
- "//absl:clang_compiler": ABSL_LLVM_TEST_FLAGS,
+ "//absl:windows": ABSL_MSVC_TEST_FLAGS,
+ "//absl:llvm_compiler": ABSL_LLVM_TEST_FLAGS,
"//conditions:default": ABSL_GCC_TEST_FLAGS,
})
ABSL_DEFAULT_LINKOPTS = select({
- "//absl:msvc_compiler": ABSL_MSVC_LINKOPTS,
+ "//absl:windows": ABSL_MSVC_LINKOPTS,
"//conditions:default": [],
})
@@ -48,9 +48,8 @@ ABSL_RANDOM_RANDEN_COPTS = select({
":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_haswell": ABSL_RANDOM_HWAES_X64_FLAGS,
":cpu_ppc": ["-mcrypto"],
- ":cpu_aarch64": ABSL_RANDOM_HWAES_ARM64_FLAGS,
# Supported by default or unsupported.
"//conditions:default": [],
@@ -66,12 +65,11 @@ def absl_random_randen_copts_init():
# These configs have consistent flags to enable HWAES intsructions.
cpu_configs = [
"ppc",
- "k8",
+ "haswell",
"darwin_x86_64",
"darwin",
"x64_windows_msvc",
"x64_windows",
- "aarch64",
]
for cpu in cpu_configs:
native.config_setting(
diff --git a/third_party/abseil-cpp/absl/copts/copts.py b/third_party/abseil-cpp/absl/copts/copts.py
index 0d6c1ec3a6..704ef23450 100644
--- a/third_party/abseil-cpp/absl/copts/copts.py
+++ b/third_party/abseil-cpp/absl/copts/copts.py
@@ -16,6 +16,77 @@ MSVC_BIG_WARNING_FLAGS = [
"/W3",
]
+LLVM_BIG_WARNING_FLAGS = [
+ "-Wall",
+ "-Wextra",
+ "-Weverything",
+]
+
+# Docs on single flags is preceded by a comment.
+# Docs on groups of flags is preceded by ###.
+LLVM_DISABLE_WARNINGS_FLAGS = [
+ # 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",
+ ###
+ "-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-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-shorten-64-to-32",
+ "-Wno-switch-enum",
+ "-Wno-thread-safety-negative",
+ "-Wno-unknown-warning-option",
+ "-Wno-unreachable-code",
+ # Causes warnings on include guards
+ "-Wno-unused-macros",
+ "-Wno-weak-vtables",
+ # Causes warnings on usage of types/compare.h comparison operators.
+ "-Wno-zero-as-null-pointer-constant",
+ ###
+ # 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_DISABLE_WARNINGS_FLAGS = [
"-Wno-c99-extensions",
"-Wno-deprecated-declarations",
@@ -54,18 +125,21 @@ COPT_VARS = {
"-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",
- # Don't define min and max macros (Build on Windows using gcc)
- "-DNOMINMAX",
+ # gcc-4.x has spurious missing field initializer warnings.
+ # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
+ # Remove when gcc-4.x is no longer supported.
+ "-Wno-missing-field-initializers",
+ # Google style does not use unsigned integers, though STL containers
+ # have unsigned types.
+ "-Wno-sign-compare",
],
"ABSL_GCC_TEST_FLAGS": [
"-Wno-conversion-null",
@@ -76,52 +150,12 @@ COPT_VARS = {
"-Wno-unused-parameter",
"-Wno-unused-private-field",
],
- "ABSL_LLVM_FLAGS": [
- "-Wall",
- "-Wextra",
- "-Wcast-qual",
- "-Wconversion",
- "-Wfloat-overflow-conversion",
- "-Wfloat-zero-conversion",
- "-Wfor-loop-analysis",
- "-Wformat-security",
- "-Wgnu-redeclared-enum",
- "-Winfinite-recursion",
- "-Winvalid-constexpr",
- "-Wliteral-conversion",
- "-Wmissing-declarations",
- "-Woverlength-strings",
- "-Wpointer-arith",
- "-Wself-assign",
- "-Wshadow-all",
- "-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-implicit-float-conversion",
- "-Wno-implicit-int-float-conversion",
- "-Wno-implicit-int-conversion",
- "-Wno-shorten-64-to-32",
- "-Wno-sign-conversion",
- # Disable warnings on unknown warning flags (when warning flags are
- # unknown on older compiler versions)
- "-Wno-unknown-warning-option",
- # Don't define min and max macros (Build on Windows using clang)
- "-DNOMINMAX",
- ],
+ "ABSL_LLVM_FLAGS":
+ LLVM_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS,
"ABSL_LLVM_TEST_FLAGS":
LLVM_TEST_DISABLE_WARNINGS_FLAGS,
"ABSL_CLANG_CL_FLAGS":
- (MSVC_BIG_WARNING_FLAGS + MSVC_DEFINES),
+ (MSVC_BIG_WARNING_FLAGS + LLVM_DISABLE_WARNINGS_FLAGS + MSVC_DEFINES),
"ABSL_CLANG_CL_TEST_FLAGS":
LLVM_TEST_DISABLE_WARNINGS_FLAGS,
"ABSL_MSVC_FLAGS":
diff --git a/third_party/abseil-cpp/absl/copts/generate_copts.py b/third_party/abseil-cpp/absl/copts/generate_copts.py
index 34be2fc23b..0e5dc9fad2 100755..100644
--- a/third_party/abseil-cpp/absl/copts/generate_copts.py
+++ b/third_party/abseil-cpp/absl/copts/generate_copts.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python3
+#!/usr/bin/python
"""Generate Abseil compile compile option configs.
Usage: <path_to_absl>/copts/generate_copts.py
diff --git a/third_party/abseil-cpp/absl/debugging/BUILD.bazel b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
index 3c4ea8dcdf..8f521bec46 100644
--- a/third_party/abseil-cpp/absl/debugging/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/debugging/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -25,7 +26,7 @@ package(
default_visibility = ["//visibility:public"],
)
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "stacktrace",
@@ -33,10 +34,8 @@ cc_library(
"internal/stacktrace_aarch64-inl.inc",
"internal/stacktrace_arm-inl.inc",
"internal/stacktrace_config.h",
- "internal/stacktrace_emscripten-inl.inc",
"internal/stacktrace_generic-inl.inc",
"internal/stacktrace_powerpc-inl.inc",
- "internal/stacktrace_riscv-inl.inc",
"internal/stacktrace_unimplemented-inl.inc",
"internal/stacktrace_win32-inl.inc",
"internal/stacktrace_x86-inl.inc",
@@ -56,9 +55,7 @@ cc_library(
name = "symbolize",
srcs = [
"symbolize.cc",
- "symbolize_darwin.inc",
"symbolize_elf.inc",
- "symbolize_emscripten.inc",
"symbolize_unimplemented.inc",
"symbolize_win32.inc",
],
@@ -68,8 +65,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS + select({
- "//absl:msvc_compiler": ["-DEFAULTLIB:dbghelp.lib"],
- "//absl:clang-cl_compiler": ["-DEFAULTLIB:dbghelp.lib"],
+ "//absl:windows": ["-DEFAULTLIB:dbghelp.lib"],
"//conditions:default": [],
}),
deps = [
@@ -81,7 +77,6 @@ cc_library(
"//absl/base:dynamic_annotations",
"//absl/base:malloc_internal",
"//absl/base:raw_logging_internal",
- "//absl/strings",
],
)
@@ -89,24 +84,20 @@ cc_test(
name = "symbolize_test",
srcs = ["symbolize_test.cc"],
copts = ABSL_TEST_COPTS + select({
- "//absl:msvc_compiler": ["/Z7"],
- "//absl:clang-cl_compiler": ["/Z7"],
+ "//absl:windows": ["/Z7"],
"//conditions:default": [],
}),
linkopts = ABSL_DEFAULT_LINKOPTS + select({
- "//absl:msvc_compiler": ["/DEBUG"],
- "//absl:clang-cl_compiler": ["/DEBUG"],
+ "//absl:windows": ["/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",
],
)
@@ -153,9 +144,7 @@ cc_test(
srcs = ["failure_signal_handler_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = select({
- "//absl:msvc_compiler": [],
- "//absl:clang-cl_compiler": [],
- "//absl:wasm": [],
+ "//absl:windows": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -182,7 +171,6 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
deps = [
"//absl/base:config",
"//absl/base:core_headers",
@@ -197,7 +185,6 @@ cc_library(
srcs = ["internal/demangle.cc"],
hdrs = ["internal/demangle.h"],
copts = ABSL_DEFAULT_COPTS,
- visibility = ["//visibility:private"],
deps = [
"//absl/base",
"//absl/base:config",
@@ -213,7 +200,6 @@ cc_test(
deps = [
":demangle_internal",
":stack_consumption",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/memory",
@@ -247,7 +233,7 @@ cc_library(
# 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:clang_compiler": ["-fsanitize=leak"],
+ "//absl:llvm_compiler": ["-fsanitize=leak"],
"//conditions:default": [],
})
@@ -257,14 +243,13 @@ cc_library(
srcs = ["leak_check.cc"],
hdrs = ["leak_check.h"],
copts = select({
- "//absl:clang_compiler": ["-DLEAK_SANITIZER"],
+ "//absl:llvm_compiler": ["-DLEAK_SANITIZER"],
"//conditions:default": [],
}),
linkopts = ABSL_DEFAULT_LINKOPTS,
visibility = ["//visibility:private"],
deps = [
"//absl/base:config",
- "//absl/base:core_headers",
],
)
@@ -278,7 +263,6 @@ cc_library(
visibility = ["//visibility:private"],
deps = [
"//absl/base:config",
- "//absl/base:core_headers",
],
)
@@ -286,7 +270,7 @@ cc_test(
name = "leak_check_test",
srcs = ["leak_check_test.cc"],
copts = select({
- "//absl:clang_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
+ "//absl:llvm_compiler": ["-DABSL_EXPECT_LEAK_SANITIZER"],
"//conditions:default": [],
}),
linkopts = ABSL_LSAN_LINKOPTS + ABSL_DEFAULT_LINKOPTS,
@@ -348,7 +332,6 @@ cc_test(
srcs = ["internal/stack_consumption_test.cc"],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["notsan"],
deps = [
":stack_consumption",
"//absl/base:core_headers",
diff --git a/third_party/abseil-cpp/absl/debugging/CMakeLists.txt b/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
index b16fa007e3..7733615939 100644
--- a/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/debugging/CMakeLists.txt
@@ -22,10 +22,8 @@ absl_cc_library(
"internal/stacktrace_aarch64-inl.inc"
"internal/stacktrace_arm-inl.inc"
"internal/stacktrace_config.h"
- "internal/stacktrace_emscripten-inl.inc"
"internal/stacktrace_generic-inl.inc"
"internal/stacktrace_powerpc-inl.inc"
- "internal/stacktrace_riscv-inl.inc"
"internal/stacktrace_unimplemented-inl.inc"
"internal/stacktrace_win32-inl.inc"
"internal/stacktrace_x86-inl.inc"
@@ -48,9 +46,7 @@ absl_cc_library(
"internal/symbolize.h"
SRCS
"symbolize.cc"
- "symbolize_darwin.inc"
"symbolize_elf.inc"
- "symbolize_emscripten.inc"
"symbolize_unimplemented.inc"
"symbolize_win32.inc"
COPTS
@@ -67,7 +63,6 @@ absl_cc_library(
absl::dynamic_annotations
absl::malloc_internal
absl::raw_logging_internal
- absl::strings
PUBLIC
)
@@ -85,12 +80,10 @@ absl_cc_test(
absl::stack_consumption
absl::symbolize
absl::base
- absl::config
absl::core_headers
absl::memory
absl::raw_logging_internal
- absl::strings
- GTest::gmock
+ gmock
)
absl_cc_library(
@@ -144,7 +137,7 @@ absl_cc_test(
absl::strings
absl::raw_logging_internal
Threads::Threads
- GTest::gmock
+ gmock
)
absl_cc_library(
@@ -193,11 +186,10 @@ absl_cc_test(
DEPS
absl::demangle_internal
absl::stack_consumption
- absl::config
absl::core_headers
absl::memory
absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -264,7 +256,7 @@ absl_cc_test(
DEPS
absl::leak_check_api_enabled_for_testing
absl::base
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -278,7 +270,7 @@ absl_cc_test(
DEPS
absl::leak_check_api_disabled_for_testing
absl::base
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -295,7 +287,7 @@ absl_cc_test(
absl::leak_check_disable
absl::base
absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -325,7 +317,7 @@ absl_cc_test(
absl::stack_consumption
absl::core_headers
absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
# component target
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
index 689e5979e7..1f69bfa84d 100644
--- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
+++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.cc
@@ -21,7 +21,6 @@
#ifdef _WIN32
#include <windows.h>
#else
-#include <sched.h>
#include <unistd.h>
#endif
@@ -136,10 +135,9 @@ static bool SetupAlternateStackOnce() {
#else
const size_t page_mask = sysconf(_SC_PAGESIZE) - 1;
#endif
- size_t stack_size =
- (std::max<size_t>(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
-#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
- defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
+ size_t stack_size = (std::max(SIGSTKSZ, 65536) + page_mask) & ~page_mask;
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
+ defined(THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_size *= 5;
#endif
@@ -221,24 +219,17 @@ static void WriteToStderr(const char* data) {
absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data));
}
-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);
- }
+static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) {
+ char buf[64];
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%s ***\n",
+ snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n",
signal_string,
- static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
- on_cpu);
+ static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
} else {
- snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
- signo, static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
- on_cpu);
+ snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n",
+ signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
}
writerfn(buf);
}
@@ -278,10 +269,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, int cpu,
+static void WriteFailureInfo(int signo, void* ucontext,
void (*writerfn)(const char*)) {
WriterFnStruct writerfn_struct{writerfn};
- WriteSignalMessage(signo, cpu, writerfn);
+ WriteSignalMessage(signo, writerfn);
WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper,
&writerfn_struct);
}
@@ -343,14 +334,6 @@ 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) {
@@ -361,13 +344,12 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
#endif
// First write to stderr.
- WriteFailureInfo(signo, ucontext, my_cpu, WriteToStderr);
+ WriteFailureInfo(signo, ucontext, 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, my_cpu, fsh_options.writerfn);
- fsh_options.writerfn(nullptr);
+ WriteFailureInfo(signo, ucontext, fsh_options.writerfn);
}
if (fsh_options.call_previous_handler) {
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.h b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.h
index 500115c0ab..f5a83962f1 100644
--- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler.h
+++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler.h
@@ -88,9 +88,9 @@ 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 string argument containing failure data. This function
+ // upon failure, with a std::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 will also be called with null data, as a hint
+ // 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
// flushing any buffered data in all calls to this function.
//
diff --git a/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc b/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
index 6a62428b33..863fb5149e 100644
--- a/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/failure_signal_handler_test.cc
@@ -55,7 +55,7 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) {
exit_regex);
#else
// Windows doesn't have testing::KilledBySignal().
- EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex);
+ EXPECT_DEATH(InstallHandlerAndRaise(signo), exit_regex);
#endif
}
@@ -107,8 +107,8 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
testing::KilledBySignal(signo), exit_regex);
#else
// Windows doesn't have testing::KilledBySignal().
- EXPECT_DEATH_IF_SUPPORTED(
- InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex);
+ EXPECT_DEATH(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo),
+ exit_regex);
#endif
// Open the file in this process and check its contents.
@@ -122,12 +122,6 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) {
"*** ", 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_THAT(error_line, StartsWith("PC: "));
diff --git a/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc b/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc
index 329c285f3b..6537606366 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/address_is_readable.cc
@@ -68,7 +68,6 @@ 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) {
absl::base_internal::ErrnoSaver errno_saver;
// We test whether a byte is readable by using write(). Normally, this would
@@ -87,7 +86,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_acquire);
+ uint64_t local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
while (current_pid != pid) {
int p[2];
@@ -99,13 +98,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_release,
+ local_pid_and_fds, new_pid_and_fds, std::memory_order_relaxed,
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_acquire);
+ local_pid_and_fds = pid_and_fds.load(std::memory_order_relaxed);
}
Unpack(local_pid_and_fds, &pid, &read_fd, &write_fd);
}
@@ -125,7 +124,7 @@ 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_release,
+ std::memory_order_relaxed,
std::memory_order_relaxed);
}
} while (errno == EBADF);
diff --git a/third_party/abseil-cpp/absl/debugging/internal/demangle.cc b/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
index 93ae32796c..fc615c3f58 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/demangle.cc
@@ -126,7 +126,6 @@ static const AbbrevPair kBuiltinTypeList[] = {
{"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},
@@ -152,7 +151,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 string.
+ int out_cur_idx; // Cursor of output std::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.
@@ -173,8 +172,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 string.
- char *out; // Beginning of output string.
+ const char *mangled_begin; // Beginning of input std::string.
+ char *out; // Beginning of output std::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.
@@ -386,35 +385,30 @@ 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') {
- 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;
- }
+ // Consume a single .<alpha>+.<digit>+ sequence.
+ if (str[i] != '.' || !IsAlpha(str[i + 1])) {
+ return false;
}
- if (str[i] == '.' && IsDigit(str[i + 1])) {
- parsed = true;
- i += 2;
- while (IsDigit(str[i])) {
- ++i;
- }
+ i += 2;
+ while (IsAlpha(str[i])) {
+ ++i;
}
- if (!parsed)
+ if (str[i] != '.' || !IsDigit(str[i + 1])) {
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];
}
@@ -427,10 +421,8 @@ 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,
- // 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] == '_')) {
+ // Remember the last identifier name for ctors/dtors.
+ if (IsAlpha(str[0]) || str[0] == '_') {
state->parse_state.prev_name_idx = state->parse_state.out_cur_idx;
state->parse_state.prev_name_length = length;
}
@@ -970,7 +962,6 @@ 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>
@@ -989,7 +980,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, "VTISH") &&
+ if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "VTIS") &&
ParseType(state)) {
return true;
}
@@ -1086,28 +1077,20 @@ static bool ParseVOffset(State *state) {
return false;
}
-// <ctor-dtor-name> ::= C1 | C2 | C3 | CI1 <base-class-type> | CI2
-// <base-class-type>
+// <ctor-dtor-name> ::= C1 | C2 | C3
// ::= 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')) {
- 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;
- }
+ 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;
}
state->parse_state = copy;
@@ -1156,7 +1139,6 @@ 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);
@@ -1223,12 +1205,6 @@ static bool ParseType(State *state) {
return true;
}
- if (ParseTwoCharToken(state, "Dv") && ParseNumber(state, nullptr) &&
- ParseOneCharToken(state, '_')) {
- return true;
- }
- state->parse_state = copy;
-
return false;
}
@@ -1277,42 +1253,13 @@ static bool ParseBuiltinType(State *state) {
return false;
}
-// <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
+// <function-type> ::= F [Y] <bare-function-type> E
static bool ParseFunctionType(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
- if (Optional(ParseExceptionSpec(state)) && ParseOneCharToken(state, 'F') &&
+ if (ParseOneCharToken(state, 'F') &&
Optional(ParseOneCharToken(state, 'Y')) && ParseBareFunctionType(state) &&
- Optional(ParseOneCharToken(state, 'O')) &&
ParseOneCharToken(state, 'E')) {
return true;
}
@@ -1617,7 +1564,6 @@ static bool ParseUnresolvedName(State *state) {
// ::= <2-ary operator-name> <expression> <expression>
// ::= <3-ary operator-name> <expression> <expression> <expression>
// ::= cl <expression>+ E
-// ::= cp <simple-id> <expression>* E # Clang-specific.
// ::= cv <type> <expression> # type (expression)
// ::= cv <type> _ <expression>* E # type (expr-list)
// ::= st <type>
@@ -1640,23 +1586,14 @@ static bool ParseExpression(State *state) {
return true;
}
- ParseState copy = state->parse_state;
-
// Object/function call expression.
+ ParseState copy = state->parse_state;
if (ParseTwoCharToken(state, "cl") && OneOrMore(ParseExpression, state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
state->parse_state = copy;
- // Clang-specific "cp <simple-id> <expression>* E"
- // https://clang.llvm.org/doxygen/ItaniumMangle_8cpp_source.html#l04338
- if (ParseTwoCharToken(state, "cp") && ParseSimpleId(state) &&
- ZeroOrMore(ParseExpression, state) && ParseOneCharToken(state, 'E')) {
- return true;
- }
- state->parse_state = copy;
-
// Function-param expression (level 0).
if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
@@ -1950,8 +1887,7 @@ 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) &&
- state.parse_state.out_cur_idx > 0;
+ return ParseTopLevelMangledName(&state) && !Overflowed(&state);
}
} // namespace debugging_internal
diff --git a/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc b/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
index 6b142902ca..c6f1ce184c 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/demangle_test.cc
@@ -18,7 +18,6 @@
#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"
@@ -70,34 +69,12 @@ TEST(Demangle, Clones) {
EXPECT_STREQ("Foo()", tmp);
EXPECT_TRUE(Demangle("_ZL3Foov.isra.2.constprop.18", tmp, sizeof(tmp)));
EXPECT_STREQ("Foo()", 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 (truncated), should not demangle.
+ EXPECT_FALSE(Demangle("_ZL3Foov.clo", 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)));
}
@@ -105,10 +82,9 @@ TEST(Demangle, Clones) {
// Tests that verify that Demangle footprint is within some limit.
// 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) && \
- !defined(ABSL_HAVE_ADDRESS_SANITIZER) && \
- !defined(ABSL_HAVE_MEMORY_SANITIZER) && \
- !defined(ABSL_HAVE_THREAD_SANITIZER)
+#if defined(ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION) && \
+ !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
+ !defined(THREAD_SANITIZER)
static const char *g_mangled;
static char g_demangle_buffer[4096];
diff --git a/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc b/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
index 29a281812b..24cc01302d 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.cc
@@ -22,7 +22,6 @@
#include <string.h>
#include <cassert>
#include <cstddef>
-#include "absl/base/config.h"
#include "absl/base/internal/raw_logging.h"
// From binutils/include/elf/common.h (this doesn't appear to be documented
@@ -44,11 +43,11 @@ namespace debugging_internal {
namespace {
-#if __SIZEOF_POINTER__ == 4
+#if __WORDSIZE == 32
const int kElfClass = ELFCLASS32;
int ElfBind(const ElfW(Sym) *symbol) { return ELF32_ST_BIND(symbol->st_info); }
int ElfType(const ElfW(Sym) *symbol) { return ELF32_ST_TYPE(symbol->st_info); }
-#elif __SIZEOF_POINTER__ == 8
+#elif __WORDSIZE == 64
const int kElfClass = ELFCLASS64;
int ElfBind(const ElfW(Sym) *symbol) { return ELF64_ST_BIND(symbol->st_info); }
int ElfType(const ElfW(Sym) *symbol) { return ELF64_ST_TYPE(symbol->st_info); }
@@ -176,17 +175,17 @@ void ElfMemImage::Init(const void *base) {
}
switch (base_as_char[EI_DATA]) {
case ELFDATA2LSB: {
-#ifndef ABSL_IS_LITTLE_ENDIAN
- assert(false);
- return;
-#endif
+ if (__LITTLE_ENDIAN != __BYTE_ORDER) {
+ assert(false);
+ return;
+ }
break;
}
case ELFDATA2MSB: {
-#ifndef ABSL_IS_BIG_ENDIAN
- assert(false);
- return;
-#endif
+ if (__BIG_ENDIAN != __BYTE_ORDER) {
+ assert(false);
+ return;
+ }
break;
}
default: {
@@ -222,7 +221,7 @@ void ElfMemImage::Init(const void *base) {
reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr +
relocation);
for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
- const auto value = dynamic_entry->d_un.d_val + relocation;
+ const ElfW(Xword) value = dynamic_entry->d_un.d_val + relocation;
switch (dynamic_entry->d_tag) {
case DT_HASH:
hash_ = reinterpret_cast<ElfW(Word) *>(value);
diff --git a/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h b/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h
index a894bd423e..46bfade350 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h
+++ b/third_party/abseil-cpp/absl/debugging/internal/elf_mem_image.h
@@ -31,8 +31,8 @@
#error ABSL_HAVE_ELF_MEM_IMAGE cannot be directly set
#endif
-#if defined(__ELF__) && !defined(__native_client__) && !defined(__asmjs__) && \
- !defined(__wasm__)
+#if defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \
+ !defined(__asmjs__) && !defined(__wasm__)
#define ABSL_HAVE_ELF_MEM_IMAGE 1
#endif
@@ -40,10 +40,6 @@
#include <link.h> // for ElfW
-#if defined(__FreeBSD__) && !defined(ElfW)
-#define ElfW(x) __ElfN(x)
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
diff --git a/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc b/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc
index 589a3ef367..a3dd893a9d 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/examine_stack.cc
@@ -20,10 +20,6 @@
#include <unistd.h>
#endif
-#ifdef __APPLE__
-#include <sys/ucontext.h>
-#endif
-
#include <csignal>
#include <cstdio>
@@ -46,72 +42,30 @@ 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.uc_regs->gregs[32]);
+ return reinterpret_cast<void*>(context->uc_mcontext.regs->nip);
#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));
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc b/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc
index 513486498a..875ca6d91f 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.cc
@@ -42,8 +42,7 @@ 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__) || \
- defined(__aarch64__) || defined(__riscv)
+#if defined(__i386__) || defined(__x86_64__) || defined(__ppc__)
constexpr bool kStackGrowsDown = true;
#else
#error Need to define kStackGrowsDown
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h b/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h
index f41b64c39d..5e60ec4229 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h
+++ b/third_party/abseil-cpp/absl/debugging/internal/stack_consumption.h
@@ -24,9 +24,8 @@
// Use this feature test macro to detect its availability.
#ifdef ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION
#error ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION cannot be set directly
-#elif !defined(__APPLE__) && !defined(_WIN32) && \
- (defined(__i386__) || defined(__x86_64__) || defined(__ppc__) || \
- defined(__aarch64__) || defined(__riscv))
+#elif !defined(__APPLE__) && !defined(_WIN32) && \
+ (defined(__i386__) || defined(__x86_64__) || defined(__ppc__))
#define ABSL_INTERNAL_HAVE_DEBUGGING_STACK_CONSUMPTION 1
namespace absl {
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
index f4859d7c21..411ea308e9 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -37,11 +37,8 @@ static const unsigned char* GetKernelRtSigreturnAddress() {
absl::debugging_internal::VDSOSupport vdso;
if (vdso.IsPresent()) {
absl::debugging_internal::VDSOSupport::SymbolInfo 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)) ||
+ if (!vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_2.6.39", STT_FUNC,
+ &symbol_info) ||
symbol_info.address == nullptr) {
// Unexpected: VDSO is present, yet the expected symbol is missing
// or null.
@@ -77,8 +74,6 @@ 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;
@@ -128,8 +123,6 @@ 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__
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
index 2a1bf2e886..fffda968dd 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_arm-inl.inc
@@ -1,18 +1,9 @@
-// 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.
+// Copyright 2011 and onwards Google Inc.
+// All rights reserved.
//
+// Author: Doug Kwan
// 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_
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
index ff21b719a0..d4e8480a8e 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_config.h
@@ -21,8 +21,6 @@
#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
@@ -30,58 +28,43 @@
#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 // defined(ABSL_HAVE_THREAD_LOCAL)
-
-#elif defined(__EMSCRIPTEN__)
-#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_emscripten-inl.inc"
-
#elif defined(__linux__) && !defined(__ANDROID__)
-#if defined(NO_FRAME_POINTER) && \
- (defined(__i386__) || defined(__x86_64__) || defined(__aarch64__))
-// Note: The libunwind-based implementation is not available to open-source
-// users.
+#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__)
#define ABSL_STACKTRACE_INL_HEADER \
- "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>)
+ "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__)
// Note: When using glibc this may require -funwind-tables to function properly.
#define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_generic-inl.inc"
-#endif // __has_include(<execinfo.h>)
-#elif defined(__i386__) || defined(__x86_64__)
-#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_x86-inl.inc"
-#elif defined(__ppc__) || defined(__PPC__)
+# else
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-#elif defined(__aarch64__)
+ "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
+# endif
+#else // defined(NO_FRAME_POINTER)
+# if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__)
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_aarch64-inl.inc"
-#elif defined(__riscv)
+ "absl/debugging/internal/stacktrace_generic-inl.inc"
+# elif defined(__ppc__) || defined(__PPC__)
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_riscv-inl.inc"
-#elif defined(__has_include)
-#if __has_include(<execinfo.h>)
-// Note: When using glibc this may require -funwind-tables to function properly.
+ "absl/debugging/internal/stacktrace_generic-inl.inc"
+# else
#define ABSL_STACKTRACE_INL_HEADER \
- "absl/debugging/internal/stacktrace_generic-inl.inc"
-#endif // __has_include(<execinfo.h>)
-#endif // defined(__has_include)
-
-#endif // defined(__linux__) && !defined(__ANDROID__)
+ "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
+# endif
+#endif // NO_FRAME_POINTER
-// Fallback to the empty implementation.
-#if !defined(ABSL_STACKTRACE_INL_HEADER)
+#else
#define ABSL_STACKTRACE_INL_HEADER \
"absl/debugging/internal/stacktrace_unimplemented-inl.inc"
+
#endif
#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_CONFIG_H_
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc
deleted file mode 100644
index 0f44451438..0000000000
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_emscripten-inl.inc
+++ /dev/null
@@ -1,110 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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
-//
-// Note: The glibc implementation may cause a call to malloc.
-// This can cause a deadlock in HeapProfiler.
-
-#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_
-#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_
-
-#include <emscripten.h>
-
-#include <atomic>
-#include <cstring>
-
-#include "absl/base/attributes.h"
-#include "absl/debugging/stacktrace.h"
-
-extern "C" {
-uintptr_t emscripten_stack_snapshot();
-uint32_t emscripten_stack_unwind_buffer(uintptr_t pc, void *buffer,
- uint32_t depth);
-}
-
-// Sometimes, we can try to get a stack trace from within a stack
-// trace, which 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).
-// 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 = []() {
- // Check if we can even create stacktraces. If not, bail early and leave
- // disable_stacktraces set as-is.
- // clang-format off
- if (!EM_ASM_INT({ return (typeof wasmOffsetConverter !== 'undefined'); })) {
- return 0;
- }
- // clang-format on
- 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.
- constexpr int kStackLength = 64;
- void *stack[kStackLength];
-
- int size;
- uintptr_t pc = emscripten_stack_snapshot();
- size = emscripten_stack_unwind_buffer(pc, stack, kStackLength);
-
- int result_count = size - skip_count;
- if (result_count < 0) result_count = 0;
- if (result_count > max_depth) result_count = max_depth;
- for (int i = 0; i < result_count; i++) result[i] = stack[i + skip_count];
-
- if (IS_STACK_FRAMES) {
- // No implementation for finding out the stack frame sizes yet.
- memset(sizes, 0, sizeof(*sizes) * result_count);
- }
- if (min_dropped_frames != nullptr) {
- if (size - skip_count - max_depth > 0) {
- *min_dropped_frames = size - skip_count - max_depth;
- } else {
- *min_dropped_frames = 0;
- }
- }
-
- --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_EMSCRIPTEN_INL_H_
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
index b2792a1f3a..ac034c9f5b 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_generic-inl.inc
@@ -1,16 +1,7 @@
-// Copyright 2017 The Abseil Authors.
+// Copyright 2000 - 2007 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.
+// Author: Sanjay Ghemawat
//
// Portable implementation - just use glibc
//
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
index cf8c05160c..2e7c2f404f 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -131,12 +131,7 @@ 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 =
-#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
+ reinterpret_cast<void**>(signal_context->uc_mcontext.gp_regs[PT_R1]);
// Check that alleged sp before signal is nonnull and is reasonably
// aligned.
if (sp_before_signal != nullptr &&
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
deleted file mode 100644
index 8cbc78548c..0000000000
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_riscv-inl.inc
+++ /dev/null
@@ -1,234 +0,0 @@
-// 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_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_
-#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_RISCV_INL_H_
-
-// Generate stack trace for riscv
-
-#include <sys/ucontext.h>
-
-#include "absl/base/config.h"
-#if defined(__linux__)
-#include <sys/mman.h>
-#include <ucontext.h>
-#include <unistd.h>
-#endif
-
-#include <atomic>
-#include <cassert>
-#include <cstdint>
-#include <iostream>
-
-#include "absl/base/attributes.h"
-#include "absl/debugging/internal/address_is_readable.h"
-#include "absl/debugging/internal/vdso_support.h"
-#include "absl/debugging/stacktrace.h"
-
-static const uintptr_t kUnknownFrameSize = 0;
-
-#if defined(__linux__)
-// Returns the address of the VDSO __kernel_rt_sigreturn function, if present.
-static const unsigned char *GetKernelRtSigreturnAddress() {
- constexpr uintptr_t kImpossibleAddress = 0;
- ABSL_CONST_INIT static std::atomic<uintptr_t> memoized(kImpossibleAddress);
- uintptr_t address = memoized.load(std::memory_order_relaxed);
- if (address != kImpossibleAddress) {
- return reinterpret_cast<const unsigned char *>(address);
- }
-
- address = reinterpret_cast<uintptr_t>(nullptr);
-
-#if ABSL_HAVE_VDSO_SUPPORT
- absl::debugging_internal::VDSOSupport vdso;
- if (vdso.IsPresent()) {
- absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info;
- // Symbol versioning pulled from arch/riscv/kernel/vdso/vdso.lds at v5.10.
- auto lookup = [&](int type) {
- return vdso.LookupSymbol("__kernel_rt_sigreturn", "LINUX_4.15", type,
- &symbol_info);
- };
- if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) ||
- symbol_info.address == nullptr) {
- // Unexpected: VDSO is present, yet the expected symbol is missing or
- // null.
- assert(false && "VDSO is present, but doesn't have expected symbol");
- } else {
- if (reinterpret_cast<uintptr_t>(symbol_info.address) !=
- kImpossibleAddress) {
- address = reinterpret_cast<uintptr_t>(symbol_info.address);
- } else {
- assert(false && "VDSO returned invalid address");
- }
- }
- }
-#endif
-
- memoized.store(address, std::memory_order_relaxed);
- return reinterpret_cast<const unsigned char *>(address);
-}
-#endif // __linux__
-
-// Compute the size of a stack frame in [low..high). We assume that low < high.
-// Return size of kUnknownFrameSize.
-template <typename T>
-static inline uintptr_t ComputeStackFrameSize(const T *low, const T *high) {
- const char *low_char_ptr = reinterpret_cast<const char *>(low);
- const char *high_char_ptr = reinterpret_cast<const char *>(high);
- return low < high ? high_char_ptr - low_char_ptr : kUnknownFrameSize;
-}
-
-// Given a pointer to a stack frame, locate and return the calling stackframe,
-// or return null if no stackframe can be found. Perform sanity 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) {
- // .
- // .
- // .
- // +-> +----------------+
- // | | return address |
- // | | previous fp |
- // | | ... |
- // | +----------------+ <-+
- // | | return address | |
- // +---|- previous fp | |
- // | ... | |
- // $fp ->|----------------+ |
- // | return address | |
- // | previous fp -|---+
- // $sp ->| ... |
- // +----------------+
- void **new_frame_pointer = reinterpret_cast<void **>(old_frame_pointer[-2]);
- bool check_frame_size = true;
-
-#if defined(__linux__)
- if (WITH_CONTEXT && uc != nullptr) {
- // Check to see if next frame's return address is __kernel_rt_sigreturn.
- if (old_frame_pointer[-1] == GetKernelRtSigreturnAddress()) {
- const ucontext_t *ucv = static_cast<const ucontext_t *>(uc);
- // old_frame_pointer is not suitable for unwinding, look at ucontext to
- // discover frame pointer before signal.
- //
- // RISCV ELF psABI has the frame pointer at x8/fp/s0.
- // -- RISCV psABI Table 18.2
- void **const pre_signal_frame_pointer =
- reinterpret_cast<void **>(ucv->uc_mcontext.__gregs[8]);
-
- // Check the alleged frame pointer is actually readable. This is to
- // prevent "double fault" in case we hit the first fault due to stack
- // corruption.
- if (!absl::debugging_internal::AddressIsReadable(
- pre_signal_frame_pointer))
- return nullptr;
-
- // Alleged frame pointer is readable, use it for further unwinding.
- new_frame_pointer = pre_signal_frame_pointer;
-
- // Skip frame size check if we return from a signal. We may be using an
- // alterate stack for signals.
- check_frame_size = false;
- }
- }
-#endif
-
- // The RISCV ELF psABI mandates that the stack pointer is always 16-byte
- // aligned.
- // FIXME(abdulras) this doesn't hold for ILP32E which only mandates a 4-byte
- // alignment.
- if ((reinterpret_cast<uintptr_t>(new_frame_pointer) & 15) != 0)
- return nullptr;
-
- // Check frame size. In strict mode, we assume frames to be under 100,000
- // bytes. In non-strict mode, we relax the limit to 1MB.
- if (check_frame_size) {
- const uintptr_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
- const uintptr_t frame_size =
- ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
- if (frame_size == kUnknownFrameSize || frame_size > max_size)
- return nullptr;
- }
-
- return new_frame_pointer;
-}
-
-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) {
-#if defined(__GNUC__)
- void **frame_pointer = reinterpret_cast<void **>(__builtin_frame_address(0));
-#else
-#error reading stack pointer not yet supported on this platform
-#endif
-
- skip_count++; // Skip the frame for this function.
- int n = 0;
-
- // The `frame_pointer` that is computed here points to the top of the frame.
- // The two words preceding the address are the return address and the previous
- // frame pointer. To find a PC value associated with the current frame, we
- // need to go down a level in the call chain. So we remember the return
- // address of the last frame seen. This does not work for the first stack
- // frame, which belongs to `UnwindImp()` but we skip the frame for
- // `UnwindImp()` anyway.
- void *prev_return_address = nullptr;
-
- while (frame_pointer && n < max_depth) {
- // The absl::GetStackFrames routine si called when we are in some
- // informational context (the failure signal handler for example). Use the
- // non-strict unwinding rules to produce a stack trace that is as complete
- // as possible (even if it contains a few bogus entries in some rare cases).
- void **next_frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
-
- if (skip_count > 0) {
- skip_count--;
- } else {
- result[n] = prev_return_address;
- if (IS_STACK_FRAMES) {
- sizes[n] = ComputeStackFrameSize(frame_pointer, next_frame_pointer);
- }
- n++;
- }
- prev_return_address = frame_pointer[-1];
- frame_pointer = next_frame_pointer;
- }
- if (min_dropped_frames != nullptr) {
- // Implementation detail: we clamp the max of frames we are willing to
- // count, so as not to spend too much time in the loop below.
- const int kMaxUnwind = 200;
- int j = 0;
- for (; frame_pointer != nullptr && j < kMaxUnwind; j++) {
- frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
- }
- *min_dropped_frames = j;
- }
- return n;
-}
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace debugging_internal {
-bool StackTraceWorksForTest() { return true; }
-} // namespace debugging_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
index 1c666c8b56..9c2c558044 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_win32-inl.inc
@@ -46,19 +46,11 @@ 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");
-#endif // WINAPI_PARTITION_APP && !WINAPI_PARTITION_DESKTOP
+ (RtlCaptureStackBackTrace_Function*)
+ GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
diff --git a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
index 847a547359..bc320ff75b 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/third_party/abseil-cpp/absl/debugging/internal/stacktrace_x86-inl.inc
@@ -27,7 +27,6 @@
#include <cassert>
#include <cstdint>
-#include <limits>
#include "absl/base/macros.h"
#include "absl/base/port.h"
@@ -133,8 +132,9 @@ static uintptr_t GetFP(const void *vuc) {
const uintptr_t bp = 0;
const uintptr_t sp = 0;
#endif
- // Sanity-check that the base pointer is valid. It's possible that some
- // code in the process is compiled with --copt=-fomit-frame-pointer or
+ // Sanity-check that the base pointer is valid. It should be as long as
+ // SHRINK_WRAP_FRAME_POINTER is not set, but it's possible that some code in
+ // the process is compiled with --copt=-fomit-frame-pointer or
// --copt=-momit-leaf-frame-pointer.
//
// TODO(bcmills): -momit-leaf-frame-pointer is currently the default
@@ -159,8 +159,7 @@ static uintptr_t GetFP(const void *vuc) {
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_fp, const void *uc,
- size_t stack_low, size_t stack_high) {
+static void **NextStackFrame(void **old_fp, const void *uc) {
void **new_fp = (void **)*old_fp;
#if defined(__linux__) && defined(__i386__)
@@ -248,7 +247,7 @@ static void **NextStackFrame(void **old_fp, const void *uc,
// using an alternate signal stack.
//
// TODO(bcmills): The GetFP call should be completely unnecessary when
- // ENABLE_COMBINED_UNWINDER is set (because we should be back in the thread's
+ // SHRINK_WRAP_FRAME_POINTER is set (because we should be back in the thread's
// stack by this point), but it is empirically still needed (e.g. when the
// stack includes a call to abort). unw_get_reg returns UNW_EBADREG for some
// frames. Figure out why GetValidFrameAddr and/or libunwind isn't doing what
@@ -259,18 +258,6 @@ static void **NextStackFrame(void **old_fp, const void *uc,
// at a greater address that the current one.
if (new_fp_u <= old_fp_u) return nullptr;
if (new_fp_u - old_fp_u > kMaxFrameBytes) return nullptr;
-
- if (stack_low < old_fp_u && old_fp_u <= stack_high) {
- // Old BP was in the expected stack region...
- if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
- // ... but new BP is outside of expected stack region.
- // It is most likely bogus.
- return nullptr;
- }
- } else {
- // We may be here if we are executing in a co-routine with a
- // separate stack. We can't do safety checks in this case.
- }
} else {
if (new_fp == nullptr) return nullptr; // skip AddressIsReadable() below
// In the non-strict mode, allow discontiguous stack frames.
@@ -310,17 +297,13 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
int n = 0;
void **fp = reinterpret_cast<void **>(__builtin_frame_address(0));
- size_t stack_low = getpagesize(); // Assume that the first page is not stack.
- size_t stack_high = std::numeric_limits<size_t>::max() - sizeof(void *);
-
while (fp && n < max_depth) {
if (*(fp + 1) == reinterpret_cast<void *>(0)) {
// In 64-bit code, we often see a frame that
// points to itself and has a return address of 0.
break;
}
- void **next_fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(
- fp, ucp, stack_low, stack_high);
+ void **next_fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, ucp);
if (skip_count > 0) {
skip_count--;
} else {
@@ -343,8 +326,7 @@ static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
const int kMaxUnwind = 1000;
int j = 0;
for (; fp != nullptr && j < kMaxUnwind; j++) {
- fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, ucp, stack_low,
- stack_high);
+ fp = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(fp, ucp);
}
*min_dropped_frames = j;
}
diff --git a/third_party/abseil-cpp/absl/debugging/internal/symbolize.h b/third_party/abseil-cpp/absl/debugging/internal/symbolize.h
index 27d5e6521e..5d0858b5c7 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/symbolize.h
+++ b/third_party/abseil-cpp/absl/debugging/internal/symbolize.h
@@ -18,18 +18,15 @@
#ifndef ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
#define ABSL_DEBUGGING_INTERNAL_SYMBOLIZE_H_
-#ifdef __cplusplus
-
#include <cstddef>
#include <cstdint>
#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
-#elif defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) \
- && !defined(__asmjs__) && !defined(__wasm__)
+#elif defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \
+ !defined(__asmjs__) && !defined(__wasm__)
#define ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE 1
#include <elf.h>
@@ -48,7 +45,7 @@ namespace debugging_internal {
//
// This is not async-signal-safe.
bool ForEachSection(int fd,
- const std::function<bool(absl::string_view name,
+ const std::function<bool(const std::string& name,
const ElfW(Shdr) &)>& callback);
// Gets the section header for the given name, if it exists. Returns true on
@@ -62,18 +59,6 @@ ABSL_NAMESPACE_END
#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
-
-#ifdef ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
-#error ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE cannot be directly set
-#elif defined(__EMSCRIPTEN__)
-#define ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE 1
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
@@ -124,30 +109,20 @@ 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/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc b/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc
index 977a9f6b3c..1e8a78ac9c 100644
--- a/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc
+++ b/third_party/abseil-cpp/absl/debugging/internal/vdso_support.cc
@@ -20,25 +20,12 @@
#ifdef ABSL_HAVE_VDSO_SUPPORT // defined in vdso_support.h
-#if !defined(__has_include)
-#define __has_include(header) 0
-#endif
-
#include <errno.h>
#include <fcntl.h>
-#if __has_include(<syscall.h>)
-#include <syscall.h>
-#elif __has_include(<sys/syscall.h>)
#include <sys/syscall.h>
-#endif
#include <unistd.h>
-#if defined(__GLIBC__) && \
- (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 16))
-#define ABSL_HAVE_GETAUXVAL
-#endif
-
-#ifdef ABSL_HAVE_GETAUXVAL
+#if __GLIBC_PREREQ(2, 16) // GLIBC-2.16 implements getauxval.
#include <sys/auxv.h>
#endif
@@ -50,11 +37,6 @@
#define AT_SYSINFO_EHDR 33 // for crosstoolv10
#endif
-#if defined(__FreeBSD__)
-using Elf64_auxv_t = Elf64_Auxinfo;
-using Elf32_auxv_t = Elf32_Auxinfo;
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace debugging_internal {
@@ -83,7 +65,7 @@ VDSOSupport::VDSOSupport()
// the operation should be idempotent.
const void *VDSOSupport::Init() {
const auto kInvalidBase = debugging_internal::ElfMemImage::kInvalidBase;
-#ifdef ABSL_HAVE_GETAUXVAL
+#if __GLIBC_PREREQ(2, 16)
if (vdso_base_.load(std::memory_order_relaxed) == kInvalidBase) {
errno = 0;
const void *const sysinfo_ehdr =
@@ -92,8 +74,17 @@ const void *VDSOSupport::Init() {
vdso_base_.store(sysinfo_ehdr, std::memory_order_relaxed);
}
}
-#endif // ABSL_HAVE_GETAUXVAL
+#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.
@@ -184,6 +175,18 @@ 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
diff --git a/third_party/abseil-cpp/absl/debugging/leak_check.cc b/third_party/abseil-cpp/absl/debugging/leak_check.cc
index 764ca0ad00..ff9049559d 100644
--- a/third_party/abseil-cpp/absl/debugging/leak_check.cc
+++ b/third_party/abseil-cpp/absl/debugging/leak_check.cc
@@ -16,7 +16,6 @@
// 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
@@ -24,7 +23,6 @@
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) { }
@@ -37,23 +35,9 @@ ABSL_NAMESPACE_END
#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);
diff --git a/third_party/abseil-cpp/absl/debugging/leak_check.h b/third_party/abseil-cpp/absl/debugging/leak_check.h
index 5fc2b052e4..7a5a22dd1c 100644
--- a/third_party/abseil-cpp/absl/debugging/leak_check.h
+++ b/third_party/abseil-cpp/absl/debugging/leak_check.h
@@ -43,12 +43,6 @@ ABSL_NAMESPACE_BEGIN
// 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
@@ -68,8 +62,7 @@ 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, leak sanitizer will assume this object is referenced even if
-// there is no actual reference in user memory.
+// allocated, the object must not get deallocated later.
//
template <typename T>
T* IgnoreLeak(T* ptr) {
@@ -77,19 +70,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/debugging/leak_check_fail_test.cc b/third_party/abseil-cpp/absl/debugging/leak_check_fail_test.cc
index c49b81a9d9..2887ceab14 100644
--- a/third_party/abseil-cpp/absl/debugging/leak_check_fail_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/leak_check_fail_test.cc
@@ -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 string %s", foo);
+ ABSL_RAW_LOG(INFO, "Should detect leaked std::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 string %s",
+ ABSL_RAW_LOG(INFO, "Re-enabled leak detection.Should detect leaked std::string %s",
foo);
}
diff --git a/third_party/abseil-cpp/absl/debugging/leak_check_test.cc b/third_party/abseil-cpp/absl/debugging/leak_check_test.cc
index 9fcfc8e50b..93a7edd2d0 100644
--- a/third_party/abseil-cpp/absl/debugging/leak_check_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/leak_check_test.cc
@@ -23,22 +23,20 @@ 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 string %s", foo->c_str());
+ ABSL_RAW_LOG(INFO, "Ignoring leaked std::string %s", foo->c_str());
}
TEST(LeakCheckTest, LeakCheckDisablerIgnoresLeak) {
absl::LeakCheckDisabler disabler;
- auto foo = new std::string("some string leaked while checks are disabled");
- ABSL_RAW_LOG(INFO, "Ignoring leaked string %s", foo->c_str());
+ 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());
}
} // namespace
diff --git a/third_party/abseil-cpp/absl/debugging/stacktrace.cc b/third_party/abseil-cpp/absl/debugging/stacktrace.cc
index ff8069f843..1f7c7d82b2 100644
--- a/third_party/abseil-cpp/absl/debugging/stacktrace.cc
+++ b/third_party/abseil-cpp/absl/debugging/stacktrace.cc
@@ -49,10 +49,8 @@
# include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
# include "absl/debugging/internal/stacktrace_arm-inl.inc"
-# include "absl/debugging/internal/stacktrace_emscripten-inl.inc"
# include "absl/debugging/internal/stacktrace_generic-inl.inc"
# include "absl/debugging/internal/stacktrace_powerpc-inl.inc"
-# include "absl/debugging/internal/stacktrace_riscv-inl.inc"
# include "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
# include "absl/debugging/internal/stacktrace_win32-inl.inc"
# include "absl/debugging/internal/stacktrace_x86-inl.inc"
diff --git a/third_party/abseil-cpp/absl/debugging/symbolize.cc b/third_party/abseil-cpp/absl/debugging/symbolize.cc
index f1abdfda59..54ed97002a 100644
--- a/third_party/abseil-cpp/absl/debugging/symbolize.cc
+++ b/third_party/abseil-cpp/absl/debugging/symbolize.cc
@@ -14,25 +14,12 @@
#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(ABSL_INTERNAL_HAVE_SYMBOLIZE_WIN32)
+#elif defined(_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"
-#elif defined(__EMSCRIPTEN__)
-#include "absl/debugging/symbolize_emscripten.inc"
#else
#include "absl/debugging/symbolize_unimplemented.inc"
#endif
diff --git a/third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc b/third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc
deleted file mode 100644
index 443ce9efc4..0000000000
--- a/third_party/abseil-cpp/absl/debugging/symbolize_darwin.inc
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc b/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
index 3ff343d64f..c371635ffa 100644
--- a/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
+++ b/third_party/abseil-cpp/absl/debugging/symbolize_elf.inc
@@ -57,7 +57,6 @@
#include <unistd.h>
#include <algorithm>
-#include <array>
#include <atomic>
#include <cerrno>
#include <cinttypes>
@@ -75,11 +74,6 @@
#include "absl/base/port.h"
#include "absl/debugging/internal/demangle.h"
#include "absl/debugging/internal/vdso_support.h"
-#include "absl/strings/string_view.h"
-
-#if defined(__FreeBSD__) && !defined(ElfW)
-#define ElfW(x) __ElfN(x)
-#endif
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -88,12 +82,6 @@ ABSL_NAMESPACE_BEGIN
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;
@@ -161,15 +149,13 @@ 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.
-ABSL_CONST_INIT absl::base_internal::SpinLock g_decorators_mu(
- absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
+base_internal::SpinLock g_decorators_mu(base_internal::kLinkerInitialized);
const int kMaxFileMappingHints = 8;
int g_num_file_mapping_hints;
FileMappingHint g_file_mapping_hints[kMaxFileMappingHints];
// Protects g_file_mapping_hints.
-ABSL_CONST_INIT absl::base_internal::SpinLock g_file_mapping_mu(
- absl::kConstInit, absl::base_internal::SCHEDULE_KERNEL_ONLY);
+base_internal::SpinLock g_file_mapping_mu(base_internal::kLinkerInitialized);
// Async-signal-safe function to zero a buffer.
// memset() is not guaranteed to be async-signal-safe.
@@ -189,7 +175,6 @@ struct ObjFile {
fd(-1),
elf_type(-1) {
SafeMemZero(&elf_header, sizeof(elf_header));
- SafeMemZero(&phdr[0], sizeof(phdr));
}
char *filename;
@@ -202,10 +187,6 @@ 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
@@ -515,7 +496,7 @@ static ABSL_ATTRIBUTE_NOINLINE bool GetSectionHeaderByType(
const int kMaxSectionNameLen = 64;
bool ForEachSection(int fd,
- const std::function<bool(absl::string_view name,
+ const std::function<bool(const std::string &name,
const ElfW(Shdr) &)> &callback) {
ElfW(Ehdr) elf_header;
if (!ReadFromOffsetExact(fd, &elf_header, sizeof(elf_header), 0)) {
@@ -537,7 +518,7 @@ bool ForEachSection(int fd,
return false;
}
off_t name_offset = shstrtab.sh_offset + out.sh_name;
- char header_name[kMaxSectionNameLen];
+ char header_name[kMaxSectionNameLen + 1];
ssize_t n_read =
ReadFromOffset(fd, &header_name, kMaxSectionNameLen, name_offset);
if (n_read == -1) {
@@ -546,8 +527,9 @@ bool ForEachSection(int fd,
// Long read?
return false;
}
+ header_name[n_read] = '\0';
- absl::string_view name(header_name, strnlen(header_name, n_read));
+ std::string name(header_name);
if (!callback(name, out)) {
break;
}
@@ -705,16 +687,6 @@ static ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
const char *start_address =
ComputeOffset(original_start_address, relocation);
-#ifdef __arm__
- // ARM functions are always aligned to multiples of two bytes; the
- // lowest-order bit in start_address is ignored by the CPU and indicates
- // whether the function contains ARM (0) or Thumb (1) code. We don't care
- // about what encoding is being used; we just want the real start address
- // of the function.
- start_address = reinterpret_cast<const char *>(
- reinterpret_cast<uintptr_t>(start_address) & ~1);
-#endif
-
if (deref_function_descriptor_pointer &&
InSection(original_start_address, opd)) {
// The opd section is mapped into memory. Just dereference
@@ -1292,36 +1264,6 @@ 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;
}
@@ -1345,52 +1287,23 @@ const char *Symbolizer::GetSymbol(const void *const pc) {
int fd = -1;
if (obj != nullptr) {
if (MaybeInitializeObjFile(obj)) {
- const size_t start_addr = reinterpret_cast<size_t>(obj->start_addr);
- if (obj->elf_type == ET_DYN && start_addr >= obj->offset) {
+ if (obj->elf_type == ET_DYN &&
+ reinterpret_cast<uint64_t>(obj->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 = 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;
- }
+ relocation = reinterpret_cast<ptrdiff_t>(obj->start_addr) - obj->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
@@ -1461,7 +1374,7 @@ int InstallSymbolDecorator(SymbolDecorator decorator, void *arg) {
if (!g_decorators_mu.TryLock()) {
// Someone else is using decorators. Get out.
- return -2;
+ return false;
}
int ret = ticket;
if (g_num_decorators >= kMaxDecorators) {
@@ -1489,7 +1402,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 string copy routine.
+ // TODO(ckennelly): Move this into a std::string copy routine.
int len = strlen(filename);
char *dst = static_cast<char *>(
base_internal::LowLevelAlloc::AllocWithArena(len + 1, SigSafeArena()));
@@ -1540,7 +1453,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.
- ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
SAFE_ASSERT(out_size >= 0);
debugging_internal::Symbolizer *s = debugging_internal::AllocateSymbolizer();
const char *name = s->GetSymbol(pc);
@@ -1559,16 +1472,9 @@ bool Symbolize(const void *pc, char *out, int out_size) {
}
}
debugging_internal::FreeSymbolizer(s);
- ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
+ 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/third_party/abseil-cpp/absl/debugging/symbolize_emscripten.inc b/third_party/abseil-cpp/absl/debugging/symbolize_emscripten.inc
deleted file mode 100644
index c226c45666..0000000000
--- a/third_party/abseil-cpp/absl/debugging/symbolize_emscripten.inc
+++ /dev/null
@@ -1,72 +0,0 @@
-// 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 <emscripten.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"
-
-extern "C" {
-const char* emscripten_pc_get_function(const void* pc);
-}
-
-// clang-format off
-EM_JS(bool, HaveOffsetConverter, (),
- { return typeof wasmOffsetConverter !== 'undefined'; });
-// clang-format on
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-void InitializeSymbolizer(const char*) {
- if (!HaveOffsetConverter()) {
- ABSL_RAW_LOG(INFO,
- "Symbolization unavailable. Rebuild with -sWASM=1 "
- "and -sUSE_OFFSET_CONVERTER=1.");
- }
-}
-
-bool Symbolize(const void* pc, char* out, int out_size) {
- // Check if we have the offset converter necessary for pc_get_function.
- // Without it, the program will abort().
- if (!HaveOffsetConverter()) {
- return false;
- }
- const char* func_name = emscripten_pc_get_function(pc);
- if (func_name == nullptr) {
- return false;
- }
-
- strncpy(out, func_name, 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/third_party/abseil-cpp/absl/debugging/symbolize_test.cc b/third_party/abseil-cpp/absl/debugging/symbolize_test.cc
index c710a3da81..a1d03aab53 100644
--- a/third_party/abseil-cpp/absl/debugging/symbolize_test.cc
+++ b/third_party/abseil-cpp/absl/debugging/symbolize_test.cc
@@ -27,13 +27,11 @@
#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;
@@ -146,22 +144,7 @@ static const char *TrySymbolize(void *pc) {
return TrySymbolizeWithLimit(pc, sizeof(try_symbolize_buffer));
}
-#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
- defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE) || \
- defined(ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE)
-
-// Test with a return address.
-void ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {
-#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
- void *return_address = __builtin_return_address(0);
- const char *symbol = TrySymbolize(return_address);
- ABSL_RAW_CHECK(symbol != nullptr, "TestWithReturnAddress failed");
- ABSL_RAW_CHECK(strcmp(symbol, "main") == 0, "TestWithReturnAddress failed");
- std::cout << "TestWithReturnAddress passed" << std::endl;
-#endif
-}
-
-#ifndef ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
+#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
TEST(Symbolize, Cached) {
// Compilers should give us pointers to them.
@@ -235,8 +218,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(ABSL_HAVE_ADDRESS_SANITIZER) || \
- defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
+ defined(THREAD_SANITIZER)
// Account for sanitizer instrumentation requiring additional stack space.
stack_consumption_upper_limit *= 5;
#endif
@@ -275,7 +258,6 @@ 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
@@ -417,8 +399,8 @@ TEST(Symbolize, ForEachSection) {
std::vector<std::string> sections;
ASSERT_TRUE(absl::debugging_internal::ForEachSection(
- fd, [&sections](const absl::string_view name, const ElfW(Shdr) &) {
- sections.emplace_back(name);
+ fd, [&sections](const std::string &name, const ElfW(Shdr) &) {
+ sections.push_back(name);
return true;
}));
@@ -431,8 +413,6 @@ TEST(Symbolize, ForEachSection) {
close(fd);
}
-#endif // !ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE
-#endif // !ABSL_INTERNAL_HAVE_EMSCRIPTEN_SYMBOLIZE
// x86 specific tests. Uses some inline assembler.
extern "C" {
@@ -481,46 +461,17 @@ void ABSL_ATTRIBUTE_NOINLINE TestWithPCInsideInlineFunction() {
}
}
-#if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
-// Test that we correctly identify bounds of Thumb functions on ARM.
-//
-// Thumb functions have the lowest-order bit set in their addresses in the ELF
-// symbol table. This requires some extra logic to properly compute function
-// bounds. To test this logic, nudge a Thumb function right up against an ARM
-// function and try to symbolize the ARM function.
-//
-// A naive implementation will simply use the Thumb function's entry point as
-// written in the symbol table and will therefore treat the Thumb function as
-// extending one byte further in the instruction stream than it actually does.
-// When asked to symbolize the start of the ARM function, it will identify an
-// overlap between the Thumb and ARM functions, and it will return the name of
-// the Thumb function.
-//
-// A correct implementation, on the other hand, will null out the lowest-order
-// bit in the Thumb function's entry point. It will correctly compute the end of
-// the Thumb function, it will find no overlap between the Thumb and ARM
-// functions, and it will return the name of the ARM function.
-
-__attribute__((target("thumb"))) int ArmThumbOverlapThumb(int x) {
- return x * x * x;
-}
-
-__attribute__((target("arm"))) int ArmThumbOverlapArm(int x) {
- return x * x * x;
-}
-
-void ABSL_ATTRIBUTE_NOINLINE TestArmThumbOverlap() {
+// Test with a return address.
+void ABSL_ATTRIBUTE_NOINLINE TestWithReturnAddress() {
#if defined(ABSL_HAVE_ATTRIBUTE_NOINLINE)
- const char *symbol = TrySymbolize((void *)&ArmThumbOverlapArm);
- ABSL_RAW_CHECK(symbol != nullptr, "TestArmThumbOverlap failed");
- ABSL_RAW_CHECK(strcmp("ArmThumbOverlapArm()", symbol) == 0,
- "TestArmThumbOverlap failed");
- std::cout << "TestArmThumbOverlap passed" << std::endl;
+ void *return_address = __builtin_return_address(0);
+ const char *symbol = TrySymbolize(return_address);
+ ABSL_RAW_CHECK(symbol != nullptr, "TestWithReturnAddress failed");
+ ABSL_RAW_CHECK(strcmp(symbol, "main") == 0, "TestWithReturnAddress failed");
+ std::cout << "TestWithReturnAddress passed" << std::endl;
#endif
}
-#endif // defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
-
#elif defined(_WIN32)
#if !defined(ABSL_CONSUME_DLL)
@@ -563,6 +514,7 @@ TEST(Symbolize, SymbolizeWithDemangling) {
#endif // !defined(ABSL_CONSUME_DLL)
#else // Symbolizer unimplemented
+
TEST(Symbolize, Unimplemented) {
char buf[64];
EXPECT_FALSE(absl::Symbolize((void *)(&nonstatic_func), buf, sizeof(buf)));
@@ -589,14 +541,10 @@ int main(int argc, char **argv) {
absl::InitializeSymbolizer(argv[0]);
testing::InitGoogleTest(&argc, argv);
-#if defined(ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE) || \
- defined(ABSL_INTERNAL_HAVE_DARWIN_SYMBOLIZE)
+#ifdef ABSL_INTERNAL_HAVE_ELF_SYMBOLIZE
TestWithPCInsideInlineFunction();
TestWithPCInsideNonInlineFunction();
TestWithReturnAddress();
-#if defined(__arm__) && ABSL_HAVE_ATTRIBUTE(target)
- TestArmThumbOverlap();
-#endif
#endif
return RUN_ALL_TESTS();
diff --git a/third_party/abseil-cpp/absl/flags/BUILD.bazel b/third_party/abseil-cpp/absl/flags/BUILD.bazel
index d20deab464..cdb4e7e8fe 100644
--- a/third_party/abseil-cpp/absl/flags/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/flags/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,21 +24,29 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
- name = "path_util",
+ name = "flag_internal",
+ srcs = [
+ "internal/flag.cc",
+ ],
hdrs = [
- "internal/path_util.h",
+ "internal/flag.h",
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl/flags:__pkg__",
- ],
+ visibility = ["//absl/base:__subpackages__"],
deps = [
+ ":config",
+ ":handle",
+ ":registry",
+ "//absl/base",
"//absl/base:config",
+ "//absl/base:core_headers",
+ "//absl/memory",
"//absl/strings",
+ "//absl/synchronization",
],
)
@@ -64,6 +73,22 @@ cc_library(
)
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 = "config",
srcs = [
"usage_config.cc",
@@ -104,111 +129,48 @@ cc_library(
)
cc_library(
- name = "commandlineflag_internal",
- srcs = [
- "internal/commandlineflag.cc",
- ],
+ name = "handle",
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",
+ ":marshalling",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/container:flat_hash_map",
"//absl/strings",
- "//absl/synchronization",
+ "//absl/types:optional",
],
)
cc_library(
- name = "flag_internal",
+ name = "registry",
srcs = [
- "internal/flag.cc",
+ "internal/registry.cc",
+ "internal/type_erased.cc",
],
hdrs = [
- "internal/flag.h",
- "internal/sequence_lock.h",
+ "internal/registry.h",
+ "internal/type_erased.h",
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//absl/base:__subpackages__"],
+ visibility = [
+ "//absl/flags:__pkg__",
+ ],
deps = [
- ":commandlineflag",
- ":commandlineflag_internal",
":config",
- ":marshalling",
- ":reflection",
- "//absl/base",
+ ":handle",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/memory",
- "//absl/meta:type_traits",
+ "//absl/base:raw_logging_internal",
"//absl/strings",
"//absl/synchronization",
- "//absl/utility",
],
)
@@ -216,7 +178,6 @@ cc_library(
name = "flag",
srcs = [
"flag.cc",
- "internal/flag_msvc.inc",
],
hdrs = [
"declare.h",
@@ -227,7 +188,9 @@ cc_library(
deps = [
":config",
":flag_internal",
- ":reflection",
+ ":handle",
+ ":marshalling",
+ ":registry",
"//absl/base",
"//absl/base:config",
"//absl/base:core_headers",
@@ -249,17 +212,15 @@ cc_library(
"//absl/flags:__pkg__",
],
deps = [
- ":commandlineflag",
":config",
":flag",
":flag_internal",
+ ":handle",
":path_util",
- ":private_handle_accessor",
":program_name",
- ":reflection",
+ ":registry",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/container:flat_hash_map",
"//absl/strings",
],
)
@@ -293,14 +254,12 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":commandlineflag",
- ":commandlineflag_internal",
":config",
":flag",
":flag_internal",
- ":private_handle_accessor",
+ ":handle",
":program_name",
- ":reflection",
+ ":registry",
":usage",
":usage_internal",
"//absl/base:config",
@@ -317,17 +276,15 @@ cc_test(
name = "commandlineflag_test",
size = "small",
srcs = [
- "commandlineflag_test.cc",
+ "internal/commandlineflag_test.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":commandlineflag",
- ":commandlineflag_internal",
":config",
":flag",
- ":private_handle_accessor",
- ":reflection",
+ ":handle",
+ ":registry",
"//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest_main",
@@ -361,12 +318,10 @@ cc_test(
":config",
":flag",
":flag_internal",
- ":marshalling",
- ":reflection",
+ ":handle",
+ ":registry",
"//absl/base:core_headers",
- "//absl/base:malloc_internal",
"//absl/strings",
- "//absl/time",
"@com_google_googletest//:gtest_main",
],
)
@@ -378,18 +333,10 @@ cc_binary(
"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",
@@ -411,36 +358,35 @@ cc_test(
)
cc_test(
- name = "parse_test",
+ name = "path_util_test",
size = "small",
srcs = [
- "parse_test.cc",
+ "internal/path_util_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",
+ ":path_util",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
- name = "path_util_test",
+ name = "parse_test",
size = "small",
srcs = [
- "internal/path_util_test.cc",
+ "parse_test.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":path_util",
+ ":flag",
+ ":parse",
+ ":registry",
+ "//absl/base:raw_logging_internal",
+ "//absl/base:scoped_set_env",
+ "//absl/strings",
+ "//absl/types:span",
"@com_google_googletest//:gtest_main",
],
)
@@ -461,40 +407,19 @@ cc_test(
)
cc_test(
- name = "reflection_test",
+ name = "type_erased_test",
size = "small",
srcs = [
- "reflection_test.cc",
+ "internal/type_erased_test.cc",
],
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":commandlineflag_internal",
":flag",
+ ":handle",
":marshalling",
- ":reflection",
- ":usage_internal",
+ ":registry",
"//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",
],
)
@@ -530,9 +455,10 @@ cc_test(
":parse",
":path_util",
":program_name",
- ":reflection",
+ ":registry",
":usage",
":usage_internal",
+ "//absl/memory",
"//absl/strings",
"@com_google_googletest//:gtest",
],
diff --git a/third_party/abseil-cpp/absl/flags/CMakeLists.txt b/third_party/abseil-cpp/absl/flags/CMakeLists.txt
index 7f3298e9dd..1d25f0ded8 100644
--- a/third_party/abseil-cpp/absl/flags/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/flags/CMakeLists.txt
@@ -17,16 +17,22 @@
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- flags_path_util
+ flags_internal
+ SRCS
+ "internal/flag.cc"
HDRS
- "internal/path_util.h"
+ "internal/flag.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
+ absl::base
absl::config
- absl::strings
+ absl::flags_config
+ absl::flags_handle
+ absl::flags_registry
+ absl::synchronization
PUBLIC
)
@@ -51,6 +57,22 @@ absl_cc_library(
PUBLIC
)
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+ NAME
+ flags_path_util
+ HDRS
+ "internal/path_util.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ LINKOPTS
+ ${ABSL_DEFAULT_LINKOPTS}
+ DEPS
+ absl::config
+ absl::strings
+ PUBLIC
+)
+
absl_cc_library(
NAME
flags_config
@@ -94,9 +116,7 @@ absl_cc_library(
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- flags_commandlineflag_internal
- SRCS
- "internal/commandlineflag.cc"
+ flags_handle
HDRS
"internal/commandlineflag.h"
COPTS
@@ -105,93 +125,37 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::fast_type_id
-)
-
-absl_cc_library(
- NAME
- flags_commandlineflag
- SRCS
- "commandlineflag.cc"
- HDRS
- "commandlineflag.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
- DEPS
- absl::config
- absl::fast_type_id
- absl::flags_commandlineflag_internal
+ absl::flags_config
+ absl::flags_marshalling
+ absl::core_headers
absl::optional
+ absl::raw_logging_internal
absl::strings
+ absl::synchronization
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- flags_private_handle_accessor
- SRCS
- "internal/private_handle_accessor.cc"
- HDRS
- "internal/private_handle_accessor.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
- DEPS
- absl::config
- absl::flags_commandlineflag
- absl::flags_commandlineflag_internal
- absl::strings
-)
-
-absl_cc_library(
- NAME
- flags_reflection
+ flags_registry
SRCS
- "reflection.cc"
+ "internal/registry.cc"
+ "internal/type_erased.cc"
HDRS
- "reflection.h"
"internal/registry.h"
+ "internal/type_erased.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::flags_commandlineflag
- absl::flags_private_handle_accessor
absl::flags_config
+ absl::flags_handle
+ absl::core_headers
+ absl::raw_logging_internal
absl::strings
absl::synchronization
- absl::flat_hash_map
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_library(
- NAME
- flags_internal
- SRCS
- "internal/flag.cc"
- HDRS
- "internal/flag.h"
- "internal/sequence_lock.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
- DEPS
- absl::base
- absl::config
- absl::flags_commandlineflag
- absl::flags_commandlineflag_internal
- absl::flags_config
- absl::flags_marshalling
- absl::synchronization
- absl::meta
- absl::utility
- PUBLIC
)
absl_cc_library(
@@ -202,17 +166,17 @@ absl_cc_library(
HDRS
"declare.h"
"flag.h"
- "internal/flag_msvc.inc"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::flags_commandlineflag
absl::flags_config
+ absl::flags_handle
absl::flags_internal
- absl::flags_reflection
+ absl::flags_marshalling
+ absl::flags_registry
absl::base
absl::core_headers
absl::strings
@@ -234,13 +198,11 @@ absl_cc_library(
absl::config
absl::flags_config
absl::flags
- absl::flags_commandlineflag
+ absl::flags_handle
absl::flags_internal
absl::flags_path_util
- absl::flags_private_handle_accessor
absl::flags_program_name
- absl::flags_reflection
- absl::flat_hash_map
+ absl::flags_registry
absl::strings
absl::synchronization
)
@@ -281,12 +243,10 @@ absl_cc_library(
absl::core_headers
absl::flags_config
absl::flags
- absl::flags_commandlineflag
- absl::flags_commandlineflag_internal
+ absl::flags_handle
absl::flags_internal
- absl::flags_private_handle_accessor
absl::flags_program_name
- absl::flags_reflection
+ absl::flags_registry
absl::flags_usage
absl::strings
absl::synchronization
@@ -299,19 +259,17 @@ absl_cc_test(
NAME
flags_commandlineflag_test
SRCS
- "commandlineflag_test.cc"
+ "internal/commandlineflag_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
absl::flags
- absl::flags_commandlineflag
- absl::flags_commandlineflag_internal
absl::flags_config
- absl::flags_private_handle_accessor
- absl::flags_reflection
+ absl::flags_handle
+ absl::flags_registry
absl::memory
absl::strings
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -323,7 +281,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::flags_config
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -338,12 +296,11 @@ absl_cc_test(
absl::core_headers
absl::flags
absl::flags_config
+ absl::flags_handle
absl::flags_internal
- absl::flags_marshalling
- absl::flags_reflection
+ absl::flags_registry
absl::strings
- absl::time
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -355,7 +312,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::flags_marshalling
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -368,13 +325,12 @@ absl_cc_test(
DEPS
absl::flags
absl::flags_parse
- absl::flags_reflection
- absl::flags_usage_internal
+ absl::flags_registry
absl::raw_logging_internal
absl::scoped_set_env
absl::span
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -386,7 +342,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::flags_path_util
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -399,38 +355,24 @@ absl_cc_test(
DEPS
absl::flags_program_name
absl::strings
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
NAME
- flags_reflection_test
+ flags_type_erased_test
SRCS
- "reflection_test.cc"
+ "internal/type_erased_test.cc"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::flags_commandlineflag_internal
absl::flags
- absl::flags_reflection
- absl::flags_usage
+ absl::flags_handle
+ absl::flags_marshalling
+ absl::flags_registry
absl::memory
absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- flags_sequence_lock_test
- SRCS
- "internal/sequence_lock_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::flags_internal
- absl::time
- GTest::gmock_main
+ gtest_main
)
absl_cc_test(
@@ -445,7 +387,7 @@ absl_cc_test(
absl::flags_path_util
absl::flags_program_name
absl::strings
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -461,8 +403,9 @@ absl_cc_test(
absl::flags_path_util
absl::flags_program_name
absl::flags_parse
- absl::flags_reflection
+ absl::flags_registry
absl::flags_usage
+ absl::memory
absl::strings
- GTest::gtest
+ gtest
)
diff --git a/third_party/abseil-cpp/absl/flags/commandlineflag.cc b/third_party/abseil-cpp/absl/flags/commandlineflag.cc
deleted file mode 100644
index 9f3b4a5a28..0000000000
--- a/third_party/abseil-cpp/absl/flags/commandlineflag.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/commandlineflag.h b/third_party/abseil-cpp/absl/flags/commandlineflag.h
deleted file mode 100644
index f2fa08977f..0000000000
--- a/third_party/abseil-cpp/absl/flags/commandlineflag.h
+++ /dev/null
@@ -1,200 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/commandlineflag_test.cc b/third_party/abseil-cpp/absl/flags/commandlineflag_test.cc
deleted file mode 100644
index 585db4ba78..0000000000
--- a/third_party/abseil-cpp/absl/flags/commandlineflag_test.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/config.h b/third_party/abseil-cpp/absl/flags/config.h
index 5ab1f311dc..001f8feaf6 100644
--- a/third_party/abseil-cpp/absl/flags/config.h
+++ b/third_party/abseil-cpp/absl/flags/config.h
@@ -45,6 +45,17 @@
#define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES
#endif
+// ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD macro is used for using atomics with
+// double words, e.g. absl::Duration.
+// For reasons in bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878, modern
+// versions of GCC do not support cmpxchg16b instruction in standard atomics.
+#ifdef ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD
+#error "ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD should not be defined."
+#elif defined(__clang__) && defined(__x86_64__) && \
+ defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16)
+#define ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD 1
+#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
@@ -53,24 +64,4 @@
#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/third_party/abseil-cpp/absl/flags/declare.h b/third_party/abseil-cpp/absl/flags/declare.h
index b9794d8b85..0f8cc6a599 100644
--- a/third_party/abseil-cpp/absl/flags/declare.h
+++ b/third_party/abseil-cpp/absl/flags/declare.h
@@ -26,6 +26,7 @@
#define ABSL_FLAGS_DECLARE_H_
#include "absl/base/config.h"
+#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/third_party/abseil-cpp/absl/flags/flag.cc b/third_party/abseil-cpp/absl/flags/flag.cc
index 531df1287a..f7a457bf0c 100644
--- a/third_party/abseil-cpp/absl/flags/flag.cc
+++ b/third_party/abseil-cpp/absl/flags/flag.cc
@@ -16,6 +16,8 @@
#include "absl/flags/flag.h"
#include "absl/base/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/flag.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/third_party/abseil-cpp/absl/flags/flag.h b/third_party/abseil-cpp/absl/flags/flag.h
index a724ccc97d..cff02c1fcb 100644
--- a/third_party/abseil-cpp/absl/flags/flag.h
+++ b/third_party/abseil-cpp/absl/flags/flag.h
@@ -33,12 +33,14 @@
#include <type_traits>
#include "absl/base/attributes.h"
+#include "absl/base/casts.h"
#include "absl/base/config.h"
-#include "absl/base/optimization.h"
#include "absl/flags/config.h"
+#include "absl/flags/declare.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/flags/internal/flag.h"
#include "absl/flags/internal/registry.h"
-#include "absl/strings/string_view.h"
+#include "absl/flags/marshalling.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -71,7 +73,98 @@ ABSL_NAMESPACE_BEGIN
template <typename T>
using Flag = flags_internal::Flag<T>;
#else
-#include "absl/flags/internal/flag_msvc.inc"
+// 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},
+ default_value_gen_);
+ 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(); }
+ bool IsAbseilFlag() const { return GetImpl()->IsAbseilFlag(); }
+ 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();
+ }
+ absl::string_view Typename() const { return GetImpl()->Typename(); }
+ 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 GetImpl()->Get(); }
+ bool AtomicGet(T* v) const { return GetImpl()->AtomicGet(v); }
+ void Set(const T& v) { GetImpl()->Set(v); }
+ void SetCallback(const flags_internal::FlagCallbackFunc mutation_callback) {
+ GetImpl()->SetCallback(mutation_callback);
+ }
+ void InvokeCallback() { GetImpl()->InvokeCallback(); }
+
+ // 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()
@@ -92,7 +185,7 @@ using Flag = flags_internal::Flag<T>;
// 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);
+ return flag.Get();
}
// SetFlag()
@@ -104,7 +197,7 @@ ABSL_MUST_USE_RESULT T GetFlag(const absl::Flag<T>& flag) {
// but especially within performance-critical code.
template <typename T>
void SetFlag(absl::Flag<T>* flag, const T& v) {
- flags_internal::FlagImplPeer::InvokeSet(*flag, v);
+ flag->Set(v);
}
// Overload of `SetFlag()` to allow callers to pass in a value that is
@@ -113,22 +206,7 @@ void SetFlag(absl::Flag<T>* flag, const T& v) {
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);
+ flag->Set(value);
}
ABSL_NAMESPACE_END
@@ -171,8 +249,6 @@ ABSL_NAMESPACE_END
//
// ABSL_FLAG(T, name, default_value, help).OnUpdate(callback);
//
-// `callback` should be convertible to `void (*)()`.
-//
// 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
@@ -187,36 +263,33 @@ ABSL_NAMESPACE_END
// 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)
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, false>(&flag)
+#else
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, false>(flag.GetImpl())
+#endif
#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__)
+#if !defined(_MSC_VER) || defined(__clang__)
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, true>(&flag)
+#else
+#define ABSL_FLAG_IMPL_REGISTRAR(T, flag) \
+ absl::flags_internal::FlagRegistrar<T, true>(flag.GetImpl())
+#endif
#endif
// ABSL_FLAG_IMPL macro definition conditional on ABSL_FLAGS_STRIP_HELP
@@ -232,48 +305,50 @@ ABSL_NAMESPACE_END
// 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 absl_flag_help = ABSL_FLAG_IMPL_FLAGHELP(txt)) { \
- return absl_flag_help; \
- } \
- 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* absl_flag_default_loc) { \
- new (absl_flag_default_loc) Type(AbslFlagDefaultGenFor##name{}.value); \
- } \
- };
+#define ABSL_FLAG_IMPL_DECLARE_HELP_WRAPPER(name, txt) \
+ struct AbslFlagHelpGenFor##name { \
+ template <typename T = void> \
+ static constexpr const char* Const() { \
+ return absl::flags_internal::HelpConstexprWrap( \
+ ABSL_FLAG_IMPL_FLAGHELP(txt)); \
+ } \
+ static std::string NonConst() { return ABSL_FLAG_IMPL_FLAGHELP(txt); } \
+ }
+
+#define ABSL_FLAG_IMPL_DECLARE_DEF_VAL_WRAPPER(name, Type, default_value) \
+ static void* AbslFlagsInitFlag##name() { \
+ return absl::flags_internal::MakeFromDefaultValue<Type>(default_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)
+#if !defined(_MSC_VER) || defined(__clang__)
+#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::flags_internal::HelpArg<AbslFlagHelpGenFor##name>(0), \
+ &AbslFlagsInitFlag##name}; \
+ extern bool FLAGS_no##name; \
+ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+#else
+// MSVC version uses aggregate initialization. We also do not try to
+// optimize away help wrapper.
+#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(), \
+ &AbslFlagHelpGenFor##name::NonConst, &AbslFlagsInitFlag##name}; \
+ extern bool FLAGS_no##name; \
+ bool FLAGS_no##name = ABSL_FLAG_IMPL_REGISTRAR(Type, FLAGS_##name)
+#endif
// ABSL_RETIRED_FLAG
//
@@ -294,12 +369,11 @@ ABSL_NAMESPACE_END
//
// `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{})
+// TODO(rogeeff): Return an anonymous struct instead of bool, and place it into
+// the unnamed namespace.
+#define ABSL_RETIRED_FLAG(type, flagname, default_value, explanation) \
+ ABSL_ATTRIBUTE_UNUSED static const bool ignored_##flagname = \
+ ([] { return type(default_value); }, \
+ absl::flags_internal::RetiredFlag<type>(#flagname))
#endif // ABSL_FLAGS_FLAG_H_
diff --git a/third_party/abseil-cpp/absl/flags/flag_benchmark.cc b/third_party/abseil-cpp/absl/flags/flag_benchmark.cc
index fc572d9ce3..87f731704c 100644
--- a/third_party/abseil-cpp/absl/flags/flag_benchmark.cc
+++ b/third_party/abseil-cpp/absl/flags/flag_benchmark.cc
@@ -13,16 +13,7 @@
// 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"
@@ -101,150 +92,20 @@ std::string AbslUnparseFlag(const UDT&) { return ""; }
A(AbslDuration) \
A(UDT)
-#define REPLICATE_0(A, T, name, index) A(T, name, index)
-#define REPLICATE_1(A, T, name, index) \
- REPLICATE_0(A, T, name, index##0) REPLICATE_0(A, T, name, index##1)
-#define REPLICATE_2(A, T, name, index) \
- REPLICATE_1(A, T, name, index##0) REPLICATE_1(A, T, name, index##1)
-#define REPLICATE_3(A, T, name, index) \
- REPLICATE_2(A, T, name, index##0) REPLICATE_2(A, T, name, index##1)
-#define REPLICATE_4(A, T, name, index) \
- REPLICATE_3(A, T, name, index##0) REPLICATE_3(A, T, name, index##1)
-#define REPLICATE_5(A, T, name, index) \
- REPLICATE_4(A, T, name, index##0) REPLICATE_4(A, T, name, index##1)
-#define REPLICATE_6(A, T, name, index) \
- REPLICATE_5(A, T, name, index##0) REPLICATE_5(A, T, name, index##1)
-#define REPLICATE_7(A, T, name, index) \
- REPLICATE_6(A, T, name, index##0) REPLICATE_6(A, T, name, index##1)
-#define REPLICATE_8(A, T, name, index) \
- REPLICATE_7(A, T, name, index##0) REPLICATE_7(A, T, name, index##1)
-#define REPLICATE_9(A, T, name, index) \
- REPLICATE_8(A, T, name, index##0) REPLICATE_8(A, T, name, index##1)
-#if defined(_MSC_VER)
-#define REPLICATE(A, T, name) \
- REPLICATE_7(A, T, name, 0) REPLICATE_7(A, T, name, 1)
-#define SINGLE_FLAG(T) FLAGS_##T##_flag_00000000
-#else
-#define REPLICATE(A, T, name) \
- REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
-#define SINGLE_FLAG(T) FLAGS_##T##_flag_0000000000
-#endif
-#define REPLICATE_ALL(A, T, name) \
- REPLICATE_9(A, T, name, 0) REPLICATE_9(A, T, name, 1)
-
-#define COUNT(T, name, index) +1
-constexpr size_t kNumFlags = 0 REPLICATE(COUNT, _, _);
+#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
-#define DEFINE_FLAG(T, name, index) ABSL_FLAG(T, name##_##index, {}, "");
-#define FLAG_DEF(T) REPLICATE(DEFINE_FLAG, T, T##_flag);
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 BLOAT_FLAG(_unused1, _unused2, index) \
- ABSL_FLAG(int, bloat_flag_##index, 0, "");
-REPLICATE_ALL(BLOAT_FLAG, _, _)
namespace {
-#define FLAG_PTR(T, name, index) &FLAGS_##name##_##index,
-#define FLAG_PTR_ARR(T) \
- static constexpr absl::Flag<T>* FlagPtrs_##T[] = { \
- REPLICATE(FLAG_PTR, T, T##_flag)};
-BENCHMARKED_TYPES(FLAG_PTR_ARR)
-
-#define BM_SingleGetFlag(T) \
- void BM_SingleGetFlag_##T(benchmark::State& state) { \
- for (auto _ : state) { \
- benchmark::DoNotOptimize(absl::GetFlag(SINGLE_FLAG(T))); \
- } \
- } \
- BENCHMARK(BM_SingleGetFlag_##T)->ThreadRange(1, 16);
-
-BENCHMARKED_TYPES(BM_SingleGetFlag)
-
-template <typename T>
-struct Accumulator {
- using type = T;
-};
-template <>
-struct Accumulator<String> {
- using type = size_t;
-};
-template <>
-struct Accumulator<VectorOfStrings> {
- using type = size_t;
-};
-template <>
-struct Accumulator<OptionalInt> {
- using type = bool;
-};
-template <>
-struct Accumulator<OptionalString> {
- using type = bool;
-};
-template <>
-struct Accumulator<UDT> {
- using type = bool;
-};
-
-template <typename T>
-void Accumulate(typename Accumulator<T>::type& a, const T& f) {
- a += f;
-}
-void Accumulate(bool& a, bool f) { a = a || f; }
-void Accumulate(size_t& a, const std::string& f) { a += f.size(); }
-void Accumulate(size_t& a, const std::vector<std::string>& f) { a += f.size(); }
-void Accumulate(bool& a, const OptionalInt& f) { a |= f.has_value(); }
-void Accumulate(bool& a, const OptionalString& f) { a |= f.has_value(); }
-void Accumulate(bool& a, const UDT& f) {
- a |= reinterpret_cast<int64_t>(&f) & 0x1;
-}
-
-#define BM_ManyGetFlag(T) \
- void BM_ManyGetFlag_##T(benchmark::State& state) { \
- Accumulator<T>::type res = {}; \
- while (state.KeepRunningBatch(kNumFlags)) { \
- for (auto* flag_ptr : FlagPtrs_##T) { \
- Accumulate(res, absl::GetFlag(*flag_ptr)); \
- } \
- } \
- benchmark::DoNotOptimize(res); \
- } \
- BENCHMARK(BM_ManyGetFlag_##T)->ThreadRange(1, 8);
-
-BENCHMARKED_TYPES(BM_ManyGetFlag)
+#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);
-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);
-
- while (state.KeepRunningBatch(kNumFlags)) {
- for (auto* flag_ptr : FlagPtrs_bool) {
- benchmark::DoNotOptimize(absl::FindCommandLineFlag(flag_ptr->Name()));
- }
- }
-}
-BENCHMARK(BM_ThreadedFindCommandLineFlag)->ThreadRange(1, 16);
+BENCHMARKED_TYPES(BM_GetFlag)
} // namespace
-
-#define InvokeGetFlag(T) \
- T AbslInvokeGetFlag##T() { return absl::GetFlag(SINGLE_FLAG(T)); } \
- 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/third_party/abseil-cpp/absl/flags/flag_benchmark.lds b/third_party/abseil-cpp/absl/flags/flag_benchmark.lds
deleted file mode 100644
index af115dfc00..0000000000
--- a/third_party/abseil-cpp/absl/flags/flag_benchmark.lds
+++ /dev/null
@@ -1,13 +0,0 @@
-/* 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/third_party/abseil-cpp/absl/flags/flag_test.cc b/third_party/abseil-cpp/absl/flags/flag_test.cc
index 6e974a5b5e..4984d28403 100644
--- a/third_party/abseil-cpp/absl/flags/flag_test.cc
+++ b/third_party/abseil-cpp/absl/flags/flag_test.cc
@@ -15,31 +15,25 @@
#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/commandlineflag.h"
#include "absl/flags/internal/flag.h"
-#include "absl/flags/marshalling.h"
-#include "absl/flags/reflection.h"
+#include "absl/flags/internal/registry.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);
@@ -49,19 +43,37 @@ 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* TestMakeDflt() {
+ return new T{};
}
void TestCallback() {}
+template <typename T>
+bool TestConstructionFor() {
+ constexpr flags::FlagHelpArg help_arg{flags::FlagHelpMsg("literal help"),
+ flags::FlagHelpKind::kLiteral};
+ constexpr flags::Flag<T> f1("f1", "file", help_arg, &TestMakeDflt<T>);
+ EXPECT_EQ(f1.Name(), "f1");
+ EXPECT_EQ(f1.Help(), "literal help");
+ EXPECT_EQ(f1.Filename(), "file");
+
+ ABSL_CONST_INIT static flags::Flag<T> f2(
+ "f2", "file",
+ {flags::FlagHelpMsg(&TestHelpMsg), flags::FlagHelpKind::kGenFunc},
+ &TestMakeDflt<T>);
+ flags::FlagRegistrar<T, false>(&f2).OnUpdate(TestCallback);
+
+ EXPECT_EQ(f2.Name(), "f2");
+ EXPECT_EQ(f2.Help(), "dynamic help");
+ EXPECT_EQ(f2.Filename(), "file");
+
+ return true;
+}
+
struct UDT {
UDT() = default;
UDT(const UDT&) = default;
- UDT& operator=(const UDT&) = default;
};
bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
std::string AbslUnparseFlag(const UDT&) { return ""; }
@@ -84,124 +96,21 @@ class FlagTest : public testing::Test {
#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::kValueAndInitBit);
- EXPECT_EQ(flags::StorageKind<bool>(),
- flags::FlagValueStorageKind::kValueAndInitBit);
- 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);
+ TestConstructionFor<bool>();
+ TestConstructionFor<int16_t>();
+ TestConstructionFor<uint16_t>();
+ TestConstructionFor<int32_t>();
+ TestConstructionFor<uint32_t>();
+ TestConstructionFor<int64_t>();
+ TestConstructionFor<uint64_t>();
+ TestConstructionFor<double>();
+ TestConstructionFor<float>();
+ TestConstructionFor<std::string>();
+
+ TestConstructionFor<UDT>();
}
// --------------------------------------------------------------------
@@ -219,7 +128,6 @@ 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 {
@@ -227,30 +135,17 @@ namespace {
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");
+ EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
+ EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
+ EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
+ EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
+ EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
+ EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
+ EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
+ EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
+ EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
+ EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
+ EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
}
#endif // !ABSL_FLAGS_STRIP_NAMES
@@ -269,7 +164,6 @@ 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 {
@@ -277,169 +171,66 @@ namespace {
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();
+ EXPECT_EQ(FLAGS_test_flag_01.Name(), "test_flag_01");
+ EXPECT_EQ(FLAGS_test_flag_01.Help(), "test flag 01");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_01.Filename(), expected_file_name))
+ << FLAGS_test_flag_01.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_02.Name(), "test_flag_02");
+ EXPECT_EQ(FLAGS_test_flag_02.Help(), "test flag 02");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_02.Filename(), expected_file_name))
+ << FLAGS_test_flag_02.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_03.Name(), "test_flag_03");
+ EXPECT_EQ(FLAGS_test_flag_03.Help(), "test flag 03");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_03.Filename(), expected_file_name))
+ << FLAGS_test_flag_03.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_04.Name(), "test_flag_04");
+ EXPECT_EQ(FLAGS_test_flag_04.Help(), "test flag 04");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_04.Filename(), expected_file_name))
+ << FLAGS_test_flag_04.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_05.Name(), "test_flag_05");
+ EXPECT_EQ(FLAGS_test_flag_05.Help(), "test flag 05");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_05.Filename(), expected_file_name))
+ << FLAGS_test_flag_05.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_06.Name(), "test_flag_06");
+ EXPECT_EQ(FLAGS_test_flag_06.Help(), "test flag 06");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_06.Filename(), expected_file_name))
+ << FLAGS_test_flag_06.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_07.Name(), "test_flag_07");
+ EXPECT_EQ(FLAGS_test_flag_07.Help(), "test flag 07");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_07.Filename(), expected_file_name))
+ << FLAGS_test_flag_07.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_08.Name(), "test_flag_08");
+ EXPECT_EQ(FLAGS_test_flag_08.Help(), "test flag 08");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_08.Filename(), expected_file_name))
+ << FLAGS_test_flag_08.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_09.Name(), "test_flag_09");
+ EXPECT_EQ(FLAGS_test_flag_09.Help(), "test flag 09");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_09.Filename(), expected_file_name))
+ << FLAGS_test_flag_09.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_10.Name(), "test_flag_10");
+ EXPECT_EQ(FLAGS_test_flag_10.Help(), "test flag 10");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_10.Filename(), expected_file_name))
+ << FLAGS_test_flag_10.Filename();
+
+ EXPECT_EQ(FLAGS_test_flag_11.Name(), "test_flag_11");
+ EXPECT_EQ(FLAGS_test_flag_11.Help(), "test flag 11");
+ EXPECT_TRUE(absl::EndsWith(FLAGS_test_flag_11.Filename(), expected_file_name))
+ << FLAGS_test_flag_11.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);
@@ -451,68 +242,6 @@ TEST_F(FlagTest, TestDefault) {
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{});
}
// --------------------------------------------------------------------
@@ -550,75 +279,6 @@ TEST_F(FlagTest, TestGetSet) {
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();
}
// --------------------------------------------------------------------
@@ -627,33 +287,28 @@ 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");
+ABSL_FLAG(int, test_flag_12, GetDflt1(), "test flag 12");
+ABSL_FLAG(std::string, test_flag_13, absl::StrCat("AAA", "BBB"),
+ "test flag 13");
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");
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_12), 1);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_13), "AAABBB");
}
// --------------------------------------------------------------------
} // namespace
-ABSL_FLAG(bool, test_flag_with_non_const_help, true,
- absl::StrCat("test ", "flag ", "non const help"));
+ABSL_FLAG(bool, test_flag_14, true, absl::StrCat("test ", "flag ", "14"));
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");
+ EXPECT_EQ(FLAGS_test_flag_14.Help(), "test flag 14");
}
#endif //! ABSL_FLAGS_STRIP_HELP
@@ -719,16 +374,14 @@ std::string AbslUnparseFlag(const CustomUDT& f) {
} // namespace
-ABSL_FLAG(CustomUDT, test_flag_custom_udt, CustomUDT(), "test flag custom UDT");
+ABSL_FLAG(CustomUDT, test_flag_15, CustomUDT(), "test flag 15");
namespace {
TEST_F(FlagTest, TestCustomUDT) {
- EXPECT_EQ(flags::StorageKind<CustomUDT>(),
- flags::FlagValueStorageKind::kOneWordAtomic);
- 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));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(1, 1));
+ absl::SetFlag(&FLAGS_test_flag_15, CustomUDT(2, 3));
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_15), CustomUDT(2, 3));
}
// MSVC produces link error on the type mismatch.
@@ -738,22 +391,18 @@ TEST_F(FlagTest, TestCustomUDT) {
using FlagDeathTest = FlagTest;
TEST_F(FlagDeathTest, TestTypeMismatchValidations) {
-#if !defined(NDEBUG)
- EXPECT_DEATH_IF_SUPPORTED(
+ EXPECT_DEBUG_DEATH(
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(
+ EXPECT_DEATH(absl::SetFlag(&FLAGS_mistyped_int_flag, 1),
+ "Flag 'mistyped_int_flag' is defined as one type and declared "
+ "as another");
+
+ EXPECT_DEATH(static_cast<void>(absl::GetFlag(FLAGS_mistyped_string_flag)),
+ "Flag 'mistyped_string_flag' is defined as one type and "
+ "declared as another");
+ EXPECT_DEATH(
absl::SetFlag(&FLAGS_mistyped_string_flag, std::vector<std::string>{}),
"Flag 'mistyped_string_flag' is defined as one type and declared as "
"another");
@@ -791,17 +440,16 @@ std::string AbslUnparseFlag(const ConversionTestVal& val) {
// 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");
+ABSL_FLAG(ConversionTestVal, test_flag_16,
+ ConversionTestVal::ViaImplicitConv::kTen, "test flag 16");
namespace {
TEST_F(FlagTest, CanSetViaImplicitConversion) {
- EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 10);
- absl::SetFlag(&FLAGS_test_flag_implicit_conv,
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 10);
+ absl::SetFlag(&FLAGS_test_flag_16,
ConversionTestVal::ViaImplicitConv::kEleven);
- EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_implicit_conv).a, 11);
+ EXPECT_EQ(absl::GetFlag(FLAGS_test_flag_16).a, 11);
}
// --------------------------------------------------------------------
@@ -846,134 +494,25 @@ TEST_F(FlagTest, TestNonDefaultConstructibleType) {
EXPECT_EQ(absl::GetFlag(FLAGS_ndc_flag2).value, 25);
}
-} // namespace
-
// --------------------------------------------------------------------
+} // 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());
+ bool is_bool = false;
+ EXPECT_TRUE(flags::IsRetiredFlag("old_bool_flag", &is_bool));
+ EXPECT_TRUE(is_bool);
+ EXPECT_TRUE(flags::IsRetiredFlag("old_int_flag", &is_bool));
+ EXPECT_FALSE(is_bool);
+ EXPECT_TRUE(flags::IsRetiredFlag("old_str_flag", &is_bool));
+ EXPECT_FALSE(is_bool);
+ EXPECT_FALSE(flags::IsRetiredFlag("some_other_flag", &is_bool));
}
} // 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
-
-// --------------------------------------------------------------------
-
-namespace {
-
-enum TestE { A = 1, B = 2, C = 3 };
-
-struct EnumWrapper {
- EnumWrapper() : e(A) {}
-
- TestE e;
-};
-
-bool AbslParseFlag(absl::string_view, EnumWrapper*, std::string*) {
- return true;
-}
-std::string AbslUnparseFlag(const EnumWrapper&) { return ""; }
-
-} // namespace
-
-ABSL_FLAG(EnumWrapper, test_enum_wrapper_flag, {}, "help");
-
-TEST_F(FlagTest, TesTypeWrappingEnum) {
- EnumWrapper value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
- EXPECT_EQ(value.e, A);
-
- value.e = B;
- absl::SetFlag(&FLAGS_test_enum_wrapper_flag, value);
- value = absl::GetFlag(FLAGS_test_enum_wrapper_flag);
- EXPECT_EQ(value.e, B);
-}
diff --git a/third_party/abseil-cpp/absl/flags/flag_test_defs.cc b/third_party/abseil-cpp/absl/flags/flag_test_defs.cc
index 4e1693cdb9..49f91dee39 100644
--- a/third_party/abseil-cpp/absl/flags/flag_test_defs.cc
+++ b/third_party/abseil-cpp/absl/flags/flag_test_defs.cc
@@ -20,5 +20,5 @@
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, "");
+ABSL_RETIRED_FLAG(bool, old_bool_flag, true,
+ "repetition of retired flag definition");
diff --git a/third_party/abseil-cpp/absl/flags/internal/commandlineflag.h b/third_party/abseil-cpp/absl/flags/internal/commandlineflag.h
index ebfe81ba1e..6363c6615b 100644
--- a/third_party/abseil-cpp/absl/flags/internal/commandlineflag.h
+++ b/third_party/abseil-cpp/absl/flags/internal/commandlineflag.h
@@ -16,19 +16,41 @@
#ifndef ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
#define ABSL_FLAGS_INTERNAL_COMMANDLINEFLAG_H_
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <typeinfo>
+
#include "absl/base/config.h"
-#include "absl/base/internal/fast_type_id.h"
+#include "absl/base/macros.h"
+#include "absl/flags/config.h"
+#include "absl/flags/marshalling.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.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
+// An alias for flag static type id. Values of type identify the flag value type
+// simialarly to typeid(T), but 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;
+using FlagStaticTypeId = void* (*)();
+
+// Address of this function template is used in current implementation as a flag
+// static type id.
+template <typename T>
+void* FlagStaticTypeIdGen() {
+#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
+ return const_cast<std::type_info*>(&typeid(T));
+#else
+ return nullptr;
+#endif
+}
// Options that control SetCommandLineOptionWithMode.
enum FlagSettingMode {
@@ -43,7 +65,7 @@ enum FlagSettingMode {
SET_FLAGS_DEFAULT
};
-// Options that control ParseFrom: Source of a value.
+// Options that control SetFromString: Source of a value.
enum ValueSource {
// Flag is being set by value specified on a command line.
kCommandLine,
@@ -55,12 +77,135 @@ enum ValueSource {
// of a flag produced this flag state from method CommandLineFlag::SaveState().
class FlagStateInterface {
public:
- virtual ~FlagStateInterface();
+ virtual ~FlagStateInterface() {}
// Restores the flag originated this object to the saved state.
virtual void Restore() const = 0;
};
+// Holds all information for a flag.
+class CommandLineFlag {
+ public:
+ constexpr CommandLineFlag() = default;
+
+ // Not copyable/assignable.
+ CommandLineFlag(const CommandLineFlag&) = delete;
+ CommandLineFlag& operator=(const CommandLineFlag&) = delete;
+
+ // Non-polymorphic access methods.
+
+ // Return true iff flag has type T.
+ template <typename T>
+ inline bool IsOfType() const {
+ return TypeId() == &flags_internal::FlagStaticTypeIdGen<T>;
+ }
+
+ // Attempts to retrieve the flag value. Returns value on success,
+ // absl::nullopt otherwise.
+ template <typename T>
+ absl::optional<T> Get() 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);
+ return std::move(u.value);
+ }
+
+ // Polymorphic access methods
+
+ // Returns name of this flag.
+ virtual absl::string_view Name() const = 0;
+ // Returns name of the file where this flag is defined.
+ virtual std::string Filename() const = 0;
+ // Returns name of the flag's value type for some built-in types or empty
+ // std::string.
+ virtual absl::string_view Typename() const = 0;
+ // Returns help message associated with this flag.
+ virtual std::string Help() const = 0;
+ // Returns true iff this object corresponds to retired flag.
+ virtual bool IsRetired() const { return false; }
+ // Returns true iff this is a handle to an Abseil Flag.
+ virtual bool IsAbseilFlag() const { return true; }
+ // Returns id of the flag's value type.
+ virtual FlagStaticTypeId TypeId() const = 0;
+ virtual bool IsModified() const = 0;
+ virtual bool IsSpecifiedOnCommandLine() const = 0;
+ virtual std::string DefaultValue() const = 0;
+ virtual std::string CurrentValue() const = 0;
+
+ // Interfaces to operate on validators.
+ virtual bool ValidateInputValue(absl::string_view value) 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<FlagStateInterface> SaveState() = 0;
+
+ // Sets the value of the flag based on specified std::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 SetFromString(absl::string_view value,
+ flags_internal::FlagSettingMode set_mode,
+ flags_internal::ValueSource source,
+ std::string* error) = 0;
+
+ // Checks that flags default value can be converted to std::string and back to the
+ // flag's value type.
+ virtual void CheckDefaultValueParsingRoundtrip() const = 0;
+
+ protected:
+ ~CommandLineFlag() = default;
+
+ private:
+ // 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;
+};
+
+// This macro is the "source of truth" for the list of supported flag built-in
+// types.
+#define ABSL_FLAGS_INTERNAL_BUILTIN_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(double) \
+ A(float) \
+ A(std::string) \
+ A(std::vector<std::string>)
+
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/flags/internal/commandlineflag_test.cc b/third_party/abseil-cpp/absl/flags/internal/commandlineflag_test.cc
new file mode 100644
index 0000000000..0e8bc3133b
--- /dev/null
+++ b/third_party/abseil-cpp/absl/flags/internal/commandlineflag_test.cc
@@ -0,0 +1,219 @@
+//
+// 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/commandlineflag.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/registry.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");
+
+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<flags::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<flags::FlagSaver> flag_saver_;
+};
+
+TEST_F(CommandLineFlagTest, TestAttributesAccessMethods) {
+ auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+ ASSERT_TRUE(flag_01);
+ EXPECT_EQ(flag_01->Name(), "int_flag");
+ EXPECT_EQ(flag_01->Help(), "int_flag help");
+ EXPECT_EQ(flag_01->Typename(), "");
+ EXPECT_TRUE(!flag_01->IsRetired());
+ EXPECT_TRUE(flag_01->IsOfType<int>());
+ EXPECT_TRUE(
+ absl::EndsWith(flag_01->Filename(),
+ "absl/flags/internal/commandlineflag_test.cc"))
+ << flag_01->Filename();
+
+ auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+ ASSERT_TRUE(flag_02);
+ EXPECT_EQ(flag_02->Name(), "string_flag");
+ EXPECT_EQ(flag_02->Help(), "string_flag help");
+ EXPECT_EQ(flag_02->Typename(), "");
+ EXPECT_TRUE(!flag_02->IsRetired());
+ EXPECT_TRUE(flag_02->IsOfType<std::string>());
+ EXPECT_TRUE(
+ absl::EndsWith(flag_02->Filename(),
+ "absl/flags/internal/commandlineflag_test.cc"))
+ << flag_02->Filename();
+
+ auto* flag_03 = flags::FindRetiredFlag("bool_retired_flag");
+
+ ASSERT_TRUE(flag_03);
+ EXPECT_EQ(flag_03->Name(), "bool_retired_flag");
+ EXPECT_EQ(flag_03->Help(), "");
+ EXPECT_EQ(flag_03->Typename(), "");
+ EXPECT_TRUE(flag_03->IsRetired());
+ EXPECT_TRUE(flag_03->IsOfType<bool>());
+ EXPECT_EQ(flag_03->Filename(), "RETIRED");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestValueAccessMethods) {
+ absl::SetFlag(&FLAGS_int_flag, 301);
+ auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+ ASSERT_TRUE(flag_01);
+ EXPECT_EQ(flag_01->CurrentValue(), "301");
+ EXPECT_EQ(flag_01->DefaultValue(), "201");
+
+ absl::SetFlag(&FLAGS_string_flag, "new_str_value");
+ auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+ ASSERT_TRUE(flag_02);
+ EXPECT_EQ(flag_02->CurrentValue(), "new_str_value");
+ EXPECT_EQ(flag_02->DefaultValue(), "dflt");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringCurrentValue) {
+ std::string err;
+
+ auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+ EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(flag_01->SetFromString("11", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+ EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(flag_01->SetFromString("-123", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), -123);
+ EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(!flag_01->SetFromString("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(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(!flag_01->SetFromString("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(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(flag_01->SetFromString("0x10", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 16);
+ EXPECT_FALSE(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(flag_01->SetFromString("011", flags::SET_FLAGS_VALUE,
+ flags::kCommandLine, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 11);
+ EXPECT_TRUE(flag_01->IsSpecifiedOnCommandLine());
+
+ EXPECT_TRUE(!flag_01->SetFromString("", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(err, "Illegal value '' specified for flag 'int_flag'");
+
+ auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+ EXPECT_TRUE(flag_02->SetFromString("xyz", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "xyz");
+
+ EXPECT_TRUE(flag_02->SetFromString("", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringDefaultValue) {
+ std::string err;
+
+ auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+ EXPECT_TRUE(flag_01->SetFromString("111", flags::SET_FLAGS_DEFAULT,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(flag_01->DefaultValue(), "111");
+
+ auto* flag_02 = flags::FindCommandLineFlag("string_flag");
+
+ EXPECT_TRUE(flag_02->SetFromString("abc", flags::SET_FLAGS_DEFAULT,
+ flags::kProgrammaticChange, &err));
+ EXPECT_EQ(flag_02->DefaultValue(), "abc");
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(CommandLineFlagTest, TestSetFromStringIfDefault) {
+ std::string err;
+
+ auto* flag_01 = flags::FindCommandLineFlag("int_flag");
+
+ EXPECT_TRUE(flag_01->SetFromString("22", flags::SET_FLAG_IF_DEFAULT,
+ flags::kProgrammaticChange, &err))
+ << err;
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 22);
+
+ EXPECT_TRUE(flag_01->SetFromString("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(flag_01->SetFromString("201", flags::SET_FLAGS_VALUE,
+ flags::kProgrammaticChange, &err));
+
+ EXPECT_TRUE(flag_01->SetFromString("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/third_party/abseil-cpp/absl/flags/internal/flag.cc b/third_party/abseil-cpp/absl/flags/internal/flag.cc
index 1515022d11..5a921e28d7 100644
--- a/third_party/abseil-cpp/absl/flags/internal/flag.cc
+++ b/third_party/abseil-cpp/absl/flags/internal/flag.cc
@@ -15,26 +15,21 @@
#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 <vector>
-#include "absl/base/call_once.h"
-#include "absl/base/casts.h"
+#include "absl/base/attributes.h"
#include "absl/base/config.h"
+#include "absl/base/const_init.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"
@@ -52,10 +47,10 @@ 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)
+bool ShouldValidateFlagValue(FlagStaticTypeId flag_type_id) {
+#define DONT_VALIDATE(T) \
+ if (flag_type_id == &FlagStaticTypeIdGen<T>) return false;
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(DONT_VALIDATE)
#undef DONT_VALIDATE
return true;
@@ -67,146 +62,55 @@ bool ShouldValidateFlagValue(FlagFastTypeId flag_type_id) {
// need to acquire these locks themselves.
class MutexRelock {
public:
- explicit MutexRelock(absl::Mutex& mu) : mu_(mu) { mu_.Unlock(); }
- ~MutexRelock() { mu_.Lock(); }
+ 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_;
+ 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_);
+ absl::MutexLock lock(reinterpret_cast<absl::Mutex*>(&data_guard_));
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- 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_));
- }
- if (ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit) {
- // We presume here the memory layout of FlagValueAndInitBit struct.
- uint8_t initialized = 1;
- std::memcpy(buf.data() + Sizeof(op_), &initialized,
- sizeof(initialized));
- }
- 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;
- }
- 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;
- }
- seq_lock_.MarkInitialized();
+ value_.dynamic = MakeInitValue().release();
+ StoreAtomic();
}
+// Ensures that the lazily initialized data is initialized,
+// and returns pointer to the mutex guarding flags data.
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.
+ // data_guard_ is initialized.
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_);
+void FlagImpl::AssertValidType(FlagStaticTypeId type_id) const {
+ FlagStaticTypeId this_type_id = flags_internal::StaticTypeId(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;
+ // `type_id` is the type id corresponding to the declaration visibile at the
+ // call site. `this_type_id` is the type id corresponding to the type stored
+ // during flag definition. They must match for this operation to be
+ // well-defined.
+ if (ABSL_PREDICT_TRUE(type_id == this_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)();
+ void* lhs_runtime_type_id = type_id();
+ void* rhs_runtime_type_id = this_type_id();
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;
+ if (*reinterpret_cast<std::type_info*>(lhs_runtime_type_id) ==
+ *reinterpret_cast<std::type_info*>(rhs_runtime_type_id))
+ return;
#endif
ABSL_INTERNAL_LOG(
@@ -216,42 +120,19 @@ void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
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;
+ if (DefaultKind() == FlagDefaultKind::kDynamicValue) {
+ res = flags_internal::Clone(op_, default_value_.dynamic_value);
+ } else {
+ res = (*default_value_.gen_func)();
}
return {res, DynValueDeleter{op_}};
}
void FlagImpl::StoreValue(const void* src) {
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- case FlagValueStorageKind::kOneWordAtomic: {
- // Load the current value to avoid setting 'init' bit manualy.
- int64_t one_word_val = OneWordValue().load(std::memory_order_acquire);
- 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;
- }
- case FlagValueStorageKind::kAlignedBuffer:
- Copy(op_, src, AlignedBufferValue());
- seq_lock_.IncrementModificationCount();
- break;
- }
+ flags_internal::Copy(op_, src, value_.dynamic);
+ StoreAtomic();
modified_ = true;
+ ++counter_;
InvokeCallback();
}
@@ -266,12 +147,9 @@ std::string FlagImpl::Help() const {
: help_.gen_func();
}
-FlagFastTypeId FlagImpl::TypeId() const {
- return flags_internal::FastTypeId(op_);
-}
-
-int64_t FlagImpl::ModificationCount() const {
- return seq_lock_.ModificationCount();
+bool FlagImpl::IsModified() const {
+ absl::MutexLock l(DataGuard());
+ return modified_;
}
bool FlagImpl::IsSpecifiedOnCommandLine() const {
@@ -287,28 +165,9 @@ std::string FlagImpl::DefaultValue() const {
}
std::string FlagImpl::CurrentValue() const {
- auto* guard = DataGuard(); // Make sure flag initialized
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- 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());
- }
- case FlagValueStorageKind::kAlignedBuffer: {
- absl::MutexLock l(guard);
- return flags_internal::Unparse(op_, AlignedBufferValue());
- }
- }
+ absl::MutexLock l(DataGuard());
- return "";
+ return flags_internal::Unparse(op_, value_.dynamic);
}
void FlagImpl::SetCallback(const FlagCallbackFunc mutation_callback) {
@@ -340,103 +199,44 @@ void FlagImpl::InvokeCallback() const {
// 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());
+ MutexRelock relock(DataGuard());
absl::MutexLock lock(&callback_->guard);
cb();
}
-std::unique_ptr<FlagStateInterface> FlagImpl::SaveState() {
- absl::MutexLock l(DataGuard());
+bool FlagImpl::RestoreState(const void* value, bool modified,
+ bool on_command_line, int64_t counter) {
+ {
+ absl::MutexLock l(DataGuard());
- bool modified = modified_;
- bool on_command_line = on_command_line_;
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- 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());
- }
- case FlagValueStorageKind::kAlignedBuffer: {
- return absl::make_unique<FlagState>(
- *this, flags_internal::Clone(op_, AlignedBufferValue()), modified,
- on_command_line, ModificationCount());
- }
+ if (counter_ == counter) return false;
}
- return nullptr;
-}
-bool FlagImpl::RestoreState(const FlagState& flag_state) {
- absl::MutexLock l(DataGuard());
- if (flag_state.counter_ == ModificationCount()) {
- return false;
- }
+ Write(value);
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- case FlagValueStorageKind::kOneWordAtomic:
- StoreValue(&flag_state.value_.one_word);
- break;
- case FlagValueStorageKind::kSequenceLocked:
- case FlagValueStorageKind::kAlignedBuffer:
- StoreValue(flag_state.value_.heap_allocated);
- break;
- }
+ {
+ absl::MutexLock l(DataGuard());
- modified_ = flag_state.modified_;
- on_command_line_ = flag_state.on_command_line_;
+ modified_ = modified;
+ on_command_line_ = 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 ||
- ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
- 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 {
+ 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);
+ *err = absl::StrCat("Illegal value '", value, "' specified for flag '",
+ Name(), "'", err_sep, parse_err);
return nullptr;
}
@@ -444,62 +244,32 @@ std::unique_ptr<void, DynValueDeleter> FlagImpl::TryParse(
}
void FlagImpl::Read(void* dst) const {
- auto* guard = DataGuard(); // Make sure flag initialized
- switch (ValueStorageKind()) {
- case FlagValueStorageKind::kValueAndInitBit:
- 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;
- }
- case FlagValueStorageKind::kAlignedBuffer: {
- absl::MutexLock l(guard);
- flags_internal::CopyConstruct(op_, AlignedBufferValue(), dst);
- break;
- }
- }
-}
+ absl::ReaderMutexLock l(DataGuard());
-int64_t FlagImpl::ReadOneWord() const {
- assert(ValueStorageKind() == FlagValueStorageKind::kOneWordAtomic ||
- ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
- auto* guard = DataGuard(); // Make sure flag initialized
- (void)guard;
- return OneWordValue().load(std::memory_order_acquire);
+ flags_internal::CopyConstruct(op_, value_.dynamic, dst);
}
-bool FlagImpl::ReadOneBool() const {
- assert(ValueStorageKind() == FlagValueStorageKind::kValueAndInitBit);
- auto* guard = DataGuard(); // Make sure flag initialized
- (void)guard;
- return absl::bit_cast<FlagValueAndInitBit<bool>>(
- OneWordValue().load(std::memory_order_acquire))
- .value;
-}
+void FlagImpl::StoreAtomic() {
+ size_t data_size = flags_internal::Sizeof(op_);
-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;
+ if (data_size <= sizeof(int64_t)) {
+ int64_t t = 0;
+ std::memcpy(&t, value_.dynamic, data_size);
+ value_.atomics.small_atomic.store(t, std::memory_order_release);
}
- // 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);
+#if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD)
+ else if (data_size <= sizeof(FlagsInternalTwoWordsType)) {
+ FlagsInternalTwoWordsType t{0, 0};
+ std::memcpy(&t, value_.dynamic, data_size);
+ value_.atomics.big_atomic.store(t, std::memory_order_release);
+ }
+#endif
}
void FlagImpl::Write(const void* src) {
absl::MutexLock l(DataGuard());
- if (ShouldValidateFlagValue(flags_internal::FastTypeId(op_))) {
+ if (ShouldValidateFlagValue(flags_internal::StaticTypeId(op_))) {
std::unique_ptr<void, DynValueDeleter> obj{flags_internal::Clone(op_, src),
DynValueDeleter{op_}};
std::string ignored_error;
@@ -521,8 +291,8 @@ void FlagImpl::Write(const void* src) {
// * 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) {
+bool FlagImpl::SetFromString(absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, std::string* err) {
absl::MutexLock l(DataGuard());
switch (set_mode) {
@@ -569,7 +339,7 @@ bool FlagImpl::ParseFrom(absl::string_view value, FlagSettingMode set_mode,
}
if (!modified_) {
- // Need to set both default value *and* current, in this case.
+ // Need to set both default value *and* current, in this case
StoreValue(default_value_.dynamic_value);
modified_ = false;
}
@@ -591,7 +361,7 @@ void FlagImpl::CheckDefaultValueParsingRoundtrip() const {
ABSL_INTERNAL_LOG(
FATAL,
absl::StrCat("Flag ", Name(), " (from ", Filename(),
- "): string form of default value '", v,
+ "): std::string form of default value '", v,
"' could not be parsed; error=", error));
}
diff --git a/third_party/abseil-cpp/absl/flags/internal/flag.h b/third_party/abseil-cpp/absl/flags/internal/flag.h
index 124a2f1c03..35a148cf66 100644
--- a/third_party/abseil-cpp/absl/flags/internal/flag.h
+++ b/third_party/abseil-cpp/absl/flags/internal/flag.h
@@ -16,95 +16,94 @@
#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/casts.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/memory/memory.h"
+#include "absl/strings/str_cat.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,
+ kClone,
kCopy,
kCopyConstruct,
kSizeof,
- kFastTypeId,
- kRuntimeTypeId,
+ kStaticTypeId,
kParse,
kUnparse,
- kValueOffset,
};
using FlagOpFn = void* (*)(FlagOp, const void*, void*, void*);
-// Forward declaration for Flag value specific operations.
+// Flag value specific operations routine.
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);
+void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) {
+ switch (op) {
+ case FlagOp::kDelete:
+ delete static_cast<const T*>(v1);
+ return nullptr;
+ case FlagOp::kClone:
+ return new T(*static_cast<const T*>(v1));
+ 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*>(sizeof(T));
+ case FlagOp::kStaticTypeId:
+ return reinterpret_cast<void*>(&FlagStaticTypeIdGen<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;
+ default:
+ return nullptr;
+ }
}
+
// Deletes memory interpreting obj as flag value type pointer.
-inline void Delete(FlagOpFn op, void* obj) {
- op(FlagOp::kDelete, nullptr, obj, nullptr);
+inline void Delete(FlagOpFn op, const void* obj) {
+ op(FlagOp::kDelete, obj, nullptr, nullptr);
+}
+// Makes a copy of flag value pointed by obj.
+inline void* Clone(FlagOpFn op, const void* obj) {
+ return op(FlagOp::kClone, obj, nullptr, nullptr);
}
// Copies src to dst interpreting as flag value type pointers.
inline void Copy(FlagOpFn op, const void* src, void* dst) {
@@ -115,12 +114,6 @@ inline void Copy(FlagOpFn op, const void* src, void* dst) {
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) {
@@ -139,36 +132,41 @@ inline size_t Sizeof(FlagOpFn op) {
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 static type id coresponding to the value type.
+inline FlagStaticTypeId StaticTypeId(FlagOpFn op) {
+ return reinterpret_cast<FlagStaticTypeId>(
+ op(FlagOp::kStaticTypeId, nullptr, nullptr, nullptr));
}
-// Returns an address of RTTI's typeid(T).
+///////////////////////////////////////////////////////////////////////////////
+// Persistent state of the flag data.
+
template <typename T>
-inline const std::type_info* GenRuntimeTypeId() {
-#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI)
- return &typeid(T);
-#else
- return nullptr;
-#endif
-}
+class FlagState : public flags_internal::FlagStateInterface {
+ public:
+ FlagState(Flag<T>* flag, T&& cur, bool modified, bool on_command_line,
+ int64_t counter)
+ : flag_(flag),
+ cur_value_(std::move(cur)),
+ modified_(modified),
+ on_command_line_(on_command_line),
+ counter_(counter) {}
+
+ ~FlagState() override = default;
+
+ private:
+ friend class Flag<T>;
+
+ // Restores the flag to the saved state.
+ void Restore() const override;
+
+ // Flag and saved flag data.
+ Flag<T>* flag_;
+ T cur_value_;
+ bool modified_;
+ bool on_command_line_;
+ int64_t counter_;
+};
///////////////////////////////////////////////////////////////////////////////
// Flag help auxiliary structs.
@@ -178,28 +176,6 @@ inline const std::type_info* GenRuntimeTypeId() {
// 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) {}
@@ -217,28 +193,40 @@ struct FlagHelpArg {
extern const char kStrippedFlagHelp[];
+// HelpConstexprWrap is used by struct AbslFlagHelpGenFor##name generated by
+// ABSL_FLAG macro. It is only used to silence the compiler in the case where
+// help message expression is not constexpr and does not have type const char*.
+// If help message expression is indeed constexpr const char* HelpConstexprWrap
+// is just a trivial identity function.
+template <typename T>
+const char* HelpConstexprWrap(const T&) {
+ return nullptr;
+}
+constexpr const char* HelpConstexprWrap(const char* p) { return p; }
+constexpr const char* HelpConstexprWrap(char* p) { return p; }
+
// 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
+// AbslFlagHelpGenFor##name as T and integer 0 as a single argument to prefer
+// first overload if possible. If T::Const is evaluatable on constexpr
+// context (see non template int parameter below) 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 T, int = (T::Const(), 1)>
+constexpr FlagHelpArg HelpArg(int) {
+ return {FlagHelpMsg(T::Const()), FlagHelpKind::kLiteral};
}
-template <typename Gen>
-constexpr FlagHelpArg HelpArg(std::false_type) {
- return {FlagHelpMsg(&Gen::NonConst), FlagHelpKind::kGenFunc};
+template <typename T>
+constexpr FlagHelpArg HelpArg(char) {
+ return {FlagHelpMsg(&T::NonConst), FlagHelpKind::kGenFunc};
}
///////////////////////////////////////////////////////////////////////////////
@@ -246,159 +234,110 @@ constexpr FlagHelpArg HelpArg(std::false_type) {
// Signature for the function generating the initial flag value (usually
// based on default value supplied in flag's definition)
-using FlagDfltGenFunc = void (*)(void*);
+using FlagDfltGenFunc = 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 =
- ((void)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};
-}
+enum class FlagDefaultKind : uint8_t { kDynamicValue = 0, kGenFunc = 1 };
///////////////////////////////////////////////////////////////////////////////
// Flag current value auxiliary structs.
-constexpr int64_t UninitializedFlagValue() { return 0xababababababababll; }
+// The minimum atomic size we believe to generate lock free code, i.e. all
+// trivially copyable types not bigger this size generate lock free code.
+static constexpr int kMinLockFreeAtomicSize = 8;
-template <typename T>
-using FlagUseValueAndInitBitStorage = std::integral_constant<
- bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
- std::is_default_constructible<T>::value && (sizeof(T) < 8)>;
+// The same as kMinLockFreeAtomicSize but maximum atomic size. As double words
+// might use two registers, we want to dispatch the logic for them.
+#if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD)
+static constexpr int kMaxLockFreeAtomicSize = 16;
+#else
+static constexpr int kMaxLockFreeAtomicSize = 8;
+#endif
+// We can use atomic in cases when it fits in the register, trivially copyable
+// in order to make memcpy operations.
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 FlagUseSequenceLockStorage = std::integral_constant<
- bool, absl::type_traits_internal::is_trivially_copyable<T>::value &&
- (sizeof(T) > 8)>;
-
-enum class FlagValueStorageKind : uint8_t {
- kValueAndInitBit = 0,
- kOneWordAtomic = 1,
- kSequenceLocked = 2,
- kAlignedBuffer = 3,
+struct IsAtomicFlagTypeTrait {
+ static constexpr bool value =
+ (sizeof(T) <= kMaxLockFreeAtomicSize &&
+ type_traits_internal::is_trivially_copyable<T>::value);
};
-template <typename T>
-static constexpr FlagValueStorageKind StorageKind() {
- return FlagUseValueAndInitBitStorage<T>::value
- ? FlagValueStorageKind::kValueAndInitBit
- : FlagUseOneWordStorage<T>::value
- ? FlagValueStorageKind::kOneWordAtomic
- : FlagUseSequenceLockStorage<T>::value
- ? FlagValueStorageKind::kSequenceLocked
- : FlagValueStorageKind::kAlignedBuffer;
-}
-
-struct FlagOneWordValue {
- constexpr explicit FlagOneWordValue(int64_t v) : value(v) {}
- std::atomic<int64_t> value;
+// Clang does not always produce cmpxchg16b instruction when alignment of a 16
+// bytes type is not 16.
+struct alignas(16) FlagsInternalTwoWordsType {
+ int64_t first;
+ int64_t second;
};
-template <typename T>
-struct alignas(8) FlagValueAndInitBit {
- T value;
- // Use an int instead of a bool to guarantee that a non-zero value has
- // a bit set.
- uint8_t init;
-};
+constexpr bool operator==(const FlagsInternalTwoWordsType& that,
+ const FlagsInternalTwoWordsType& other) {
+ return that.first == other.first && that.second == other.second;
+}
+constexpr bool operator!=(const FlagsInternalTwoWordsType& that,
+ const FlagsInternalTwoWordsType& other) {
+ return !(that == other);
+}
-template <typename T,
- FlagValueStorageKind Kind = flags_internal::StorageKind<T>()>
-struct FlagValue;
+constexpr int64_t SmallAtomicInit() { return 0xababababababababll; }
-template <typename T>
-struct FlagValue<T, FlagValueStorageKind::kValueAndInitBit> : FlagOneWordValue {
- constexpr FlagValue() : FlagOneWordValue(0) {}
- bool Get(const SequenceLock&, T& dst) const {
- int64_t storage = value.load(std::memory_order_acquire);
- if (ABSL_PREDICT_FALSE(storage == 0)) {
- return false;
- }
- dst = absl::bit_cast<FlagValueAndInitBit<T>>(storage).value;
- return true;
- }
-};
-
-template <typename T>
-struct FlagValue<T, FlagValueStorageKind::kOneWordAtomic> : FlagOneWordValue {
- constexpr FlagValue() : FlagOneWordValue(UninitializedFlagValue()) {}
- 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, typename S = void>
+struct BestAtomicType {
+ using type = int64_t;
+ static constexpr int64_t AtomicInit() { return SmallAtomicInit(); }
};
template <typename T>
-struct FlagValue<T, FlagValueStorageKind::kSequenceLocked> {
- bool Get(const SequenceLock& lock, T& dst) const {
- return lock.TryRead(&dst, value_words, sizeof(T));
+struct BestAtomicType<
+ T, typename std::enable_if<(kMinLockFreeAtomicSize < sizeof(T) &&
+ sizeof(T) <= kMaxLockFreeAtomicSize),
+ void>::type> {
+ using type = FlagsInternalTwoWordsType;
+ static constexpr FlagsInternalTwoWordsType AtomicInit() {
+ return {SmallAtomicInit(), SmallAtomicInit()};
}
-
- 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];
};
-template <typename T>
-struct FlagValue<T, FlagValueStorageKind::kAlignedBuffer> {
- bool Get(const SequenceLock&, T&) const { return false; }
+struct FlagValue {
+ // Heap allocated value.
+ void* dynamic = nullptr;
+ // For some types, a copy of the current value is kept in an atomically
+ // accessible field.
+ union Atomics {
+ // Using small atomic for small types.
+ std::atomic<int64_t> small_atomic;
+ template <typename T,
+ typename K = typename std::enable_if<
+ (sizeof(T) <= kMinLockFreeAtomicSize), void>::type>
+ int64_t load() const {
+ return small_atomic.load(std::memory_order_acquire);
+ }
- alignas(T) char value[sizeof(T)];
+#if defined(ABSL_FLAGS_INTERNAL_ATOMIC_DOUBLE_WORD)
+ // Using big atomics for big types.
+ std::atomic<FlagsInternalTwoWordsType> big_atomic;
+ template <typename T, typename K = typename std::enable_if<
+ (kMinLockFreeAtomicSize < sizeof(T) &&
+ sizeof(T) <= kMaxLockFreeAtomicSize),
+ void>::type>
+ FlagsInternalTwoWordsType load() const {
+ return big_atomic.load(std::memory_order_acquire);
+ }
+ constexpr Atomics()
+ : big_atomic{FlagsInternalTwoWordsType{SmallAtomicInit(),
+ SmallAtomicInit()}} {}
+#else
+ constexpr Atomics() : small_atomic{SmallAtomicInit()} {}
+#endif
+ };
+ Atomics atomics{};
};
///////////////////////////////////////////////////////////////////////////////
@@ -419,161 +358,134 @@ struct FlagCallback {
// The class encapsulates the Flag's data and access to it.
struct DynValueDeleter {
- explicit DynValueDeleter(FlagOpFn op_arg = nullptr);
- void operator()(void* ptr) const;
+ explicit DynValueDeleter(FlagOpFn op_arg = nullptr) : op(op_arg) {}
+ void operator()(void* ptr) const {
+ if (op != nullptr) Delete(op, ptr);
+ }
FlagOpFn op;
};
-class FlagState;
-
-class FlagImpl final : public CommandLineFlag {
+class FlagImpl {
public:
constexpr FlagImpl(const char* name, const char* filename, FlagOpFn op,
- FlagHelpArg help, FlagValueStorageKind value_kind,
- FlagDefaultArg default_arg)
+ FlagHelpArg help, FlagDfltGenFunc default_value_gen)
: 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)),
+ def_kind_(static_cast<uint8_t>(FlagDefaultKind::kGenFunc)),
modified_(false),
on_command_line_(false),
+ counter_(0),
callback_(nullptr),
- default_value_(default_arg.source),
+ default_value_(default_value_gen),
data_guard_{} {}
// Constant access methods
- int64_t ReadOneWord() const ABSL_LOCKS_EXCLUDED(*DataGuard());
- bool ReadOneBool() const ABSL_LOCKS_EXCLUDED(*DataGuard());
- void Read(void* dst) const override ABSL_LOCKS_EXCLUDED(*DataGuard());
- void Read(bool* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
- *value = ReadOneBool();
+ absl::string_view Name() const;
+ std::string Filename() const;
+ std::string Help() const;
+ bool IsModified() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool IsSpecifiedOnCommandLine() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+ std::string DefaultValue() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+ std::string CurrentValue() const ABSL_LOCKS_EXCLUDED(*DataGuard());
+ void Read(void* dst) const ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ template <typename T, typename std::enable_if<
+ !IsAtomicFlagTypeTrait<T>::value, int>::type = 0>
+ void Get(T* dst) const {
+ AssertValidType(&flags_internal::FlagStaticTypeIdGen<T>);
+ Read(dst);
}
- template <typename T,
- absl::enable_if_t<flags_internal::StorageKind<T>() ==
- FlagValueStorageKind::kOneWordAtomic,
- int> = 0>
- void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
- int64_t v = ReadOneWord();
- std::memcpy(value, static_cast<const void*>(&v), sizeof(T));
+ // Overload for `GetFlag()` for types that support lock-free reads.
+ template <typename T, typename std::enable_if<IsAtomicFlagTypeTrait<T>::value,
+ int>::type = 0>
+ void Get(T* dst) const {
+ // For flags of types which can be accessed "atomically" we want to avoid
+ // slowing down flag value access due to type validation. That's why
+ // this validation is hidden behind !NDEBUG
+#ifndef NDEBUG
+ AssertValidType(&flags_internal::FlagStaticTypeIdGen<T>);
+#endif
+ using U = flags_internal::BestAtomicType<T>;
+ typename U::type r = value_.atomics.template load<T>();
+ if (r != U::AtomicInit()) {
+ std::memcpy(static_cast<void*>(dst), &r, sizeof(T));
+ } else {
+ Read(dst);
+ }
}
- template <typename T,
- typename std::enable_if<flags_internal::StorageKind<T>() ==
- FlagValueStorageKind::kValueAndInitBit,
- int>::type = 0>
- void Read(T* value) const ABSL_LOCKS_EXCLUDED(*DataGuard()) {
- *value = absl::bit_cast<FlagValueAndInitBit<T>>(ReadOneWord()).value;
+ template <typename T>
+ void Set(const T& src) {
+ AssertValidType(&flags_internal::FlagStaticTypeIdGen<T>);
+ Write(&src);
}
// Mutating access methods
void Write(const void* src) ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool SetFromString(absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, std::string* err)
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+ // If possible, updates copy of the Flag's value that is stored in an
+ // atomic word.
+ void StoreAtomic() ABSL_EXCLUSIVE_LOCKS_REQUIRED(*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:
+ // Interfaces to save/restore mutable flag data
template <typename T>
- friend class Flag;
- friend class FlagState;
+ std::unique_ptr<FlagStateInterface> SaveState(Flag<T>* flag) const
+ ABSL_LOCKS_EXCLUDED(*DataGuard()) {
+ T&& cur_value = flag->Get();
+ absl::MutexLock l(DataGuard());
+
+ return absl::make_unique<FlagState<T>>(
+ flag, std::move(cur_value), modified_, on_command_line_, counter_);
+ }
+ bool RestoreState(const void* value, bool modified, bool on_command_line,
+ int64_t counter) ABSL_LOCKS_EXCLUDED(*DataGuard());
+ // Value validation interfaces.
+ void CheckDefaultValueParsingRoundtrip() const
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+ bool ValidateInputValue(absl::string_view value) const
+ ABSL_LOCKS_EXCLUDED(*DataGuard());
+
+ private:
// Ensures that `data_guard_` is initialized and returns it.
- absl::Mutex* DataGuard() const
- ABSL_LOCK_RETURNED(reinterpret_cast<absl::Mutex*>(data_guard_));
+ absl::Mutex* DataGuard() const ABSL_LOCK_RETURNED((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,
+ // Attempts to parse supplied `value` std::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
+ 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());
+ // 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 `op`, which is in turn is validated against the type id
+ // stored in flag object by flag definition statement.
+ void AssertValidType(FlagStaticTypeId type_id) const;
// Immutable flag's state.
@@ -587,35 +499,40 @@ class FlagImpl final : public CommandLineFlag {
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.
+ // ------------------------------------------------------------------------
+ // The bytes containing the const bitfields must not be shared with bytes
+ // containing the mutable bitfields.
+ // ------------------------------------------------------------------------
+
+ // Unique tag for absl::call_once call to initialize this flag.
+ //
+ // The placement of this variable between the immutable and mutable bitfields
+ // is important as prevents them from occupying the same byte. If you remove
+ // this variable, make sure to maintain this property.
+ absl::once_flag init_control_;
// 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;
+ // If def_kind_ == kDynamicValue, default_value_ holds a dynamically allocated
+ // value.
+ uint8_t def_kind_ : 1 ABSL_GUARDED_BY(*DataGuard());
// 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_;
-
+ // Mutation counter
+ int64_t counter_ ABSL_GUARDED_BY(*DataGuard());
// 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_;
+ FlagDefaultSrc default_value_ ABSL_GUARDED_BY(*DataGuard());
+ // Current Flag Value
+ FlagValue value_;
// This is reserved space for an absl::Mutex to guard flag data. It will be
// initialized in FlagImpl::Init via placement new.
@@ -632,29 +549,11 @@ class FlagImpl final : public CommandLineFlag {
// flag reflection handle interface.
template <typename T>
-class Flag {
+class Flag final : public flags_internal::CommandLineFlag {
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;
+ constexpr Flag(const char* name, const char* filename, const FlagHelpArg help,
+ const FlagDfltGenFunc default_value_gen)
+ : impl_(name, filename, &FlagOps<T>, help, default_value_gen) {}
T Get() const {
// See implementation notes in CommandLineFlag::Get().
@@ -665,132 +564,106 @@ class Flag {
};
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);
- }
+ impl_.Get(&u.value);
return std::move(u.value);
}
- void Set(const T& v) {
- impl_.AssertValidType(base_internal::FastTypeId<T>(), &GenRuntimeTypeId<T>);
- impl_.Write(&v);
+ void Set(const T& v) { impl_.Set(v); }
+ void SetCallback(const FlagCallbackFunc mutation_callback) {
+ impl_.SetCallback(mutation_callback);
}
- // 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_;
-};
+ // CommandLineFlag interface
+ absl::string_view Name() const override { return impl_.Name(); }
+ std::string Filename() const override { return impl_.Filename(); }
+ absl::string_view Typename() const override { return ""; }
+ std::string Help() const override { return impl_.Help(); }
+ bool IsModified() const override { return impl_.IsModified(); }
+ bool IsSpecifiedOnCommandLine() const override {
+ return impl_.IsSpecifiedOnCommandLine();
+ }
+ std::string DefaultValue() const override { return impl_.DefaultValue(); }
+ std::string CurrentValue() const override { return impl_.CurrentValue(); }
+ bool ValidateInputValue(absl::string_view value) const override {
+ return impl_.ValidateInputValue(value);
+ }
-///////////////////////////////////////////////////////////////////////////////
-// Trampoline for friend access
+ // 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 {
+ return impl_.SaveState(this);
+ }
-class FlagImplPeer {
- public:
- template <typename T, typename FlagType>
- static T InvokeGet(const FlagType& flag) {
- return flag.Get();
+ // Restores the flag state to the supplied state object. If there is
+ // nothing to restore returns false. Otherwise returns true.
+ bool RestoreState(const FlagState<T>& flag_state) {
+ return impl_.RestoreState(&flag_state.cur_value_, flag_state.modified_,
+ flag_state.on_command_line_, flag_state.counter_);
}
- template <typename FlagType, typename T>
- static void InvokeSet(FlagType& flag, const T& v) {
- flag.Set(v);
+ bool SetFromString(absl::string_view value, FlagSettingMode set_mode,
+ ValueSource source, std::string* error) override {
+ return impl_.SetFromString(value, set_mode, source, error);
}
- template <typename FlagType>
- static const CommandLineFlag& InvokeReflect(const FlagType& f) {
- return f.Reflect();
+ void CheckDefaultValueParsingRoundtrip() const override {
+ impl_.CheckDefaultValueParsingRoundtrip();
}
+
+ private:
+ friend class FlagState<T>;
+
+ void Read(void* dst) const override { impl_.Read(dst); }
+ FlagStaticTypeId TypeId() const override { return &FlagStaticTypeIdGen<T>; }
+
+ // Flag's data
+ FlagImpl impl_;
};
-///////////////////////////////////////////////////////////////////////////////
-// 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);
- }
+inline void FlagState<T>::Restore() const {
+ if (flag_->RestoreState(*this)) {
+ ABSL_INTERNAL_LOG(INFO,
+ absl::StrCat("Restore saved value of ", flag_->Name(),
+ " to: ", flag_->CurrentValue()));
}
- 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);
+ explicit FlagRegistrar(Flag<T>* flag) : flag_(flag) {
+ if (do_register) flags_internal::RegisterCommandLineFlag(flag_);
}
- FlagRegistrar OnUpdate(FlagCallbackFunc cb) && {
- flag_.impl_.SetCallback(cb);
+ FlagRegistrar& OnUpdate(FlagCallbackFunc cb) && {
+ flag_->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
+ // Make the registrar "die" gracefully as a bool on a line where registration
+ // happens. Registrar objects are intended to live only as temporary.
+ operator bool() const { return true; } // NOLINT
private:
- Flag<T>& flag_; // Flag being registered (not owned).
+ Flag<T>* flag_; // Flag being registered (not owned).
};
+// This struct and corresponding overload to MakeDefaultValue are used to
+// facilitate usage of {} as default value in ABSL_FLAG macro.
+struct EmptyBraces {};
+
+template <typename T>
+T* MakeFromDefaultValue(T t) {
+ return new T(std::move(t));
+}
+
+template <typename T>
+T* MakeFromDefaultValue(EmptyBraces) {
+ return new T;
+}
+
} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/flags/internal/flag_msvc.inc b/third_party/abseil-cpp/absl/flags/internal/flag_msvc.inc
deleted file mode 100644
index c31bd27fd8..0000000000
--- a/third_party/abseil-cpp/absl/flags/internal/flag_msvc.inc
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// 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.
-
-// Do not include this file directly.
-// Include absl/flags/flag.h instead.
-
-// 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
-
-// Public methods of `absl::Flag<T>` are NOT part of the Abseil Flags API.
-// See https://abseil.io/docs/cpp/guides/flags
-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_;
-};
diff --git a/third_party/abseil-cpp/absl/flags/internal/parse.h b/third_party/abseil-cpp/absl/flags/internal/parse.h
index de706c8984..03e8a07bf3 100644
--- a/third_party/abseil-cpp/absl/flags/internal/parse.h
+++ b/third_party/abseil-cpp/absl/flags/internal/parse.h
@@ -21,7 +21,6 @@
#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);
@@ -45,13 +44,6 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
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
diff --git a/third_party/abseil-cpp/absl/flags/internal/path_util.h b/third_party/abseil-cpp/absl/flags/internal/path_util.h
index a6594d3347..365c830522 100644
--- a/third_party/abseil-cpp/absl/flags/internal/path_util.h
+++ b/third_party/abseil-cpp/absl/flags/internal/path_util.h
@@ -17,6 +17,7 @@
#define ABSL_FLAGS_INTERNAL_PATH_UTIL_H_
#include "absl/base/config.h"
+#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
namespace absl {
diff --git a/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.cc b/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.cc
deleted file mode 100644
index a7eb58b6d4..0000000000
--- a/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.h b/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.h
deleted file mode 100644
index c64435cd61..0000000000
--- a/third_party/abseil-cpp/absl/flags/internal/private_handle_accessor.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/internal/program_name_test.cc b/third_party/abseil-cpp/absl/flags/internal/program_name_test.cc
index aff9f6315e..269142f225 100644
--- a/third_party/abseil-cpp/absl/flags/internal/program_name_test.cc
+++ b/third_party/abseil-cpp/absl/flags/internal/program_name_test.cc
@@ -25,7 +25,7 @@ namespace {
namespace flags = absl::flags_internal;
-TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
+TEST(FlagsPathUtilTest, TestInitialProgamName) {
flags::SetProgramInvocationName("absl/flags/program_name_test");
std::string program_name = flags::ProgramInvocationName();
for (char& c : program_name)
@@ -43,7 +43,9 @@ TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
EXPECT_TRUE(absl::EndsWith(program_name, expect_name)) << program_name;
EXPECT_EQ(flags::ShortProgramInvocationName(), expect_basename);
+}
+TEST(FlagsPathUtilTest, TestProgamNameInterfaces) {
flags::SetProgramInvocationName("a/my_test");
EXPECT_EQ(flags::ProgramInvocationName(), "a/my_test");
diff --git a/third_party/abseil-cpp/absl/flags/internal/registry.cc b/third_party/abseil-cpp/absl/flags/internal/registry.cc
new file mode 100644
index 0000000000..e434a85912
--- /dev/null
+++ b/third_party/abseil-cpp/absl/flags/internal/registry.cc
@@ -0,0 +1,351 @@
+//
+// 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/registry.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/base/thread_annotations.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+
+// --------------------------------------------------------------------
+// FlagRegistry implementation
+// A FlagRegistry holds all flag objects indexed
+// by their names so that if you know a flag's name you can access or
+// set it.
+
+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 (as a C
+// string), 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);
+
+ 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* FindFlagLocked(absl::string_view name);
+
+ // Returns the retired flag object for the specified name, or nullptr if not
+ // found or not retired. Does not emit a warning.
+ CommandLineFlag* FindRetiredFlagLocked(absl::string_view name);
+
+ static FlagRegistry* GlobalRegistry(); // returns a singleton registry
+
+ private:
+ friend class FlagSaverImpl; // reads all the flags in order to copy them
+ friend void ForEachFlagUnlocked(
+ std::function<void(CommandLineFlag*)> visitor);
+
+ // The map from name to flag, for FindFlagLocked().
+ using FlagMap = std::map<absl::string_view, CommandLineFlag*>;
+ using FlagIterator = FlagMap::iterator;
+ using FlagConstIterator = FlagMap::const_iterator;
+ FlagMap flags_;
+
+ absl::Mutex lock_;
+
+ // Disallow
+ FlagRegistry(const FlagRegistry&);
+ FlagRegistry& operator=(const FlagRegistry&);
+};
+
+FlagRegistry* FlagRegistry::GlobalRegistry() {
+ static FlagRegistry* global_registry = new FlagRegistry;
+ return global_registry;
+}
+
+namespace {
+
+class FlagRegistryLock {
+ public:
+ explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
+ ~FlagRegistryLock() { fr_->Unlock(); }
+
+ private:
+ FlagRegistry* const fr_;
+};
+
+void DestroyRetiredFlag(CommandLineFlag* flag);
+} // namespace
+
+void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
+ 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 (flag->TypeId() != old_flag->TypeId()) {
+ 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(),
+ "' with types '", old_flag->Typename(), "' and '",
+ flag->Typename(), "', respectively."),
+ true);
+ } else if (old_flag->IsRetired()) {
+ // Retired flag can just be deleted.
+ DestroyRetiredFlag(flag);
+ 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 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);
+ }
+}
+
+CommandLineFlag* FlagRegistry::FindFlagLocked(absl::string_view name) {
+ FlagConstIterator i = flags_.find(name);
+ if (i == flags_.end()) {
+ return nullptr;
+ }
+
+ if (i->second->IsRetired()) {
+ flags_internal::ReportUsageError(
+ absl::StrCat("Accessing retired flag '", name, "'"), false);
+ }
+
+ return i->second;
+}
+
+CommandLineFlag* FlagRegistry::FindRetiredFlagLocked(absl::string_view name) {
+ FlagConstIterator i = flags_.find(name);
+ if (i == flags_.end() || !i->second->IsRetired()) {
+ return nullptr;
+ }
+
+ return i->second;
+}
+
+// --------------------------------------------------------------------
+// FlagSaver
+// FlagSaverImpl
+// This class stores the states of all flags at construct time,
+// and restores all flags to that state at destruct time.
+// Its major implementation challenge is that it never modifies
+// pointers in the 'main' registry, so global FLAG_* vars always
+// point to the right place.
+// --------------------------------------------------------------------
+
+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([&](flags_internal::CommandLineFlag* flag) {
+ if (auto flag_state = flag->SaveState()) {
+ 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_;
+};
+
+FlagSaver::FlagSaver() : impl_(new FlagSaverImpl) { impl_->SaveFromRegistry(); }
+
+void FlagSaver::Ignore() {
+ delete impl_;
+ impl_ = nullptr;
+}
+
+FlagSaver::~FlagSaver() {
+ if (!impl_) return;
+
+ impl_->RestoreToRegistry();
+ delete impl_;
+}
+
+// --------------------------------------------------------------------
+
+CommandLineFlag* FindCommandLineFlag(absl::string_view name) {
+ if (name.empty()) return nullptr;
+ FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ FlagRegistryLock frl(registry);
+
+ return registry->FindFlagLocked(name);
+}
+
+CommandLineFlag* FindRetiredFlag(absl::string_view name) {
+ FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ FlagRegistryLock frl(registry);
+
+ return registry->FindRetiredFlagLocked(name);
+}
+
+// --------------------------------------------------------------------
+
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor) {
+ FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ for (FlagRegistry::FlagConstIterator i = registry->flags_.begin();
+ i != registry->flags_.end(); ++i) {
+ visitor(i->second);
+ }
+}
+
+void ForEachFlag(std::function<void(CommandLineFlag*)> visitor) {
+ FlagRegistry* const registry = FlagRegistry::GlobalRegistry();
+ FlagRegistryLock frl(registry);
+ ForEachFlagUnlocked(visitor);
+}
+
+// --------------------------------------------------------------------
+
+bool RegisterCommandLineFlag(CommandLineFlag* flag) {
+ FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+ return true;
+}
+
+// --------------------------------------------------------------------
+
+namespace {
+
+class RetiredFlagObj final : public flags_internal::CommandLineFlag {
+ public:
+ constexpr RetiredFlagObj(const char* name, FlagStaticTypeId type_id)
+ : name_(name), type_id_(type_id) {}
+
+ private:
+ absl::string_view Name() const override { return name_; }
+ std::string Filename() const override { return "RETIRED"; }
+ absl::string_view Typename() const override { return ""; }
+ FlagStaticTypeId TypeId() const override { return type_id_; }
+ std::string Help() const override { return ""; }
+ bool IsRetired() const override { return true; }
+ bool IsModified() const override { return false; }
+ bool IsSpecifiedOnCommandLine() const override { return false; }
+ std::string DefaultValue() const override { return ""; }
+ std::string CurrentValue() const override { return ""; }
+
+ // Any input is valid
+ bool ValidateInputValue(absl::string_view) const override { return true; }
+
+ std::unique_ptr<flags_internal::FlagStateInterface> SaveState() override {
+ return nullptr;
+ }
+
+ bool SetFromString(absl::string_view, flags_internal::FlagSettingMode,
+ flags_internal::ValueSource, std::string*) override {
+ return false;
+ }
+
+ void CheckDefaultValueParsingRoundtrip() const override {}
+
+ void Read(void*) const override {}
+
+ // Data members
+ const char* const name_;
+ const FlagStaticTypeId type_id_;
+};
+
+void DestroyRetiredFlag(flags_internal::CommandLineFlag* flag) {
+ assert(flag->IsRetired());
+ delete static_cast<RetiredFlagObj*>(flag);
+}
+
+} // namespace
+
+bool Retire(const char* name, FlagStaticTypeId type_id) {
+ auto* flag = new flags_internal::RetiredFlagObj(name, type_id);
+ FlagRegistry::GlobalRegistry()->RegisterFlag(flag);
+ return true;
+}
+
+// --------------------------------------------------------------------
+
+bool IsRetiredFlag(absl::string_view name, bool* type_is_bool) {
+ assert(!name.empty());
+ CommandLineFlag* flag = flags_internal::FindRetiredFlag(name);
+ if (flag == nullptr) {
+ return false;
+ }
+ assert(type_is_bool);
+ *type_is_bool = flag->IsOfType<bool>();
+ return true;
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/third_party/abseil-cpp/absl/flags/internal/registry.h b/third_party/abseil-cpp/absl/flags/internal/registry.h
index 4b68c85f5c..69ff889fb1 100644
--- a/third_party/abseil-cpp/absl/flags/internal/registry.h
+++ b/third_party/abseil-cpp/absl/flags/internal/registry.h
@@ -17,9 +17,11 @@
#define ABSL_FLAGS_INTERNAL_REGISTRY_H_
#include <functional>
+#include <map>
+#include <string>
#include "absl/base/config.h"
-#include "absl/flags/commandlineflag.h"
+#include "absl/base/macros.h"
#include "absl/flags/internal/commandlineflag.h"
#include "absl/strings/string_view.h"
@@ -30,15 +32,19 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace flags_internal {
+CommandLineFlag* FindCommandLineFlag(absl::string_view name);
+CommandLineFlag* FindRetiredFlag(absl::string_view name);
+
+// Executes specified visitor for each non-retired flag in the registry.
+// Requires the caller hold the registry lock.
+void ForEachFlagUnlocked(std::function<void(CommandLineFlag*)> visitor);
// 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);
+void ForEachFlag(std::function<void(CommandLineFlag*)> visitor);
//-----------------------------------------------------------------------------
-bool RegisterCommandLineFlag(CommandLineFlag&, const char* filename);
-
-void FinalizeRegistry();
+bool RegisterCommandLineFlag(CommandLineFlag*);
//-----------------------------------------------------------------------------
// Retired registrations:
@@ -73,21 +79,42 @@ void FinalizeRegistry();
//
// 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*);
+bool Retire(const char* name, FlagStaticTypeId type_id);
// Registered a retired flag with name 'flag_name' and type 'T'.
template <typename T>
-class RetiredFlag {
+inline bool RetiredFlag(const char* flag_name) {
+ return flags_internal::Retire(flag_name, &FlagStaticTypeIdGen<T>);
+}
+
+// If the flag is retired, returns true and indicates in |*type_is_bool|
+// whether the type of the retired flag is a bool.
+// Only to be called by code that needs to explicitly ignore retired flags.
+bool IsRetiredFlag(absl::string_view name, bool* type_is_bool);
+
+//-----------------------------------------------------------------------------
+// Saves the states (value, default value, whether the user has set
+// the flag, registered validators, etc) of all flags, and restores
+// them when the FlagSaver is destroyed.
+//
+// This class is thread-safe. However, its destructor writes to
+// exactly the set of flags that have changed value during its
+// lifetime, so concurrent _direct_ access to those flags
+// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
+
+class FlagSaver {
public:
- void Retire(const char* flag_name) {
- flags_internal::Retire(flag_name, base_internal::FastTypeId<T>(), buf_);
- }
+ FlagSaver();
+ ~FlagSaver();
+
+ FlagSaver(const FlagSaver&) = delete;
+ void operator=(const FlagSaver&) = delete;
+
+ // Prevents saver from restoring the saved state of flags.
+ void Ignore();
private:
- alignas(kRetiredFlagObjAlignment) char buf_[kRetiredFlagObjSize];
+ class FlagSaverImpl* impl_; // we use pimpl here to keep API steady
};
} // namespace flags_internal
diff --git a/third_party/abseil-cpp/absl/flags/internal/sequence_lock.h b/third_party/abseil-cpp/absl/flags/internal/sequence_lock.h
deleted file mode 100644
index 36318ab9d3..0000000000
--- a/third_party/abseil-cpp/absl/flags/internal/sequence_lock.h
+++ /dev/null
@@ -1,187 +0,0 @@
-//
-// 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<uint64>`. 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/third_party/abseil-cpp/absl/flags/internal/sequence_lock_test.cc b/third_party/abseil-cpp/absl/flags/internal/sequence_lock_test.cc
deleted file mode 100644
index c3ec372ed8..0000000000
--- a/third_party/abseil-cpp/absl/flags/internal/sequence_lock_test.cc
+++ /dev/null
@@ -1,169 +0,0 @@
-// 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/third_party/abseil-cpp/absl/flags/internal/type_erased.cc b/third_party/abseil-cpp/absl/flags/internal/type_erased.cc
new file mode 100644
index 0000000000..490bc4ebae
--- /dev/null
+++ b/third_party/abseil-cpp/absl/flags/internal/type_erased.cc
@@ -0,0 +1,90 @@
+//
+// 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/type_erased.h"
+
+#include <assert.h>
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/base/internal/raw_logging.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/usage_config.h"
+#include "absl/strings/string_view.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+bool GetCommandLineOption(absl::string_view name, std::string* value) {
+ if (name.empty()) return false;
+ assert(value);
+
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+ if (flag == nullptr || flag->IsRetired()) {
+ return false;
+ }
+
+ *value = flag->CurrentValue();
+ return true;
+}
+
+bool SetCommandLineOption(absl::string_view name, absl::string_view value) {
+ return SetCommandLineOptionWithMode(name, value,
+ flags_internal::SET_FLAGS_VALUE);
+}
+
+bool SetCommandLineOptionWithMode(absl::string_view name,
+ absl::string_view value,
+ FlagSettingMode set_mode) {
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+
+ if (!flag || flag->IsRetired()) return false;
+
+ std::string error;
+ if (!flag->SetFromString(value, set_mode, kProgrammaticChange, &error)) {
+ // Errors here are all of the form: the provided name was a recognized
+ // flag, but the value was invalid (bad type, or validation failed).
+ flags_internal::ReportUsageError(error, false);
+ return false;
+ }
+
+ return true;
+}
+
+// --------------------------------------------------------------------
+
+bool IsValidFlagValue(absl::string_view name, absl::string_view value) {
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+
+ return flag != nullptr &&
+ (flag->IsRetired() || flag->ValidateInputValue(value));
+}
+
+// --------------------------------------------------------------------
+
+bool SpecifiedOnCommandLine(absl::string_view name) {
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+ if (flag != nullptr && !flag->IsRetired()) {
+ return flag->IsSpecifiedOnCommandLine();
+ }
+ return false;
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/third_party/abseil-cpp/absl/flags/internal/type_erased.h b/third_party/abseil-cpp/absl/flags/internal/type_erased.h
new file mode 100644
index 0000000000..188429c771
--- /dev/null
+++ b/third_party/abseil-cpp/absl/flags/internal/type_erased.h
@@ -0,0 +1,90 @@
+//
+// 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_TYPE_ERASED_H_
+#define ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
+
+#include <string>
+
+#include "absl/base/config.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/strings/string_view.h"
+
+// --------------------------------------------------------------------
+// Registry interfaces operating on type erased handles.
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace flags_internal {
+
+// If a flag named "name" exists, store its current value in *OUTPUT
+// and return true. Else return false without changing *OUTPUT.
+// Thread-safe.
+bool GetCommandLineOption(absl::string_view name, std::string* value);
+
+// Set the value of the flag named "name" to value. If successful,
+// returns true. If not successful (e.g., the flag was not found or
+// the value is not a valid value), returns false.
+// Thread-safe.
+bool SetCommandLineOption(absl::string_view name, absl::string_view value);
+
+bool SetCommandLineOptionWithMode(absl::string_view name,
+ absl::string_view value,
+ FlagSettingMode set_mode);
+
+//-----------------------------------------------------------------------------
+
+// Returns true iff all of the following conditions are true:
+// (a) "name" names a registered flag
+// (b) "value" can be parsed succesfully according to the type of the flag
+// (c) parsed value passes any validator associated with the flag
+bool IsValidFlagValue(absl::string_view name, absl::string_view value);
+
+//-----------------------------------------------------------------------------
+
+// Returns true iff a flag named "name" was specified on the command line
+// (either directly, or via one of --flagfile or --fromenv or --tryfromenv).
+//
+// Any non-command-line modification of the flag does not affect the
+// result of this function. So for example, if a flag was passed on
+// the command line but then reset via SET_FLAGS_DEFAULT, this
+// function will still return true.
+bool SpecifiedOnCommandLine(absl::string_view name);
+
+//-----------------------------------------------------------------------------
+
+// If a flag with specified "name" exists and has type T, store
+// its current value in *dst and return true. Else return false
+// without touching *dst. T must obey all of the requirements for
+// types passed to DEFINE_FLAG.
+template <typename T>
+inline bool GetByName(absl::string_view name, T* dst) {
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(name);
+ if (!flag) return false;
+
+ if (auto val = flag->Get<T>()) {
+ *dst = *val;
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace flags_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_FLAGS_INTERNAL_TYPE_ERASED_H_
diff --git a/third_party/abseil-cpp/absl/flags/internal/type_erased_test.cc b/third_party/abseil-cpp/absl/flags/internal/type_erased_test.cc
new file mode 100644
index 0000000000..4ce5981047
--- /dev/null
+++ b/third_party/abseil-cpp/absl/flags/internal/type_erased_test.cc
@@ -0,0 +1,157 @@
+//
+// 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/type_erased.h"
+
+#include <memory>
+#include <string>
+
+#include "gtest/gtest.h"
+#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.h"
+#include "absl/flags/internal/registry.h"
+#include "absl/flags/marshalling.h"
+#include "absl/memory/memory.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 {
+
+namespace flags = absl::flags_internal;
+
+class TypeErasedTest : public testing::Test {
+ protected:
+ void SetUp() override { flag_saver_ = absl::make_unique<flags::FlagSaver>(); }
+ void TearDown() override { flag_saver_.reset(); }
+
+ private:
+ std::unique_ptr<flags::FlagSaver> flag_saver_;
+};
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestGetCommandLineOption) {
+ std::string value;
+ EXPECT_TRUE(flags::GetCommandLineOption("int_flag", &value));
+ EXPECT_EQ(value, "1");
+
+ EXPECT_TRUE(flags::GetCommandLineOption("string_flag", &value));
+ EXPECT_EQ(value, "dflt");
+
+ EXPECT_FALSE(flags::GetCommandLineOption("bool_retired_flag", &value));
+
+ EXPECT_FALSE(flags::GetCommandLineOption("unknown_flag", &value));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOption) {
+ EXPECT_TRUE(flags::SetCommandLineOption("int_flag", "101"));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+ EXPECT_TRUE(flags::SetCommandLineOption("string_flag", "asdfgh"));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+ EXPECT_FALSE(flags::SetCommandLineOption("bool_retired_flag", "true"));
+
+ EXPECT_FALSE(flags::SetCommandLineOption("unknown_flag", "true"));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_VALUE) {
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+ flags::SET_FLAGS_VALUE));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+ flags::SET_FLAGS_VALUE));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+ flags::SET_FLAGS_VALUE));
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+ flags::SET_FLAGS_VALUE));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAG_IF_DEFAULT) {
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+ flags::SET_FLAG_IF_DEFAULT));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+ // This semantic is broken. We return true instead of false. Value is not
+ // updated.
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
+ flags::SET_FLAG_IF_DEFAULT));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 101);
+
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+ flags::SET_FLAG_IF_DEFAULT));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+ flags::SET_FLAG_IF_DEFAULT));
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+ flags::SET_FLAG_IF_DEFAULT));
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestSetCommandLineOptionWithMode_SET_FLAGS_DEFAULT) {
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "101",
+ flags::SET_FLAGS_DEFAULT));
+
+ // Set it again to ensure that resetting logic is covered.
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "102",
+ flags::SET_FLAGS_DEFAULT));
+
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "103",
+ flags::SET_FLAGS_DEFAULT));
+
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("string_flag", "asdfgh",
+ flags::SET_FLAGS_DEFAULT));
+ EXPECT_EQ(absl::GetFlag(FLAGS_string_flag), "asdfgh");
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("bool_retired_flag", "true",
+ flags::SET_FLAGS_DEFAULT));
+
+ EXPECT_FALSE(flags::SetCommandLineOptionWithMode("unknown_flag", "true",
+ flags::SET_FLAGS_DEFAULT));
+
+ // This should be successfull, since flag is still is not set
+ EXPECT_TRUE(flags::SetCommandLineOptionWithMode("int_flag", "202",
+ flags::SET_FLAG_IF_DEFAULT));
+ EXPECT_EQ(absl::GetFlag(FLAGS_int_flag), 202);
+}
+
+// --------------------------------------------------------------------
+
+TEST_F(TypeErasedTest, TestIsValidFlagValue) {
+ EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "57"));
+ EXPECT_TRUE(flags::IsValidFlagValue("int_flag", "-101"));
+ EXPECT_FALSE(flags::IsValidFlagValue("int_flag", "1.1"));
+
+ EXPECT_TRUE(flags::IsValidFlagValue("string_flag", "#%^#%^$%DGHDG$W%adsf"));
+
+ EXPECT_TRUE(flags::IsValidFlagValue("bool_retired_flag", "true"));
+}
+
+} // namespace
diff --git a/third_party/abseil-cpp/absl/flags/internal/usage.cc b/third_party/abseil-cpp/absl/flags/internal/usage.cc
index 949709e883..ff90716194 100644
--- a/third_party/abseil-cpp/absl/flags/internal/usage.cc
+++ b/third_party/abseil-cpp/absl/flags/internal/usage.cc
@@ -15,8 +15,6 @@
#include "absl/flags/internal/usage.h"
-#include <stdint.h>
-
#include <functional>
#include <map>
#include <ostream>
@@ -25,11 +23,10 @@
#include <vector>
#include "absl/base/config.h"
-#include "absl/flags/commandlineflag.h"
#include "absl/flags/flag.h"
+#include "absl/flags/internal/commandlineflag.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"
@@ -37,25 +34,46 @@
#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;
+ABSL_FLAG(bool, help, false,
+ "show help on important flags for this binary [tip: all flags can "
+ "have two dashes]");
+ABSL_FLAG(bool, helpfull, false, "show help on all flags");
+ABSL_FLAG(bool, helpshort, false,
+ "show help on only the main module for this program");
+ABSL_FLAG(bool, helppackage, false,
+ "show help on all modules in the main package");
+ABSL_FLAG(bool, version, false, "show version and build info and exit");
+ABSL_FLAG(bool, only_check_args, false, "exit after checking all flags");
+ABSL_FLAG(std::string, helpon, "",
+ "show help on the modules named by this flag value");
+ABSL_FLAG(std::string, helpmatch, "",
+ "show help on modules whose name contains the specified substr");
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace flags_internal {
namespace {
-using PerFlagFilter = std::function<bool(const absl::CommandLineFlag&)>;
+absl::string_view TypenameForHelp(const flags_internal::CommandLineFlag& flag) {
+ // Only report names of v1 built-in types
+#define HANDLE_V1_BUILTIN_TYPE(t) \
+ if (flag.IsOfType<t>()) { \
+ return #t; \
+ }
+
+ HANDLE_V1_BUILTIN_TYPE(bool);
+ HANDLE_V1_BUILTIN_TYPE(int32_t);
+ HANDLE_V1_BUILTIN_TYPE(int64_t);
+ HANDLE_V1_BUILTIN_TYPE(uint64_t);
+ HANDLE_V1_BUILTIN_TYPE(double);
+#undef HANDLE_V1_BUILTIN_TYPE
-// Maximum length size in a human readable format.
-constexpr size_t kHrfMaxLineLength = 80;
+ if (flag.IsOfType<std::string>()) {
+ return "string";
+ }
+
+ return "";
+}
// 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.
@@ -109,24 +127,21 @@ 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),
+ FlagHelpPrettyPrinter(int max_line_len, 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.
+ // Empty std::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.
+ // Keep line separators in the input std::string.
tokens.push_back("\n");
}
for (auto token :
@@ -141,15 +156,14 @@ class FlagHelpPrettyPrinter {
for (auto token : tokens) {
bool new_line = (line_len_ == 0);
- // Respect line separators in the input string.
+ // Respect line separators in the input std::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_)) {
+ // Write the token, ending the std::string first if necessary/possible.
+ if (!new_line && (line_len_ + token.size() >= max_line_len_)) {
EndLine();
new_line = true;
}
@@ -168,12 +182,13 @@ class FlagHelpPrettyPrinter {
void StartLine() {
if (first_line_) {
- line_len_ = min_line_len_;
+ out_ << " ";
+ line_len_ = 4;
first_line_ = false;
} else {
- line_len_ = min_line_len_ + wrapped_line_indent_;
+ out_ << " ";
+ line_len_ = 6;
}
- out_ << std::string(line_len_, ' ');
}
void EndLine() {
out_ << '\n';
@@ -182,15 +197,14 @@ class FlagHelpPrettyPrinter {
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_;
+ const int max_line_len_;
+ int line_len_;
bool first_line_;
};
-void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
- FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 4, 2, out);
+void FlagHelpHumanReadable(const flags_internal::CommandLineFlag& flag,
+ std::ostream* out) {
+ FlagHelpPrettyPrinter printer(80, out); // Max line length is 80.
// Flag name.
printer.Write(absl::StrCat("--", flag.Name()));
@@ -198,20 +212,23 @@ void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
// Flag help.
printer.Write(absl::StrCat("(", flag.Help(), ");"), /*wrap_line=*/true);
+ // Flag data type (for V1 flags only).
+ if (!flag.IsAbseilFlag() && !flag.IsRetired()) {
+ printer.Write(absl::StrCat("type: ", TypenameForHelp(flag), ";"));
+ }
+
// 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.IsModified()) {
+ std::string curr_val = flag.CurrentValue();
if (flag.IsOfType<std::string>()) {
curr_val = absl::StrCat("\"", curr_val, "\"");
}
@@ -226,7 +243,7 @@ void FlagHelpHumanReadable(const CommandLineFlag& flag, std::ostream& out) {
// 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,
+void FlagsHelpImpl(std::ostream& out, flags_internal::FlagKindFilter filter_cb,
HelpFormat format, absl::string_view program_usage_message) {
if (format == HelpFormat::kHumanReadable) {
out << flags_internal::ShortProgramInvocationName() << ": "
@@ -245,54 +262,50 @@ void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
<< XMLElement("usage", program_usage_message) << '\n';
}
- // Ordered map of package name to
+ // 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*>>>
+ std::map<std::string,
+ std::vector<const flags_internal::CommandLineFlag*>>>
matching_flags;
- flags_internal::ForEachFlag([&](absl::CommandLineFlag& flag) {
+ flags_internal::ForEachFlag([&](flags_internal::CommandLineFlag* flag) {
+ std::string flag_filename = flag->Filename();
+
// Ignore retired flags.
- if (flag.IsRetired()) return;
+ if (flag->IsRetired()) return;
// If the flag has been stripped, pretend that it doesn't exist.
- if (flag.Help() == flags_internal::kStrippedFlagHelp) return;
+ if (flag->Help() == flags_internal::kStrippedFlagHelp) return;
// Make sure flag satisfies the filter
- if (!filter_cb(flag)) return;
-
- std::string flag_filename = flag.Filename();
+ if (!filter_cb || !filter_cb(flag_filename)) return;
matching_flags[std::string(flags_internal::Package(flag_filename))]
[flag_filename]
- .push_back(&flag);
+ .push_back(flag);
});
- absl::string_view package_separator; // controls blank lines between packages
- absl::string_view file_separator; // controls blank lines between files
- for (auto& package : matching_flags) {
+ 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 (auto& flags_in_file : package.second) {
+ 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";
}
- std::sort(std::begin(flags_in_file.second),
- std::end(flags_in_file.second),
- [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
- return lhs->Name() < rhs->Name();
- });
-
for (const auto* flag : flags_in_file.second) {
flags_internal::FlagHelp(out, *flag, format);
}
@@ -300,46 +313,27 @@ void FlagsHelpImpl(std::ostream& out, PerFlagFilter filter_cb,
}
if (format == HelpFormat::kHumanReadable) {
- FlagHelpPrettyPrinter printer(kHrfMaxLineLength, 0, 0, out);
-
if (filter_cb && matching_flags.empty()) {
- printer.Write("No flags matched.\n", true);
+ out << " No modules matched: use -helpfull\n";
}
- 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,
+void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
HelpFormat format) {
if (format == HelpFormat::kHumanReadable)
- flags_internal::FlagHelpHumanReadable(flag, out);
+ flags_internal::FlagHelpHumanReadable(flag, &out);
}
// --------------------------------------------------------------------
-// Produces the help messages for all flags matching the filename filter.
+// Produces the help messages for all flags matching the 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) {
@@ -354,169 +348,66 @@ void FlagsHelp(std::ostream& out, absl::string_view filter, HelpFormat format,
// 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;
+ if (absl::GetFlag(FLAGS_helpshort)) {
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helpshort_flags,
+ HelpFormat::kHumanReadable, program_usage_message);
+ return 1;
}
- 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;
-}
+ if (absl::GetFlag(FLAGS_helpfull)) {
+ // show all options
+ flags_internal::FlagsHelp(out, "", HelpFormat::kHumanReadable,
+ program_usage_message);
+ return 1;
+ }
-void SetFlagsHelpFormat(HelpFormat format) {
- absl::MutexLock l(&help_attributes_guard);
- help_format = format;
-}
+ if (!absl::GetFlag(FLAGS_helpon).empty()) {
+ flags_internal::FlagsHelp(
+ out, absl::StrCat("/", absl::GetFlag(FLAGS_helpon), "."),
+ HelpFormat::kHumanReadable, program_usage_message);
+ return 1;
+ }
-// 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 (!absl::GetFlag(FLAGS_helpmatch).empty()) {
+ flags_internal::FlagsHelp(out, absl::GetFlag(FLAGS_helpmatch),
+ HelpFormat::kHumanReadable,
+ program_usage_message);
+ return 1;
+ }
- if (name == "match") {
- SetFlagsHelpMode(HelpMode::kMatch);
- SetFlagsHelpMatchSubstr(value);
- return true;
- }
+ if (absl::GetFlag(FLAGS_help)) {
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_help_flags,
+ HelpFormat::kHumanReadable, program_usage_message);
- if (name == "on") {
- SetFlagsHelpMode(HelpMode::kMatch);
- SetFlagsHelpMatchSubstr(absl::StrCat("/", value, "."));
- return true;
- }
+ out << "\nTry --helpfull to get a list of all flags.\n";
- if (name == "full") {
- SetFlagsHelpMode(HelpMode::kFull);
- return true;
- }
+ return 1;
+ }
- if (name == "short") {
- SetFlagsHelpMode(HelpMode::kShort);
- return true;
- }
+ if (absl::GetFlag(FLAGS_helppackage)) {
+ flags_internal::FlagsHelpImpl(
+ out, flags_internal::GetUsageConfig().contains_helppackage_flags,
+ HelpFormat::kHumanReadable, program_usage_message);
- if (name == "package") {
- SetFlagsHelpMode(HelpMode::kPackage);
- return true;
- }
+ out << "\nTry --helpfull to get a list of all flags.\n";
- return false;
+ return 1;
}
- if (name == "version") {
- SetFlagsHelpMode(HelpMode::kVersion);
- return true;
+ if (absl::GetFlag(FLAGS_version)) {
+ 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;
}
- if (name == "only_check_args") {
- SetFlagsHelpMode(HelpMode::kOnlyCheckArgs);
- return true;
+ if (absl::GetFlag(FLAGS_only_check_args)) {
+ return 0;
}
- return false;
+ return -1;
}
} // namespace flags_internal
diff --git a/third_party/abseil-cpp/absl/flags/internal/usage.h b/third_party/abseil-cpp/absl/flags/internal/usage.h
index c0bcac5762..6b080fd1ee 100644
--- a/third_party/abseil-cpp/absl/flags/internal/usage.h
+++ b/third_party/abseil-cpp/absl/flags/internal/usage.h
@@ -20,8 +20,8 @@
#include <string>
#include "absl/base/config.h"
-#include "absl/flags/commandlineflag.h"
#include "absl/flags/declare.h"
+#include "absl/flags/internal/commandlineflag.h"
#include "absl/strings/string_view.h"
// --------------------------------------------------------------------
@@ -36,9 +36,8 @@ 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,
+// Outputs the help message describing specific flag.
+void FlagHelp(std::ostream& out, const flags_internal::CommandLineFlag& flag,
HelpFormat format = HelpFormat::kHumanReadable);
// Produces the help messages for all flags matching the filter. A flag matches
@@ -66,39 +65,17 @@ void FlagsHelp(std::ostream& out, absl::string_view filter,
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
+ABSL_DECLARE_FLAG(bool, help);
+ABSL_DECLARE_FLAG(bool, helpfull);
+ABSL_DECLARE_FLAG(bool, helpshort);
+ABSL_DECLARE_FLAG(bool, helppackage);
+ABSL_DECLARE_FLAG(bool, version);
+ABSL_DECLARE_FLAG(bool, only_check_args);
+ABSL_DECLARE_FLAG(std::string, helpon);
+ABSL_DECLARE_FLAG(std::string, helpmatch);
+
#endif // ABSL_FLAGS_INTERNAL_USAGE_H_
diff --git a/third_party/abseil-cpp/absl/flags/internal/usage_test.cc b/third_party/abseil-cpp/absl/flags/internal/usage_test.cc
index 044d71c87d..e1e57e5570 100644
--- a/third_party/abseil-cpp/absl/flags/internal/usage_test.cc
+++ b/third_party/abseil-cpp/absl/flags/internal/usage_test.cc
@@ -21,13 +21,15 @@
#include <string>
#include "gtest/gtest.h"
+#include "absl/flags/declare.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/internal/registry.h"
#include "absl/flags/usage.h"
#include "absl/flags/usage_config.h"
+#include "absl/memory/memory.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
@@ -45,7 +47,6 @@ static const char kTestUsageMessage[] = "Custom usage message";
struct UDT {
UDT() = default;
UDT(const UDT&) = default;
- UDT& operator=(const UDT&) = default;
};
bool AbslParseFlag(absl::string_view, UDT*, std::string*) { return true; }
std::string AbslUnparseFlag(const UDT&) { return "UDT{}"; }
@@ -88,14 +89,9 @@ class UsageReportingTest : public testing::Test {
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_;
+ flags::FlagSaver flag_saver_;
};
// --------------------------------------------------------------------
@@ -107,16 +103,15 @@ TEST_F(UsageReportingDeathTest, TestSetProgramUsageMessage) {
#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.*");
+ EXPECT_DEATH(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");
+ const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_01");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -128,7 +123,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_01) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
- const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_02");
+ const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_02");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -140,7 +135,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_02) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
- const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_03");
+ const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_03");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -152,7 +147,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_03) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
- const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_04");
+ const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_04");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -164,7 +159,7 @@ TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_04) {
}
TEST_F(UsageReportingTest, TestFlagHelpHRF_on_flag_05) {
- const auto* flag = absl::FindCommandLineFlag("usage_reporting_test_flag_05");
+ const auto* flag = flags::FindCommandLineFlag("usage_reporting_test_flag_05");
std::stringstream test_buf;
flags::FlagHelp(test_buf, *flag, flags::HelpFormat::kHumanReadable);
@@ -197,10 +192,6 @@ TEST_F(UsageReportingTest, TestFlagsHelpHRF) {
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;
@@ -224,11 +215,7 @@ path.
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.
+ No modules matched: use -helpfull
)");
std::stringstream test_buf_05;
@@ -240,8 +227,12 @@ path.
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,
+ "Flags from absl/flags/internal/usage.cc:"));
EXPECT_TRUE(
absl::StrContains(test_out_str, "-usage_reporting_test_flag_01 "));
+ EXPECT_TRUE(absl::StrContains(test_out_str, "-help (show help"))
+ << test_out_str;
}
// --------------------------------------------------------------------
@@ -254,40 +245,7 @@ TEST_F(UsageReportingTest, TestNoUsageFlags) {
// --------------------------------------------------------------------
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);
+ absl::SetFlag(&FLAGS_helpshort, true);
std::stringstream test_buf;
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -310,42 +268,13 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_simple) {
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");
+TEST_F(UsageReportingTest, TestUsageFlag_help) {
+ absl::SetFlag(&FLAGS_help, true);
std::stringstream test_buf;
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -369,16 +298,14 @@ TEST_F(UsageReportingTest, TestUsageFlag_help_multiple_flag) {
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.
+Try --helpfull to get a list of all flags.
)");
}
// --------------------------------------------------------------------
TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
- flags::SetFlagsHelpMode(flags::HelpMode::kPackage);
+ absl::SetFlag(&FLAGS_helppackage, true);
std::stringstream test_buf;
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 1);
@@ -402,16 +329,14 @@ TEST_F(UsageReportingTest, TestUsageFlag_helppackage) {
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.
+Try --helpfull to get a list of all flags.
)");
}
// --------------------------------------------------------------------
TEST_F(UsageReportingTest, TestUsageFlag_version) {
- flags::SetFlagsHelpMode(flags::HelpMode::kVersion);
+ absl::SetFlag(&FLAGS_version, true);
std::stringstream test_buf;
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -425,7 +350,7 @@ TEST_F(UsageReportingTest, TestUsageFlag_version) {
// --------------------------------------------------------------------
TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
- flags::SetFlagsHelpMode(flags::HelpMode::kOnlyCheckArgs);
+ absl::SetFlag(&FLAGS_only_check_args, true);
std::stringstream test_buf;
EXPECT_EQ(flags::HandleUsageFlags(test_buf, kTestUsageMessage), 0);
@@ -435,22 +360,17 @@ TEST_F(UsageReportingTest, TestUsageFlag_only_check_args) {
// --------------------------------------------------------------------
TEST_F(UsageReportingTest, TestUsageFlag_helpon) {
- flags::SetFlagsHelpMode(flags::HelpMode::kMatch);
- flags::SetFlagsHelpMatchSubstr("/bla-bla.");
+ absl::SetFlag(&FLAGS_helpon, "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.
+ No modules matched: use -helpfull
)");
- flags::SetFlagsHelpMatchSubstr("/usage_test.");
+ absl::SetFlag(&FLAGS_helpon, "usage_test");
std::stringstream test_buf_02;
EXPECT_EQ(flags::HandleUsageFlags(test_buf_02, kTestUsageMessage), 1);
@@ -473,10 +393,6 @@ path.
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.
)");
}
diff --git a/third_party/abseil-cpp/absl/flags/marshalling.cc b/third_party/abseil-cpp/absl/flags/marshalling.cc
index 81f9cebd6f..6f2ddda8c3 100644
--- a/third_party/abseil-cpp/absl/flags/marshalling.cc
+++ b/third_party/abseil-cpp/absl/flags/marshalling.cc
@@ -74,16 +74,15 @@ static int NumericBase(absl::string_view text) {
}
template <typename IntType>
-inline bool ParseFlagImpl(absl::string_view text, IntType& dst) {
+inline bool ParseFlagImpl(absl::string_view text, IntType* dst) {
text = absl::StripAsciiWhitespace(text);
- return absl::numbers_internal::safe_strtoi_base(text, &dst,
- NumericBase(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 (!ParseFlagImpl(text, &val)) return false;
if (static_cast<short>(val) != val) // worked, but number out of range
return false;
*dst = static_cast<short>(val);
@@ -92,7 +91,7 @@ bool AbslParseFlag(absl::string_view text, short* dst, std::string*) {
bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
unsigned int val;
- if (!ParseFlagImpl(text, val)) return false;
+ if (!ParseFlagImpl(text, &val)) return false;
if (static_cast<unsigned short>(val) !=
val) // worked, but number out of range
return false;
@@ -101,28 +100,28 @@ bool AbslParseFlag(absl::string_view text, unsigned short* dst, std::string*) {
}
bool AbslParseFlag(absl::string_view text, int* dst, std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
bool AbslParseFlag(absl::string_view text, unsigned int* dst, std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
bool AbslParseFlag(absl::string_view text, long* dst, std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
bool AbslParseFlag(absl::string_view text, unsigned long* dst, std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
bool AbslParseFlag(absl::string_view text, long long* dst, std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
bool AbslParseFlag(absl::string_view text, unsigned long long* dst,
std::string*) {
- return ParseFlagImpl(text, *dst);
+ return ParseFlagImpl(text, dst);
}
// --------------------------------------------------------------------
@@ -173,7 +172,7 @@ 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
+ // digits10 is guaranteed to roundtrip correctly in std::string -> value -> std::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);
diff --git a/third_party/abseil-cpp/absl/flags/marshalling.h b/third_party/abseil-cpp/absl/flags/marshalling.h
index 7cbc136d57..0b5033547e 100644
--- a/third_party/abseil-cpp/absl/flags/marshalling.h
+++ b/third_party/abseil-cpp/absl/flags/marshalling.h
@@ -83,7 +83,7 @@
// // 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
+// // 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,
@@ -139,7 +139,7 @@
//
// // 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).
+// // (which have built-in Abseil flag support.
//
// bool AbslParseFlag(absl::string_view text, MyFlagType* flag,
// std::string* err) {
diff --git a/third_party/abseil-cpp/absl/flags/parse.cc b/third_party/abseil-cpp/absl/flags/parse.cc
index dd1a6796ca..812e498189 100644
--- a/third_party/abseil-cpp/absl/flags/parse.cc
+++ b/third_party/abseil-cpp/absl/flags/parse.cc
@@ -34,16 +34,14 @@
#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/registry.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"
@@ -68,22 +66,6 @@ ABSL_CONST_INIT bool fromenv_needs_processing
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
@@ -223,7 +205,7 @@ bool ArgsList::ReadFromFlagfile(const std::string& flag_file_name) {
// 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) {
+bool GetEnvVar(const char* var_name, std::string* var_value) {
#ifdef _WIN32
char buf[1024];
auto get_res = GetEnvironmentVariableA(var_name, buf, sizeof(buf));
@@ -235,14 +217,14 @@ bool GetEnvVar(const char* var_name, std::string& var_value) {
return false;
}
- var_value = std::string(buf, get_res);
+ *var_value = std::string(buf, get_res);
#else
const char* val = ::getenv(var_name);
if (val == nullptr) {
return false;
}
- var_value = val;
+ *var_value = val;
#endif
return true;
@@ -290,11 +272,11 @@ std::tuple<absl::string_view, absl::string_view, bool> SplitNameAndValue(
// 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);
+ CommandLineFlag* flag = flags_internal::FindCommandLineFlag(flag_name);
bool is_negative = false;
if (!flag && absl::ConsumePrefix(&flag_name, "no")) {
- flag = absl::FindCommandLineFlag(flag_name);
+ flag = flags_internal::FindCommandLineFlag(flag_name);
is_negative = true;
}
@@ -307,17 +289,16 @@ std::tuple<CommandLineFlag*, bool> LocateFlag(absl::string_view flag_name) {
// back.
void CheckDefaultValuesParsingRoundtrip() {
#ifndef NDEBUG
- flags_internal::ForEachFlag([&](CommandLineFlag& flag) {
- if (flag.IsRetired()) return;
+ flags_internal::ForEachFlag([&](CommandLineFlag* flag) {
+ if (flag->IsRetired()) return;
-#define ABSL_FLAGS_INTERNAL_IGNORE_TYPE(T, _) \
- if (flag.IsOfType<T>()) return;
+#define IGNORE_TYPE(T) \
+ if (flag->IsOfType<T>()) return;
- ABSL_FLAGS_INTERNAL_SUPPORTED_TYPES(ABSL_FLAGS_INTERNAL_IGNORE_TYPE)
-#undef ABSL_FLAGS_INTERNAL_IGNORE_TYPE
+ ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(IGNORE_TYPE)
+#undef IGNORE_TYPE
- flags_internal::PrivateHandleAccessor::CheckDefaultValueParsingRoundtrip(
- flag);
+ flag->CheckDefaultValueParsingRoundtrip();
});
#endif
}
@@ -330,13 +311,13 @@ void CheckDefaultValuesParsingRoundtrip() {
// 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) {
+ 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);
+ input_args->push_back(al);
} else {
success = false;
}
@@ -351,7 +332,7 @@ bool ReadFlagfiles(const std::vector<std::string>& flagfiles,
// `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,
+ std::vector<ArgsList>* input_args,
bool fail_on_absent_in_env) {
bool success = true;
std::vector<std::string> args;
@@ -372,7 +353,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
const std::string envname = absl::StrCat("FLAGS_", flag_name);
std::string envval;
- if (!GetEnvVar(envname.c_str(), envval)) {
+ if (!GetEnvVar(envname.c_str(), &envval)) {
if (fail_on_absent_in_env) {
flags_internal::ReportUsageError(
absl::StrCat(envname, " not found in environment"), true);
@@ -387,7 +368,7 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
}
if (success) {
- input_args.emplace_back(args);
+ input_args->emplace_back(args);
}
return success;
@@ -397,8 +378,8 @@ bool ReadFlagsFromEnv(const std::vector<std::string>& flag_names,
// 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 HandleGeneratorFlags(std::vector<ArgsList>* input_args,
+ std::vector<std::string>* flagfile_value) {
bool success = true;
absl::MutexLock l(&flags_internal::processing_checks_guard);
@@ -423,9 +404,9 @@ bool HandleGeneratorFlags(std::vector<ArgsList>& input_args,
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());
+ if (input_args->size() == 1) {
+ flagfile_value->insert(flagfile_value->end(), flagfiles.begin(),
+ flagfiles.end());
}
success &= ReadFlagfiles(flagfiles, input_args);
@@ -552,10 +533,10 @@ std::tuple<bool, absl::string_view> DeduceFlagValue(const CommandLineFlag& flag,
curr_list->PopFront();
value = curr_list->Front();
- // Heuristic to detect the case where someone treats a string arg
+ // Heuristic to detect the case where someone treats a std::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
+ // We look for a flag of std::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)));
@@ -594,28 +575,12 @@ bool CanIgnoreUndefinedFlag(absl::string_view flag_name) {
// --------------------------------------------------------------------
-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();
@@ -640,20 +605,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
}
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);
+ success &= HandleGeneratorFlags(&input_args, &flagfile_value);
// 30. Select top-most (most recent) arguments list. If it is empty drop it
// and re-try.
@@ -688,7 +646,7 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
// 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
+ // can be empty either if there were no '=' in argument std::string at all or
// an argument looked like "--foo=". In a latter case is_empty_value is
// true.
absl::string_view flag_name;
@@ -713,11 +671,6 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
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));
@@ -739,17 +692,13 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
}
// 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;
+ // Setting retired flag fails, but we ignoring it here.
+ if (flag->IsRetired()) continue;
+ std::string error;
+ if (!flag->SetFromString(value, SET_FLAGS_VALUE, kCommandLine, &error)) {
flags_internal::ReportUsageError(error, true);
success = false;
- } else {
- specified_flags->push_back(flag);
}
}
@@ -801,10 +750,6 @@ std::vector<char*> ParseCommandLineImpl(int argc, char* argv[],
}
}
- // Trim and sort the vector.
- specified_flags->shrink_to_fit();
- std::sort(specified_flags->begin(), specified_flags->end(),
- SpecifiedFlagsCompare{});
return output_args;
}
diff --git a/third_party/abseil-cpp/absl/flags/parse.h b/third_party/abseil-cpp/absl/flags/parse.h
index 929de2cb40..f37b0602e6 100644
--- a/third_party/abseil-cpp/absl/flags/parse.h
+++ b/third_party/abseil-cpp/absl/flags/parse.h
@@ -23,6 +23,7 @@
#ifndef ABSL_FLAGS_PARSE_H_
#define ABSL_FLAGS_PARSE_H_
+#include <string>
#include <vector>
#include "absl/base/config.h"
diff --git a/third_party/abseil-cpp/absl/flags/parse_test.cc b/third_party/abseil-cpp/absl/flags/parse_test.cc
index 8dc91db2b3..6f49377a93 100644
--- a/third_party/abseil-cpp/absl/flags/parse_test.cc
+++ b/third_party/abseil-cpp/absl/flags/parse_test.cc
@@ -28,8 +28,7 @@
#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/flags/internal/registry.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
@@ -46,7 +45,6 @@ using absl::base_internal::ScopedSetEnv;
struct UDT {
UDT() = default;
UDT(const UDT&) = default;
- UDT& operator=(const UDT&) = default;
UDT(int v) : value(v) {} // NOLINT
int value;
@@ -173,8 +171,8 @@ constexpr const char* const ff2_data[] = {
// 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=";
+ std::string* flagfile_flag) {
+ *flagfile_flag = "--flagfile=";
absl::string_view separator;
for (const auto& flagfile_data : ffd) {
std::string flagfile_name =
@@ -185,11 +183,11 @@ const char* GetFlagfileFlag(const std::vector<FlagfileData>& ffd,
flagfile_out << absl::Substitute(line, GetTestTempDir()) << "\n";
}
- absl::StrAppend(&flagfile_flag, separator, flagfile_name);
+ absl::StrAppend(flagfile_flag, separator, flagfile_name);
separator = ",";
}
- return flagfile_flag.c_str();
+ return flagfile_flag->c_str();
}
} // namespace
@@ -209,11 +207,8 @@ 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_;
+ flags::FlagSaver flag_saver_;
};
// --------------------------------------------------------------------
@@ -486,22 +481,21 @@ TEST_F(ParseDeathTest, TestUndefinedArg) {
"testbin",
"--undefined_flag",
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Unknown command line flag 'undefined_flag'");
+ EXPECT_DEATH(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'");
+ EXPECT_DEATH(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'");
+ EXPECT_DEATH(InvokeParse(in_args3), "Unknown command line flag 'Int_flag'");
}
// --------------------------------------------------------------------
@@ -511,7 +505,7 @@ TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
"testbin",
"--bool_flag=",
};
- EXPECT_DEATH_IF_SUPPORTED(
+ EXPECT_DEATH(
InvokeParse(in_args1),
"Missing the value after assignment for the boolean flag 'bool_flag'");
@@ -519,7 +513,7 @@ TEST_F(ParseDeathTest, TestInvalidBoolFlagFormat) {
"testbin",
"--nobool_flag=true",
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ EXPECT_DEATH(InvokeParse(in_args2),
"Negative form with assignment is not valid for the boolean "
"flag 'bool_flag'");
}
@@ -531,14 +525,14 @@ TEST_F(ParseDeathTest, TestInvalidNonBoolFlagFormat) {
"testbin",
"--nostring_flag",
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ EXPECT_DEATH(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),
+ EXPECT_DEATH(InvokeParse(in_args2),
"Missing the value for the flag 'int_flag'");
}
@@ -549,7 +543,7 @@ TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
"testbin",
"--udt_flag=1",
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ EXPECT_DEATH(InvokeParse(in_args1),
"Illegal value '1' specified for flag 'udt_flag'; Use values A, "
"AAA instead");
@@ -558,7 +552,7 @@ TEST_F(ParseDeathTest, TestInvalidUDTFlagFormat) {
"--udt_flag",
"AA",
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ EXPECT_DEATH(InvokeParse(in_args2),
"Illegal value 'AA' specified for flag 'udt_flag'; Use values "
"A, AAA instead");
}
@@ -593,14 +587,14 @@ TEST_F(ParseTest, TestSimpleValidFlagfile) {
const char* in_args1[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
+ &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),
+ &flagfile_flag),
};
TestParse(in_args2, 100, 0.1, "q2w2 ", false);
}
@@ -614,7 +608,7 @@ TEST_F(ParseTest, TestValidMultiFlagfile) {
"testbin",
GetFlagfileFlag({{"parse_test.ff2", absl::MakeConstSpan(ff2_data)},
{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
+ &flagfile_flag),
};
TestParse(in_args1, -1, 0.1, "q2w2 ", true);
}
@@ -627,7 +621,7 @@ TEST_F(ParseTest, TestFlagfileMixedWithRegularFlags) {
const char* in_args1[] = {
"testbin", "--int_flag=3",
GetFlagfileFlag({{"parse_test.ff1", absl::MakeConstSpan(ff1_data)}},
- flagfile_flag),
+ &flagfile_flag),
"-double_flag=0.2"};
TestParse(in_args1, -1, 0.2, "q2w2 ", true);
}
@@ -642,14 +636,10 @@ TEST_F(ParseTest, TestFlagfileInFlagfile) {
"--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),
+ &flagfile_flag),
};
TestParse(in_args1, 100, 0.1, "q2w2 ", false);
}
@@ -666,9 +656,9 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args1[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff4",
- absl::MakeConstSpan(ff4_data)}}, flagfile_flag),
+ absl::MakeConstSpan(ff4_data)}}, &flagfile_flag),
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ EXPECT_DEATH(InvokeParse(in_args1),
"Unknown command line flag 'unknown_flag'");
constexpr const char* const ff5_data[] = {
@@ -678,9 +668,9 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args2[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff5",
- absl::MakeConstSpan(ff5_data)}}, flagfile_flag),
+ absl::MakeConstSpan(ff5_data)}}, &flagfile_flag),
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args2),
+ EXPECT_DEATH(InvokeParse(in_args2),
"Unknown command line flag 'int_flag 10'");
constexpr const char* const ff6_data[] = {
@@ -690,17 +680,16 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args3[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff6", absl::MakeConstSpan(ff6_data)}},
- flagfile_flag),
+ &flagfile_flag),
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args3),
+ EXPECT_DEATH(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");
+ EXPECT_DEATH(InvokeParse(in_args4), "Can't open flagfile invalid_flag_file");
constexpr const char* const ff7_data[] = {
"--int_flag=10",
@@ -711,9 +700,9 @@ TEST_F(ParseDeathTest, TestInvalidFlagfiles) {
const char* in_args5[] = {
"testbin",
GetFlagfileFlag({{"parse_test.ff7", absl::MakeConstSpan(ff7_data)}},
- flagfile_flag),
+ &flagfile_flag),
};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args5),
+ EXPECT_DEATH(InvokeParse(in_args5),
"Unexpected line in the flagfile .*: \\*bin\\*");
}
@@ -735,7 +724,7 @@ TEST_F(ParseTest, TestReadingRequiredFlagsFromEnv) {
TEST_F(ParseDeathTest, TestReadingUnsetRequiredFlagsFromEnv) {
const char* in_args1[] = {"testbin", "--fromenv=int_flag"};
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
+ EXPECT_DEATH(InvokeParse(in_args1),
"FLAGS_int_flag not found in environment");
}
@@ -746,8 +735,7 @@ TEST_F(ParseDeathTest, TestRecursiveFlagsFromEnv) {
ScopedSetEnv set_tryfromenv("FLAGS_tryfromenv", "int_flag");
- EXPECT_DEATH_IF_SUPPORTED(InvokeParse(in_args1),
- "Infinite recursion on flag tryfromenv");
+ EXPECT_DEATH(InvokeParse(in_args1), "Infinite recursion on flag tryfromenv");
}
// --------------------------------------------------------------------
@@ -856,7 +844,7 @@ TEST_F(ParseTest, TestIgnoreUndefinedFlags) {
// --------------------------------------------------------------------
-TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
+TEST_F(ParseDeathTest, TestHelpFlagHandling) {
const char* in_args1[] = {
"testbin",
"--help",
@@ -875,56 +863,7 @@ TEST_F(ParseDeathTest, TestSimpleHelpFlagHandling) {
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/third_party/abseil-cpp/absl/flags/reflection.cc b/third_party/abseil-cpp/absl/flags/reflection.cc
deleted file mode 100644
index dbce4032ab..0000000000
--- a/third_party/abseil-cpp/absl/flags/reflection.cc
+++ /dev/null
@@ -1,354 +0,0 @@
-//
-// 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 <string>
-
-#include "absl/base/config.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/container/flat_hash_map.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 = absl::flat_hash_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);
- }
- std::sort(std::begin(registry.flat_flags_), std::end(registry.flat_flags_),
- [](const CommandLineFlag* lhs, const CommandLineFlag* rhs) {
- return lhs->Name() < rhs->Name();
- });
- 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/third_party/abseil-cpp/absl/flags/reflection.h b/third_party/abseil-cpp/absl/flags/reflection.h
deleted file mode 100644
index e6baf5de4b..0000000000
--- a/third_party/abseil-cpp/absl/flags/reflection.h
+++ /dev/null
@@ -1,90 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/reflection_test.cc b/third_party/abseil-cpp/absl/flags/reflection_test.cc
deleted file mode 100644
index 79cfa90c3a..0000000000
--- a/third_party/abseil-cpp/absl/flags/reflection_test.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/flags/usage_config.cc b/third_party/abseil-cpp/absl/flags/usage_config.cc
index 5d7426db31..2d837ec590 100644
--- a/third_party/abseil-cpp/absl/flags/usage_config.cc
+++ b/third_party/abseil-cpp/absl/flags/usage_config.cc
@@ -15,7 +15,6 @@
#include "absl/flags/usage_config.h"
-#include <functional>
#include <iostream>
#include <string>
@@ -34,8 +33,7 @@ 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) {}
+ABSL_ATTRIBUTE_WEAK void AbslInternalReportFatalUsageError(absl::string_view) {}
} // extern "C"
@@ -52,15 +50,10 @@ namespace {
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).
+ // <program>_main.cc, where the <program> is the name of the binary.
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))
+ if (!absl::ConsumePrefix(&suffix,
+ flags_internal::ShortProgramInvocationName()))
return false;
return absl::StartsWith(suffix, ".") || absl::StartsWith(suffix, "-main.") ||
absl::StartsWith(suffix, "_main.");
@@ -129,7 +122,7 @@ void ReportUsageError(absl::string_view msg, bool is_fatal) {
std::cerr << "ERROR: " << msg << std::endl;
if (is_fatal) {
- ABSL_INTERNAL_C_SYMBOL(AbslInternalReportFatalUsageError)(msg);
+ AbslInternalReportFatalUsageError(msg);
}
}
diff --git a/third_party/abseil-cpp/absl/flags/usage_config.h b/third_party/abseil-cpp/absl/flags/usage_config.h
index ded70300f0..0ed7e1b47c 100644
--- a/third_party/abseil-cpp/absl/flags/usage_config.h
+++ b/third_party/abseil-cpp/absl/flags/usage_config.h
@@ -90,7 +90,7 @@ struct FlagsUsageConfig {
// program output.
flags_internal::FlagKindFilter contains_helppackage_flags;
- // Generates string containing program version. This is the string reported
+ // Generates std::string containing program version. This is the std::string reported
// when user specifies --version in a command line.
std::function<std::string()> version_string;
@@ -127,8 +127,7 @@ 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);
+void AbslInternalReportFatalUsageError(absl::string_view);
} // extern "C"
diff --git a/third_party/abseil-cpp/absl/flags/usage_config_test.cc b/third_party/abseil-cpp/absl/flags/usage_config_test.cc
index e57a8832f6..70eca30b8f 100644
--- a/third_party/abseil-cpp/absl/flags/usage_config_test.cc
+++ b/third_party/abseil-cpp/absl/flags/usage_config_test.cc
@@ -84,11 +84,7 @@ TEST_F(FlagsUsageConfigTest, TestGetSetFlagsUsageConfig) {
// --------------------------------------------------------------------
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"));
diff --git a/third_party/abseil-cpp/absl/functional/BUILD.bazel b/third_party/abseil-cpp/absl/functional/BUILD.bazel
index f9f2b9c2f5..432546ce0c 100644
--- a/third_party/abseil-cpp/absl/functional/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/functional/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "bind_front",
@@ -59,7 +60,6 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
"//absl/base:base_internal",
- "//absl/base:core_headers",
"//absl/meta:type_traits",
],
)
diff --git a/third_party/abseil-cpp/absl/functional/CMakeLists.txt b/third_party/abseil-cpp/absl/functional/CMakeLists.txt
index 338ddc6c6c..cda914f2cd 100644
--- a/third_party/abseil-cpp/absl/functional/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/functional/CMakeLists.txt
@@ -39,7 +39,7 @@ absl_cc_test(
DEPS
absl::bind_front
absl::memory
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -53,7 +53,6 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::base_internal
- absl::core_headers
absl::meta
PUBLIC
)
@@ -69,5 +68,5 @@ absl_cc_test(
absl::function_ref
absl::memory
absl::test_instance_tracker
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/functional/function_ref.h b/third_party/abseil-cpp/absl/functional/function_ref.h
index 824e3cea9d..370acc55b0 100644
--- a/third_party/abseil-cpp/absl/functional/function_ref.h
+++ b/third_party/abseil-cpp/absl/functional/function_ref.h
@@ -50,7 +50,6 @@
#include <functional>
#include <type_traits>
-#include "absl/base/attributes.h"
#include "absl/functional/internal/function_ref.h"
#include "absl/meta/type_traits.h"
@@ -91,7 +90,7 @@ class FunctionRef<R(Args...)> {
// 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&&...>>
+ typename FR = absl::base_internal::InvokeT<F, Args&&...>>
using EnableIfCompatible =
typename std::enable_if<std::is_void<R>::value ||
std::is_convertible<FR, R>::value>::type;
@@ -99,8 +98,7 @@ class FunctionRef<R(Args...)> {
public:
// Constructs a FunctionRef from any invokable type.
template <typename F, typename = EnableIfCompatible<const F&>>
- // NOLINTNEXTLINE(runtime/explicit)
- FunctionRef(const F& f ABSL_ATTRIBUTE_LIFETIME_BOUND)
+ FunctionRef(const F& f) // NOLINT(runtime/explicit)
: invoker_(&absl::functional_internal::InvokeObject<F, R, Args...>) {
absl::functional_internal::AssertNonNull(f);
ptr_.obj = &f;
@@ -124,7 +122,6 @@ class FunctionRef<R(Args...)> {
// 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;
- FunctionRef(const FunctionRef& rhs) = default;
// Call the underlying object.
R operator()(Args... args) const {
diff --git a/third_party/abseil-cpp/absl/functional/internal/front_binder.h b/third_party/abseil-cpp/absl/functional/internal/front_binder.h
index 45f52de73d..a4d95da44a 100644
--- a/third_party/abseil-cpp/absl/functional/internal/front_binder.h
+++ b/third_party/abseil-cpp/absl/functional/internal/front_binder.h
@@ -33,7 +33,7 @@ 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(
+ return base_internal::Invoke(
absl::forward<Tuple>(bound).template get<Idx>()...,
absl::forward<Args>(free)...);
}
@@ -50,22 +50,22 @@ class FrontBinder {
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&&...>>
+ template <class... FreeArgs,
+ class R = base_internal::InvokeT<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&&...>>
+ class R = base_internal::InvokeT<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<
+ template <class... FreeArgs, class R = base_internal::InvokeT<
F&&, BoundArgs&&..., FreeArgs&&...>>
R operator()(FreeArgs&&... free_args) && {
// This overload is called when *this is an rvalue. If some of the bound
@@ -75,8 +75,8 @@ class FrontBinder {
}
template <class... FreeArgs,
- class R = base_internal::invoke_result_t<
- const F&&, const BoundArgs&&..., FreeArgs&&...>>
+ class R = base_internal::InvokeT<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.
diff --git a/third_party/abseil-cpp/absl/functional/internal/function_ref.h b/third_party/abseil-cpp/absl/functional/internal/function_ref.h
index b5bb8b430a..d1575054ea 100644
--- a/third_party/abseil-cpp/absl/functional/internal/function_ref.h
+++ b/third_party/abseil-cpp/absl/functional/internal/function_ref.h
@@ -71,14 +71,14 @@ 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)...));
+ 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)...));
+ absl::base_internal::Invoke(f, std::forward<Args>(args)...));
}
template <typename Sig>
diff --git a/third_party/abseil-cpp/absl/hash/BUILD.bazel b/third_party/abseil-cpp/absl/hash/BUILD.bazel
index f0640d34e4..ffe8c294a0 100644
--- a/third_party/abseil-cpp/absl/hash/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/hash/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "hash",
@@ -36,8 +37,6 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":city",
- ":low_level_hash",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/container:fixed_array",
@@ -77,30 +76,10 @@ cc_test(
"//absl/container:flat_hash_set",
"//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,
@@ -140,31 +119,3 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
-
-cc_library(
- name = "low_level_hash",
- srcs = ["internal/low_level_hash.cc"],
- hdrs = ["internal/low_level_hash.h"],
- copts = ABSL_DEFAULT_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
- deps = [
- "//absl/base:config",
- "//absl/base:endian",
- "//absl/numeric:bits",
- "//absl/numeric:int128",
- ],
-)
-
-cc_test(
- name = "low_level_hash_test",
- srcs = ["internal/low_level_hash_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":low_level_hash",
- "//absl/strings",
- "@com_google_googletest//:gtest_main",
- ],
-)
diff --git a/third_party/abseil-cpp/absl/hash/CMakeLists.txt b/third_party/abseil-cpp/absl/hash/CMakeLists.txt
index 5916ae3cf0..febc551fce 100644
--- a/third_party/abseil-cpp/absl/hash/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/hash/CMakeLists.txt
@@ -24,9 +24,7 @@ absl_cc_library(
"internal/hash.h"
COPTS
${ABSL_DEFAULT_COPTS}
- DEPS
- absl::city
- absl::config
+ DEPS
absl::core_headers
absl::endian
absl::fixed_array
@@ -36,7 +34,7 @@ absl_cc_library(
absl::optional
absl::variant
absl::utility
- absl::low_level_hash
+ absl::city
PUBLIC
)
@@ -52,7 +50,7 @@ absl_cc_library(
absl::meta
absl::strings
absl::variant
- GTest::gmock
+ gmock
TESTONLY
)
@@ -64,7 +62,6 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::cord_test_helpers
absl::hash
absl::hash_testing
absl::core_headers
@@ -72,7 +69,7 @@ absl_cc_test(
absl::spy_hash_state
absl::meta
absl::int128
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -113,34 +110,6 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::city
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- low_level_hash
- HDRS
- "internal/low_level_hash.h"
- SRCS
- "internal/low_level_hash.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::bits
- absl::config
- absl::endian
- absl::int128
+ gmock_main
)
-absl_cc_test(
- NAME
- low_level_hash_test
- SRCS
- "internal/low_level_hash_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::low_level_hash
- absl::strings
- GTest::gmock_main
-)
diff --git a/third_party/abseil-cpp/absl/hash/hash.h b/third_party/abseil-cpp/absl/hash/hash.h
index 8282ea53c6..23a65ea868 100644
--- a/third_party/abseil-cpp/absl/hash/hash.h
+++ b/third_party/abseil-cpp/absl/hash/hash.h
@@ -37,11 +37,8 @@
// 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).
+// each process. E.g., absl::Hash<int>()(9) in one process and
+// absl::Hash<int>()(9) in another process are likely to differ.
//
// Example:
//
@@ -73,8 +70,6 @@
#ifndef ABSL_HASH_HASH_H_
#define ABSL_HASH_HASH_H_
-#include <tuple>
-
#include "absl/hash/internal/hash.h"
namespace absl {
@@ -90,6 +85,7 @@ ABSL_NAMESPACE_BEGIN
// * 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:
@@ -102,7 +98,6 @@ ABSL_NAMESPACE_BEGIN
// * 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)
@@ -129,6 +124,8 @@ ABSL_NAMESPACE_BEGIN
// * 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
@@ -216,26 +213,6 @@ ABSL_NAMESPACE_BEGIN
template <typename T>
using Hash = absl::hash_internal::Hash<T>;
-// HashOf
-//
-// absl::HashOf() is a helper that generates a hash from the values of its
-// arguments. It dispatches to absl::Hash directly, as follows:
-// * HashOf(t) == absl::Hash<T>{}(t)
-// * HashOf(a, b, c) == HashOf(std::make_tuple(a, b, c))
-//
-// HashOf(a1, a2, ...) == HashOf(b1, b2, ...) is guaranteed when
-// * The argument lists have pairwise identical C++ types
-// * a1 == b1 && a2 == b2 && ...
-//
-// The requirement that the arguments match in both type and value is critical.
-// It means that `a == b` does not necessarily imply `HashOf(a) == HashOf(b)` if
-// `a` and `b` have different types. For example, `HashOf(2) != HashOf(2.0)`.
-template <int&... ExplicitArgumentBarrier, typename... Types>
-size_t HashOf(const Types&... values) {
- auto tuple = std::tie(values...);
- return absl::Hash<decltype(tuple)>{}(tuple);
-}
-
// HashState
//
// A type erased version of the hash state concept, for use in user-defined
diff --git a/third_party/abseil-cpp/absl/hash/hash_benchmark.cc b/third_party/abseil-cpp/absl/hash/hash_benchmark.cc
deleted file mode 100644
index d498ac29c0..0000000000
--- a/third_party/abseil-cpp/absl/hash/hash_benchmark.cc
+++ /dev/null
@@ -1,254 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/hash/hash_test.cc b/third_party/abseil-cpp/absl/hash/hash_test.cc
index b3ddebdd42..f02a537ae8 100644
--- a/third_party/abseil-cpp/absl/hash/hash_test.cc
+++ b/third_party/abseil-cpp/absl/hash/hash_test.cc
@@ -42,7 +42,6 @@
#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 {
@@ -82,8 +81,8 @@ 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 };
@@ -270,22 +269,6 @@ struct WrapInTuple {
}
};
-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));
@@ -294,29 +277,25 @@ TEST(HashValueTest, Strings) {
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))));
+ EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ std::string(), absl::string_view(),
+ std::string(""), absl::string_view(""),
+ std::string(small), absl::string_view(small),
+ std::string(dup), absl::string_view(dup),
+ std::string(large), absl::string_view(large),
+ std::string(huge), absl::string_view(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_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+ t(std::string()), t(absl::string_view()),
+ t(std::string("")), t(absl::string_view("")),
+ t(std::string(small)), t(absl::string_view(small)),
+ t(std::string(dup)), t(absl::string_view(dup)),
+ t(std::string(large)), t(absl::string_view(large)),
+ t(std::string(huge)), t(absl::string_view(huge)))));
+
+ // Make sure that hashing a `const char*` does not use its std::string-value.
EXPECT_NE(SpyHash(static_cast<const char*>("ABC")),
SpyHash(absl::string_view("ABC")));
}
@@ -407,7 +386,7 @@ using IntSequenceTypes =
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.
+// implentation is recursive within absl::Hash.
// It uses std::abs() on the value to provide different bitwise representations
// of the same logical value.
struct Private {
@@ -512,7 +491,7 @@ TEST(HashValueTest, CombinePiecewiseBuffer) {
SCOPED_TRACE(big_buffer_size);
std::string big_buffer;
for (int i = 0; i < big_buffer_size; ++i) {
- // Arbitrary string
+ // Arbitrary std::string
big_buffer.push_back(32 + (i * (i / 3)) % 64);
}
auto big_buffer_hash = hash(PiecewiseHashTester(big_buffer));
@@ -581,24 +560,6 @@ TEST(HashValueTest, Maps) {
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 IsHashCallable : std::false_type {};
@@ -819,8 +780,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 {
@@ -973,39 +934,4 @@ TEST(HashTest, DoesNotUseImplicitConversionsToBool) {
absl::Hash<ValueWithBoolConversion>()(ValueWithBoolConversion{1}));
}
-TEST(HashOf, MatchesHashForSingleArgument) {
- std::string s = "forty two";
- int i = 42;
- double d = 42.0;
- std::tuple<int, int> t{4, 2};
-
- EXPECT_EQ(absl::HashOf(s), absl::Hash<std::string>{}(s));
- EXPECT_EQ(absl::HashOf(i), absl::Hash<int>{}(i));
- EXPECT_EQ(absl::HashOf(d), absl::Hash<double>{}(d));
- EXPECT_EQ(absl::HashOf(t), (absl::Hash<std::tuple<int, int>>{}(t)));
-}
-
-TEST(HashOf, MatchesHashOfTupleForMultipleArguments) {
- std::string hello = "hello";
- std::string world = "world";
-
- EXPECT_EQ(absl::HashOf(), absl::HashOf(std::make_tuple()));
- EXPECT_EQ(absl::HashOf(hello), absl::HashOf(std::make_tuple(hello)));
- EXPECT_EQ(absl::HashOf(hello, world),
- absl::HashOf(std::make_tuple(hello, world)));
-}
-
-template <typename T>
-std::true_type HashOfExplicitParameter(decltype(absl::HashOf<T>(0))) {
- return {};
-}
-template <typename T>
-std::false_type HashOfExplicitParameter(size_t) {
- return {};
-}
-
-TEST(HashOf, CantPassExplicitTemplateParameters) {
- EXPECT_FALSE(HashOfExplicitParameter<int>(0));
-}
-
} // namespace
diff --git a/third_party/abseil-cpp/absl/hash/internal/city.cc b/third_party/abseil-cpp/absl/hash/internal/city.cc
index 5460134e57..e122c184b6 100644
--- a/third_party/abseil-cpp/absl/hash/internal/city.cc
+++ b/third_party/abseil-cpp/absl/hash/internal/city.cc
@@ -200,6 +200,10 @@ 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;
@@ -210,11 +214,6 @@ 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;
@@ -254,8 +253,9 @@ 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;
@@ -266,9 +266,8 @@ static std::pair<uint64_t, uint64_t> WeakHashLen32WithSeeds(
}
// 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);
}
@@ -311,10 +310,8 @@ 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.
@@ -340,7 +337,7 @@ 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);
}
diff --git a/third_party/abseil-cpp/absl/hash/internal/city.h b/third_party/abseil-cpp/absl/hash/internal/city.h
index 393da0b95d..161c7748ec 100644
--- a/third_party/abseil-cpp/absl/hash/internal/city.h
+++ b/third_party/abseil-cpp/absl/hash/internal/city.h
@@ -56,6 +56,11 @@ 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);
@@ -66,11 +71,24 @@ 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
diff --git a/third_party/abseil-cpp/absl/hash/internal/hash.cc b/third_party/abseil-cpp/absl/hash/internal/hash.cc
index 11451e575c..b44ecb3a6b 100644
--- a/third_party/abseil-cpp/absl/hash/internal/hash.cc
+++ b/third_party/abseil-cpp/absl/hash/internal/hash.cc
@@ -18,12 +18,13 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace hash_internal {
-uint64_t MixingHashState::CombineLargeContiguousImpl32(
- uint64_t state, const unsigned char* first, size_t len) {
+uint64_t CityHashState::CombineLargeContiguousImpl32(uint64_t state,
+ const unsigned char* first,
+ size_t len) {
while (len >= PiecewiseChunkSize()) {
- state = Mix(state,
- hash_internal::CityHash32(reinterpret_cast<const char*>(first),
- PiecewiseChunkSize()));
+ state =
+ Mix(state, absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first),
+ PiecewiseChunkSize()));
len -= PiecewiseChunkSize();
first += PiecewiseChunkSize();
}
@@ -32,10 +33,13 @@ uint64_t MixingHashState::CombineLargeContiguousImpl32(
std::integral_constant<int, 4>{});
}
-uint64_t MixingHashState::CombineLargeContiguousImpl64(
- uint64_t state, const unsigned char* first, size_t len) {
+uint64_t CityHashState::CombineLargeContiguousImpl64(uint64_t state,
+ const unsigned char* first,
+ size_t len) {
while (len >= PiecewiseChunkSize()) {
- state = Mix(state, Hash64(first, PiecewiseChunkSize()));
+ state =
+ Mix(state, absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first),
+ PiecewiseChunkSize()));
len -= PiecewiseChunkSize();
first += PiecewiseChunkSize();
}
@@ -44,25 +48,7 @@ uint64_t MixingHashState::CombineLargeContiguousImpl64(
std::integral_constant<int, 8>{});
}
-ABSL_CONST_INIT const void* const MixingHashState::kSeed = &kSeed;
-
-// The salt array used by LowLevelHash. 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 kHashSalt[5] = {
- uint64_t{0x243F6A8885A308D3}, uint64_t{0x13198A2E03707344},
- uint64_t{0xA4093822299F31D0}, uint64_t{0x082EFA98EC4E6C89},
- uint64_t{0x452821E638D01377},
-};
-
-uint64_t MixingHashState::LowLevelHashImpl(const unsigned char* data,
- size_t len) {
- return LowLevelHash(data, len, Seed(), kHashSalt);
-}
+ABSL_CONST_INIT const void* const CityHashState::kSeed = &kSeed;
} // namespace hash_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/hash/internal/hash.h b/third_party/abseil-cpp/absl/hash/internal/hash.h
index b1e33caf4c..ae7a60cd55 100644
--- a/third_party/abseil-cpp/absl/hash/internal/hash.h
+++ b/third_party/abseil-cpp/absl/hash/internal/hash.h
@@ -21,7 +21,6 @@
#include <algorithm>
#include <array>
-#include <bitset>
#include <cmath>
#include <cstring>
#include <deque>
@@ -39,82 +38,27 @@
#include <utility>
#include <vector>
-#include "absl/base/config.h"
-#include "absl/base/internal/unaligned_access.h"
+#include "absl/base/internal/endian.h"
#include "absl/base/port.h"
#include "absl/container/fixed_array.h"
-#include "absl/hash/internal/city.h"
-#include "absl/hash/internal/low_level_hash.h"
#include "absl/meta/type_traits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/variant.h"
#include "absl/utility/utility.h"
+#include "absl/hash/internal/city.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace hash_internal {
+class PiecewiseCombiner;
+
// 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
@@ -181,7 +125,8 @@ class HashStateBase {
template <typename T>
static H combine_contiguous(H state, const T* data, size_t size);
- using AbslInternalPiecewiseCombiner = PiecewiseCombiner;
+ private:
+ friend class PiecewiseCombiner;
};
// is_uniquely_represented
@@ -252,6 +197,61 @@ H hash_bytes(H hash_state, const T& value) {
return H::combine_contiguous(std::move(hash_state), start, sizeof(value));
}
+// 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_;
+};
+
// -----------------------------------------------------------------------------
// AbslHashValue for Basic Types
// -----------------------------------------------------------------------------
@@ -380,7 +380,7 @@ template <typename H, typename... Ts>
// This SFINAE gets MSVC confused under some conditions. Let's just disable it
// for now.
H
-#else // _MSC_VER
+#else // _MSC_VER
typename std::enable_if<absl::conjunction<is_hashable<Ts>...>::value, H>::type
#endif // _MSC_VER
AbslHashValue(H hash_state, const std::tuple<Ts...>& t) {
@@ -413,7 +413,6 @@ 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`
@@ -490,9 +489,8 @@ typename std::enable_if<is_hashable<T>::value, H>::type AbslHashValue(
// AbslHashValue for hashing std::vector
//
-// Do not use this for vector<bool> on platforms that have a working
-// implementation of std::hash. It does not have a .data(), and a fallback for
-// std::hash<> is most likely faster.
+// Do not use this for vector<bool>. It does not have a .data(), and a fallback
+// for std::hash<> is most likely faster.
template <typename H, typename T, typename Allocator>
typename std::enable_if<is_hashable<T>::value && !std::is_same<T, bool>::value,
H>::type
@@ -502,27 +500,6 @@ AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
vector.size());
}
-#if defined(ABSL_IS_BIG_ENDIAN) && \
- (defined(__GLIBCXX__) || defined(__GLIBCPP__))
-// AbslHashValue for hashing std::vector<bool>
-//
-// std::hash in libstdc++ does not work correctly with vector<bool> on Big
-// Endian platforms therefore we need to implement a custom AbslHashValue for
-// it. More details on the bug:
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102531
-template <typename H, typename T, typename Allocator>
-typename std::enable_if<is_hashable<T>::value && std::is_same<T, bool>::value,
- H>::type
-AbslHashValue(H hash_state, const std::vector<T, Allocator>& vector) {
- typename H::AbslInternalPiecewiseCombiner combiner;
- for (const auto& i : vector) {
- unsigned char c = static_cast<unsigned char>(i);
- hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));
- }
- return H::combine(combiner.finalize(std::move(hash_state)), vector.size());
-}
-#endif
-
// -----------------------------------------------------------------------------
// AbslHashValue for Ordered Associative Containers
// -----------------------------------------------------------------------------
@@ -576,13 +553,6 @@ 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(
@@ -615,28 +585,9 @@ AbslHashValue(H hash_state, const absl::variant<T...>& v) {
// AbslHashValue for Other Types
// -----------------------------------------------------------------------------
-// AbslHashValue for hashing std::bitset is not defined on Little Endian
-// platforms, for the same reason as for vector<bool> (see std::vector above):
-// It does not expose the raw bytes, and a fallback to std::hash<> is most
-// likely faster.
-
-#if defined(ABSL_IS_BIG_ENDIAN) && \
- (defined(__GLIBCXX__) || defined(__GLIBCPP__))
-// AbslHashValue for hashing std::bitset
-//
-// std::hash in libstdc++ does not work correctly with std::bitset on Big Endian
-// platforms therefore we need to implement a custom AbslHashValue for it. More
-// details on the bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102531
-template <typename H, size_t N>
-H AbslHashValue(H hash_state, const std::bitset<N>& set) {
- typename H::AbslInternalPiecewiseCombiner combiner;
- for (int i = 0; i < N; i++) {
- unsigned char c = static_cast<unsigned char>(set[i]);
- hash_state = combiner.add_buffer(std::move(hash_state), &c, sizeof(c));
- }
- return H::combine(combiner.finalize(std::move(hash_state)), N);
-}
-#endif
+// AbslHashValue for hashing std::bitset is not defined, for the same reason as
+// for vector<bool> (see std::vector above): It does not expose the raw bytes,
+// and a fallback to std::hash<> is most likely faster.
// -----------------------------------------------------------------------------
@@ -756,8 +707,9 @@ template <typename T>
struct is_hashable
: std::integral_constant<bool, HashSelect::template Apply<T>::value> {};
-// MixingHashState
-class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
+// CityHashState
+class ABSL_DLL CityHashState
+ : public HashStateBase<CityHashState> {
// 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
@@ -776,23 +728,23 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
public:
// Move only
- MixingHashState(MixingHashState&&) = default;
- MixingHashState& operator=(MixingHashState&&) = default;
+ CityHashState(CityHashState&&) = default;
+ CityHashState& operator=(CityHashState&&) = default;
- // MixingHashState::combine_contiguous()
+ // CityHashState::combine_contiguous()
//
// Fundamental base case for hash recursion: mixes the given range of bytes
// into the hash state.
- static MixingHashState combine_contiguous(MixingHashState hash_state,
- const unsigned char* first,
- size_t size) {
- return MixingHashState(
+ static CityHashState combine_contiguous(CityHashState hash_state,
+ const unsigned char* first,
+ size_t size) {
+ return CityHashState(
CombineContiguousImpl(hash_state.state_, first, size,
std::integral_constant<int, sizeof(size_t)>{}));
}
- using MixingHashState::HashStateBase::combine_contiguous;
+ using CityHashState::HashStateBase::combine_contiguous;
- // MixingHashState::hash()
+ // CityHashState::hash()
//
// For performance reasons in non-opt mode, we specialize this for
// integral types.
@@ -804,24 +756,24 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
return static_cast<size_t>(Mix(Seed(), static_cast<uint64_t>(value)));
}
- // Overload of MixingHashState::hash()
+ // Overload of CityHashState::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(MixingHashState{}, value).state_);
+ return static_cast<size_t>(combine(CityHashState{}, 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.
- MixingHashState() : state_(Seed()) {}
+ CityHashState() : 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.
- MixingHashState(const MixingHashState&) = default;
+ CityHashState(const CityHashState&) = default;
- explicit MixingHashState(uint64_t state) : state_(state) {}
+ explicit CityHashState(uint64_t state) : state_(state) {}
// Implementation of the base case for combine_contiguous where we actually
// mix the bytes into the state.
@@ -834,7 +786,7 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
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
@@ -847,66 +799,31 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
size_t len);
// Reads 9 to 16 bytes from p.
- // The least significant 8 bytes are in .first, the rest (zero padded) bytes
- // are in .second.
+ // The first 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 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)};
+ uint64_t high = little_endian::Load64(p + len - 8);
+ return {little_endian::Load64(p), high >> (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) {
- 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;
+ return (static_cast<uint64_t>(little_endian::Load32(p + len - 4))
+ << (len - 4) * 8) |
+ little_endian::Load32(p);
}
// Reads 1 to 3 bytes from p. Zero pads to fill uint32_t.
static uint32_t Read1To3(const unsigned char* p, size_t len) {
- 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)));
+ return static_cast<uint32_t>((p[0]) | //
+ (p[len / 2] << (len / 2 * 8)) | //
+ (p[len - 1] << ((len - 1) * 8)));
}
ABSL_ATTRIBUTE_ALWAYS_INLINE static uint64_t Mix(uint64_t state, uint64_t v) {
-#if defined(__aarch64__)
- // On AArch64, calculating a 128-bit product is inefficient, because it
- // requires a sequence of two instructions to calculate the upper and lower
- // halves of the result.
- using MultType = uint64_t;
-#else
using MultType =
absl::conditional_t<sizeof(size_t) == 4, uint64_t, uint128>;
-#endif
// We do the addition in 64-bit space to make sure the 128-bit
// multiplication is fast. If we were to do it as MultType the compiler has
// to assume that the high word is non-zero and needs to perform 2
@@ -916,19 +833,6 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
return static_cast<uint64_t>(m ^ (m >> (sizeof(m) * 8 / 2)));
}
- // An extern to avoid bloat on a direct call to LowLevelHash() with fixed
- // values for both the seed and salt parameters.
- static uint64_t LowLevelHashImpl(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 LowLevelHashImpl(data, len);
-#else
- return hash_internal::CityHash64(reinterpret_cast<const char*>(data), len);
-#endif
- }
-
// Seed()
//
// A non-deterministic seed.
@@ -946,22 +850,15 @@ class ABSL_DLL MixingHashState : public HashStateBase<MixingHashState> {
// 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_;
};
-// MixingHashState::CombineContiguousImpl()
-inline uint64_t MixingHashState::CombineContiguousImpl(
+// CityHashState::CombineContiguousImpl()
+inline uint64_t CityHashState::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
@@ -971,7 +868,7 @@ inline uint64_t MixingHashState::CombineContiguousImpl(
if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
return CombineLargeContiguousImpl32(state, first, len);
}
- v = hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
+ v = absl::hash_internal::CityHash32(reinterpret_cast<const char*>(first), len);
} else if (len >= 4) {
v = Read4To8(first, len);
} else if (len > 0) {
@@ -983,18 +880,18 @@ inline uint64_t MixingHashState::CombineContiguousImpl(
return Mix(state, v);
}
-// Overload of MixingHashState::CombineContiguousImpl()
-inline uint64_t MixingHashState::CombineContiguousImpl(
+// Overload of CityHashState::CombineContiguousImpl()
+inline uint64_t CityHashState::CombineContiguousImpl(
uint64_t state, const unsigned char* first, size_t len,
std::integral_constant<int, 8> /* sizeof_size_t */) {
- // For large values we use LowLevelHash or CityHash depending on the platform,
- // for small ones we just use a multiplicative hash.
+ // For large values we use CityHash, for small ones we just use a
+ // multiplicative hash.
uint64_t v;
if (len > 16) {
if (ABSL_PREDICT_FALSE(len > PiecewiseChunkSize())) {
return CombineLargeContiguousImpl64(state, first, len);
}
- v = Hash64(first, len);
+ v = absl::hash_internal::CityHash64(reinterpret_cast<const char*>(first), len);
} else if (len > 8) {
auto p = Read9To16(first, len);
state = Mix(state, p.first);
@@ -1025,9 +922,7 @@ struct PoisonedHash : private AggregateBarrier {
template <typename T>
struct HashImpl {
- size_t operator()(const T& value) const {
- return MixingHashState::hash(value);
- }
+ size_t operator()(const T& value) const { return CityHashState::hash(value); }
};
template <typename T>
@@ -1060,15 +955,12 @@ H PiecewiseCombiner::add_buffer(H state, const unsigned char* data,
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;
- }
+ // Complete the buffer and hash it
+ 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()) {
diff --git a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc b/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc
deleted file mode 100644
index 6f9cb9c7bf..0000000000
--- a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.cc
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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/low_level_hash.h"
-
-#include "absl/base/internal/unaligned_access.h"
-#include "absl/numeric/bits.h"
-#include "absl/numeric/int128.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace hash_internal {
-
-static uint64_t Mix(uint64_t v0, uint64_t v1) {
-#if !defined(__aarch64__)
- // The default bit-mixer uses 64x64->128-bit multiplication.
- absl::uint128 p = v0;
- p *= v1;
- return absl::Uint128Low64(p) ^ absl::Uint128High64(p);
-#else
- // The default bit-mixer above would perform poorly on some ARM microarchs,
- // where calculating a 128-bit product requires a sequence of two
- // instructions with a high combined latency and poor throughput.
- // Instead, we mix bits using only 64-bit arithmetic, which is faster.
- uint64_t p = v0 ^ absl::rotl(v1, 40);
- p *= v1 ^ absl::rotl(v0, 39);
- return p ^ (p >> 11);
-#endif
-}
-
-uint64_t LowLevelHash(const void* data, size_t len, uint64_t seed,
- const uint64_t salt[]) {
- const 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 = Mix(a ^ salt[1], b ^ current_state);
- uint64_t cs1 = Mix(c ^ salt[2], d ^ current_state);
- current_state = (cs0 ^ cs1);
-
- uint64_t ds0 = Mix(e ^ salt[3], f ^ duplicated_state);
- uint64_t ds1 = Mix(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 = Mix(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 = Mix(a ^ salt[1], b ^ current_state);
- uint64_t z = salt[1] ^ starting_length;
- return Mix(w, z);
-}
-
-} // namespace hash_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.h b/third_party/abseil-cpp/absl/hash/internal/low_level_hash.h
deleted file mode 100644
index 439968aa98..0000000000
--- a/third_party/abseil-cpp/absl/hash/internal/low_level_hash.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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 LowLevelHash.
-//
-// LowLevelHash 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.
-//
-// It is closely based on a version of wyhash, but does not maintain or
-// guarantee future compatibility with it.
-
-#ifndef ABSL_HASH_INTERNAL_LOW_LEVEL_HASH_H_
-#define ABSL_HASH_INTERNAL_LOW_LEVEL_HASH_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 algorithm, we keep the API low-level, with as few dependencies as
-// possible.
-uint64_t LowLevelHash(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_LOW_LEVEL_HASH_H_
diff --git a/third_party/abseil-cpp/absl/hash/internal/low_level_hash_test.cc b/third_party/abseil-cpp/absl/hash/internal/low_level_hash_test.cc
deleted file mode 100644
index ae930b349b..0000000000
--- a/third_party/abseil-cpp/absl/hash/internal/low_level_hash_test.cc
+++ /dev/null
@@ -1,580 +0,0 @@
-// 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/low_level_hash.h"
-
-#include <cinttypes>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/strings/escaping.h"
-
-#define UPDATE_GOLDEN 0
-
-namespace {
-
-static const uint64_t kSalt[5] = {0xa0761d6478bd642f, 0xe7037ed1a0b428dbl,
- 0x8ebc6af09c88c6e3, 0x589965cc75374cc3l,
- 0x1d8e4e27c47d124f};
-
-TEST(LowLevelHashTest, VerifyGolden) {
- constexpr size_t kNumGoldenOutputs = 134;
- static struct {
- absl::string_view base64_data;
- uint64_t seed;
- } cases[] = {
- {"", uint64_t{0xec42b7ab404b8acb}},
- {"ICAg", uint64_t{0}},
- {"YWFhYQ==", uint64_t{0}},
- {"AQID", uint64_t{0}},
- {"AQIDBA==", uint64_t{0}},
- {"dGhpcmRfcGFydHl8d3loYXNofDY0", uint64_t{0}},
- {"Zw==", uint64_t{0xeeee074043a3ee0f}},
- {"xmk=", uint64_t{0x857902089c393de}},
- {"c1H/", uint64_t{0x993df040024ca3af}},
- {"SuwpzQ==", uint64_t{0xc4e4c2acea740e96}},
- {"uqvy++M=", uint64_t{0x6a214b3db872d0cf}},
- {"RnzCVPgb", uint64_t{0x44343db6a89dba4d}},
- {"6OeNdlouYw==", uint64_t{0x77b5d6d1ae1dd483}},
- {"M5/JmmYyDbc=", uint64_t{0x89ab8ecb44d221f1}},
- {"MVijWiVdBRdY", uint64_t{0x60244b17577ca81b}},
- {"6V7Uq7LNxpu0VA==", uint64_t{0x59a08dcee0717067}},
- {"EQ6CdEEhPdyHcOk=", uint64_t{0xf5f20db3ade57396}},
- {"PqFB4fxnPgF+l+rc", uint64_t{0xbf8dee0751ad3efb}},
- {"a5aPOFwq7LA7+zKvPA==", uint64_t{0x6b7a06b268d63e30}},
- {"VOwY21wCGv5D+/qqOvs=", uint64_t{0xb8c37f0ae0f54c82}},
- {"KdHmBTx8lHXYvmGJ+Vy7", uint64_t{0x9fcbed0c38e50eef}},
- {"qJkPlbHr8bMF7/cA6aE65Q==", uint64_t{0x2af4bade1d8e3a1d}},
- {"ygvL0EhHZL0fIx6oHHtkxRQ=", uint64_t{0x714e3aa912da2f2c}},
- {"c1rFXkt5YztwZCQRngncqtSs", uint64_t{0xf5ee75e3cbb82c1c}},
- {"8hsQrzszzeNQSEcVXLtvIhm6mw==", uint64_t{0x620e7007321b93b9}},
- {"ffUL4RocfyP4KfikGxO1yk7omDI=", uint64_t{0xc08528cac2e551fc}},
- {"OOB5TT00vF9Od/rLbAWshiErqhpV", uint64_t{0x6a1debf9cc3ad39}},
- {"or5wtXM7BFzTNpSzr+Lw5J5PMhVJ/Q==", uint64_t{0x7e0a3c88111fc226}},
- {"gk6pCHDUsoopVEiaCrzVDhioRKxb844=", uint64_t{0x1301fef15df39edb}},
- {"TNctmwlC5QbEM6/No4R/La3UdkfeMhzs", uint64_t{0x64e181f3d5817ab}},
- {"SsQw9iAjhWz7sgcE9OwLuSC6hsM+BfHs2Q==", uint64_t{0xafafc44961078ecb}},
- {"ZzO3mVCj4xTT2TT3XqDyEKj2BZQBvrS8RHg=", uint64_t{0x4f7bb45549250094}},
- {"+klp5iPQGtppan5MflEls0iEUzqU+zGZkDJX", uint64_t{0xa30061abaa2818c}},
- {"RO6bvOnlJc8I9eniXlNgqtKy0IX6VNg16NRmgg==",
- uint64_t{0xd902ee3e44a5705f}},
- {"ZJjZqId1ZXBaij9igClE3nyliU5XWdNRrayGlYA=", uint64_t{0x316d36da516f583}},
- {"7BfkhfGMDGbxfMB8uyL85GbaYQtjr2K8g7RpLzr/",
- uint64_t{0x402d83f9f834f616}},
- {"rycWk6wHH7htETQtje9PidS2YzXBx+Qkg2fY7ZYS7A==",
- uint64_t{0x9c604164c016b72c}},
- {"RTkC2OUK+J13CdGllsH0H5WqgspsSa6QzRZouqx6pvI=",
- uint64_t{0x3f4507e01f9e73ba}},
- {"tKjKmbLCNyrLCM9hycOAXm4DKNpM12oZ7dLTmUx5iwAi",
- uint64_t{0xc3fe0d5be8d2c7c7}},
- {"VprUGNH+5NnNRaORxgH/ySrZFQFDL+4VAodhfBNinmn8cg==",
- uint64_t{0x531858a40bfa7ea1}},
- {"gc1xZaY+q0nPcUvOOnWnT3bqfmT/geth/f7Dm2e/DemMfk4=",
- uint64_t{0x86689478a7a7e8fa}},
- {"Mr35fIxqx1ukPAL0su1yFuzzAU3wABCLZ8+ZUFsXn47UmAph",
- uint64_t{0x4ec948b8e7f27288}},
- {"A9G8pw2+m7+rDtWYAdbl8tb2fT7FFo4hLi2vAsa5Y8mKH3CX3g==",
- uint64_t{0xce46c7213c10032}},
- {"DFaJGishGwEHDdj9ixbCoaTjz9KS0phLNWHVVdFsM93CvPft3hM=",
- uint64_t{0xf63e96ee6f32a8b6}},
- {"7+Ugx+Kr3aRNgYgcUxru62YkTDt5Hqis+2po81hGBkcrJg4N0uuy",
- uint64_t{0x1cfe85e65fc5225}},
- {"H2w6O8BUKqu6Tvj2xxaecxEI2wRgIgqnTTG1WwOgDSINR13Nm4d4Vg==",
- uint64_t{0x45c474f1cee1d2e8}},
- {"1XBMnIbqD5jy65xTDaf6WtiwtdtQwv1dCVoqpeKj+7cTR1SaMWMyI04=",
- uint64_t{0x6e024e14015f329c}},
- {"znZbdXG2TSFrKHEuJc83gPncYpzXGbAebUpP0XxzH0rpe8BaMQ17nDbt",
- uint64_t{0x760c40502103ae1c}},
- {"ylu8Atu13j1StlcC1MRMJJXIl7USgDDS22HgVv0WQ8hx/8pNtaiKB17hCQ==",
- uint64_t{0x17fd05c3c560c320}},
- {"M6ZVVzsd7vAvbiACSYHioH/440dp4xG2mLlBnxgiqEvI/aIEGpD0Sf4VS0g=",
- uint64_t{0x8b34200a6f8e90d9}},
- {"li3oFSXLXI+ubUVGJ4blP6mNinGKLHWkvGruun85AhVn6iuMtocbZPVhqxzn",
- uint64_t{0x6be89e50818bdf69}},
- {"kFuQHuUCqBF3Tc3hO4dgdIp223ShaCoog48d5Do5zMqUXOh5XpGK1t5XtxnfGA==",
- uint64_t{0xfb389773315b47d8}},
- {"jWmOad0v0QhXVJd1OdGuBZtDYYS8wBVHlvOeTQx9ZZnm8wLEItPMeihj72E0nWY=",
- uint64_t{0x4f2512a23f61efee}},
- {"z+DHU52HaOQdW4JrZwDQAebEA6rm13Zg/9lPYA3txt3NjTBqFZlOMvTRnVzRbl23",
- uint64_t{0x59ccd92fc16c6fda}},
- {"MmBiGDfYeTayyJa/tVycg+rN7f9mPDFaDc+23j0TlW9094er0ADigsl4QX7V3gG/qw==",
- uint64_t{0x25c5a7f5bd330919}},
- {"774RK+9rOL4iFvs1q2qpo/JVc/I39buvNjqEFDtDvyoB0FXxPI2vXqOrk08VPfIHkmU=",
- uint64_t{0x51df4174d34c97d7}},
- {"+slatXiQ7/2lK0BkVUI1qzNxOOLP3I1iK6OfHaoxgqT63FpzbElwEXSwdsryq3UlHK0I",
- uint64_t{0x80ce6d76f89cb57}},
- {"64mVTbQ47dHjHlOHGS/hjJwr/"
- "K2frCNpn87exOqMzNUVYiPKmhCbfS7vBUce5tO6Ec9osQ==",
- uint64_t{0x20961c911965f684}},
- {"fIsaG1r530SFrBqaDj1kqE0AJnvvK8MNEZbII2Yw1OK77v0V59xabIh0B5axaz/"
- "+a2V5WpA=",
- uint64_t{0x4e5b926ec83868e7}},
- {"PGih0zDEOWCYGxuHGDFu9Ivbff/"
- "iE7BNUq65tycTR2R76TerrXALRosnzaNYO5fjFhTi+CiS",
- uint64_t{0x3927b30b922eecef}},
- {"RnpA/"
- "zJnEnnLjmICORByRVb9bCOgxF44p3VMiW10G7PvW7IhwsWajlP9kIwNA9FjAD2GoQHk2Q="
- "=",
- uint64_t{0xbd0291284a49b61c}},
- {"qFklMceaTHqJpy2qavJE+EVBiNFOi6OxjOA3LeIcBop1K7w8xQi3TrDk+"
- "BrWPRIbfprszSaPfrI=",
- uint64_t{0x73a77c575bcc956}},
- {"cLbfUtLl3EcQmITWoTskUR8da/VafRDYF/ylPYwk7/"
- "zazk6ssyrzxMN3mmSyvrXR2yDGNZ3WDrTT",
- uint64_t{0x766a0e2ade6d09a6}},
- {"s/"
- "Jf1+"
- "FbsbCpXWPTUSeWyMH6e4CvTFvPE5Fs6Z8hvFITGyr0dtukHzkI84oviVLxhM1xMxrMAy1db"
- "w==",
- uint64_t{0x2599f4f905115869}},
- {"FvyQ00+j7nmYZVQ8hI1Edxd0AWplhTfWuFGiu34AK5X8u2hLX1bE97sZM0CmeLe+"
- "7LgoUT1fJ/axybE=",
- uint64_t{0xd8256e5444d21e53}},
- {"L8ncxMaYLBH3g9buPu8hfpWZNlOF7nvWLNv9IozH07uQsIBWSKxoPy8+"
- "LW4tTuzC6CIWbRGRRD1sQV/4",
- uint64_t{0xf664a91333fb8dfd}},
- {"CDK0meI07yrgV2kQlZZ+"
- "wuVqhc2NmzqeLH7bmcA6kchsRWFPeVF5Wqjjaj556ABeUoUr3yBmfU3kWOakkg==",
- uint64_t{0x9625b859be372cd1}},
- {"d23/vc5ONh/"
- "HkMiq+gYk4gaCNYyuFKwUkvn46t+dfVcKfBTYykr4kdvAPNXGYLjM4u1YkAEFpJP+"
- "nX7eOvs=",
- uint64_t{0x7b99940782e29898}},
- {"NUR3SRxBkxTSbtQORJpu/GdR6b/h6sSGfsMj/KFd99ahbh+9r7LSgSGmkGVB/"
- "mGoT0pnMTQst7Lv2q6QN6Vm",
- uint64_t{0x4fe12fa5383b51a8}},
- {"2BOFlcI3Z0RYDtS9T9Ie9yJoXlOdigpPeeT+CRujb/"
- "O39Ih5LPC9hP6RQk1kYESGyaLZZi3jtabHs7DiVx/VDg==",
- uint64_t{0xe2ccb09ac0f5b4b6}},
- {"FF2HQE1FxEvWBpg6Z9zAMH+Zlqx8S1JD/"
- "wIlViL6ZDZY63alMDrxB0GJQahmAtjlm26RGLnjW7jmgQ4Ie3I+014=",
- uint64_t{0x7d0a37adbd7b753b}},
- {"tHmO7mqVL/PX11nZrz50Hc+M17Poj5lpnqHkEN+4bpMx/"
- "YGbkrGOaYjoQjgmt1X2QyypK7xClFrjeWrCMdlVYtbW",
- uint64_t{0xd3ae96ef9f7185f2}},
- {"/WiHi9IQcxRImsudkA/KOTqGe8/"
- "gXkhKIHkjddv5S9hi02M049dIK3EUyAEjkjpdGLUs+BN0QzPtZqjIYPOgwsYE9g==",
- uint64_t{0x4fb88ea63f79a0d8}},
- {"qds+1ExSnU11L4fTSDz/QE90g4Jh6ioqSh3KDOTOAo2pQGL1k/"
- "9CCC7J23YF27dUTzrWsCQA2m4epXoCc3yPHb3xElA=",
- uint64_t{0xed564e259bb5ebe9}},
- {"8FVYHx40lSQPTHheh08Oq0/"
- "pGm2OlG8BEf8ezvAxHuGGdgCkqpXIueJBF2mQJhTfDy5NncO8ntS7vaKs7sCNdDaNGOEi",
- uint64_t{0x3e3256b60c428000}},
- {"4ZoEIrJtstiCkeew3oRzmyJHVt/pAs2pj0HgHFrBPztbQ10NsQ/"
- "lM6DM439QVxpznnBSiHMgMQJhER+70l72LqFTO1JiIQ==",
- uint64_t{0xfb05bad59ec8705}},
- {"hQPtaYI+wJyxXgwD5n8jGIKFKaFA/"
- "P83KqCKZfPthnjwdOFysqEOYwAaZuaaiv4cDyi9TyS8hk5cEbNP/jrI7q6pYGBLbsM=",
- uint64_t{0xafdc251dbf97b5f8}},
- {"S4gpMSKzMD7CWPsSfLeYyhSpfWOntyuVZdX1xSBjiGvsspwOZcxNKCRIOqAA0moUfOh3I5+"
- "juQV4rsqYElMD/gWfDGpsWZKQ",
- uint64_t{0x10ec9c92ddb5dcbc}},
- {"oswxop+"
- "bthuDLT4j0PcoSKby4LhF47ZKg8K17xxHf74UsGCzTBbOz0MM8hQEGlyqDT1iUiAYnaPaUp"
- "L2mRK0rcIUYA4qLt5uOw==",
- uint64_t{0x9a767d5822c7dac4}},
- {"0II/"
- "697p+"
- "BtLSjxj5989OXI004TogEb94VUnDzOVSgMXie72cuYRvTFNIBgtXlKfkiUjeqVpd4a+"
- "n5bxNOD1TGrjQtzKU5r7obo=",
- uint64_t{0xee46254080d6e2db}},
- {"E84YZW2qipAlMPmctrg7TKlwLZ68l4L+c0xRDUfyyFrA4MAti0q9sHq3TDFviH0Y+"
- "Kq3tEE5srWFA8LM9oomtmvm5PYxoaarWPLc",
- uint64_t{0xbbb669588d8bf398}},
- {"x3pa4HIElyZG0Nj7Vdy9IdJIR4izLmypXw5PCmZB5y68QQ4uRaVVi3UthsoJROvbjDJkP2D"
- "Q6L/eN8pFeLFzNPKBYzcmuMOb5Ull7w==",
- uint64_t{0xdc2afaa529beef44}},
- {"jVDKGYIuWOP/"
- "QKLdd2wi8B2VJA8Wh0c8PwrXJVM8FOGM3voPDVPyDJOU6QsBDPseoR8uuKd19OZ/"
- "zAvSCB+zlf6upAsBlheUKgCfKww=",
- uint64_t{0xf1f67391d45013a8}},
- {"mkquunhmYe1aR2wmUz4vcvLEcKBoe6H+kjUok9VUn2+eTSkWs4oDDtJvNCWtY5efJwg/"
- "j4PgjRYWtqnrCkhaqJaEvkkOwVfgMIwF3e+d",
- uint64_t{0x16fce2b8c65a3429}},
- {"fRelvKYonTQ+s+rnnvQw+JzGfFoPixtna0vzcSjiDqX5s2Kg2//"
- "UGrK+AVCyMUhO98WoB1DDbrsOYSw2QzrcPe0+3ck9sePvb+Q/IRaHbw==",
- uint64_t{0xf4b096699f49fe67}},
- {"DUwXFJzagljo44QeJ7/"
- "6ZKw4QXV18lhkYT2jglMr8WB3CHUU4vdsytvw6AKv42ZcG6fRkZkq9fpnmXy6xG0aO3WPT1"
- "eHuyFirAlkW+zKtwg=",
- uint64_t{0xca584c4bc8198682}},
- {"cYmZCrOOBBongNTr7e4nYn52uQUy2mfe48s50JXx2AZ6cRAt/"
- "xRHJ5QbEoEJOeOHsJyM4nbzwFm++SlT6gFZZHJpkXJ92JkR86uS/eV1hJUR",
- uint64_t{0xed269fc3818b6aad}},
- {"EXeHBDfhwzAKFhsMcH9+2RHwV+mJaN01+9oacF6vgm8mCXRd6jeN9U2oAb0of5c5cO4i+"
- "Vb/LlHZSMI490SnHU0bejhSCC2gsC5d2K30ER3iNA==",
- uint64_t{0x33f253cbb8fe66a8}},
- {"FzkzRYoNjkxFhZDso94IHRZaJUP61nFYrh5MwDwv9FNoJ5jyNCY/"
- "eazPZk+tbmzDyJIGw2h3GxaWZ9bSlsol/vK98SbkMKCQ/wbfrXRLcDzdd/8=",
- uint64_t{0xd0b76b2c1523d99c}},
- {"Re4aXISCMlYY/XsX7zkIFR04ta03u4zkL9dVbLXMa/q6hlY/CImVIIYRN3VKP4pnd0AUr/"
- "ugkyt36JcstAInb4h9rpAGQ7GMVOgBniiMBZ/MGU7H",
- uint64_t{0xfd28f0811a2a237f}},
- {"ueLyMcqJXX+MhO4UApylCN9WlTQ+"
- "ltJmItgG7vFUtqs2qNwBMjmAvr5u0sAKd8jpzV0dDPTwchbIeAW5zbtkA2NABJV6hFM48ib"
- "4/J3A5mseA3cS8w==",
- uint64_t{0x6261fb136482e84}},
- {"6Si7Yi11L+jZMkwaN+GUuzXMrlvEqviEkGOilNq0h8TdQyYKuFXzkYc/"
- "q74gP3pVCyiwz9KpVGMM9vfnq36riMHRknkmhQutxLZs5fbmOgEO69HglCU=",
- uint64_t{0x458efc750bca7c3a}},
- {"Q6AbOofGuTJOegPh9Clm/"
- "9crtUMQqylKrTc1fhfJo1tqvpXxhU4k08kntL1RG7woRnFrVh2UoMrL1kjin+s9CanT+"
- "y4hHwLqRranl9FjvxfVKm3yvg68",
- uint64_t{0xa7e69ff84e5e7c27}},
- {"ieQEbIPvqY2YfIjHnqfJiO1/MIVRk0RoaG/WWi3kFrfIGiNLCczYoklgaecHMm/"
- "1sZ96AjO+a5stQfZbJQwS7Sc1ODABEdJKcTsxeW2hbh9A6CFzpowP1A==",
- uint64_t{0x3c59bfd0c29efe9e}},
- {"zQUv8hFB3zh2GGl3KTvCmnfzE+"
- "SUgQPVaSVIELFX5H9cE3FuVFGmymkPQZJLAyzC90Cmi8GqYCvPqTuAAB//"
- "XTJxy4bCcVArgZG9zJXpjowpNBfr3ngWrSE=",
- uint64_t{0x10befacc6afd298d}},
- {"US4hcC1+op5JKGC7eIs8CUgInjKWKlvKQkapulxW262E/"
- "B2ye79QxOexf188u2mFwwe3WTISJHRZzS61IwljqAWAWoBAqkUnW8SHmIDwHUP31J0p5sGd"
- "P47L",
- uint64_t{0x41d5320b0a38efa7}},
- {"9bHUWFna2LNaGF6fQLlkx1Hkt24nrkLE2CmFdWgTQV3FFbUe747SSqYw6ebpTa07MWSpWRP"
- "sHesVo2B9tqHbe7eQmqYebPDFnNqrhSdZwFm9arLQVs+7a3Ic6A==",
- uint64_t{0x58db1c7450fe17f3}},
- {"Kb3DpHRUPhtyqgs3RuXjzA08jGb59hjKTOeFt1qhoINfYyfTt2buKhD6YVffRCPsgK9SeqZ"
- "qRPJSyaqsa0ovyq1WnWW8jI/NhvAkZTVHUrX2pC+cD3OPYT05Dag=",
- uint64_t{0x6098c055a335b7a6}},
- {"gzxyMJIPlU+bJBwhFUCHSofZ/"
- "319LxqMoqnt3+L6h2U2+ZXJCSsYpE80xmR0Ta77Jq54o92SMH87HV8dGOaCTuAYF+"
- "lDL42SY1P316Cl0sZTS2ow3ZqwGbcPNs/1",
- uint64_t{0x1bbacec67845a801}},
- {"uR7V0TW+FGVMpsifnaBAQ3IGlr1wx5sKd7TChuqRe6OvUXTlD4hKWy8S+"
- "8yyOw8lQabism19vOQxfmocEOW/"
- "vzY0pEa87qHrAZy4s9fH2Bltu8vaOIe+agYohhYORQ==",
- uint64_t{0xc419cfc7442190}},
- {"1UR5eoo2aCwhacjZHaCh9bkOsITp6QunUxHQ2SfeHv0imHetzt/"
- "Z70mhyWZBalv6eAx+YfWKCUib2SHDtz/"
- "A2dc3hqUWX5VfAV7FQsghPUAtu6IiRatq4YSLpDvKZBQ=",
- uint64_t{0xc95e510d94ba270c}},
- {"opubR7H63BH7OtY+Avd7QyQ25UZ8kLBdFDsBTwZlY6gA/"
- "u+x+"
- "czC9AaZMgmQrUy15DH7YMGsvdXnviTtI4eVI4aF1H9Rl3NXMKZgwFOsdTfdcZeeHVRzBBKX"
- "8jUfh1il",
- uint64_t{0xff1ae05c98089c3f}},
- {"DC0kXcSXtfQ9FbSRwirIn5tgPri0sbzHSa78aDZVDUKCMaBGyFU6BmrulywYX8yzvwprdLs"
- "oOwTWN2wMjHlPDqrvVHNEjnmufRDblW+nSS+xtKNs3N5xsxXdv6JXDrAB/Q==",
- uint64_t{0x90c02b8dceced493}},
- {"BXRBk+3wEP3Lpm1y75wjoz+PgB0AMzLe8tQ1AYU2/"
- "oqrQB2YMC6W+9QDbcOfkGbeH+b7IBkt/"
- "gwCMw2HaQsRFEsurXtcQ3YwRuPz5XNaw5NAvrNa67Fm7eRzdE1+hWLKtA8=",
- uint64_t{0x9f8a76697ab1aa36}},
- {"RRBSvEGYnzR9E45Aps/+WSnpCo/X7gJLO4DRnUqFrJCV/kzWlusLE/"
- "6ZU6RoUf2ROwcgEvUiXTGjLs7ts3t9SXnJHxC1KiOzxHdYLMhVvgNd3hVSAXODpKFSkVXND"
- "55G2L1W",
- uint64_t{0x6ba1bf3d811a531d}},
- {"jeh6Qazxmdi57pa9S3XSnnZFIRrnc6s8QLrah5OX3SB/V2ErSPoEAumavzQPkdKF1/"
- "SfvmdL+qgF1C+Yawy562QaFqwVGq7+tW0yxP8FStb56ZRgNI4IOmI30s1Ei7iops9Uuw==",
- uint64_t{0x6a418974109c67b4}},
- {"6QO5nnDrY2/"
- "wrUXpltlKy2dSBcmK15fOY092CR7KxAjNfaY+"
- "aAmtWbbzQk3MjBg03x39afSUN1fkrWACdyQKRaGxgwq6MGNxI6W+8DLWJBHzIXrntrE/"
- "ml6fnNXEpxplWJ1vEs4=",
- uint64_t{0x8472f1c2b3d230a3}},
- {"0oPxeEHhqhcFuwonNfLd5jF3RNATGZS6NPoS0WklnzyokbTqcl4BeBkMn07+fDQv83j/"
- "BpGUwcWO05f3+DYzocfnizpFjLJemFGsls3gxcBYxcbqWYev51tG3lN9EvRE+X9+Pwww",
- uint64_t{0x5e06068f884e73a7}},
- {"naSBSjtOKgAOg8XVbR5cHAW3Y+QL4Pb/JO9/"
- "oy6L08wvVRZqo0BrssMwhzBP401Um7A4ppAupbQeJFdMrysY34AuSSNvtNUy5VxjNECwiNt"
- "gwYHw7yakDUv8WvonctmnoSPKENegQg==",
- uint64_t{0x55290b1a8f170f59}},
- {"vPyl8DxVeRe1OpilKb9KNwpGkQRtA94UpAHetNh+"
- "95V7nIW38v7PpzhnTWIml5kw3So1Si0TXtIUPIbsu32BNhoH7QwFvLM+"
- "JACgSpc5e3RjsL6Qwxxi11npwxRmRUqATDeMUfRAjxg=",
- uint64_t{0x5501cfd83dfe706a}},
- {"QC9i2GjdTMuNC1xQJ74ngKfrlA4w3o58FhvNCltdIpuMhHP1YsDA78scQPLbZ3OCUgeQguY"
- "f/vw6zAaVKSgwtaykqg5ka/4vhz4hYqWU5ficdXqClHl+zkWEY26slCNYOM5nnDlly8Cj",
- uint64_t{0xe43ed13d13a66990}},
- {"7CNIgQhAHX27nxI0HeB5oUTnTdgKpRDYDKwRcXfSFGP1XeT9nQF6WKCMjL1tBV6x7KuJ91G"
- "Zz11F4c+8s+MfqEAEpd4FHzamrMNjGcjCyrVtU6y+7HscMVzr7Q/"
- "ODLcPEFztFnwjvCjmHw==",
- uint64_t{0xdf43bc375cf5283f}},
- {"Qa/hC2RPXhANSospe+gUaPfjdK/yhQvfm4cCV6/pdvCYWPv8p1kMtKOX3h5/"
- "8oZ31fsmx4Axphu5qXJokuhZKkBUJueuMpxRyXpwSWz2wELx5glxF7CM0Fn+"
- "OevnkhUn5jsPlG2r5jYlVn8=",
- uint64_t{0x8112b806d288d7b5}},
- {"kUw/0z4l3a89jTwN5jpG0SHY5km/"
- "IVhTjgM5xCiPRLncg40aqWrJ5vcF891AOq5hEpSq0bUCJUMFXgct7kvnys905HjerV7Vs1G"
- "y84tgVJ70/2+pAZTsB/PzNOE/G6sOj4+GbTzkQu819OLB",
- uint64_t{0xd52a18abb001cb46}},
- {"VDdfSDbO8Tdj3T5W0XM3EI7iHh5xpIutiM6dvcJ/fhe23V/srFEkDy5iZf/"
- "VnA9kfi2C79ENnFnbOReeuZW1b3MUXB9lgC6U4pOTuC+"
- "jHK3Qnpyiqzj7h3ISJSuo2pob7vY6VHZo6Fn7exEqHg==",
- uint64_t{0xe12b76a2433a1236}},
- {"Ldfvy3ORdquM/R2fIkhH/ONi69mcP1AEJ6n/"
- "oropwecAsLJzQSgezSY8bEiEs0VnFTBBsW+RtZY6tDj03fnb3amNUOq1b7jbqyQkL9hpl+"
- "2Z2J8IaVSeownWl+bQcsR5/xRktIMckC5AtF4YHfU=",
- uint64_t{0x175bf7319cf1fa00}},
- {"BrbNpb42+"
- "VzZAjJw6QLirXzhweCVRfwlczzZ0VX2xluskwBqyfnGovz5EuX79JJ31VNXa5hTkAyQat3l"
- "YKRADTdAdwE5PqM1N7YaMqqsqoAAAeuYVXuk5eWCykYmClNdSspegwgCuT+403JigBzi",
- uint64_t{0xd63d57b3f67525ae}},
- {"gB3NGHJJvVcuPyF0ZSvHwnWSIfmaI7La24VMPQVoIIWF7Z74NltPZZpx2f+cocESM+"
- "ILzQW9p+BC8x5IWz7N4Str2WLGKMdgmaBfNkEhSHQDU0IJEOnpUt0HmjhFaBlx0/"
- "LTmhua+rQ6Wup8ezLwfg==",
- uint64_t{0x933faea858832b73}},
- {"hTKHlRxx6Pl4gjG+6ksvvj0CWFicUg3WrPdSJypDpq91LUWRni2KF6+"
- "81ZoHBFhEBrCdogKqeK+hy9bLDnx7g6rAFUjtn1+cWzQ2YjiOpz4+"
- "ROBB7lnwjyTGWzJD1rXtlso1g2qVH8XJVigC5M9AIxM=",
- uint64_t{0x53d061e5f8e7c04f}},
- {"IWQBelSQnhrr0F3BhUpXUIDauhX6f95Qp+A0diFXiUK7irwPG1oqBiqHyK/SH/"
- "9S+"
- "rln9DlFROAmeFdH0OCJi2tFm4afxYzJTFR4HnR4cG4x12JqHaZLQx6iiu6CE3rtWBVz99oA"
- "wCZUOEXIsLU24o2Y",
- uint64_t{0xdb4124556dd515e0}},
- {"TKo+l+"
- "1dOXdLvIrFqeLaHdm0HZnbcdEgOoLVcGRiCbAMR0j5pIFw8D36tefckAS1RCFOH5IgP8yiF"
- "T0Gd0a2hI3+"
- "fTKA7iK96NekxWeoeqzJyctc6QsoiyBlkZerRxs5RplrxoeNg29kKDTM0K94mnhD9g==",
- uint64_t{0x4fb31a0dd681ee71}},
- {"YU4e7G6EfQYvxCFoCrrT0EFgVLHFfOWRTJQJ5gxM3G2b+"
- "1kJf9YPrpsxF6Xr6nYtS8reEEbDoZJYqnlk9lXSkVArm88Cqn6d25VCx3+"
- "49MqC0trIlXtb7SXUUhwpJK16T0hJUfPH7s5cMZXc6YmmbFuBNPE=",
- uint64_t{0x27cc72eefa138e4c}},
- {"/I/"
- "eImMwPo1U6wekNFD1Jxjk9XQVi1D+"
- "FPdqcHifYXQuP5aScNQfxMAmaPR2XhuOQhADV5tTVbBKwCDCX4E3jcDNHzCiPvViZF1W27t"
- "xaf2BbFQdwKrNCmrtzcluBFYu0XZfc7RU1RmxK/RtnF1qHsq/O4pp",
- uint64_t{0x44bc2dfba4bd3ced}},
- {"CJTT9WGcY2XykTdo8KodRIA29qsqY0iHzWZRjKHb9alwyJ7RZAE3V5Juv4MY3MeYEr1EPCC"
- "MxO7yFXqT8XA8YTjaMp3bafRt17Pw8JC4iKJ1zN+WWKOESrj+"
- "3aluGQqn8z1EzqY4PH7rLG575PYeWsP98BugdA==",
- uint64_t{0x242da1e3a439bed8}},
- {"ZlhyQwLhXQyIUEnMH/"
- "AEW27vh9xrbNKJxpWGtrEmKhd+nFqAfbeNBQjW0SfG1YI0xQkQMHXjuTt4P/"
- "EpZRtA47ibZDVS8TtaxwyBjuIDwqcN09eCtpC+Ls+"
- "vWDTLmBeDM3u4hmzz4DQAYsLiZYSJcldg9Q3wszw=",
- uint64_t{0xdc559c746e35c139}},
- {"v2KU8y0sCrBghmnm8lzGJlwo6D6ObccAxCf10heoDtYLosk4ztTpLlpSFEyu23MLA1tJkcg"
- "Rko04h19QMG0mOw/"
- "wc93EXAweriBqXfvdaP85sZABwiKO+6rtS9pacRVpYYhHJeVTQ5NzrvBvi1huxAr+"
- "xswhVMfL",
- uint64_t{0xd0b0350275b9989}},
- {"QhKlnIS6BuVCTQsnoE67E/"
- "yrgogE8EwO7xLaEGei26m0gEU4OksefJgppDh3X0x0Cs78Dr9IHK5b977CmZlrTRmwhlP8p"
- "M+UzXPNRNIZuN3ntOum/QhUWP8SGpirheXENWsXMQ/"
- "nxtxakyEtrNkKk471Oov9juP8oQ==",
- uint64_t{0xb04489e41d17730c}},
- {"/ZRMgnoRt+Uo6fUPr9FqQvKX7syhgVqWu+"
- "WUSsiQ68UlN0efSP6Eced5gJZL6tg9gcYJIkhjuQNITU0Q3TjVAnAcobgbJikCn6qZ6pRxK"
- "BY4MTiAlfGD3T7R7hwJwx554MAy++Zb/YUFlnCaCJiwQMnowF7aQzwYFCo=",
- uint64_t{0x2217285eb4572156}},
- {"NB7tU5fNE8nI+SXGfipc7sRkhnSkUF1krjeo6k+8FITaAtdyz+"
- "o7mONgXmGLulBPH9bEwyYhKNVY0L+njNQrZ9YC2aXsFD3PdZsxAFaBT3VXEzh+"
- "NGBTjDASNL3mXyS8Yv1iThGfHoY7T4aR0NYGJ+k+pR6f+KrPC96M",
- uint64_t{0x12c2e8e68aede73b}},
- {"8T6wrqCtEO6/rwxF6lvMeyuigVOLwPipX/FULvwyu+1wa5sQGav/"
- "2FsLHUVn6cGSi0LlFwLewGHPFJDLR0u4t7ZUyM//"
- "x6da0sWgOa5hzDqjsVGmjxEHXiaXKW3i4iSZNuxoNbMQkIbVML+"
- "DkYu9ND0O2swg4itGeVSzXA==",
- uint64_t{0x4d612125bdc4fd00}},
- {"Ntf1bMRdondtMv1CYr3G80iDJ4WSAlKy5H34XdGruQiCrnRGDBa+"
- "eUi7vKp4gp3BBcVGl8eYSasVQQjn7MLvb3BjtXx6c/"
- "bCL7JtpzQKaDnPr9GWRxpBXVxKREgMM7d8lm35EODv0w+"
- "hQLfVSh8OGs7fsBb68nNWPLeeSOo=",
- uint64_t{0x81826b553954464e}},
- {"VsSAw72Ro6xks02kaiLuiTEIWBC5bgqr4WDnmP8vglXzAhixk7td926rm9jNimL+"
- "kroPSygZ9gl63aF5DCPOACXmsbmhDrAQuUzoh9ZKhWgElLQsrqo1KIjWoZT5b5QfVUXY9lS"
- "IBg3U75SqORoTPq7HalxxoIT5diWOcJQi",
- uint64_t{0xc2e5d345dc0ddd2d}},
- {"j+loZ+C87+"
- "bJxNVebg94gU0mSLeDulcHs84tQT7BZM2rzDSLiCNxUedHr1ZWJ9ejTiBa0dqy2I2ABc++"
- "xzOLcv+//YfibtjKtYggC6/3rv0XCc7xu6d/"
- "O6xO+XOBhOWAQ+IHJVHf7wZnDxIXB8AUHsnjEISKj7823biqXjyP3g==",
- uint64_t{0x3da6830a9e32631e}},
- {"f3LlpcPElMkspNtDq5xXyWU62erEaKn7RWKlo540gR6mZsNpK1czV/"
- "sOmqaq8XAQLEn68LKj6/"
- "cFkJukxRzCa4OF1a7cCAXYFp9+wZDu0bw4y63qbpjhdCl8GO6Z2lkcXy7KOzbPE01ukg7+"
- "gN+7uKpoohgAhIwpAKQXmX5xtd0=",
- uint64_t{0xc9ae5c8759b4877a}},
- };
-
-#if defined(ABSL_IS_BIG_ENDIAN)
- constexpr uint64_t kGolden[kNumGoldenOutputs] = {
- 0xe5a40d39ab796423, 0x1766974bf7527d81, 0x5c3bbbe230db17a8,
- 0xa6630143a7e6aa6f, 0x17645cb7318b86b, 0x218b175f30ba61f8,
- 0xa6564b468248c683, 0xef192f401b116e1c, 0xbe8dc0c54617639d,
- 0xe7b01610fc22dbb8, 0x99d9f694404af913, 0xf4eecd37464b45c5,
- 0x7d2c653d63596d9b, 0x3f15c8544ec5393a, 0x6b9dc0c1704f796c,
- 0xf1ded7a7eae5ed5a, 0x2db2fd7c6dd4641b, 0x151ca2d3d4cd33ab,
- 0xa5af5994ac2ccd64, 0x2b2a4ca3191d2fce, 0xf89e68c9364e7c05,
- 0x71724c70b799c21, 0x70536fabfd157369, 0xdee92794c3c3082b,
- 0xac033a6743d3b3eb, 0xed2956b506cd5151, 0xbd669644755264b6,
- 0x6ab1ff5d5f549a63, 0xf6bd551a2e3e04e, 0x7b5a8cef6875ea73,
- 0x22bccf4d4db0a91c, 0x4f2bc07754c7c7eb, 0xfb6b8342a86725db,
- 0x13a1a0d4c5854da, 0x5f6e44655f7dedac, 0x54a9198dff2bdf85,
- 0xdb17e6915d4e4042, 0xa69926cf5c3b89f, 0xf77f031bfd74c096,
- 0x1d6f916fdd50ec3c, 0x334ac76013ade393, 0x99370f899111de15,
- 0x352457a03ada6de, 0x341974d4f42d854d, 0xda89ab02872aeb5,
- 0x6ec2b74e143b10d9, 0x6f284c0b5cd60522, 0xf9670de353438f88,
- 0xde920913adf0a2b4, 0xb7a07d7c0c17a8ec, 0x879a69f558ba3a98,
- 0x360cf6d802df20f9, 0x53530f8046673738, 0xbd8f5f2bcf35e483,
- 0x3f171f047144b983, 0x644d04e820823465, 0x50e44773a20b2702,
- 0xe584ed4c05c745dd, 0x9a825c85b95ab6c0, 0xbce2931deb74e775,
- 0x10468e9e705c7cfe, 0x12e01de3104141e2, 0x5c11ae2ee3713abd,
- 0x6ac5ffb0860319e6, 0xc1e6da1849d30fc9, 0xa0e4d247a458b447,
- 0x4530d4615c32b89b, 0x116aa09107a76505, 0xf941339d00d9bb73,
- 0x573a0fc1615afb33, 0xa975c81dc868b258, 0x3ab2c5250ab54bda,
- 0x37f99f208a3e3b11, 0x4b49b0ff706689d, 0x30bafa0b8f0a87fe,
- 0xea6787a65cc20cdd, 0x55861729f1fc3ab8, 0xea38e009c5be9b72,
- 0xcb8522cba33c3c66, 0x352e77653fe306f3, 0xe0bb760793bac064,
- 0xf66ec59322662956, 0x637aa320455d56f8, 0x46ee546be5824a89,
- 0x9e6842421e83d8a4, 0xf98ac2bc96b9fb8c, 0xf2c1002fd9a70b99,
- 0x4c2b62b1e39e9405, 0x3248555fa3ade9c4, 0xd4d04c37f6417c21,
- 0xf40cd506b1bf5653, 0x6c45d6005c760d2f, 0x61d88a7e61ff0d7e,
- 0x131591e8a53cc967, 0xdae85cb9bc29bab6, 0xe98835334905e626,
- 0x7cce50a2b66b8754, 0x5b0b3d0c5ac498ae, 0xd35a218c974d1756,
- 0xfce436ddc1d003c, 0xd183901de90bb741, 0x9378f8f34974a66,
- 0x21f11ae0a0402368, 0xf2fbd7c94ef89cb6, 0xc329c69d0f0d080b,
- 0xf2841cba16216a61, 0x47aba97b44916df1, 0x724d4e00a8019fcf,
- 0x2df9005c2a728d63, 0xc788892a1a5d7515, 0x9e993a65f9df0480,
- 0x76876721ff49f969, 0xbe7a796cfba15bf5, 0xa4c8bd54586f5488,
- 0xb390a325275501ab, 0x893f11317427ccf1, 0x92f2bb57da5695b9,
- 0x30985b90da88269f, 0x2c690e268e086de8, 0x1c02df6097997196,
- 0x1f9778f8bbdf6455, 0x7d57378c7bf8416d, 0xba8582a5f8d84d38,
- 0xe8ca43b85050be4e, 0x5048cf6bed8a5d9f, 0xfbc5ba80917d0ea4,
- 0x8011026525bf1691, 0x26b8dc6aed9fb50d, 0x191f5bfee77c1fe3,
- 0xdd497891465a2cc1, 0x6f1fe8c57a33072e, 0x2c9f4ec078c460c0,
- 0x9a725bde8f6a1437, 0x6ce545fa3ef61e4d,
- };
-#elif defined(__aarch64__)
- constexpr uint64_t kGolden[kNumGoldenOutputs] = {
- 0x45c0aadee165dcbe, 0x25ed8587f6f20d06, 0x5f23ae668ce7926d,
- 0xfef74d1da0846719, 0x54478408e68cb7d4, 0xee27ddaf88c6fe68,
- 0xb7ac7031e81867ca, 0xf1168f818ec6c36d, 0x1dd0b734a83b019a,
- 0xd6ae30d4142b54fe, 0xcd860c721ccb80fb, 0x068acf8493794756,
- 0xd4ada0be58681307, 0x13ffe0f64ca540ed, 0xffc1d7a3401aec02,
- 0xd81c4d865cf95fb9, 0x1dd0793acede62e0, 0xa6722abbca8fe4cf,
- 0x5453d3e4111a7e40, 0xf29b3e3204c9dcd2, 0x23be2980e43117f7,
- 0x74e2ccbc286f08eb, 0x19ef7c0f9496003a, 0xbfbf1c3e49b27987,
- 0x6e6c179eb4a82c70, 0x07f4e184216bc4fc, 0xf17fbc4254927554,
- 0xe57696b70a45b1b6, 0x6d3b144631b320e8, 0xccf8729792c75a2d,
- 0xe832495b41fa980b, 0x5c96cfdc7b227d34, 0xc4dca234ef4e43f4,
- 0x5fc801abf9abe307, 0xe41e3c5076d88f4d, 0x522346200ddec3c3,
- 0x72bed1946fd7aaa4, 0x0ac1f84dcc335f96, 0x3af78db5e0a47670,
- 0x6100ebf1481f1caf, 0xf5fd10037fc651a3, 0xa01227d8944665f3,
- 0x7217681c4bbc9420, 0x4adee538e3eb10d1, 0x35e1761ad96de9a7,
- 0x8b370aef9613bfba, 0x824506f749eeaf59, 0x85e805fa04423991,
- 0xb61e9c33283c3de7, 0xc79721bbcb039ed6, 0x04e1c19a3a1e6639,
- 0x6aaf6346b68dd638, 0x601a4b496be6d0c4, 0x3ece355f91c41787,
- 0xd2fc8998448d7888, 0xd7529804f843efa9, 0xabdcc38a288536aa,
- 0xdd323e48a9718648, 0x2090279c0030a52a, 0xe2f90faca88a3cd1,
- 0x3e0c4e92fc50e4aa, 0xa26d308798e801dd, 0x432eefeedee8c02e,
- 0xca4ce494614b77df, 0xbba82911e838066d, 0x4b00821016adee4b,
- 0x4cf6e526dfb5a20f, 0x5b8466495142cba2, 0xe28ac1406e88a68c,
- 0x8511e5f9d3100999, 0x05acbfe02798890b, 0x74c249c7ce4a8425,
- 0xdbe7468d09bc34bc, 0x11079ab10e3b9b58, 0xb7788dec9032035a,
- 0xb7e8daa786513f80, 0x34c3288831f46b45, 0x014cce5f0c21ecc6,
- 0xc6a8f7b024551a28, 0x49784e902e207fd8, 0x4720d32af0b55158,
- 0x8df3ec5de0c1da00, 0xf4db677b2c9e6853, 0xaa419abea78d312d,
- 0x181e0f91bd757443, 0xa8c45136fada083b, 0x91303b93f5f0582c,
- 0x883b95c6ddc62a08, 0x93186a8875fe952b, 0xd94f533928e957e2,
- 0x6ba343003e10c172, 0xc8623b620c715d6a, 0x8ca0c512e180e244,
- 0xdc9b74c2536b6216, 0x8eb5fdc61b295d96, 0x2ad83966b37c95ba,
- 0xb90bf154ac5edec9, 0x902cf847b326cfb3, 0x7b02d0c0ca7808ca,
- 0x492f310d003ea15f, 0x3eb6497a47c95990, 0x5d46b0ced31428b7,
- 0x081afa67d1986157, 0x043482ec286b20eb, 0xc103c8f18c1a2a53,
- 0xe8e9995a81481e83, 0x6bb3295822bc90b5, 0xeec75297a3fa5672,
- 0x591c8440c4857412, 0x74947f455aaf24ad, 0xcf0e571586ec77a9,
- 0x0c2553ea8c0400ad, 0x380219118066255f, 0x7595adb88b15ebe2,
- 0xb33c00696c64ae23, 0xa143516ddd7c9857, 0x39179af229248d26,
- 0x65d387a6f2ee2079, 0x89f8a9b21cd2f195, 0xbfef032d25df92e6,
- 0x6b7e18a36c69da71, 0x4b3b15f6c28974e6, 0x032a75917f6c544c,
- 0xe3b97ecca6d287cd, 0xa4a563110d3cda81, 0x35e09e8134f4e7f1,
- 0xc9419dd03a9a390e, 0x7b86fae9000fd329, 0x1e044f8d54fe74c3,
- 0x9c4991d7a47e9666, 0xfb485f3a1df4fdb6, 0xb11519969eeb94ff,
- 0x3224ea1c44caeb8d, 0x86570bbd7cc6b80d,
- };
-#else
- constexpr uint64_t kGolden[kNumGoldenOutputs] = {
- 0xe5a40d39ab796423, 0x1766974bf7527d81, 0x5c3bbbe230db17a8,
- 0xa6630143a7e6aa6f, 0x8787cb2d04b0c984, 0x33603654ff574ac2,
- 0xa6564b468248c683, 0xef192f401b116e1c, 0xbe8dc0c54617639d,
- 0x93d7f665b5521c8e, 0x646d70bb42445f28, 0x96a7b1e3cc9bd426,
- 0x76020289ab0790c4, 0x39f842e4133b9b44, 0x2b8d7047be4bcaab,
- 0x99628abef6716a97, 0x4432e02ba42b2740, 0x74d810efcad7918a,
- 0x88c84e986002507f, 0x4f99acf193cf39b9, 0xd90e7a3655891e37,
- 0x3bb378b1d4df8fcf, 0xf78e94045c052d47, 0x26da0b2130da6b40,
- 0x30b4d426af8c6986, 0x5413b4aaf3baaeae, 0x756ab265370a1597,
- 0xdaf5f4b7d09814fb, 0x8f874ae37742b75e, 0x8fecd03956121ce8,
- 0x229c292ea7a08285, 0x0bb4bf0692d14bae, 0x207b24ca3bdac1db,
- 0x64f6cd6745d3825b, 0xa2b2e1656b58df1e, 0x0d01d30d9ee7a148,
- 0x1cb4cd00ab804e3b, 0x4697f2637fd90999, 0x8383a756b5688c07,
- 0x695c29cb3696a975, 0xda2e5a5a5e971521, 0x7935d4befa056b2b,
- 0x38dd541ca95420fe, 0xcc06c7a4963f967f, 0xbf0f6f66e232fb20,
- 0xf7efb32d373fe71a, 0xe2e64634b1c12660, 0x285b8fd1638e306d,
- 0x658e8a4e3b714d6c, 0xf391fb968e0eb398, 0x744a9ea0cc144bf2,
- 0x12636f2be11012f1, 0x29c57de825948f80, 0x58c6f99ab0d1c021,
- 0x13e7b5a7b82fe3bb, 0x10fbc87901e02b63, 0xa24c9184901b748b,
- 0xcac4fd4c5080e581, 0xc38bdb7483ba68e1, 0xdb2a8069b2ceaffa,
- 0xdf9fe91d0d1c7887, 0xe83f49e96e2e6a08, 0x0c69e61b62ca2b62,
- 0xb4a4f3f85f8298fe, 0x167a1b39e1e95f41, 0xf8a2a5649855ee41,
- 0x27992565b595c498, 0x3e08cca5b71f9346, 0xad406b10c770a6d2,
- 0xd1713ce6e552bcf2, 0x753b287194c73ad3, 0x5ae41a95f600af1c,
- 0x4a61163b86a8bb4c, 0x42eeaa79e760c7e4, 0x698df622ef465b0a,
- 0x157583111e1a6026, 0xaa1388f078e793e0, 0xf10d68d0f3309360,
- 0x2af056184457a3de, 0x6d0058e1590b2489, 0x638f287f68817f12,
- 0xc46b71fecefd5467, 0x2c8e94679d964e0a, 0x8612b797ce22503a,
- 0x59f929babfba7170, 0x9527556923fb49a0, 0x1039ab644f5e150b,
- 0x7816c83f3aa05e6d, 0xf51d2f564518c619, 0x67d494cff03ac004,
- 0x2802d636ced1cfbb, 0xf64e20bad771cb12, 0x0b9a6cf84a83e15e,
- 0x8da6630319609301, 0x40946a86e2a996f3, 0xcab7f5997953fa76,
- 0x39129ca0e04fc465, 0x5238221fd685e1b8, 0x175130c407dbcaab,
- 0x02f20e7536c0b0df, 0x2742cb488a04ad56, 0xd6afb593879ff93b,
- 0xf50ad64caac0ca7f, 0x2ade95c4261364ae, 0x5c4f3299faacd07a,
- 0xfffe3bff0ae5e9bc, 0x1db785c0005166e4, 0xea000d962ad18418,
- 0xe42aef38359362d9, 0xc8e95657348a3891, 0xc162eca864f238c6,
- 0xbe1fb373e20579ad, 0x628a1d4f40aa6ffd, 0xa87bdb7456340f90,
- 0x5960ef3ba982c801, 0x5026586df9a431ec, 0xfe4b8a20fdf0840b,
- 0xdcb761867da7072f, 0xc10d4653667275b7, 0x727720deec13110b,
- 0x710b009662858dc9, 0xfbf8f7a3ecac1eb7, 0xb6fc4fcd0722e3df,
- 0x7cb86dcc55104aac, 0x19e71e9b45c3a51e, 0x51de38573c2bea48,
- 0xa73ab6996d6df158, 0x55ef2b8c930817b2, 0xb2850bf5fae87157,
- 0xecf3de1acd04651f, 0xcc0a40552559ff32, 0xc385c374f20315b1,
- 0xb90208a4c7234183, 0x58aa1ca7a4c075d9,
- };
-#endif
-
-#if UPDATE_GOLDEN
- (void)kGolden; // Silence warning.
- for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
- std::string str;
- ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));
- uint64_t h = absl::hash_internal::LowLevelHash(str.data(), str.size(),
- cases[i].seed, kSalt);
- printf("0x%016" PRIx64 ", ", h);
- if (i % 3 == 2) {
- printf("\n");
- }
- }
- printf("\n\n\n");
- EXPECT_FALSE(true);
-#else
- for (size_t i = 0; i < kNumGoldenOutputs; ++i) {
- SCOPED_TRACE(::testing::Message()
- << "i = " << i << "; input = " << cases[i].base64_data);
- std::string str;
- ASSERT_TRUE(absl::Base64Unescape(cases[i].base64_data, &str));
- EXPECT_EQ(absl::hash_internal::LowLevelHash(str.data(), str.size(),
- cases[i].seed, kSalt),
- kGolden[i]);
- }
-#endif
-}
-
-} // namespace
diff --git a/third_party/abseil-cpp/absl/memory/BUILD.bazel b/third_party/abseil-cpp/absl/memory/BUILD.bazel
index c16bf8a948..2ba9d7cb98 100644
--- a/third_party/abseil-cpp/absl/memory/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/memory/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "memory",
diff --git a/third_party/abseil-cpp/absl/memory/CMakeLists.txt b/third_party/abseil-cpp/absl/memory/CMakeLists.txt
index 9d50e1dcd4..78fb7e1b31 100644
--- a/third_party/abseil-cpp/absl/memory/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/memory/CMakeLists.txt
@@ -37,7 +37,7 @@ absl_cc_test(
DEPS
absl::memory
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -51,5 +51,5 @@ absl_cc_test(
absl::memory
absl::config
absl::exception_safety_testing
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/memory/memory.h b/third_party/abseil-cpp/absl/memory/memory.h
index d63326068f..513f7103a0 100644
--- a/third_party/abseil-cpp/absl/memory/memory.h
+++ b/third_party/abseil-cpp/absl/memory/memory.h
@@ -420,9 +420,6 @@ struct pointer_traits<T*> {
//
// A C++11 compatible implementation of C++17's std::allocator_traits.
//
-#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
-using std::allocator_traits;
-#else // __cplusplus >= 201703L
template <typename Alloc>
struct allocator_traits {
using allocator_type = Alloc;
@@ -612,7 +609,6 @@ struct allocator_traits {
return a;
}
};
-#endif // __cplusplus >= 201703L
namespace memory_internal {
diff --git a/third_party/abseil-cpp/absl/memory/memory_test.cc b/third_party/abseil-cpp/absl/memory/memory_test.cc
index 1990c7ba47..c47820e54a 100644
--- a/third_party/abseil-cpp/absl/memory/memory_test.cc
+++ b/third_party/abseil-cpp/absl/memory/memory_test.cc
@@ -17,7 +17,6 @@
#include "absl/memory/memory.h"
#include <sys/types.h>
-
#include <cstddef>
#include <memory>
#include <string>
@@ -37,10 +36,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_; }
@@ -157,7 +156,9 @@ 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;
@@ -170,7 +171,8 @@ 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)));
}
@@ -179,7 +181,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>());
@@ -539,8 +541,8 @@ struct MinimalMockAllocator {
MinimalMockAllocator(const MinimalMockAllocator& other)
: value(other.value) {}
using value_type = TestValue;
- MOCK_METHOD(value_type*, allocate, (size_t));
- MOCK_METHOD(void, deallocate, (value_type*, size_t));
+ MOCK_METHOD1(allocate, value_type*(size_t));
+ MOCK_METHOD2(deallocate, void(value_type*, size_t));
int value;
};
@@ -555,7 +557,7 @@ TEST(AllocatorTraits, FunctionsMinimal) {
EXPECT_CALL(mock, deallocate(&x, 7));
EXPECT_EQ(&x, Traits::allocate(mock, 7));
- static_cast<void>(Traits::allocate(mock, 7, static_cast<const void*>(&hint)));
+ 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);
@@ -577,14 +579,13 @@ struct FullMockAllocator {
explicit FullMockAllocator(int value) : value(value) {}
FullMockAllocator(const FullMockAllocator& other) : value(other.value) {}
using value_type = TestValue;
- 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));
+ 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());
int value;
};
@@ -641,7 +642,8 @@ 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/third_party/abseil-cpp/absl/meta/BUILD.bazel b/third_party/abseil-cpp/absl/meta/BUILD.bazel
index fb379251a6..c06d2d9708 100644
--- a/third_party/abseil-cpp/absl/meta/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/meta/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "type_traits",
diff --git a/third_party/abseil-cpp/absl/meta/CMakeLists.txt b/third_party/abseil-cpp/absl/meta/CMakeLists.txt
index 9de4bd3751..672ead2fd0 100644
--- a/third_party/abseil-cpp/absl/meta/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/meta/CMakeLists.txt
@@ -35,7 +35,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
# component target
diff --git a/third_party/abseil-cpp/absl/meta/type_traits.h b/third_party/abseil-cpp/absl/meta/type_traits.h
index d886cb30a8..ba87d2f0ed 100644
--- a/third_party/abseil-cpp/absl/meta/type_traits.h
+++ b/third_party/abseil-cpp/absl/meta/type_traits.h
@@ -35,7 +35,7 @@
#ifndef ABSL_META_TYPE_TRAITS_H_
#define ABSL_META_TYPE_TRAITS_H_
-#include <cstddef>
+#include <stddef.h>
#include <functional>
#include <type_traits>
@@ -47,14 +47,6 @@
#define ABSL_META_INTERNAL_STD_CONSTRUCTION_TRAITS_DONT_CHECK_DESTRUCTION 1
#endif
-// Defines the default alignment. `__STDCPP_DEFAULT_NEW_ALIGNMENT__` is a C++17
-// feature.
-#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
-#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT __STDCPP_DEFAULT_NEW_ALIGNMENT__
-#else // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
-#define ABSL_INTERNAL_DEFAULT_NEW_ALIGNMENT alignof(std::max_align_t)
-#endif // defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
-
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -227,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 : std::true_type {};
+struct conjunction;
template <typename T, typename... Ts>
struct conjunction<T, Ts...>
@@ -236,6 +228,9 @@ 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
@@ -246,7 +241,7 @@ struct conjunction<T> : T {};
// This metafunction is designed to be a drop-in replacement for the C++17
// `std::disjunction` metafunction.
template <typename... Ts>
-struct disjunction : std::false_type {};
+struct disjunction;
template <typename T, typename... Ts>
struct disjunction<T, Ts...> :
@@ -255,6 +250,9 @@ 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
@@ -507,27 +505,6 @@ struct is_trivially_copy_assignable
#endif // ABSL_HAVE_STD_IS_TRIVIALLY_ASSIGNABLE
};
-#if defined(__cpp_lib_remove_cvref) && __cpp_lib_remove_cvref >= 201711L
-template <typename T>
-using remove_cvref = std::remove_cvref<T>;
-
-template <typename T>
-using remove_cvref_t = typename std::remove_cvref<T>::type;
-#else
-// remove_cvref()
-//
-// C++11 compatible implementation of std::remove_cvref which was added in
-// C++20.
-template <typename T>
-struct remove_cvref {
- using type =
- typename std::remove_cv<typename std::remove_reference<T>::type>::type;
-};
-
-template <typename T>
-using remove_cvref_t = typename remove_cvref<T>::type;
-#endif
-
namespace type_traits_internal {
// is_trivially_copyable()
//
@@ -639,23 +616,8 @@ using common_type_t = typename std::common_type<T...>::type;
template <typename T>
using underlying_type_t = typename std::underlying_type<T>::type;
-
-namespace type_traits_internal {
-
-#if (defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703L) || \
- (defined(_MSVC_LANG) && _MSVC_LANG >= 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;
+template <typename T>
+using result_of_t = typename std::result_of<T>::type;
namespace type_traits_internal {
// In MSVC we can't probe std::hash or stdext::hash because it triggers a
diff --git a/third_party/abseil-cpp/absl/meta/type_traits_test.cc b/third_party/abseil-cpp/absl/meta/type_traits_test.cc
index 0ef5b66558..1aafd0d49a 100644
--- a/third_party/abseil-cpp/absl/meta/type_traits_test.cc
+++ b/third_party/abseil-cpp/absl/meta/type_traits_test.cc
@@ -942,34 +942,6 @@ TEST(TypeTraitsTest, TestTriviallyCopyable) {
absl::type_traits_internal::is_trivially_copyable<Trivial&>::value);
}
-TEST(TypeTraitsTest, TestRemoveCVRef) {
- EXPECT_TRUE(
- (std::is_same<typename absl::remove_cvref<int>::type, int>::value));
- EXPECT_TRUE(
- (std::is_same<typename absl::remove_cvref<int&>::type, int>::value));
- EXPECT_TRUE(
- (std::is_same<typename absl::remove_cvref<int&&>::type, int>::value));
- EXPECT_TRUE((
- std::is_same<typename absl::remove_cvref<const int&>::type, int>::value));
- EXPECT_TRUE(
- (std::is_same<typename absl::remove_cvref<int*>::type, int*>::value));
- // Does not remove const in this case.
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int*>::type,
- const int*>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int[2]>::type,
- int[2]>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&)[2]>::type,
- int[2]>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<int(&&)[2]>::type,
- int[2]>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int[2]>::type,
- int[2]>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&)[2]>::type,
- int[2]>::value));
- EXPECT_TRUE((std::is_same<typename absl::remove_cvref<const int(&&)[2]>::type,
- int[2]>::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))
diff --git a/third_party/abseil-cpp/absl/numeric/BUILD.bazel b/third_party/abseil-cpp/absl/numeric/BUILD.bazel
index 1f9e0f2055..e09e52d21f 100644
--- a/third_party/abseil-cpp/absl/numeric/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/numeric/BUILD.bazel
@@ -12,6 +12,7 @@
# 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",
@@ -21,36 +22,7 @@ load(
package(default_visibility = ["//visibility:public"])
-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",
- ],
-)
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "int128",
@@ -63,7 +35,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":bits",
"//absl/base:config",
"//absl/base:core_headers",
],
@@ -100,15 +71,3 @@ 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/third_party/abseil-cpp/absl/numeric/CMakeLists.txt b/third_party/abseil-cpp/absl/numeric/CMakeLists.txt
index 26df5cf703..242889f088 100644
--- a/third_party/abseil-cpp/absl/numeric/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/numeric/CMakeLists.txt
@@ -16,33 +16,6 @@
absl_cc_library(
NAME
- bits
- HDRS
- "bits.h"
- "internal/bits.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::core_headers
- PUBLIC
-)
-
-absl_cc_test(
- NAME
- bits_test
- SRCS
- "bits_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::bits
- absl::core_headers
- absl::random_random
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
int128
HDRS
"int128.h"
@@ -55,7 +28,6 @@ absl_cc_library(
DEPS
absl::config
absl::core_headers
- absl::bits
PUBLIC
)
@@ -73,7 +45,7 @@ absl_cc_test(
absl::core_headers
absl::hash_testing
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
# component target
@@ -86,15 +58,3 @@ absl_cc_library(
absl::int128
PUBLIC
)
-
-absl_cc_library(
- NAME
- numeric_representation
- HDRS
- "internal/representation.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- PUBLIC
-)
diff --git a/third_party/abseil-cpp/absl/numeric/bits.h b/third_party/abseil-cpp/absl/numeric/bits.h
deleted file mode 100644
index 52013ad49b..0000000000
--- a/third_party/abseil-cpp/absl/numeric/bits.h
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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/third_party/abseil-cpp/absl/numeric/bits_test.cc b/third_party/abseil-cpp/absl/numeric/bits_test.cc
deleted file mode 100644
index 7c942aaecd..0000000000
--- a/third_party/abseil-cpp/absl/numeric/bits_test.cc
+++ /dev/null
@@ -1,573 +0,0 @@
-// 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/third_party/abseil-cpp/absl/numeric/int128.cc b/third_party/abseil-cpp/absl/numeric/int128.cc
index 17d88744ae..b605a87042 100644
--- a/third_party/abseil-cpp/absl/numeric/int128.cc
+++ b/third_party/abseil-cpp/absl/numeric/int128.cc
@@ -15,7 +15,6 @@
#include "absl/numeric/int128.h"
#include <stddef.h>
-
#include <cassert>
#include <iomanip>
#include <ostream> // NOLINT(readability/streams)
@@ -23,9 +22,6 @@
#include <string>
#include <type_traits>
-#include "absl/base/optimization.h"
-#include "absl/numeric/bits.h"
-
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -35,26 +31,44 @@ ABSL_DLL const uint128 kuint128max = MakeUint128(
namespace {
// Returns the 0-based position of the last set bit (i.e., most significant bit)
-// in the given uint128. The argument is not 0.
+// in the given uint64_t. The argument may not be 0.
//
// For example:
// Given: 5 (decimal) == 101 (binary)
// Returns: 2
-inline ABSL_ATTRIBUTE_ALWAYS_INLINE int Fls128(uint128 n) {
+#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) {
if (uint64_t hi = Uint128High64(n)) {
- ABSL_INTERNAL_ASSUME(hi != 0);
- return 127 - countl_zero(hi);
+ return Fls64(hi) + 64;
}
- const uint64_t low = Uint128Low64(n);
- ABSL_INTERNAL_ASSUME(low != 0);
- return 63 - countl_zero(low);
+ return Fls64(Uint128Low64(n));
}
// Long division/modulo for uint128 implemented using the shift-subtract
// division algorithm adapted from:
// https://stackoverflow.com/questions/5386377/division-without-using
-inline void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
- uint128* remainder_ret) {
+void DivModImpl(uint128 dividend, uint128 divisor, uint128* quotient_ret,
+ uint128* remainder_ret) {
assert(divisor != 0);
if (divisor > dividend) {
@@ -138,21 +152,28 @@ uint128::uint128(float v) : uint128(MakeUint128FromFloat(v)) {}
uint128::uint128(double v) : uint128(MakeUint128FromFloat(v)) {}
uint128::uint128(long double v) : uint128(MakeUint128FromFloat(v)) {}
-#if !defined(ABSL_HAVE_INTRINSIC_INT128)
uint128 operator/(uint128 lhs, uint128 rhs) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ return static_cast<unsigned __int128>(lhs) /
+ static_cast<unsigned __int128>(rhs);
+#else // ABSL_HAVE_INTRINSIC_INT128
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(lhs, rhs, &quotient, &remainder);
return quotient;
+#endif // ABSL_HAVE_INTRINSIC_INT128
}
-
uint128 operator%(uint128 lhs, uint128 rhs) {
+#if defined(ABSL_HAVE_INTRINSIC_INT128)
+ return static_cast<unsigned __int128>(lhs) %
+ static_cast<unsigned __int128>(rhs);
+#else // ABSL_HAVE_INTRINSIC_INT128
uint128 quotient = 0;
uint128 remainder = 0;
DivModImpl(lhs, rhs, &quotient, &remainder);
return remainder;
+#endif // ABSL_HAVE_INTRINSIC_INT128
}
-#endif // !defined(ABSL_HAVE_INTRINSIC_INT128)
namespace {
diff --git a/third_party/abseil-cpp/absl/numeric/int128.h b/third_party/abseil-cpp/absl/numeric/int128.h
index c7ad96befd..636e3a5bc7 100644
--- a/third_party/abseil-cpp/absl/numeric/int128.h
+++ b/third_party/abseil-cpp/absl/numeric/int128.h
@@ -18,10 +18,6 @@
// -----------------------------------------------------------------------------
//
// This header file defines 128-bit integer types, `uint128` and `int128`.
-//
-// TODO(absl-team): This module is inconsistent as many inline `uint128` methods
-// are defined in this file, while many inline `int128` methods are defined in
-// the `int128_*_intrinsic.inc` files.
#ifndef ABSL_NUMERIC_INT128_H_
#define ABSL_NUMERIC_INT128_H_
@@ -586,10 +582,10 @@ inline uint128& uint128::operator=(int128 v) {
// Arithmetic operators.
-constexpr uint128 operator<<(uint128 lhs, int amount);
-constexpr uint128 operator>>(uint128 lhs, int amount);
-constexpr uint128 operator+(uint128 lhs, uint128 rhs);
-constexpr uint128 operator-(uint128 lhs, uint128 rhs);
+uint128 operator<<(uint128 lhs, int amount);
+uint128 operator>>(uint128 lhs, int amount);
+uint128 operator+(uint128 lhs, uint128 rhs);
+uint128 operator-(uint128 lhs, uint128 rhs);
uint128 operator*(uint128 lhs, uint128 rhs);
uint128 operator/(uint128 lhs, uint128 rhs);
uint128 operator%(uint128 lhs, uint128 rhs);
@@ -786,192 +782,137 @@ inline uint128::operator long double() const {
// Comparison operators.
-constexpr bool operator==(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) ==
- static_cast<unsigned __int128>(rhs);
-#else
+inline bool operator==(uint128 lhs, uint128 rhs) {
return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
Uint128High64(lhs) == Uint128High64(rhs));
-#endif
}
-constexpr bool operator!=(uint128 lhs, uint128 rhs) { return !(lhs == rhs); }
+inline bool operator!=(uint128 lhs, uint128 rhs) {
+ return !(lhs == rhs);
+}
-constexpr bool operator<(uint128 lhs, uint128 rhs) {
-#ifdef ABSL_HAVE_INTRINSIC_INT128
- return static_cast<unsigned __int128>(lhs) <
- static_cast<unsigned __int128>(rhs);
-#else
+inline bool operator<(uint128 lhs, uint128 rhs) {
return (Uint128High64(lhs) == Uint128High64(rhs))
? (Uint128Low64(lhs) < Uint128Low64(rhs))
: (Uint128High64(lhs) < Uint128High64(rhs));
-#endif
}
-constexpr bool operator>(uint128 lhs, uint128 rhs) { return rhs < lhs; }
-
-constexpr bool operator<=(uint128 lhs, uint128 rhs) { return !(rhs < lhs); }
-
-constexpr bool operator>=(uint128 lhs, uint128 rhs) { return !(lhs < rhs); }
-
-// Unary operators.
+inline bool operator>(uint128 lhs, uint128 rhs) {
+ return (Uint128High64(lhs) == Uint128High64(rhs))
+ ? (Uint128Low64(lhs) > Uint128Low64(rhs))
+ : (Uint128High64(lhs) > Uint128High64(rhs));
+}
-constexpr inline uint128 operator+(uint128 val) {
- return val;
+inline bool operator<=(uint128 lhs, uint128 rhs) {
+ return (Uint128High64(lhs) == Uint128High64(rhs))
+ ? (Uint128Low64(lhs) <= Uint128Low64(rhs))
+ : (Uint128High64(lhs) <= Uint128High64(rhs));
}
-constexpr inline int128 operator+(int128 val) {
- return val;
+inline bool operator>=(uint128 lhs, uint128 rhs) {
+ return (Uint128High64(lhs) == Uint128High64(rhs))
+ ? (Uint128Low64(lhs) >= Uint128Low64(rhs))
+ : (Uint128High64(lhs) >= Uint128High64(rhs));
}
-constexpr uint128 operator-(uint128 val) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return -static_cast<unsigned __int128>(val);
-#else
- return MakeUint128(
- ~Uint128High64(val) + static_cast<unsigned long>(Uint128Low64(val) == 0),
- ~Uint128Low64(val) + 1);
-#endif
+// Unary operators.
+
+inline uint128 operator-(uint128 val) {
+ uint64_t hi = ~Uint128High64(val);
+ uint64_t lo = ~Uint128Low64(val) + 1;
+ if (lo == 0) ++hi; // carry
+ return MakeUint128(hi, lo);
}
-constexpr inline bool operator!(uint128 val) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return !static_cast<unsigned __int128>(val);
-#else
+inline bool operator!(uint128 val) {
return !Uint128High64(val) && !Uint128Low64(val);
-#endif
}
// Logical operators.
-constexpr inline uint128 operator~(uint128 val) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return ~static_cast<unsigned __int128>(val);
-#else
+inline uint128 operator~(uint128 val) {
return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
-#endif
}
-constexpr inline uint128 operator|(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) |
- static_cast<unsigned __int128>(rhs);
-#else
+inline uint128 operator|(uint128 lhs, uint128 rhs) {
return MakeUint128(Uint128High64(lhs) | Uint128High64(rhs),
- Uint128Low64(lhs) | Uint128Low64(rhs));
-#endif
+ Uint128Low64(lhs) | Uint128Low64(rhs));
}
-constexpr inline uint128 operator&(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) &
- static_cast<unsigned __int128>(rhs);
-#else
+inline uint128 operator&(uint128 lhs, uint128 rhs) {
return MakeUint128(Uint128High64(lhs) & Uint128High64(rhs),
- Uint128Low64(lhs) & Uint128Low64(rhs));
-#endif
+ Uint128Low64(lhs) & Uint128Low64(rhs));
}
-constexpr inline uint128 operator^(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) ^
- static_cast<unsigned __int128>(rhs);
-#else
+inline uint128 operator^(uint128 lhs, uint128 rhs) {
return MakeUint128(Uint128High64(lhs) ^ Uint128High64(rhs),
- Uint128Low64(lhs) ^ Uint128Low64(rhs));
-#endif
+ Uint128Low64(lhs) ^ Uint128Low64(rhs));
}
inline uint128& uint128::operator|=(uint128 other) {
- *this = *this | other;
+ hi_ |= other.hi_;
+ lo_ |= other.lo_;
return *this;
}
inline uint128& uint128::operator&=(uint128 other) {
- *this = *this & other;
+ hi_ &= other.hi_;
+ lo_ &= other.lo_;
return *this;
}
inline uint128& uint128::operator^=(uint128 other) {
- *this = *this ^ other;
+ hi_ ^= other.hi_;
+ lo_ ^= other.lo_;
return *this;
}
// Arithmetic operators.
-constexpr uint128 operator<<(uint128 lhs, int amount) {
-#ifdef ABSL_HAVE_INTRINSIC_INT128
- return static_cast<unsigned __int128>(lhs) << amount;
-#else
+inline uint128 operator<<(uint128 lhs, int amount) {
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
- return amount >= 64 ? MakeUint128(Uint128Low64(lhs) << (amount - 64), 0)
- : amount == 0 ? lhs
- : MakeUint128((Uint128High64(lhs) << amount) |
- (Uint128Low64(lhs) >> (64 - amount)),
- Uint128Low64(lhs) << amount);
-#endif
+ if (amount < 64) {
+ if (amount != 0) {
+ return MakeUint128(
+ (Uint128High64(lhs) << amount) | (Uint128Low64(lhs) >> (64 - amount)),
+ Uint128Low64(lhs) << amount);
+ }
+ return lhs;
+ }
+ return MakeUint128(Uint128Low64(lhs) << (amount - 64), 0);
}
-constexpr uint128 operator>>(uint128 lhs, int amount) {
-#ifdef ABSL_HAVE_INTRINSIC_INT128
- return static_cast<unsigned __int128>(lhs) >> amount;
-#else
+inline uint128 operator>>(uint128 lhs, int amount) {
// uint64_t shifts of >= 64 are undefined, so we will need some
// special-casing.
- return amount >= 64 ? MakeUint128(0, Uint128High64(lhs) >> (amount - 64))
- : amount == 0 ? lhs
- : MakeUint128(Uint128High64(lhs) >> amount,
- (Uint128Low64(lhs) >> amount) |
- (Uint128High64(lhs) << (64 - amount)));
-#endif
-}
-
-#if !defined(ABSL_HAVE_INTRINSIC_INT128)
-namespace int128_internal {
-constexpr uint128 AddResult(uint128 result, uint128 lhs) {
- // check for carry
- return (Uint128Low64(result) < Uint128Low64(lhs))
- ? MakeUint128(Uint128High64(result) + 1, Uint128Low64(result))
- : result;
-}
-} // namespace int128_internal
-#endif
-
-constexpr uint128 operator+(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) +
- static_cast<unsigned __int128>(rhs);
-#else
- return int128_internal::AddResult(
- MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
- Uint128Low64(lhs) + Uint128Low64(rhs)),
- lhs);
-#endif
+ if (amount < 64) {
+ if (amount != 0) {
+ return MakeUint128(Uint128High64(lhs) >> amount,
+ (Uint128Low64(lhs) >> amount) |
+ (Uint128High64(lhs) << (64 - amount)));
+ }
+ return lhs;
+ }
+ return MakeUint128(0, Uint128High64(lhs) >> (amount - 64));
}
-#if !defined(ABSL_HAVE_INTRINSIC_INT128)
-namespace int128_internal {
-constexpr uint128 SubstructResult(uint128 result, uint128 lhs, uint128 rhs) {
- // check for carry
- return (Uint128Low64(lhs) < Uint128Low64(rhs))
- ? MakeUint128(Uint128High64(result) - 1, Uint128Low64(result))
- : result;
+inline uint128 operator+(uint128 lhs, uint128 rhs) {
+ uint128 result = MakeUint128(Uint128High64(lhs) + Uint128High64(rhs),
+ Uint128Low64(lhs) + Uint128Low64(rhs));
+ if (Uint128Low64(result) < Uint128Low64(lhs)) { // check for carry
+ return MakeUint128(Uint128High64(result) + 1, Uint128Low64(result));
+ }
+ return result;
}
-} // namespace int128_internal
-#endif
-constexpr uint128 operator-(uint128 lhs, uint128 rhs) {
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return static_cast<unsigned __int128>(lhs) -
- static_cast<unsigned __int128>(rhs);
-#else
- return int128_internal::SubstructResult(
- MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
- Uint128Low64(lhs) - Uint128Low64(rhs)),
- lhs, rhs);
-#endif
+inline uint128 operator-(uint128 lhs, uint128 rhs) {
+ uint128 result = MakeUint128(Uint128High64(lhs) - Uint128High64(rhs),
+ Uint128Low64(lhs) - Uint128Low64(rhs));
+ if (Uint128Low64(lhs) < Uint128Low64(rhs)) { // check for carry
+ return MakeUint128(Uint128High64(result) - 1, Uint128Low64(result));
+ }
+ return result;
}
inline uint128 operator*(uint128 lhs, uint128 rhs) {
@@ -1001,18 +942,6 @@ inline uint128 operator*(uint128 lhs, uint128 rhs) {
#endif // ABSL_HAVE_INTRINSIC128
}
-#if defined(ABSL_HAVE_INTRINSIC_INT128)
-inline uint128 operator/(uint128 lhs, uint128 rhs) {
- return static_cast<unsigned __int128>(lhs) /
- static_cast<unsigned __int128>(rhs);
-}
-
-inline uint128 operator%(uint128 lhs, uint128 rhs) {
- return static_cast<unsigned __int128>(lhs) %
- static_cast<unsigned __int128>(rhs);
-}
-#endif
-
// Increment/decrement operators.
inline uint128 uint128::operator++(int) {
@@ -1070,17 +999,17 @@ inline int128& int128::operator=(unsigned long long v) {
}
// Arithmetic operators.
-constexpr int128 operator-(int128 v);
-constexpr int128 operator+(int128 lhs, int128 rhs);
-constexpr 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);
-constexpr int128 operator|(int128 lhs, int128 rhs);
-constexpr int128 operator&(int128 lhs, int128 rhs);
-constexpr int128 operator^(int128 lhs, int128 rhs);
-constexpr int128 operator<<(int128 lhs, int amount);
-constexpr int128 operator>>(int128 lhs, int amount);
+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;
@@ -1132,9 +1061,6 @@ inline int128& int128::operator>>=(int amount) {
return *this;
}
-// Forward declaration for comparison operators.
-constexpr bool operator!=(int128 lhs, int128 rhs);
-
namespace int128_internal {
// Casts from unsigned to signed while preserving the underlying binary
diff --git a/third_party/abseil-cpp/absl/numeric/int128_benchmark.cc b/third_party/abseil-cpp/absl/numeric/int128_benchmark.cc
index eab1515c0a..a5502d927c 100644
--- a/third_party/abseil-cpp/absl/numeric/int128_benchmark.cc
+++ b/third_party/abseil-cpp/absl/numeric/int128_benchmark.cc
@@ -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,85 +32,57 @@ std::mt19937 MakeRandomEngine() {
return std::mt19937(seed);
}
-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::vector<std::pair<absl::uint128, absl::uint128>>
+GetRandomClass128SampleUniformDivisor() {
+ std::vector<std::pair<absl::uint128, absl::uint128>> values;
std::mt19937 random = MakeRandomEngine();
- std::uniform_int_distribution<H> uniform_h;
+ std::uniform_int_distribution<uint64_t> uniform_uint64;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- 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)));
+ 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)));
}
return values;
}
-template <typename T>
void BM_DivideClass128UniformDivisor(benchmark::State& state) {
- auto values = GetRandomClass128SampleUniformDivisor<T>();
+ auto values = GetRandomClass128SampleUniformDivisor();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-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);
+BENCHMARK(BM_DivideClass128UniformDivisor);
-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::vector<std::pair<absl::uint128, uint64_t>>
+GetRandomClass128SampleSmallDivisor() {
+ std::vector<std::pair<absl::uint128, uint64_t>> values;
std::mt19937 random = MakeRandomEngine();
- std::uniform_int_distribution<H> uniform_h;
+ std::uniform_int_distribution<uint64_t> uniform_uint64;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- 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);
+ 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);
}
return values;
}
-template <typename T>
void BM_DivideClass128SmallDivisor(benchmark::State& state) {
- auto values = GetRandomClass128SampleSmallDivisor<T>();
+ auto values = GetRandomClass128SampleSmallDivisor();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-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);
+BENCHMARK(BM_DivideClass128SmallDivisor);
std::vector<std::pair<absl::uint128, absl::uint128>> GetRandomClass128Sample() {
std::vector<std::pair<absl::uint128, absl::uint128>> values;
@@ -149,107 +121,74 @@ 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
- T operator()(std::mt19937& generator) {
- return (static_cast<T>(dist64_(generator)) << 64) | dist64_(generator);
+ unsigned __int128 operator()(std::mt19937& generator) {
+ return (static_cast<unsigned __int128>(dist64_(generator)) << 64) |
+ dist64_(generator);
}
private:
- std::uniform_int_distribution<H> dist64_;
+ std::uniform_int_distribution<uint64_t> dist64_;
};
-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::vector<std::pair<unsigned __int128, unsigned __int128>>
+GetRandomIntrinsic128SampleUniformDivisor() {
+ std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128<T> uniform_128;
+ UniformIntDistribution128 uniform_uint128;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- 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)));
+ 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)));
}
return values;
}
-template <typename T>
void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) {
- auto values = GetRandomIntrinsic128SampleUniformDivisor<T>();
+ auto values = GetRandomIntrinsic128SampleUniformDivisor();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-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);
+BENCHMARK(BM_DivideIntrinsic128UniformDivisor);
-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::vector<std::pair<unsigned __int128, uint64_t>>
+GetRandomIntrinsic128SampleSmallDivisor() {
+ std::vector<std::pair<unsigned __int128, uint64_t>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128<T> uniform_int128;
- std::uniform_int_distribution<H> uniform_int64;
+ UniformIntDistribution128 uniform_uint128;
+ std::uniform_int_distribution<uint64_t> uniform_uint64;
values.reserve(kSampleSize);
for (size_t i = 0; i < kSampleSize; ++i) {
- 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);
+ 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);
}
return values;
}
-template <typename T>
void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) {
- auto values = GetRandomIntrinsic128SampleSmallDivisor<T>();
+ auto values = GetRandomIntrinsic128SampleSmallDivisor();
while (state.KeepRunningBatch(values.size())) {
for (const auto& pair : values) {
benchmark::DoNotOptimize(pair.first / pair.second);
}
}
}
-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);
+BENCHMARK(BM_DivideIntrinsic128SmallDivisor);
std::vector<std::pair<unsigned __int128, unsigned __int128>>
GetRandomIntrinsic128Sample() {
std::vector<std::pair<unsigned __int128, unsigned __int128>> values;
std::mt19937 random = MakeRandomEngine();
- UniformIntDistribution128<unsigned __int128> uniform_uint128;
+ UniformIntDistribution128 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/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc b/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
index 3945fa2983..d6c76dd320 100644
--- a/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
+++ b/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc
@@ -155,7 +155,7 @@ constexpr int128::operator unsigned __int128() const {
#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 double () const { return static_cast<double>(v_); }
inline int128::operator long double() const {
return static_cast<long double>(v_);
@@ -163,8 +163,8 @@ inline int128::operator long double() const {
#else // Clang on PowerPC
// Forward declaration for conversion operators to floating point types.
-constexpr int128 operator-(int128 v);
-constexpr bool operator!=(int128 lhs, int128 rhs);
+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
@@ -199,45 +199,51 @@ inline int128::operator long double() const {
// Comparison operators.
-constexpr bool operator==(int128 lhs, int128 rhs) {
+inline bool operator==(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) == static_cast<__int128>(rhs);
}
-constexpr bool operator!=(int128 lhs, int128 rhs) {
+inline bool operator!=(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) != static_cast<__int128>(rhs);
}
-constexpr bool operator<(int128 lhs, int128 rhs) {
+inline bool operator<(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) < static_cast<__int128>(rhs);
}
-constexpr bool operator>(int128 lhs, int128 rhs) {
+inline bool operator>(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) > static_cast<__int128>(rhs);
}
-constexpr bool operator<=(int128 lhs, int128 rhs) {
+inline bool operator<=(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) <= static_cast<__int128>(rhs);
}
-constexpr bool operator>=(int128 lhs, int128 rhs) {
+inline bool operator>=(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) >= static_cast<__int128>(rhs);
}
// Unary operators.
-constexpr int128 operator-(int128 v) { return -static_cast<__int128>(v); }
+inline int128 operator-(int128 v) {
+ return -static_cast<__int128>(v);
+}
-constexpr bool operator!(int128 v) { return !static_cast<__int128>(v); }
+inline bool operator!(int128 v) {
+ return !static_cast<__int128>(v);
+}
-constexpr int128 operator~(int128 val) { return ~static_cast<__int128>(val); }
+inline int128 operator~(int128 val) {
+ return ~static_cast<__int128>(val);
+}
// Arithmetic operators.
-constexpr int128 operator+(int128 lhs, int128 rhs) {
+inline int128 operator+(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) + static_cast<__int128>(rhs);
}
-constexpr int128 operator-(int128 lhs, int128 rhs) {
+inline int128 operator-(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) - static_cast<__int128>(rhs);
}
@@ -275,22 +281,22 @@ inline int128& int128::operator--() {
return *this;
}
-constexpr int128 operator|(int128 lhs, int128 rhs) {
+inline int128 operator|(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) | static_cast<__int128>(rhs);
}
-constexpr int128 operator&(int128 lhs, int128 rhs) {
+inline int128 operator&(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) & static_cast<__int128>(rhs);
}
-constexpr int128 operator^(int128 lhs, int128 rhs) {
+inline int128 operator^(int128 lhs, int128 rhs) {
return static_cast<__int128>(lhs) ^ static_cast<__int128>(rhs);
}
-constexpr int128 operator<<(int128 lhs, int amount) {
+inline int128 operator<<(int128 lhs, int amount) {
return static_cast<__int128>(lhs) << amount;
}
-constexpr int128 operator>>(int128 lhs, int amount) {
+inline int128 operator>>(int128 lhs, int amount) {
return static_cast<__int128>(lhs) >> amount;
}
diff --git a/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc b/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
index 8834804cec..c753771ae7 100644
--- a/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
+++ b/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc
@@ -134,6 +134,10 @@ 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
@@ -165,80 +169,76 @@ inline int128::operator long double() const {
// Comparison operators.
-constexpr bool operator==(int128 lhs, int128 rhs) {
+inline bool operator==(int128 lhs, int128 rhs) {
return (Int128Low64(lhs) == Int128Low64(rhs) &&
Int128High64(lhs) == Int128High64(rhs));
}
-constexpr bool operator!=(int128 lhs, int128 rhs) { return !(lhs == rhs); }
+inline bool operator!=(int128 lhs, int128 rhs) {
+ return !(lhs == rhs);
+}
-constexpr bool operator<(int128 lhs, int128 rhs) {
+inline bool operator<(int128 lhs, int128 rhs) {
return (Int128High64(lhs) == Int128High64(rhs))
? (Int128Low64(lhs) < Int128Low64(rhs))
: (Int128High64(lhs) < Int128High64(rhs));
}
-constexpr bool operator>(int128 lhs, int128 rhs) {
+inline bool operator>(int128 lhs, int128 rhs) {
return (Int128High64(lhs) == Int128High64(rhs))
? (Int128Low64(lhs) > Int128Low64(rhs))
: (Int128High64(lhs) > Int128High64(rhs));
}
-constexpr bool operator<=(int128 lhs, int128 rhs) { return !(lhs > rhs); }
+inline bool operator<=(int128 lhs, int128 rhs) {
+ return !(lhs > rhs);
+}
-constexpr bool operator>=(int128 lhs, int128 rhs) { return !(lhs < rhs); }
+inline bool operator>=(int128 lhs, int128 rhs) {
+ return !(lhs < rhs);
+}
// Unary operators.
-constexpr int128 operator-(int128 v) {
- return MakeInt128(~Int128High64(v) + (Int128Low64(v) == 0),
- ~Int128Low64(v) + 1);
+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);
}
-constexpr bool operator!(int128 v) {
+inline bool operator!(int128 v) {
return !Int128Low64(v) && !Int128High64(v);
}
-constexpr int128 operator~(int128 val) {
+inline int128 operator~(int128 val) {
return MakeInt128(~Int128High64(val), ~Int128Low64(val));
}
// Arithmetic operators.
-namespace int128_internal {
-constexpr int128 SignedAddResult(int128 result, int128 lhs) {
- // check for carry
- return (Int128Low64(result) < Int128Low64(lhs))
- ? MakeInt128(Int128High64(result) + 1, Int128Low64(result))
- : result;
-}
-} // namespace int128_internal
-constexpr int128 operator+(int128 lhs, int128 rhs) {
- return int128_internal::SignedAddResult(
- MakeInt128(Int128High64(lhs) + Int128High64(rhs),
- Int128Low64(lhs) + Int128Low64(rhs)),
- lhs);
+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;
}
-namespace int128_internal {
-constexpr int128 SignedSubstructResult(int128 result, int128 lhs, int128 rhs) {
- // check for carry
- return (Int128Low64(lhs) < Int128Low64(rhs))
- ? MakeInt128(Int128High64(result) - 1, Int128Low64(result))
- : result;
-}
-} // namespace int128_internal
-constexpr int128 operator-(int128 lhs, int128 rhs) {
- return int128_internal::SignedSubstructResult(
- MakeInt128(Int128High64(lhs) - Int128High64(rhs),
- Int128Low64(lhs) - Int128Low64(rhs)),
- lhs, rhs);
+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) {
- return MakeInt128(
- int128_internal::BitCastToSigned(Uint128High64(uint128(lhs) * rhs)),
- Uint128Low64(uint128(lhs) * rhs));
+ uint128 result = uint128(lhs) * rhs;
+ return MakeInt128(int128_internal::BitCastToSigned(Uint128High64(result)),
+ Uint128Low64(result));
}
inline int128 int128::operator++(int) {
@@ -263,49 +263,46 @@ inline int128& int128::operator--() {
return *this;
}
-constexpr int128 operator|(int128 lhs, int128 rhs) {
+inline int128 operator|(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) | Int128High64(rhs),
Int128Low64(lhs) | Int128Low64(rhs));
}
-constexpr int128 operator&(int128 lhs, int128 rhs) {
+inline int128 operator&(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) & Int128High64(rhs),
Int128Low64(lhs) & Int128Low64(rhs));
}
-constexpr int128 operator^(int128 lhs, int128 rhs) {
+inline int128 operator^(int128 lhs, int128 rhs) {
return MakeInt128(Int128High64(lhs) ^ Int128High64(rhs),
Int128Low64(lhs) ^ Int128Low64(rhs));
}
-constexpr int128 operator<<(int128 lhs, int amount) {
- // int64_t shifts of >= 64 are undefined, so we need some special-casing.
- return amount >= 64
- ? MakeInt128(
- static_cast<int64_t>(Int128Low64(lhs) << (amount - 64)), 0)
- : amount == 0
- ? lhs
- : MakeInt128(
- (Int128High64(lhs) << amount) |
- static_cast<int64_t>(Int128Low64(lhs) >> (64 - amount)),
- Int128Low64(lhs) << amount);
-}
-
-constexpr int128 operator>>(int128 lhs, int amount) {
- // int64_t shifts of >= 64 are undefined, so we need some special-casing.
- // The (Int128High64(lhs) >> 32) >> 32 "trick" causes the the most significant
- // int64 to be inititialized with all zeros or all ones correctly. It takes
- // into account whether the number is negative or positive, and whether the
- // current architecture does arithmetic or logical right shifts for negative
- // numbers.
- return amount >= 64
- ? MakeInt128(
- (Int128High64(lhs) >> 32) >> 32,
- static_cast<uint64_t>(Int128High64(lhs) >> (amount - 64)))
- : amount == 0
- ? lhs
- : MakeInt128(Int128High64(lhs) >> amount,
- (Int128Low64(lhs) >> amount) |
- (static_cast<uint64_t>(Int128High64(lhs))
- << (64 - amount)));
+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/third_party/abseil-cpp/absl/numeric/int128_test.cc b/third_party/abseil-cpp/absl/numeric/int128_test.cc
index dd9425d77a..bc86c714ac 100644
--- a/third_party/abseil-cpp/absl/numeric/int128_test.cc
+++ b/third_party/abseil-cpp/absl/numeric/int128_test.cc
@@ -226,11 +226,6 @@ TEST(Uint128, AllTests) {
EXPECT_EQ(test >>= 1, one);
EXPECT_EQ(test <<= 1, two);
- EXPECT_EQ(big, +big);
- EXPECT_EQ(two, +two);
- EXPECT_EQ(absl::Uint128Max(), +absl::Uint128Max());
- EXPECT_EQ(zero, +zero);
-
EXPECT_EQ(big, -(-big));
EXPECT_EQ(two, -((-one) - 1));
EXPECT_EQ(absl::Uint128Max(), -one);
@@ -239,24 +234,6 @@ TEST(Uint128, AllTests) {
EXPECT_EQ(absl::Uint128Max(), absl::kuint128max);
}
-TEST(Int128, RightShiftOfNegativeNumbers) {
- absl::int128 minus_six = -6;
- absl::int128 minus_three = -3;
- absl::int128 minus_two = -2;
- absl::int128 minus_one = -1;
- if ((-6 >> 1) == -3) {
- // Right shift is arithmetic (sign propagates)
- EXPECT_EQ(minus_six >> 1, minus_three);
- EXPECT_EQ(minus_six >> 2, minus_two);
- EXPECT_EQ(minus_six >> 65, minus_one);
- } else {
- // Right shift is logical (zeros shifted in at MSB)
- EXPECT_EQ(minus_six >> 1, absl::int128(absl::uint128(minus_six) >> 1));
- EXPECT_EQ(minus_six >> 2, absl::int128(absl::uint128(minus_six) >> 2));
- EXPECT_EQ(minus_six >> 65, absl::int128(absl::uint128(minus_six) >> 65));
- }
-}
-
TEST(Uint128, ConversionTests) {
EXPECT_TRUE(absl::MakeUint128(1, 0));
@@ -792,19 +769,6 @@ TEST(Int128, ComparisonTest) {
}
}
-TEST(Int128, UnaryPlusTest) {
- 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, UnaryNegationTest) {
int64_t values64[] = {0, 1, 12345, 0x4000000000000000,
std::numeric_limits<int64_t>::max()};
diff --git a/third_party/abseil-cpp/absl/numeric/internal/bits.h b/third_party/abseil-cpp/absl/numeric/internal/bits.h
deleted file mode 100644
index bfef06bce1..0000000000
--- a/third_party/abseil-cpp/absl/numeric/internal/bits.h
+++ /dev/null
@@ -1,358 +0,0 @@
-// 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/third_party/abseil-cpp/absl/numeric/internal/representation.h b/third_party/abseil-cpp/absl/numeric/internal/representation.h
deleted file mode 100644
index 82d332fdde..0000000000
--- a/third_party/abseil-cpp/absl/numeric/internal/representation.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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/third_party/abseil-cpp/absl/profiling/BUILD.bazel b/third_party/abseil-cpp/absl/profiling/BUILD.bazel
deleted file mode 100644
index 496a06b276..0000000000
--- a/third_party/abseil-cpp/absl/profiling/BUILD.bazel
+++ /dev/null
@@ -1,126 +0,0 @@
-# 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(
- "//absl:copts/configure_copts.bzl",
- "ABSL_DEFAULT_COPTS",
- "ABSL_DEFAULT_LINKOPTS",
- "ABSL_TEST_COPTS",
-)
-
-package(default_visibility = ["//visibility:private"])
-
-licenses(["notice"])
-
-cc_library(
- name = "sample_recorder",
- hdrs = ["internal/sample_recorder.h"],
- copts = ABSL_DEFAULT_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/synchronization",
- "//absl/time",
- ],
-)
-
-cc_test(
- name = "sample_recorder_test",
- srcs = ["internal/sample_recorder_test.cc"],
- linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- ":sample_recorder",
- "//absl/base:core_headers",
- "//absl/synchronization",
- "//absl/synchronization:thread_pool",
- "//absl/time",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
- name = "exponential_biased",
- srcs = ["internal/exponential_biased.cc"],
- hdrs = ["internal/exponential_biased.h"],
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- "//absl/base:config",
- "//absl/base:core_headers",
- ],
-)
-
-cc_test(
- name = "exponential_biased_test",
- size = "small",
- srcs = ["internal/exponential_biased_test.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":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,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":exponential_biased",
- "//absl/base:core_headers",
- ],
-)
-
-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 = [
- ":periodic_sampler",
- "//absl/base:core_headers",
- "@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 = [
- ":periodic_sampler",
- "//absl/base:core_headers",
- "@com_github_google_benchmark//:benchmark_main",
- ],
-)
diff --git a/third_party/abseil-cpp/absl/profiling/CMakeLists.txt b/third_party/abseil-cpp/absl/profiling/CMakeLists.txt
deleted file mode 100644
index 9b3a71021c..0000000000
--- a/third_party/abseil-cpp/absl/profiling/CMakeLists.txt
+++ /dev/null
@@ -1,93 +0,0 @@
-# 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.
-
-absl_cc_library(
- NAME
- sample_recorder
- HDRS
- "internal/sample_recorder.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base
- absl::synchronization
-)
-
-absl_cc_test(
- NAME
- sample_recorder_test
- SRCS
- "internal/sample_recorder_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::sample_recorder
- absl::time
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- exponential_biased
- SRCS
- "internal/exponential_biased.cc"
- HDRS
- "internal/exponential_biased.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::core_headers
-)
-
-absl_cc_test(
- NAME
- exponential_biased_test
- SRCS
- "internal/exponential_biased_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::exponential_biased
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- periodic_sampler
- SRCS
- "internal/periodic_sampler.cc"
- HDRS
- "internal/periodic_sampler.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::core_headers
- absl::exponential_biased
-)
-
-absl_cc_test(
- NAME
- periodic_sampler_test
- SRCS
- "internal/periodic_sampler_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::core_headers
- absl::periodic_sampler
- GTest::gmock_main
-)
-
diff --git a/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h b/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h
deleted file mode 100644
index 5e04a9cd19..0000000000
--- a/third_party/abseil-cpp/absl/profiling/internal/sample_recorder.h
+++ /dev/null
@@ -1,230 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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: sample_recorder.h
-// -----------------------------------------------------------------------------
-//
-// This header file defines a lock-free linked list for recording samples
-// collected from a random/stochastic process.
-//
-// This utility is internal-only. Use at your own risk.
-
-#ifndef ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_
-#define ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_
-
-#include <atomic>
-#include <cstddef>
-#include <functional>
-
-#include "absl/base/config.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
-
-// Sample<T> that has members required for linking samples in the linked list of
-// samples maintained by the SampleRecorder. Type T defines the sampled data.
-template <typename T>
-struct Sample {
- // Guards the ability to restore the sample to a pristine state. This
- // prevents races with sampling and resurrecting an object.
- absl::Mutex init_mu;
- T* next = nullptr;
- T* dead ABSL_GUARDED_BY(init_mu) = nullptr;
-};
-
-// Holds samples and their associated stack traces with a soft limit of
-// `SetHashtablezMaxSamples()`.
-//
-// Thread safe.
-template <typename T>
-class SampleRecorder {
- public:
- SampleRecorder();
- ~SampleRecorder();
-
- // Registers for sampling. Returns an opaque registration info.
- T* Register();
-
- // Unregisters the sample.
- void Unregister(T* 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 T&);
- 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 T& stack)>& f);
-
- void SetMaxSamples(int32_t max);
-
- private:
- void PushNew(T* sample);
- void PushDead(T* sample);
- T* PopDead();
-
- std::atomic<size_t> dropped_samples_;
- std::atomic<size_t> size_estimate_;
- std::atomic<int32_t> max_samples_{1 << 20};
-
- // 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<T*> all_;
- T graveyard_;
-
- std::atomic<DisposeCallback> dispose_;
-};
-
-template <typename T>
-typename SampleRecorder<T>::DisposeCallback
-SampleRecorder<T>::SetDisposeCallback(DisposeCallback f) {
- return dispose_.exchange(f, std::memory_order_relaxed);
-}
-
-template <typename T>
-SampleRecorder<T>::SampleRecorder()
- : dropped_samples_(0), size_estimate_(0), all_(nullptr), dispose_(nullptr) {
- absl::MutexLock l(&graveyard_.init_mu);
- graveyard_.dead = &graveyard_;
-}
-
-template <typename T>
-SampleRecorder<T>::~SampleRecorder() {
- T* s = all_.load(std::memory_order_acquire);
- while (s != nullptr) {
- T* next = s->next;
- delete s;
- s = next;
- }
-}
-
-template <typename T>
-void SampleRecorder<T>::PushNew(T* 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)) {
- }
-}
-
-template <typename T>
-void SampleRecorder<T>::PushDead(T* 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;
-}
-
-template <typename T>
-T* SampleRecorder<T>::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.
- T* sample = graveyard_.dead;
- if (sample == &graveyard_) return nullptr;
-
- absl::MutexLock sample_lock(&sample->init_mu);
- graveyard_.dead = sample->dead;
- sample->dead = nullptr;
- sample->PrepareForSampling();
- return sample;
-}
-
-template <typename T>
-T* SampleRecorder<T>::Register() {
- int64_t size = size_estimate_.fetch_add(1, std::memory_order_relaxed);
- if (size > max_samples_.load(std::memory_order_relaxed)) {
- size_estimate_.fetch_sub(1, std::memory_order_relaxed);
- dropped_samples_.fetch_add(1, std::memory_order_relaxed);
- return nullptr;
- }
-
- T* sample = PopDead();
- if (sample == nullptr) {
- // Resurrection failed. Hire a new warlock.
- sample = new T();
- PushNew(sample);
- }
-
- return sample;
-}
-
-template <typename T>
-void SampleRecorder<T>::Unregister(T* sample) {
- PushDead(sample);
- size_estimate_.fetch_sub(1, std::memory_order_relaxed);
-}
-
-template <typename T>
-int64_t SampleRecorder<T>::Iterate(
- const std::function<void(const T& stack)>& f) {
- T* 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);
-}
-
-template <typename T>
-void SampleRecorder<T>::SetMaxSamples(int32_t max) {
- max_samples_.store(max, std::memory_order_release);
-}
-
-} // namespace profiling_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_PROFILING_INTERNAL_SAMPLE_RECORDER_H_
diff --git a/third_party/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc b/third_party/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc
deleted file mode 100644
index ec6e0fa22d..0000000000
--- a/third_party/abseil-cpp/absl/profiling/internal/sample_recorder_test.cc
+++ /dev/null
@@ -1,171 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/profiling/internal/sample_recorder.h"
-
-#include <atomic>
-#include <random>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/synchronization/internal/thread_pool.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/synchronization/notification.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace profiling_internal {
-
-namespace {
-using ::absl::synchronization_internal::ThreadPool;
-using ::testing::IsEmpty;
-using ::testing::UnorderedElementsAre;
-
-struct Info : public Sample<Info> {
- public:
- void PrepareForSampling() {}
- std::atomic<size_t> size;
- absl::Time create_time;
-};
-
-std::vector<size_t> GetSizes(SampleRecorder<Info>* s) {
- std::vector<size_t> res;
- s->Iterate([&](const Info& info) {
- res.push_back(info.size.load(std::memory_order_acquire));
- });
- return res;
-}
-
-Info* Register(SampleRecorder<Info>* s, size_t size) {
- auto* info = s->Register();
- assert(info != nullptr);
- info->size.store(size);
- return info;
-}
-
-TEST(SampleRecorderTest, Registration) {
- SampleRecorder<Info> 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(SampleRecorderTest, Unregistration) {
- SampleRecorder<Info> sampler;
- std::vector<Info*> 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(SampleRecorderTest, MultiThreaded) {
- SampleRecorder<Info> 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<Info*> 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);
- Info* info = infoz[p];
- infoz[p] = infoz.back();
- infoz.pop_back();
- sampler.Unregister(info);
- break;
- }
- case 2: {
- absl::Duration oldest = absl::ZeroDuration();
- sampler.Iterate([&](const Info& 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(SampleRecorderTest, Callback) {
- SampleRecorder<Info> sampler;
-
- auto* info1 = Register(&sampler, 1);
- auto* info2 = Register(&sampler, 2);
-
- static const Info* expected;
-
- auto callback = [](const Info& 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 profiling_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/random/BUILD.bazel b/third_party/abseil-cpp/absl/random/BUILD.bazel
index fdde78b606..f78fbc7eed 100644
--- a/third_party/abseil-cpp/absl/random/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/random/BUILD.bazel
@@ -16,6 +16,7 @@
# 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",
@@ -52,6 +53,7 @@ cc_library(
"bernoulli_distribution.h",
"beta_distribution.h",
"discrete_distribution.h",
+ "distribution_format_traits.h",
"distributions.h",
"exponential_distribution.h",
"gaussian_distribution.h",
@@ -68,8 +70,7 @@ cc_library(
"//absl/base:config",
"//absl/base:core_headers",
"//absl/meta:type_traits",
- "//absl/numeric:bits",
- "//absl/random/internal:distribution_caller",
+ "//absl/random/internal:distributions",
"//absl/random/internal:fast_uniform_bits",
"//absl/random/internal:fastmath",
"//absl/random/internal:generate_real",
@@ -78,6 +79,7 @@ cc_library(
"//absl/random/internal:uniform_helper",
"//absl/random/internal:wide_multiply",
"//absl/strings",
+ "//absl/types:span",
],
)
@@ -115,12 +117,11 @@ cc_library(
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",
+ "//absl/random/internal:mocking_bit_gen_base",
],
)
@@ -140,17 +141,20 @@ cc_library(
cc_library(
name = "mocking_bit_gen",
testonly = 1,
+ srcs = [
+ "mocking_bit_gen.cc",
+ ],
hdrs = [
"mocking_bit_gen.h",
],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":distributions",
- ":random",
- "//absl/base:fast_type_id",
+ "//absl/base:raw_logging_internal",
"//absl/container:flat_hash_map",
"//absl/meta:type_traits",
"//absl/random/internal:distribution_caller",
+ "//absl/random/internal:mocking_bit_gen_base",
"//absl/strings",
"//absl/types:span",
"//absl/types:variant",
@@ -169,7 +173,6 @@ cc_test(
deps = [
":distributions",
":random",
- "//absl/random/internal:pcg_engine",
"//absl/random/internal:sequence_urbg",
"@com_google_googletest//:gtest_main",
],
@@ -187,9 +190,7 @@ cc_test(
":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",
@@ -200,7 +201,6 @@ cc_test(
cc_test(
name = "distributions_test",
size = "small",
- timeout = "moderate",
srcs = [
"distributions_test.cc",
],
@@ -238,9 +238,9 @@ cc_test(
deps = [
":distributions",
":random",
+ "//absl/base:core_headers",
"//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",
@@ -261,7 +261,6 @@ cc_test(
":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",
@@ -289,7 +288,6 @@ cc_test(
"//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",
@@ -308,9 +306,7 @@ cc_test(
":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",
@@ -332,7 +328,6 @@ cc_test(
":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",
@@ -355,7 +350,6 @@ cc_test(
":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",
@@ -379,9 +373,7 @@ cc_test(
":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",
@@ -401,7 +393,6 @@ cc_test(
":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",
@@ -417,7 +408,6 @@ cc_test(
deps = [
":bit_gen_ref",
":random",
- "//absl/base:fast_type_id",
"//absl/random/internal:sequence_urbg",
"@com_google_googletest//:gtest_main",
],
@@ -427,7 +417,6 @@ 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",
@@ -442,8 +431,6 @@ 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",
diff --git a/third_party/abseil-cpp/absl/random/CMakeLists.txt b/third_party/abseil-cpp/absl/random/CMakeLists.txt
index 9d1c67fb33..efa55d8fa7 100644
--- a/third_party/abseil-cpp/absl/random/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/random/CMakeLists.txt
@@ -45,6 +45,7 @@ absl_cc_library(
absl::core_headers
absl::random_internal_distribution_caller
absl::random_internal_fast_uniform_bits
+ absl::random_internal_mocking_bit_gen_base
absl::type_traits
)
@@ -61,24 +62,23 @@ absl_cc_test(
absl::random_bit_gen_ref
absl::random_random
absl::random_internal_sequence_urbg
- absl::fast_type_id
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
absl_cc_library(
NAME
- random_internal_mock_helpers
+ random_internal_mocking_bit_gen_base
HDRS
- "internal/mock_helpers.h"
+ "internal/mocking_bit_gen_base.h"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::fast_type_id
- absl::optional
+ absl::random_random
+ absl::strings
)
# Internal-only target, do not depend on directly.
@@ -93,7 +93,6 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_mocking_bit_gen
- absl::random_internal_mock_helpers
TESTONLY
)
@@ -103,6 +102,8 @@ absl_cc_library(
HDRS
"mock_distributions.h"
"mocking_bit_gen.h"
+ SRCS
+ "mocking_bit_gen.cc"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
@@ -112,15 +113,15 @@ absl_cc_library(
absl::raw_logging_internal
absl::random_distributions
absl::random_internal_distribution_caller
+ absl::random_internal_mocking_bit_gen_base
absl::random_internal_mock_overload_set
- absl::random_random
absl::strings
absl::span
absl::type_traits
absl::utility
absl::variant
- GTest::gmock
- GTest::gtest
+ gmock
+ gtest
TESTONLY
)
@@ -136,8 +137,8 @@ absl_cc_test(
DEPS
absl::random_mocking_bit_gen
absl::random_random
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -153,8 +154,8 @@ absl_cc_test(
absl::random_bit_gen_ref
absl::random_mocking_bit_gen
absl::random_random
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_library(
@@ -167,6 +168,7 @@ absl_cc_library(
"bernoulli_distribution.h"
"beta_distribution.h"
"discrete_distribution.h"
+ "distribution_format_traits.h"
"distributions.h"
"exponential_distribution.h"
"gaussian_distribution.h"
@@ -184,7 +186,7 @@ absl_cc_library(
absl::config
absl::core_headers
absl::random_internal_generate_real
- absl::random_internal_distribution_caller
+ absl::random_internal_distributions
absl::random_internal_fast_uniform_bits
absl::random_internal_fastmath
absl::random_internal_iostream_state_saver
@@ -192,6 +194,7 @@ absl_cc_library(
absl::random_internal_uniform_helper
absl::random_internal_wide_multiply
absl::strings
+ absl::span
absl::type_traits
)
@@ -244,9 +247,8 @@ absl_cc_test(
absl::random_distributions
absl::random_random
absl::random_internal_sequence_urbg
- absl::random_internal_pcg_engine
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -259,17 +261,15 @@ absl_cc_test(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::numeric_representation
absl::random_distributions
absl::random_random
absl::random_internal_distribution_test_util
absl::random_internal_sequence_urbg
- absl::random_internal_pcg_engine
absl::raw_logging_internal
absl::strings
absl::str_format
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -285,8 +285,8 @@ absl_cc_test(
absl::random_distributions
absl::random_random
absl::random_internal_distribution_test_util
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -301,8 +301,8 @@ absl_cc_test(
absl::random_distributions
absl::random_random
absl::raw_logging_internal
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -314,16 +314,16 @@ absl_cc_test(
${ABSL_TEST_COPTS}
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
+ absl::core_headers
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::raw_logging_internal
absl::strings
absl::str_format
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -338,13 +338,12 @@ absl_cc_test(
DEPS
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::raw_logging_internal
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -362,13 +361,12 @@ absl_cc_test(
absl::core_headers
absl::flat_hash_map
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::raw_logging_internal
absl::strings
absl::str_format
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -382,17 +380,15 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::core_headers
- absl::numeric_representation
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::raw_logging_internal
absl::strings
absl::str_format
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -406,7 +402,6 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::core_headers
- absl::numeric_representation
absl::random_distributions
absl::random_internal_distribution_test_util
absl::random_internal_sequence_urbg
@@ -414,8 +409,8 @@ absl_cc_test(
absl::raw_logging_internal
absl::strings
absl::str_format
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -430,13 +425,12 @@ absl_cc_test(
DEPS
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::raw_logging_internal
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -449,15 +443,13 @@ absl_cc_test(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::numeric_representation
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -472,13 +464,12 @@ absl_cc_test(
DEPS
absl::random_distributions
absl::random_internal_distribution_test_util
- absl::random_internal_pcg_engine
absl::random_internal_sequence_urbg
absl::random_random
absl::raw_logging_internal
absl::strings
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
absl_cc_test(
@@ -492,7 +483,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_random
- GTest::gtest_main
+ gtest_main
)
absl_cc_test(
@@ -508,8 +499,8 @@ absl_cc_test(
absl::random_seed_sequences
absl::random_internal_nonsecure_base
absl::random_random
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -538,8 +529,27 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::utility
- absl::fast_type_id
+)
+
+# Internal-only target, do not depend on directly.
+absl_cc_library(
+ NAME
+ random_internal_distributions
+ HDRS
+ "internal/distributions.h"
+ COPTS
+ ${ABSL_DEFAULT_COPTS}
+ LINKOPTS
+ ${ABSL_DEFAULT_LINKOPTS}
+ DEPS
+ absl::random_internal_distribution_caller
+ absl::random_internal_fast_uniform_bits
+ absl::random_internal_fastmath
+ absl::random_internal_traits
+ absl::random_internal_uniform_helper
+ absl::span
+ absl::strings
+ absl::type_traits
)
# Internal-only target, do not depend on directly.
@@ -615,7 +625,6 @@ absl_cc_library(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::config
- absl::endian
TESTONLY
)
@@ -731,6 +740,7 @@ absl_cc_library(
absl::random_internal_salted_seed_seq
absl::random_internal_seed_material
absl::span
+ absl::strings
absl::type_traits
)
@@ -763,7 +773,6 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::endian
absl::random_internal_iostream_state_saver
absl::random_internal_randen
absl::raw_logging_internal
@@ -776,9 +785,8 @@ absl_cc_library(
random_internal_platform
HDRS
"internal/randen_traits.h"
+ "internal/randen-keys.inc"
"internal/platform.h"
- SRCS
- "internal/randen_round_keys.cc"
COPTS
${ABSL_DEFAULT_COPTS}
LINKOPTS
@@ -894,7 +902,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_traits
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -911,7 +919,7 @@ absl_cc_test(
absl::bits
absl::flags
absl::random_internal_generate_real
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -926,7 +934,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_distribution_test_util
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -941,7 +949,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_fastmath
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -957,8 +965,8 @@ absl_cc_test(
DEPS
absl::random_internal_explicit_seed_seq
absl::random_seed_sequences
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -973,8 +981,8 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_salted_seed_seq
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -990,7 +998,7 @@ absl_cc_test(
DEPS
absl::core_headers
absl::random_internal_distribution_test_util
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1005,7 +1013,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_fast_uniform_bits
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1024,7 +1032,7 @@ absl_cc_test(
absl::random_distributions
absl::random_seed_sequences
absl::strings
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1039,8 +1047,8 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_seed_material
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1057,7 +1065,7 @@ absl_cc_test(
absl::random_internal_pool_urbg
absl::span
absl::type_traits
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1074,8 +1082,8 @@ absl_cc_test(
absl::random_internal_explicit_seed_seq
absl::random_internal_pcg_engine
absl::time
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1094,8 +1102,8 @@ absl_cc_test(
absl::raw_logging_internal
absl::strings
absl::time
- GTest::gmock
- GTest::gtest_main
+ gmock
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1111,7 +1119,7 @@ absl_cc_test(
DEPS
absl::random_internal_randen
absl::type_traits
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1125,9 +1133,8 @@ absl_cc_test(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::endian
absl::random_internal_randen_slow
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1146,8 +1153,8 @@ absl_cc_test(
absl::random_internal_randen_hwaes_impl
absl::raw_logging_internal
absl::str_format
- GTest::gmock
- GTest::gtest
+ gmock
+ gtest
)
# Internal-only target, do not depend on directly.
@@ -1161,7 +1168,9 @@ absl_cc_library(
LINKOPTS
${ABSL_DEFAULT_LINKOPTS}
DEPS
- absl::config
+ absl::core_headers
+ absl::random_internal_fast_uniform_bits
+ absl::random_internal_iostream_state_saver
absl::random_internal_traits
absl::type_traits
)
@@ -1169,21 +1178,6 @@ absl_cc_library(
# Internal-only target, do not depend on directly.
absl_cc_test(
NAME
- random_internal_uniform_helper_test
- SRCS
- "internal/uniform_helper_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- LINKOPTS
- ${ABSL_DEFAULT_LINKOPTS}
- DEPS
- absl::random_internal_uniform_helper
- GTest::gtest_main
-)
-
-# Internal-only target, do not depend on directly.
-absl_cc_test(
- NAME
random_internal_iostream_state_saver_test
SRCS
"internal/iostream_state_saver_test.cc"
@@ -1193,7 +1187,7 @@ absl_cc_test(
${ABSL_DEFAULT_LINKOPTS}
DEPS
absl::random_internal_iostream_state_saver
- GTest::gtest_main
+ gtest_main
)
# Internal-only target, do not depend on directly.
@@ -1210,5 +1204,5 @@ absl_cc_test(
absl::random_internal_wide_multiply
absl::bits
absl::int128
- GTest::gtest_main
+ gtest_main
)
diff --git a/third_party/abseil-cpp/absl/random/bernoulli_distribution_test.cc b/third_party/abseil-cpp/absl/random/bernoulli_distribution_test.cc
index b250f8787c..f2c3b99cd4 100644
--- a/third_party/abseil-cpp/absl/random/bernoulli_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/bernoulli_distribution_test.cc
@@ -21,7 +21,6 @@
#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"
@@ -64,10 +63,7 @@ TEST_P(BernoulliTest, Accuracy) {
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);
+ absl::InsecureBitGen rng;
size_t yes = 0;
absl::bernoulli_distribution dist(p);
@@ -135,7 +131,7 @@ TEST(BernoulliTest, StabilityTest) {
0x275b0dc7e0a18acfull, 0x36cebe0d2653682eull, 0x0361e9b23861596bull,
});
- // Generate a string of '0' and '1' for the distribution output.
+ // Generate a std::string of '0' and '1' for the distribution output.
auto generate = [&urbg](absl::bernoulli_distribution& dist) {
std::string output;
output.reserve(36);
@@ -180,7 +176,7 @@ TEST(BernoulliTest, StabilityTest2) {
0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull, 0x0334FE1EAA0363CFull,
0xB5735C904C70A239ull, 0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull});
- // Generate a string of '0' and '1' for the distribution output.
+ // Generate a std::string of '0' and '1' for the distribution output.
auto generate = [&urbg](absl::bernoulli_distribution& dist) {
std::string output;
output.reserve(13);
diff --git a/third_party/abseil-cpp/absl/random/beta_distribution_test.cc b/third_party/abseil-cpp/absl/random/beta_distribution_test.cc
index d980c969f7..d0111b3e3a 100644
--- a/third_party/abseil-cpp/absl/random/beta_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/beta_distribution_test.cc
@@ -15,24 +15,20 @@
#include "absl/random/beta_distribution.h"
#include <algorithm>
-#include <cfloat>
#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"
@@ -45,15 +41,7 @@ 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;
+using RealTypes = ::testing::Types<float, double, long double>;
TYPED_TEST_CASE(BetaDistributionInterfaceTest, RealTypes);
TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
@@ -64,6 +52,9 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
const TypeParam kLargeA =
std::exp(std::log((std::numeric_limits<TypeParam>::max)()) -
std::log(std::log((std::numeric_limits<TypeParam>::max)())));
+ const TypeParam kLargeAPPC = std::exp(
+ std::log((std::numeric_limits<TypeParam>::max)()) -
+ std::log(std::log((std::numeric_limits<TypeParam>::max)())) - 10.0f);
using param_type = typename absl::beta_distribution<TypeParam>::param_type;
constexpr int kCount = 1000;
@@ -84,6 +75,9 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
kLargeA, //
std::nextafter(kLargeA, TypeParam(0)), //
std::nextafter(kLargeA, std::numeric_limits<TypeParam>::max()),
+ kLargeAPPC, //
+ std::nextafter(kLargeAPPC, TypeParam(0)),
+ std::nextafter(kLargeAPPC, std::numeric_limits<TypeParam>::max()),
// Boundary cases.
std::numeric_limits<TypeParam>::max(),
std::numeric_limits<TypeParam>::epsilon(),
@@ -130,6 +124,28 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
ss >> after;
+#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__PPC__)
+ if (std::is_same<TypeParam, long double>::value) {
+ // Roundtripping floating point values requires sufficient precision
+ // to reconstruct the exact value. It turns out that long double
+ // has some errors doing this on ppc.
+ if (alpha <= std::numeric_limits<double>::max() &&
+ alpha >= std::numeric_limits<double>::lowest()) {
+ EXPECT_EQ(static_cast<double>(before.alpha()),
+ static_cast<double>(after.alpha()))
+ << ss.str();
+ }
+ if (beta <= std::numeric_limits<double>::max() &&
+ beta >= std::numeric_limits<double>::lowest()) {
+ EXPECT_EQ(static_cast<double>(before.beta()),
+ static_cast<double>(after.beta()))
+ << ss.str();
+ }
+ continue;
+ }
+#endif
+
EXPECT_EQ(before.alpha(), after.alpha());
EXPECT_EQ(before.beta(), after.beta());
EXPECT_EQ(before, after) //
@@ -143,12 +159,8 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) {
}
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.
+ absl::InsecureBitGen gen;
constexpr int kCount = 1000;
const TypeParam kSmallValues[] = {
std::numeric_limits<TypeParam>::min(),
@@ -174,7 +186,7 @@ TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
int ones = 0;
absl::beta_distribution<TypeParam> d(alpha, beta);
for (int i = 0; i < kCount; ++i) {
- TypeParam x = d(rng);
+ TypeParam x = d(gen);
if (x == 0.0) {
zeros++;
} else if (x == 1.0) {
@@ -200,7 +212,7 @@ TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
for (TypeParam beta : kLargeValues) {
absl::beta_distribution<TypeParam> d(alpha, beta);
for (int i = 0; i < kCount; ++i) {
- EXPECT_EQ(d(rng), 0.0);
+ EXPECT_EQ(d(gen), 0.0);
}
}
}
@@ -215,7 +227,7 @@ TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
for (TypeParam beta : kSmallValues) {
absl::beta_distribution<TypeParam> d(alpha, beta);
for (int i = 0; i < kCount; ++i) {
- EXPECT_EQ(d(rng), 1.0);
+ EXPECT_EQ(d(gen), 1.0);
}
}
}
@@ -225,7 +237,7 @@ TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
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);
+ EXPECT_EQ(d(gen), 0.5);
}
}
{
@@ -234,7 +246,7 @@ TYPED_TEST(BetaDistributionInterfaceTest, DegenerateCases) {
std::numeric_limits<TypeParam>::max(),
std::numeric_limits<TypeParam>::max() * 0.9999);
for (int i = 0; i < kCount; ++i) {
- TypeParam x = d(rng);
+ TypeParam x = d(gen);
EXPECT_NE(x, 0.5f);
EXPECT_FLOAT_EQ(x, 0.500025f);
}
@@ -559,14 +571,6 @@ TEST(BetaDistributionTest, StabilityTest) {
// dependencies of the distribution change, such as RandU64ToDouble, then this
// is also likely to change.
TEST(BetaDistributionTest, AlgorithmBounds) {
-#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
- // We're using an x87-compatible FPU, and intermediate operations are
- // performed with 80-bit floats. This produces slightly different results from
- // what we expect below.
- GTEST_SKIP()
- << "Skipping the test because we detected x87 floating-point semantics";
-#endif
-
{
absl::random_internal::sequence_urbg urbg(
{0x7fbe76c8b4395800ull, 0x8000000000000000ull});
diff --git a/third_party/abseil-cpp/absl/random/bit_gen_ref.h b/third_party/abseil-cpp/absl/random/bit_gen_ref.h
index 9555460fd4..e8771162e5 100644
--- a/third_party/abseil-cpp/absl/random/bit_gen_ref.h
+++ b/third_party/abseil-cpp/absl/random/bit_gen_ref.h
@@ -24,11 +24,11 @@
#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"
+#include "absl/random/internal/mocking_bit_gen_base.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -51,10 +51,6 @@ struct is_urbg<
typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
: std::true_type {};
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
-
} // namespace random_internal
// -----------------------------------------------------------------------------
@@ -81,50 +77,23 @@ class MockHelpers;
// }
//
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>) {}
+ using result_type = uint64_t;
+
+ BitGenRef(const absl::BitGenRef&) = default;
+ BitGenRef(absl::BitGenRef&&) = default;
+ BitGenRef& operator=(const absl::BitGenRef&) = default;
+ BitGenRef& operator=(absl::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>
+ typename absl::enable_if_t<
+ (!std::is_same<URBG, BitGenRef>::value &&
+ random_internal::is_urbg<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;
+ : mocked_gen_ptr_(MakeMockPointer(&gen)),
+ t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
+ generate_impl_fn_(ImplFn<URBG>) {
+ }
static constexpr result_type(min)() {
return (std::numeric_limits<result_type>::min)();
@@ -137,9 +106,14 @@ class BitGenRef {
result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
private:
+ friend struct absl::random_internal::DistributionCaller<absl::BitGenRef>;
using impl_fn = result_type (*)(uintptr_t);
- using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
- void*);
+ using mocker_base_t = absl::random_internal::MockingBitGenBase;
+
+ // Convert an arbitrary URBG pointer into either a valid mocker_base_t
+ // pointer or a nullptr.
+ static inline mocker_base_t* MakeMockPointer(mocker_base_t* t) { return t; }
+ static inline mocker_base_t* MakeMockPointer(void*) { return nullptr; }
template <typename URBG>
static result_type ImplFn(uintptr_t ptr) {
@@ -149,32 +123,30 @@ class BitGenRef {
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);
- }
-
+ mocker_base_t* mocked_gen_ptr_;
uintptr_t t_erased_gen_ptr_;
- mock_call_fn mock_call_;
impl_fn generate_impl_fn_;
+};
+
+namespace random_internal {
- template <typename>
- friend struct ::absl::random_internal::DistributionCaller; // for InvokeMock
- friend class ::absl::random_internal::MockHelpers; // for InvokeMock
+template <>
+struct DistributionCaller<absl::BitGenRef> {
+ template <typename DistrT, typename FormatT, typename... Args>
+ static typename DistrT::result_type Call(absl::BitGenRef* gen_ref,
+ Args&&... args) {
+ auto* mock_ptr = gen_ref->mocked_gen_ptr_;
+ if (mock_ptr == nullptr) {
+ DistrT dist(std::forward<Args>(args)...);
+ return dist(*gen_ref);
+ } else {
+ return mock_ptr->template Call<DistrT, FormatT>(
+ std::forward<Args>(args)...);
+ }
+ }
};
+} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/random/bit_gen_ref_test.cc b/third_party/abseil-cpp/absl/random/bit_gen_ref_test.cc
index 1135cf2da0..ca0e4d7072 100644
--- a/third_party/abseil-cpp/absl/random/bit_gen_ref_test.cc
+++ b/third_party/abseil-cpp/absl/random/bit_gen_ref_test.cc
@@ -17,31 +17,30 @@
#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) {
+class ConstBitGen : public absl::random_internal::MockingBitGenBase {
+ bool CallImpl(const std::type_info&, void*, void* result) override {
*static_cast<int*>(result) = 42;
return true;
}
};
-namespace {
+namespace random_internal {
+template <>
+struct DistributionCaller<ConstBitGen> {
+ template <typename DistrT, typename FormatT, typename... Args>
+ static typename DistrT::result_type Call(ConstBitGen* gen, Args&&... args) {
+ return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
+ }
+};
+} // namespace random_internal
+namespace {
int FnTest(absl::BitGenRef gen_ref) { return absl::Uniform(gen_ref, 1, 7); }
template <typename T>
diff --git a/third_party/abseil-cpp/absl/random/discrete_distribution_test.cc b/third_party/abseil-cpp/absl/random/discrete_distribution_test.cc
index 415b14cc76..7296f0ac22 100644
--- a/third_party/abseil-cpp/absl/random/discrete_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/discrete_distribution_test.cc
@@ -29,7 +29,6 @@
#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"
@@ -99,7 +98,6 @@ TYPED_TEST(DiscreteDistributionTypeTest, Constructor) {
}
TEST(DiscreteDistributionTest, InitDiscreteDistribution) {
- using testing::_;
using testing::Pair;
{
@@ -112,8 +110,8 @@ TEST(DiscreteDistributionTest, InitDiscreteDistribution) {
// 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, _), //
- Pair(1.0, _)));
+ Pair(1.0, 1), //
+ Pair(1.0, 2)));
}
{
@@ -136,7 +134,7 @@ TEST(DiscreteDistributionTest, InitDiscreteDistribution) {
EXPECT_THAT(q, testing::ElementsAre(Pair(b0, 3), //
Pair(b1, 3), //
- Pair(1.0, _), //
+ Pair(1.0, 2), //
Pair(b3, 2), //
Pair(b1, 3)));
}
@@ -158,10 +156,7 @@ TEST(DiscreteDistributionTest, ChiSquaredTest50) {
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);
+ absl::InsecureBitGen rng;
std::vector<int32_t> counts(kBuckets, 0);
for (size_t i = 0; i < kTrials; i++) {
diff --git a/third_party/abseil-cpp/absl/random/distribution_format_traits.h b/third_party/abseil-cpp/absl/random/distribution_format_traits.h
new file mode 100644
index 0000000000..22b358cc8c
--- /dev/null
+++ b/third_party/abseil-cpp/absl/random/distribution_format_traits.h
@@ -0,0 +1,278 @@
+//
+// 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_DISTRIBUTION_FORMAT_TRAITS_H_
+#define ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
+
+#include <string>
+#include <tuple>
+#include <typeinfo>
+
+#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/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"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+struct IntervalClosedClosedTag;
+struct IntervalClosedOpenTag;
+struct IntervalOpenClosedTag;
+struct IntervalOpenOpenTag;
+
+namespace random_internal {
+
+// ScalarTypeName defines a preferred hierarchy of preferred type names for
+// scalars, and is evaluated at compile time for the specific type
+// specialization.
+template <typename T>
+constexpr const char* ScalarTypeName() {
+ static_assert(std::is_integral<T>() || std::is_floating_point<T>(), "");
+ // clang-format off
+ return
+ std::is_same<T, float>::value ? "float" :
+ std::is_same<T, double>::value ? "double" :
+ std::is_same<T, long double>::value ? "long double" :
+ std::is_same<T, bool>::value ? "bool" :
+ std::is_signed<T>::value && sizeof(T) == 1 ? "int8_t" :
+ std::is_signed<T>::value && sizeof(T) == 2 ? "int16_t" :
+ std::is_signed<T>::value && sizeof(T) == 4 ? "int32_t" :
+ std::is_signed<T>::value && sizeof(T) == 8 ? "int64_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 1 ? "uint8_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 2 ? "uint16_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 4 ? "uint32_t" :
+ std::is_unsigned<T>::value && sizeof(T) == 8 ? "uint64_t" :
+ "undefined";
+ // clang-format on
+
+ // NOTE: It would be nice to use typeid(T).name(), but that's an
+ // implementation-defined attribute which does not necessarily
+ // correspond to a name. We could potentially demangle it
+ // using, e.g. abi::__cxa_demangle.
+}
+
+// Distribution traits used by DistributionCaller and internal implementation
+// details of the mocking framework.
+/*
+struct DistributionFormatTraits {
+ // Returns the parameterized name of the distribution function.
+ static constexpr const char* FunctionName()
+ // Format DistrT parameters.
+ static std::string FormatArgs(DistrT& dist);
+ // Format DistrT::result_type results.
+ static std::string FormatResults(DistrT& dist);
+};
+*/
+template <typename DistrT>
+struct DistributionFormatTraits;
+
+template <typename R>
+struct DistributionFormatTraits<absl::uniform_int_distribution<R>> {
+ using distribution_t = absl::uniform_int_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat("absl::IntervalClosedClosed, ", (d.min)(), ", ",
+ (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::uniform_real_distribution<R>> {
+ using distribution_t = absl::uniform_real_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat((d.min)(), ", ", (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::exponential_distribution<R>> {
+ using distribution_t = absl::exponential_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Exponential"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.lambda());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::poisson_distribution<R>> {
+ using distribution_t = absl::poisson_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Poisson"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.mean());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <>
+struct DistributionFormatTraits<absl::bernoulli_distribution> {
+ using distribution_t = absl::bernoulli_distribution;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Bernoulli"; }
+
+ static constexpr const char* FunctionName() { return Name(); }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.p());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::beta_distribution<R>> {
+ using distribution_t = absl::beta_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Beta"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.alpha(), ", ", d.beta());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::zipf_distribution<R>> {
+ using distribution_t = absl::zipf_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Zipf"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat(d.k(), ", ", d.v(), ", ", d.q());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::gaussian_distribution<R>> {
+ using distribution_t = absl::gaussian_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "Gaussian"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrJoin(std::make_tuple(d.mean(), d.stddev()), ", ");
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename R>
+struct DistributionFormatTraits<absl::log_uniform_int_distribution<R>> {
+ using distribution_t = absl::log_uniform_int_distribution<R>;
+ using result_t = typename distribution_t::result_type;
+
+ static constexpr const char* Name() { return "LogUniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<R>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrJoin(std::make_tuple((d.min)(), (d.max)(), d.base()), ", ");
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+template <typename NumType>
+struct UniformDistributionWrapper;
+
+template <typename NumType>
+struct DistributionFormatTraits<UniformDistributionWrapper<NumType>> {
+ using distribution_t = UniformDistributionWrapper<NumType>;
+ using result_t = NumType;
+
+ static constexpr const char* Name() { return "Uniform"; }
+
+ static std::string FunctionName() {
+ return absl::StrCat(Name(), "<", ScalarTypeName<NumType>(), ">");
+ }
+ static std::string FormatArgs(const distribution_t& d) {
+ return absl::StrCat((d.min)(), ", ", (d.max)());
+ }
+ static std::string FormatResults(absl::Span<const result_t> results) {
+ return absl::StrJoin(results, ", ");
+ }
+};
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_DISTRIBUTION_FORMAT_TRAITS_H_
diff --git a/third_party/abseil-cpp/absl/random/distributions.h b/third_party/abseil-cpp/absl/random/distributions.h
index 31c79694e5..d026d92b90 100644
--- a/third_party/abseil-cpp/absl/random/distributions.h
+++ b/third_party/abseil-cpp/absl/random/distributions.h
@@ -55,9 +55,10 @@
#include "absl/base/internal/inline_variable.h"
#include "absl/random/bernoulli_distribution.h"
#include "absl/random/beta_distribution.h"
+#include "absl/random/distribution_format_traits.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/distributions.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"
@@ -125,13 +126,14 @@ Uniform(TagType tag,
R lo, R hi) {
using gen_t = absl::decay_t<URBG>;
using distribution_t = random_internal::UniformDistributionWrapper<R>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
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;
+ if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, tag, lo, hi);
+ distribution_t, format_t>(&urbg, tag, lo, hi);
}
// absl::Uniform<T>(bitgen, lo, hi)
@@ -144,14 +146,15 @@ 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;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
+ 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;
+ if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lo, hi);
+ distribution_t, format_t>(&urbg, lo, hi);
}
// absl::Uniform(tag, bitgen, lo, hi)
@@ -169,13 +172,14 @@ Uniform(TagType tag,
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>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_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;
+ if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, tag, static_cast<return_t>(lo),
+ distribution_t, format_t>(&urbg, tag, static_cast<return_t>(lo),
static_cast<return_t>(hi));
}
@@ -192,14 +196,15 @@ Uniform(URBG&& urbg, // NOLINT(runtime/references)
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>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_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;
+ if (a > b) return a;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, static_cast<return_t>(lo),
+ distribution_t, format_t>(&urbg, static_cast<return_t>(lo),
static_cast<return_t>(hi));
}
@@ -212,9 +217,10 @@ 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>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg);
+ distribution_t, format_t>(&urbg);
}
// -----------------------------------------------------------------------------
@@ -242,9 +248,10 @@ bool Bernoulli(URBG&& urbg, // NOLINT(runtime/references)
double p) {
using gen_t = absl::decay_t<URBG>;
using distribution_t = absl::bernoulli_distribution;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, p);
+ distribution_t, format_t>(&urbg, p);
}
// -----------------------------------------------------------------------------
@@ -274,9 +281,10 @@ RealType Beta(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::beta_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, alpha, beta);
+ distribution_t, format_t>(&urbg, alpha, beta);
}
// -----------------------------------------------------------------------------
@@ -306,9 +314,10 @@ RealType Exponential(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::exponential_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lambda);
+ distribution_t, format_t>(&urbg, lambda);
}
// -----------------------------------------------------------------------------
@@ -337,9 +346,10 @@ RealType Gaussian(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::gaussian_distribution<RealType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, mean, stddev);
+ distribution_t, format_t>(&urbg, mean, stddev);
}
// -----------------------------------------------------------------------------
@@ -379,9 +389,10 @@ IntType LogUniform(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::log_uniform_int_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, lo, hi, base);
+ distribution_t, format_t>(&urbg, lo, hi, base);
}
// -----------------------------------------------------------------------------
@@ -409,9 +420,10 @@ IntType Poisson(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::poisson_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, mean);
+ distribution_t, format_t>(&urbg, mean);
}
// -----------------------------------------------------------------------------
@@ -441,9 +453,10 @@ IntType Zipf(URBG&& urbg, // NOLINT(runtime/references)
using gen_t = absl::decay_t<URBG>;
using distribution_t = typename absl::zipf_distribution<IntType>;
+ using format_t = random_internal::DistributionFormatTraits<distribution_t>;
return random_internal::DistributionCaller<gen_t>::template Call<
- distribution_t>(&urbg, hi, q, v);
+ distribution_t, format_t>(&urbg, hi, q, v);
}
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/random/distributions_test.cc b/third_party/abseil-cpp/absl/random/distributions_test.cc
index d3a5dd75e5..2d92723ad2 100644
--- a/third_party/abseil-cpp/absl/random/distributions_test.cc
+++ b/third_party/abseil-cpp/absl/random/distributions_test.cc
@@ -14,7 +14,6 @@
#include "absl/random/distributions.h"
-#include <cfloat>
#include <cmath>
#include <cstdint>
#include <random>
@@ -30,6 +29,94 @@ constexpr int kSize = 400000;
class RandomDistributionsTest : public testing::Test {};
+TEST_F(RandomDistributionsTest, UniformBoundFunctions) {
+ using absl::IntervalClosedClosed;
+ using absl::IntervalClosedOpen;
+ using absl::IntervalOpenClosed;
+ using absl::IntervalOpenOpen;
+ using absl::random_internal::uniform_lower_bound;
+ using absl::random_internal::uniform_upper_bound;
+
+ // 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);
+
+ // Edge cases: the next value toward itself is itself.
+ const double d = 1.0;
+ const float f = 1.0;
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, d, d), d);
+ EXPECT_EQ(uniform_lower_bound(IntervalOpenClosed, f, f), f);
+
+ 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);
+
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0.0f,
+ std::numeric_limits<float>::max()),
+ std::numeric_limits<float>::max());
+ EXPECT_EQ(uniform_upper_bound(IntervalClosedClosed, 0.0,
+ std::numeric_limits<double>::max()),
+ std::numeric_limits<double>::max());
+}
struct Invalid {};
@@ -197,9 +284,7 @@ TEST_F(RandomDistributionsTest, UniformTypeInference) {
// 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));
@@ -222,67 +307,6 @@ TEST_F(RandomDistributionsTest, UniformNoBounds) {
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.
-
-#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
- // We're using an x87-compatible FPU, and intermediate operations can be
- // performed with 80-bit floats. This produces slightly different results from
- // what we expect below.
- GTEST_SKIP()
- << "Skipping the test because we detected x87 floating-point semantics";
-#endif
-
- 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);
diff --git a/third_party/abseil-cpp/absl/random/exponential_distribution_test.cc b/third_party/abseil-cpp/absl/random/exponential_distribution_test.cc
index 81a5d17bac..f3cfd76442 100644
--- a/third_party/abseil-cpp/absl/random/exponential_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/exponential_distribution_test.cc
@@ -15,7 +15,6 @@
#include "absl/random/exponential_distribution.h"
#include <algorithm>
-#include <cfloat>
#include <cmath>
#include <cstddef>
#include <cstdint>
@@ -31,10 +30,8 @@
#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"
@@ -49,15 +46,11 @@ 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;
+#if defined(__EMSCRIPTEN__)
+using RealTypes = ::testing::Types<float, double>;
+#else
+using RealTypes = ::testing::Types<float, double, long double>;
+#endif // defined(__EMSCRIPTEN__)
TYPED_TEST_CASE(ExponentialDistributionTypedTest, RealTypes);
TYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) {
@@ -136,6 +129,23 @@ TYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) {
ss >> after;
+#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__PPC__)
+ if (std::is_same<TypeParam, long double>::value) {
+ // Roundtripping floating point values requires sufficient precision to
+ // reconstruct the exact value. It turns out that long double has some
+ // errors doing this on ppc, particularly for values
+ // near {1.0 +/- epsilon}.
+ if (lambda <= std::numeric_limits<double>::max() &&
+ lambda >= std::numeric_limits<double>::lowest()) {
+ EXPECT_EQ(static_cast<double>(before.lambda()),
+ static_cast<double>(after.lambda()))
+ << ss.str();
+ }
+ continue;
+ }
+#endif
+
EXPECT_EQ(before.lambda(), after.lambda()) //
<< ss.str() << " " //
<< (ss.good() ? "good " : "") //
@@ -195,10 +205,7 @@ class ExponentialDistributionTests : public testing::TestWithParam<Param>,
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};
+ absl::InsecureBitGen rng_;
};
template <typename D>
@@ -385,15 +392,6 @@ TEST(ExponentialDistributionTest, StabilityTest) {
TEST(ExponentialDistributionTest, AlgorithmBounds) {
// Relies on absl::uniform_real_distribution, so some of these comments
// reference that.
-
-#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
- // We're using an x87-compatible FPU, and intermediate operations can be
- // performed with 80-bit floats. This produces slightly different results from
- // what we expect below.
- GTEST_SKIP()
- << "Skipping the test because we detected x87 floating-point semantics";
-#endif
-
absl::exponential_distribution<double> dist;
{
diff --git a/third_party/abseil-cpp/absl/random/gaussian_distribution_test.cc b/third_party/abseil-cpp/absl/random/gaussian_distribution_test.cc
index c0bac2b0db..49c07513bf 100644
--- a/third_party/abseil-cpp/absl/random/gaussian_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/gaussian_distribution_test.cc
@@ -21,14 +21,12 @@
#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"
@@ -45,15 +43,7 @@ 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;
+using RealTypes = ::testing::Types<float, double, long double>;
TYPED_TEST_CASE(GaussianDistributionInterfaceTest, RealTypes);
TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) {
@@ -139,6 +129,29 @@ TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) {
ss >> after;
+#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \
+ defined(__ppc__) || defined(__PPC__)
+ if (std::is_same<TypeParam, long double>::value) {
+ // Roundtripping floating point values requires sufficient precision
+ // to reconstruct the exact value. It turns out that long double
+ // has some errors doing this on ppc, particularly for values
+ // near {1.0 +/- epsilon}.
+ if (mean <= std::numeric_limits<double>::max() &&
+ mean >= std::numeric_limits<double>::lowest()) {
+ EXPECT_EQ(static_cast<double>(before.mean()),
+ static_cast<double>(after.mean()))
+ << ss.str();
+ }
+ if (stddev <= std::numeric_limits<double>::max() &&
+ stddev >= std::numeric_limits<double>::lowest()) {
+ EXPECT_EQ(static_cast<double>(before.stddev()),
+ static_cast<double>(after.stddev()))
+ << ss.str();
+ }
+ continue;
+ }
+#endif
+
EXPECT_EQ(before.mean(), after.mean());
EXPECT_EQ(before.stddev(), after.stddev()) //
<< ss.str() << " " //
@@ -200,10 +213,7 @@ class GaussianDistributionTests : public testing::TestWithParam<Param>,
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};
+ absl::InsecureBitGen rng_;
};
template <typename D>
diff --git a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
index e93eebb68d..d7ad4efec9 100644
--- a/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/random/internal/BUILD.bazel
@@ -14,6 +14,8 @@
# 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",
@@ -28,13 +30,16 @@ package(default_visibility = [
"//absl/random:__pkg__",
])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "traits",
hdrs = ["traits.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/random:__pkg__",
+ ],
deps = ["//absl/base:config"],
)
@@ -43,10 +48,24 @@ cc_library(
hdrs = ["distribution_caller.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
+ visibility = [
+ "//absl/random:__pkg__",
+ ],
+ deps = ["//absl/base:config"],
+)
+
+cc_library(
+ name = "distributions",
+ hdrs = ["distributions.h"],
+ copts = ABSL_DEFAULT_COPTS,
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base:config",
- "//absl/base:fast_type_id",
- "//absl/utility",
+ ":distribution_caller",
+ ":traits",
+ ":uniform_helper",
+ "//absl/base",
+ "//absl/meta:type_traits",
+ "//absl/strings",
],
)
@@ -57,10 +76,10 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- "//absl/base:config",
- "//absl/meta:type_traits",
+ visibility = [
+ "//absl/random:__pkg__",
],
+ deps = ["//absl/base:config"],
)
cc_library(
@@ -73,14 +92,12 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS + select({
- "//absl:msvc_compiler": ["-DEFAULTLIB:bcrypt.lib"],
- "//absl:clang-cl_compiler": ["-DEFAULTLIB:bcrypt.lib"],
+ "//absl:windows": ["-DEFAULTLIB:bcrypt.lib"],
"//conditions:default": [],
}),
deps = [
":fast_uniform_bits",
"//absl/base:core_headers",
- "//absl/base:dynamic_annotations",
"//absl/base:raw_logging_internal",
"//absl/strings",
"//absl/types:optional",
@@ -98,9 +115,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
- "//absl:msvc_compiler": [],
- "//absl:clang-cl_compiler": [],
- "//absl:wasm": [],
+ "//absl:windows": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -125,10 +140,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = [
- "//absl/base:config",
- "//absl/base:endian",
- ],
+ deps = ["//absl/base:config"],
)
cc_library(
@@ -179,8 +191,8 @@ cc_library(
deps = [
":fastmath",
":traits",
+ "//absl/base:bits",
"//absl/meta:type_traits",
- "//absl/numeric:bits",
],
)
@@ -191,7 +203,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
- deps = ["//absl/numeric:bits"],
+ deps = ["//absl/base:bits"],
)
cc_library(
@@ -201,8 +213,8 @@ cc_library(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":traits",
+ "//absl/base:bits",
"//absl/base:config",
- "//absl/numeric:bits",
"//absl/numeric:int128",
],
)
@@ -218,6 +230,7 @@ cc_library(
":seed_material",
"//absl/base:core_headers",
"//absl/meta:type_traits",
+ "//absl/strings",
"//absl/types:optional",
"//absl/types:span",
],
@@ -233,7 +246,6 @@ cc_library(
":iostream_state_saver",
"//absl/base:config",
"//absl/meta:type_traits",
- "//absl/numeric:bits",
"//absl/numeric:int128",
],
)
@@ -246,22 +258,19 @@ cc_library(
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 = [
+ "randen-keys.inc",
"platform.h",
],
deps = ["//absl/base:config"],
@@ -295,8 +304,6 @@ cc_library(
":platform",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/base:endian",
- "//absl/numeric:int128",
],
)
@@ -328,16 +335,18 @@ cc_library(
"randen_hwaes.h",
],
copts = ABSL_DEFAULT_COPTS + ABSL_RANDOM_RANDEN_COPTS + select({
- "//absl:msvc_compiler": [],
- "//absl:clang-cl_compiler": [],
+ "//absl:windows": [],
"//conditions:default": ["-Wno-pass-failed"],
}),
+ # copts in RANDEN_HWAES_COPTS can make this target unusable as a module
+ # leading to a Clang diagnostic. Furthermore, it only has a private header
+ # anyway and thus there wouldn't be any gain from using it as a module.
+ features = ["-header_modules"],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":platform",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/numeric:int128",
],
)
@@ -410,8 +419,8 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":generate_real",
+ "//absl/base:bits",
"//absl/flags:flag",
- "//absl/numeric:bits",
"@com_google_googletest//:gtest_main",
],
)
@@ -495,11 +504,12 @@ cc_test(
)
cc_library(
- name = "mock_helpers",
- hdrs = ["mock_helpers.h"],
+ name = "mocking_bit_gen_base",
+ hdrs = ["mocking_bit_gen_base.h"],
+ linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- "//absl/base:fast_type_id",
- "//absl/types:optional",
+ "//absl/random",
+ "//absl/strings",
],
)
@@ -507,8 +517,10 @@ cc_library(
name = "mock_overload_set",
testonly = 1,
hdrs = ["mock_overload_set.h"],
+ visibility = [
+ "//absl/random:__pkg__",
+ ],
deps = [
- ":mock_helpers",
"//absl/random:mocking_bit_gen",
"@com_google_googletest//:gtest",
],
@@ -613,9 +625,7 @@ cc_test(
copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":platform",
":randen_slow",
- "//absl/base:endian",
"@com_google_googletest//:gtest_main",
],
)
@@ -624,7 +634,7 @@ cc_test(
name = "randen_hwaes_test",
size = "small",
srcs = ["randen_hwaes_test.cc"],
- copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,
+ copts = ABSL_TEST_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
tags = ABSL_RANDOM_NONPORTABLE_TAGS,
deps = [
@@ -645,7 +655,7 @@ cc_test(
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
":wide_multiply",
- "//absl/numeric:bits",
+ "//absl/base:bits",
"//absl/numeric:int128",
"@com_google_googletest//:gtest_main",
],
@@ -659,7 +669,6 @@ cc_library(
deps = [
":platform",
":randen_engine",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
],
@@ -671,8 +680,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
- ":traits",
- "//absl/base:config",
"//absl/meta:type_traits",
],
)
@@ -698,7 +705,6 @@ cc_test(
cc_test(
name = "randen_benchmarks",
size = "medium",
- timeout = "long",
srcs = ["randen_benchmarks.cc"],
copts = ABSL_TEST_COPTS + ABSL_RANDOM_RANDEN_COPTS,
flaky = 1,
@@ -719,6 +725,7 @@ cc_test(
cc_test(
name = "iostream_state_saver_test",
+ size = "small",
srcs = ["iostream_state_saver_test.cc"],
linkopts = ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -726,15 +733,3 @@ cc_test(
"@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/third_party/abseil-cpp/absl/random/internal/distribution_caller.h b/third_party/abseil-cpp/absl/random/internal/distribution_caller.h
index fc81b787eb..02603cf843 100644
--- a/third_party/abseil-cpp/absl/random/internal/distribution_caller.h
+++ b/third_party/abseil-cpp/absl/random/internal/distribution_caller.h
@@ -20,8 +20,6 @@
#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
@@ -32,57 +30,27 @@ namespace random_internal {
// 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*).
+ // Call the provided distribution type. The parameters are expected
+ // to be explicitly specified.
+ // DistrT is the distribution type.
+ // FormatT is the formatter type:
//
- // 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) {
+ // struct FormatT {
+ // using result_type = distribution_t::result_type;
+ // static std::string FormatCall(
+ // const distribution_t& distr,
+ // absl::Span<const result_type>);
+ //
+ // static std::string FormatExpectation(
+ // absl::string_view match_args,
+ // absl::Span<const result_t> results);
+ // }
+ //
+ template <typename DistrT, typename FormatT, typename... Args>
+ static typename DistrT::result_type Call(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
diff --git a/third_party/abseil-cpp/absl/random/internal/distributions.h b/third_party/abseil-cpp/absl/random/internal/distributions.h
new file mode 100644
index 0000000000..d7e3c0161f
--- /dev/null
+++ b/third_party/abseil-cpp/absl/random/internal/distributions.h
@@ -0,0 +1,52 @@
+// 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_DISTRIBUTIONS_H_
+#define ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
+
+#include <type_traits>
+
+#include "absl/meta/type_traits.h"
+#include "absl/random/internal/distribution_caller.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/internal/uniform_helper.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+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>;
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_DISTRIBUTIONS_H_
diff --git a/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq.h b/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq.h
index 25f791535f..6a743eaf46 100644
--- a/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq.h
+++ b/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq.h
@@ -23,7 +23,6 @@
#include <vector>
#include "absl/base/config.h"
-#include "absl/base/internal/endian.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
diff --git a/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc b/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc
index f867f610d0..a55ad73948 100644
--- a/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/explicit_seed_seq_test.cc
@@ -24,8 +24,6 @@
namespace {
-using ::absl::random_internal::ExplicitSeedSeq;
-
template <typename Sseq>
bool ConformsToInterface() {
// Check that the SeedSequence can be default-constructed.
@@ -66,14 +64,14 @@ TEST(SeedSequences, CheckInterfaces) {
EXPECT_TRUE(ConformsToInterface<std::seed_seq>());
// Abseil classes
- EXPECT_TRUE(ConformsToInterface<ExplicitSeedSeq>());
+ EXPECT_TRUE(ConformsToInterface<absl::random_internal::ExplicitSeedSeq>());
}
TEST(ExplicitSeedSeq, DefaultConstructorGeneratesZeros) {
const size_t kNumBlocks = 128;
uint32_t outputs[kNumBlocks];
- ExplicitSeedSeq seq;
+ absl::random_internal::ExplicitSeedSeq seq;
seq.generate(outputs, &outputs[kNumBlocks]);
for (uint32_t& seed : outputs) {
@@ -89,7 +87,8 @@ TEST(ExplicitSeeqSeq, SeedMaterialIsForwardedIdentically) {
for (uint32_t& seed : seed_material) {
seed = urandom();
}
- ExplicitSeedSeq seq(seed_material, &seed_material[kNumBlocks]);
+ absl::random_internal::ExplicitSeedSeq seq(seed_material,
+ &seed_material[kNumBlocks]);
// Check that output is same as seed-material provided to constructor.
{
@@ -134,10 +133,11 @@ TEST(ExplicitSeedSeq, CopyAndMoveConstructors) {
for (uint32_t& entry : entropy) {
entry = urandom();
}
- ExplicitSeedSeq seq_from_entropy(std::begin(entropy), std::end(entropy));
+ absl::random_internal::ExplicitSeedSeq seq_from_entropy(std::begin(entropy),
+ std::end(entropy));
// Copy constructor.
{
- ExplicitSeedSeq seq_copy(seq_from_entropy);
+ absl::random_internal::ExplicitSeedSeq seq_copy(seq_from_entropy);
EXPECT_EQ(seq_copy.size(), seq_from_entropy.size());
std::vector<uint32_t> seeds_1;
@@ -155,7 +155,8 @@ TEST(ExplicitSeedSeq, CopyAndMoveConstructors) {
for (uint32_t& entry : entropy) {
entry = urandom();
}
- ExplicitSeedSeq another_seq(std::begin(entropy), std::end(entropy));
+ absl::random_internal::ExplicitSeedSeq another_seq(std::begin(entropy),
+ std::end(entropy));
std::vector<uint32_t> seeds_1;
seeds_1.resize(1000, 0);
@@ -201,35 +202,3 @@ TEST(ExplicitSeedSeq, CopyAndMoveConstructors) {
EXPECT_THAT(seeds_1, Each(Eq(0)));
}
}
-
-TEST(ExplicitSeedSeq, StdURBGGoldenTests) {
- // Verify that for std::- URBG instances the results are stable across
- // platforms (these should have deterministic output).
- {
- ExplicitSeedSeq seed_sequence{12, 34, 56};
- std::minstd_rand rng(seed_sequence);
-
- std::minstd_rand::result_type values[4] = {rng(), rng(), rng(), rng()};
- EXPECT_THAT(values,
- testing::ElementsAre(579252, 43785881, 464353103, 1501811174));
- }
-
- {
- ExplicitSeedSeq seed_sequence{12, 34, 56};
- std::mt19937 rng(seed_sequence);
-
- std::mt19937::result_type values[4] = {rng(), rng(), rng(), rng()};
- EXPECT_THAT(values, testing::ElementsAre(138416803, 151130212, 33817739,
- 138416803));
- }
-
- {
- ExplicitSeedSeq seed_sequence{12, 34, 56};
- std::mt19937_64 rng(seed_sequence);
-
- std::mt19937_64::result_type values[4] = {rng(), rng(), rng(), rng()};
- EXPECT_THAT(values,
- testing::ElementsAre(19738651785169348, 1464811352364190456,
- 18054685302720800, 19738651785169348));
- }
-}
diff --git a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
index 425aaf7d83..f13c8729f7 100644
--- a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
+++ b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits.h
@@ -21,7 +21,6 @@
#include <type_traits>
#include "absl/base/config.h"
-#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -39,17 +38,28 @@ constexpr bool IsPowerOfTwoOrZero(UIntType n) {
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});
+ : (URBG::max)() - (URBG::min)() + result_type{1};
+}
+
+template <typename UIntType>
+constexpr UIntType LargestPowerOfTwoLessThanOrEqualTo(UIntType n) {
+ return n < 2 ? n : 2 * LargestPowerOfTwoLessThanOrEqualTo(n / 2);
+}
+
+// Given a URBG generating values in the closed interval [Lo, Hi], returns the
+// largest power of two less than or equal to `Hi - Lo + 1`.
+template <typename URBG>
+constexpr typename URBG::result_type PowerOfTwoSubRangeSize() {
+ return LargestPowerOfTwoLessThanOrEqualTo(RangeSize<URBG>());
}
// 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);
+ return (n <= 1) ? 0 : 1 + IntegerLog2(n / 2);
}
// Returns the number of bits of randomness returned through
@@ -58,23 +68,18 @@ template <typename URBG>
constexpr size_t NumBits() {
return RangeSize<URBG>() == 0
? std::numeric_limits<typename URBG::result_type>::digits
- : IntegerLog2(RangeSize<URBG>());
+ : IntegerLog2(PowerOfTwoSubRangeSize<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) {
+constexpr UIntType MaskFromShift(UIntType 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:
@@ -102,16 +107,50 @@ class FastUniformBits {
"Class-template FastUniformBits<> must be parameterized using "
"an unsigned type.");
+ // PowerOfTwoVariate() generates a single random variate, always returning a
+ // value in the half-open interval `[0, PowerOfTwoSubRangeSize<URBG>())`. If
+ // the URBG already generates values in a power-of-two range, the generator
+ // itself is used. Otherwise, we use rejection sampling on the largest
+ // possible power-of-two-sized subrange.
+ struct PowerOfTwoTag {};
+ struct RejectionSamplingTag {};
+ template <typename URBG>
+ static typename URBG::result_type PowerOfTwoVariate(
+ URBG& g) { // NOLINT(runtime/references)
+ using tag =
+ typename std::conditional<IsPowerOfTwoOrZero(RangeSize<URBG>()),
+ PowerOfTwoTag, RejectionSamplingTag>::type;
+ return PowerOfTwoVariate(g, tag{});
+ }
+
+ template <typename URBG>
+ static typename URBG::result_type PowerOfTwoVariate(
+ URBG& g, // NOLINT(runtime/references)
+ PowerOfTwoTag) {
+ return g() - (URBG::min)();
+ }
+
+ template <typename URBG>
+ static typename URBG::result_type PowerOfTwoVariate(
+ URBG& g, // NOLINT(runtime/references)
+ RejectionSamplingTag) {
+ // Use rejection sampling to ensure uniformity across the range.
+ typename URBG::result_type u;
+ do {
+ u = g() - (URBG::min)();
+ } while (u >= PowerOfTwoSubRangeSize<URBG>());
+ return u;
+ }
+
// 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.
+ // the underlying URBG must loop over multiple calls or not.
template <typename URBG>
result_type Generate(URBG& g, // NOLINT(runtime/references)
- SimplifiedLoopTag);
+ std::true_type /* avoid_looping */);
template <typename URBG>
result_type Generate(URBG& g, // NOLINT(runtime/references)
- RejectionLoopTag);
+ std::false_type /* avoid_looping */);
};
template <typename UIntType>
@@ -123,47 +162,31 @@ FastUniformBits<UIntType>::operator()(URBG& g) { // NOLINT(runtime/references)
// 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{});
+ using urbg_result_type = typename URBG::result_type;
+ constexpr urbg_result_type kRangeMask =
+ RangeSize<URBG>() == 0
+ ? (std::numeric_limits<urbg_result_type>::max)()
+ : static_cast<urbg_result_type>(PowerOfTwoSubRangeSize<URBG>() - 1);
+ return Generate(g, std::integral_constant<bool, (kRangeMask >= (max)())>{});
}
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)();
+ std::true_type /* avoid_looping */) {
+ // The width of the result_type is less than than the width of the random bits
+ // provided by URBG. Thus, generate a single value and then simply mask off
+ // the required bits.
- 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;
+ return PowerOfTwoVariate(g) & (max)();
}
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;
-
+ std::false_type /* avoid_looping */) {
// 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
@@ -176,44 +199,21 @@ FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
// `kSmallIters` and `kLargeIters` times respectively such
// that
//
- // `kResultBits == kSmallIters * kSmallBits
- // + kLargeIters * kLargeBits`
+ // `kTotalWidth == kSmallIters * kSmallWidth
+ // + kLargeIters * kLargeWidth`
//
- // where `kResultBits` is the total number of bits in `result_type`.
+ // where `kTotalWidth` 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
-
+ constexpr size_t kTotalWidth = std::numeric_limits<result_type>::digits;
+ constexpr size_t kUrbgWidth = NumBits<URBG>();
+ constexpr size_t kTotalIters =
+ kTotalWidth / kUrbgWidth + (kTotalWidth % kUrbgWidth != 0);
+ constexpr size_t kSmallWidth = kTotalWidth / kTotalIters;
+ constexpr size_t kLargeWidth = kSmallWidth + 1;
//
- // Because `kLargeBits == kSmallBits + 1`, it follows that
+ // Because `kLargeWidth == kSmallWidth + 1`, it follows that
//
- // `kResultBits == kSmallIters * kSmallBits + kLargeIters`
+ // `kTotalWidth == kTotalIters * kSmallWidth + kLargeIters`
//
// and therefore
//
@@ -224,40 +224,36 @@ FastUniformBits<UIntType>::Generate(URBG& g, // NOLINT(runtime/references)
// 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.");
+ constexpr size_t kLargeIters = kTotalWidth % kSmallWidth;
+ constexpr size_t kSmallIters =
+ (kTotalWidth - (kLargeWidth * kLargeIters)) / kSmallWidth;
- // 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)();
+ static_assert(
+ kTotalWidth == kSmallIters * kSmallWidth + kLargeIters * kLargeWidth,
+ "Error in looping constant calculations.");
result_type s = 0;
+
+ constexpr size_t kSmallShift = kSmallWidth % kTotalWidth;
+ constexpr result_type kSmallMask = MaskFromShift(result_type{kSmallShift});
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>(PowerOfTwoVariate(g)) & kSmallMask);
+ }
- s = (s << kSmallShift) + static_cast<result_type>(v & kSmallMask);
+ constexpr size_t kLargeShift = kLargeWidth % kTotalWidth;
+ constexpr result_type kLargeMask = MaskFromShift(result_type{kLargeShift});
+ for (size_t n = 0; n < kLargeIters; ++n) {
+ s = (s << kLargeShift) +
+ (static_cast<result_type>(PowerOfTwoVariate(g)) & kLargeMask);
}
- for (size_t n = kSmallIters; n < kTotalIters; ++n) {
- urbg_result_type v;
- do {
- v = g() - kMin;
- } while (v >= kLargeRejection);
+ static_assert(
+ kLargeShift == kSmallShift + 1 ||
+ (kLargeShift == 0 &&
+ kSmallShift == std::numeric_limits<result_type>::digits - 1),
+ "Error in looping constant calculations");
- s = (s << kLargeShift) + static_cast<result_type>(v & kLargeMask);
- }
return s;
}
diff --git a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
index cee702df85..f5b837e586 100644
--- a/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/fast_uniform_bits_test.cc
@@ -34,8 +34,8 @@ 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)());
+ EXPECT_EQ(0, FastBits::min());
+ EXPECT_EQ(Limits::max(), FastBits::max());
constexpr int kIters = 10000;
std::random_device rd;
@@ -43,8 +43,8 @@ TYPED_TEST(FastUniformBitsTypedTest, BasicTest) {
FastBits fast;
for (int i = 0; i < kIters; i++) {
const auto v = fast(gen);
- EXPECT_LE(v, (FastBits::max)());
- EXPECT_GE(v, (FastBits::min)());
+ EXPECT_LE(v, FastBits::max());
+ EXPECT_GE(v, FastBits::min());
}
}
@@ -52,26 +52,21 @@ 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;
+ result_type operator()() { return Val; }
};
+using UrngOddbits = FakeUrbg<uint8_t, 1, 0xfe, 0x73>;
+using Urng4bits = FakeUrbg<uint8_t, 1, 0x10, 2>;
+using Urng31bits = FakeUrbg<uint32_t, 1, 0xfffffffe, 0x60070f03>;
+using Urng32bits = FakeUrbg<uint32_t, 0, 0xffffffff, 0x74010f01>;
+
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)()));
@@ -80,7 +75,6 @@ TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {
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)()));
@@ -97,237 +91,181 @@ TEST(FastUniformBitsTest, IsPowerOfTwoOrZero) {
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)()));
+ EXPECT_EQ(IntegerLog2(uint16_t{0}), 0);
+ EXPECT_EQ(IntegerLog2(uint16_t{1}), 0);
+ EXPECT_EQ(IntegerLog2(uint16_t{2}), 1);
+ EXPECT_EQ(IntegerLog2(uint16_t{3}), 1);
+ EXPECT_EQ(IntegerLog2(uint16_t{4}), 2);
+ EXPECT_EQ(IntegerLog2(uint16_t{5}), 2);
+ EXPECT_EQ(IntegerLog2(std::numeric_limits<uint64_t>::max()), 63);
}
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((RangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 6>>()), 5);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint8_t, 2, 10>>()), 9);
EXPECT_EQ(
- 0, (RangeSize<
- FakeUrbg<uint8_t, 0, (std::numeric_limits<uint8_t>::max)()>>()));
+ (RangeSize<FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 2, 6>>()), 5);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 18);
+ EXPECT_EQ((RangeSize<
+ FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 6>>()), 5);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 18);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()), 0xffffffff);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()), 0xfffffffe);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint32_t, 2, 0xfffffffe>>()), 0xfffffffd);
+ EXPECT_EQ((RangeSize<
+ FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 6>>()), 5);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 18);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()), 0x100000000ull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()), 0xffffffffull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()), 0xfffffffeull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffe>>()), 0xfffffffdull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()), 0ull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
+ 0xffffffffffffffffull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
+ 0xfffffffffffffffeull);
+ EXPECT_EQ((RangeSize<FakeUrbg<uint64_t, 2, 0xfffffffffffffffeull>>()),
+ 0xfffffffffffffffdull);
+ EXPECT_EQ((RangeSize<
+ FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
+ 0);
+}
- 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>>()));
+TEST(FastUniformBitsTest, PowerOfTwoSubRangeSize) {
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 0, 3>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 2>>()), 1);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 5>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 6>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint8_t, 2, 10>>()), 8);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<
+ FakeUrbg<uint8_t, 0, std::numeric_limits<uint8_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 0, 3>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 2>>()), 1);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 5>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 2, 6>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint16_t, 1000, 1017>>()), 16);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<
+ FakeUrbg<uint16_t, 0, std::numeric_limits<uint16_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 3>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 2>>()), 1);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 5>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 2, 6>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1000, 1017>>()), 16);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 0, 0xffffffff>>()), 0);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xffffffff>>()),
+ 0x80000000);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint32_t, 1, 0xfffffffe>>()),
+ 0x80000000);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<
+ FakeUrbg<uint32_t, 0, std::numeric_limits<uint32_t>::max()>>()),
+ 0);
+
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 3>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 2>>()), 1);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 5>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 2, 6>>()), 4);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1000, 1017>>()), 16);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffff>>()),
+ 0x100000000ull);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffff>>()),
+ 0x80000000ull);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffe>>()),
+ 0x80000000ull);
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>>()));
+ (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 0, 0xffffffffffffffffull>>()),
+ 0);
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>>()));
+ (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xffffffffffffffffull>>()),
+ 0x8000000000000000ull);
EXPECT_EQ(
- 0, (RangeSize<
- FakeUrbg<uint64_t, 0, (std::numeric_limits<uint64_t>::max)()>>()));
+ (PowerOfTwoSubRangeSize<FakeUrbg<uint64_t, 1, 0xfffffffffffffffeull>>()),
+ 0x8000000000000000ull);
+ EXPECT_EQ((PowerOfTwoSubRangeSize<
+ FakeUrbg<uint64_t, 0, std::numeric_limits<uint64_t>::max()>>()),
+ 0);
}
-// 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) {
+TEST(FastUniformBitsTest, Urng4_VariousOutputs) {
// 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));
+ EXPECT_EQ(0xf02, fast16(urng31));
+ EXPECT_EQ(0xf01, fast16(urng32));
}
// 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;
+ // 64-bit types
{
- 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.
+ FastUniformBits<uint64_t> fast64;
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));
+ EXPECT_EQ(0x05e47095f847c122ull, fast64(gen));
+ EXPECT_EQ(0x8f82c1ba30b64d22ull, fast64(gen));
+ EXPECT_EQ(0x3b971a3558155039ull, fast64(gen));
}
} // namespace
diff --git a/third_party/abseil-cpp/absl/random/internal/fastmath.h b/third_party/abseil-cpp/absl/random/internal/fastmath.h
index 963b7690f1..6baeb5a7c9 100644
--- a/third_party/abseil-cpp/absl/random/internal/fastmath.h
+++ b/third_party/abseil-cpp/absl/random/internal/fastmath.h
@@ -22,22 +22,27 @@
#include <cmath>
#include <cstdint>
-#include "absl/numeric/bits.h"
+#include "absl/base/internal/bits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
+// Returns the position of the first bit set.
+inline int LeadingSetBit(uint64_t n) {
+ return 64 - base_internal::CountLeadingZeros64(n);
+}
+
// 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));
+ return (n <= 1) ? 0 : (63 - base_internal::CountLeadingZeros64(n));
}
inline int IntLog2Ceil(uint64_t n) {
- return (n <= 1) ? 0 : (64 - countl_zero(n - 1));
+ return (n <= 1) ? 0 : (64 - base_internal::CountLeadingZeros64(n - 1));
}
inline double StirlingLogFactorial(double n) {
@@ -50,6 +55,18 @@ inline double StirlingLogFactorial(double n) {
(1.0 / 360.0) * ninv * ninv * ninv;
}
+// Rotate value right.
+//
+// We only implement the uint32_t / uint64_t versions because
+// 1) those are the only ones we use, and
+// 2) those are the only ones where clang detects the rotate idiom correctly.
+inline constexpr uint32_t rotr(uint32_t value, uint8_t bits) {
+ return (value >> (bits & 31)) | (value << ((-bits) & 31));
+}
+inline constexpr uint64_t rotr(uint64_t value, uint8_t bits) {
+ return (value >> (bits & 63)) | (value << ((-bits) & 63));
+}
+
} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/random/internal/fastmath_test.cc b/third_party/abseil-cpp/absl/random/internal/fastmath_test.cc
index 0d6f9dc157..65859c25de 100644
--- a/third_party/abseil-cpp/absl/random/internal/fastmath_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/fastmath_test.cc
@@ -27,6 +27,19 @@
namespace {
+TEST(DistributionImplTest, LeadingSetBit) {
+ using absl::random_internal::LeadingSetBit;
+ constexpr uint64_t kZero = 0;
+ EXPECT_EQ(0, LeadingSetBit(kZero));
+ EXPECT_EQ(64, LeadingSetBit(~kZero));
+
+ for (int index = 0; index < 64; index++) {
+ uint64_t x = static_cast<uint64_t>(1) << index;
+ EXPECT_EQ(index + 1, LeadingSetBit(x)) << index;
+ EXPECT_EQ(index + 1, LeadingSetBit(x + x - 1)) << index;
+ }
+}
+
TEST(FastMathTest, IntLog2FloorTest) {
using absl::random_internal::IntLog2Floor;
constexpr uint64_t kZero = 0;
diff --git a/third_party/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc b/third_party/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc
index a95333d55f..a2bf03940f 100644
--- a/third_party/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc
+++ b/third_party/abseil-cpp/absl/random/internal/gaussian_distribution_gentables.cc
@@ -111,9 +111,12 @@ void TableGenerator::Print(std::ostream* os) {
"\n"
"#include \"absl/random/gaussian_distribution.h\"\n"
"\n"
- "namespace absl {\n"
- "ABSL_NAMESPACE_BEGIN\n"
- "namespace random_internal {\n"
+ // "namespace " and "absl" are broken apart so as not to conflict with
+ // script that adds the LTS inline namespace.
+ "namespace "
+ "absl {\n"
+ "namespace "
+ "random_internal {\n"
"\n"
"const gaussian_distribution_base::Tables\n"
" gaussian_distribution_base::zg_ = {\n";
@@ -122,9 +125,10 @@ void TableGenerator::Print(std::ostream* os) {
FormatArrayContents(os, tables_.f);
*os << "};\n"
"\n"
- "} // namespace random_internal\n"
- "ABSL_NAMESPACE_END\n"
- "} // namespace absl\n"
+ "} // namespace "
+ "random_internal\n"
+ "} // namespace "
+ "absl\n"
"\n"
"// clang-format on\n"
"// END GENERATED CODE";
diff --git a/third_party/abseil-cpp/absl/random/internal/generate_real.h b/third_party/abseil-cpp/absl/random/internal/generate_real.h
index d5fbb44c24..20f6d20807 100644
--- a/third_party/abseil-cpp/absl/random/internal/generate_real.h
+++ b/third_party/abseil-cpp/absl/random/internal/generate_real.h
@@ -23,8 +23,8 @@
#include <limits>
#include <type_traits>
+#include "absl/base/internal/bits.h"
#include "absl/meta/type_traits.h"
-#include "absl/numeric/bits.h"
#include "absl/random/internal/fastmath.h"
#include "absl/random/internal/traits.h"
@@ -120,15 +120,17 @@ inline RealType GenerateRealFromBits(uint64_t bits, int exp_bias = 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);
+ int clz = base_internal::CountLeadingZeros64(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 = sign | (static_cast<uint_type>(exp) << kExp) |
- (static_cast<uint_type>(bits) & kMask);
+ 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;
diff --git a/third_party/abseil-cpp/absl/random/internal/generate_real_test.cc b/third_party/abseil-cpp/absl/random/internal/generate_real_test.cc
index b099dbf35f..aa02f0c2c1 100644
--- a/third_party/abseil-cpp/absl/random/internal/generate_real_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/generate_real_test.cc
@@ -20,8 +20,8 @@
#include <string>
#include "gtest/gtest.h"
+#include "absl/base/internal/bits.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.");
@@ -413,13 +413,14 @@ TEST(GenerateRealTest, U64ToDoubleSignedTest) {
}
TEST(GenerateRealTest, ExhaustiveFloat) {
+ using absl::base_internal::CountLeadingZeros64;
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
+ // 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.
//
@@ -463,7 +464,7 @@ TEST(GenerateRealTest, ExhaustiveFloat) {
// 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);
+ const int clz = CountLeadingZeros64(x);
if (clz < kDig) {
dec <<= (kDig - clz);
chk = (~uint64_t(0)) >> (clz + 1);
diff --git a/third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h b/third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h
index e6e242ee1e..7378829a42 100644
--- a/third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h
+++ b/third_party/abseil-cpp/absl/random/internal/iostream_state_saver.h
@@ -192,8 +192,8 @@ struct stream_u128_helper<absl::uint128> {
template <typename OStream>
inline void write(absl::uint128 val, OStream& out) {
- uint64_t h = absl::Uint128High64(val);
- uint64_t l = absl::Uint128Low64(val);
+ uint64_t h = Uint128High64(val);
+ uint64_t l = Uint128Low64(val);
out << h << out.fill() << l;
}
};
diff --git a/third_party/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc b/third_party/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
index 6e66266cc0..7bb8ad959c 100644
--- a/third_party/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
@@ -14,9 +14,6 @@
#include "absl/random/internal/iostream_state_saver.h"
-#include <errno.h>
-#include <stdio.h>
-
#include <sstream>
#include <string>
@@ -275,6 +272,7 @@ TEST(IOStreamStateSaver, RoundTripDoubles) {
}
}
+#if !defined(__EMSCRIPTEN__)
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.
@@ -352,6 +350,7 @@ TEST(IOStreamStateSaver, RoundTripLongDoubles) {
}
}
}
+#endif // !defined(__EMSCRIPTEN__)
TEST(StrToDTest, DoubleMin) {
const char kV[] = "2.22507385850720138e-308";
diff --git a/third_party/abseil-cpp/absl/random/internal/mock_helpers.h b/third_party/abseil-cpp/absl/random/internal/mock_helpers.h
deleted file mode 100644
index 9d6ab21ef5..0000000000
--- a/third_party/abseil-cpp/absl/random/internal/mock_helpers.h
+++ /dev/null
@@ -1,134 +0,0 @@
-//
-// 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/third_party/abseil-cpp/absl/random/internal/mock_overload_set.h b/third_party/abseil-cpp/absl/random/internal/mock_overload_set.h
index 0d9c6c120c..c2a30d89d5 100644
--- a/third_party/abseil-cpp/absl/random/internal/mock_overload_set.h
+++ b/third_party/abseil-cpp/absl/random/internal/mock_overload_set.h
@@ -19,7 +19,7 @@
#include <type_traits>
#include "gmock/gmock.h"
-#include "absl/random/internal/mock_helpers.h"
+#include "gtest/gtest.h"
#include "absl/random/mocking_bit_gen.h"
namespace absl {
@@ -35,22 +35,17 @@ struct MockSingleOverload;
// 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.
+// arguments to Mocking::Register.
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...);
+ "distributions result type.");
+ auto gmock_Call(
+ absl::MockingBitGen& gen, // NOLINT(google-runtime-references)
+ const ::testing::Matcher<Args>&... args)
+ -> decltype(gen.Register<DistrT, Args...>(args...)) {
+ return gen.Register<DistrT, Args...>(args...);
}
};
@@ -58,17 +53,13 @@ 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...);
+ "distributions result type.");
+ auto gmock_Call(
+ const ::testing::Matcher<Arg>& arg,
+ absl::MockingBitGen& gen, // NOLINT(google-runtime-references)
+ const ::testing::Matcher<Args>&... args)
+ -> decltype(gen.Register<DistrT, Arg, Args...>(arg, args...)) {
+ return gen.Register<DistrT, Arg, Args...>(arg, args...);
}
};
diff --git a/third_party/abseil-cpp/absl/random/internal/mocking_bit_gen_base.h b/third_party/abseil-cpp/absl/random/internal/mocking_bit_gen_base.h
new file mode 100644
index 0000000000..eeeae9d295
--- /dev/null
+++ b/third_party/abseil-cpp/absl/random/internal/mocking_bit_gen_base.h
@@ -0,0 +1,120 @@
+//
+// 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_MOCKING_BIT_GEN_BASE_H_
+#define ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
+
+#include <atomic>
+#include <deque>
+#include <string>
+#include <typeinfo>
+
+#include "absl/random/random.h"
+#include "absl/strings/str_cat.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+namespace random_internal {
+
+// MockingBitGenExpectationFormatter is invoked to format unsatisfied mocks
+// and remaining results into a description string.
+template <typename DistrT, typename FormatT>
+struct MockingBitGenExpectationFormatter {
+ std::string operator()(absl::string_view args) {
+ return absl::StrCat(FormatT::FunctionName(), "(", args, ")");
+ }
+};
+
+// MockingBitGenCallFormatter is invoked to format each distribution call
+// into a description string for the mock log.
+template <typename DistrT, typename FormatT>
+struct MockingBitGenCallFormatter {
+ std::string operator()(const DistrT& dist,
+ const typename DistrT::result_type& result) {
+ return absl::StrCat(
+ FormatT::FunctionName(), "(", FormatT::FormatArgs(dist), ") => {",
+ FormatT::FormatResults(absl::MakeSpan(&result, 1)), "}");
+ }
+};
+
+class MockingBitGenBase {
+ template <typename>
+ friend struct DistributionCaller;
+ using generator_type = absl::BitGen;
+
+ public:
+ // URBG interface
+ using result_type = generator_type::result_type;
+ static constexpr result_type(min)() { return (generator_type::min)(); }
+ static constexpr result_type(max)() { return (generator_type::max)(); }
+ result_type operator()() { return gen_(); }
+
+ MockingBitGenBase() : gen_(), observed_call_log_() {}
+ virtual ~MockingBitGenBase() = default;
+
+ protected:
+ const std::deque<std::string>& observed_call_log() {
+ return observed_call_log_;
+ }
+
+ // CallImpl is the type-erased virtual dispatch.
+ // The type of dist is always distribution<T>,
+ // The type of result is always distribution<T>::result_type.
+ virtual bool CallImpl(const std::type_info& distr_type, void* dist_args,
+ void* result) = 0;
+
+ template <typename DistrT, typename ArgTupleT>
+ static const std::type_info& GetTypeId() {
+ return typeid(std::pair<absl::decay_t<DistrT>, absl::decay_t<ArgTupleT>>);
+ }
+
+ // Call the generating distribution function.
+ // Invoked by DistributionCaller<>::Call<DistT, FormatT>.
+ // DistT is the distribution type.
+ // FormatT is the distribution formatter traits type.
+ template <typename DistrT, typename FormatT, typename... Args>
+ typename DistrT::result_type Call(Args&&... args) {
+ using distr_result_type = typename DistrT::result_type;
+ using ArgTupleT = std::tuple<absl::decay_t<Args>...>;
+
+ ArgTupleT arg_tuple(std::forward<Args>(args)...);
+ auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
+
+ distr_result_type result{};
+ bool found_match =
+ CallImpl(GetTypeId<DistrT, ArgTupleT>(), &arg_tuple, &result);
+
+ if (!found_match) {
+ result = dist(gen_);
+ }
+
+ // TODO(asoffer): Forwarding the args through means we no longer need to
+ // extract them from the from the distribution in formatter traits. We can
+ // just StrJoin them.
+ observed_call_log_.push_back(
+ MockingBitGenCallFormatter<DistrT, FormatT>{}(dist, result));
+ return result;
+ }
+
+ private:
+ generator_type gen_;
+ std::deque<std::string> observed_call_log_;
+}; // namespace random_internal
+
+} // namespace random_internal
+ABSL_NAMESPACE_END
+} // namespace absl
+
+#endif // ABSL_RANDOM_INTERNAL_MOCKING_BIT_GEN_BASE_H_
diff --git a/third_party/abseil-cpp/absl/random/internal/nanobenchmark.cc b/third_party/abseil-cpp/absl/random/internal/nanobenchmark.cc
index c9181813f7..8fee77fcc7 100644
--- a/third_party/abseil-cpp/absl/random/internal/nanobenchmark.cc
+++ b/third_party/abseil-cpp/absl/random/internal/nanobenchmark.cc
@@ -101,7 +101,7 @@ std::string BrandString() {
char brand_string[49];
uint32_t abcd[4];
- // Check if brand string is supported (it is on all reasonable Intel/AMD)
+ // Check if brand std::string is supported (it is on all reasonable Intel/AMD)
Cpuid(0x80000000U, 0, abcd);
if (abcd[0] < 0x80000004U) {
return std::string();
diff --git a/third_party/abseil-cpp/absl/random/internal/nanobenchmark_test.cc b/third_party/abseil-cpp/absl/random/internal/nanobenchmark_test.cc
index f1571e269f..ab824ef55f 100644
--- a/third_party/abseil-cpp/absl/random/internal/nanobenchmark_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/nanobenchmark_test.cc
@@ -53,7 +53,7 @@ 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)) {
+ if (!SimpleAtoi(argv[1], &cpu)) {
ABSL_RAW_LOG(FATAL, "The optional argument must be a CPU number >= 0.\n");
}
}
diff --git a/third_party/abseil-cpp/absl/random/internal/pcg_engine.h b/third_party/abseil-cpp/absl/random/internal/pcg_engine.h
index 8efaf2e09a..53c23fe1b4 100644
--- a/third_party/abseil-cpp/absl/random/internal/pcg_engine.h
+++ b/third_party/abseil-cpp/absl/random/internal/pcg_engine.h
@@ -19,7 +19,6 @@
#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"
@@ -262,7 +261,7 @@ struct pcg_xsl_rr_128_64 {
uint64_t rotate = h >> 58u;
uint64_t s = Uint128Low64(state) ^ h;
#endif
- return rotr(s, rotate);
+ return random_internal::rotr(s, rotate);
}
};
@@ -282,8 +281,8 @@ 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);
+ return random_internal::rotr(
+ static_cast<uint32_t>(((state >> 18) ^ state) >> 27), state >> 59);
}
};
diff --git a/third_party/abseil-cpp/absl/random/internal/pool_urbg.cc b/third_party/abseil-cpp/absl/random/internal/pool_urbg.cc
index 725100a415..5bee530770 100644
--- a/third_party/abseil-cpp/absl/random/internal/pool_urbg.cc
+++ b/third_party/abseil-cpp/absl/random/internal/pool_urbg.cc
@@ -194,10 +194,11 @@ RandenPoolEntry* PoolAlignedAlloc() {
// Not all the platforms that we build for have std::aligned_alloc, however
// since we never free these objects, we can over allocate and munge the
// pointers to the correct alignment.
- intptr_t x = reinterpret_cast<intptr_t>(
- new char[sizeof(RandenPoolEntry) + kAlignment]);
+ void* memory = std::malloc(sizeof(RandenPoolEntry) + kAlignment);
+ auto x = reinterpret_cast<intptr_t>(memory);
auto y = x % kAlignment;
- void* aligned = reinterpret_cast<void*>(y == 0 ? x : (x + kAlignment - y));
+ void* aligned =
+ (y == 0) ? memory : reinterpret_cast<void*>(x + kAlignment - y);
return new (aligned) RandenPoolEntry();
}
diff --git a/third_party/abseil-cpp/absl/random/internal/randen-keys.inc b/third_party/abseil-cpp/absl/random/internal/randen-keys.inc
new file mode 100644
index 0000000000..fa4b166835
--- /dev/null
+++ b/third_party/abseil-cpp/absl/random/internal/randen-keys.inc
@@ -0,0 +1,207 @@
+// 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_KEYS_INC_
+#define ABSL_RANDOM_INTERNAL_RANDEN_KEYS_INC_
+
+// Textual header to include the randen_keys where necessary.
+// REQUIRES: struct u64x2{}
+//
+// PROVIDES: kKeys
+// PROVIDES: round_keys[]
+
+// "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 << EOF
+"""Generates Randen round keys array from pi-hex.62500.txt file."""
+import binascii
+
+KEYS = 136
+
+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))
+
+digits = digits_from_pi()
+print("static constexpr const size_t kRoundKeys = {0};\n".format(KEYS))
+print("alignas(16) constexpr const u64x2 round_keys[kRoundKeys] = {")
+
+for i, (hi, lo) in zip(range(KEYS), pairwise(chunks(digits, 16))):
+ hi = "0x{0}ull".format(hi)
+ lo = "0x{0}ull".format(lo)
+ print(" u64x2({0}, {1}){2}".format(hi, lo, ',' if i+1 < KEYS else ''))
+
+print("};")
+EOF
+*/
+
+static constexpr const size_t kRoundKeys = 136;
+
+alignas(16) constexpr u64x2 round_keys[kRoundKeys] = {
+ u64x2(0x243F6A8885A308D3ull, 0x13198A2E03707344ull),
+ u64x2(0xA4093822299F31D0ull, 0x082EFA98EC4E6C89ull),
+ u64x2(0x452821E638D01377ull, 0xBE5466CF34E90C6Cull),
+ u64x2(0xC0AC29B7C97C50DDull, 0x3F84D5B5B5470917ull),
+ u64x2(0x9216D5D98979FB1Bull, 0xD1310BA698DFB5ACull),
+ u64x2(0x2FFD72DBD01ADFB7ull, 0xB8E1AFED6A267E96ull),
+ u64x2(0xBA7C9045F12C7F99ull, 0x24A19947B3916CF7ull),
+ u64x2(0x0801F2E2858EFC16ull, 0x636920D871574E69ull),
+ u64x2(0xA458FEA3F4933D7Eull, 0x0D95748F728EB658ull),
+ u64x2(0x718BCD5882154AEEull, 0x7B54A41DC25A59B5ull),
+ u64x2(0x9C30D5392AF26013ull, 0xC5D1B023286085F0ull),
+ u64x2(0xCA417918B8DB38EFull, 0x8E79DCB0603A180Eull),
+ u64x2(0x6C9E0E8BB01E8A3Eull, 0xD71577C1BD314B27ull),
+ u64x2(0x78AF2FDA55605C60ull, 0xE65525F3AA55AB94ull),
+ u64x2(0x5748986263E81440ull, 0x55CA396A2AAB10B6ull),
+ u64x2(0xB4CC5C341141E8CEull, 0xA15486AF7C72E993ull),
+ u64x2(0xB3EE1411636FBC2Aull, 0x2BA9C55D741831F6ull),
+ u64x2(0xCE5C3E169B87931Eull, 0xAFD6BA336C24CF5Cull),
+ u64x2(0x7A32538128958677ull, 0x3B8F48986B4BB9AFull),
+ u64x2(0xC4BFE81B66282193ull, 0x61D809CCFB21A991ull),
+ u64x2(0x487CAC605DEC8032ull, 0xEF845D5DE98575B1ull),
+ u64x2(0xDC262302EB651B88ull, 0x23893E81D396ACC5ull),
+ u64x2(0x0F6D6FF383F44239ull, 0x2E0B4482A4842004ull),
+ u64x2(0x69C8F04A9E1F9B5Eull, 0x21C66842F6E96C9Aull),
+ u64x2(0x670C9C61ABD388F0ull, 0x6A51A0D2D8542F68ull),
+ u64x2(0x960FA728AB5133A3ull, 0x6EEF0B6C137A3BE4ull),
+ u64x2(0xBA3BF0507EFB2A98ull, 0xA1F1651D39AF0176ull),
+ u64x2(0x66CA593E82430E88ull, 0x8CEE8619456F9FB4ull),
+ u64x2(0x7D84A5C33B8B5EBEull, 0xE06F75D885C12073ull),
+ u64x2(0x401A449F56C16AA6ull, 0x4ED3AA62363F7706ull),
+ u64x2(0x1BFEDF72429B023Dull, 0x37D0D724D00A1248ull),
+ u64x2(0xDB0FEAD349F1C09Bull, 0x075372C980991B7Bull),
+ u64x2(0x25D479D8F6E8DEF7ull, 0xE3FE501AB6794C3Bull),
+ u64x2(0x976CE0BD04C006BAull, 0xC1A94FB6409F60C4ull),
+ u64x2(0x5E5C9EC2196A2463ull, 0x68FB6FAF3E6C53B5ull),
+ u64x2(0x1339B2EB3B52EC6Full, 0x6DFC511F9B30952Cull),
+ u64x2(0xCC814544AF5EBD09ull, 0xBEE3D004DE334AFDull),
+ u64x2(0x660F2807192E4BB3ull, 0xC0CBA85745C8740Full),
+ u64x2(0xD20B5F39B9D3FBDBull, 0x5579C0BD1A60320Aull),
+ u64x2(0xD6A100C6402C7279ull, 0x679F25FEFB1FA3CCull),
+ u64x2(0x8EA5E9F8DB3222F8ull, 0x3C7516DFFD616B15ull),
+ u64x2(0x2F501EC8AD0552ABull, 0x323DB5FAFD238760ull),
+ u64x2(0x53317B483E00DF82ull, 0x9E5C57BBCA6F8CA0ull),
+ u64x2(0x1A87562EDF1769DBull, 0xD542A8F6287EFFC3ull),
+ u64x2(0xAC6732C68C4F5573ull, 0x695B27B0BBCA58C8ull),
+ u64x2(0xE1FFA35DB8F011A0ull, 0x10FA3D98FD2183B8ull),
+ u64x2(0x4AFCB56C2DD1D35Bull, 0x9A53E479B6F84565ull),
+ u64x2(0xD28E49BC4BFB9790ull, 0xE1DDF2DAA4CB7E33ull),
+ u64x2(0x62FB1341CEE4C6E8ull, 0xEF20CADA36774C01ull),
+ u64x2(0xD07E9EFE2BF11FB4ull, 0x95DBDA4DAE909198ull),
+ u64x2(0xEAAD8E716B93D5A0ull, 0xD08ED1D0AFC725E0ull),
+ u64x2(0x8E3C5B2F8E7594B7ull, 0x8FF6E2FBF2122B64ull),
+ u64x2(0x8888B812900DF01Cull, 0x4FAD5EA0688FC31Cull),
+ u64x2(0xD1CFF191B3A8C1ADull, 0x2F2F2218BE0E1777ull),
+ u64x2(0xEA752DFE8B021FA1ull, 0xE5A0CC0FB56F74E8ull),
+ u64x2(0x18ACF3D6CE89E299ull, 0xB4A84FE0FD13E0B7ull),
+ u64x2(0x7CC43B81D2ADA8D9ull, 0x165FA26680957705ull),
+ u64x2(0x93CC7314211A1477ull, 0xE6AD206577B5FA86ull),
+ u64x2(0xC75442F5FB9D35CFull, 0xEBCDAF0C7B3E89A0ull),
+ u64x2(0xD6411BD3AE1E7E49ull, 0x00250E2D2071B35Eull),
+ u64x2(0x226800BB57B8E0AFull, 0x2464369BF009B91Eull),
+ u64x2(0x5563911D59DFA6AAull, 0x78C14389D95A537Full),
+ u64x2(0x207D5BA202E5B9C5ull, 0x832603766295CFA9ull),
+ u64x2(0x11C819684E734A41ull, 0xB3472DCA7B14A94Aull),
+ u64x2(0x1B5100529A532915ull, 0xD60F573FBC9BC6E4ull),
+ u64x2(0x2B60A47681E67400ull, 0x08BA6FB5571BE91Full),
+ u64x2(0xF296EC6B2A0DD915ull, 0xB6636521E7B9F9B6ull),
+ u64x2(0xFF34052EC5855664ull, 0x53B02D5DA99F8FA1ull),
+ u64x2(0x08BA47996E85076Aull, 0x4B7A70E9B5B32944ull),
+ u64x2(0xDB75092EC4192623ull, 0xAD6EA6B049A7DF7Dull),
+ u64x2(0x9CEE60B88FEDB266ull, 0xECAA8C71699A18FFull),
+ u64x2(0x5664526CC2B19EE1ull, 0x193602A575094C29ull),
+ u64x2(0xA0591340E4183A3Eull, 0x3F54989A5B429D65ull),
+ u64x2(0x6B8FE4D699F73FD6ull, 0xA1D29C07EFE830F5ull),
+ u64x2(0x4D2D38E6F0255DC1ull, 0x4CDD20868470EB26ull),
+ u64x2(0x6382E9C6021ECC5Eull, 0x09686B3F3EBAEFC9ull),
+ u64x2(0x3C9718146B6A70A1ull, 0x687F358452A0E286ull),
+ u64x2(0xB79C5305AA500737ull, 0x3E07841C7FDEAE5Cull),
+ u64x2(0x8E7D44EC5716F2B8ull, 0xB03ADA37F0500C0Dull),
+ u64x2(0xF01C1F040200B3FFull, 0xAE0CF51A3CB574B2ull),
+ u64x2(0x25837A58DC0921BDull, 0xD19113F97CA92FF6ull),
+ u64x2(0x9432477322F54701ull, 0x3AE5E58137C2DADCull),
+ u64x2(0xC8B576349AF3DDA7ull, 0xA94461460FD0030Eull),
+ u64x2(0xECC8C73EA4751E41ull, 0xE238CD993BEA0E2Full),
+ u64x2(0x3280BBA1183EB331ull, 0x4E548B384F6DB908ull),
+ u64x2(0x6F420D03F60A04BFull, 0x2CB8129024977C79ull),
+ u64x2(0x5679B072BCAF89AFull, 0xDE9A771FD9930810ull),
+ u64x2(0xB38BAE12DCCF3F2Eull, 0x5512721F2E6B7124ull),
+ u64x2(0x501ADDE69F84CD87ull, 0x7A5847187408DA17ull),
+ u64x2(0xBC9F9ABCE94B7D8Cull, 0xEC7AEC3ADB851DFAull),
+ u64x2(0x63094366C464C3D2ull, 0xEF1C18473215D808ull),
+ u64x2(0xDD433B3724C2BA16ull, 0x12A14D432A65C451ull),
+ u64x2(0x50940002133AE4DDull, 0x71DFF89E10314E55ull),
+ u64x2(0x81AC77D65F11199Bull, 0x043556F1D7A3C76Bull),
+ u64x2(0x3C11183B5924A509ull, 0xF28FE6ED97F1FBFAull),
+ u64x2(0x9EBABF2C1E153C6Eull, 0x86E34570EAE96FB1ull),
+ u64x2(0x860E5E0A5A3E2AB3ull, 0x771FE71C4E3D06FAull),
+ u64x2(0x2965DCB999E71D0Full, 0x803E89D65266C825ull),
+ u64x2(0x2E4CC9789C10B36Aull, 0xC6150EBA94E2EA78ull),
+ u64x2(0xA6FC3C531E0A2DF4ull, 0xF2F74EA7361D2B3Dull),
+ u64x2(0x1939260F19C27960ull, 0x5223A708F71312B6ull),
+ u64x2(0xEBADFE6EEAC31F66ull, 0xE3BC4595A67BC883ull),
+ u64x2(0xB17F37D1018CFF28ull, 0xC332DDEFBE6C5AA5ull),
+ u64x2(0x6558218568AB9702ull, 0xEECEA50FDB2F953Bull),
+ u64x2(0x2AEF7DAD5B6E2F84ull, 0x1521B62829076170ull),
+ u64x2(0xECDD4775619F1510ull, 0x13CCA830EB61BD96ull),
+ u64x2(0x0334FE1EAA0363CFull, 0xB5735C904C70A239ull),
+ u64x2(0xD59E9E0BCBAADE14ull, 0xEECC86BC60622CA7ull),
+ u64x2(0x9CAB5CABB2F3846Eull, 0x648B1EAF19BDF0CAull),
+ u64x2(0xA02369B9655ABB50ull, 0x40685A323C2AB4B3ull),
+ u64x2(0x319EE9D5C021B8F7ull, 0x9B540B19875FA099ull),
+ u64x2(0x95F7997E623D7DA8ull, 0xF837889A97E32D77ull),
+ u64x2(0x11ED935F16681281ull, 0x0E358829C7E61FD6ull),
+ u64x2(0x96DEDFA17858BA99ull, 0x57F584A51B227263ull),
+ u64x2(0x9B83C3FF1AC24696ull, 0xCDB30AEB532E3054ull),
+ u64x2(0x8FD948E46DBC3128ull, 0x58EBF2EF34C6FFEAull),
+ u64x2(0xFE28ED61EE7C3C73ull, 0x5D4A14D9E864B7E3ull),
+ u64x2(0x42105D14203E13E0ull, 0x45EEE2B6A3AAABEAull),
+ u64x2(0xDB6C4F15FACB4FD0ull, 0xC742F442EF6ABBB5ull),
+ u64x2(0x654F3B1D41CD2105ull, 0xD81E799E86854DC7ull),
+ u64x2(0xE44B476A3D816250ull, 0xCF62A1F25B8D2646ull),
+ u64x2(0xFC8883A0C1C7B6A3ull, 0x7F1524C369CB7492ull),
+ u64x2(0x47848A0B5692B285ull, 0x095BBF00AD19489Dull),
+ u64x2(0x1462B17423820D00ull, 0x58428D2A0C55F5EAull),
+ u64x2(0x1DADF43E233F7061ull, 0x3372F0928D937E41ull),
+ u64x2(0xD65FECF16C223BDBull, 0x7CDE3759CBEE7460ull),
+ u64x2(0x4085F2A7CE77326Eull, 0xA607808419F8509Eull),
+ u64x2(0xE8EFD85561D99735ull, 0xA969A7AAC50C06C2ull),
+ u64x2(0x5A04ABFC800BCADCull, 0x9E447A2EC3453484ull),
+ u64x2(0xFDD567050E1E9EC9ull, 0xDB73DBD3105588CDull),
+ u64x2(0x675FDA79E3674340ull, 0xC5C43465713E38D8ull),
+ u64x2(0x3D28F89EF16DFF20ull, 0x153E21E78FB03D4Aull),
+ u64x2(0xE6E39F2BDB83ADF7ull, 0xE93D5A68948140F7ull),
+ u64x2(0xF64C261C94692934ull, 0x411520F77602D4F7ull),
+ u64x2(0xBCF46B2ED4A10068ull, 0xD40824713320F46Aull),
+ u64x2(0x43B7D4B7500061AFull, 0x1E39F62E97244546ull)};
+
+#endif // ABSL_RANDOM_INTERNAL_RANDEN_KEYS_INC_
diff --git a/third_party/abseil-cpp/absl/random/internal/randen.cc b/third_party/abseil-cpp/absl/random/internal/randen.cc
index c1bc044435..78a1e00c08 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen.cc
@@ -17,7 +17,7 @@
#include "absl/base/internal/raw_logging.h"
#include "absl/random/internal/randen_detect.h"
-// RANDen = RANDom generator or beetroots in Swiss High German.
+// RANDen = RANDom generator or beetroots in Swiss German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
diff --git a/third_party/abseil-cpp/absl/random/internal/randen.h b/third_party/abseil-cpp/absl/random/internal/randen.h
index 9a3840b8f1..c2834aaf3d 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen.h
+++ b/third_party/abseil-cpp/absl/random/internal/randen.h
@@ -26,7 +26,7 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
-// RANDen = RANDom generator or beetroots in Swiss High German.
+// RANDen = RANDom generator or beetroots in Swiss German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_detect.cc b/third_party/abseil-cpp/absl/random/internal/randen_detect.cc
index bbe7b96532..d63230c255 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_detect.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_detect.cc
@@ -1,13 +1,13 @@
// Copyright 2017 The Abseil Authors.
//
-// Licensed under the Apache License, Version 2.0 (the "License");
+// Licensed under the Apache License, Version 2.0 (the"License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
+// distributed under the License is distributed on an"AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_engine.h b/third_party/abseil-cpp/absl/random/internal/randen_engine.h
index 372c3ac2bd..6b33731336 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_engine.h
+++ b/third_party/abseil-cpp/absl/random/internal/randen_engine.h
@@ -23,7 +23,6 @@
#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"
@@ -77,7 +76,7 @@ class alignas(16) randen_engine {
impl_.Generate(state_);
}
- return little_endian::ToHost(state_[next_++]);
+ return state_[next_++];
}
template <class SeedSequence>
@@ -121,13 +120,6 @@ class alignas(16) randen_engine {
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);
-#ifdef ABSL_IS_BIG_ENDIAN
- // Randen expects the seed buffer to be in Little Endian; reverse it on
- // Big Endian platforms.
- for (sequence_result_type& e : buffer) {
- e = absl::little_endian::FromHost(e);
- }
-#endif
// The Randen paper suggests preferentially initializing even-numbered
// 128-bit vectors of the randen state (there are 16 such vectors).
// The seed data is merged into the state offset by 128-bits, which
@@ -189,8 +181,7 @@ class alignas(16) randen_engine {
// 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 << static_cast<numeric_type>(elem) << os.fill();
}
os << engine.next_;
return os;
@@ -209,7 +200,7 @@ class alignas(16) randen_engine {
// 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));
+ elem = static_cast<result_type>(value);
}
is >> next;
if (is.fail()) {
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc b/third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc
index fee6677cb4..e23844f12e 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_hwaes.cc
@@ -23,20 +23,48 @@
#include <cstring>
#include "absl/base/attributes.h"
-#include "absl/numeric/int128.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
-// The following plaforms have implemented RandenHwAes.
-#if defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32) || \
- defined(ABSL_ARCH_PPC) || defined(ABSL_ARCH_ARM) || \
- defined(ABSL_ARCH_AARCH64)
#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)
@@ -87,11 +115,8 @@ ABSL_NAMESPACE_END
// Accelerated implementations are supported.
// We need the per-architecture includes and defines.
//
-namespace {
-
-using absl::random_internal::RandenTraits;
-} // namespace
+#include "absl/random/internal/randen_traits.h"
// TARGET_CRYPTO defines a crypto attribute for each architecture.
//
@@ -116,7 +141,6 @@ using absl::random_internal::RandenTraits;
#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:
@@ -126,6 +150,7 @@ using absl::random_internal::RandenTraits;
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,
@@ -152,9 +177,14 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
}
// Enables native loads in the round loop by pre-swapping.
-inline ABSL_TARGET_CRYPTO void SwapEndian(absl::uint128* state) {
- for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
- Vector128Store(ReverseBytes(Vector128Load(state + block)), state + block);
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t* state) {
+ using absl::random_internal::RandenTraits;
+ constexpr size_t kLanes = 2;
+ constexpr size_t kFeistelBlocks = RandenTraits::kFeistelBlocks;
+
+ for (uint32_t branch = 0; branch < kFeistelBlocks; ++branch) {
+ const Vector128 v = ReverseBytes(Vector128Load(state + kLanes * branch));
+ Vector128Store(v, state + kLanes * branch);
}
}
@@ -162,6 +192,22 @@ inline ABSL_TARGET_CRYPTO void SwapEndian(absl::uint128* state) {
#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
@@ -205,13 +251,13 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
return vaesmcq_u8(vaeseq_u8(state, uint8x16_t{})) ^ round_key;
}
-inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t*) {}
} // namespace
#elif defined(ABSL_ARCH_X86_64) || defined(ABSL_ARCH_X86_32)
// On x86 we rely on the aesni instructions
-#include <immintrin.h>
+#include <wmmintrin.h>
namespace {
@@ -220,7 +266,7 @@ namespace {
class Vector128 {
public:
// Convert from/to intrinsics.
- inline explicit Vector128(const __m128i& v) : data_(v) {}
+ inline explicit Vector128(const __m128i& Vector128) : data_(Vector128) {}
inline __m128i data() const { return data_; }
@@ -251,12 +297,39 @@ inline ABSL_TARGET_CRYPTO Vector128 AesRound(const Vector128& state,
return Vector128(_mm_aesenc_si128(state.data(), round_key.data()));
}
-inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
+inline ABSL_TARGET_CRYPTO void SwapEndian(uint64_t*) {}
} // namespace
#endif
+namespace {
+
+// u64x2 is a 128-bit, (2 x uint64_t lanes) struct used to store
+// the randen_keys.
+struct alignas(16) u64x2 {
+ constexpr u64x2(uint64_t hi, uint64_t lo)
+#if defined(ABSL_ARCH_PPC)
+ // This has been tested with PPC running in little-endian mode;
+ // We byte-swap the u64x2 structure from little-endian to big-endian
+ // because altivec always runs in big-endian mode.
+ : v{__builtin_bswap64(hi), __builtin_bswap64(lo)} {
+#else
+ : v{lo, hi} {
+#endif
+ }
+
+ constexpr bool operator==(const u64x2& other) const {
+ return v[0] == other.v[0] && v[1] == other.v[1];
+ }
+
+ constexpr bool operator!=(const u64x2& other) const {
+ return !(*this == other);
+ }
+
+ uint64_t v[2];
+}; // namespace
+
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunknown-pragmas"
@@ -265,6 +338,7 @@ inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
// At this point, all of the platform-specific features have been defined /
// implemented.
//
+// REQUIRES: using u64x2 = ...
// REQUIRES: using Vector128 = ...
// REQUIRES: Vector128 Vector128Load(void*) {...}
// REQUIRES: void Vector128Store(Vector128, void*) {...}
@@ -273,50 +347,94 @@ inline ABSL_TARGET_CRYPTO void SwapEndian(void*) {}
//
// PROVIDES: absl::random_internal::RandenHwAes::Absorb
// PROVIDES: absl::random_internal::RandenHwAes::Generate
-namespace {
+
+// RANDen = RANDom generator or beetroots in Swiss 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.
+
+// Randen constants.
+using absl::random_internal::RandenTraits;
+constexpr size_t kStateBytes = RandenTraits::kStateBytes;
+constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
+constexpr size_t kFeistelBlocks = RandenTraits::kFeistelBlocks;
+constexpr size_t kFeistelRounds = RandenTraits::kFeistelRounds;
+constexpr size_t kFeistelFunctions = RandenTraits::kFeistelFunctions;
+
+// Independent keys (272 = 2.1 KiB) for the first AES subround of each function.
+constexpr size_t kKeys = kFeistelRounds * kFeistelFunctions;
+
+// INCLUDE keys.
+#include "absl/random/internal/randen-keys.inc"
+
+static_assert(kKeys == kRoundKeys, "kKeys and kRoundKeys must be equal");
+static_assert(round_keys[kKeys - 1] != u64x2(0, 0),
+ "Too few round_keys initializers");
+
+// Number of uint64_t lanes per 128-bit vector;
+constexpr size_t kLanes = 2;
// 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(absl::uint128* 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);
+inline ABSL_TARGET_CRYPTO void BlockShuffle(uint64_t* state) {
+ static_assert(kFeistelBlocks == 16, "Expecting 16 FeistelBlocks.");
+
+ constexpr size_t shuffle[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 loop.
+ const Vector128 v0 = Vector128Load(state + kLanes * shuffle[0]);
+ const Vector128 v1 = Vector128Load(state + kLanes * shuffle[1]);
+ const Vector128 v2 = Vector128Load(state + kLanes * shuffle[2]);
+ const Vector128 v3 = Vector128Load(state + kLanes * shuffle[3]);
+ const Vector128 v4 = Vector128Load(state + kLanes * shuffle[4]);
+ const Vector128 v5 = Vector128Load(state + kLanes * shuffle[5]);
+ const Vector128 v6 = Vector128Load(state + kLanes * shuffle[6]);
+ const Vector128 v7 = Vector128Load(state + kLanes * shuffle[7]);
+ const Vector128 w0 = Vector128Load(state + kLanes * shuffle[8]);
+ const Vector128 w1 = Vector128Load(state + kLanes * shuffle[9]);
+ const Vector128 w2 = Vector128Load(state + kLanes * shuffle[10]);
+ const Vector128 w3 = Vector128Load(state + kLanes * shuffle[11]);
+ const Vector128 w4 = Vector128Load(state + kLanes * shuffle[12]);
+ const Vector128 w5 = Vector128Load(state + kLanes * shuffle[13]);
+ const Vector128 w6 = Vector128Load(state + kLanes * shuffle[14]);
+ const Vector128 w7 = Vector128Load(state + kLanes * shuffle[15]);
+
+ Vector128Store(v0, state + kLanes * 0);
+ Vector128Store(v1, state + kLanes * 1);
+ Vector128Store(v2, state + kLanes * 2);
+ Vector128Store(v3, state + kLanes * 3);
+ Vector128Store(v4, state + kLanes * 4);
+ Vector128Store(v5, state + kLanes * 5);
+ Vector128Store(v6, state + kLanes * 6);
+ Vector128Store(v7, state + kLanes * 7);
+ Vector128Store(w0, state + kLanes * 8);
+ Vector128Store(w1, state + kLanes * 9);
+ Vector128Store(w2, state + kLanes * 10);
+ Vector128Store(w3, state + kLanes * 11);
+ Vector128Store(w4, state + kLanes * 12);
+ Vector128Store(w5, state + kLanes * 13);
+ Vector128Store(w6, state + kLanes * 14);
+ Vector128Store(w7, state + kLanes * 15);
}
// Feistel round function using two AES subrounds. Very similar to F()
@@ -324,30 +442,28 @@ inline ABSL_TARGET_CRYPTO void BlockShuffle(absl::uint128* state) {
// 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 absl::uint128* FeistelRound(
- absl::uint128* state,
- const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
- static_assert(RandenTraits::kFeistelBlocks == 16,
- "Expecting 16 FeistelBlocks.");
+inline ABSL_TARGET_CRYPTO const u64x2* FeistelRound(
+ uint64_t* state, const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ static_assert(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);
+ const Vector128 s0 = Vector128Load(state + kLanes * 0);
+ const Vector128 s1 = Vector128Load(state + kLanes * 1);
+ const Vector128 s2 = Vector128Load(state + kLanes * 2);
+ const Vector128 s3 = Vector128Load(state + kLanes * 3);
+ const Vector128 s4 = Vector128Load(state + kLanes * 4);
+ const Vector128 s5 = Vector128Load(state + kLanes * 5);
+ const Vector128 s6 = Vector128Load(state + kLanes * 6);
+ const Vector128 s7 = Vector128Load(state + kLanes * 7);
+ const Vector128 s8 = Vector128Load(state + kLanes * 8);
+ const Vector128 s9 = Vector128Load(state + kLanes * 9);
+ const Vector128 s10 = Vector128Load(state + kLanes * 10);
+ const Vector128 s11 = Vector128Load(state + kLanes * 11);
+ const Vector128 s12 = Vector128Load(state + kLanes * 12);
+ const Vector128 s13 = Vector128Load(state + kLanes * 13);
+ const Vector128 s14 = Vector128Load(state + kLanes * 14);
+ const Vector128 s15 = Vector128Load(state + kLanes * 15);
// Encode even blocks with keys.
const Vector128 e0 = AesRound(s0, Vector128Load(keys + 0));
@@ -370,14 +486,14 @@ inline ABSL_TARGET_CRYPTO const absl::uint128* FeistelRound(
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);
+ Vector128Store(o1, state + kLanes * 1);
+ Vector128Store(o3, state + kLanes * 3);
+ Vector128Store(o5, state + kLanes * 5);
+ Vector128Store(o7, state + kLanes * 7);
+ Vector128Store(o9, state + kLanes * 9);
+ Vector128Store(o11, state + kLanes * 11);
+ Vector128Store(o13, state + kLanes * 13);
+ Vector128Store(o15, state + kLanes * 15);
return keys + 8;
}
@@ -387,14 +503,16 @@ inline ABSL_TARGET_CRYPTO const absl::uint128* FeistelRound(
// 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(
- absl::uint128* state,
- const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ const void* ABSL_RANDOM_INTERNAL_RESTRICT keys, uint64_t* state) {
+ const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys128 =
+ static_cast<const u64x2*>(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);
+ for (size_t round = 0; round < kFeistelRounds; ++round) {
+ keys128 = FeistelRound(state, keys128);
BlockShuffle(state);
}
}
@@ -410,102 +528,96 @@ 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
+ return round_keys;
}
// 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<absl::uint128 * ABSL_RANDOM_INTERNAL_RESTRICT>(
- state_void);
- const auto* seed =
- reinterpret_cast<const absl::uint128 * 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);
+ auto* state = static_cast<uint64_t*>(state_void);
+ const auto* seed = static_cast<const uint64_t*>(seed_void);
+
+ constexpr size_t kCapacityBlocks = kCapacityBytes / sizeof(Vector128);
+ constexpr size_t kStateBlocks = kStateBytes / sizeof(Vector128);
+
+ static_assert(kCapacityBlocks * sizeof(Vector128) == kCapacityBytes,
+ "Not i*V");
+ static_assert(kCapacityBlocks == 1, "Unexpected Randen kCapacityBlocks");
+ static_assert(kStateBlocks == 16, "Unexpected Randen kStateBlocks");
+
+ Vector128 b1 = Vector128Load(state + kLanes * 1);
+ b1 ^= Vector128Load(seed + kLanes * 0);
+ Vector128Store(b1, state + kLanes * 1);
+
+ Vector128 b2 = Vector128Load(state + kLanes * 2);
+ b2 ^= Vector128Load(seed + kLanes * 1);
+ Vector128Store(b2, state + kLanes * 2);
+
+ Vector128 b3 = Vector128Load(state + kLanes * 3);
+ b3 ^= Vector128Load(seed + kLanes * 2);
+ Vector128Store(b3, state + kLanes * 3);
+
+ Vector128 b4 = Vector128Load(state + kLanes * 4);
+ b4 ^= Vector128Load(seed + kLanes * 3);
+ Vector128Store(b4, state + kLanes * 4);
+
+ Vector128 b5 = Vector128Load(state + kLanes * 5);
+ b5 ^= Vector128Load(seed + kLanes * 4);
+ Vector128Store(b5, state + kLanes * 5);
+
+ Vector128 b6 = Vector128Load(state + kLanes * 6);
+ b6 ^= Vector128Load(seed + kLanes * 5);
+ Vector128Store(b6, state + kLanes * 6);
+
+ Vector128 b7 = Vector128Load(state + kLanes * 7);
+ b7 ^= Vector128Load(seed + kLanes * 6);
+ Vector128Store(b7, state + kLanes * 7);
+
+ Vector128 b8 = Vector128Load(state + kLanes * 8);
+ b8 ^= Vector128Load(seed + kLanes * 7);
+ Vector128Store(b8, state + kLanes * 8);
+
+ Vector128 b9 = Vector128Load(state + kLanes * 9);
+ b9 ^= Vector128Load(seed + kLanes * 8);
+ Vector128Store(b9, state + kLanes * 9);
+
+ Vector128 b10 = Vector128Load(state + kLanes * 10);
+ b10 ^= Vector128Load(seed + kLanes * 9);
+ Vector128Store(b10, state + kLanes * 10);
+
+ Vector128 b11 = Vector128Load(state + kLanes * 11);
+ b11 ^= Vector128Load(seed + kLanes * 10);
+ Vector128Store(b11, state + kLanes * 11);
+
+ Vector128 b12 = Vector128Load(state + kLanes * 12);
+ b12 ^= Vector128Load(seed + kLanes * 11);
+ Vector128Store(b12, state + kLanes * 12);
+
+ Vector128 b13 = Vector128Load(state + kLanes * 13);
+ b13 ^= Vector128Load(seed + kLanes * 12);
+ Vector128Store(b13, state + kLanes * 13);
+
+ Vector128 b14 = Vector128Load(state + kLanes * 14);
+ b14 ^= Vector128Load(seed + kLanes * 13);
+ Vector128Store(b14, state + kLanes * 14);
+
+ Vector128 b15 = Vector128Load(state + kLanes * 15);
+ b15 ^= Vector128Load(seed + kLanes * 14);
+ Vector128Store(b15, state + kLanes * 15);
}
// NOLINTNEXTLINE
-void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys_void,
+void ABSL_TARGET_CRYPTO RandenHwAes::Generate(const void* keys,
void* state_void) {
- static_assert(RandenTraits::kCapacityBytes == sizeof(Vector128),
- "Capacity mismatch");
+ static_assert(kCapacityBytes == sizeof(Vector128), "Capacity mismatch");
- auto* state = reinterpret_cast<absl::uint128*>(state_void);
- const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);
+ auto* state = static_cast<uint64_t*>(state_void);
const Vector128 prev_inner = Vector128Load(state);
SwapEndian(state);
- Permute(state, keys);
+ Permute(keys, state);
SwapEndian(state);
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_hwaes.h b/third_party/abseil-cpp/absl/random/internal/randen_hwaes.h
index 71a7f69f25..bce36b5226 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_hwaes.h
+++ b/third_party/abseil-cpp/absl/random/internal/randen_hwaes.h
@@ -26,7 +26,7 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
-// RANDen = RANDom generator or beetroots in Swiss High German.
+// RANDen = RANDom generator or beetroots in Swiss German.
// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
//
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_hwaes_test.cc b/third_party/abseil-cpp/absl/random/internal/randen_hwaes_test.cc
index 2348b55c35..a7cbd46b2d 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_hwaes_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_hwaes_test.cc
@@ -27,39 +27,42 @@ namespace {
using absl::random_internal::RandenHwAes;
using absl::random_internal::RandenTraits;
+struct randen {
+ static constexpr size_t kStateSizeT =
+ RandenTraits::kStateBytes / sizeof(uint64_t);
+ uint64_t state[kStateSizeT];
+ static constexpr size_t kSeedSizeT =
+ RandenTraits::kSeedBytes / sizeof(uint32_t);
+ uint32_t seed[kSeedSizeT];
+};
+
TEST(RandenHwAesTest, Default) {
EXPECT_TRUE(absl::random_internal::CPUSupportsRandenHwAes());
- constexpr uint8_t kGolden[] = {
- 0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,
- 0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,
- 0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,
- 0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,
- 0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,
- 0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,
- 0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,
- 0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,
- 0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,
- 0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,
- 0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,
- 0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,
- 0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,
- 0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,
- 0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,
- 0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,
- 0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,
- 0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,
- 0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,
- 0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,
- 0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,
- 0x82, 0xf0, 0x1e, 0x81,
+ 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) uint8_t state[RandenTraits::kStateBytes];
- std::memset(state, 0, sizeof(state));
+ alignas(16) randen d;
+ memset(d.state, 0, sizeof(d.state));
+ RandenHwAes::Generate(RandenHwAes::GetKeys(), d.state);
- RandenHwAes::Generate(RandenHwAes::GetKeys(), state);
- EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(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
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc b/third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc
deleted file mode 100644
index 5fb3ca556d..0000000000
--- a/third_party/abseil-cpp/absl/random/internal/randen_round_keys.cc
+++ /dev/null
@@ -1,462 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/random/internal/randen_slow.cc b/third_party/abseil-cpp/absl/random/internal/randen_slow.cc
index 9bfd2a4092..8d07458254 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_slow.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_slow.cc
@@ -19,10 +19,7 @@
#include <cstring>
#include "absl/base/attributes.h"
-#include "absl/base/internal/endian.h"
-#include "absl/numeric/int128.h"
#include "absl/random/internal/platform.h"
-#include "absl/random/internal/randen_traits.h"
#if ABSL_HAVE_ATTRIBUTE(always_inline) || \
(defined(__GNUC__) && !defined(__clang__))
@@ -40,303 +37,369 @@
namespace {
// AES portions based on rijndael-alg-fst.c,
-// https://fastcrypto.org/front/misc/rijndael-alg-fst.c, and modified for
-// platform-endianness.
+// 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] = {
- 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6,
- 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56,
- 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f,
- 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb,
- 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
- 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c,
- 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551,
- 0x34e5e5d1, 0x08f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a,
- 0x0c040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637,
- 0x0f05050a, 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
- 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d,
- 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b,
- 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd,
- 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1,
- 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
- 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85,
- 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a,
- 0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x06020204, 0x817f7ffe,
- 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d,
- 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
- 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5,
- 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3,
- 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755,
- 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6,
- 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
- 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428,
- 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264,
- 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0x0a06060c, 0x6c242448, 0xe45c5cb8,
- 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531,
- 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
- 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac,
- 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810,
- 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657,
- 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e,
- 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
- 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7, 0x120e0e1c,
- 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199,
- 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122,
- 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c,
- 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
- 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7,
- 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e,
- 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c,
+ 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] = {
- 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d, 0x6b6bd6bd,
- 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203, 0x6767cea9, 0x2b2b567d,
- 0xfefee719, 0xd7d7b562, 0xabab4de6, 0x7676ec9a, 0xcaca8f45, 0x82821f9d,
- 0xc9c98940, 0x7d7dfa87, 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b,
- 0xadad41ec, 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
- 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae, 0x26264c6a,
- 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f, 0x3434685c, 0xa5a551f4,
- 0xe5e5d134, 0xf1f1f908, 0x7171e293, 0xd8d8ab73, 0x31316253, 0x15152a3f,
- 0x0404080c, 0xc7c79552, 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1,
- 0x05050a0f, 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
- 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b, 0x83831d9e,
- 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2, 0x5a5ab4ee, 0xa0a05bfb,
- 0x5252a4f6, 0x3b3b764d, 0xd6d6b761, 0xb3b37dce, 0x2929527b, 0xe3e3dd3e,
- 0x2f2f5e71, 0x84841397, 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c,
- 0x20204060, 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
- 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8, 0xcfcf854a,
- 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16, 0x434386c5, 0x4d4d9ad7,
- 0x33336655, 0x85851194, 0x45458acf, 0xf9f9e910, 0x02020406, 0x7f7ffe81,
- 0x5050a0f0, 0x3c3c7844, 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe,
- 0x404080c0, 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
- 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030, 0xffffe51a,
- 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814, 0x13132635, 0xececc32f,
- 0x5f5fbee1, 0x979735a2, 0x444488cc, 0x17172e39, 0xc4c49357, 0xa7a755f2,
- 0x7e7efc82, 0x3d3d7a47, 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695,
- 0x6060c0a0, 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
- 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3, 0x1414283c,
- 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76, 0xe0e0db3b, 0x32326456,
- 0x3a3a744e, 0x0a0a141e, 0x494992db, 0x06060c0a, 0x2424486c, 0x5c5cb8e4,
- 0xc2c29f5d, 0xd3d3bd6e, 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4,
- 0xe4e4d337, 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
- 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4, 0x5656acfa,
- 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e, 0xaeae47e9, 0x08081018,
- 0xbaba6fd5, 0x7878f088, 0x25254a6f, 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1,
- 0xb4b473c7, 0xc6c69751, 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21,
- 0x4b4b96dd, 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
- 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701, 0x0e0e1c12,
- 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0, 0x86861791, 0xc1c19958,
- 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938, 0xf8f8eb13, 0x98982bb3, 0x11112233,
- 0x6969d2bb, 0xd9d9a970, 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22,
- 0x87871592, 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
- 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da, 0xe6e6d731,
- 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0, 0x2d2d5a77, 0x0f0f1e11,
- 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6, 0x16162c3a,
+ 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] = {
- 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2, 0x6bd6bd6b,
- 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301, 0x67cea967, 0x2b567d2b,
- 0xfee719fe, 0xd7b562d7, 0xab4de6ab, 0x76ec9a76, 0xca8f45ca, 0x821f9d82,
- 0xc98940c9, 0x7dfa877d, 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0,
- 0xad41ecad, 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
- 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93, 0x264c6a26,
- 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc, 0x34685c34, 0xa551f4a5,
- 0xe5d134e5, 0xf1f908f1, 0x71e29371, 0xd8ab73d8, 0x31625331, 0x152a3f15,
- 0x04080c04, 0xc79552c7, 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196,
- 0x050a0f05, 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
- 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09, 0x831d9e83,
- 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e, 0x5ab4ee5a, 0xa05bfba0,
- 0x52a4f652, 0x3b764d3b, 0xd6b761d6, 0xb37dceb3, 0x29527b29, 0xe3dd3ee3,
- 0x2f5e712f, 0x84139784, 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced,
- 0x20406020, 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
- 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858, 0xcf854acf,
- 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb, 0x4386c543, 0x4d9ad74d,
- 0x33665533, 0x85119485, 0x458acf45, 0xf9e910f9, 0x02040602, 0x7ffe817f,
- 0x50a0f050, 0x3c78443c, 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3,
- 0x4080c040, 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
- 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010, 0xffe51aff,
- 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c, 0x13263513, 0xecc32fec,
- 0x5fbee15f, 0x9735a297, 0x4488cc44, 0x172e3917, 0xc49357c4, 0xa755f2a7,
- 0x7efc827e, 0x3d7a473d, 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573,
- 0x60c0a060, 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
- 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8, 0x14283c14,
- 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db, 0xe0db3be0, 0x32645632,
- 0x3a744e3a, 0x0a141e0a, 0x4992db49, 0x060c0a06, 0x24486c24, 0x5cb8e45c,
- 0xc29f5dc2, 0xd3bd6ed3, 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495,
- 0xe4d337e4, 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
- 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c, 0x56acfa56,
- 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a, 0xae47e9ae, 0x08101808,
- 0xba6fd5ba, 0x78f08878, 0x254a6f25, 0x2e5c722e, 0x1c38241c, 0xa657f1a6,
- 0xb473c7b4, 0xc69751c6, 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f,
- 0x4b96dd4b, 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
- 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6, 0x0e1c120e,
- 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9, 0x86179186, 0xc19958c1,
- 0x1d3a271d, 0x9e27b99e, 0xe1d938e1, 0xf8eb13f8, 0x982bb398, 0x11223311,
- 0x69d2bb69, 0xd9a970d9, 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e,
- 0x87159287, 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
- 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf, 0xe6d731e6,
- 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099, 0x2d5a772d, 0x0f1e110f,
- 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb, 0x162c3a16,
+ 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] = {
- 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2, 0xd6bd6b6b,
- 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101, 0xcea96767, 0x567d2b2b,
- 0xe719fefe, 0xb562d7d7, 0x4de6abab, 0xec9a7676, 0x8f45caca, 0x1f9d8282,
- 0x8940c9c9, 0xfa877d7d, 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0,
- 0x41ecadad, 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
- 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393, 0x4c6a2626,
- 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc, 0x685c3434, 0x51f4a5a5,
- 0xd134e5e5, 0xf908f1f1, 0xe2937171, 0xab73d8d8, 0x62533131, 0x2a3f1515,
- 0x080c0404, 0x9552c7c7, 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696,
- 0x0a0f0505, 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
- 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909, 0x1d9e8383,
- 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e, 0xb4ee5a5a, 0x5bfba0a0,
- 0xa4f65252, 0x764d3b3b, 0xb761d6d6, 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3,
- 0x5e712f2f, 0x13978484, 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded,
- 0x40602020, 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
- 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858, 0x854acfcf,
- 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb, 0x86c54343, 0x9ad74d4d,
- 0x66553333, 0x11948585, 0x8acf4545, 0xe910f9f9, 0x04060202, 0xfe817f7f,
- 0xa0f05050, 0x78443c3c, 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3,
- 0x80c04040, 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
- 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010, 0xe51affff,
- 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c, 0x26351313, 0xc32fecec,
- 0xbee15f5f, 0x35a29797, 0x88cc4444, 0x2e391717, 0x9357c4c4, 0x55f2a7a7,
- 0xfc827e7e, 0x7a473d3d, 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373,
- 0xc0a06060, 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
- 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8, 0x283c1414,
- 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb, 0xdb3be0e0, 0x64563232,
- 0x744e3a3a, 0x141e0a0a, 0x92db4949, 0x0c0a0606, 0x486c2424, 0xb8e45c5c,
- 0x9f5dc2c2, 0xbd6ed3d3, 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595,
- 0xd337e4e4, 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
- 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c, 0xacfa5656,
- 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a, 0x47e9aeae, 0x10180808,
- 0x6fd5baba, 0xf0887878, 0x4a6f2525, 0x5c722e2e, 0x38241c1c, 0x57f1a6a6,
- 0x73c7b4b4, 0x9751c6c6, 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f,
- 0x96dd4b4b, 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
- 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6, 0x1c120e0e,
- 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9, 0x17918686, 0x9958c1c1,
- 0x3a271d1d, 0x27b99e9e, 0xd938e1e1, 0xeb13f8f8, 0x2bb39898, 0x22331111,
- 0xd2bb6969, 0xa970d9d9, 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e,
- 0x15928787, 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
- 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf, 0xd731e6e6,
- 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999, 0x5a772d2d, 0x1e110f0f,
- 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb, 0x2c3a1616,
+ 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,
+};
+
+struct alignas(16) u64x2 {
+ constexpr u64x2() : v{0, 0} {};
+ constexpr u64x2(uint64_t hi, uint64_t lo) : v{lo, hi} {}
+
+ uint64_t v[2];
};
// Software implementation of the Vector128 class, using uint32_t
// as an underlying vector register.
-struct alignas(16) Vector128 {
+//
+struct Vector128 {
+ inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128& operator^=(
+ const Vector128& other) {
+ s[0] ^= other.s[0];
+ s[1] ^= other.s[1];
+ s[2] ^= other.s[2];
+ s[3] ^= other.s[3];
+ return *this;
+ }
+
uint32_t s[4];
};
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE Vector128
-Vector128Load(const void* from) {
+Vector128Load(const void* ABSL_RANDOM_INTERNAL_RESTRICT from) {
Vector128 result;
- std::memcpy(result.s, from, sizeof(Vector128));
+ const uint8_t* ABSL_RANDOM_INTERNAL_RESTRICT 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) {
- std::memcpy(to, v.s, sizeof(Vector128));
+ const Vector128& v, void* ABSL_RANDOM_INTERNAL_RESTRICT 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) {
+ // clang-format off
Vector128 result;
-#ifdef ABSL_IS_LITTLE_ENDIAN
- result.s[0] = round_key.s[0] ^ //
- te0[uint8_t(state.s[0])] ^ //
- te1[uint8_t(state.s[1] >> 8)] ^ //
- te2[uint8_t(state.s[2] >> 16)] ^ //
- te3[uint8_t(state.s[3] >> 24)];
- result.s[1] = round_key.s[1] ^ //
- te0[uint8_t(state.s[1])] ^ //
- te1[uint8_t(state.s[2] >> 8)] ^ //
- te2[uint8_t(state.s[3] >> 16)] ^ //
- te3[uint8_t(state.s[0] >> 24)];
- result.s[2] = round_key.s[2] ^ //
- te0[uint8_t(state.s[2])] ^ //
- te1[uint8_t(state.s[3] >> 8)] ^ //
- te2[uint8_t(state.s[0] >> 16)] ^ //
- te3[uint8_t(state.s[1] >> 24)];
- result.s[3] = round_key.s[3] ^ //
- te0[uint8_t(state.s[3])] ^ //
- te1[uint8_t(state.s[0] >> 8)] ^ //
- te2[uint8_t(state.s[1] >> 16)] ^ //
- te3[uint8_t(state.s[2] >> 24)];
-#else
- result.s[0] = round_key.s[0] ^ //
- te0[uint8_t(state.s[0])] ^ //
- te1[uint8_t(state.s[3] >> 8)] ^ //
- te2[uint8_t(state.s[2] >> 16)] ^ //
- te3[uint8_t(state.s[1] >> 24)];
- result.s[1] = round_key.s[1] ^ //
- te0[uint8_t(state.s[1])] ^ //
- te1[uint8_t(state.s[0] >> 8)] ^ //
- te2[uint8_t(state.s[3] >> 16)] ^ //
- te3[uint8_t(state.s[2] >> 24)];
- result.s[2] = round_key.s[2] ^ //
- te0[uint8_t(state.s[2])] ^ //
- te1[uint8_t(state.s[1] >> 8)] ^ //
- te2[uint8_t(state.s[0] >> 16)] ^ //
- te3[uint8_t(state.s[3] >> 24)];
- result.s[3] = round_key.s[3] ^ //
- te0[uint8_t(state.s[3])] ^ //
- te1[uint8_t(state.s[2] >> 8)] ^ //
- te2[uint8_t(state.s[1] >> 16)] ^ //
- te3[uint8_t(state.s[0] >> 24)];
-#endif
+ 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;
+ // clang-format on
}
-using ::absl::random_internal::RandenTraits;
+// RANDen = RANDom generator or beetroots in Swiss 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.
+
+// Randen constants.
+constexpr size_t kFeistelBlocks = 16;
+constexpr size_t kFeistelFunctions = kFeistelBlocks / 2; // = 8
+constexpr size_t kFeistelRounds = 16 + 1; // > 4 * log2(kFeistelBlocks)
+constexpr size_t kKeys = kFeistelRounds * kFeistelFunctions;
+
+// INCLUDE keys.
+#include "absl/random/internal/randen-keys.inc"
+
+static_assert(kKeys == kRoundKeys, "kKeys and kRoundKeys must be equal");
+
+// 2 uint64_t lanes per Vector128
+static constexpr size_t kLanes = 2;
// The improved Feistel block shuffle function for 16 blocks.
inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
- absl::uint128* state) {
- static_assert(RandenTraits::kFeistelBlocks == 16,
+ uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state_u64) {
+ static_assert(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};
+ constexpr size_t shuffle[kFeistelBlocks] = {7, 2, 13, 4, 11, 8, 3, 6,
+ 15, 0, 9, 10, 1, 14, 5, 12};
+
+ u64x2* ABSL_RANDOM_INTERNAL_RESTRICT state =
+ reinterpret_cast<u64x2*>(state_u64);
// The fully unrolled loop without the memcpy improves the speed by about
- // 30% over the equivalent:
-#if 0
- absl::uint128 source[RandenTraits::kFeistelBlocks];
- std::memcpy(source, state, sizeof(source));
- for (size_t i = 0; i < RandenTraits::kFeistelBlocks; i++) {
- const absl::uint128 v0 = source[shuffle[i]];
- state[i] = v0;
+ // 30% over the equivalent (leaving code here as a comment):
+ if (false) {
+ u64x2 source[kFeistelBlocks];
+ std::memcpy(source, state, sizeof(source));
+ for (size_t i = 0; i < kFeistelBlocks; i++) {
+ const u64x2 v0 = source[shuffle[i]];
+ state[i] = v0;
+ }
}
- return;
-#endif
- const absl::uint128 v0 = state[shuffle[0]];
- const absl::uint128 v1 = state[shuffle[1]];
- const absl::uint128 v2 = state[shuffle[2]];
- const absl::uint128 v3 = state[shuffle[3]];
- const absl::uint128 v4 = state[shuffle[4]];
- const absl::uint128 v5 = state[shuffle[5]];
- const absl::uint128 v6 = state[shuffle[6]];
- const absl::uint128 v7 = state[shuffle[7]];
- const absl::uint128 w0 = state[shuffle[8]];
- const absl::uint128 w1 = state[shuffle[9]];
- const absl::uint128 w2 = state[shuffle[10]];
- const absl::uint128 w3 = state[shuffle[11]];
- const absl::uint128 w4 = state[shuffle[12]];
- const absl::uint128 w5 = state[shuffle[13]];
- const absl::uint128 w6 = state[shuffle[14]];
- const absl::uint128 w7 = state[shuffle[15]];
+ 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;
@@ -360,24 +423,24 @@ inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void BlockShuffle(
// 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 absl::uint128*
-FeistelRound(absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT state,
- const absl::uint128* 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);
+inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE const u64x2* FeistelRound(
+ uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state,
+ const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
+ for (size_t branch = 0; branch < kFeistelBlocks; branch += 4) {
+ const Vector128 s0 = Vector128Load(state + kLanes * branch);
+ const Vector128 s1 = Vector128Load(state + kLanes * (branch + 1));
const Vector128 f0 = AesRound(s0, Vector128Load(keys));
keys++;
const Vector128 o1 = AesRound(f0, s1);
- Vector128Store(o1, state + branch + 1);
+ Vector128Store(o1, state + kLanes * (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 s2 = Vector128Load(state + kLanes * (branch + 2));
+ const Vector128 s3 = Vector128Load(state + kLanes * (branch + 3));
const Vector128 f2 = AesRound(s2, Vector128Load(keys));
keys++;
const Vector128 o3 = AesRound(f2, s3);
- Vector128Store(o3, state + branch + 3);
+ Vector128Store(o3, state + kLanes * (branch + 3));
}
return keys;
}
@@ -387,31 +450,15 @@ FeistelRound(absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT state,
// 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(
- absl::uint128* state,
- const absl::uint128* ABSL_RANDOM_INTERNAL_RESTRICT keys) {
- for (size_t round = 0; round < RandenTraits::kFeistelRounds; ++round) {
- keys = FeistelRound(state, keys);
+ const void* keys, uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state) {
+ const u64x2* ABSL_RANDOM_INTERNAL_RESTRICT keys128 =
+ static_cast<const u64x2*>(keys);
+ for (size_t round = 0; round < kFeistelRounds; ++round) {
+ keys128 = FeistelRound(state, keys128);
BlockShuffle(state);
}
}
-// Enables native loads in the round loop by pre-swapping.
-inline ABSL_RANDOM_INTERNAL_ATTRIBUTE_ALWAYS_INLINE void SwapEndian(
- absl::uint128* state) {
-#ifdef ABSL_IS_BIG_ENDIAN
- for (uint32_t block = 0; block < RandenTraits::kFeistelBlocks; ++block) {
- uint64_t new_lo = absl::little_endian::ToHost64(
- static_cast<uint64_t>(state[block] >> 64));
- uint64_t new_hi = absl::little_endian::ToHost64(
- static_cast<uint64_t>((state[block] << 64) >> 64));
- state[block] = (static_cast<absl::uint128>(new_hi) << 64) | new_lo;
- }
-#else
- // Avoid warning about unused variable.
- (void)state;
-#endif
-}
-
} // namespace
namespace absl {
@@ -421,49 +468,37 @@ 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.
-#ifdef ABSL_IS_LITTLE_ENDIAN
- return kRandenRoundKeys;
-#else
- return kRandenRoundKeysBE;
-#endif
+ return round_keys;
}
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) {
+ uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
+ reinterpret_cast<uint64_t*>(state_void);
+ const uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT seed =
+ reinterpret_cast<const uint64_t*>(seed_void);
+
+ constexpr size_t kCapacityBlocks = kCapacityBytes / sizeof(uint64_t);
+ static_assert(kCapacityBlocks * sizeof(uint64_t) == kCapacityBytes,
+ "Not i*V");
+ for (size_t i = kCapacityBlocks; i < 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(absl::uint128),
- "Capacity mismatch");
-
- auto* state = reinterpret_cast<absl::uint128*>(state_void);
- const auto* keys = reinterpret_cast<const absl::uint128*>(keys_void);
-
- const absl::uint128 prev_inner = state[0];
+void RandenSlow::Generate(const void* keys, void* state_void) {
+ static_assert(kCapacityBytes == sizeof(Vector128), "Capacity mismatch");
- SwapEndian(state);
+ uint64_t* ABSL_RANDOM_INTERNAL_RESTRICT state =
+ reinterpret_cast<uint64_t*>(state_void);
- Permute(state, keys);
+ const Vector128 prev_inner = Vector128Load(state);
- SwapEndian(state);
+ Permute(keys, state);
// Ensure backtracking resistance.
- *state ^= prev_inner;
+ Vector128 inner = Vector128Load(state);
+ inner ^= prev_inner;
+ Vector128Store(inner, state);
}
} // namespace random_internal
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_slow.h b/third_party/abseil-cpp/absl/random/internal/randen_slow.h
index 532c3a8991..72f92b54ad 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_slow.h
+++ b/third_party/abseil-cpp/absl/random/internal/randen_slow.h
@@ -23,11 +23,18 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
-// RANDen = RANDom generator or beetroots in Swiss High German.
+// RANDen = RANDom generator or beetroots in Swiss German.
// RandenSlow implements the basic state manipulation methods for
// architectures lacking AES hardware acceleration intrinsics.
class RandenSlow {
public:
+ // 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
+
static void Generate(const void* keys, void* state_void);
static void Absorb(const void* seed_void, void* state_void);
static const void* GetKeys();
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_slow_test.cc b/third_party/abseil-cpp/absl/random/internal/randen_slow_test.cc
index ed6039586c..c07155d8dd 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_slow_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_slow_test.cc
@@ -17,45 +17,45 @@
#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 =
+ RandenSlow::kStateBytes - RandenSlow::kCapacityBytes;
+constexpr size_t kStateSizeT = RandenSlow::kStateBytes / sizeof(uint64_t);
+constexpr size_t kSeedSizeT = kSeedBytes / sizeof(uint32_t);
+
+struct randen {
+ uint64_t state[kStateSizeT];
+ uint32_t seed[kSeedSizeT];
+};
TEST(RandenSlowTest, Default) {
- constexpr uint8_t kGolden[] = {
- 0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,
- 0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,
- 0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,
- 0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,
- 0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,
- 0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,
- 0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,
- 0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,
- 0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,
- 0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,
- 0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,
- 0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,
- 0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,
- 0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,
- 0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,
- 0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,
- 0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,
- 0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,
- 0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,
- 0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,
- 0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,
- 0x82, 0xf0, 0x1e, 0x81,
+ 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) uint8_t state[RandenTraits::kStateBytes];
- std::memset(state, 0, sizeof(state));
+ alignas(16) randen d;
+ std::memset(d.state, 0, sizeof(d.state));
+ RandenSlow::Generate(RandenSlow::GetKeys(), d.state);
- RandenSlow::Generate(RandenSlow::GetKeys(), state);
- EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(state)));
+ uint64_t* id = d.state;
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, *id++);
+ }
}
} // namespace
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_test.cc b/third_party/abseil-cpp/absl/random/internal/randen_test.cc
index 92773b8d9a..c186fe0d68 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/randen_test.cc
@@ -23,6 +23,9 @@ 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");
@@ -38,38 +41,30 @@ TEST(RandenTest, CopyAndMove) {
}
TEST(RandenTest, Default) {
- constexpr uint8_t kGolden[] = {
- 0xee, 0xd3, 0xe6, 0x0e, 0x09, 0x34, 0x65, 0x6c, 0xc6, 0x33, 0x53, 0x9d,
- 0x9b, 0x2b, 0x4e, 0x04, 0x77, 0x39, 0x43, 0x4e, 0x13, 0x4f, 0xc1, 0xc3,
- 0xee, 0x10, 0x04, 0xd9, 0x7c, 0xf4, 0xa9, 0xdd, 0x10, 0xca, 0xd8, 0x7f,
- 0x08, 0xf3, 0x7b, 0x88, 0x12, 0x29, 0xc7, 0x45, 0xf5, 0x80, 0xb7, 0xf0,
- 0x9f, 0x59, 0x96, 0x76, 0xd3, 0xb1, 0xdb, 0x15, 0x59, 0x6d, 0x3c, 0xff,
- 0xba, 0x63, 0xec, 0x30, 0xa6, 0x20, 0x7f, 0x6f, 0x60, 0x73, 0x9f, 0xb2,
- 0x4c, 0xa5, 0x49, 0x6f, 0x31, 0x8a, 0x80, 0x02, 0x0e, 0xe5, 0xc8, 0xd5,
- 0xf9, 0xea, 0x8f, 0x3b, 0x8a, 0xde, 0xd9, 0x3f, 0x5e, 0x60, 0xbf, 0x9c,
- 0xbb, 0x3b, 0x18, 0x78, 0x1a, 0xae, 0x70, 0xc9, 0xd5, 0x1e, 0x30, 0x56,
- 0xd3, 0xff, 0xb2, 0xd8, 0x37, 0x3c, 0xc7, 0x0f, 0xfe, 0x27, 0xb3, 0xf4,
- 0x19, 0x9a, 0x8f, 0xeb, 0x76, 0x8d, 0xfd, 0xcd, 0x9d, 0x0c, 0x42, 0x91,
- 0xeb, 0x06, 0xa5, 0xc3, 0x56, 0x95, 0xff, 0x3e, 0xdd, 0x05, 0xaf, 0xd5,
- 0xa1, 0xc4, 0x83, 0x8f, 0xb7, 0x1b, 0xdb, 0x48, 0x8c, 0xfe, 0x6b, 0x0d,
- 0x0e, 0x92, 0x23, 0x70, 0x42, 0x6d, 0x95, 0x34, 0x58, 0x57, 0xd3, 0x58,
- 0x40, 0xb8, 0x87, 0x6b, 0xc2, 0xf4, 0x1e, 0xed, 0xf3, 0x2d, 0x0b, 0x3e,
- 0xa2, 0x32, 0xef, 0x8e, 0xfc, 0x54, 0x11, 0x43, 0xf3, 0xab, 0x7c, 0x49,
- 0x8b, 0x9a, 0x02, 0x70, 0x05, 0x37, 0x24, 0x4e, 0xea, 0xe5, 0x90, 0xf0,
- 0x49, 0x57, 0x8b, 0xd8, 0x2f, 0x69, 0x70, 0xa9, 0x82, 0xa5, 0x51, 0xc6,
- 0xf5, 0x42, 0x63, 0xbb, 0x2c, 0xec, 0xfc, 0x78, 0xdb, 0x55, 0x2f, 0x61,
- 0x45, 0xb7, 0x3c, 0x46, 0xe3, 0xaf, 0x16, 0x18, 0xad, 0xe4, 0x2e, 0x35,
- 0x7e, 0xda, 0x01, 0xc1, 0x74, 0xf3, 0x6f, 0x02, 0x51, 0xe8, 0x3d, 0x1c,
- 0x82, 0xf0, 0x1e, 0x81,
+ 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) uint8_t state[Randen::kStateBytes];
+ alignas(16) uint64_t state[kStateSizeT];
std::memset(state, 0, sizeof(state));
Randen r;
r.Generate(state);
- EXPECT_EQ(0, std::memcmp(state, kGolden, sizeof(state)));
+ auto id = std::begin(state);
+ for (const auto& elem : kGolden) {
+ EXPECT_EQ(elem, *id++);
+ }
}
} // namespace
diff --git a/third_party/abseil-cpp/absl/random/internal/randen_traits.h b/third_party/abseil-cpp/absl/random/internal/randen_traits.h
index 120022c9fb..2b8bbe7383 100644
--- a/third_party/abseil-cpp/absl/random/internal/randen_traits.h
+++ b/third_party/abseil-cpp/absl/random/internal/randen_traits.h
@@ -28,29 +28,10 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
-// RANDen = RANDom generator or beetroots in Swiss High German.
+// RANDen = RANDom generator or beetroots in Swiss 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 {
@@ -64,23 +45,17 @@ struct RandenTraits {
// 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;
+ // Type-2 generalized Feistel => one round function for every two blocks.
+ static constexpr size_t kFeistelFunctions = kFeistelBlocks / 2; // = 8
+
// 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
diff --git a/third_party/abseil-cpp/absl/random/internal/seed_material.cc b/third_party/abseil-cpp/absl/random/internal/seed_material.cc
index c03cad8502..4d38a57419 100644
--- a/third_party/abseil-cpp/absl/random/internal/seed_material.cc
+++ b/third_party/abseil-cpp/absl/random/internal/seed_material.cc
@@ -28,7 +28,6 @@
#include <cstdlib>
#include <cstring>
-#include "absl/base/dynamic_annotations.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
@@ -51,18 +50,6 @@
#endif
-#if defined(__GLIBC__) && \
- (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
-// glibc >= 2.25 has getentropy()
-#define ABSL_RANDOM_USE_GET_ENTROPY 1
-#endif
-
-#if defined(__EMSCRIPTEN__)
-#include <sys/random.h>
-// Emscripten has getentropy, but it resides in a different header.
-#define ABSL_RANDOM_USE_GET_ENTROPY 1
-#endif
-
#if defined(ABSL_RANDOM_USE_BCRYPT)
#include <bcrypt.h>
@@ -135,32 +122,8 @@ bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
#else
-#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
-// On *nix, use getentropy() if supported. Note that libc may support
-// getentropy(), but the kernel may not, in which case this function will return
-// false.
-bool ReadSeedMaterialFromGetEntropy(absl::Span<uint32_t> values) {
- auto buffer = reinterpret_cast<uint8_t*>(values.data());
- size_t buffer_size = sizeof(uint32_t) * values.size();
- while (buffer_size > 0) {
- // getentropy() has a maximum permitted length of 256.
- size_t to_read = std::min<size_t>(buffer_size, 256);
- int result = getentropy(buffer, to_read);
- if (result < 0) {
- return false;
- }
- // https://github.com/google/sanitizers/issues/1173
- // MemorySanitizer can't see through getentropy().
- ABSL_ANNOTATE_MEMORY_IS_INITIALIZED(buffer, to_read);
- buffer += to_read;
- buffer_size -= to_read;
- }
- return true;
-}
-#endif // defined(ABSL_RANDOM_GETENTROPY)
-
// On *nix, read entropy from /dev/urandom.
-bool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {
+bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
const char kEntropyFile[] = "/dev/urandom";
auto buffer = reinterpret_cast<uint8_t*>(values.data());
@@ -187,17 +150,6 @@ bool ReadSeedMaterialFromDevURandom(absl::Span<uint32_t> values) {
return success;
}
-bool ReadSeedMaterialFromOSEntropyImpl(absl::Span<uint32_t> values) {
-#if defined(ABSL_RANDOM_USE_GET_ENTROPY)
- if (ReadSeedMaterialFromGetEntropy(values)) {
- return true;
- }
-#endif
- // Libc may support getentropy, but the kernel may not, so we still have
- // to fallback to ReadSeedMaterialFromDevURandom().
- return ReadSeedMaterialFromDevURandom(values);
-}
-
#endif
} // namespace
diff --git a/third_party/abseil-cpp/absl/random/internal/uniform_helper.h b/third_party/abseil-cpp/absl/random/internal/uniform_helper.h
index 1243bc1c62..663107cb3a 100644
--- a/third_party/abseil-cpp/absl/random/internal/uniform_helper.h
+++ b/third_party/abseil-cpp/absl/random/internal/uniform_helper.h
@@ -19,13 +19,10 @@
#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;
@@ -61,26 +58,6 @@ 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
@@ -105,7 +82,7 @@ typename absl::enable_if_t<
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
IntType>
uniform_lower_bound(Tag, IntType a, IntType) {
- return a < (std::numeric_limits<IntType>::max)() ? (a + 1) : a;
+ return a + 1;
}
template <typename FloatType, typename Tag>
@@ -136,7 +113,7 @@ typename absl::enable_if_t<
std::is_same<Tag, IntervalOpenOpenTag>>>::value,
IntType>
uniform_upper_bound(Tag, IntType, IntType b) {
- return b > (std::numeric_limits<IntType>::min)() ? (b - 1) : b;
+ return b - 1;
}
template <typename FloatType, typename Tag>
@@ -172,53 +149,12 @@ 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>
diff --git a/third_party/abseil-cpp/absl/random/internal/uniform_helper_test.cc b/third_party/abseil-cpp/absl/random/internal/uniform_helper_test.cc
deleted file mode 100644
index 173c49b0b7..0000000000
--- a/third_party/abseil-cpp/absl/random/internal/uniform_helper_test.cc
+++ /dev/null
@@ -1,279 +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
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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/third_party/abseil-cpp/absl/random/internal/wide_multiply.h b/third_party/abseil-cpp/absl/random/internal/wide_multiply.h
index b6e6c4b6aa..6e4cf1be0a 100644
--- a/third_party/abseil-cpp/absl/random/internal/wide_multiply.h
+++ b/third_party/abseil-cpp/absl/random/internal/wide_multiply.h
@@ -26,7 +26,7 @@
#endif
#include "absl/base/config.h"
-#include "absl/numeric/bits.h"
+#include "absl/base/internal/bits.h"
#include "absl/numeric/int128.h"
#include "absl/random/internal/traits.h"
@@ -38,9 +38,9 @@ namespace random_internal {
// 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) {
+inline uint128 MultiplyU64ToU128(uint64_t a, uint64_t b) {
#if defined(ABSL_HAVE_INTRINSIC_INT128)
- return absl::uint128(static_cast<__uint128_t>(a) * b);
+ return 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;
@@ -93,14 +93,14 @@ struct wide_multiply {
template <>
struct wide_multiply<uint64_t> {
using input_type = uint64_t;
- using result_type = absl::uint128;
+ using result_type = 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); }
+ static uint64_t hi(result_type r) { return Uint128High64(r); }
+ static uint64_t lo(result_type r) { return Uint128Low64(r); }
};
#endif
diff --git a/third_party/abseil-cpp/absl/random/internal/wide_multiply_test.cc b/third_party/abseil-cpp/absl/random/internal/wide_multiply_test.cc
index e276cb51cf..922603f226 100644
--- a/third_party/abseil-cpp/absl/random/internal/wide_multiply_test.cc
+++ b/third_party/abseil-cpp/absl/random/internal/wide_multiply_test.cc
@@ -15,6 +15,7 @@
#include "absl/random/internal/wide_multiply.h"
#include "gtest/gtest.h"
+#include "absl/base/internal/bits.h"
#include "absl/numeric/int128.h"
using absl::random_internal::MultiplyU64ToU128;
@@ -27,7 +28,7 @@ TEST(WideMultiplyTest, MultiplyU64ToU128Test) {
EXPECT_EQ(absl::uint128(0), MultiplyU64ToU128(0, 0));
- // Max uint64_t
+ // Max uint64
EXPECT_EQ(MultiplyU64ToU128(kMax, kMax),
absl::MakeUint128(0xfffffffffffffffe, 0x0000000000000001));
EXPECT_EQ(absl::MakeUint128(0, kMax), MultiplyU64ToU128(kMax, 1));
diff --git a/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h b/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h
index 43e101169c..960816e2f8 100644
--- a/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h
+++ b/third_party/abseil-cpp/absl/random/log_uniform_int_distribution.h
@@ -23,7 +23,6 @@
#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"
@@ -69,10 +68,8 @@ class log_uniform_int_distribution {
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));
+ log_range_ = (std::min)(random_internal::LeadingSetBit(range()),
+ std::numeric_limits<unsigned_type>::digits);
} else {
// NOTE: Computing the logN(x) introduces error from 2 sources:
// 1. Conversion of int to double loses precision for values >=
diff --git a/third_party/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc b/third_party/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc
index 5e780d96d3..5270531d20 100644
--- a/third_party/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/log_uniform_int_distribution_test.cc
@@ -27,7 +27,6 @@
#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"
@@ -122,10 +121,7 @@ class LogUniformIntChiSquaredTest
// 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};
+ absl::InsecureBitGen rng_;
};
double LogUniformIntChiSquaredTest::ChiSquaredTestImpl() {
@@ -198,6 +194,7 @@ double LogUniformIntChiSquaredTest::ChiSquaredTestImpl() {
TEST_P(LogUniformIntChiSquaredTest, MultiTest) {
const int kTrials = 5;
+
int failures = 0;
for (int i = 0; i < kTrials; i++) {
double p_value = ChiSquaredTestImpl();
diff --git a/third_party/abseil-cpp/absl/random/mock_distributions.h b/third_party/abseil-cpp/absl/random/mock_distributions.h
index 764ab370ab..d36d5ba03c 100644
--- a/third_party/abseil-cpp/absl/random/mock_distributions.h
+++ b/third_party/abseil-cpp/absl/random/mock_distributions.h
@@ -27,11 +27,6 @@
// 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;
diff --git a/third_party/abseil-cpp/absl/flags/internal/commandlineflag.cc b/third_party/abseil-cpp/absl/random/mocking_bit_gen.cc
index 4482955c4c..6bb1e414ae 100644
--- a/third_party/abseil-cpp/absl/flags/internal/commandlineflag.cc
+++ b/third_party/abseil-cpp/absl/random/mocking_bit_gen.cc
@@ -1,5 +1,5 @@
//
-// Copyright 2020 The Abseil Authors.
+// 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.
@@ -12,15 +12,19 @@
// WITHOUT 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 "absl/flags/internal/commandlineflag.h"
+#include <string>
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace flags_internal {
+MockingBitGen::~MockingBitGen() {
-FlagStateInterface::~FlagStateInterface() {}
+ for (const auto& del : deleters_) {
+ del();
+ }
+}
-} // namespace flags_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/random/mocking_bit_gen.h b/third_party/abseil-cpp/absl/random/mocking_bit_gen.h
index 7b2b80eb35..36cef91113 100644
--- a/third_party/abseil-cpp/absl/random/mocking_bit_gen.h
+++ b/third_party/abseil-cpp/absl/random/mocking_bit_gen.h
@@ -33,16 +33,17 @@
#include <memory>
#include <tuple>
#include <type_traits>
+#include <typeindex>
+#include <typeinfo>
#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/random/internal/mocking_bit_gen_base.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/types/span.h"
@@ -53,12 +54,11 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
+
+template <typename, typename>
+struct MockSingleOverload;
} // namespace random_internal
-class BitGenRef;
// MockingBitGen
//
@@ -96,144 +96,100 @@ class BitGenRef;
// 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 {
+class MockingBitGen : public absl::random_internal::MockingBitGenBase {
public:
- MockingBitGen() = default;
- ~MockingBitGen() = default;
+ MockingBitGen() {}
- // 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_(); }
+ ~MockingBitGen() override;
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 DistrT, typename... Args>
+ using MockFnType =
+ ::testing::MockFunction<typename DistrT::result_type(Args...)>;
- 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
+ // MockingBitGen::Register
//
- // 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.
+ // Register<DistrT, FormatT, ArgTupleT> is the main extension point for
+ // extending the MockingBitGen framework. It provides a mechanism to install a
+ // mock expectation for the distribution `distr_t` onto the MockingBitGen
+ // context.
//
// 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>();
+ template <typename DistrT, typename... Args, typename... Ms>
+ decltype(std::declval<MockFnType<DistrT, Args...>>().gmock_Call(
+ std::declval<Ms>()...))
+ Register(Ms&&... matchers) {
+ auto& mock =
+ mocks_[std::type_index(GetTypeId<DistrT, std::tuple<Args...>>())];
+
+ if (!mock.mock_fn) {
+ auto* mock_fn = new MockFnType<DistrT, Args...>;
+ mock.mock_fn = mock_fn;
+ mock.match_impl = &MatchImpl<DistrT, Args...>;
+ deleters_.emplace_back([mock_fn] { delete mock_fn; });
}
- return static_cast<ImplT*>(mock.get())->mock_fn_;
+
+ return static_cast<MockFnType<DistrT, Args...>*>(mock.mock_fn)
+ ->gmock_Call(std::forward<Ms>(matchers)...);
}
- // 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) {
+ mutable std::vector<std::function<void()>> deleters_;
+
+ using match_impl_fn = void (*)(void* mock_fn, void* t_erased_dist_args,
+ void* t_erased_result);
+ struct MockData {
+ void* mock_fn = nullptr;
+ match_impl_fn match_impl = nullptr;
+ };
+
+ mutable absl::flat_hash_map<std::type_index, MockData> mocks_;
+
+ template <typename DistrT, typename... Args>
+ static void MatchImpl(void* mock_fn, void* dist_args, void* result) {
+ using result_type = typename DistrT::result_type;
+ *static_cast<result_type*>(result) = absl::apply(
+ [mock_fn](Args... args) -> result_type {
+ return (*static_cast<MockFnType<DistrT, Args...>*>(mock_fn))
+ .Call(std::move(args)...);
+ },
+ *static_cast<std::tuple<Args...>*>(dist_args));
+ }
+
+ // Looks for an appropriate mock - Returns the mocked result if one is found.
+ // Otherwise, returns a random value generated by the underlying URBG.
+ bool CallImpl(const std::type_info& key_type, void* dist_args,
+ void* result) override {
// Trigger a mock, if there exists one that matches `param`.
- auto it = mocks_.find(type);
+ auto it = mocks_.find(std::type_index(key_type));
if (it == mocks_.end()) return false;
- it->second->Apply(args_tuple, result);
+ auto* mock_data = static_cast<MockData*>(&it->second);
+ mock_data->match_impl(mock_data->mock_fn, dist_args, result);
return true;
}
- absl::flat_hash_map<base_internal::FastTypeIdType,
- std::unique_ptr<FunctionHolder>>
- mocks_;
- absl::BitGen gen_;
+ template <typename, typename>
+ friend struct ::absl::random_internal::MockSingleOverload;
+ friend struct ::absl::random_internal::DistributionCaller<
+ absl::MockingBitGen>;
+};
- 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
+// -----------------------------------------------------------------------------
+// Implementation Details Only Below
+// -----------------------------------------------------------------------------
+
+namespace random_internal {
+
+template <>
+struct DistributionCaller<absl::MockingBitGen> {
+ template <typename DistrT, typename FormatT, typename... Args>
+ static typename DistrT::result_type Call(absl::MockingBitGen* gen,
+ Args&&... args) {
+ return gen->template Call<DistrT, FormatT>(std::forward<Args>(args)...);
+ }
};
+} // namespace random_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/random/mocking_bit_gen_test.cc b/third_party/abseil-cpp/absl/random/mocking_bit_gen_test.cc
index c713ceafd2..f0ffc9ac92 100644
--- a/third_party/abseil-cpp/absl/random/mocking_bit_gen_test.cc
+++ b/third_party/abseil-cpp/absl/random/mocking_bit_gen_test.cc
@@ -15,7 +15,6 @@
//
#include "absl/random/mocking_bit_gen.h"
-#include <cmath>
#include <numeric>
#include <random>
@@ -27,8 +26,6 @@
#include "absl/random/random.h"
namespace {
-
-using ::testing::_;
using ::testing::Ne;
using ::testing::Return;
@@ -329,9 +326,8 @@ TEST(BasicMocking, WillByDefaultWithArgs) {
absl::MockingBitGen gen;
ON_CALL(absl::MockPoisson<int>(), Call(gen, _))
- .WillByDefault([](double lambda) {
- return static_cast<int>(std::rint(lambda * 10));
- });
+ .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);
}
@@ -348,47 +344,4 @@ TEST(MockingBitGen, InSequenceSucceedsInOrder) {
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/third_party/abseil-cpp/absl/random/poisson_distribution_test.cc b/third_party/abseil-cpp/absl/random/poisson_distribution_test.cc
index 8baabd1118..9d215fbc70 100644
--- a/third_party/abseil-cpp/absl/random/poisson_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/poisson_distribution_test.cc
@@ -30,7 +30,6 @@
#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"
@@ -258,10 +257,7 @@ class PoissonDistributionZTest : public testing::TestWithParam<ZParam>,
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};
+ absl::InsecureBitGen rng_;
};
template <typename D>
@@ -361,13 +357,9 @@ class PoissonDistributionChiSquaredTest : public testing::TestWithParam<double>,
private:
void InitChiSquaredTest(const double buckets);
+ absl::InsecureBitGen rng_;
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(
diff --git a/third_party/abseil-cpp/absl/random/random.h b/third_party/abseil-cpp/absl/random/random.h
index 71b6309288..c8f326e642 100644
--- a/third_party/abseil-cpp/absl/random/random.h
+++ b/third_party/abseil-cpp/absl/random/random.h
@@ -109,7 +109,7 @@ ABSL_NAMESPACE_BEGIN
// absl::BitGen::max()
//
-// Returns the largest possible value from this bit generator.
+// Returns the largest possible value from this bit generator., and
// absl::BitGen::discard(num)
//
diff --git a/third_party/abseil-cpp/absl/random/seed_sequences_test.cc b/third_party/abseil-cpp/absl/random/seed_sequences_test.cc
index fe1100bda0..2cc8b0e6f2 100644
--- a/third_party/abseil-cpp/absl/random/seed_sequences_test.cc
+++ b/third_party/abseil-cpp/absl/random/seed_sequences_test.cc
@@ -96,6 +96,7 @@ template <typename URBG>
void TestReproducibleVariateSequencesForNonsecureURBG() {
const size_t kNumVariates = 1000;
+ // Master RNG instance.
URBG rng;
// Reused for both RNG instances.
auto reusable_seed = absl::CreateSeedSeqFrom(&rng);
diff --git a/third_party/abseil-cpp/absl/random/uniform_int_distribution.h b/third_party/abseil-cpp/absl/random/uniform_int_distribution.h
index c1f54ccebc..da66564a6b 100644
--- a/third_party/abseil-cpp/absl/random/uniform_int_distribution.h
+++ b/third_party/abseil-cpp/absl/random/uniform_int_distribution.h
@@ -196,7 +196,7 @@ 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;
+ random_internal::FastUniformBits<unsigned_type> fast_bits;
unsigned_type bits = fast_bits(g);
const unsigned_type Lim = R + 1;
if ((R & Lim) == 0) {
diff --git a/third_party/abseil-cpp/absl/random/uniform_int_distribution_test.cc b/third_party/abseil-cpp/absl/random/uniform_int_distribution_test.cc
index 276d72ad20..aacff88d38 100644
--- a/third_party/abseil-cpp/absl/random/uniform_int_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/uniform_int_distribution_test.cc
@@ -26,7 +26,6 @@
#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"
@@ -124,7 +123,7 @@ TYPED_TEST(UniformIntDistributionTest, ViolatesPreconditionsDeathTest) {
absl::uniform_int_distribution<TypeParam> dist(10, 1);
auto x = dist(gen);
- // Any value will generate a non-empty string.
+ // Any value will generate a non-empty std::string.
EXPECT_FALSE(absl::StrCat(+x).empty()) << x;
#endif // NDEBUG
}
@@ -135,11 +134,7 @@ TYPED_TEST(UniformIntDistributionTest, TestMoments) {
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};
-
+ absl::InsecureBitGen rng;
std::vector<double> values(kSize);
for (const auto& param :
{param_type(0, Limits::max()), param_type(13, 127)}) {
@@ -183,11 +178,7 @@ TYPED_TEST(UniformIntDistributionTest, ChiSquaredTest50) {
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::InsecureBitGen rng;
absl::uniform_int_distribution<TypeParam> dist(min, max);
std::vector<int32_t> counts(kBuckets + 1, 0);
diff --git a/third_party/abseil-cpp/absl/random/uniform_real_distribution_test.cc b/third_party/abseil-cpp/absl/random/uniform_real_distribution_test.cc
index 035bd284d1..a56374a65b 100644
--- a/third_party/abseil-cpp/absl/random/uniform_real_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/uniform_real_distribution_test.cc
@@ -14,23 +14,19 @@
#include "absl/random/uniform_real_distribution.h"
-#include <cfloat>
#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"
@@ -58,27 +54,15 @@ 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;
+#if defined(__EMSCRIPTEN__)
+using RealTypes = ::testing::Types<float, double>;
+#else
+using RealTypes = ::testing::Types<float, double, long double>;
+#endif // defined(__EMSCRIPTEN__)
TYPED_TEST_SUITE(UniformRealDistributionTest, RealTypes);
TYPED_TEST(UniformRealDistributionTest, ParamSerializeTest) {
-#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
- // We're using an x87-compatible FPU, and intermediate operations are
- // performed with 80-bit floats. This produces slightly different results from
- // what we expect below.
- GTEST_SKIP()
- << "Skipping the test because we detected x87 floating-point semantics";
-#endif
-
using param_type =
typename absl::uniform_real_distribution<TypeParam>::param_type;
@@ -223,11 +207,7 @@ 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::InsecureBitGen rng;
absl::uniform_real_distribution<TypeParam> dist;
for (int i = 0; i < kSize; i++) {
values[i] = dist(rng);
@@ -257,11 +237,7 @@ TYPED_TEST(UniformRealDistributionTest, ChiSquaredTest50) {
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};
-
+ absl::InsecureBitGen rng;
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();
diff --git a/third_party/abseil-cpp/absl/random/zipf_distribution_test.cc b/third_party/abseil-cpp/absl/random/zipf_distribution_test.cc
index f8cf70e0dd..4d4a0fcf79 100644
--- a/third_party/abseil-cpp/absl/random/zipf_distribution_test.cc
+++ b/third_party/abseil-cpp/absl/random/zipf_distribution_test.cc
@@ -27,7 +27,6 @@
#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"
@@ -214,10 +213,7 @@ class ZipfTest : public testing::TestWithParam<zipf_u64::param_type>,
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};
+ absl::InsecureBitGen rng_;
};
TEST_P(ZipfTest, ChiSquaredTest) {
diff --git a/third_party/abseil-cpp/absl/status/BUILD.bazel b/third_party/abseil-cpp/absl/status/BUILD.bazel
index bae5156f4a..2b83077def 100644
--- a/third_party/abseil-cpp/absl/status/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/status/BUILD.bazel
@@ -17,6 +17,7 @@
# 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",
@@ -25,12 +26,11 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "status",
srcs = [
- "internal/status_internal.h",
"status.cc",
"status_payload_printer.cc",
],
@@ -40,14 +40,12 @@ cc_library(
],
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/functional:function_ref",
"//absl/strings",
"//absl/strings:cord",
"//absl/strings:str_format",
@@ -65,41 +63,3 @@ cc_test(
"@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",
- "//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/strings",
- "//absl/types:any",
- "//absl/utility",
- "@com_google_googletest//:gtest_main",
- ],
-)
diff --git a/third_party/abseil-cpp/absl/status/CMakeLists.txt b/third_party/abseil-cpp/absl/status/CMakeLists.txt
index f107c85b1c..f05cee5e95 100644
--- a/third_party/abseil-cpp/absl/status/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/status/CMakeLists.txt
@@ -19,17 +19,14 @@ absl_cc_library(
HDRS
"status.h"
SRCS
- "internal/status_internal.h"
"status.cc"
"status_payload_printer.h"
"status_payload_printer.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::atomic_hook
absl::config
absl::core_headers
- absl::function_ref
absl::raw_logging_internal
absl::inlined_vector
absl::stacktrace
@@ -51,40 +48,5 @@ absl_cc_test(
DEPS
absl::status
absl::strings
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- statusor
- HDRS
- "statusor.h"
- SRCS
- "statusor.cc"
- "internal/statusor_internal.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base
- absl::status
- absl::core_headers
- absl::raw_logging_internal
- absl::type_traits
- absl::strings
- absl::utility
- absl::variant
- PUBLIC
-)
-
-absl_cc_test(
- NAME
- statusor_test
- SRCS
- "statusor_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::status
- absl::statusor
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/status/internal/status_internal.h b/third_party/abseil-cpp/absl/status/internal/status_internal.h
deleted file mode 100644
index ac12940a6d..0000000000
--- a/third_party/abseil-cpp/absl/status/internal/status_internal.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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_arg, absl::string_view message_arg,
- std::unique_ptr<status_internal::Payloads> payloads_arg)
- : ref(int32_t{1}),
- code(code_arg),
- message(message_arg),
- payloads(std::move(payloads_arg)) {}
-
- 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/third_party/abseil-cpp/absl/status/internal/statusor_internal.h b/third_party/abseil-cpp/absl/status/internal/statusor_internal.h
deleted file mode 100644
index eaac2c0b14..0000000000
--- a/third_party/abseil-cpp/absl/status/internal/statusor_internal.h
+++ /dev/null
@@ -1,396 +0,0 @@
-// 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/third_party/abseil-cpp/absl/status/status.cc b/third_party/abseil-cpp/absl/status/status.cc
index bcf3413e5f..df3b740f77 100644
--- a/third_party/abseil-cpp/absl/status/status.cc
+++ b/third_party/abseil-cpp/absl/status/status.cc
@@ -27,6 +27,8 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
+// The implementation was intentionally kept same as util::error::Code_Name()
+// to ease the migration.
std::string StatusCodeToString(StatusCode code) {
switch (code) {
case StatusCode::kOk:
@@ -78,7 +80,7 @@ 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) {
+ for (int i = 0; i < payloads->size(); ++i) {
if ((*payloads)[i].type_url == type_url) return i;
}
@@ -161,21 +163,21 @@ bool Status::ErasePayload(absl::string_view type_url) {
}
void Status::ForEachPayload(
- absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
+ 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) {
+ for (int 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.
+ // In debug mode invaldiate the type url to prevent users from relying on
+ // this std::string lifetime.
// NOLINTNEXTLINE intentional extra conversion to force temporary.
visitor(std::string(elem.type_url), elem.payload);
@@ -207,10 +209,20 @@ void Status::UnrefNonInlined(uintptr_t rep) {
}
}
+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;
+ rep->ref.store(1, std::memory_order_relaxed);
+ rep->code = code;
+ rep->message.assign(msg.data(), msg.size());
+ rep->payloads = 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_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
+ rep_ = NewRep(code, msg, nullptr);
}
}
@@ -229,9 +241,8 @@ absl::StatusCode Status::code() const {
void Status::PrepareToModify() {
ABSL_RAW_CHECK(!ok(), "PrepareToModify shouldn't be called on OK status.");
if (IsInlined(rep_)) {
- rep_ = PointerToRep(new status_internal::StatusRep(
- static_cast<absl::StatusCode>(raw_code()), absl::string_view(),
- nullptr));
+ rep_ = NewRep(static_cast<absl::StatusCode>(raw_code()),
+ absl::string_view(), nullptr);
return;
}
@@ -242,9 +253,7 @@ void Status::PrepareToModify() {
if (rep->payloads) {
payloads = absl::make_unique<status_internal::Payloads>(*rep->payloads);
}
- status_internal::StatusRep* const new_rep = new status_internal::StatusRep(
- rep->code, message(), std::move(payloads));
- rep_ = PointerToRep(new_rep);
+ rep_ = NewRep(rep->code, message(), std::move(payloads));
UnrefNonInlined(rep_i);
}
}
@@ -283,32 +292,26 @@ bool Status::EqualsSlow(const absl::Status& a, const absl::Status& b) {
return true;
}
-std::string Status::ToStringSlow(StatusToStringMode mode) const {
+std::string Status::ToStringSlow() 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)),
- "']");
- });
- }
+ 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(StatusToStringMode::kWithEverything);
+ os << x.ToString();
return os;
}
diff --git a/third_party/abseil-cpp/absl/status/status.h b/third_party/abseil-cpp/absl/status/status.h
index 39071e5f4a..9706d4bace 100644
--- a/third_party/abseil-cpp/absl/status/status.h
+++ b/third_party/abseil-cpp/absl/status/status.h
@@ -11,43 +11,6 @@
// WITHOUT 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_
@@ -55,543 +18,168 @@
#include <string>
#include "absl/container/inlined_vector.h"
-#include "absl/functional/function_ref.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 cross 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 as a malformed filename. Note that use
- // of such errors should be narrowly limited to indicate 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 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 that the entity a
- // caller attempted to create (such as a 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 a "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 a 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,
- // Default mode used by ToString. Its exact value might change in the future.
- kDefault = kWithPayload,
+namespace status_internal {
+
+// Container for status payloads.
+struct Payload {
+ std::string type_url;
+ absl::Cord payload;
};
-// 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;
-}
+using Payloads = absl::InlinedVector<Payload, 1>;
-// 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 construct 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
+// Reference-counted representation of Status data.
+struct StatusRep {
+ 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
- // 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()`.
+class ABSL_MUST_USE_RESULT Status final {
+ public:
+ // Creates an OK status with no message or payload.
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.
+ // Create a status in the canonical error space with the specified code and
+ // error message. If `code == util::error::OK`, `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
+ // `msg` must be in UTF-8. The implementation may complain (e.g.,
// 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
-
+ // Move operations.
// 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`.
+ // If `this->ok()`, stores `new_status` into *this. If `!this->ok()`,
+ // preserves the current data. May, in the future, augment the current 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"
+ // Convenient way of keeping track of the first error encountered.
+ // Instead of:
+ // if (overall_status.ok()) overall_status = new_status
+ // Use:
// overall_status.Update(new_status);
//
+ // Style guide exception for rvalue reference granted in CL 153567220.
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.
+ // Returns true if the Status is OK.
ABSL_MUST_USE_RESULT bool ok() const;
- // Status::code()
- //
- // Returns the canonical error code of type `absl::StatusCode` of this status.
+ // Returns the (canonical) error code.
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.
+ // Returns the raw (canonical) error code which could be out of the range of
+ // the local `absl::StatusCode` enum. NOTE: This should only be called when
+ // converting to wire format. Use `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
- // `operator<<` or `Status::ToString()` for debug logging.
+ // Returns the error message. Note: prefer ToString() for debug logging.
+ // This message rarely describes the error code. It is not unusual for the
+ // error message to be the empty std::string.
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::kDefault) const;
+ // Returns a combination of the error code name, the message and the payloads.
+ // You can expect the code name and the message to be substrings of the
+ // result, and the payloads to be printed by the registered printer extensions
+ // if they are recognized.
+ // WARNING: Do not depend on the exact format of the result of `ToString()`
+ // which is subject to change.
+ std::string ToString() 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.
+ // Swap the contents of `a` with `b`
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
+ // Payload management APIs
+
+ // Type URL should be unique and follow the naming convention below:
+ // The idea of type URL comes from `google.protobuf.Any`
+ // (https://developers.google.com/protocol-buffers/docs/proto3#any). The
+ // type URL should be globally unique and follow the format of URL
+ // (https://en.wikipedia.org/wiki/URL). The default type URL for a given
+ // protobuf message type is "type.googleapis.com/packagename.messagename". For
+ // other custom wire formats, users should define the format of type URL in a
+ // similar practice so as to minimize the chance of conflict between type
+ // URLs. Users should make sure 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.
+
+ // Gets the payload based for `type_url` key, if it is present.
absl::optional<absl::Cord> GetPayload(absl::string_view type_url) const;
- // Status::SetPayload()
+ // Sets the payload for `type_url` key for a non-ok status, overwriting any
+ // existing payload for `type_url`.
//
- // 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.
+ // NOTE: 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
+ // 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.
+ // Iterates over the stored payloads and calls `visitor(type_key, payload)`
+ // for each one.
//
- // NOTE: The order of calls to `visitor()` is not specified and may change at
+ // 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
+ // NOTE: Any mutation on the same 'Status' object during visitation is
// forbidden and could result in undefined behavior.
void ForEachPayload(
- absl::FunctionRef<void(absl::string_view, const absl::Cord&)> visitor)
+ const std::function<void(absl::string_view, const absl::Cord&)>& visitor)
const;
private:
@@ -613,9 +201,8 @@ class Status final {
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 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.
@@ -644,7 +231,8 @@ class Status final {
static uintptr_t PointerToRep(status_internal::StatusRep* r);
static status_internal::StatusRep* RepToPointer(uintptr_t r);
- std::string ToStringSlow(StatusToStringMode mode) const;
+ // Returns std::string for non-ok Status.
+ std::string ToStringSlow() const;
// Status supports two different representations.
// - When the low bit is off it is an inlined representation.
@@ -657,93 +245,14 @@ class Status final {
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.
+// Returns an OK status, equivalent to a default constructed instance.
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)) {}
@@ -767,11 +276,9 @@ inline Status::Status(Status&& x) noexcept : rep_(x.rep_) {
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);
- }
+ rep_ = x.rep_;
+ x.rep_ = MovedFromRep();
+ Unref(old_rep);
return *this;
}
@@ -808,8 +315,8 @@ 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 std::string Status::ToString() const {
+ return ok() ? "OK" : ToStringSlow();
}
inline void Status::IgnoreError() const {
@@ -871,11 +378,50 @@ inline void Status::Unref(uintptr_t rep) {
inline Status OkStatus() { return Status(); }
+// Each of the functions below creates a Status object with a particular error
+// code and the given message. The error code of the returned status object
+// matches the name of the function.
+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);
+
// 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); }
+// Each of the functions below returns true if the given status matches the
+// error code implied by the function's name.
+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);
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/status/status_payload_printer.cc b/third_party/abseil-cpp/absl/status/status_payload_printer.cc
index a47aea11c2..ad96d76acf 100644
--- a/third_party/abseil-cpp/absl/status/status_payload_printer.cc
+++ b/third_party/abseil-cpp/absl/status/status_payload_printer.cc
@@ -16,21 +16,26 @@
#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;
+namespace {
+// Tried constant initialized global variable but it doesn't work with Lexan
+// (MSVC's `std::atomic` has trouble constant initializing).
+std::atomic<StatusPayloadPrinter>& GetStatusPayloadPrinterStorage() {
+ ABSL_CONST_INIT static std::atomic<StatusPayloadPrinter> instance{nullptr};
+ return instance;
+}
+} // namespace
void SetStatusPayloadPrinter(StatusPayloadPrinter printer) {
- storage.Store(printer);
+ GetStatusPayloadPrinterStorage().store(printer, std::memory_order_relaxed);
}
StatusPayloadPrinter GetStatusPayloadPrinter() {
- return storage.Load();
+ return GetStatusPayloadPrinterStorage().load(std::memory_order_relaxed);
}
} // namespace status_internal
diff --git a/third_party/abseil-cpp/absl/status/status_test.cc b/third_party/abseil-cpp/absl/status/status_test.cc
index 1b038f6d98..ca9488ad22 100644
--- a/third_party/abseil-cpp/absl/status/status_test.cc
+++ b/third_party/abseil-cpp/absl/status/status_test.cc
@@ -36,9 +36,7 @@ TEST(StatusCode, InsertionOperator) {
// its creator, and its classifier.
struct ErrorTest {
absl::StatusCode code;
- using Creator = absl::Status (*)(
- absl::string_view
- );
+ using Creator = absl::Status (*)(absl::string_view);
using Classifier = bool (*)(const absl::Status&);
Creator creator;
Classifier classifier;
@@ -80,9 +78,7 @@ TEST(Status, CreateAndClassify) {
// expected error code and message.
std::string message =
absl::StrCat("error code ", test.code, " test message");
- absl::Status status = test.creator(
- message
- );
+ absl::Status status = test.creator(message);
EXPECT_EQ(test.code, status.code());
EXPECT_EQ(message, status.message());
@@ -284,27 +280,6 @@ TEST(Status, ToString) {
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));
@@ -422,12 +397,6 @@ TEST(Status, MoveAssignment) {
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) {
@@ -485,4 +454,5 @@ TEST(Status, Swap) {
test_swap(no_payload, with_payload);
test_swap(with_payload, no_payload);
}
+
} // namespace
diff --git a/third_party/abseil-cpp/absl/status/statusor.cc b/third_party/abseil-cpp/absl/status/statusor.cc
deleted file mode 100644
index 96642b340f..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// 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/call_once.h"
-#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(const BadStatusOrAccess& other)
- : status_(other.status_) {}
-
-BadStatusOrAccess& BadStatusOrAccess::operator=(
- const BadStatusOrAccess& other) {
- // Ensure assignment is correct regardless of whether this->InitWhat() has
- // already been called.
- other.InitWhat();
- status_ = other.status_;
- what_ = other.what_;
- return *this;
-}
-
-BadStatusOrAccess& BadStatusOrAccess::operator=(BadStatusOrAccess&& other) {
- // Ensure assignment is correct regardless of whether this->InitWhat() has
- // already been called.
- other.InitWhat();
- status_ = std::move(other.status_);
- what_ = std::move(other.what_);
- return *this;
-}
-
-BadStatusOrAccess::BadStatusOrAccess(BadStatusOrAccess&& other)
- : status_(std::move(other.status_)) {}
-
-const char* BadStatusOrAccess::what() const noexcept {
- InitWhat();
- return what_.c_str();
-}
-
-const absl::Status& BadStatusOrAccess::status() const { return status_; }
-
-void BadStatusOrAccess::InitWhat() const {
- absl::call_once(init_what_, [this] {
- what_ = absl::StrCat("Bad StatusOr access: ", status_.ToString());
- });
-}
-
-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/third_party/abseil-cpp/absl/status/statusor.h b/third_party/abseil-cpp/absl/status/statusor.h
deleted file mode 100644
index c051fbb3aa..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor.h
+++ /dev/null
@@ -1,770 +0,0 @@
-// 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/base/call_once.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 = default;
-
- BadStatusOrAccess(const BadStatusOrAccess& other);
- BadStatusOrAccess& operator=(const BadStatusOrAccess& other);
- BadStatusOrAccess(BadStatusOrAccess&& other);
- BadStatusOrAccess& operator=(BadStatusOrAccess&& other);
-
- // BadStatusOrAccess::what()
- //
- // Returns the associated explanatory string of the `absl::StatusOr<T>`
- // object's error code. This function contains information about the failing
- // status, but its exact formatting may change and should not be depended on.
- //
- // 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:
- void InitWhat() const;
-
- absl::Status status_;
- mutable absl::once_flag init_what_;
- mutable std::string what_;
-};
-
-// 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 constructor 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& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T& value() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
- const T&& value() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T&& value() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // 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& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T& operator*() & ABSL_ATTRIBUTE_LIFETIME_BOUND;
- const T&& operator*() const&& ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T&& operator*() && ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // 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 ABSL_ATTRIBUTE_LIFETIME_BOUND;
- T* operator->() ABSL_ATTRIBUTE_LIFETIME_BOUND;
-
- // 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/third_party/abseil-cpp/absl/status/statusor_test.cc b/third_party/abseil-cpp/absl/status/statusor_test.cc
deleted file mode 100644
index 7cae90e185..0000000000
--- a/third_party/abseil-cpp/absl/status/statusor_test.cc
+++ /dev/null
@@ -1,1847 +0,0 @@
-// 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 <string>
-#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/strings/string_view.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::HasSubstr;
-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");
-}
-
-TEST(BadStatusOrAccessTest, CopyConstructionWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{e1};
- EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, CopyAssignmentWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{absl::InternalError("other")};
- e2 = e1;
- EXPECT_THAT(e1.what(), HasSubstr(error.ToString()));
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, MoveConstructionWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{std::move(e1)};
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-TEST(BadStatusOrAccessTest, MoveAssignmentWhatOk) {
- absl::Status error =
- absl::InternalError("some arbitrary message too big for the sso buffer");
- absl::BadStatusOrAccess e1{error};
- absl::BadStatusOrAccess e2{absl::InternalError("other")};
- e2 = std::move(e1);
- EXPECT_THAT(e2.what(), HasSubstr(error.ToString()));
-}
-
-// 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_); \
- EXPECT_THAT(e.what(), HasSubstr(e.status().ToString())); \
- 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/third_party/abseil-cpp/absl/strings/BUILD.bazel b/third_party/abseil-cpp/absl/strings/BUILD.bazel
index 090fc58a2c..b950ec769f 100644
--- a/third_party/abseil-cpp/absl/strings/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/strings/BUILD.bazel
@@ -13,6 +13,7 @@
# 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",
@@ -53,7 +54,6 @@ cc_library(
"ascii.h",
"charconv.h",
"escaping.h",
- "internal/string_constant.h",
"match.h",
"numbers.h",
"str_cat.h",
@@ -68,6 +68,7 @@ cc_library(
deps = [
":internal",
"//absl/base",
+ "//absl/base:bits",
"//absl/base:config",
"//absl/base:core_headers",
"//absl/base:endian",
@@ -75,7 +76,6 @@ cc_library(
"//absl/base:throw_delegate",
"//absl/memory",
"//absl/meta:type_traits",
- "//absl/numeric:bits",
"//absl/numeric:int128",
],
)
@@ -223,19 +223,6 @@ 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,
@@ -266,125 +253,12 @@ cc_test(
cc_library(
name = "cord_internal",
- srcs = [
- "internal/cord_internal.cc",
- "internal/cord_rep_btree.cc",
- "internal/cord_rep_btree_navigator.cc",
- "internal/cord_rep_btree_reader.cc",
- "internal/cord_rep_consume.cc",
- "internal/cord_rep_ring.cc",
- ],
- hdrs = [
- "internal/cord_internal.h",
- "internal/cord_rep_btree.h",
- "internal/cord_rep_btree_navigator.h",
- "internal/cord_rep_btree_reader.h",
- "internal/cord_rep_consume.h",
- "internal/cord_rep_flat.h",
- "internal/cord_rep_ring.h",
- "internal/cord_rep_ring_reader.h",
- ],
+ hdrs = ["internal/cord_internal.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/functional:function_ref",
- "//absl/meta:type_traits",
- "//absl/types:span",
- ],
-)
-
-cc_test(
- name = "cord_internal_test",
- srcs = ["internal/cord_internal_test.cc"],
- copts = ABSL_TEST_COPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":cord_internal",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cord_rep_btree_test",
- size = "medium",
- srcs = ["internal/cord_rep_btree_test.cc"],
- copts = ABSL_TEST_COPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":cord_internal",
- ":cord_rep_test_util",
- ":strings",
- "//absl/base:config",
- "//absl/base:raw_logging_internal",
- "//absl/cleanup",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cord_rep_btree_navigator_test",
- size = "medium",
- srcs = ["internal/cord_rep_btree_navigator_test.cc"],
- copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
- ":cord_internal",
- ":cord_rep_test_util",
":strings",
- "//absl/base:config",
- "//absl/base:raw_logging_internal",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cord_rep_btree_reader_test",
- size = "medium",
- srcs = ["internal/cord_rep_btree_reader_test.cc"],
- copts = ABSL_TEST_COPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":cord",
- ":cord_internal",
- ":cord_rep_test_util",
- ":strings",
- "//absl/base:config",
- "//absl/base:raw_logging_internal",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
- name = "cordz_update_tracker",
- hdrs = ["internal/cordz_update_tracker.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = ["//absl/base:config"],
-)
-
-cc_test(
- name = "cordz_update_tracker_test",
- srcs = ["internal/cordz_update_tracker_test.cc"],
- deps = [
- ":cordz_update_tracker",
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/synchronization",
- "@com_google_googletest//:gtest_main",
+ "//absl/meta:type_traits",
],
)
@@ -399,16 +273,11 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
deps = [
":cord_internal",
- ":cordz_functions",
- ":cordz_info",
- ":cordz_statistics",
- ":cordz_update_scope",
- ":cordz_update_tracker",
":internal",
":str_format",
":strings",
"//absl/base",
- "//absl/base:config",
+ "//absl/base:base_internal",
"//absl/base:core_headers",
"//absl/base:endian",
"//absl/base:raw_logging_internal",
@@ -416,216 +285,6 @@ cc_library(
"//absl/container:inlined_vector",
"//absl/functional:function_ref",
"//absl/meta:type_traits",
- "//absl/types:optional",
- ],
-)
-
-cc_library(
- name = "cordz_handle",
- srcs = ["internal/cordz_handle.cc"],
- hdrs = ["internal/cordz_handle.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- "//absl/base",
- "//absl/base:config",
- "//absl/base:raw_logging_internal",
- "//absl/synchronization",
- ],
-)
-
-cc_library(
- name = "cordz_info",
- srcs = ["internal/cordz_info.cc"],
- hdrs = ["internal/cordz_info.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":cord_internal",
- ":cordz_functions",
- ":cordz_handle",
- ":cordz_statistics",
- ":cordz_update_tracker",
- "//absl/base",
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
- "//absl/container:inlined_vector",
- "//absl/debugging:stacktrace",
- "//absl/synchronization",
- "//absl/types:span",
- ],
-)
-
-cc_library(
- name = "cordz_update_scope",
- hdrs = ["internal/cordz_update_scope.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":cord_internal",
- ":cordz_info",
- ":cordz_update_tracker",
- "//absl/base:config",
- "//absl/base:core_headers",
- ],
-)
-
-cc_test(
- name = "cordz_update_scope_test",
- srcs = ["internal/cordz_update_scope_test.cc"],
- copts = ABSL_DEFAULT_COPTS,
- deps = [
- ":cord_internal",
- ":cordz_info",
- ":cordz_test_helpers",
- ":cordz_update_scope",
- ":cordz_update_tracker",
- "//absl/base:config",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_library(
- name = "cordz_sample_token",
- srcs = ["internal/cordz_sample_token.cc"],
- hdrs = ["internal/cordz_sample_token.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":cordz_handle",
- ":cordz_info",
- "//absl/base:config",
- ],
-)
-
-cc_library(
- name = "cordz_functions",
- srcs = ["internal/cordz_functions.cc"],
- hdrs = ["internal/cordz_functions.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
- "//absl/profiling:exponential_biased",
- ],
-)
-
-cc_library(
- name = "cordz_statistics",
- hdrs = ["internal/cordz_statistics.h"],
- copts = ABSL_DEFAULT_COPTS,
- visibility = [
- "//absl:__subpackages__",
- ],
- deps = [
- ":cordz_update_tracker",
- "//absl/base:config",
- ],
-)
-
-cc_test(
- name = "cordz_functions_test",
- srcs = [
- "internal/cordz_functions_test.cc",
- ],
- deps = [
- ":cordz_functions",
- ":cordz_test_helpers",
- "//absl/base:config",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cordz_handle_test",
- srcs = [
- "internal/cordz_handle_test.cc",
- ],
- deps = [
- ":cordz_handle",
- "//absl/base:config",
- "//absl/memory",
- "//absl/random",
- "//absl/random:distributions",
- "//absl/synchronization",
- "//absl/synchronization:thread_pool",
- "//absl/time",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cordz_info_test",
- srcs = [
- "internal/cordz_info_test.cc",
- ],
- deps = [
- ":cord_internal",
- ":cordz_handle",
- ":cordz_info",
- ":cordz_statistics",
- ":cordz_test_helpers",
- ":cordz_update_tracker",
- ":strings",
- "//absl/base:config",
- "//absl/debugging:stacktrace",
- "//absl/debugging:symbolize",
- "//absl/types:span",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cordz_info_statistics_test",
- srcs = [
- "internal/cordz_info_statistics_test.cc",
- ],
- deps = [
- ":cord",
- ":cord_internal",
- ":cordz_info",
- ":cordz_sample_token",
- ":cordz_statistics",
- ":cordz_update_scope",
- ":cordz_update_tracker",
- "//absl/base:config",
- "//absl/synchronization",
- "//absl/synchronization:thread_pool",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cordz_sample_token_test",
- srcs = [
- "internal/cordz_sample_token_test.cc",
- ],
- deps = [
- ":cord_internal",
- ":cordz_handle",
- ":cordz_info",
- ":cordz_sample_token",
- ":cordz_test_helpers",
- "//absl/base:config",
- "//absl/memory",
- "//absl/random",
- "//absl/synchronization",
- "//absl/synchronization:thread_pool",
- "//absl/time",
- "@com_google_googletest//:gtest_main",
],
)
@@ -638,41 +297,6 @@ cc_library(
copts = ABSL_DEFAULT_COPTS,
deps = [
":cord",
- ":cord_internal",
- ":strings",
- "//absl/base:config",
- ],
-)
-
-cc_library(
- name = "cord_rep_test_util",
- testonly = 1,
- hdrs = ["internal/cord_rep_test_util.h"],
- copts = ABSL_DEFAULT_COPTS,
- deps = [
- ":cord_internal",
- ":strings",
- "//absl/base:config",
- "//absl/base:raw_logging_internal",
- ],
-)
-
-cc_library(
- name = "cordz_test_helpers",
- testonly = 1,
- hdrs = ["cordz_test_helpers.h"],
- copts = ABSL_DEFAULT_COPTS,
- deps = [
- ":cord",
- ":cord_internal",
- ":cordz_info",
- ":cordz_sample_token",
- ":cordz_statistics",
- ":cordz_update_tracker",
- ":strings",
- "//absl/base:config",
- "//absl/base:core_headers",
- "@com_google_googletest//:gtest",
],
)
@@ -685,98 +309,12 @@ cc_test(
deps = [
":cord",
":cord_test_helpers",
- ":cordz_functions",
- ":cordz_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",
- "//absl/random",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cordz_test",
- size = "medium",
- srcs = ["cordz_test.cc"],
- copts = ABSL_TEST_COPTS,
- 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",
- ],
- visibility = ["//visibility:private"],
- deps = [
- ":cord",
- ":cord_test_helpers",
- ":cordz_functions",
- ":cordz_info",
- ":cordz_sample_token",
- ":cordz_statistics",
- ":cordz_test_helpers",
- ":cordz_update_tracker",
- ":strings",
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/base:raw_logging_internal",
- "@com_google_googletest//:gtest_main",
- ],
-)
-
-cc_test(
- name = "cord_rep_consume_test",
- size = "medium",
- srcs = ["internal/cord_rep_consume_test.cc"],
- copts = ABSL_TEST_COPTS,
- visibility = ["//visibility:private"],
- deps = [
- ":cord_internal",
- ":strings",
- "//absl/base:config",
- "//absl/base:core_headers",
- "//absl/debugging:leak_check",
- "@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",
],
)
@@ -828,9 +366,6 @@ cc_test(
":strings",
"//absl/base:core_headers",
"//absl/base:dynamic_annotations",
- "//absl/container:btree",
- "//absl/container:flat_hash_map",
- "//absl/container:node_hash_map",
"@com_google_googletest//:gtest_main",
],
)
@@ -949,7 +484,6 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
- ":internal",
":pow10_helper",
":strings",
"//absl/base:config",
@@ -1100,12 +634,8 @@ cc_library(
":strings",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/functional:function_ref",
"//absl/meta:type_traits",
- "//absl/numeric:bits",
"//absl/numeric:int128",
- "//absl/numeric:representation",
- "//absl/types:optional",
"//absl/types:span",
],
)
@@ -1116,7 +646,6 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
- ":cord",
":str_format",
":strings",
"//absl/base:core_headers",
@@ -1134,7 +663,6 @@ cc_test(
deps = [
":str_format",
":str_format_internal",
- ":strings",
"@com_google_googletest//:gtest_main",
],
)
@@ -1181,9 +709,8 @@ cc_test(
visibility = ["//visibility:private"],
deps = [
":str_format_internal",
- ":strings",
"//absl/base:raw_logging_internal",
- "//absl/types:optional",
+ "//absl/numeric:int128",
"@com_google_googletest//:gtest_main",
],
)
@@ -1194,7 +721,6 @@ cc_test(
copts = ABSL_TEST_COPTS,
visibility = ["//visibility:private"],
deps = [
- ":cord",
":str_format_internal",
"@com_google_googletest//:gtest_main",
],
diff --git a/third_party/abseil-cpp/absl/strings/CMakeLists.txt b/third_party/abseil-cpp/absl/strings/CMakeLists.txt
index d6801fe6fd..fbf0f5ac52 100644
--- a/third_party/abseil-cpp/absl/strings/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/strings/CMakeLists.txt
@@ -21,7 +21,6 @@ absl_cc_library(
"ascii.h"
"charconv.h"
"escaping.h"
- "internal/string_constant.h"
"match.h"
"numbers.h"
"str_cat.h"
@@ -101,7 +100,7 @@ absl_cc_test(
DEPS
absl::strings
absl::base
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -115,7 +114,7 @@ absl_cc_test(
absl::strings
absl::core_headers
absl::fixed_array
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -128,7 +127,7 @@ absl_cc_test(
DEPS
absl::strings
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -142,7 +141,7 @@ absl_cc_test(
DEPS
absl::strings
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -156,20 +155,7 @@ absl_cc_test(
absl::strings_internal
absl::base
absl::core_headers
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- string_constant_test
- SRCS
- "internal/string_constant_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::strings
- absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -184,7 +170,7 @@ absl_cc_test(
absl::config
absl::core_headers
absl::dynamic_annotations
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -197,7 +183,7 @@ absl_cc_test(
DEPS
absl::strings
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -209,7 +195,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -221,12 +207,10 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::strings
+ absl::base
absl::core_headers
absl::dynamic_annotations
- absl::btree
- absl::flat_hash_map
- absl::node_hash_map
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -238,7 +222,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::strings_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -253,7 +237,7 @@ absl_cc_test(
absl::base
absl::core_headers
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -268,7 +252,7 @@ absl_cc_test(
absl::base
absl::core_headers
absl::memory
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -281,7 +265,7 @@ absl_cc_test(
DEPS
absl::strings
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -300,8 +284,7 @@ absl_cc_test(
absl::raw_logging_internal
absl::random_random
absl::random_distributions
- absl::strings_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -314,7 +297,7 @@ absl_cc_test(
DEPS
absl::strings
absl::base
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -326,7 +309,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::strings_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -340,7 +323,7 @@ absl_cc_test(
absl::strings
absl::str_format
absl::pow10_helper
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -355,7 +338,7 @@ absl_cc_test(
absl::strings
absl::config
absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -370,7 +353,7 @@ absl_cc_test(
DEPS
absl::strings
absl::config
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -406,11 +389,9 @@ absl_cc_library(
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
- absl::bits
absl::strings
absl::config
absl::core_headers
- absl::numeric_representation
absl::type_traits
absl::int128
absl::span
@@ -425,10 +406,9 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::str_format
- absl::cord
absl::strings
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -441,8 +421,7 @@ absl_cc_test(
DEPS
absl::str_format
absl::str_format_internal
- absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -455,7 +434,7 @@ absl_cc_test(
DEPS
absl::str_format
absl::str_format_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -467,7 +446,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::str_format_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -479,7 +458,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::str_format
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -490,11 +469,10 @@ absl_cc_test(
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::strings
absl::str_format_internal
absl::raw_logging_internal
absl::int128
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -506,8 +484,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::str_format_internal
- absl::cord
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -520,7 +497,7 @@ absl_cc_test(
DEPS
absl::str_format_internal
absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -547,281 +524,7 @@ absl_cc_test(
DEPS
absl::pow10_helper
absl::str_format
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cord_internal
- HDRS
- "internal/cord_internal.h"
- "internal/cord_rep_btree.h"
- "internal/cord_rep_btree_navigator.h"
- "internal/cord_rep_btree_reader.h"
- "internal/cord_rep_consume.h"
- "internal/cord_rep_flat.h"
- "internal/cord_rep_ring.h"
- "internal/cord_rep_ring_reader.h"
- SRCS
- "internal/cord_internal.cc"
- "internal/cord_rep_btree.cc"
- "internal/cord_rep_btree_navigator.cc"
- "internal/cord_rep_btree_reader.cc"
- "internal/cord_rep_consume.cc"
- "internal/cord_rep_ring.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base_internal
- absl::compressed_tuple
- absl::config
- absl::core_headers
- absl::endian
- absl::inlined_vector
- absl::layout
- absl::raw_logging_internal
- absl::strings
- absl::throw_delegate
- absl::type_traits
-)
-
-absl_cc_library(
- NAME
- cordz_update_tracker
- HDRS
- "internal/cordz_update_tracker.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
-)
-
-absl_cc_test(
- NAME
- cordz_update_tracker_test
- SRCS
- "internal/cordz_update_tracker_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cordz_update_tracker
- absl::core_headers
- absl::synchronization
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cordz_functions
- HDRS
- "internal/cordz_functions.h"
- SRCS
- "internal/cordz_functions.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::core_headers
- absl::exponential_biased
- absl::raw_logging_internal
-)
-
-absl_cc_test(
- NAME
- cordz_functions_test
- SRCS
- "internal/cordz_functions_test.cc"
- DEPS
- absl::config
- absl::cordz_functions
- absl::cordz_test_helpers
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cordz_statistics
- HDRS
- "internal/cordz_statistics.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::core_headers
- absl::cordz_update_tracker
- absl::synchronization
-)
-
-absl_cc_library(
- NAME
- cordz_handle
- HDRS
- "internal/cordz_handle.h"
- SRCS
- "internal/cordz_handle.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base
- absl::config
- absl::raw_logging_internal
- absl::synchronization
-)
-
-absl_cc_test(
- NAME
- cordz_handle_test
- SRCS
- "internal/cordz_handle_test.cc"
- DEPS
- absl::config
- absl::cordz_handle
- absl::cordz_test_helpers
- absl::memory
- absl::random_random
- absl::random_distributions
- absl::synchronization
- absl::time
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cordz_info
- HDRS
- "internal/cordz_info.h"
- SRCS
- "internal/cordz_info.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::base
- absl::config
- absl::cord_internal
- absl::cordz_functions
- absl::cordz_handle
- absl::cordz_statistics
- absl::cordz_update_tracker
- absl::core_headers
- absl::inlined_vector
- absl::span
- absl::raw_logging_internal
- absl::stacktrace
- absl::synchronization
-)
-
-absl_cc_test(
- NAME
- cordz_info_test
- SRCS
- "internal/cordz_info_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cord_internal
- absl::cordz_test_helpers
- absl::cordz_handle
- absl::cordz_info
- absl::cordz_statistics
- absl::cordz_test_helpers
- absl::cordz_update_tracker
- absl::span
- absl::stacktrace
- absl::symbolize
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cordz_info_statistics_test
- SRCS
- "internal/cordz_info_statistics_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cord
- absl::cord_internal
- absl::cordz_info
- absl::cordz_sample_token
- absl::cordz_statistics
- absl::cordz_update_scope
- absl::cordz_update_tracker
- absl::thread_pool
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cordz_sample_token
- HDRS
- "internal/cordz_sample_token.h"
- SRCS
- "internal/cordz_sample_token.cc"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::cordz_handle
- absl::cordz_info
-)
-
-absl_cc_test(
- NAME
- cordz_sample_token_test
- SRCS
- "internal/cordz_sample_token_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cord_internal
- absl::cordz_handle
- absl::cordz_info
- absl::cordz_info
- absl::cordz_sample_token
- absl::cordz_test_helpers
- absl::memory
- absl::random_random
- absl::synchronization
- absl::thread_pool
- absl::time
- GTest::gmock_main
-)
-
-absl_cc_library(
- NAME
- cordz_update_scope
- HDRS
- "internal/cordz_update_scope.h"
- COPTS
- ${ABSL_DEFAULT_COPTS}
- DEPS
- absl::config
- absl::cord_internal
- absl::cordz_info
- absl::cordz_update_tracker
- absl::core_headers
-)
-
-absl_cc_test(
- NAME
- cordz_update_scope_test
- SRCS
- "internal/cordz_update_scope_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cord_internal
- absl::cordz_info
- absl::cordz_test_helpers
- absl::cordz_update_scope
- absl::cordz_update_tracker
- absl::core_headers
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -831,75 +534,33 @@ absl_cc_library(
"cord.h"
SRCS
"cord.cc"
+ "internal/cord_internal.h"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::strings
+ absl::strings_internal
absl::base
- absl::config
- absl::cord_internal
- absl::cordz_functions
- absl::cordz_info
- absl::cordz_update_scope
- absl::cordz_update_tracker
+ absl::base_internal
absl::core_headers
absl::endian
absl::fixed_array
absl::function_ref
absl::inlined_vector
- absl::optional
absl::raw_logging_internal
- absl::strings
absl::type_traits
PUBLIC
)
absl_cc_library(
NAME
- cord_rep_test_util
- HDRS
- "internal/cord_rep_test_util.h"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
- absl::cord_internal
- absl::raw_logging_internal
- absl::strings
- TESTONLY
-)
-
-absl_cc_library(
- NAME
cord_test_helpers
HDRS
"cord_test_helpers.h"
COPTS
${ABSL_TEST_COPTS}
DEPS
- absl::config
- absl::cord
- absl::cord_internal
- absl::strings
- TESTONLY
-)
-
-absl_cc_library(
- NAME
- cordz_test_helpers
- HDRS
- "cordz_test_helpers.h"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::config
absl::cord
- absl::cord_internal
- absl::cordz_info
- absl::cordz_sample_token
- absl::cordz_statistics
- absl::cordz_update_tracker
- absl::core_headers
- absl::strings
TESTONLY
)
@@ -912,157 +573,11 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::cord
- absl::str_format
absl::strings
absl::base
absl::config
- absl::cord_test_helpers
- absl::cordz_test_helpers
- absl::core_headers
absl::endian
- absl::random_random
absl::raw_logging_internal
absl::fixed_array
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_rep_consume_test
- SRCS
- "internal/cord_rep_consume_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::config
- absl::cord_internal
- absl::core_headers
- absl::function_ref
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_internal_test
- SRCS
- "internal/cord_internal_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::cord_internal
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_rep_btree_test
- SRCS
- "internal/cord_rep_btree_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::cleanup
- absl::config
- absl::cord_internal
- absl::cord_rep_test_util
- absl::core_headers
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_rep_btree_navigator_test
- SRCS
- "internal/cord_rep_btree_navigator_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::config
- absl::cord_internal
- absl::cord_rep_test_util
- absl::core_headers
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_rep_btree_reader_test
- SRCS
- "internal/cord_rep_btree_reader_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::config
- absl::cord_internal
- absl::cord_rep_test_util
- absl::core_headers
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_ring_test
- SRCS
- "cord_ring_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::config
- absl::cord_internal
- absl::core_headers
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cord_ring_reader_test
- SRCS
- "cord_ring_reader_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::base
- absl::cord_internal
- absl::core_headers
- absl::strings
- GTest::gmock_main
-)
-
-absl_cc_test(
- NAME
- cordz_test
- SRCS
- "cordz_test.cc"
- COPTS
- ${ABSL_TEST_COPTS}
- DEPS
- absl::cord
- absl::cord_test_helpers
- absl::cordz_test_helpers
- absl::cordz_functions
- absl::cordz_info
- absl::cordz_sample_token
- absl::cordz_statistics
- absl::cordz_update_tracker
- absl::base
- absl::config
- absl::core_headers
- absl::raw_logging_internal
- absl::strings
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/strings/ascii_test.cc b/third_party/abseil-cpp/absl/strings/ascii_test.cc
index 83af7825e1..5ecd23f869 100644
--- a/third_party/abseil-cpp/absl/strings/ascii_test.cc
+++ b/third_party/abseil-cpp/absl/strings/ascii_test.cc
@@ -197,15 +197,11 @@ 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/third_party/abseil-cpp/absl/strings/charconv.cc b/third_party/abseil-cpp/absl/strings/charconv.cc
index fefcfc90a5..bdba768dcd 100644
--- a/third_party/abseil-cpp/absl/strings/charconv.cc
+++ b/third_party/abseil-cpp/absl/strings/charconv.cc
@@ -20,7 +20,7 @@
#include <cstring>
#include "absl/base/casts.h"
-#include "absl/numeric/bits.h"
+#include "absl/base/internal/bits.h"
#include "absl/numeric/int128.h"
#include "absl/strings/internal/charconv_bigint.h"
#include "absl/strings/internal/charconv_parse.h"
@@ -111,7 +111,7 @@ struct FloatTraits<double> {
return sign ? -ldexp(mantissa, exponent) : ldexp(mantissa, exponent);
#else
constexpr uint64_t kMantissaMask =
- (uint64_t{1} << (kTargetMantissaBits - 1)) - 1;
+ (uint64_t(1) << (kTargetMantissaBits - 1)) - 1;
uint64_t dbl = static_cast<uint64_t>(sign) << 63;
if (mantissa > kMantissaMask) {
// Normal value.
@@ -151,7 +151,7 @@ struct FloatTraits<float> {
return sign ? -ldexpf(mantissa, exponent) : ldexpf(mantissa, exponent);
#else
constexpr uint32_t kMantissaMask =
- (uint32_t{1} << (kTargetMantissaBits - 1)) - 1;
+ (uint32_t(1) << (kTargetMantissaBits - 1)) - 1;
uint32_t flt = static_cast<uint32_t>(sign) << 31;
if (mantissa > kMantissaMask) {
// Normal value.
@@ -242,11 +242,11 @@ struct CalculatedFloat {
// Returns the bit width of the given uint128. (Equivalently, returns 128
// minus the number of leading zero bits.)
-unsigned BitWidth(uint128 value) {
+int BitWidth(uint128 value) {
if (Uint128High64(value) == 0) {
- return static_cast<unsigned>(bit_width(Uint128Low64(value)));
+ return 64 - base_internal::CountLeadingZeros64(Uint128Low64(value));
}
- return 128 - countl_zero(Uint128High64(value));
+ return 128 - base_internal::CountLeadingZeros64(Uint128High64(value));
}
// Calculates how far to the right a mantissa needs to be shifted to create a
@@ -499,7 +499,7 @@ bool MustRoundUp(uint64_t guess_mantissa, int guess_exponent,
template <typename FloatType>
CalculatedFloat CalculatedFloatFromRawValues(uint64_t mantissa, int exponent) {
CalculatedFloat result;
- if (mantissa == uint64_t{1} << FloatTraits<FloatType>::kTargetMantissaBits) {
+ if (mantissa == uint64_t(1) << FloatTraits<FloatType>::kTargetMantissaBits) {
mantissa >>= 1;
exponent += 1;
}
@@ -519,7 +519,7 @@ CalculatedFloat CalculateFromParsedHexadecimal(
const strings_internal::ParsedFloat& parsed_hex) {
uint64_t mantissa = parsed_hex.mantissa;
int exponent = parsed_hex.exponent;
- auto mantissa_width = static_cast<unsigned>(bit_width(mantissa));
+ int mantissa_width = 64 - base_internal::CountLeadingZeros64(mantissa);
const int shift = NormalizedShiftSize<FloatType>(mantissa_width, exponent);
bool result_exact;
exponent += shift;
@@ -619,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 string that begins with "0x" also begins with "0", which
+ // However, a std::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 string "0" does not have.)
+ // means an exponent is required, which the std::string "0" does not have.)
if (fmt_flags == chars_format::scientific) {
result.ec = std::errc::invalid_argument;
} else {
diff --git a/third_party/abseil-cpp/absl/strings/charconv.h b/third_party/abseil-cpp/absl/strings/charconv.h
index 7c50981245..e04be32f95 100644
--- a/third_party/abseil-cpp/absl/strings/charconv.h
+++ b/third_party/abseil-cpp/absl/strings/charconv.h
@@ -64,9 +64,8 @@ struct from_chars_result {
// the result in `value`.
//
// The matching pattern format is almost the same as that of strtod(), except
-// that (1) C locale is not respected, (2) an initial '+' character in the
-// input range will never be matched, and (3) leading whitespaces are not
-// ignored.
+// that C locale is not respected, and an initial '+' character in the input
+// range will never be matched.
//
// If `fmt` is set, it must be one of the enumerator values of the chars_format.
// (This is despite the fact that chars_format is a bitmask type.) If set to
diff --git a/third_party/abseil-cpp/absl/strings/charconv_benchmark.cc b/third_party/abseil-cpp/absl/strings/charconv_benchmark.cc
index e8c7371d65..644b2abdf6 100644
--- a/third_party/abseil-cpp/absl/strings/charconv_benchmark.cc
+++ b/third_party/abseil-cpp/absl/strings/charconv_benchmark.cc
@@ -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 string below.
+ // the std::string below.
const std::string digits =
"1."
"152113937042223790993097181572444900347587985074226836242307364987727724"
diff --git a/third_party/abseil-cpp/absl/strings/charconv_test.cc b/third_party/abseil-cpp/absl/strings/charconv_test.cc
index b83de5a0ba..9090e9c89c 100644
--- a/third_party/abseil-cpp/absl/strings/charconv_test.cc
+++ b/third_party/abseil-cpp/absl/strings/charconv_test.cc
@@ -653,9 +653,7 @@ 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));
- // 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);
+ from_chars_float = std::copysign(from_chars_float, -1.0);
EXPECT_TRUE(Identical(negative_from_chars_float, from_chars_float));
}
}
diff --git a/third_party/abseil-cpp/absl/strings/cord.cc b/third_party/abseil-cpp/absl/strings/cord.cc
index 854047ca98..d9503ae332 100644
--- a/third_party/abseil-cpp/absl/strings/cord.cc
+++ b/third_party/abseil-cpp/absl/strings/cord.cc
@@ -15,12 +15,10 @@
#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>
@@ -30,17 +28,11 @@
#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_btree.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_scope.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
#include "absl/strings/internal/resize_uninitialized.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
@@ -51,18 +43,144 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
using ::absl::cord_internal::CordRep;
-using ::absl::cord_internal::CordRepBtree;
using ::absl::cord_internal::CordRepConcat;
using ::absl::cord_internal::CordRepExternal;
-using ::absl::cord_internal::CordRepFlat;
using ::absl::cord_internal::CordRepSubstring;
-using ::absl::cord_internal::CordzUpdateTracker;
-using ::absl::cord_internal::InlineData;
-using ::absl::cord_internal::kMaxFlatLength;
-using ::absl::cord_internal::kMinFlatLength;
-using ::absl::cord_internal::kInlinedVectorSize;
-using ::absl::cord_internal::kMaxBytesToCopy;
+// Various representations that we allow
+enum CordRepKind {
+ CONCAT = 0,
+ EXTERNAL = 1,
+ SUBSTRING = 2,
+
+ // We have different tags for different sized flat arrays,
+ // starting with FLAT
+ FLAT = 3,
+};
+
+namespace {
+
+// Type used with std::allocator for allocating and deallocating
+// `CordRepExternal`. std::allocator is used because it opaquely handles the
+// different new / delete overloads available on a given platform.
+struct alignas(absl::cord_internal::ExternalRepAlignment()) ExternalAllocType {
+ unsigned char value[absl::cord_internal::ExternalRepAlignment()];
+};
+
+// Returns the number of objects to pass in to std::allocator<ExternalAllocType>
+// allocate() and deallocate() to create enough room for `CordRepExternal` with
+// `releaser_size` bytes on the end.
+constexpr size_t GetExternalAllocNumObjects(size_t releaser_size) {
+ // Be sure to round up since `releaser_size` could be smaller than
+ // `sizeof(ExternalAllocType)`.
+ return (sizeof(CordRepExternal) + releaser_size + sizeof(ExternalAllocType) -
+ 1) /
+ sizeof(ExternalAllocType);
+}
+
+// Allocates enough memory for `CordRepExternal` and a releaser with size
+// `releaser_size` bytes.
+void* AllocateExternal(size_t releaser_size) {
+ return std::allocator<ExternalAllocType>().allocate(
+ GetExternalAllocNumObjects(releaser_size));
+}
+
+// Deallocates the memory for a `CordRepExternal` assuming it was allocated with
+// a releaser of given size and alignment.
+void DeallocateExternal(CordRepExternal* p, size_t releaser_size) {
+ std::allocator<ExternalAllocType>().deallocate(
+ reinterpret_cast<ExternalAllocType*>(p),
+ GetExternalAllocNumObjects(releaser_size));
+}
+
+// Returns a pointer to the type erased releaser for the given CordRepExternal.
+void* GetExternalReleaser(CordRepExternal* rep) {
+ return rep + 1;
+}
+
+} // namespace
+
+namespace cord_internal {
+
+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);
+}
+
+} // namespace cord_internal
+
+static const size_t kFlatOverhead = offsetof(CordRep, data);
+
+static_assert(kFlatOverhead == 13, "Unittests assume kFlatOverhead == 13");
+
+// 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.
+static constexpr size_t kMaxFlatSize = 4096;
+static constexpr size_t kMaxFlatLength = kMaxFlatSize - kFlatOverhead;
+static constexpr size_t kMinFlatLength = 32 - kFlatOverhead;
+
+// Prefer copying blocks of at most this size, otherwise reference count.
+static const size_t kMaxBytesToCopy = 511;
+
+// Helper functions for rounded div, and rounding to exact sizes.
+static size_t DivUp(size_t n, size_t m) { return (n + m - 1) / m; }
+static 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.
+static 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>).
+static uint8_t AllocatedSizeToTag(size_t size) {
+ const size_t tag = (size <= 1024) ? size / 8 : 128 + size / 32 - 1024 / 32;
+ assert(tag <= std::numeric_limits<uint8_t>::max());
+ return tag;
+}
+
+// Converts the provided tag to the corresponding allocated size
+static 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
+static 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");
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);
@@ -77,30 +195,70 @@ static_assert(Fibonacci(63) == 6557470319842,
// 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),
+ 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 btree_enabled() {
- return cord_internal::cord_btree_enabled.load(
- std::memory_order_relaxed);
-}
+// 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).
+static const int kInlinedVectorSize = 47;
static inline bool IsRootBalanced(CordRep* node) {
- if (!node->IsConcat()) {
+ if (node->tag != CONCAT) {
return true;
} else if (node->concat()->depth() <= 15) {
return true;
@@ -114,8 +272,7 @@ static inline bool IsRootBalanced(CordRep* node) {
}
static CordRep* Rebalance(CordRep* node);
-static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
- int indent = 0);
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os);
static bool VerifyNode(CordRep* root, CordRep* start_node,
bool full_validation);
@@ -135,9 +292,103 @@ static inline CordRep* VerifyTree(CordRep* node) {
return node;
}
+// --------------------------------------------------------------------
+// Memory management
+
+inline CordRep* Ref(CordRep* rep) {
+ if (rep != nullptr) {
+ rep->refcount.Increment();
+ }
+ return rep;
+}
+
+// This internal routine is called from the cold path of Unref below. Keeping it
+// in a separate routine allows good inlining of Unref into many profitable call
+// sites. However, the call to this function can be highly disruptive to the
+// register pressure in those callers. To minimize the cost to callers, we use
+// a special LLVM calling convention that preserves most registers. This allows
+// the call to this routine in cold paths to not disrupt the caller's register
+// pressure. This calling convention is not available on all platforms; we
+// intentionally allow LLVM to ignore the attribute rather than attempting to
+// hardcode the list of supported platforms.
+#if defined(__clang__) && !defined(__i386__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wattributes"
+__attribute__((preserve_most))
+#pragma clang diagnostic pop
+#endif
+static void UnrefInternal(CordRep* rep) {
+ assert(rep != nullptr);
+
+ absl::InlinedVector<CordRep*, kInlinedVectorSize> pending;
+ while (true) {
+ 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 == EXTERNAL) {
+ CordRepExternal* rep_external = rep->external();
+ absl::string_view data(rep_external->base, rep->length);
+ void* releaser = GetExternalReleaser(rep_external);
+ size_t releaser_size = rep_external->releaser_invoker(releaser, data);
+ rep_external->~CordRepExternal();
+ DeallocateExternal(rep_external, releaser_size);
+ 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 {
+ // Flat CordReps are allocated and constructed with raw ::operator new
+ // and placement new, and must be destructed and deallocated
+ // accordingly.
+#if defined(__cpp_sized_deallocation)
+ size_t size = TagToAllocatedSize(rep->tag);
+ rep->~CordRep();
+ ::operator delete(rep, size);
+#else
+ rep->~CordRep();
+ ::operator delete(rep);
+#endif
+ rep = nullptr;
+ }
+
+ if (!pending.empty()) {
+ rep = pending.back();
+ pending.pop_back();
+ } else {
+ break;
+ }
+ }
+}
+
+inline void Unref(CordRep* rep) {
+ // Fast-path for two common, hot cases: a null rep and a shared root.
+ if (ABSL_PREDICT_TRUE(rep == nullptr ||
+ rep->refcount.DecrementExpectHighRefcount())) {
+ return;
+ }
+
+ UnrefInternal(rep);
+}
+
// Return the depth of a node
static int Depth(const CordRep* rep) {
- if (rep->IsConcat()) {
+ if (rep->tag == CONCAT) {
return rep->concat()->depth();
} else {
return 0;
@@ -158,19 +409,17 @@ static void SetConcatChildren(CordRepConcat* concat, CordRep* left,
// 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);
+ if (left == nullptr || left->length == 0) {
+ Unref(left);
return right;
}
- if (right->length == 0) {
- CordRep::Unref(right);
+ if (right == nullptr || right->length == 0) {
+ Unref(right);
return left;
}
CordRepConcat* rep = new CordRepConcat();
- rep->tag = cord_internal::CONCAT;
+ rep->tag = CONCAT;
SetConcatChildren(rep, left, right);
return rep;
@@ -204,41 +453,35 @@ static CordRep* MakeBalancedTree(CordRep** reps, size_t n) {
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 Btree out of the specified array.
-// The returned node has a refcount of 1.
-static CordRep* NewBtree(const char* data, size_t length, size_t alloc_hint) {
- if (length <= kMaxFlatLength) {
- return CreateFlat(data, length, alloc_hint);
+// Create a new flat node.
+static CordRep* NewFlat(size_t length_hint) {
+ if (length_hint <= kMinFlatLength) {
+ length_hint = kMinFlatLength;
+ } else if (length_hint > kMaxFlatLength) {
+ length_hint = kMaxFlatLength;
}
- CordRepFlat* flat = CreateFlat(data, kMaxFlatLength, 0);
- data += kMaxFlatLength;
- length -= kMaxFlatLength;
- auto* root = CordRepBtree::Create(flat);
- return CordRepBtree::Append(root, {data, length}, alloc_hint);
+
+ // Round size up so it matches a size we can exactly express in a tag.
+ const size_t size = RoundUpForTag(length_hint + kFlatOverhead);
+ void* const raw_rep = ::operator new(size);
+ CordRep* rep = new (raw_rep) CordRep();
+ rep->tag = AllocatedSizeToTag(size);
+ return VerifyTree(rep);
}
// 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) {
+static CordRep* NewTree(const char* data,
+ size_t length,
+ size_t alloc_hint) {
if (length == 0) return nullptr;
- if (btree_enabled()) {
- return NewBtree(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);
+ CordRep* rep = NewFlat(len + alloc_hint);
rep->length = len;
- memcpy(rep->Data(), data, len);
+ memcpy(rep->data, data, len);
reps[n++] = VerifyTree(rep);
data += len;
length -= len;
@@ -248,12 +491,18 @@ static CordRep* NewTree(const char* data, size_t length, size_t alloc_hint) {
namespace cord_internal {
-void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
+ExternalRepReleaserPair NewExternalWithUninitializedReleaser(
+ absl::string_view data, ExternalReleaserInvoker invoker,
+ size_t releaser_size) {
assert(!data.empty());
+
+ void* raw_rep = AllocateExternal(releaser_size);
+ auto* rep = new (raw_rep) CordRepExternal();
rep->length = data.size();
rep->tag = EXTERNAL;
rep->base = data.data();
- VerifyTree(rep);
+ rep->releaser_invoker = invoker;
+ return {VerifyTree(rep), GetExternalReleaser(rep)};
}
} // namespace cord_internal
@@ -261,155 +510,87 @@ void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep) {
static CordRep* NewSubstring(CordRep* child, size_t offset, size_t length) {
// Never create empty substring nodes
if (length == 0) {
- CordRep::Unref(child);
+ Unref(child);
return nullptr;
} else {
CordRepSubstring* rep = new CordRepSubstring();
assert((offset + length) <= child->length);
rep->length = length;
- rep->tag = cord_internal::SUBSTRING;
+ rep->tag = SUBSTRING;
rep->start = offset;
rep->child = child;
return VerifyTree(rep);
}
}
-// Creates a CordRep from the provided string. If the string is large enough,
-// and not wasteful, we move the string into an external cord rep, preserving
-// the already allocated string contents.
-// Requires the provided string length to be larger than `kMaxInline`.
-static CordRep* CordRepFromString(std::string&& src) {
- assert(src.length() > cord_internal::kMaxInline);
- 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
- ) {
- return NewTree(src.data(), src.size(), 0);
- }
-
- 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::move(src)}));
- // Moving src may have invalidated its data pointer, so adjust it.
- rep->base = rep->template get<0>().data.data();
- return rep;
-}
-
// --------------------------------------------------------------------
// Cord::InlineRep functions
-constexpr unsigned char Cord::InlineRep::kMaxInline;
+// This will trigger LNK2005 in MSVC.
+#ifndef COMPILER_MSVC
+const unsigned char Cord::InlineRep::kMaxInline;
+#endif // COMPILER_MSVC
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);
+ cord_internal::SmallMemmove(data_, data, n, nullify_tail);
+ data_[kMaxInline] = static_cast<char>(n);
}
inline char* Cord::InlineRep::set_data(size_t n) {
assert(n <= kMaxInline);
- ResetToEmpty();
- set_inline_size(n);
- return data_.as_chars();
+ memset(data_, 0, sizeof(data_));
+ data_[kMaxInline] = static_cast<char>(n);
+ return data_;
+}
+
+inline CordRep* Cord::InlineRep::force_tree(size_t extra_hint) {
+ size_t len = data_[kMaxInline];
+ CordRep* result;
+ if (len > kMaxInline) {
+ memcpy(&result, data_, sizeof(result));
+ } else {
+ result = NewFlat(len + extra_hint);
+ result->length = len;
+ memcpy(result->data, data_, len);
+ set_tree(result);
+ }
+ return result;
}
inline void Cord::InlineRep::reduce_size(size_t n) {
- size_t tag = inline_size();
+ size_t tag = data_[kMaxInline];
assert(tag <= kMaxInline);
assert(tag >= n);
tag -= n;
- memset(data_.as_chars() + tag, 0, n);
- set_inline_size(static_cast<char>(tag));
+ memset(data_ + tag, 0, n);
+ data_[kMaxInline] = 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);
+ cord_internal::SmallMemmove(data_, data_ + n, data_[kMaxInline] - n);
reduce_size(n);
}
-// Returns `rep` converted into a CordRepBtree.
-// Directly returns `rep` if `rep` is already a CordRepBtree.
-static CordRepBtree* ForceBtree(CordRep* rep) {
- return rep->IsBtree() ? rep->btree() : CordRepBtree::Create(rep);
-}
-
-void Cord::InlineRep::AppendTreeToInlined(CordRep* tree,
- MethodIdentifier method) {
- assert(!is_tree());
- if (!data_.is_empty()) {
- CordRepFlat* flat = MakeFlatWithExtraCapacity(0);
- if (btree_enabled()) {
- tree = CordRepBtree::Append(CordRepBtree::Create(flat), tree);
- } else {
- tree = Concat(flat, tree);
- }
- }
- EmplaceTree(tree, method);
-}
-
-void Cord::InlineRep::AppendTreeToTree(CordRep* tree, MethodIdentifier method) {
- assert(is_tree());
- const CordzUpdateScope scope(data_.cordz_info(), method);
- if (btree_enabled()) {
- tree = CordRepBtree::Append(ForceBtree(data_.as_tree()), tree);
- } else {
- tree = Concat(data_.as_tree(), tree);
- }
- SetTree(tree, scope);
-}
-
-void Cord::InlineRep::AppendTree(CordRep* tree, MethodIdentifier method) {
+void Cord::InlineRep::AppendTree(CordRep* tree) {
if (tree == nullptr) return;
- if (data_.is_tree()) {
- AppendTreeToTree(tree, method);
- } else {
- AppendTreeToInlined(tree, method);
- }
-}
-
-void Cord::InlineRep::PrependTreeToInlined(CordRep* tree,
- MethodIdentifier method) {
- assert(!is_tree());
- if (!data_.is_empty()) {
- CordRepFlat* flat = MakeFlatWithExtraCapacity(0);
- if (btree_enabled()) {
- tree = CordRepBtree::Prepend(CordRepBtree::Create(flat), tree);
- } else {
- tree = Concat(tree, flat);
- }
- }
- EmplaceTree(tree, method);
-}
-
-void Cord::InlineRep::PrependTreeToTree(CordRep* tree,
- MethodIdentifier method) {
- assert(is_tree());
- const CordzUpdateScope scope(data_.cordz_info(), method);
- if (btree_enabled()) {
- tree = CordRepBtree::Prepend(ForceBtree(data_.as_tree()), tree);
+ size_t len = data_[kMaxInline];
+ if (len == 0) {
+ set_tree(tree);
} else {
- tree = Concat(tree, data_.as_tree());
+ set_tree(Concat(force_tree(0), tree));
}
- SetTree(tree, scope);
}
-void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
- assert(tree != nullptr);
- if (data_.is_tree()) {
- PrependTreeToTree(tree, method);
+void Cord::InlineRep::PrependTree(CordRep* tree) {
+ if (tree == nullptr) return;
+ size_t len = data_[kMaxInline];
+ if (len == 0) {
+ set_tree(tree);
} else {
- PrependTreeToInlined(tree, method);
+ set_tree(Concat(tree, force_tree(0)));
}
}
@@ -419,29 +600,20 @@ void Cord::InlineRep::PrependTree(CordRep* tree, MethodIdentifier method) {
// 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->IsBtree() && root->refcount.IsMutable()) {
- Span<char> span = root->btree()->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->IsConcat() && dst->refcount.IsMutable()) {
+ while (dst->tag == CONCAT && dst->refcount.IsOne()) {
dst = dst->concat()->right;
}
- if (!dst->IsFlat() || !dst->refcount.IsMutable()) {
+ 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();
+ const size_t capacity = TagToLength(dst->tag);
if (in_use == capacity) {
*region = nullptr;
*size = 0;
@@ -456,281 +628,214 @@ static inline bool PrepareAppendRegion(CordRep* root, char** region,
}
dst->length += size_increase;
- *region = dst->flat()->Data() + in_use;
+ *region = dst->data + in_use;
*size = size_increase;
return true;
}
-template <bool has_length>
void Cord::InlineRep::GetAppendRegion(char** region, size_t* size,
- size_t length) {
- auto constexpr method = CordzUpdateTracker::kGetAppendRegion;
+ size_t max_length) {
+ if (max_length == 0) {
+ *region = nullptr;
+ *size = 0;
+ return;
+ }
- CordRep* root = tree();
- size_t sz = root ? root->length : inline_size();
- if (root == nullptr) {
- size_t available = kMaxInline - sz;
- if (available >= (has_length ? length : 1)) {
- *region = data_.as_chars() + sz;
- *size = has_length ? length : available;
- set_inline_size(has_length ? sz + length : kMaxInline);
- return;
- }
+ // Try to fit in the inline buffer if possible.
+ size_t inline_length = data_[kMaxInline];
+ if (inline_length < kMaxInline && max_length <= kMaxInline - inline_length) {
+ *region = data_ + inline_length;
+ *size = max_length;
+ data_[kMaxInline] = static_cast<char>(inline_length + max_length);
+ return;
}
- size_t extra = has_length ? length : (std::max)(sz, kMinFlatLength);
- CordRep* rep = root ? root : MakeFlatWithExtraCapacity(extra);
- CordzUpdateScope scope(root ? data_.cordz_info() : nullptr, method);
- if (PrepareAppendRegion(rep, region, size, length)) {
- CommitTree(root, rep, scope, method);
+ CordRep* root = force_tree(max_length);
+
+ if (PrepareAppendRegion(root, region, size, max_length)) {
return;
}
// Allocate new node.
- CordRepFlat* new_node = CordRepFlat::New(extra);
- new_node->length = std::min(new_node->Capacity(), length);
- *region = new_node->Data();
+ CordRep* new_node =
+ NewFlat(std::max(static_cast<size_t>(root->length), max_length));
+ new_node->length =
+ std::min(static_cast<size_t>(TagToLength(new_node->tag)), max_length);
+ *region = new_node->data;
*size = new_node->length;
-
- if (btree_enabled()) {
- rep = CordRepBtree::Append(ForceBtree(rep), new_node);
- } else {
- rep = Concat(rep, new_node);
- }
- CommitTree(root, rep, scope, method);
+ replace_tree(Concat(root, new_node));
}
-// Computes the memory side of the provided edge which must be a valid data edge
-// for a btrtee, i.e., a FLAT, EXTERNAL or SUBSTRING of a FLAT or EXTERNAL node.
-static bool RepMemoryUsageDataEdge(const CordRep* rep,
- size_t* total_mem_usage) {
- size_t maybe_sub_size = 0;
- if (ABSL_PREDICT_FALSE(rep->IsSubstring())) {
- maybe_sub_size = sizeof(cord_internal::CordRepSubstring);
- rep = rep->substring()->child;
- }
- if (rep->IsFlat()) {
- *total_mem_usage += maybe_sub_size + rep->flat()->AllocatedSize();
- return true;
+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.
+ size_t inline_length = data_[kMaxInline];
+ if (inline_length < kMaxInline) {
+ *region = data_ + inline_length;
+ *size = kMaxInline - inline_length;
+ data_[kMaxInline] = kMaxInline;
+ return;
}
- if (rep->IsExternal()) {
- // We don't know anything about the embedded / bound data, but we can safely
- // assume it is 'at least' a word / pointer to data. In the future we may
- // choose to use the 'data' byte as a tag to identify the types of some
- // well-known externals, such as a std::string instance.
- *total_mem_usage += maybe_sub_size +
- sizeof(cord_internal::CordRepExternalImpl<intptr_t>) +
- rep->length;
- return true;
+
+ CordRep* root = force_tree(max_length);
+
+ if (PrepareAppendRegion(root, region, size, max_length)) {
+ return;
}
- return false;
+
+ // Allocate new node.
+ CordRep* new_node = NewFlat(root->length);
+ new_node->length = TagToLength(new_node->tag);
+ *region = new_node->data;
+ *size = new_node->length;
+ 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->IsFlat()) {
- *total_mem_usage += rep->flat()->AllocatedSize();
+ if (rep->tag >= FLAT) {
+ *total_mem_usage += TagToAllocatedSize(rep->tag);
return true;
}
- if (rep->IsExternal()) {
- // We don't know anything about the embedded / bound data, but we can safely
- // assume it is 'at least' a word / pointer to data. In the future we may
- // choose to use the 'data' byte as a tag to identify the types of some
- // well-known externals, such as a std::string instance.
- *total_mem_usage +=
- sizeof(cord_internal::CordRepExternalImpl<intptr_t>) + rep->length;
+ if (rep->tag == EXTERNAL) {
+ *total_mem_usage += sizeof(CordRepConcat) + rep->length;
return true;
}
return false;
}
void Cord::InlineRep::AssignSlow(const Cord::InlineRep& src) {
- assert(&src != this);
- assert(is_tree() || src.is_tree());
- auto constexpr method = CordzUpdateTracker::kAssignCord;
- if (ABSL_PREDICT_TRUE(!is_tree())) {
- EmplaceTree(CordRep::Ref(src.as_tree()), src.data_, method);
- return;
- }
+ ClearSlow();
- CordRep* tree = as_tree();
- if (CordRep* src_tree = src.tree()) {
- // Leave any existing `cordz_info` in place, and let MaybeTrackCord()
- // decide if this cord should be (or remains to be) sampled or not.
- data_.set_tree(CordRep::Ref(src_tree));
- CordzInfo::MaybeTrackCord(data_, src.data_, method);
- } else {
- CordzInfo::MaybeUntrackCord(data_.cordz_info());
- data_ = src.data_;
+ memcpy(data_, src.data_, sizeof(data_));
+ if (is_tree()) {
+ Ref(tree());
}
- CordRep::Unref(tree);
}
-void Cord::InlineRep::UnrefTree() {
+void Cord::InlineRep::ClearSlow() {
if (is_tree()) {
- CordzInfo::MaybeUntrackCord(data_.cordz_info());
- CordRep::Unref(tree());
+ Unref(tree());
}
+ memset(data_, 0, sizeof(data_));
}
// --------------------------------------------------------------------
// Constructors and destructors
-Cord::Cord(absl::string_view src, MethodIdentifier method)
- : contents_(InlineData::kDefaultInit) {
- const size_t n = src.size();
- if (n <= InlineRep::kMaxInline) {
- contents_.set_data(src.data(), n, true);
- } else {
- CordRep* rep = NewTree(src.data(), n, 0);
- contents_.EmplaceTree(rep, method);
- }
+Cord::Cord(const Cord& src) : contents_(src.contents_) {
+ Ref(contents_.tree()); // Does nothing if contents_ has embedded data
}
-template <typename T, Cord::EnableIfString<T>>
-Cord::Cord(T&& src) : contents_(InlineData::kDefaultInit) {
- if (src.size() <= InlineRep::kMaxInline) {
- contents_.set_data(src.data(), src.size(), true);
+Cord::Cord(absl::string_view src) {
+ const size_t n = src.size();
+ if (n <= InlineRep::kMaxInline) {
+ contents_.set_data(src.data(), n, false);
} else {
- CordRep* rep = CordRepFromString(std::forward<T>(src));
- contents_.EmplaceTree(rep, CordzUpdateTracker::kConstructorString);
+ contents_.set_tree(NewTree(src.data(), n, 0));
}
}
-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() {
- assert(contents_.is_tree());
- CordzInfo::MaybeUntrackCord(contents_.cordz_info());
- CordRep::Unref(VerifyTree(contents_.as_tree()));
+ Unref(VerifyTree(contents_.tree()));
}
// --------------------------------------------------------------------
// Mutators
void Cord::Clear() {
- if (CordRep* tree = contents_.clear()) {
- CordRep::Unref(tree);
- }
-}
-
-Cord& Cord::AssignLargeString(std::string&& src) {
- auto constexpr method = CordzUpdateTracker::kAssignString;
- assert(src.size() > kMaxBytesToCopy);
- CordRep* rep = CordRepFromString(std::move(src));
- if (CordRep* tree = contents_.tree()) {
- CordzUpdateScope scope(contents_.cordz_info(), method);
- contents_.SetTree(rep, scope);
- CordRep::Unref(tree);
- } else {
- contents_.EmplaceTree(rep, method);
- }
- return *this;
+ Unref(contents_.clear());
}
Cord& Cord::operator=(absl::string_view src) {
- auto constexpr method = CordzUpdateTracker::kAssignString;
+
const char* data = src.data();
size_t length = src.size();
CordRep* tree = contents_.tree();
if (length <= InlineRep::kMaxInline) {
- // Embed into this->contents_, which is somewhat subtle:
- // - MaybeUntrackCord must be called before Unref(tree).
- // - MaybeUntrackCord must be called before set_data() clobbers cordz_info.
- // - set_data() must be called before Unref(tree) as it may reference tree.
- if (tree != nullptr) CordzInfo::MaybeUntrackCord(contents_.cordz_info());
+ // Embed into this->contents_
contents_.set_data(data, length, true);
- if (tree != nullptr) CordRep::Unref(tree);
+ Unref(tree);
return *this;
}
- if (tree != nullptr) {
- CordzUpdateScope scope(contents_.cordz_info(), method);
- if (tree->IsFlat() && tree->flat()->Capacity() >= length &&
- tree->refcount.IsMutable()) {
- // Copy in place if the existing FLAT node is reusable.
- memmove(tree->flat()->Data(), data, length);
- tree->length = length;
- VerifyTree(tree);
- return *this;
- }
- contents_.SetTree(NewTree(data, length, 0), scope);
- CordRep::Unref(tree);
- } else {
- contents_.EmplaceTree(NewTree(data, length, 0), method);
+ if (tree != nullptr && tree->tag >= FLAT &&
+ TagToLength(tree->tag) >= length && tree->refcount.IsOne()) {
+ // Copy in place if the existing FLAT node is reusable.
+ memmove(tree->data, data, length);
+ tree->length = length;
+ VerifyTree(tree);
+ return *this;
}
+ contents_.set_tree(NewTree(data, length, 0));
+ Unref(tree);
return *this;
}
// TODO(sanjay): Move to Cord::InlineRep section of file. For now,
// we keep it here to make diffs easier.
-void Cord::InlineRep::AppendArray(absl::string_view src,
- MethodIdentifier method) {
- if (src.empty()) return; // memcpy(_, nullptr, 0) is undefined.
+void Cord::InlineRep::AppendArray(const char* src_data, size_t src_size) {
+ if (src_size == 0) return; // memcpy(_, nullptr, 0) is undefined.
+ // Try to fit in the inline buffer if possible.
+ size_t inline_length = data_[kMaxInline];
+ if (inline_length < kMaxInline && src_size <= kMaxInline - inline_length) {
+ // Append new data to embedded array
+ data_[kMaxInline] = static_cast<char>(inline_length + src_size);
+ memcpy(data_ + inline_length, src_data, src_size);
+ return;
+ }
+
+ CordRep* root = tree();
size_t appended = 0;
- CordRep* rep = tree();
- const CordRep* const root = rep;
- CordzUpdateScope scope(root ? cordz_info() : nullptr, method);
- if (root != nullptr) {
+ if (root) {
char* region;
- if (PrepareAppendRegion(rep, &region, &appended, src.size())) {
- memcpy(region, src.data(), appended);
+ 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;
- }
-
- // Allocate flat to be a perfect fit on first append exceeding inlined size.
- // Subsequent growth will use amortized growth until we reach maximum flat
- // size.
- rep = CordRepFlat::New(inline_length + src.size());
- appended = std::min(src.size(), rep->flat()->Capacity() - inline_length);
- memcpy(rep->flat()->Data(), data_.as_chars(), inline_length);
- memcpy(rep->flat()->Data() + inline_length, src.data(), appended);
- rep->length = inline_length + appended;
- }
-
- src.remove_prefix(appended);
- if (src.empty()) {
- CommitTree(root, rep, scope, method);
+ // 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 = NewFlat(std::max<size_t>(size1, size2));
+ appended = std::min(src_size, TagToLength(root->tag) - inline_length);
+ memcpy(root->data, data_, inline_length);
+ memcpy(root->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 (btree_enabled()) {
- // TODO(b/192061034): keep legacy 10% growth rate: consider other rates.
- rep = ForceBtree(rep);
- const size_t min_growth = std::max<size_t>(rep->length / 10, src.size());
- rep = CordRepBtree::Append(rep->btree(), src, min_growth - src.size());
- } else {
- // 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>(rep->length / 10, src.size());
- }
- rep = Concat(rep, NewTree(src.data(), src.size(), length - src.size()));
+ // 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);
}
- CommitTree(root, rep, scope, method);
+ set_tree(Concat(root, NewTree(src_data, src_size, length - src_size)));
}
inline CordRep* Cord::TakeRep() const& {
- return CordRep::Ref(contents_.tree());
+ return Ref(contents_.tree());
}
inline CordRep* Cord::TakeRep() && {
@@ -741,17 +846,10 @@ inline CordRep* Cord::TakeRep() && {
template <typename C>
inline void Cord::AppendImpl(C&& src) {
- auto constexpr method = CordzUpdateTracker::kAppendCord;
if (empty()) {
- // Since destination is empty, we can avoid allocating a node,
- if (src.contents_.is_tree()) {
- // by taking the tree directly
- CordRep* rep = std::forward<C>(src).TakeRep();
- contents_.EmplaceTree(rep, method);
- } else {
- // or copying over inline data
- contents_.data_ = src.contents_.data_;
- }
+ // In case of an empty destination avoid allocating a new node, do not copy
+ // data.
+ *this = std::forward<C>(src);
return;
}
@@ -761,12 +859,12 @@ inline void Cord::AppendImpl(C&& src) {
CordRep* src_tree = src.contents_.tree();
if (src_tree == nullptr) {
// src has embedded data.
- contents_.AppendArray({src.contents_.data(), src_size}, method);
+ contents_.AppendArray(src.contents_.data(), src_size);
return;
}
- if (src_tree->IsFlat()) {
+ if (src_tree->tag >= FLAT) {
// src tree just has one flat node.
- contents_.AppendArray({src_tree->flat()->Data(), src_size}, method);
+ contents_.AppendArray(src_tree->data, src_size);
return;
}
if (&src == this) {
@@ -781,36 +879,18 @@ inline void Cord::AppendImpl(C&& src) {
return;
}
- // Guaranteed to be a tree (kMaxBytesToCopy > kInlinedSize)
- CordRep* rep = std::forward<C>(src).TakeRep();
- contents_.AppendTree(rep, CordzUpdateTracker::kAppendCord);
-}
-
-void Cord::Append(const Cord& src) {
- AppendImpl(src);
+ contents_.AppendTree(std::forward<C>(src).TakeRep());
}
-void Cord::Append(Cord&& src) {
- AppendImpl(std::move(src));
-}
+void Cord::Append(const Cord& src) { AppendImpl(src); }
-template <typename T, Cord::EnableIfString<T>>
-void Cord::Append(T&& src) {
- if (src.size() <= kMaxBytesToCopy) {
- Append(absl::string_view(src));
- } else {
- CordRep* rep = CordRepFromString(std::forward<T>(src));
- contents_.AppendTree(rep, CordzUpdateTracker::kAppendString);
- }
-}
-
-template void Cord::Append(std::string&& src);
+void Cord::Append(Cord&& src) { AppendImpl(std::move(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, CordzUpdateTracker::kPrependCord);
+ Ref(src_tree);
+ contents_.PrependTree(src_tree);
return;
}
@@ -819,42 +899,28 @@ void Cord::Prepend(const Cord& src) {
return Prepend(src_contents);
}
-void Cord::PrependArray(absl::string_view src, MethodIdentifier method) {
+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;
- }
- }
- CordRep* rep = NewTree(src.data(), src.size(), 0);
- contents_.PrependTree(rep, method);
-}
-
-template <typename T, Cord::EnableIfString<T>>
-inline void Cord::Prepend(T&& src) {
- if (src.size() <= kMaxBytesToCopy) {
- Prepend(absl::string_view(src));
+ size_t cur_size = contents_.size();
+ if (!contents_.is_tree() && cur_size + src.size() <= InlineRep::kMaxInline) {
+ // Use embedded storage.
+ char data[InlineRep::kMaxInline + 1] = {0};
+ data[InlineRep::kMaxInline] = cur_size + src.size(); // set size
+ memcpy(data, src.data(), src.size());
+ memcpy(data + src.size(), contents_.data(), cur_size);
+ memcpy(reinterpret_cast<void*>(&contents_), data,
+ InlineRep::kMaxInline + 1);
} else {
- CordRep* rep = CordRepFromString(std::forward<T>(src));
- contents_.PrependTree(rep, CordzUpdateTracker::kPrependString);
+ contents_.PrependTree(NewTree(src.data(), src.size(), 0));
}
}
-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);
+ if (n == 0) return Ref(node);
absl::InlinedVector<CordRep*, kInlinedVectorSize> rhs_stack;
- while (node->IsConcat()) {
+ while (node->tag == CONCAT) {
assert(n <= node->length);
if (n < node->concat()->left->length) {
// Push right to stack, descend left.
@@ -869,19 +935,19 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
assert(n <= node->length);
if (n == 0) {
- CordRep::Ref(node);
+ Ref(node);
} else {
size_t start = n;
size_t len = node->length - n;
- if (node->IsSubstring()) {
+ 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);
+ node = NewSubstring(Ref(node), start, len);
}
while (!rhs_stack.empty()) {
- node = Concat(node, CordRep::Ref(rhs_stack.back()));
+ node = Concat(node, Ref(rhs_stack.back()));
rhs_stack.pop_back();
}
return node;
@@ -892,11 +958,11 @@ static CordRep* RemovePrefixFrom(CordRep* node, size_t n) {
// 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);
+ if (n == 0) return Ref(node);
absl::InlinedVector<CordRep*, kInlinedVectorSize> lhs_stack;
- bool inplace_ok = node->refcount.IsMutable();
+ bool inplace_ok = node->refcount.IsOne();
- while (node->IsConcat()) {
+ while (node->tag == CONCAT) {
assert(n <= node->length);
if (n < node->concat()->right->length) {
// Push left to stack, descend right.
@@ -907,28 +973,28 @@ static CordRep* RemoveSuffixFrom(CordRep* node, size_t n) {
n -= node->concat()->right->length;
node = node->concat()->left;
}
- inplace_ok = inplace_ok && node->refcount.IsMutable();
+ inplace_ok = inplace_ok && node->refcount.IsOne();
}
assert(n <= node->length);
if (n == 0) {
- CordRep::Ref(node);
- } else if (inplace_ok && !node->IsExternal()) {
+ 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);
+ Ref(node);
node->length -= n;
} else {
size_t start = 0;
size_t len = node->length - n;
- if (node->IsSubstring()) {
+ if (node->tag == SUBSTRING) {
start = node->substring()->start;
node = node->substring()->child;
}
- node = NewSubstring(CordRep::Ref(node), start, len);
+ node = NewSubstring(Ref(node), start, len);
}
while (!lhs_stack.empty()) {
- node = Concat(CordRep::Ref(lhs_stack.back()), node);
+ node = Concat(Ref(lhs_stack.back()), node);
lhs_stack.pop_back();
}
return node;
@@ -942,18 +1008,9 @@ void Cord::RemovePrefix(size_t n) {
if (tree == nullptr) {
contents_.remove_prefix(n);
} else {
- auto constexpr method = CordzUpdateTracker::kRemovePrefix;
- CordzUpdateScope scope(contents_.cordz_info(), method);
- if (tree->IsBtree()) {
- CordRep* old = tree;
- tree = tree->btree()->SubTree(n, tree->length - n);
- CordRep::Unref(old);
- } else {
- CordRep* newrep = RemovePrefixFrom(tree, n);
- CordRep::Unref(tree);
- tree = VerifyTree(newrep);
- }
- contents_.SetTreeOrEmpty(tree, scope);
+ CordRep* newrep = RemovePrefixFrom(tree, n);
+ Unref(tree);
+ contents_.replace_tree(VerifyTree(newrep));
}
}
@@ -965,16 +1022,9 @@ void Cord::RemoveSuffix(size_t n) {
if (tree == nullptr) {
contents_.reduce_size(n);
} else {
- auto constexpr method = CordzUpdateTracker::kRemoveSuffix;
- CordzUpdateScope scope(contents_.cordz_info(), method);
- if (tree->IsBtree()) {
- tree = CordRepBtree::RemoveSuffix(tree->btree(), n);
- } else {
- CordRep* newrep = RemoveSuffixFrom(tree, n);
- CordRep::Unref(tree);
- tree = VerifyTree(newrep);
- }
- contents_.SetTreeOrEmpty(tree, scope);
+ CordRep* newrep = RemoveSuffixFrom(tree, n);
+ Unref(tree);
+ contents_.replace_tree(VerifyTree(newrep));
}
}
@@ -1006,13 +1056,13 @@ static CordRep* NewSubRange(CordRep* node, size_t pos, size_t n) {
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->IsConcat()) {
- if (node->IsSubstring()) {
+ results.push_back(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));
+ results.push_back(NewSubstring(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) {
@@ -1034,20 +1084,17 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
size_t length = size();
if (pos > length) pos = length;
if (new_size > length - pos) new_size = length - pos;
- if (new_size == 0) return sub_cord;
-
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);
- return sub_cord;
- }
-
- if (new_size <= InlineRep::kMaxInline) {
- char* dest = sub_cord.contents_.data_.as_chars();
+ } 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_;
size_t remaining_size = new_size;
while (remaining_size > it->size()) {
cord_internal::SmallMemmove(dest, it->data(), it->size());
@@ -1056,17 +1103,10 @@ Cord Cord::Subcord(size_t pos, size_t new_size) const {
++it;
}
cord_internal::SmallMemmove(dest, it->data(), remaining_size);
- sub_cord.contents_.set_inline_size(new_size);
- return sub_cord;
- }
-
- if (tree->IsBtree()) {
- tree = tree->btree()->SubTree(pos, new_size);
+ sub_cord.contents_.data_[InlineRep::kMaxInline] = new_size;
} else {
- tree = NewSubRange(tree, pos, new_size);
+ sub_cord.contents_.set_tree(NewSubRange(tree, pos, new_size));
}
- sub_cord.contents_.EmplaceTree(tree, contents_.data_,
- CordzUpdateTracker::kSubCord);
return sub_cord;
}
@@ -1085,7 +1125,7 @@ class CordForest {
CordRep* node = pending.back();
pending.pop_back();
CheckNode(node);
- if (ABSL_PREDICT_FALSE(!node->IsConcat())) {
+ if (ABSL_PREDICT_FALSE(node->tag != CONCAT)) {
AddNode(node);
continue;
}
@@ -1100,9 +1140,9 @@ class CordForest {
concat_node->left = concat_freelist_;
concat_freelist_ = concat_node;
} else {
- CordRep::Ref(concat_node->right);
- CordRep::Ref(concat_node->left);
- CordRep::Unref(concat_node);
+ Ref(concat_node->right);
+ Ref(concat_node->left);
+ Unref(concat_node);
}
} else {
AddNode(node);
@@ -1135,7 +1175,7 @@ class CordForest {
void AddNode(CordRep* node) {
CordRep* sum = nullptr;
- // Collect together everything with which we will merge with node
+ // Collect together everything with which we will merge node
int i = 0;
for (; node->length > min_length[i + 1]; ++i) {
auto& tree_at_i = trees_[i];
@@ -1179,7 +1219,7 @@ class CordForest {
static void CheckNode(CordRep* node) {
ABSL_INTERNAL_CHECK(node->length != 0u, "");
- if (node->IsConcat()) {
+ 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 +
@@ -1199,7 +1239,7 @@ class CordForest {
static CordRep* Rebalance(CordRep* node) {
VerifyTree(node);
- assert(node->IsConcat());
+ assert(node->tag == CONCAT);
if (node->length == 0) {
return nullptr;
@@ -1249,33 +1289,25 @@ bool ComputeCompareResult<bool>(int memcmp_res) {
} // namespace
-// Helper routine. Locates the first flat or external chunk of the Cord without
-// initializing the iterator, and returns a string_view referencing the data.
+// 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());
+ size_t n = data_[kMaxInline];
+ if (n <= kMaxInline) {
+ return absl::string_view(data_, n);
}
CordRep* node = tree();
- if (node->IsFlat()) {
- return absl::string_view(node->flat()->Data(), node->length);
+ if (node->tag >= FLAT) {
+ return absl::string_view(node->data, node->length);
}
- if (node->IsExternal()) {
+ if (node->tag == EXTERNAL) {
return absl::string_view(node->external()->base, node->length);
}
- if (node->IsBtree()) {
- CordRepBtree* tree = node->btree();
- int height = tree->height();
- while (--height >= 0) {
- tree = tree->Edge(CordRepBtree::kFront)->btree();
- }
- return tree->Data(tree->begin());
- }
-
// Walk down the left branches until we hit a non-CONCAT node.
- while (node->IsConcat()) {
+ while (node->tag == CONCAT) {
node = node->concat()->left;
}
@@ -1284,16 +1316,16 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const {
size_t length = node->length;
assert(length != 0);
- if (node->IsSubstring()) {
+ if (node->tag == SUBSTRING) {
offset = node->substring()->start;
node = node->substring()->child;
}
- if (node->IsFlat()) {
- return absl::string_view(node->flat()->Data() + offset, length);
+ if (node->tag >= FLAT) {
+ return absl::string_view(node->data + offset, length);
}
- assert(node->IsExternal() && "Expect FLAT or EXTERNAL node here");
+ assert((node->tag == EXTERNAL) && "Expect FLAT or EXTERNAL node here");
return absl::string_view(node->external()->base + offset, length);
}
@@ -1473,47 +1505,48 @@ void Cord::CopyToArraySlowPath(char* dst) const {
}
}
-Cord::ChunkIterator& Cord::ChunkIterator::AdvanceStack() {
- auto& stack_of_right_children = stack_of_right_children_;
- if (stack_of_right_children.empty()) {
+Cord::ChunkIterator& Cord::ChunkIterator::operator++() {
+ assert(bytes_remaining_ > 0 && "Attempted to iterate past `end()`");
+ assert(bytes_remaining_ >= current_chunk_.size());
+ bytes_remaining_ -= current_chunk_.size();
+
+ 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();
+ 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->IsConcat()) {
- stack_of_right_children.push_back(node->concat()->right);
+ 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->IsSubstring()) {
+ if (node->tag == SUBSTRING) {
offset = node->substring()->start;
node = node->substring()->child;
}
- assert(node->IsExternal() || node->IsFlat());
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
assert(length != 0);
const char* data =
- node->IsExternal() ? node->external()->base : node->flat()->Data();
+ node->tag == EXTERNAL ? node->external()->base : node->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()`");
+ assert(bytes_remaining_ >= n && "Attempted to iterate past `end()`");
Cord subcord;
- auto constexpr method = CordzUpdateTracker::kCordReader;
if (n <= InlineRep::kMaxInline) {
// Range to read fits in inline data. Flatten it.
@@ -1532,34 +1565,14 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
}
return subcord;
}
-
- if (btree_reader_) {
- size_t chunk_size = current_chunk_.size();
- if (n <= chunk_size && n <= kMaxBytesToCopy) {
- subcord = Cord(current_chunk_.substr(0, n), method);
- if (n < chunk_size) {
- current_chunk_.remove_prefix(n);
- } else {
- current_chunk_ = btree_reader_.Next();
- }
- } else {
- CordRep* rep;
- current_chunk_ = btree_reader_.Read(n, chunk_size, rep);
- subcord.contents_.EmplaceTree(rep, method);
- }
- bytes_remaining_ -= 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->IsExternal() ? subnode->external()->base
- : subnode->flat()->Data();
+ CordRep* subnode = Ref(current_leaf_);
+ const char* data =
+ subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
subnode = NewSubstring(subnode, current_chunk_.data() - data, n);
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
+ subcord.contents_.set_tree(VerifyTree(subnode));
RemoveChunkPrefix(n);
return subcord;
}
@@ -1567,10 +1580,10 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// 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_);
+ CordRep* subnode = Ref(current_leaf_);
if (current_chunk_.size() < subnode->length) {
- const char* data = subnode->IsExternal() ? subnode->external()->base
- : subnode->flat()->Data();
+ const char* data =
+ subnode->tag == EXTERNAL ? subnode->external()->base : subnode->data;
subnode = NewSubstring(subnode, current_chunk_.data() - data,
current_chunk_.size());
}
@@ -1580,20 +1593,20 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// 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();
+ 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
+ // 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));
+ subnode = Concat(subnode, Ref(node));
n -= node->length;
bytes_remaining_ -= node->length;
node = nullptr;
@@ -1602,20 +1615,20 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
if (node == nullptr) {
// We have reached the end of the Cord.
assert(bytes_remaining_ == 0);
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
+ 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->IsConcat()) {
+ while (node->tag == CONCAT) {
if (node->concat()->left->length > n) {
// Push right, descend left.
- stack_of_right_children.push_back(node->concat()->right);
+ 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));
+ subnode = Concat(subnode, Ref(node->concat()->left));
n -= node->concat()->left->length;
bytes_remaining_ -= node->concat()->left->length;
node = node->concat()->right;
@@ -1625,24 +1638,22 @@ Cord Cord::ChunkIterator::AdvanceAndReadBytes(size_t n) {
// Get the child node if we encounter a SUBSTRING.
size_t offset = 0;
size_t length = node->length;
- if (node->IsSubstring()) {
+ 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->IsExternal() || node->IsFlat());
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
assert(length > n);
- if (n > 0) {
- subnode = Concat(subnode, NewSubstring(CordRep::Ref(node), offset, n));
- }
+ if (n > 0) subnode = Concat(subnode, NewSubstring(Ref(node), offset, n));
const char* data =
- node->IsExternal() ? node->external()->base : node->flat()->Data();
+ node->tag == EXTERNAL ? node->external()->base : node->data;
current_chunk_ = absl::string_view(data + offset + n, length - n);
current_leaf_ = node;
bytes_remaining_ -= n;
- subcord.contents_.EmplaceTree(VerifyTree(subnode), method);
+ subcord.contents_.set_tree(VerifyTree(subnode));
return subcord;
}
@@ -1654,19 +1665,12 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
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();
+ 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;
@@ -1681,10 +1685,10 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
// Walk down the appropriate branches until we hit a non-CONCAT node. Save the
// right children to the stack for subsequent traversal.
- while (node->IsConcat()) {
+ while (node->tag == CONCAT) {
if (node->concat()->left->length > n) {
// Push right, descend left.
- stack_of_right_children.push_back(node->concat()->right);
+ stack_of_right_children_.push_back(node->concat()->right);
node = node->concat()->left;
} else {
// Skip left, descend right.
@@ -1697,22 +1701,22 @@ void Cord::ChunkIterator::AdvanceBytesSlowPath(size_t n) {
// Get the child node if we encounter a SUBSTRING.
size_t offset = 0;
size_t length = node->length;
- if (node->IsSubstring()) {
+ if (node->tag == SUBSTRING) {
offset = node->substring()->start;
node = node->substring()->child;
}
- assert(node->IsExternal() || node->IsFlat());
+ assert(node->tag == EXTERNAL || node->tag >= FLAT);
assert(length > n);
const char* data =
- node->IsExternal() ? node->external()->base : node->flat()->Data();
+ node->tag == EXTERNAL ? node->external()->base : node->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());
+ assert(i < size());
size_t offset = i;
const CordRep* rep = contents_.tree();
if (rep == nullptr) {
@@ -1721,15 +1725,13 @@ char Cord::operator[](size_t i) const {
while (true) {
assert(rep != nullptr);
assert(offset < rep->length);
- if (rep->IsFlat()) {
+ if (rep->tag >= FLAT) {
// Get the "i"th character directly from the flat array.
- return rep->flat()->Data()[offset];
- } else if (rep->IsBtree()) {
- return rep->btree()->GetCharacter(offset);
- } else if (rep->IsExternal()) {
+ return rep->data[offset];
+ } else if (rep->tag == EXTERNAL) {
// Get the "i"th character from the external array.
return rep->external()->base[offset];
- } else if (rep->IsConcat()) {
+ } 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;
@@ -1741,7 +1743,7 @@ char Cord::operator[](size_t i) const {
}
} else {
// This must be a substring a node, so bypass it to get to the child.
- assert(rep->IsSubstring());
+ assert(rep->tag == SUBSTRING);
offset += rep->substring()->start;
rep = rep->substring()->child;
}
@@ -1749,7 +1751,6 @@ char Cord::operator[](size_t i) const {
}
absl::string_view Cord::FlattenSlowPath() {
- assert(contents_.is_tree());
size_t total_size = size();
CordRep* new_rep;
char* new_buffer;
@@ -1757,9 +1758,9 @@ absl::string_view Cord::FlattenSlowPath() {
// 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 = NewFlat(total_size);
new_rep->length = total_size;
- new_buffer = new_rep->flat()->Data();
+ new_buffer = new_rep->data;
CopyToArraySlowPath(new_buffer);
} else {
new_buffer = std::allocator<char>().allocate(total_size);
@@ -1770,35 +1771,29 @@ absl::string_view Cord::FlattenSlowPath() {
s.size());
});
}
- CordzUpdateScope scope(contents_.cordz_info(), CordzUpdateTracker::kFlatten);
- CordRep::Unref(contents_.as_tree());
- contents_.SetTree(new_rep, scope);
+ Unref(contents_.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->IsFlat()) {
- *fragment = absl::string_view(rep->flat()->Data(), rep->length);
+ if (rep->tag >= FLAT) {
+ *fragment = absl::string_view(rep->data, rep->length);
return true;
- } else if (rep->IsExternal()) {
+ } else if (rep->tag == EXTERNAL) {
*fragment = absl::string_view(rep->external()->base, rep->length);
return true;
- } else if (rep->IsBtree()) {
- return rep->btree()->IsFlat(fragment);
- } else if (rep->IsSubstring()) {
+ } else if (rep->tag == SUBSTRING) {
CordRep* child = rep->substring()->child;
- if (child->IsFlat()) {
- *fragment = absl::string_view(
- child->flat()->Data() + rep->substring()->start, rep->length);
+ if (child->tag >= FLAT) {
+ *fragment =
+ absl::string_view(child->data + rep->substring()->start, rep->length);
return true;
- } else if (child->IsExternal()) {
+ } else if (child->tag == EXTERNAL) {
*fragment = absl::string_view(
child->external()->base + rep->substring()->start, rep->length);
return true;
- } else if (child->IsBtree()) {
- return child->btree()->IsFlat(rep->substring()->start, rep->length,
- fragment);
}
}
return false;
@@ -1807,15 +1802,6 @@ absl::string_view Cord::FlattenSlowPath() {
/* static */ void Cord::ForEachChunkAux(
absl::cord_internal::CordRep* rep,
absl::FunctionRef<void(absl::string_view)> callback) {
- if (rep->IsBtree()) {
- ChunkIterator it(rep), end;
- while (it != end) {
- callback(*it);
- ++it;
- }
- return;
- }
-
assert(rep != nullptr);
int stack_pos = 0;
constexpr int stack_max = 128;
@@ -1823,7 +1809,7 @@ absl::string_view Cord::FlattenSlowPath() {
absl::cord_internal::CordRep* stack[stack_max];
absl::cord_internal::CordRep* current_node = rep;
while (true) {
- if (current_node->IsConcat()) {
+ 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
@@ -1857,9 +1843,9 @@ absl::string_view Cord::FlattenSlowPath() {
}
}
-static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
- int indent) {
+static void DumpNode(CordRep* rep, bool include_data, std::ostream* os) {
const int kIndentStep = 1;
+ int indent = 0;
absl::InlinedVector<CordRep*, kInlinedVectorSize> stack;
absl::InlinedVector<int, kInlinedVectorSize> indents;
for (;;) {
@@ -1870,29 +1856,27 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os,
*os << "]";
*os << " " << (IsRootBalanced(rep) ? 'b' : 'u');
*os << " " << std::setw(indent) << "";
- if (rep->IsConcat()) {
+ 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->IsSubstring()) {
+ } else if (rep->tag == SUBSTRING) {
*os << "SUBSTRING @ " << rep->substring()->start << "\n";
indent += kIndentStep;
rep = rep->substring()->child;
- } else { // Leaf or ring
- if (rep->IsExternal()) {
+ } else { // Leaf
+ if (rep->tag == EXTERNAL) {
*os << "EXTERNAL [";
if (include_data)
*os << absl::CEscape(std::string(rep->external()->base, rep->length));
*os << "]\n";
- } else if (rep->IsFlat()) {
- *os << "FLAT cap=" << rep->flat()->Capacity() << " [";
+ } else {
+ *os << "FLAT cap=" << TagToLength(rep->tag) << " [";
if (include_data)
- *os << absl::CEscape(std::string(rep->flat()->Data(), rep->length));
+ *os << absl::CEscape(std::string(rep->data, rep->length));
*os << "]\n";
- } else {
- CordRepBtree::Dump(rep, /*label=*/ "", include_data, *os);
}
if (stack.empty()) break;
rep = stack.back();
@@ -1924,7 +1908,7 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
ABSL_INTERNAL_CHECK(node->length != 0, ReportError(root, node));
}
- if (node->IsConcat()) {
+ if (node->tag == CONCAT) {
ABSL_INTERNAL_CHECK(node->concat()->left != nullptr,
ReportError(root, node));
ABSL_INTERNAL_CHECK(node->concat()->right != nullptr,
@@ -1936,13 +1920,13 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
worklist.push_back(node->concat()->right);
worklist.push_back(node->concat()->left);
}
- } else if (node->IsFlat()) {
- ABSL_INTERNAL_CHECK(node->length <= node->flat()->Capacity(),
+ } else if (node->tag >= FLAT) {
+ ABSL_INTERNAL_CHECK(node->length <= TagToLength(node->tag),
ReportError(root, node));
- } else if (node->IsExternal()) {
+ } else if (node->tag == EXTERNAL) {
ABSL_INTERNAL_CHECK(node->external()->base != nullptr,
ReportError(root, node));
- } else if (node->IsSubstring()) {
+ } else if (node->tag == SUBSTRING) {
ABSL_INTERNAL_CHECK(
node->substring()->start < node->substring()->child->length,
ReportError(root, node));
@@ -1971,7 +1955,7 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
while (true) {
const CordRep* next_node = nullptr;
- if (cur_node->IsConcat()) {
+ if (cur_node->tag == CONCAT) {
total_mem_usage += sizeof(CordRepConcat);
const CordRep* left = cur_node->concat()->left;
if (!RepMemoryUsageLeaf(left, &total_mem_usage)) {
@@ -1985,21 +1969,9 @@ static bool VerifyNode(CordRep* root, CordRep* start_node,
}
next_node = right;
}
- } else if (cur_node->IsBtree()) {
- total_mem_usage += sizeof(CordRepBtree);
- const CordRepBtree* node = cur_node->btree();
- if (node->height() == 0) {
- for (const CordRep* edge : node->Edges()) {
- RepMemoryUsageDataEdge(edge, &total_mem_usage);
- }
- } else {
- for (const CordRep* edge : node->Edges()) {
- tree_stack.push_back(edge);
- }
- }
} else {
// Since cur_node is not a leaf or a concat node it must be a substring.
- assert(cur_node->IsSubstring());
+ assert(cur_node->tag == SUBSTRING);
total_mem_usage += sizeof(CordRepSubstring);
next_node = cur_node->substring()->child;
if (RepMemoryUsageLeaf(next_node, &total_mem_usage)) {
@@ -2026,14 +1998,14 @@ std::ostream& operator<<(std::ostream& out, const Cord& cord) {
}
namespace strings_internal {
-size_t CordTestAccess::FlatOverhead() { return cord_internal::kFlatOverhead; }
-size_t CordTestAccess::MaxFlatLength() { return cord_internal::kMaxFlatLength; }
+size_t CordTestAccess::FlatOverhead() { return kFlatOverhead; }
+size_t CordTestAccess::MaxFlatLength() { return kMaxFlatLength; }
size_t CordTestAccess::FlatTagToLength(uint8_t tag) {
- return cord_internal::TagToLength(tag);
+ return 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);
+ return AllocatedSizeToTag(s + kFlatOverhead);
}
size_t CordTestAccess::SizeofCordRepConcat() { return sizeof(CordRepConcat); }
size_t CordTestAccess::SizeofCordRepExternal() {
diff --git a/third_party/abseil-cpp/absl/strings/cord.h b/third_party/abseil-cpp/absl/strings/cord.h
index f0a1991471..40566cbaa0 100644
--- a/third_party/abseil-cpp/absl/strings/cord.h
+++ b/third_party/abseil-cpp/absl/strings/cord.h
@@ -11,52 +11,25 @@
// WITHOUT 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 Cord is a sequence of characters with some unusual access propreties.
+// A Cord supports efficient insertions and deletions at the start and end of
+// the byte sequence, but random access reads are slower, and random access
+// modifications are not supported by the API. Cord also provides cheap copies
+// (using a copy-on-write strategy) and cheap substring operations.
//
-// -----------------------------------------------------------------------------
-// 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
-//
+// 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.
+// particular, if no thread may call a non-const method, then it is safe to
+// concurrently call const methods. Copying a Cord produces a new instance that
+// can be used concurrently with the original in arbitrary ways.
+//
+// Implementation is similar to the "Ropes" described in:
+// Ropes: An alternative to strings
+// Hans J. Boehm, Russ Atkinson, Michael Plass
+// Software Practice and Experience, December 1995
#ifndef ABSL_STRINGS_CORD_H_
#define ABSL_STRINGS_CORD_H_
@@ -65,13 +38,12 @@
#include <cstddef>
#include <cstdint>
#include <cstring>
-#include <iosfwd>
+#include <iostream>
#include <iterator>
#include <string>
-#include <type_traits>
-#include "absl/base/config.h"
#include "absl/base/internal/endian.h"
+#include "absl/base/internal/invoke.h"
#include "absl/base/internal/per_thread_tls.h"
#include "absl/base/macros.h"
#include "absl/base/port.h"
@@ -79,18 +51,8 @@
#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_btree.h"
-#include "absl/strings/internal/cord_rep_btree_reader.h"
-#include "absl/strings/internal/cord_rep_ring.h"
-#include "absl/strings/internal/cordz_functions.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_scope.h"
-#include "absl/strings/internal/cordz_update_tracker.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
@@ -99,35 +61,12 @@ class CordTestPeer;
template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view, Releaser&&);
void CopyCordToString(const Cord& src, std::string* dst);
+namespace hash_internal {
+template <typename H>
+H HashFragmentedCord(H, const Cord&);
+}
-// 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.
-//
+// A Cord is a sequence of characters.
class Cord {
private:
template <typename T>
@@ -135,53 +74,51 @@ class Cord {
absl::enable_if_t<std::is_same<T, std::string>::value, int>;
public:
- // Cord::Cord() Constructors.
+ // --------------------------------------------------------------------
+ // Constructors, destructors and helper factories
- // Creates an empty Cord.
+ // Create 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 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`.
+ // Create a cord out of "src". This constructor is explicit on
+ // purpose so that people do not get automatic type conversions.
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*`.
+ // These are templated to avoid ambiguities for types that are convertible to
+ // both `absl::string_view` and `std::string`, such as `const char*`.
+ //
+ // Note that these functions reserve the right to reuse the `string&&`'s
+ // memory and that they will do so in the future.
template <typename T, EnableIfString<T> = 0>
- explicit Cord(T&& src);
+ explicit Cord(T&& src) : Cord(absl::string_view(src)) {}
template <typename T, EnableIfString<T> = 0>
Cord& operator=(T&& src);
- // Cord::~Cord()
- //
- // Destructs the Cord.
+ // Destroy 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.
+ // Creates a Cord that takes ownership of external memory. The contents of
+ // `data` are not copied.
//
- // `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()`
+ // This function takes a callable that is invoked when all Cords are
+ // finished with `data`. The data must remain live and unchanging until the
+ // releaser is called. The requirements for the releaser are that it:
+ // * is move constructible,
+ // * supports `void operator()(absl::string_view) const`,
+ // * does not have alignment requirement greater than what is guaranteed by
+ // ::operator new. This is dictated by alignof(std::max_align_t) before
+ // C++17 and __STDCPP_DEFAULT_NEW_ALIGNMENT__ if compiling with C++17 or
+ // it is supported by the implementation.
//
// Example:
//
@@ -190,13 +127,13 @@ class Cord {
// FillBlock(block);
// return absl::MakeCordFromExternal(
// block->ToStringView(),
- // [pool, block](absl::string_view v) {
- // pool->FreeBlock(block, v);
+ // [pool, block](absl::string_view /*ignored*/) {
+ // pool->FreeBlock(block);
// });
// }
//
- // 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:
+ // WARNING: 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),
@@ -210,141 +147,97 @@ class Cord {
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.
+ // --------------------------------------------------------------------
+ // Mutations
+
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
+ // 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;
+ friend void swap(Cord& x, Cord& y) noexcept;
- // swap()
- //
- // Swaps the contents of two Cords.
- friend void swap(Cord& x, Cord& y) noexcept { x.swap(y); }
+ // --------------------------------------------------------------------
+ // Accessors
- // 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.
+ // Returns the approximate number of bytes pinned by this Cord. 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:
- //
+ // --------------------------------------------------------------------
+ // Comparators
+
+ // Compares 'this' Cord with rhs. This function and its relatives
+ // treat Cords as sequences of unsigned bytes. The comparison is a
+ // straightforward lexicographic comparison. Return value:
// -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`.
+ // Does 'this' cord start/end with 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.
+ // --------------------------------------------------------------------
+ // Conversion to other types
+
explicit operator std::string() const;
- // CopyCordToString()
+ // Copies the contents from `src` to `*dst`.
//
- // Copies the contents of a `src` Cord into a `*dst` string.
- //
- // This function optimizes the case of reusing the destination string since it
+ // This function optimizes the case of reusing the destination std::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);
+ // --------------------------------------------------------------------
+ // Iteration
+
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:
+ // Type for iterating over the chunks of a `Cord`. See comments for
+ // `Cord::chunk_begin()`, `Cord::chunk_end()` and `Cord::Chunks()` below for
+ // preferred usage.
//
- // * The iterator is invalidated after any non-const operation on the
- // Cord object over which it iterates.
+ // Additional notes:
// * 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
+ // * A `ChunkIterator` object is invalidated after any non-const
+ // operation on the `Cord` object over which it iterates.
+ // * Two `ChunkIterator` objects can be equality compared if and only if
+ // they remain valid and iterate over the same `Cord`.
+ // * This is a proxy iterator. This means 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 issues,
+ // `ChunkIterator::reference` is not a true reference type and is
+ // equivalent to `value_type`.
+ // * The iterator keeps state that can grow for `Cord`s that contain many
// nodes and are imbalanced due to sharing. Prefer to pass this type by
// const reference instead of by value.
class ChunkIterator {
@@ -368,38 +261,14 @@ class Cord {
friend class CharIterator;
private:
- using CordRep = absl::cord_internal::CordRep;
- using CordRepBtree = absl::cord_internal::CordRepBtree;
- using CordRepBtreeReader = absl::cord_internal::CordRepBtreeReader;
-
- // 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();
-
- // Btree specific operator++
- ChunkIterator& AdvanceBtree();
- void AdvanceBytesBtree(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);
@@ -413,21 +282,14 @@ class Cord {
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 cord btrees. Empty if not traversing a btree.
- CordRepBtreeReader btree_reader_;
-
- // See 'Stack' alias definition.
- Stack stack_of_right_children_;
+ absl::InlinedVector<absl::cord_internal::CordRep*, 4>
+ 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.
+ // This is useful for getting a `ChunkIterator` outside the context of a
+ // range-based for-loop (in which case see `Cord::Chunks()` below).
//
// Example:
//
@@ -436,40 +298,15 @@ class Cord {
// 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.
+ // Convenience wrapper over `Cord::chunk_begin()` and `Cord::chunk_end()` to
+ // enable range-based for-loop iteration over `Cord` chunks.
//
- // Implementation note: `ChunkRange` is simply a convenience wrapper over
- // `Cord::chunk_begin()` and `Cord::chunk_end()`.
+ // Prefer to use `Cord::Chunks()` below instead of constructing this directly.
class ChunkRange {
public:
- // Fulfill minimum c++ container requirements [container.requirements]
- // Theses (partial) container type definitions allow ChunkRange to be used
- // in various utilities expecting a subset of [container.requirements].
- // For example, the below enables using `::testing::ElementsAre(...)`
- using value_type = absl::string_view;
- using reference = value_type&;
- using const_reference = const value_type&;
- using iterator = ChunkIterator;
- using const_iterator = ChunkIterator;
-
explicit ChunkRange(const Cord* cord) : cord_(cord) {}
ChunkIterator begin() const;
@@ -479,11 +316,8 @@ class Cord {
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.
+ // Returns a range for iterating over the chunks of a `Cord` with a
+ // range-based for-loop.
//
// Example:
//
@@ -500,30 +334,22 @@ class Cord {
// }
ChunkRange Chunks() const;
- //----------------------------------------------------------------------------
- // Cord::CharIterator
- //----------------------------------------------------------------------------
- //
- // A `Cord::CharIterator` allows iteration over the constituent characters of
- // a `Cord`.
+ // Type for iterating over the characters of a `Cord`. See comments for
+ // `Cord::char_begin()`, `Cord::char_end()` and `Cord::Chars()` below for
+ // preferred usage.
//
- // 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
+ // Additional notes:
+ // * A `CharIterator` object is invalidated after any non-const
+ // operation on the `Cord` object over which it iterates.
+ // * Two `CharIterator` objects can be equality compared if and only if
+ // they remain valid and iterate over the same `Cord`.
+ // * The iterator keeps state that can grow for `Cord`s 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.
+ // * This type cannot be a forward iterator because a `Cord` can reuse
+ // sections of memory. This violates the requirement that if dereferencing
+ // two iterators returns the same object, the iterators must compare
+ // equal.
class CharIterator {
public:
using iterator_category = std::input_iterator_tag;
@@ -549,68 +375,36 @@ class Cord {
ChunkIterator chunk_iterator_;
};
- // Cord::CharIterator::AdvanceAndRead()
+ // Advances `*it` by `n_bytes` and returns the bytes passed as a `Cord`.
//
- // 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`.
+ // `n_bytes` must be less than or equal to the number of bytes remaining for
+ // iteration. Otherwise the 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 `*it` by `n_bytes`.
//
- // 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`.
+ // `n_bytes` must be less than or equal to the number of bytes remaining for
+ // iteration. Otherwise the 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
+ // Convenience wrapper over `Cord::char_begin()` and `Cord::char_end()` to
+ // enable range-based for-loop iterator over the characters of a `Cord`.
//
- // `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()`.
+ // Prefer to use `Cord::Chars()` below instead of constructing this directly.
class CharRange {
public:
- // Fulfill minimum c++ container requirements [container.requirements]
- // Theses (partial) container type definitions allow CharRange to be used
- // in various utilities expecting a subset of [container.requirements].
- // For example, the below enables using `::testing::ElementsAre(...)`
- using value_type = char;
- using reference = value_type&;
- using const_reference = const value_type&;
- using iterator = CharIterator;
- using const_iterator = CharIterator;
-
explicit CharRange(const Cord* cord) : cord_(cord) {}
CharIterator begin() const;
@@ -620,11 +414,8 @@ class Cord {
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.
+ // Returns a range for iterating over the characters of a `Cord` with a
+ // range-based for-loop.
//
// Example:
//
@@ -641,73 +432,32 @@ class Cord {
// }
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;
+ // --------------------------------------------------------------------
+ // Miscellaneous
- // Cord::TryFlat()
+ // Get the "i"th character of 'this' and return it.
+ // NOTE: This routine is reasonably efficient. It is roughly
+ // logarithmic in the number of nodes that make up the cord. Still,
+ // if you need to iterate over the contents of a cord, you should
+ // use a CharIterator/CordIterator rather than call operator[] or Get()
+ // repeatedly in a loop.
//
- // 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;
+ // REQUIRES: 0 <= i < size()
+ char operator[](size_t i) 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:
- using CordRep = absl::cord_internal::CordRep;
- using CordRepFlat = absl::cord_internal::CordRepFlat;
- using CordzInfo = cord_internal::CordzInfo;
- using CordzUpdateScope = cord_internal::CordzUpdateScope;
- using CordzUpdateTracker = cord_internal::CordzUpdateTracker;
- using InlineData = cord_internal::InlineData;
- using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
-
- // Creates a cord instance with `method` representing the originating
- // public API call causing the cord to be created.
- explicit Cord(absl::string_view src, MethodIdentifier method);
-
friend class CordTestPeer;
+ template <typename H>
+ friend H absl::hash_internal::HashFragmentedCord(H, const Cord&);
friend bool operator==(const Cord& lhs, const Cord& rhs);
friend bool operator==(const Cord& lhs, absl::string_view rhs);
- friend const CordzInfo* GetCordzInfoForTesting(const Cord& cord);
-
- // Calls the provided function once for each cord chunk, in order. Unlike
+ // Call 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;
@@ -719,92 +469,60 @@ class Cord {
// 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.
+ // InlineRep holds either either a tree pointer, or an array of kMaxInline
+ // bytes.
class InlineRep {
public:
- static constexpr unsigned char kMaxInline = cord_internal::kMaxInline;
+ static const unsigned char kMaxInline = 15;
static_assert(kMaxInline >= sizeof(absl::cord_internal::CordRep*), "");
+ // Tag byte & kMaxInline means we are storing a pointer.
+ static const unsigned char kTreeFlag = 1 << 4;
+ // Tag byte & kProfiledFlag means we are profiling the Cord.
+ static const unsigned char kProfiledFlag = 1 << 5;
- constexpr InlineRep() : data_() {}
- explicit InlineRep(InlineData::DefaultInitType init) : data_(init) {}
+ 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
+ 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.
- void reduce_size(size_t n); // REQUIRES: holding data
+ // Convert 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(absl::string_view src, MethodIdentifier method);
+ void AppendArray(const char* src_data, size_t src_size);
absl::string_view FindFlatStartPiece() const;
-
- // Creates a CordRepFlat instance from the current inlined data with `extra'
- // bytes of desired additional capacity.
- CordRepFlat* MakeFlatWithExtraCapacity(size_t extra);
-
- // Sets the tree value for this instance. `rep` must not be null.
- // Requires the current instance to hold a tree, and a lock to be held on
- // any CordzInfo referenced by this instance. The latter is enforced through
- // the CordzUpdateScope argument. If the current instance is sampled, then
- // the CordzInfo instance is updated to reference the new `rep` value.
- void SetTree(CordRep* rep, const CordzUpdateScope& scope);
-
- // Identical to SetTree(), except that `rep` is allowed to be null, in
- // which case the current instance is reset to an empty value.
- void SetTreeOrEmpty(CordRep* rep, const CordzUpdateScope& scope);
-
- // Sets the tree value for this instance, and randomly samples this cord.
- // This function disregards existing contents in `data_`, and should be
- // called when a Cord is 'promoted' from an 'uninitialized' or 'inlined'
- // value to a non-inlined (tree / ring) value.
- void EmplaceTree(CordRep* rep, MethodIdentifier method);
-
- // Identical to EmplaceTree, except that it copies the parent stack from
- // the provided `parent` data if the parent is sampled.
- void EmplaceTree(CordRep* rep, const InlineData& parent,
- MethodIdentifier method);
-
- // Commits the change of a newly created, or updated `rep` root value into
- // this cord. `old_rep` indicates the old (inlined or tree) value of the
- // cord, and determines if the commit invokes SetTree() or EmplaceTree().
- void CommitTree(const CordRep* old_rep, CordRep* rep,
- const CordzUpdateScope& scope, MethodIdentifier method);
-
- void AppendTreeToInlined(CordRep* tree, MethodIdentifier method);
- void AppendTreeToTree(CordRep* tree, MethodIdentifier method);
- void AppendTree(CordRep* tree, MethodIdentifier method);
- void PrependTreeToInlined(CordRep* tree, MethodIdentifier method);
- void PrependTreeToTree(CordRep* tree, MethodIdentifier method);
- void PrependTree(CordRep* tree, MethodIdentifier method);
-
- template <bool has_length>
- void GetAppendRegion(char** region, size_t* size, size_t length);
-
+ 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;
+ 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));
+ // Use memcpy to avoid anti-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));
+ memcpy(&x, data_ + 8, sizeof(x));
+ memcpy(&y, other.data_ + 8, sizeof(y));
if (x == y) return 0;
}
return absl::big_endian::FromHost64(x) < absl::big_endian::FromHost64(y)
@@ -813,62 +531,43 @@ class Cord {
}
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
+ // platforms, the small std::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);
+ 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());
+ dst->erase(data_[kMaxInline]);
}
// 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(); }
+ bool is_tree() const { return data_[kMaxInline] > kMaxInline; }
private:
friend class Cord;
void AssignSlow(const InlineRep& src);
- // Unrefs the tree and stops profiling.
- void UnrefTree();
-
- void ResetToEmpty() { data_ = {}; }
+ // Unrefs the tree, stops profiling, and zeroes the contents
+ void ClearSlow();
- 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_;
+ // If the data has length <= kMaxInline, we store it in data_[0..len-1],
+ // and store the length in data_[kMaxInline]. Else we store it in a tree
+ // and store a pointer to that tree in data_[0..sizeof(CordRep*)-1].
+ alignas(absl::cord_internal::CordRep*) char data_[kMaxInline + 1];
};
InlineRep contents_;
- // Helper for MemoryUsage().
+ // Helper for MemoryUsage()
static size_t MemoryUsageAux(const absl::cord_internal::CordRep* rep);
- // Helper for GetFlat() and TryFlat().
+ // Helper for GetFlat()
static bool GetFlatAux(absl::cord_internal::CordRep* rep,
absl::string_view* fragment);
- // Helper for ForEachChunk().
+ // Helper for ForEachChunk()
static void ForEachChunkAux(
absl::cord_internal::CordRep* rep,
absl::FunctionRef<void(absl::string_view)> callback);
@@ -897,28 +596,9 @@ class Cord {
absl::cord_internal::CordRep* TakeRep() const&;
absl::cord_internal::CordRep* TakeRep() &&;
- // Helper for Append().
+ // Helper for Append()
template <typename C>
void AppendImpl(C&& src);
-
- // Prepends the provided data to this instance. `method` contains the public
- // API method for this action which is tracked for Cordz sampling purposes.
- void PrependArray(absl::string_view src, MethodIdentifier method);
-
- // Assigns the value in 'src' to this instance, 'stealing' its contents.
- // Requires src.length() > kMaxBytesToCopy.
- Cord& AssignLargeString(std::string&& 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
@@ -975,27 +655,52 @@ inline void SmallMemmove(char* dst, const char* src, size_t n,
}
}
-// Does non-template-specific `CordRepExternal` initialization.
+struct ExternalRepReleaserPair {
+ CordRep* rep;
+ void* releaser_address;
+};
+
+// Allocates a new external `CordRep` and returns a pointer to it and a pointer
+// to `releaser_size` bytes where the desired releaser can be constructed.
// Expects `data` to be non-empty.
-void InitializeCordRepExternal(absl::string_view data, CordRepExternal* rep);
+ExternalRepReleaserPair NewExternalWithUninitializedReleaser(
+ absl::string_view data, ExternalReleaserInvoker invoker,
+ size_t releaser_size);
// 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) {
+ static_assert(
+#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ alignof(Releaser) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__,
+#else
+ alignof(Releaser) <= alignof(max_align_t),
+#endif
+ "Releasers with alignment requirement greater than what is returned by "
+ "default `::operator new()` are not supported.");
+
using ReleaserType = absl::decay_t<Releaser>;
if (data.empty()) {
// Never create empty external nodes.
- InvokeReleaser(Rank0{}, ReleaserType(std::forward<Releaser>(releaser)),
- data);
+ ::absl::base_internal::Invoke(
+ ReleaserType(std::forward<Releaser>(releaser)), data);
return nullptr;
}
- CordRepExternal* rep = new CordRepExternalImpl<ReleaserType>(
- std::forward<Releaser>(releaser), 0);
- InitializeCordRepExternal(data, rep);
- return rep;
+ auto releaser_invoker = [](void* type_erased_releaser, absl::string_view d) {
+ auto* my_releaser = static_cast<ReleaserType*>(type_erased_releaser);
+ ::absl::base_internal::Invoke(std::move(*my_releaser), d);
+ my_releaser->~ReleaserType();
+ return sizeof(Releaser);
+ };
+
+ ExternalRepReleaserPair external = NewExternalWithUninitializedReleaser(
+ data, releaser_invoker, sizeof(releaser));
+ ::new (external.releaser_address)
+ ReleaserType(std::forward<Releaser>(releaser));
+ return external.rep;
}
// Overload for function reference types that dispatches using a function
@@ -1011,29 +716,18 @@ inline CordRep* NewExternalRep(absl::string_view data,
template <typename Releaser>
Cord MakeCordFromExternal(absl::string_view data, Releaser&& releaser) {
Cord cord;
- if (auto* rep = ::absl::cord_internal::NewExternalRep(
- data, std::forward<Releaser>(releaser))) {
- cord.contents_.EmplaceTree(rep,
- Cord::MethodIdentifier::kMakeCordFromExternal);
- }
+ 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_(InlineData::kDefaultInit) {
- if (CordRep* tree = src.tree()) {
- EmplaceTree(CordRep::Ref(tree), src.data_,
- CordzUpdateTracker::kConstructorCord);
- } else {
- data_ = src.data_;
- }
+inline Cord::InlineRep::InlineRep(const Cord::InlineRep& src) {
+ cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
}
-inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) : data_(src.data_) {
- src.ResetToEmpty();
+inline Cord::InlineRep::InlineRep(Cord::InlineRep&& src) {
+ memcpy(data_, src.data_, sizeof(data_));
+ memset(src.data_, 0, sizeof(data_));
}
inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
@@ -1041,7 +735,7 @@ inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
return *this;
}
if (!is_tree() && !src.is_tree()) {
- data_ = src.data_;
+ cord_internal::SmallMemmove(data_, src.data_, sizeof(data_));
return *this;
}
AssignSlow(src);
@@ -1051,10 +745,10 @@ inline Cord::InlineRep& Cord::InlineRep::operator=(const Cord::InlineRep& src) {
inline Cord::InlineRep& Cord::InlineRep::operator=(
Cord::InlineRep&& src) noexcept {
if (is_tree()) {
- UnrefTree();
+ ClearSlow();
}
- data_ = src.data_;
- src.ResetToEmpty();
+ memcpy(data_, src.data_, sizeof(data_));
+ memset(src.data_, 0, sizeof(data_));
return *this;
}
@@ -1062,143 +756,94 @@ 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();
+ Cord::InlineRep tmp;
+ cord_internal::SmallMemmove(tmp.data_, data_, sizeof(data_));
+ cord_internal::SmallMemmove(data_, rhs->data_, sizeof(data_));
+ cord_internal::SmallMemmove(rhs->data_, tmp.data_, sizeof(data_));
}
-inline absl::cord_internal::CordRep* Cord::InlineRep::as_tree() const {
- assert(data_.is_tree());
- return data_.as_tree();
+inline const char* Cord::InlineRep::data() const {
+ return is_tree() ? nullptr : data_;
}
inline absl::cord_internal::CordRep* Cord::InlineRep::tree() const {
if (is_tree()) {
- return as_tree();
+ absl::cord_internal::CordRep* rep;
+ memcpy(&rep, data_, sizeof(rep));
+ return rep;
} else {
return nullptr;
}
}
-inline bool Cord::InlineRep::empty() const { return data_.is_empty(); }
+inline bool Cord::InlineRep::empty() const { return data_[kMaxInline] == 0; }
inline size_t Cord::InlineRep::size() const {
- return is_tree() ? as_tree()->length : inline_size();
+ const char tag = data_[kMaxInline];
+ if (tag <= kMaxInline) return tag;
+ return static_cast<size_t>(tree()->length);
}
-inline cord_internal::CordRepFlat* Cord::InlineRep::MakeFlatWithExtraCapacity(
- size_t extra) {
- static_assert(cord_internal::kMinFlatLength >= sizeof(data_), "");
- size_t len = data_.inline_size();
- auto* result = CordRepFlat::New(len + extra);
- result->length = len;
- memcpy(result->Data(), data_.as_chars(), sizeof(data_));
- return result;
-}
-
-inline void Cord::InlineRep::EmplaceTree(CordRep* rep,
- MethodIdentifier method) {
- assert(rep);
- data_.make_tree(rep);
- CordzInfo::MaybeTrackCord(data_, method);
-}
-
-inline void Cord::InlineRep::EmplaceTree(CordRep* rep, const InlineData& parent,
- MethodIdentifier method) {
- data_.make_tree(rep);
- CordzInfo::MaybeTrackCord(data_, parent, method);
-}
-
-inline void Cord::InlineRep::SetTree(CordRep* rep,
- const CordzUpdateScope& scope) {
- assert(rep);
- assert(data_.is_tree());
- data_.set_tree(rep);
- scope.SetCordRep(rep);
-}
-
-inline void Cord::InlineRep::SetTreeOrEmpty(CordRep* rep,
- const CordzUpdateScope& scope) {
- assert(data_.is_tree());
- if (rep) {
- data_.set_tree(rep);
+inline void Cord::InlineRep::set_tree(absl::cord_internal::CordRep* rep) {
+ if (rep == nullptr) {
+ memset(data_, 0, sizeof(data_));
} else {
- data_ = {};
+ bool was_tree = is_tree();
+ memcpy(data_, &rep, sizeof(rep));
+ memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
+ if (!was_tree) {
+ data_[kMaxInline] = kTreeFlag;
+ }
}
- scope.SetCordRep(rep);
}
-inline void Cord::InlineRep::CommitTree(const CordRep* old_rep, CordRep* rep,
- const CordzUpdateScope& scope,
- MethodIdentifier method) {
- if (old_rep) {
- SetTree(rep, scope);
- } else {
- EmplaceTree(rep, method);
+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;
}
+ memcpy(data_, &rep, sizeof(rep));
+ memset(data_ + sizeof(rep), 0, sizeof(data_) - sizeof(rep) - 1);
}
inline absl::cord_internal::CordRep* Cord::InlineRep::clear() {
- if (is_tree()) {
- CordzInfo::MaybeUntrackCord(cordz_info());
+ const char tag = data_[kMaxInline];
+ absl::cord_internal::CordRep* result = nullptr;
+ if (tag > kMaxInline) {
+ memcpy(&result, data_, sizeof(result));
}
- absl::cord_internal::CordRep* result = tree();
- ResetToEmpty();
+ memset(data_, 0, sizeof(data_)); // Clear the cord
return result;
}
inline void Cord::InlineRep::CopyToArray(char* dst) const {
assert(!is_tree());
- size_t n = inline_size();
+ size_t n = data_[kMaxInline];
assert(n != 0);
- cord_internal::SmallMemmove(dst, data_.as_chars(), n);
+ cord_internal::SmallMemmove(dst, data_, n);
}
constexpr inline Cord::Cord() noexcept {}
-inline Cord::Cord(absl::string_view src)
- : Cord(src, CordzUpdateTracker::kConstructorString) {}
-
-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;
}
-template <typename T, Cord::EnableIfString<T>>
-Cord& Cord::operator=(T&& src) {
- if (src.size() <= cord_internal::kMaxBytesToCopy) {
- return operator=(absl::string_view(src));
- } else {
- return AssignLargeString(std::forward<T>(src));
- }
-}
-
-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);
+template <typename T, Cord::EnableIfString<T>>
+inline Cord& Cord::operator=(T&& src) {
+ *this = absl::string_view(src);
+ return *this;
+}
inline size_t Cord::size() const {
// Length is 1st field in str.rep_
@@ -1215,18 +860,6 @@ inline size_t Cord::EstimatedMemoryUsage() const {
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) {
@@ -1241,15 +874,22 @@ inline absl::string_view Cord::Flatten() {
}
inline void Cord::Append(absl::string_view src) {
- contents_.AppendArray(src, CordzUpdateTracker::kAppendString);
+ contents_.AppendArray(src.data(), src.size());
}
-inline void Cord::Prepend(absl::string_view src) {
- PrependArray(src, CordzUpdateTracker::kPrependString);
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Append(T&& src) {
+ // Note that this function reserves the right to reuse the `string&&`'s
+ // memory and that it will do so in the future.
+ Append(absl::string_view(src));
}
-extern template void Cord::Append(std::string&& src);
-extern template void Cord::Prepend(std::string&& src);
+template <typename T, Cord::EnableIfString<T>>
+inline void Cord::Prepend(T&& src) {
+ // Note that this function reserves the right to reuse the `string&&`'s
+ // memory and that it will do so in the future.
+ Prepend(absl::string_view(src));
+}
inline int Cord::Compare(const Cord& rhs) const {
if (!contents_.is_tree() && !rhs.contents_.is_tree()) {
@@ -1273,64 +913,17 @@ inline bool Cord::StartsWith(absl::string_view rhs) const {
return EqualsImpl(rhs, rhs_size);
}
-inline void Cord::ChunkIterator::InitTree(cord_internal::CordRep* tree) {
- if (tree->tag == cord_internal::BTREE) {
- current_chunk_ = btree_reader_.Init(tree->btree());
- 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->empty()) return;
if (cord->contents_.is_tree()) {
- InitTree(cord->contents_.as_tree());
+ stack_of_right_children_.push_back(cord->contents_.tree());
+ operator++();
} else {
- current_chunk_ =
- absl::string_view(cord->contents_.data(), bytes_remaining_);
+ current_chunk_ = absl::string_view(cord->contents_.data(), cord->size());
}
}
-inline Cord::ChunkIterator& Cord::ChunkIterator::AdvanceBtree() {
- current_chunk_ = btree_reader_.Next();
- return *this;
-}
-
-inline void Cord::ChunkIterator::AdvanceBytesBtree(size_t n) {
- assert(n >= current_chunk_.size());
- bytes_remaining_ -= n;
- if (bytes_remaining_) {
- if (n == current_chunk_.size()) {
- current_chunk_ = btree_reader_.Next();
- } else {
- size_t offset = btree_reader_.length() - bytes_remaining_;
- current_chunk_ = btree_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 btree_reader_ ? AdvanceBtree() : AdvanceStack();
- } else {
- current_chunk_ = {};
- }
- return *this;
-}
-
inline Cord::ChunkIterator Cord::ChunkIterator::operator++(int) {
ChunkIterator tmp(*this);
operator++();
@@ -1346,12 +939,12 @@ inline bool Cord::ChunkIterator::operator!=(const ChunkIterator& other) const {
}
inline Cord::ChunkIterator::reference Cord::ChunkIterator::operator*() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ assert(bytes_remaining_ != 0);
return current_chunk_;
}
inline Cord::ChunkIterator::pointer Cord::ChunkIterator::operator->() const {
- ABSL_HARDENING_ASSERT(bytes_remaining_ != 0);
+ assert(bytes_remaining_ != 0);
return &current_chunk_;
}
@@ -1362,11 +955,10 @@ inline void Cord::ChunkIterator::RemoveChunkPrefix(size_t 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) {
- btree_reader_ ? AdvanceBytesBtree(n) : AdvanceBytesSlowPath(n);
+ AdvanceBytesSlowPath(n);
}
}
@@ -1466,8 +1058,12 @@ inline bool operator==(const Cord& lhs, const Cord& rhs) {
}
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;
+}
inline bool operator<=(const Cord& x, const Cord& y) {
return x.Compare(y) <= 0;
}
@@ -1502,6 +1098,10 @@ 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); }
+// Overload of swap for Cord. The use of non-const references is
+// required. :(
+inline void swap(Cord& x, Cord& y) noexcept { y.contents_.Swap(&x.contents_); }
+
// Some internals exposed to test code.
namespace strings_internal {
class CordTestAccess {
diff --git a/third_party/abseil-cpp/absl/strings/cord_ring_reader_test.cc b/third_party/abseil-cpp/absl/strings/cord_ring_reader_test.cc
deleted file mode 100644
index d9a9a76d1e..0000000000
--- a/third_party/abseil-cpp/absl/strings/cord_ring_reader_test.cc
+++ /dev/null
@@ -1,180 +0,0 @@
-// 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.node(), Eq(ring->entry_child(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) {
- CordRepRing::index_type index = ring->advance(head, 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(index));
- ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
- 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) {
- CordRepRing::index_type index = ring->advance(head, 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(index));
- ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
- 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) {
- CordRepRing::index_type index = ring->advance(head, 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(index));
- ASSERT_THAT(reader.node(), Eq(ring->entry_child(index)));
- 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/third_party/abseil-cpp/absl/strings/cord_ring_test.cc b/third_party/abseil-cpp/absl/strings/cord_ring_test.cc
deleted file mode 100644
index f131859532..0000000000
--- a/third_party/abseil-cpp/absl/strings/cord_ring_test.cc
+++ /dev/null
@@ -1,1495 +0,0 @@
-// 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;
-
-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 : true;
-}
-
-// 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 : true;
-}
-
-// Matcher validating a shared ring was re-allocated. Should only be used for
-// tests doing exactly one update as subsequent updates could return the
-// original (freed and re-used) pointer.
-MATCHER_P2(NeIfShared, param, rep,
- absl::StrCat("Not equal 0x", absl::Hex(rep), " if shared")) {
- return param.refcount_is_one ? true : 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 = reinterpret_cast<const char*>(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(GTEST_FLAG_GET(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 {
- for (CordRep* rep : unrefs_) {
- CordRep::Unref(rep);
- }
- }
-
- template <typename CordRepType>
- CordRepType* NeedsUnref(CordRepType* rep) {
- assert(rep);
- unrefs_.push_back(rep);
- return rep;
- }
-
- template <typename CordRepType>
- CordRepType* Ref(CordRepType* rep) {
- CordRep::Ref(rep);
- return NeedsUnref(rep);
- }
-
- private:
- std::vector<CordRep*> unrefs_;
-};
-
-class CordRingTestWithParam : public testing::TestWithParam<TestParam> {
- public:
- ~CordRingTestWithParam() override {
- for (CordRep* rep : unrefs_) {
- CordRep::Unref(rep);
- }
- }
-
- 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);
- unrefs_.push_back(rep);
- return rep;
- }
-
- template <typename CordRepType>
- CordRepType* Ref(CordRepType* rep) {
- CordRep::Ref(rep);
- return NeedsUnref(rep);
- }
-
- template <typename CordRepType>
- CordRepType* RefIfShared(CordRepType* rep) {
- return Shared() ? Ref(rep) : rep;
- }
-
- template <typename CordRepType>
- CordRepType* RefIfInputShared(CordRepType* rep) {
- return InputShared() ? Ref(rep) : rep;
- }
-
- template <typename CordRepType>
- CordRepType* RefIfInputSharedIndirect(CordRepType* rep) {
- return InputSharedIndirect() ? Ref(rep) : rep;
- }
-
- private:
- std::vector<CordRep*> unrefs_;
-};
-
-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_SUITE_P(WithParam, CordRingSubTest,
- testing::ValuesIn(CordRingSubTest::CreateTestParams()),
- TestParamToString);
-
-INSTANTIATE_TEST_SUITE_P(
- WithParam, CordRingCreateTest,
- testing::ValuesIn(CordRingCreateTest::CreateTestParams()),
- TestParamToString);
-
-INSTANTIATE_TEST_SUITE_P(
- WithParam, CordRingCreateFromTreeTest,
- testing::ValuesIn(CordRingCreateFromTreeTest::CreateTestParams()),
- TestParamToString);
-
-INSTANTIATE_TEST_SUITE_P(
- WithParam, CordRingBuildTest,
- testing::ValuesIn(CordRingBuildTest::CreateTestParams()),
- TestParamToString);
-
-INSTANTIATE_TEST_SUITE_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));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
-}
-
-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));
-}
-
-TEST_F(CordRingTest, CreateWithIllegalExtraCapacity) {
-#if defined(ABSL_HAVE_EXCEPTIONS)
- CordRep* flat = NeedsUnref(MakeFlat("Hello world"));
- try {
- CordRepRing::Create(flat, CordRepRing::kMaxCapacity);
- GTEST_FAIL() << "expected std::length_error exception";
- } catch (const std::length_error&) {
- }
-#elif defined(GTEST_HAS_DEATH_TEST)
- CordRep* flat = NeedsUnref(MakeFlat("Hello world"));
- EXPECT_DEATH(CordRepRing::Create(flat, CordRepRing::kMaxCapacity), ".*");
-#endif
-}
-
-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)));
-}
-
-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));
-}
-
-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)));
-}
-
-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));
-}
-
-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));
-}
-
-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));
- }
- }
-}
-
-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));
-}
-
-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));
-}
-
-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));
-}
-
-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, NeIfShared(GetParam(), ring));
- EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
- EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
-}
-
-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, NeIfShared(GetParam(), ring));
- EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
- EXPECT_THAT(ToFlats(result), ElementsAre(str2, str1));
-}
-
-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, NeIfShared(GetParam(), ring));
- EXPECT_THAT(result->length, Eq(str1.size() + str2.size()));
- EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
-}
-
-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));
- EXPECT_THAT(result, NeIfShared(GetParam(), ring));
-}
-
-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));
- EXPECT_THAT(result, NeIfShared(GetParam(), ring));
- if (GetParam().refcount_is_one) {
- EXPECT_THAT(ToFlats(result), ElementsAre(StrCat(str1, str1a), str2a));
- } else {
- EXPECT_THAT(ToFlats(result), ElementsAre(str1, str2));
- }
-}
-
-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, NeIfShared(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));
- }
-}
-
-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, NeIfShared(GetParam(), ring));
- EXPECT_THAT(result->length, Eq(4 + str2.size()));
- EXPECT_THAT(ToFlats(result), ElementsAre("1234", str2));
-
- 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)));
-}
-
-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));
-}
-
-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, NeIfShared(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"));
- }
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre(str2, str1a));
- 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));
-}
-
-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]);
- }
- NeedsUnref(result);
- ASSERT_THAT(result, IsValidRingBuffer());
- EXPECT_THAT(result, EqIfPrivateAndCapacity(GetParam(), ring));
- EXPECT_THAT(ToString(result), kFox);
-}
-
-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"));
- }
-}
-
-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"));
- }
-}
-
-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);
-
- 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(result, NeIfShared(GetParam(), ring));
- ASSERT_THAT(ToString(result), Eq(all.substr(offset, len)));
- }
- }
-}
-
-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);
-
- 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));
- ASSERT_THAT(result, NeIfShared(GetParam(), ring));
- auto str = ToString(result);
- ASSERT_THAT(str, SizeIs(len));
- ASSERT_THAT(str, Eq(all.substr(offset, len)));
- }
- }
-}
-
-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);
-
- 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));
- ASSERT_THAT(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToString(result), Eq(all.substr(len)));
- }
-}
-
-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)));
-}
-
-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);
-
- for (size_t len = 1; len < all.size(); ++len) {
- ring = RefIfShared(FromFlats(flats, composition));
- result = NeedsUnref(CordRepRing::RemoveSuffix(ring, len));
- ASSERT_THAT(result, IsValidRingBuffer());
- ASSERT_THAT(result, EqIfPrivate(GetParam(), ring));
- ASSERT_THAT(result, NeIfShared(GetParam(), ring));
- ASSERT_THAT(ToString(result), Eq(all.substr(0, all.size() - len)));
- }
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("Head", "brown ", "fox ", "jumps ",
- "over ", "the ", "lazy ", "dog"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result),
- ElementsAre("Head", "umps ", "over ", "the ", "lazy ", "dog"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("Head", "The ", "quick ", "brown ",
- "fox ", "jumps ", "over ", "the "));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("Head", "The ", "quick ", "brown ",
- "fox ", "jumps ", "ov"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result),
- ElementsAre("Head", "ck ", "brown ", "fox ", "jum"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("Head", "row"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("Prepend", "Head", "row"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAreArray(kFoxFlats));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("brown ", "fox ", "jumps ", "over ",
- "the ", "lazy ", "dog", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result),
- ElementsAre("umps ", "over ", "the ", "lazy ", "dog", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("The ", "quick ", "brown ", "fox ",
- "jumps ", "over ", "the ", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("The ", "quick ", "brown ", "fox ",
- "jumps ", "ov", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result),
- ElementsAre("ck ", "brown ", "fox ", "jum", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("row", "Tail"));
-}
-
-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(result, NeIfShared(GetParam(), ring));
- EXPECT_THAT(ToFlats(result), ElementsAre("row", "Prepend", "Tail"));
-}
-
-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]));
- }
-}
-
-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();
- }
-}
-
-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]));
- }
-}
-
-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]));
- }
-}
-
-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]));
- }
-}
-
-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]));
- }
-}
-
-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]));
- }
-}
-
-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]));
- }
-}
-
-TEST_F(CordRingTest, IsFlatSingleFlat) {
- for (bool external : {false, true}) {
- SCOPED_TRACE(external ? "With External" : "With Flat");
- absl::string_view str = "Hello world";
- CordRep* rep = external ? MakeExternal(str) : MakeFlat(str);
- CordRepRing* ring = NeedsUnref(CordRepRing::Create(rep));
-
- // The ring is a single non-fragmented flat:
- absl::string_view fragment;
- EXPECT_TRUE(ring->IsFlat(nullptr));
- EXPECT_TRUE(ring->IsFlat(&fragment));
- EXPECT_THAT(fragment, Eq("Hello world"));
- fragment = "";
- EXPECT_TRUE(ring->IsFlat(0, 11, nullptr));
- EXPECT_TRUE(ring->IsFlat(0, 11, &fragment));
- EXPECT_THAT(fragment, Eq("Hello world"));
-
- // Arbitrary ranges must check true as well.
- EXPECT_TRUE(ring->IsFlat(1, 4, &fragment));
- EXPECT_THAT(fragment, Eq("ello"));
- EXPECT_TRUE(ring->IsFlat(6, 5, &fragment));
- EXPECT_THAT(fragment, Eq("world"));
- }
-}
-
-TEST_F(CordRingTest, IsFlatMultiFlat) {
- for (bool external : {false, true}) {
- SCOPED_TRACE(external ? "With External" : "With Flat");
- absl::string_view str1 = "Hello world";
- absl::string_view str2 = "Halt and catch fire";
- CordRep* rep1 = external ? MakeExternal(str1) : MakeFlat(str1);
- CordRep* rep2 = external ? MakeExternal(str2) : MakeFlat(str2);
- CordRepRing* ring = CordRepRing::Append(CordRepRing::Create(rep1), rep2);
- NeedsUnref(ring);
-
- // The ring is fragmented, IsFlat() on the entire cord must be false.
- EXPECT_FALSE(ring->IsFlat(nullptr));
- absl::string_view fragment = "Don't touch this";
- EXPECT_FALSE(ring->IsFlat(&fragment));
- EXPECT_THAT(fragment, Eq("Don't touch this"));
-
- // Check for ranges exactly within both flats.
- EXPECT_TRUE(ring->IsFlat(0, 11, &fragment));
- EXPECT_THAT(fragment, Eq("Hello world"));
- EXPECT_TRUE(ring->IsFlat(11, 19, &fragment));
- EXPECT_THAT(fragment, Eq("Halt and catch fire"));
-
- // Check for arbitrary partial range inside each flat.
- EXPECT_TRUE(ring->IsFlat(1, 4, &fragment));
- EXPECT_THAT(fragment, "ello");
- EXPECT_TRUE(ring->IsFlat(26, 4, &fragment));
- EXPECT_THAT(fragment, "fire");
-
- // Check ranges spanning across both flats
- fragment = "Don't touch this";
- EXPECT_FALSE(ring->IsFlat(1, 18, &fragment));
- EXPECT_FALSE(ring->IsFlat(10, 2, &fragment));
- EXPECT_THAT(fragment, Eq("Don't touch this"));
- }
-}
-
-TEST_F(CordRingTest, Dump) {
- std::stringstream ss;
- auto flats = MakeSpan(kFoxFlats);
- CordRepRing* ring = NeedsUnref(FromFlats(flats, kPrepend));
- ss << *ring;
-}
-
-} // namespace
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/cord_test.cc b/third_party/abseil-cpp/absl/strings/cord_test.cc
index cced9bba39..434f3a247e 100644
--- a/third_party/abseil-cpp/absl/strings/cord_test.cc
+++ b/third_party/abseil-cpp/absl/strings/cord_test.cc
@@ -1,17 +1,3 @@
-// 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>
@@ -32,13 +18,9 @@
#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/random/random.h"
#include "absl/strings/cord_test_helpers.h"
-#include "absl/strings/cordz_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;
@@ -88,8 +70,9 @@ static std::string RandomLowercaseString(RandomEngine* rng) {
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)); });
+ std::generate(result.begin(), result.end(), [&]() {
+ return static_cast<char>(chars(*rng));
+ });
return result;
}
@@ -183,60 +166,16 @@ class CordTestPeer {
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();
- }
-
- static Cord MakeSubstring(Cord src, size_t offset, size_t length) {
- ABSL_RAW_CHECK(src.contents_.is_tree(), "Can not be inlined");
- Cord cord;
- auto* rep = new cord_internal::CordRepSubstring;
- rep->tag = cord_internal::SUBSTRING;
- rep->child = cord_internal::CordRep::Ref(src.contents_.tree());
- rep->start = offset;
- rep->length = length;
- cord.contents_.EmplaceTree(rep,
- cord_internal::CordzUpdateTracker::kSubCord);
- return cord;
- }
};
ABSL_NAMESPACE_END
} // namespace absl
-// The CordTest fixture runs all tests with and without Cord Btree enabled.
-class CordTest : public testing::TestWithParam<bool> {
- public:
- CordTest() : was_btree_(absl::cord_internal::cord_btree_enabled.load()) {
- absl::cord_internal::cord_btree_enabled.store(UseBtree());
- }
- ~CordTest() override {
- absl::cord_internal::cord_btree_enabled.store(was_btree_);
- }
-
- // Returns true if test is running with btree enabled.
- bool UseBtree() const { return GetParam(); }
-
- // Returns human readable string representation of the test parameter.
- static std::string ToString(testing::TestParamInfo<bool> param) {
- return param.param ? "Btree" : "Concat";
- }
-
- private:
- const bool was_btree_;
-};
-
-INSTANTIATE_TEST_SUITE_P(WithParam, CordTest, testing::Bool(),
- CordTest::ToString);
-
-TEST_P(CordTest, AllFlatSizes) {
+TEST(Cord, AllFlatSizes) {
using absl::strings_internal::CordTestAccess;
for (size_t s = 0; s < CordTestAccess::MaxFlatLength(); s++) {
- // Make a string of length s.
+ // Make a std::string of length s.
std::string src;
while (src.size() < s) {
src.push_back('a' + (src.size() % 26));
@@ -250,7 +189,7 @@ TEST_P(CordTest, AllFlatSizes) {
// 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_P(CordTest, GigabyteCordFromExternal) {
+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;
@@ -267,6 +206,7 @@ TEST_P(CordTest, GigabyteCordFromExternal) {
// 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);
@@ -299,7 +239,7 @@ static absl::Cord MakeExternalCord(int size) {
extern bool my_unique_true_boolean;
bool my_unique_true_boolean = true;
-TEST_P(CordTest, Assignment) {
+TEST(Cord, Assignment) {
absl::Cord x(absl::string_view("hi there"));
absl::Cord y(x);
ASSERT_EQ(std::string(x), "hi there");
@@ -353,7 +293,7 @@ TEST_P(CordTest, Assignment) {
}
}
-TEST_P(CordTest, StartsEndsWith) {
+TEST(Cord, StartsEndsWith) {
absl::Cord x(absl::string_view("abcde"));
absl::Cord empty("");
@@ -386,13 +326,13 @@ TEST_P(CordTest, StartsEndsWith) {
ASSERT_TRUE(!empty.EndsWith("xyz"));
}
-TEST_P(CordTest, Subcord) {
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+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, std::string(a));
+ ASSERT_EQ(s.size(), a.size());
// Check subcords of a, from a variety of interesting points.
std::set<size_t> positions;
@@ -410,7 +350,7 @@ TEST_P(CordTest, Subcord) {
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),
+ EXPECT_EQ(absl::string_view(s).substr(pos, end_pos - pos),
std::string(sa))
<< a;
}
@@ -422,7 +362,7 @@ TEST_P(CordTest, Subcord) {
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;
+ EXPECT_EQ(sh.substr(pos, n), std::string(sc)) << c;
}
}
@@ -432,7 +372,7 @@ TEST_P(CordTest, Subcord) {
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;
+ EXPECT_EQ(ss, std::string(sa)) << a;
if (HasFailure()) break; // halt cascade
}
@@ -447,7 +387,7 @@ TEST_P(CordTest, Subcord) {
EXPECT_TRUE(sa.empty());
}
-TEST_P(CordTest, Swap) {
+TEST(Cord, Swap) {
absl::string_view a("Dexter");
absl::string_view b("Mandark");
absl::Cord x(a);
@@ -455,9 +395,6 @@ TEST_P(CordTest, Swap) {
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) {
@@ -473,13 +410,13 @@ static void VerifyCopyToString(const absl::Cord& cord) {
if (cord.size() <= kInitialLength) {
EXPECT_EQ(has_initial_contents.data(), address_before_copy)
- << "CopyCordToString allocated new string storage; "
+ << "CopyCordToString allocated new std::string storage; "
"has_initial_contents = \""
<< has_initial_contents << "\"";
}
}
-TEST_P(CordTest, CopyToString) {
+TEST(Cord, CopyToString) {
VerifyCopyToString(absl::Cord());
VerifyCopyToString(absl::Cord("small cord"));
VerifyCopyToString(
@@ -487,80 +424,6 @@ TEST_P(CordTest, CopyToString) {
"copying ", "to ", "a ", "string."}));
}
-TEST_P(CordTest, TryFlatEmpty) {
- absl::Cord c;
- EXPECT_EQ(c.TryFlat(), "");
-}
-
-TEST_P(CordTest, TryFlatFlat) {
- absl::Cord c("hello");
- EXPECT_EQ(c.TryFlat(), "hello");
-}
-
-TEST_P(CordTest, TryFlatSubstrInlined) {
- absl::Cord c("hello");
- c.RemovePrefix(1);
- EXPECT_EQ(c.TryFlat(), "ello");
-}
-
-TEST_P(CordTest, TryFlatSubstrFlat) {
- absl::Cord c("longer than 15 bytes");
- absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
- EXPECT_EQ(sub.TryFlat(), "onger than 15 bytes");
-}
-
-TEST_P(CordTest, TryFlatConcat) {
- absl::Cord c = absl::MakeFragmentedCord({"hel", "lo"});
- EXPECT_EQ(c.TryFlat(), absl::nullopt);
-}
-
-TEST_P(CordTest, TryFlatExternal) {
- absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
- EXPECT_EQ(c.TryFlat(), "hell");
-}
-
-TEST_P(CordTest, TryFlatSubstrExternal) {
- absl::Cord c = absl::MakeCordFromExternal("hell", [](absl::string_view) {});
- absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
- EXPECT_EQ(sub.TryFlat(), "ell");
-}
-
-TEST_P(CordTest, TryFlatSubstrConcat) {
- absl::Cord c = absl::MakeFragmentedCord({"hello", " world"});
- absl::Cord sub = absl::CordTestPeer::MakeSubstring(c, 1, c.size() - 1);
- EXPECT_EQ(sub.TryFlat(), absl::nullopt);
- c.RemovePrefix(1);
- EXPECT_EQ(c.TryFlat(), absl::nullopt);
-}
-
-TEST_P(CordTest, TryFlatCommonlyAssumedInvariants) {
- // The behavior tested below is not part of the API contract of Cord, but it's
- // something we intend to be true in our current implementation. This test
- // exists to detect and prevent accidental breakage of the implementation.
- absl::string_view fragments[] = {"A fragmented test",
- " cord",
- " to test subcords",
- " of ",
- "a",
- " cord for",
- " each chunk "
- "returned by the ",
- "iterator"};
- absl::Cord c = absl::MakeFragmentedCord(fragments);
- int fragment = 0;
- int offset = 0;
- absl::Cord::CharIterator itc = c.char_begin();
- for (absl::string_view sv : c.Chunks()) {
- absl::string_view expected = fragments[fragment];
- absl::Cord subcord1 = c.Subcord(offset, sv.length());
- absl::Cord subcord2 = absl::Cord::AdvanceAndRead(&itc, sv.size());
- EXPECT_EQ(subcord1.TryFlat(), expected);
- EXPECT_EQ(subcord2.TryFlat(), expected);
- ++fragment;
- offset += sv.length();
- }
-}
-
static bool IsFlat(const absl::Cord& c) {
return c.chunk_begin() == c.chunk_end() || ++c.chunk_begin() == c.chunk_end();
}
@@ -589,14 +452,14 @@ static void VerifyFlatten(absl::Cord c) {
EXPECT_TRUE(IsFlat(c));
}
-TEST_P(CordTest, Flatten) {
+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(GTEST_FLAG_GET(random_seed));
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
VerifyFlatten(absl::Cord(RandomLowercaseString(&rng, 8192)));
}
@@ -643,29 +506,29 @@ class TestData {
};
} // namespace
-TEST_P(CordTest, MultipleLengths) {
+TEST(Cord, MultipleLengths) {
TestData d;
for (size_t i = 0; i < d.size(); i++) {
std::string a = d.data(i);
- { // Construct from Cord
+ { // Construct from Cord
absl::Cord tmp(a);
absl::Cord x(tmp);
EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
}
- { // Construct from absl::string_view
+ { // Construct from absl::string_view
absl::Cord x(a);
EXPECT_EQ(a, std::string(x)) << "'" << a << "'";
}
- { // Append cord to self
+ { // Append cord to self
absl::Cord self(a);
self.Append(self);
EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
}
- { // Prepend cord to self
+ { // Prepend cord to self
absl::Cord self(a);
self.Prepend(self);
EXPECT_EQ(a + a, std::string(self)) << "'" << a << "' + '" << a << "'";
@@ -675,40 +538,40 @@ TEST_P(CordTest, MultipleLengths) {
for (size_t j = 0; j < d.size(); j++) {
std::string b = d.data(j);
- { // CopyFrom Cord
+ { // CopyFrom Cord
absl::Cord x(a);
absl::Cord y(b);
x = y;
EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
}
- { // CopyFrom absl::string_view
+ { // CopyFrom absl::string_view
absl::Cord x(a);
x = b;
EXPECT_EQ(b, std::string(x)) << "'" << a << "' + '" << b << "'";
}
- { // Cord::Append(Cord)
+ { // 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)
+ { // Cord::Append(absl::string_view)
absl::Cord x(a);
x.Append(b);
EXPECT_EQ(a + b, std::string(x)) << "'" << a << "' + '" << b << "'";
}
- { // Cord::Prepend(Cord)
+ { // 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)
+ { // Cord::Prepend(absl::string_view)
absl::Cord x(a);
x.Prepend(b);
EXPECT_EQ(b + a, std::string(x)) << "'" << b << "' + '" << a << "'";
@@ -719,7 +582,7 @@ TEST_P(CordTest, MultipleLengths) {
namespace {
-TEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {
+TEST(Cord, RemoveSuffixWithExternalOrSubstring) {
absl::Cord cord = absl::MakeCordFromExternal(
"foo bar baz", [](absl::string_view s) { DoNothing(s, nullptr); });
@@ -734,7 +597,7 @@ TEST_P(CordTest, RemoveSuffixWithExternalOrSubstring) {
EXPECT_EQ("foo", std::string(cord));
}
-TEST_P(CordTest, RemoveSuffixMakesZeroLengthNode) {
+TEST(Cord, RemoveSuffixMakesZeroLengthNode) {
absl::Cord c;
c.Append(absl::Cord(std::string(100, 'x')));
absl::Cord other_ref = c; // Prevent inplace appends
@@ -761,7 +624,7 @@ absl::Cord CordWithZedBlock(size_t size) {
}
// Establish that ZedBlock does what we think it does.
-TEST_P(CordTest, CordSpliceTestZedBlock) {
+TEST(CordSpliceTest, ZedBlock) {
absl::Cord blob = CordWithZedBlock(10);
EXPECT_EQ(10, blob.size());
std::string s;
@@ -769,7 +632,7 @@ TEST_P(CordTest, CordSpliceTestZedBlock) {
EXPECT_EQ("zzzzzzzzzz", s);
}
-TEST_P(CordTest, CordSpliceTestZedBlock0) {
+TEST(CordSpliceTest, ZedBlock0) {
absl::Cord blob = CordWithZedBlock(0);
EXPECT_EQ(0, blob.size());
std::string s;
@@ -777,7 +640,7 @@ TEST_P(CordTest, CordSpliceTestZedBlock0) {
EXPECT_EQ("", s);
}
-TEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {
+TEST(CordSpliceTest, ZedBlockSuffix1) {
absl::Cord blob = CordWithZedBlock(10);
EXPECT_EQ(10, blob.size());
absl::Cord suffix(blob);
@@ -789,7 +652,7 @@ TEST_P(CordTest, CordSpliceTestZedBlockSuffix1) {
}
// Remove all of a prefix block
-TEST_P(CordTest, CordSpliceTestZedBlockSuffix0) {
+TEST(CordSpliceTest, ZedBlockSuffix0) {
absl::Cord blob = CordWithZedBlock(10);
EXPECT_EQ(10, blob.size());
absl::Cord suffix(blob);
@@ -821,7 +684,7 @@ absl::Cord SpliceCord(const absl::Cord& blob, int64_t offset,
}
// Taking an empty suffix of a block breaks appending.
-TEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {
+TEST(CordSpliceTest, RemoveEntireBlock1) {
absl::Cord zero = CordWithZedBlock(10);
absl::Cord suffix(zero);
suffix.RemovePrefix(10);
@@ -829,7 +692,7 @@ TEST_P(CordTest, CordSpliceTestRemoveEntireBlock1) {
result.Append(suffix);
}
-TEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {
+TEST(CordSpliceTest, RemoveEntireBlock2) {
absl::Cord zero = CordWithZedBlock(10);
absl::Cord prefix(zero);
prefix.RemoveSuffix(10);
@@ -839,7 +702,7 @@ TEST_P(CordTest, CordSpliceTestRemoveEntireBlock2) {
result.Append(suffix);
}
-TEST_P(CordTest, CordSpliceTestRemoveEntireBlock3) {
+TEST(CordSpliceTest, RemoveEntireBlock3) {
absl::Cord blob = CordWithZedBlock(10);
absl::Cord block = BigCord(10, 'b');
blob = SpliceCord(blob, 0, block);
@@ -870,7 +733,7 @@ void VerifyComparison(const CordCompareTestCase& test_case) {
<< "LHS=" << rhs_string << "; RHS=" << lhs_string;
}
-TEST_P(CordTest, Compare) {
+TEST(Cord, Compare) {
absl::Cord subcord("aaaaaBBBBBcccccDDDDD");
subcord = subcord.Subcord(3, 10);
@@ -933,7 +796,7 @@ TEST_P(CordTest, Compare) {
}
}
-TEST_P(CordTest, CompareAfterAssign) {
+TEST(Cord, CompareAfterAssign) {
absl::Cord a("aaaaaa1111111");
absl::Cord b("aaaaaa2222222");
a = "cccccc";
@@ -950,7 +813,7 @@ TEST_P(CordTest, CompareAfterAssign) {
}
// Test CompareTo() and ComparePrefix() against string and substring
-// comparison methods from basic_string.
+// comparison methods from std::basic_string.
static void TestCompare(const absl::Cord& c, const absl::Cord& d,
RandomEngine* rng) {
typedef std::basic_string<uint8_t> ustring;
@@ -962,8 +825,8 @@ static void TestCompare(const absl::Cord& c, const absl::Cord& d,
EXPECT_EQ(expected, sign(c.Compare(d))) << c << ", " << d;
}
-TEST_P(CordTest, CompareComparisonIsUnsigned) {
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+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(
@@ -971,9 +834,9 @@ TEST_P(CordTest, CompareComparisonIsUnsigned) {
absl::Cord(std::string(GetUniformRandomUpTo(&rng, 100), x ^ 0x80)), &rng);
}
-TEST_P(CordTest, CompareRandomComparisons) {
+TEST(Compare, RandomComparisons) {
const int kIters = 5000;
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
int n = GetUniformRandomUpTo(&rng, 5000);
absl::Cord a[] = {MakeExternalCord(n),
@@ -1006,7 +869,7 @@ void CompareOperators() {
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.
+ // instead of the std::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);
@@ -1029,43 +892,43 @@ void CompareOperators() {
EXPECT_FALSE(b <= a);
}
-TEST_P(CordTest, ComparisonOperators_Cord_Cord) {
+TEST(ComparisonOperators, Cord_Cord) {
CompareOperators<absl::Cord, absl::Cord>();
}
-TEST_P(CordTest, ComparisonOperators_Cord_StringPiece) {
+TEST(ComparisonOperators, Cord_StringPiece) {
CompareOperators<absl::Cord, absl::string_view>();
}
-TEST_P(CordTest, ComparisonOperators_StringPiece_Cord) {
+TEST(ComparisonOperators, StringPiece_Cord) {
CompareOperators<absl::string_view, absl::Cord>();
}
-TEST_P(CordTest, ComparisonOperators_Cord_string) {
+TEST(ComparisonOperators, Cord_string) {
CompareOperators<absl::Cord, std::string>();
}
-TEST_P(CordTest, ComparisonOperators_string_Cord) {
+TEST(ComparisonOperators, string_Cord) {
CompareOperators<std::string, absl::Cord>();
}
-TEST_P(CordTest, ComparisonOperators_stdstring_Cord) {
+TEST(ComparisonOperators, stdstring_Cord) {
CompareOperators<std::string, absl::Cord>();
}
-TEST_P(CordTest, ComparisonOperators_Cord_stdstring) {
+TEST(ComparisonOperators, Cord_stdstring) {
CompareOperators<absl::Cord, std::string>();
}
-TEST_P(CordTest, ComparisonOperators_charstar_Cord) {
+TEST(ComparisonOperators, charstar_Cord) {
CompareOperators<const char*, absl::Cord>();
}
-TEST_P(CordTest, ComparisonOperators_Cord_charstar) {
+TEST(ComparisonOperators, Cord_charstar) {
CompareOperators<absl::Cord, const char*>();
}
-TEST_P(CordTest, ConstructFromExternalReleaserInvoked) {
+TEST(ConstructFromExternal, ReleaserInvoked) {
// Empty external memory means the releaser should be called immediately.
{
bool invoked = false;
@@ -1107,8 +970,8 @@ TEST_P(CordTest, ConstructFromExternalReleaserInvoked) {
}
}
-TEST_P(CordTest, ConstructFromExternalCompareContents) {
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+TEST(ConstructFromExternal, CompareContents) {
+ RandomEngine rng(testing::GTEST_FLAG(random_seed));
for (int length = 1; length <= 2048; length *= 2) {
std::string data = RandomLowercaseString(&rng, length);
@@ -1123,8 +986,8 @@ TEST_P(CordTest, ConstructFromExternalCompareContents) {
}
}
-TEST_P(CordTest, ConstructFromExternalLargeReleaser) {
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+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;
@@ -1138,7 +1001,7 @@ TEST_P(CordTest, ConstructFromExternalLargeReleaser) {
EXPECT_TRUE(invoked);
}
-TEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {
+TEST(ConstructFromExternal, FunctionPointerReleaser) {
static absl::string_view data("hello world");
static bool invoked;
auto* releaser =
@@ -1155,7 +1018,7 @@ TEST_P(CordTest, ConstructFromExternalFunctionPointerReleaser) {
EXPECT_TRUE(invoked);
}
-TEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {
+TEST(ConstructFromExternal, MoveOnlyReleaser) {
struct Releaser {
explicit Releaser(bool* invoked) : invoked(invoked) {}
Releaser(Releaser&& other) noexcept : invoked(other.invoked) {}
@@ -1169,20 +1032,7 @@ TEST_P(CordTest, ConstructFromExternalMoveOnlyReleaser) {
EXPECT_TRUE(invoked);
}
-TEST_P(CordTest, ConstructFromExternalNoArgLambda) {
- bool invoked = false;
- (void)absl::MakeCordFromExternal("dummy", [&invoked]() { invoked = true; });
- EXPECT_TRUE(invoked);
-}
-
-TEST_P(CordTest, ConstructFromExternalStringViewArgLambda) {
- bool invoked = false;
- (void)absl::MakeCordFromExternal(
- "dummy", [&invoked](absl::string_view) { invoked = true; });
- EXPECT_TRUE(invoked);
-}
-
-TEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {
+TEST(ConstructFromExternal, NonTrivialReleaserDestructor) {
struct Releaser {
explicit Releaser(bool* destroyed) : destroyed(destroyed) {}
~Releaser() { *destroyed = true; }
@@ -1197,7 +1047,7 @@ TEST_P(CordTest, ConstructFromExternalNonTrivialReleaserDestructor) {
EXPECT_TRUE(destroyed);
}
-TEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {
+TEST(ConstructFromExternal, ReferenceQualifierOverloads) {
struct Releaser {
void operator()(absl::string_view) & { *lvalue_invoked = true; }
void operator()(absl::string_view) && { *rvalue_invoked = true; }
@@ -1225,8 +1075,8 @@ TEST_P(CordTest, ConstructFromExternalReferenceQualifierOverloads) {
EXPECT_TRUE(rvalue_invoked);
}
-TEST_P(CordTest, ExternalMemoryBasicUsage) {
- static const char* strings[] = {"", "hello", "there"};
+TEST(ExternalMemory, BasicUsage) {
+ static const char* strings[] = { "", "hello", "there" };
for (const char* str : strings) {
absl::Cord dst("(prefix)");
AddExternalMemory(str, &dst);
@@ -1236,7 +1086,7 @@ TEST_P(CordTest, ExternalMemoryBasicUsage) {
}
}
-TEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {
+TEST(ExternalMemory, RemovePrefixSuffix) {
// Exhaustively try all sub-strings.
absl::Cord cord = MakeComposite();
std::string s = std::string(cord);
@@ -1251,7 +1101,7 @@ TEST_P(CordTest, ExternalMemoryRemovePrefixSuffix) {
}
}
-TEST_P(CordTest, ExternalMemoryGet) {
+TEST(ExternalMemory, Get) {
absl::Cord cord("hello");
AddExternalMemory(" world!", &cord);
AddExternalMemory(" how are ", &cord);
@@ -1270,16 +1120,16 @@ TEST_P(CordTest, ExternalMemoryGet) {
// Additionally we have some whiteboxed expectations based on our knowledge of
// the layout and size of empty and inlined cords, and flat nodes.
-TEST_P(CordTest, CordMemoryUsageEmpty) {
+TEST(CordMemoryUsage, Empty) {
EXPECT_EQ(sizeof(absl::Cord), absl::Cord().EstimatedMemoryUsage());
}
-TEST_P(CordTest, CordMemoryUsageEmbedded) {
+TEST(CordMemoryUsage, Embedded) {
absl::Cord a("hello");
EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
}
-TEST_P(CordTest, CordMemoryUsageEmbeddedAppend) {
+TEST(CordMemoryUsage, EmbeddedAppend) {
absl::Cord a("a");
absl::Cord b("bcd");
EXPECT_EQ(b.EstimatedMemoryUsage(), sizeof(absl::Cord));
@@ -1287,7 +1137,7 @@ TEST_P(CordTest, CordMemoryUsageEmbeddedAppend) {
EXPECT_EQ(a.EstimatedMemoryUsage(), sizeof(absl::Cord));
}
-TEST_P(CordTest, CordMemoryUsageExternalMemory) {
+TEST(CordMemoryUsage, ExternalMemory) {
static const int kLength = 1000;
absl::Cord cord;
AddExternalMemory(std::string(kLength, 'x'), &cord);
@@ -1295,14 +1145,14 @@ TEST_P(CordTest, CordMemoryUsageExternalMemory) {
EXPECT_LE(cord.EstimatedMemoryUsage(), kLength * 1.5);
}
-TEST_P(CordTest, CordMemoryUsageFlat) {
+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_P(CordTest, CordMemoryUsageAppendFlat) {
+TEST(CordMemoryUsage, AppendFlat) {
using absl::strings_internal::CordTestAccess;
absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
size_t length = a.EstimatedMemoryUsage();
@@ -1312,32 +1162,9 @@ TEST_P(CordTest, CordMemoryUsageAppendFlat) {
EXPECT_LE(delta, CordTestAccess::MaxFlatLength() * 1.5);
}
-TEST_P(CordTest, CordMemoryUsageAppendExternal) {
- static const int kLength = 1000;
- using absl::strings_internal::CordTestAccess;
- absl::Cord a(std::string(CordTestAccess::MaxFlatLength(), 'a'));
- size_t length = a.EstimatedMemoryUsage();
- AddExternalMemory(std::string(kLength, 'b'), &a);
- size_t delta = a.EstimatedMemoryUsage() - length;
- EXPECT_GT(delta, kLength);
- EXPECT_LE(delta, kLength * 1.5);
-}
-
-TEST_P(CordTest, CordMemoryUsageSubString) {
- static const int kLength = 2000;
- using absl::strings_internal::CordTestAccess;
- absl::Cord a(std::string(kLength, 'a'));
- size_t length = a.EstimatedMemoryUsage();
- AddExternalMemory(std::string(kLength, 'b'), &a);
- absl::Cord b = a.Subcord(0, kLength + kLength / 2);
- size_t delta = b.EstimatedMemoryUsage() - length;
- EXPECT_GT(delta, kLength);
- EXPECT_LE(delta, kLength * 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_P(CordTest, CordMemoryUsageInlineRep) {
+TEST(CordMemoryUsage, InlineRep) {
constexpr size_t kMaxInline = 15; // Cord::InlineRep::N
const std::string small_string(kMaxInline, 'x');
absl::Cord c1(small_string);
@@ -1351,7 +1178,7 @@ TEST_P(CordTest, CordMemoryUsageInlineRep) {
} // namespace
// Regtest for 7510292 (fix a bug introduced by 7465150)
-TEST_P(CordTest, Concat_Append) {
+TEST(Cord, Concat_Append) {
// Create a rep of type CONCAT
absl::Cord s1("foobarbarbarbarbar");
s1.Append("abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefg");
@@ -1366,80 +1193,7 @@ TEST_P(CordTest, Concat_Append) {
EXPECT_EQ(s2.size(), size + 1);
}
-TEST_P(CordTest, DiabolicalGrowth) {
- // This test exercises a diabolical Append(<one char>) on a cord, making the
- // cord shared before each Append call resulting in a terribly fragmented
- // resulting cord.
- // TODO(b/183983616): Apply some minimum compaction when copying a shared
- // source cord into a mutable copy for updates in CordRepRing.
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
- const std::string expected = RandomLowercaseString(&rng, 5000);
- absl::Cord cord;
- for (char c : expected) {
- absl::Cord shared(cord);
- cord.Append(absl::string_view(&c, 1));
- }
- std::string value;
- absl::CopyCordToString(cord, &value);
- EXPECT_EQ(value, expected);
- ABSL_RAW_LOG(INFO, "Diabolical size allocated = %zu",
- cord.EstimatedMemoryUsage());
-}
-
-// The following tests check support for >4GB cords in 64-bit binaries, and
-// 2GB-4GB cords in 32-bit binaries. This function returns the large cord size
-// that's appropriate for the binary.
-
-// Construct a huge cord with the specified valid prefix.
-static absl::Cord MakeHuge(absl::string_view prefix) {
- absl::Cord cord;
- if (sizeof(size_t) > 4) {
- // In 64-bit binaries, test 64-bit Cord support.
- const size_t size =
- static_cast<size_t>(std::numeric_limits<uint32_t>::max()) + 314;
- cord.Append(absl::MakeCordFromExternal(
- absl::string_view(prefix.data(), size),
- [](absl::string_view s) { DoNothing(s, nullptr); }));
- } else {
- // Cords are limited to 32-bit lengths in 32-bit binaries. The following
- // tests check for use of "signed int" to represent Cord length/offset.
- // However absl::string_view does not allow lengths >= (1u<<31), so we need
- // to append in two parts;
- const size_t s1 = (1u << 31) - 1;
- // For shorter cord, `Append` copies the data rather than allocating a new
- // node. The threshold is currently set to 511, so `s2` needs to be bigger
- // to not trigger the copy.
- const size_t s2 = 600;
- cord.Append(absl::MakeCordFromExternal(
- absl::string_view(prefix.data(), s1),
- [](absl::string_view s) { DoNothing(s, nullptr); }));
- cord.Append(absl::MakeCordFromExternal(
- absl::string_view("", s2),
- [](absl::string_view s) { DoNothing(s, nullptr); }));
- }
- return cord;
-}
-
-TEST_P(CordTest, HugeCord) {
- absl::Cord cord = MakeHuge("huge cord");
- EXPECT_LE(cord.size(), cord.EstimatedMemoryUsage());
- EXPECT_GE(cord.size() + 100, cord.EstimatedMemoryUsage());
-}
-
-// Tests that Append() works ok when handed a self reference
-TEST_P(CordTest, AppendSelf) {
- // We run the test until data is ~16K
- // This guarantees it covers small, medium and large data.
- std::string control_data = "Abc";
- absl::Cord data(control_data);
- while (control_data.length() < 0x4000) {
- data.Append(data);
- control_data.append(control_data);
- ASSERT_EQ(control_data, data);
- }
-}
-
-TEST_P(CordTest, MakeFragmentedCordFromInitializerList) {
+TEST(MakeFragmentedCord, MakeFragmentedCordFromInitializerList) {
absl::Cord fragmented =
absl::MakeFragmentedCord({"A ", "fragmented ", "Cord"});
@@ -1459,7 +1213,7 @@ TEST_P(CordTest, MakeFragmentedCordFromInitializerList) {
ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
}
-TEST_P(CordTest, MakeFragmentedCordFromVector) {
+TEST(MakeFragmentedCord, MakeFragmentedCordFromVector) {
std::vector<absl::string_view> chunks = {"A ", "fragmented ", "Cord"};
absl::Cord fragmented = absl::MakeFragmentedCord(chunks);
@@ -1479,7 +1233,7 @@ TEST_P(CordTest, MakeFragmentedCordFromVector) {
ASSERT_TRUE(++chunk_it == fragmented.chunk_end());
}
-TEST_P(CordTest, CordChunkIteratorTraits) {
+TEST(CordChunkIterator, Traits) {
static_assert(std::is_copy_constructible<absl::Cord::ChunkIterator>::value,
"");
static_assert(std::is_copy_assignable<absl::Cord::ChunkIterator>::value, "");
@@ -1560,7 +1314,7 @@ static void VerifyChunkIterator(const absl::Cord& cord,
EXPECT_TRUE(post_iter == cord.chunk_end()); // NOLINT
}
-TEST_P(CordTest, CordChunkIteratorOperations) {
+TEST(CordChunkIterator, Operations) {
absl::Cord empty_cord;
VerifyChunkIterator(empty_cord, 0);
@@ -1585,14 +1339,14 @@ TEST_P(CordTest, CordChunkIteratorOperations) {
VerifyChunkIterator(reused_nodes_cord, expected_chunks);
}
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+ 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_P(CordTest, CharIteratorTraits) {
+TEST(CordCharIterator, Traits) {
static_assert(std::is_copy_constructible<absl::Cord::CharIterator>::value,
"");
static_assert(std::is_copy_assignable<absl::Cord::CharIterator>::value, "");
@@ -1701,7 +1455,7 @@ static void VerifyCharIterator(const absl::Cord& cord) {
}
}
-TEST_P(CordTest, CharIteratorOperations) {
+TEST(CordCharIterator, Operations) {
absl::Cord empty_cord;
VerifyCharIterator(empty_cord);
@@ -1723,49 +1477,14 @@ TEST_P(CordTest, CharIteratorOperations) {
VerifyCharIterator(reused_nodes_cord);
}
- RandomEngine rng(GTEST_FLAG_GET(random_seed));
+ 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_P(CordTest, CharIteratorAdvanceAndRead) {
- // Create a Cord holding 6 flats of 2500 bytes each, and then iterate over it
- // reading 150, 1500, 2500 and 3000 bytes. This will result in all possible
- // partial, full and straddled read combinations including reads below
- // kMaxBytesToCopy. b/197776822 surfaced a bug for a specific partial, small
- // read 'at end' on Cord which caused a failure on attempting to read past the
- // end in CordRepBtreeReader which was not covered by any existing test.
- constexpr int kBlocks = 6;
- constexpr size_t kBlockSize = 2500;
- constexpr size_t kChunkSize1 = 1500;
- constexpr size_t kChunkSize2 = 2500;
- constexpr size_t kChunkSize3 = 3000;
- constexpr size_t kChunkSize4 = 150;
- RandomEngine rng;
- std::string data = RandomLowercaseString(&rng, kBlocks * kBlockSize);
- absl::Cord cord;
- for (int i = 0; i < kBlocks; ++i) {
- const std::string block = data.substr(i * kBlockSize, kBlockSize);
- cord.Append(absl::Cord(block));
- }
-
- for (size_t chunk_size :
- {kChunkSize1, kChunkSize2, kChunkSize3, kChunkSize4}) {
- absl::Cord::CharIterator it = cord.char_begin();
- size_t offset = 0;
- while (offset < data.length()) {
- const size_t n = std::min<size_t>(data.length() - offset, chunk_size);
- absl::Cord chunk = cord.AdvanceAndRead(&it, n);
- ASSERT_EQ(chunk.size(), n);
- ASSERT_EQ(chunk.Compare(data.substr(offset, n)), 0);
- offset += n;
- }
- }
-}
-
-TEST_P(CordTest, StreamingOutput) {
+TEST(Cord, StreamingOutput) {
absl::Cord c =
absl::MakeFragmentedCord({"A ", "small ", "fragmented ", "Cord", "."});
std::stringstream output;
@@ -1773,7 +1492,7 @@ TEST_P(CordTest, StreamingOutput) {
EXPECT_EQ("A small fragmented Cord.", output.str());
}
-TEST_P(CordTest, ForEachChunk) {
+TEST(Cord, ForEachChunk) {
for (int num_elements : {1, 10, 200}) {
SCOPED_TRACE(num_elements);
std::vector<std::string> cord_chunks;
@@ -1791,7 +1510,7 @@ TEST_P(CordTest, ForEachChunk) {
}
}
-TEST_P(CordTest, SmallBufferAssignFromOwnData) {
+TEST(Cord, SmallBufferAssignFromOwnData) {
constexpr size_t kMaxInline = 15;
std::string contents = "small buff cord";
EXPECT_EQ(contents.size(), kMaxInline);
@@ -1805,153 +1524,3 @@ TEST_P(CordTest, SmallBufferAssignFromOwnData) {
}
}
}
-
-TEST_P(CordTest, 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_P(CordTest, 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(), "");
-}
-
-// This test mimics a specific (and rare) application repeatedly splitting a
-// cord, inserting (overwriting) a string value, and composing a new cord from
-// the three pieces. This is hostile towards a Btree implementation: A split of
-// a node at any level is likely to have the right-most edge of the left split,
-// and the left-most edge of the right split shared. For example, splitting a
-// leaf node with 6 edges will result likely in a 1-6, 2-5, 3-4, etc. split,
-// sharing the 'split node'. When recomposing such nodes, we 'injected' an edge
-// in that node. As this happens with some probability on each level of the
-// tree, this will quickly grow the tree until it reaches maximum height.
-TEST_P(CordTest, BtreeHostileSplitInsertJoin) {
- absl::BitGen bitgen;
-
- // Start with about 1GB of data
- std::string data(1 << 10, 'x');
- absl::Cord buffer(data);
- absl::Cord cord;
- for (int i = 0; i < 1000000; ++i) {
- cord.Append(buffer);
- }
-
- for (int j = 0; j < 1000; ++j) {
- size_t offset = absl::Uniform(bitgen, 0u, cord.size());
- size_t length = absl::Uniform(bitgen, 100u, data.size());
- if (cord.size() == offset) {
- cord.Append(absl::string_view(data.data(), length));
- } else {
- absl::Cord suffix;
- if (offset + length < cord.size()) {
- suffix = cord;
- suffix.RemovePrefix(offset + length);
- }
- if (cord.size() > offset) {
- cord.RemoveSuffix(cord.size() - offset);
- }
- cord.Append(absl::string_view(data.data(), length));
- if (!suffix.empty()) {
- cord.Append(suffix);
- }
- }
- }
-}
-
-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_P(CordTest, ConstinitConstructor) {
- TestConstinitConstructor(
- absl::strings_internal::MakeStringConstant(ShortView{}));
- TestConstinitConstructor(
- absl::strings_internal::MakeStringConstant(LongView{}));
-}
diff --git a/third_party/abseil-cpp/absl/strings/cord_test_helpers.h b/third_party/abseil-cpp/absl/strings/cord_test_helpers.h
index 31a1dc8980..f1036e3b13 100644
--- a/third_party/abseil-cpp/absl/strings/cord_test_helpers.h
+++ b/third_party/abseil-cpp/absl/strings/cord_test_helpers.h
@@ -17,73 +17,11 @@
#ifndef ABSL_STRINGS_CORD_TEST_HELPERS_H_
#define ABSL_STRINGS_CORD_TEST_HELPERS_H_
-#include <cstdint>
-#include <iostream>
-#include <string>
-
-#include "absl/base/config.h"
#include "absl/strings/cord.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/string_view.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-// Cord sizes relevant for testing
-enum class TestCordSize {
- // An empty value
- kEmpty = 0,
-
- // An inlined string value
- kInlined = cord_internal::kMaxInline / 2 + 1,
-
- // 'Well known' SSO lengths (excluding terminating zero).
- // libstdcxx has a maximum SSO of 15, libc++ has a maximum SSO of 22.
- kStringSso1 = 15,
- kStringSso2 = 22,
-
- // A string value which is too large to fit in inlined data, but small enough
- // such that Cord prefers copying the value if possible, i.e.: not stealing
- // std::string inputs, or referencing existing CordReps on Append, etc.
- kSmall = cord_internal::kMaxBytesToCopy / 2 + 1,
-
- // A string value large enough that Cord prefers to reference or steal from
- // existing inputs rather than copying contents of the input.
- kMedium = cord_internal::kMaxFlatLength / 2 + 1,
-
- // A string value large enough to cause it to be stored in mutliple flats.
- kLarge = cord_internal::kMaxFlatLength * 4
-};
-
-// To string helper
-inline absl::string_view ToString(TestCordSize size) {
- switch (size) {
- case TestCordSize::kEmpty:
- return "Empty";
- case TestCordSize::kInlined:
- return "Inlined";
- case TestCordSize::kSmall:
- return "Small";
- case TestCordSize::kStringSso1:
- return "StringSso1";
- case TestCordSize::kStringSso2:
- return "StringSso2";
- case TestCordSize::kMedium:
- return "Medium";
- case TestCordSize::kLarge:
- return "Large";
- }
- return "???";
-}
-
-// Returns the length matching the specified size
-inline size_t Length(TestCordSize size) { return static_cast<size_t>(size); }
-
-// Stream output helper
-inline std::ostream& operator<<(std::ostream& stream, TestCordSize size) {
- return stream << ToString(size);
-}
-
// Creates a multi-segment Cord from an iterable container of strings. The
// resulting Cord is guaranteed to have one segment for every string in the
// container. This allows code to be unit tested with multi-segment Cord
diff --git a/third_party/abseil-cpp/absl/strings/cordz_test.cc b/third_party/abseil-cpp/absl/strings/cordz_test.cc
deleted file mode 100644
index 2b7d30b0e0..0000000000
--- a/third_party/abseil-cpp/absl/strings/cordz_test.cc
+++ /dev/null
@@ -1,466 +0,0 @@
-// 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 <cstdint>
-#include <string>
-
-#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/strings/cord.h"
-#include "absl/strings/cord_test_helpers.h"
-#include "absl/strings/cordz_test_helpers.h"
-#include "absl/strings/internal/cordz_functions.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_sample_token.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-
-#ifdef ABSL_INTERNAL_CORDZ_ENABLED
-
-using testing::Eq;
-using testing::AnyOf;
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-using cord_internal::CordzInfo;
-using cord_internal::CordzSampleToken;
-using cord_internal::CordzStatistics;
-using cord_internal::CordzUpdateTracker;
-using Method = CordzUpdateTracker::MethodIdentifier;
-
-// Do not print cord contents, we only care about 'size' perhaps.
-// Note that this method must be inside the named namespace.
-inline void PrintTo(const Cord& cord, std::ostream* s) {
- if (s) *s << "Cord[" << cord.size() << "]";
-}
-
-namespace {
-
-auto constexpr kMaxInline = cord_internal::kMaxInline;
-
-// Returns a string_view value of the specified length
-// We do this to avoid 'consuming' large strings in Cord by default.
-absl::string_view MakeString(size_t size) {
- thread_local std::string str;
- str = std::string(size, '.');
- return str;
-}
-
-absl::string_view MakeString(TestCordSize size) {
- return MakeString(Length(size));
-}
-
-// Returns a cord with a sampled method of kAppendString.
-absl::Cord MakeAppendStringCord(TestCordSize size) {
- CordzSamplingIntervalHelper always(1);
- absl::Cord cord;
- cord.Append(MakeString(size));
- return cord;
-}
-
-std::string TestParamToString(::testing::TestParamInfo<TestCordSize> size) {
- return absl::StrCat("On", ToString(size.param), "Cord");
-}
-
-class CordzUpdateTest : public testing::TestWithParam<TestCordSize> {
- public:
- Cord& cord() { return cord_; }
-
- Method InitialOr(Method method) const {
- return (GetParam() > TestCordSize::kInlined) ? Method::kConstructorString
- : method;
- }
-
- private:
- CordzSamplingIntervalHelper sample_every_{1};
- Cord cord_{MakeString(GetParam())};
-};
-
-template <typename T>
-std::string ParamToString(::testing::TestParamInfo<T> param) {
- return std::string(ToString(param.param));
-}
-
-INSTANTIATE_TEST_SUITE_P(WithParam, CordzUpdateTest,
- testing::Values(TestCordSize::kEmpty,
- TestCordSize::kInlined,
- TestCordSize::kLarge),
- TestParamToString);
-
-class CordzStringTest : public testing::TestWithParam<TestCordSize> {
- private:
- CordzSamplingIntervalHelper sample_every_{1};
-};
-
-INSTANTIATE_TEST_SUITE_P(WithParam, CordzStringTest,
- testing::Values(TestCordSize::kInlined,
- TestCordSize::kStringSso1,
- TestCordSize::kStringSso2,
- TestCordSize::kSmall,
- TestCordSize::kLarge),
- ParamToString<TestCordSize>);
-
-TEST(CordzTest, ConstructSmallArray) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
-}
-
-TEST(CordzTest, ConstructLargeArray) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
-}
-
-TEST_P(CordzStringTest, ConstructString) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- }
-}
-
-TEST(CordzTest, CopyConstructFromUnsampled) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord cord(src);
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
-}
-
-TEST(CordzTest, CopyConstructFromSampled) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(src);
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
-}
-
-TEST(CordzTest, MoveConstruct) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src(MakeString(TestCordSize::kLarge));
- Cord cord(std::move(src));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
-}
-
-TEST_P(CordzUpdateTest, AssignUnsampledCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- const CordzInfo* info = GetCordzInfoForTesting(cord());
- cord() = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
-}
-
-TEST_P(CordzUpdateTest, AssignSampledCord) {
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord() = src;
- ASSERT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord())->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
-}
-
-TEST(CordzUpdateTest, AssignSampledCordToInlined) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord;
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
-}
-
-TEST(CordzUpdateTest, AssignSampledCordToUnsampledCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
-}
-
-TEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithoutSampling) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord cord = MakeAppendStringCord(TestCordSize::kLarge);
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
-}
-
-TEST(CordzUpdateTest, AssignUnsampledCordToSampledCordWithSampling) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeAppendStringCord(TestCordSize::kLarge);
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
-}
-
-TEST(CordzUpdateTest, AssignSampledCordToSampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
-}
-
-TEST(CordzUpdateTest, AssignUnsampledCordToSampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = src;
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kAssignCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
- EXPECT_THAT(stats.update_tracker.Value(Method::kConstructorString), Eq(0));
-}
-
-TEST(CordzTest, AssignInlinedCordToSampledCord) {
- CordzSampleToken token;
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord(MakeString(TestCordSize::kLarge));
- const CordzInfo* info = GetCordzInfoForTesting(cord);
- Cord src = UnsampledCord(MakeString(TestCordSize::kInlined));
- cord = src;
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
- EXPECT_FALSE(CordzInfoIsListed(info));
-}
-
-TEST(CordzUpdateTest, MoveAssignCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord;
- Cord src(MakeString(TestCordSize::kLarge));
- cord = std::move(src);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
-}
-
-TEST_P(CordzUpdateTest, AssignLargeArray) {
- cord() = MakeString(TestCordSize::kSmall);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));
-}
-
-TEST_P(CordzUpdateTest, AssignSmallArray) {
- cord() = MakeString(TestCordSize::kSmall);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(Method::kAssignString));
-}
-
-TEST_P(CordzUpdateTest, AssignInlinedArray) {
- cord() = MakeString(TestCordSize::kInlined);
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
-}
-
-TEST_P(CordzStringTest, AssignStringToInlined) {
- Cord cord;
- cord = std::string(Length(GetParam()), '.');
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAssignString));
- }
-}
-
-TEST_P(CordzStringTest, AssignStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord = std::string(Length(GetParam()), '.');
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kAssignString, 1));
- }
-}
-
-TEST_P(CordzUpdateTest, AssignInlinedString) {
- cord() = std::string(Length(TestCordSize::kInlined), '.');
- EXPECT_THAT(GetCordzInfoForTesting(cord()), Eq(nullptr));
-}
-
-TEST_P(CordzUpdateTest, AppendCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord().Append(src);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));
-}
-
-TEST_P(CordzUpdateTest, MoveAppendCord) {
- cord().Append(UnsampledCord(MakeString(TestCordSize::kLarge)));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendCord)));
-}
-
-TEST_P(CordzUpdateTest, AppendSmallArray) {
- cord().Append(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));
-}
-
-TEST_P(CordzUpdateTest, AppendLargeArray) {
- cord().Append(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kAppendString)));
-}
-
-TEST_P(CordzStringTest, AppendStringToEmpty) {
- Cord cord;
- cord.Append(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));
- }
-}
-
-TEST_P(CordzStringTest, AppendStringToInlined) {
- Cord cord(MakeString(TestCordSize::kInlined));
- cord.Append(std::string(Length(GetParam()), '.'));
- if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kAppendString));
- }
-}
-
-TEST_P(CordzStringTest, AppendStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord.Append(std::string(Length(GetParam()), '.'));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kAppendString, 1));
-}
-
-TEST(CordzTest, MakeCordFromExternal) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeCordFromExternal("Hello world", [](absl::string_view) {});
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kMakeCordFromExternal));
-}
-
-TEST(CordzTest, MakeCordFromEmptyExternal) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord cord = MakeCordFromExternal({}, [](absl::string_view) {});
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
-}
-
-TEST_P(CordzUpdateTest, PrependCord) {
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- cord().Prepend(src);
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependCord)));
-}
-
-TEST_P(CordzUpdateTest, PrependSmallArray) {
- cord().Prepend(MakeString(TestCordSize::kSmall));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));
-}
-
-TEST_P(CordzUpdateTest, PrependLargeArray) {
- cord().Prepend(MakeString(TestCordSize::kLarge));
- EXPECT_THAT(cord(), HasValidCordzInfoOf(InitialOr(Method::kPrependString)));
-}
-
-TEST_P(CordzStringTest, PrependStringToEmpty) {
- Cord cord;
- cord.Prepend(std::string(Length(GetParam()), '.'));
- if (Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));
- }
-}
-
-TEST_P(CordzStringTest, PrependStringToInlined) {
- Cord cord(MakeString(TestCordSize::kInlined));
- cord.Prepend(std::string(Length(GetParam()), '.'));
- if (Length(TestCordSize::kInlined) + Length(GetParam()) > kMaxInline) {
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kPrependString));
- }
-}
-
-TEST_P(CordzStringTest, PrependStringToCord) {
- Cord cord(MakeString(TestCordSize::kLarge));
- cord.Prepend(std::string(Length(GetParam()), '.'));
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kPrependString, 1));
-}
-
-TEST(CordzTest, RemovePrefix) {
- CordzSamplingIntervalHelper sample_every(1);
- Cord cord(MakeString(TestCordSize::kLarge));
-
- // Half the cord
- cord.RemovePrefix(cord.size() / 2);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 1));
-
- // TODO(mvels): RemovePrefix does not reset to inlined, except if empty?
- cord.RemovePrefix(cord.size() - kMaxInline);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemovePrefix, 2));
-
- cord.RemovePrefix(cord.size());
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
-}
-
-TEST(CordzTest, RemoveSuffix) {
- CordzSamplingIntervalHelper sample_every(1);
- Cord cord(MakeString(TestCordSize::kLarge));
-
- // Half the cord
- cord.RemoveSuffix(cord.size() / 2);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 1));
-
- // TODO(mvels): RemoveSuffix does not reset to inlined, except if empty?
- cord.RemoveSuffix(cord.size() - kMaxInline);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kConstructorString));
- EXPECT_THAT(cord, CordzMethodCountEq(Method::kRemoveSuffix, 2));
-
- cord.RemoveSuffix(cord.size());
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
-}
-
-TEST(CordzTest, SubCordFromUnsampledCord) {
- CordzSamplingIntervalHelper sample_every{1};
- Cord src = UnsampledCord(MakeString(TestCordSize::kLarge));
- Cord cord = src.Subcord(10, src.size() / 2);
- EXPECT_THAT(GetCordzInfoForTesting(cord), Eq(nullptr));
-}
-
-TEST(CordzTest, SubCordFromSampledCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord = src.Subcord(10, src.size() / 2);
- ASSERT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));
- CordzStatistics stats = GetCordzInfoForTesting(cord)->GetCordzStatistics();
- EXPECT_THAT(stats.parent_method, Eq(Method::kAppendString));
- EXPECT_THAT(stats.update_tracker.Value(Method::kAppendString), Eq(1));
-}
-
-TEST(CordzTest, SmallSubCord) {
- CordzSamplingIntervalHelper sample_never{99999};
- Cord src = MakeAppendStringCord(TestCordSize::kLarge);
- Cord cord = src.Subcord(10, kMaxInline + 1);
- EXPECT_THAT(cord, HasValidCordzInfoOf(Method::kSubCord));
-}
-
-} // namespace
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_INTERNAL_CORDZ_ENABLED
diff --git a/third_party/abseil-cpp/absl/strings/cordz_test_helpers.h b/third_party/abseil-cpp/absl/strings/cordz_test_helpers.h
deleted file mode 100644
index e410eecf7f..0000000000
--- a/third_party/abseil-cpp/absl/strings/cordz_test_helpers.h
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2021 The Abseil Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_CORDZ_TEST_HELPERS_H_
-#define ABSL_STRINGS_CORDZ_TEST_HELPERS_H_
-
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/macros.h"
-#include "absl/strings/cord.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_sample_token.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/str_cat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-
-// Returns the CordzInfo for the cord, or nullptr if the cord is not sampled.
-inline const cord_internal::CordzInfo* GetCordzInfoForTesting(
- const Cord& cord) {
- if (!cord.contents_.is_tree()) return nullptr;
- return cord.contents_.cordz_info();
-}
-
-// Returns true if the provided cordz_info is in the list of sampled cords.
-inline bool CordzInfoIsListed(const cord_internal::CordzInfo* cordz_info,
- cord_internal::CordzSampleToken token = {}) {
- for (const cord_internal::CordzInfo& info : token) {
- if (cordz_info == &info) return true;
- }
- return false;
-}
-
-// Matcher on Cord that verifies all of:
-// - the cord is sampled
-// - the CordzInfo of the cord is listed / discoverable.
-// - the reported CordzStatistics match the cord's actual properties
-// - the cord has an (initial) UpdateTracker count of 1 for `method`
-MATCHER_P(HasValidCordzInfoOf, method, "CordzInfo matches cord") {
- const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);
- if (cord_info == nullptr) {
- *result_listener << "cord is not sampled";
- return false;
- }
- if (!CordzInfoIsListed(cord_info)) {
- *result_listener << "cord is sampled, but not listed";
- return false;
- }
- cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();
- if (stat.size != arg.size()) {
- *result_listener << "cordz size " << stat.size
- << " does not match cord size " << arg.size();
- return false;
- }
- if (stat.update_tracker.Value(method) != 1) {
- *result_listener << "Expected method count 1 for " << method << ", found "
- << stat.update_tracker.Value(method);
- return false;
- }
- return true;
-}
-
-// Matcher on Cord that verifies that the cord is sampled and that the CordzInfo
-// update tracker has 'method' with a call count of 'n'
-MATCHER_P2(CordzMethodCountEq, method, n,
- absl::StrCat("CordzInfo method count equals ", n)) {
- const cord_internal::CordzInfo* cord_info = GetCordzInfoForTesting(arg);
- if (cord_info == nullptr) {
- *result_listener << "cord is not sampled";
- return false;
- }
- cord_internal::CordzStatistics stat = cord_info->GetCordzStatistics();
- if (stat.update_tracker.Value(method) != n) {
- *result_listener << "Expected method count " << n << " for " << method
- << ", found " << stat.update_tracker.Value(method);
- return false;
- }
- return true;
-}
-
-// Cordz will only update with a new rate once the previously scheduled event
-// has fired. When we disable Cordz, a long delay takes place where we won't
-// consider profiling new Cords. CordzSampleIntervalHelper will burn through
-// that interval and allow for testing that assumes that the average sampling
-// interval is a particular value.
-class CordzSamplingIntervalHelper {
- public:
- explicit CordzSamplingIntervalHelper(int32_t interval)
- : orig_mean_interval_(absl::cord_internal::get_cordz_mean_interval()) {
- absl::cord_internal::set_cordz_mean_interval(interval);
- absl::cord_internal::cordz_set_next_sample_for_testing(interval);
- }
-
- ~CordzSamplingIntervalHelper() {
- absl::cord_internal::set_cordz_mean_interval(orig_mean_interval_);
- absl::cord_internal::cordz_set_next_sample_for_testing(orig_mean_interval_);
- }
-
- private:
- int32_t orig_mean_interval_;
-};
-
-// Wrapper struct managing a small CordRep `rep`
-struct TestCordRep {
- cord_internal::CordRepFlat* rep;
-
- TestCordRep() {
- rep = cord_internal::CordRepFlat::New(100);
- rep->length = 100;
- memset(rep->Data(), 1, 100);
- }
- ~TestCordRep() { cord_internal::CordRep::Unref(rep); }
-};
-
-// Wrapper struct managing a small CordRep `rep`, and
-// an InlineData `data` initialized with that CordRep.
-struct TestCordData {
- TestCordRep rep;
- cord_internal::InlineData data{rep.rep};
-};
-
-// Creates a Cord that is not sampled
-template <typename... Args>
-Cord UnsampledCord(Args... args) {
- CordzSamplingIntervalHelper never(9999);
- Cord cord(std::forward<Args>(args)...);
- ABSL_ASSERT(GetCordzInfoForTesting(cord) == nullptr);
- return cord;
-}
-
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORDZ_TEST_HELPERS_H_
diff --git a/third_party/abseil-cpp/absl/strings/escaping.cc b/third_party/abseil-cpp/absl/strings/escaping.cc
index 18b20b83fd..7adc1b6571 100644
--- a/third_party/abseil-cpp/absl/strings/escaping.cc
+++ b/third_party/abseil-cpp/absl/strings/escaping.cc
@@ -137,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++ = '\\';
- memmove(d, octal_start, octal_size);
+ memcpy(d, octal_start, octal_size);
d += octal_size;
break;
}
@@ -170,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++ = '\\';
- memmove(d, hex_start, hex_size);
+ memcpy(d, hex_start, hex_size);
d += hex_size;
break;
}
@@ -203,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++ = '\\';
- memmove(d, hex_start, 5); // u0000
+ memcpy(d, hex_start, 5); // u0000
d += 5;
break;
}
@@ -251,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++ = '\\';
- memmove(d, hex_start, 9); // U00000000
+ memcpy(d, hex_start, 9); // U00000000
d += 9;
break;
}
@@ -450,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
- // string or when we read any non-data character. The arguments are
+ // std::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.
@@ -473,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 string for a full iteration, so the loop may
+ // data left in the std::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 string (src[0..3]) are four good data bytes
+ // bytes of the std::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 string (no matter how long
- // szsrc claims the string is).
+ // never read past a null in the std::string (no matter how long
+ // szsrc claims the std::string is).
if (!src[0] || !src[1] || !src[2] ||
((temp = ((unsigned(unbase64[src[0]]) << 18) |
@@ -509,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 string.
+ // characters in the std::string.
szsrc -= 4;
src += 4;
@@ -644,7 +644,7 @@ bool Base64UnescapeInternal(const char* src_param, size_t szsrc, char* dest,
state);
}
- // The remainder of the string should be all whitespace, mixed with
+ // The remainder of the std::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.)
@@ -771,7 +771,7 @@ constexpr char kWebSafeBase64Chars[] =
template <typename String>
bool Base64UnescapeInternal(const char* src, size_t slen, String* dest,
const signed char* unbase64) {
- // Determine the size of the output string. Base64 encodes every 3 bytes into
+ // Determine the size of the output std::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);
@@ -779,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
- // string and converting it into a char *.
+ // std::string and converting it into a char *.
size_t len;
const bool ok =
Base64UnescapeInternal(src, slen, &(*dest)[0], dest_len, unbase64, &len);
diff --git a/third_party/abseil-cpp/absl/strings/escaping_test.cc b/third_party/abseil-cpp/absl/strings/escaping_test.cc
index 45671a0ed5..1967975b69 100644
--- a/third_party/abseil-cpp/absl/strings/escaping_test.cc
+++ b/third_party/abseil-cpp/absl/strings/escaping_test.cc
@@ -300,7 +300,7 @@ static struct {
absl::string_view plaintext;
absl::string_view cyphertext;
} const base64_tests[] = {
- // Empty string.
+ // Empty std::string.
{{"", 0}, {"", 0}},
{{nullptr, 0},
{"", 0}}, // if length is zero, plaintext ptr must be ignored!
@@ -586,7 +586,7 @@ void TestEscapeAndUnescape() {
EXPECT_EQ(encoded, websafe);
EXPECT_EQ(absl::WebSafeBase64Escape(tc.plaintext), websafe);
- // Let's try the string version of the decoder
+ // Let's try the std::string version of the decoder
decoded = "this junk should be ignored";
EXPECT_TRUE(absl::WebSafeBase64Unescape(websafe, &decoded));
EXPECT_EQ(decoded, tc.plaintext);
@@ -625,7 +625,7 @@ TEST(Base64, DISABLED_HugeData) {
std::string escaped;
absl::Base64Escape(huge, &escaped);
- // Generates the string that should match a base64 encoded "xxx..." string.
+ // Generates the std::string that should match a base64 encoded "xxx..." std::string.
// "xxx" in base64 is "eHh4".
std::string expected_encoding;
expected_encoding.reserve(kSize / 3 * 4);
diff --git a/third_party/abseil-cpp/absl/strings/internal/char_map.h b/third_party/abseil-cpp/absl/strings/internal/char_map.h
index 61484de0b7..a76e60362b 100644
--- a/third_party/abseil-cpp/absl/strings/internal/char_map.h
+++ b/third_party/abseil-cpp/absl/strings/internal/char_map.h
@@ -72,7 +72,7 @@ class Charmap {
CharMaskForWord(x, 2), CharMaskForWord(x, 3));
}
- // Containing all the chars in the C-string 's'.
+ // Containing all the chars in the C-std::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) {
diff --git a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc
index ebf8c0791a..66f33e7207 100644
--- a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc
@@ -208,7 +208,7 @@ int BigUnsigned<max_words>::ReadDigits(const char* begin, const char* end,
++dropped_digits;
}
if (begin < end && *std::prev(end) == '.') {
- // If the string ends in '.', either before or after dropping zeroes, then
+ // If the std::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;
diff --git a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h
index 8f702976a8..999e9ae3a2 100644
--- a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h
+++ b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h
@@ -66,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 string is not a decimal integer, constructs a 0
+ // value. If the input std::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
@@ -210,7 +210,7 @@ class BigUnsigned {
return words_[index];
}
- // Returns this integer as a decimal string. This is not used in the decimal-
+ // Returns this integer as a decimal std::string. This is not used in the decimal-
// to-binary conversion; it is intended to aid in testing.
std::string ToString() const;
diff --git a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
index a8b9945829..363bcb03d9 100644
--- a/third_party/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/charconv_bigint_test.cc
@@ -69,61 +69,6 @@ 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) {
diff --git a/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc b/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc
index d29acaf462..d9a57a7822 100644
--- a/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc
@@ -52,7 +52,7 @@ static_assert(std::numeric_limits<double>::digits == 53, "IEEE double fact");
// The lowest valued 19-digit decimal mantissa we can read still contains
// sufficient information to reconstruct a binary mantissa.
-static_assert(1000000000000000000u > (uint64_t{1} << (53 + 3)), "(b) above");
+static_assert(1000000000000000000u > (uint64_t(1) << (53 + 3)), "(b) above");
// ParseFloat<16> will read the first 15 significant digits of the mantissa.
//
@@ -246,8 +246,8 @@ 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>
-int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
- bool* dropped_nonzero_digit) {
+std::size_t 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) {
@@ -282,7 +282,7 @@ int ConsumeDigits(const char* begin, const char* end, int max_digits, T* out,
*dropped_nonzero_digit = true;
}
*out = accumulator;
- return static_cast<int>(begin - original_begin);
+ return begin - original_begin;
}
// Returns true if `v` is one of the chars allowed inside parentheses following
@@ -302,7 +302,7 @@ bool ParseInfinityOrNan(const char* begin, const char* end,
switch (*begin) {
case 'i':
case 'I': {
- // An infinity string consists of the characters "inf" or "infinity",
+ // An infinity std::string consists of the characters "inf" or "infinity",
// case insensitive.
if (strings_internal::memcasecmp(begin + 1, "nf", 2) != 0) {
return false;
@@ -326,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 string, consisting of
+ // NaN is allowed to be followed by a parenthesized std::string, consisting of
// only the characters [a-zA-Z0-9_]. Match that if it's present.
begin += 3;
if (begin < end && *begin == '(') {
@@ -372,7 +372,7 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
int exponent_adjustment = 0;
bool mantissa_is_inexact = false;
- int pre_decimal_digits = ConsumeDigits<base>(
+ std::size_t pre_decimal_digits = ConsumeDigits<base>(
begin, end, MantissaDigitsMax<base>(), &mantissa, &mantissa_is_inexact);
begin += pre_decimal_digits;
int digits_left;
@@ -398,14 +398,14 @@ strings_internal::ParsedFloat ParseFloat(const char* begin, const char* end,
while (begin < end && *begin == '0') {
++begin;
}
- int zeros_skipped = static_cast<int>(begin - begin_zeros);
+ std::size_t zeros_skipped = begin - begin_zeros;
if (zeros_skipped >= DigitLimit<base>()) {
// refuse to parse pathological inputs
return result;
}
exponent_adjustment -= static_cast<int>(zeros_skipped);
}
- int post_decimal_digits = ConsumeDigits<base>(
+ std::size_t post_decimal_digits = ConsumeDigits<base>(
begin, end, digits_left, &mantissa, &mantissa_is_inexact);
begin += post_decimal_digits;
diff --git a/third_party/abseil-cpp/absl/strings/internal/charconv_parse_test.cc b/third_party/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
index bc2d111876..9511c98745 100644
--- a/third_party/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/charconv_parse_test.cc
@@ -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 string must contain $");
+ "Input std::string must contain $");
s.replace(expected_characters_matched, 1, "");
ParsedFloat parsed =
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_internal.cc b/third_party/abseil-cpp/absl/strings/internal/cord_internal.cc
deleted file mode 100644
index 1767e6fcc5..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_internal.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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_btree.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_btree_enabled(kCordEnableBtreeDefault);
-ABSL_CONST_INIT std::atomic<bool> cord_ring_buffer_enabled(
- kCordEnableRingBufferDefault);
-ABSL_CONST_INIT std::atomic<bool> shallow_subcords_enabled(
- kCordShallowSubcordsDefault);
-ABSL_CONST_INIT std::atomic<bool> cord_btree_exhaustive_validation(false);
-
-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 == BTREE) {
- CordRepBtree::Destroy(rep->btree());
- rep = nullptr;
- } 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/third_party/abseil-cpp/absl/strings/internal/cord_internal.h b/third_party/abseil-cpp/absl/strings/internal/cord_internal.h
index bfe5564e46..5b5d108308 100644
--- a/third_party/abseil-cpp/absl/strings/internal/cord_internal.h
+++ b/third_party/abseil-cpp/absl/strings/internal/cord_internal.h
@@ -1,4 +1,4 @@
-// Copyright 2021 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.
@@ -21,11 +21,6 @@
#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"
@@ -33,153 +28,49 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace cord_internal {
-class CordzInfo;
-
-// Default feature enable states for cord ring buffers
-enum CordFeatureDefaults {
- kCordEnableBtreeDefault = true,
- kCordEnableRingBufferDefault = false,
- kCordShallowSubcordsDefault = false
-};
-
-extern std::atomic<bool> cord_btree_enabled;
-extern std::atomic<bool> cord_ring_buffer_enabled;
-extern std::atomic<bool> shallow_subcords_enabled;
-
-// `cord_btree_exhaustive_validation` can be set to force exhaustive validation
-// in debug assertions, and code that calls `IsValid()` explicitly. By default,
-// assertions should be relatively cheap and AssertValid() can easily lead to
-// O(n^2) complexity as recursive / full tree validation is O(n).
-extern std::atomic<bool> cord_btree_exhaustive_validation;
-
-inline void enable_cord_btree(bool enable) {
- cord_btree_enabled.store(enable, std::memory_order_relaxed);
-}
-
-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
-};
-
-// Compact class for tracking the reference count and state flags for CordRep
-// instances. Data is stored in an atomic int32_t for compactness and speed.
-class RefcountAndFlags {
+// Wraps std::atomic for reference counting.
+class Refcount {
public:
- constexpr RefcountAndFlags() : count_{kRefIncrement} {}
- struct Immortal {};
- explicit constexpr RefcountAndFlags(Immortal) : count_(kImmortalFlag) {}
- struct WithCrc {};
- explicit constexpr RefcountAndFlags(WithCrc)
- : count_(kCrcFlag | kRefIncrement) {}
+ Refcount() : count_{1} {}
+ ~Refcount() {}
- // Increments the reference count. Imposes no memory ordering.
- inline void Increment() {
- count_.fetch_add(kRefIncrement, std::memory_order_relaxed);
- }
+ // Increments the reference count by 1. Imposes no memory ordering.
+ inline void Increment() { count_.fetch_add(1, std::memory_order_relaxed); }
// Asserts that the current refcount is greater than 0. If the refcount is
- // greater than 1, decrements the reference count.
+ // greater than 1, decrements the reference count by 1.
//
// 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. Always returns false when the immortal bit is set.
+ // false.
inline bool Decrement() {
- int32_t refcount = count_.load(std::memory_order_acquire) & kRefcountMask;
- assert(refcount > 0 || refcount & kImmortalFlag);
- return refcount != kRefIncrement &&
- (count_.fetch_sub(kRefIncrement, std::memory_order_acq_rel) &
- kRefcountMask) != kRefIncrement;
+ int32_t refcount = count_.load(std::memory_order_acquire);
+ assert(refcount > 0);
+ return refcount != 1 && count_.fetch_sub(1, std::memory_order_acq_rel) != 1;
}
// 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) &
- kRefcountMask;
- assert(refcount > 0 || refcount & kImmortalFlag);
- return refcount != kRefIncrement;
+ int32_t refcount = count_.fetch_sub(1, std::memory_order_acq_rel);
+ assert(refcount > 0);
+ return refcount != 1;
}
// Returns the current reference count using acquire semantics.
- inline int32_t Get() const {
- return count_.load(std::memory_order_acquire) >> kNumFlags;
- }
-
- // Returns true if the referenced object carries a CRC value.
- bool HasCrc() const {
- return (count_.load(std::memory_order_relaxed) & kCrcFlag) != 0;
- }
-
- // Returns true iff the atomic integer is 1 and this node does not store
- // a CRC. When both these conditions are met, the current thread owns
- // the reference and no other thread shares it, so its contents may be
- // safely mutated.
- //
- // If the referenced item is shared, carries a CRC, or is immortal,
- // it should not be modified in-place, and this function returns false.
- //
- // This call performs the memory barrier needed for the owning thread
- // to act on the object, so that if it returns true, it may safely
- // assume exclusive access to the object.
- inline bool IsMutable() {
- return (count_.load(std::memory_order_acquire)) == kRefIncrement;
- }
-
- // Returns whether the atomic integer is 1. Similar to IsMutable(),
- // but does not check for a stored CRC. (An unshared node with a CRC is not
- // mutable, because changing its data would invalidate the CRC.)
- //
- // When this returns true, there are no other references, and data sinks
- // may safely adopt the children of the CordRep.
- inline bool IsOne() {
- return (count_.load(std::memory_order_acquire) & kRefcountMask) ==
- kRefIncrement;
- }
-
- bool IsImmortal() const {
- return (count_.load(std::memory_order_relaxed) & kImmortalFlag) != 0;
- }
+ inline int32_t Get() const { return count_.load(std::memory_order_acquire); }
+
+ // 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) == 1; }
private:
- // We reserve the bottom bits for flags.
- // kImmortalBit indicates that this entity should never be collected; it is
- // used for the StringConstant constructor to avoid collecting immutable
- // constant cords.
- // kReservedFlag is reserved for future use.
- enum {
- kNumFlags = 2,
-
- kImmortalFlag = 0x1,
- kCrcFlag = 0x2,
- kRefIncrement = (1 << kNumFlags),
-
- // Bitmask to use when checking refcount by equality. This masks out
- // all flags except kImmortalFlag, which is part of the refcount for
- // purposes of equality. (A refcount of 0 or 1 does not count as 0 or 1
- // if the immortal bit is set.)
- kRefcountMask = ~kCrcFlag,
- };
-
std::atomic<int32_t> count_;
};
@@ -189,106 +80,34 @@ class RefcountAndFlags {
// functions in the base class.
struct CordRepConcat;
-struct CordRepExternal;
-struct CordRepFlat;
struct CordRepSubstring;
-class CordRepRing;
-class CordRepBtree;
-
-// Various representations that we allow
-enum CordRepKind {
- CONCAT = 0,
- SUBSTRING = 1,
- BTREE = 2,
- RING = 3,
- EXTERNAL = 4,
-
- // We have different tags for different sized flat arrays,
- // starting with FLAT, and limited to MAX_FLAT_TAG. The 225 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 = 5,
- MAX_FLAT_TAG = 225
-};
-
-// There are various locations where we want to check if some rep is a 'plain'
-// data edge, i.e. an external or flat rep. By having FLAT == EXTERNAL + 1, we
-// can perform this check in a single branch as 'tag >= EXTERNAL'
-// Likewise, we have some locations where we check for 'ring or external/flat',
-// so likewise align RING to EXTERNAL.
-// Note that we can leave this optimization to the compiler. The compiler will
-// DTRT when it sees a condition like `tag == EXTERNAL || tag >= FLAT`.
-static_assert(RING == BTREE + 1, "BTREE and RING not consecutive");
-static_assert(EXTERNAL == RING + 1, "BTREE and EXTERNAL not consecutive");
-static_assert(FLAT == EXTERNAL + 1, "EXTERNAL and FLAT not consecutive");
+struct CordRepExternal;
struct CordRep {
- CordRep() = default;
- constexpr CordRep(RefcountAndFlags::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;
- RefcountAndFlags refcount;
+ // We use uint64_t for the length even in 32-bit binaries.
+ uint64_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 data[1]; // Starting point for flat array: MUST BE LAST FIELD of CordRep
- // `storage` provides two main purposes:
- // - the starting point for FlatCordRep.Data() [flexible-array-member]
- // - 3 bytes of additional storage for use by derived classes.
- // The latter is used by CordrepConcat and CordRepBtree. CordRepConcat stores
- // a 'depth' value in storage[0], and the (future) CordRepBtree class stores
- // `height`, `begin` and `end` in the 3 entries. Otherwise we would need to
- // allocate room for these in the derived class, as not all compilers reuse
- // padding space from the base class (clang and gcc do, MSVC does not, etc)
- uint8_t storage[3];
-
- // Returns true if this instance's tag matches the requested type.
- constexpr bool IsRing() const { return tag == RING; }
- constexpr bool IsConcat() const { return tag == CONCAT; }
- constexpr bool IsSubstring() const { return tag == SUBSTRING; }
- constexpr bool IsExternal() const { return tag == EXTERNAL; }
- constexpr bool IsFlat() const { return tag >= FLAT; }
- constexpr bool IsBtree() const { return tag == BTREE; }
-
- 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;
- inline CordRepBtree* btree();
- inline const CordRepBtree* btree() 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 storage[0]; }
- void set_depth(uint8_t depth) { storage[0] = depth; }
+ uint8_t depth() const { return static_cast<uint8_t>(data[0]); }
+ void set_depth(uint8_t depth) { data[0] = static_cast<char>(depth); }
};
struct CordRepSubstring : public CordRep {
@@ -296,325 +115,37 @@ struct CordRepSubstring : public CordRep {
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(RefcountAndFlags::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->IsExternal()
- 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->IsExternal());
- 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;
+// TODO(strel): replace the following logic (and related functions in cord.cc)
+// with container_internal::Layout.
-// 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;
+// Alignment requirement for CordRepExternal so that the type erased releaser
+// will be stored at a suitably aligned address.
+constexpr size_t ExternalRepAlignment() {
+#if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ return __STDCPP_DEFAULT_NEW_ALIGNMENT__;
#else
- return static_cast<cordz_info_t>(value) << ((sizeof(cordz_info_t) - 1) * 8);
+ return alignof(max_align_t);
#endif
}
-class InlineData {
- public:
- // DefaultInitType forces the use of the default initialization constructor.
- enum DefaultInitType { kDefaultInit };
-
- // 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);
-
- constexpr InlineData() : as_chars_{0} {}
- explicit InlineData(DefaultInitType) {}
- explicit constexpr InlineData(CordRep* rep) : as_tree_(rep) {}
- explicit constexpr InlineData(absl::string_view chars)
- : as_chars_{
- GetOrNull(chars, 0), GetOrNull(chars, 1),
- GetOrNull(chars, 2), GetOrNull(chars, 3),
- GetOrNull(chars, 4), GetOrNull(chars, 5),
- GetOrNull(chars, 6), GetOrNull(chars, 7),
- GetOrNull(chars, 8), GetOrNull(chars, 9),
- GetOrNull(chars, 10), GetOrNull(chars, 11),
- GetOrNull(chars, 12), GetOrNull(chars, 13),
- GetOrNull(chars, 14), static_cast<char>((chars.size() << 1))} {}
-
- // 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 true if either of the provided instances hold a cordz_info value.
- // This method is more efficient than the equivalent `data1.is_profiled() ||
- // data2.is_profiled()`. Requires both arguments to hold a tree.
- static bool is_either_profiled(const InlineData& data1,
- const InlineData& data2) {
- assert(data1.is_tree() && data2.is_tree());
- return (data1.as_tree_.cordz_info | data2.as_tree_.cordz_info) !=
- kNullCordzInfo;
- }
+// Type for function pointer that will invoke and destroy the type-erased
+// releaser function object. Accepts a pointer to the releaser and the
+// `string_view` that were passed in to `NewExternalRep` below. The return value
+// is the size of the `Releaser` type.
+using ExternalReleaserInvoker = size_t (*)(void*, absl::string_view);
- // 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);
- }
-
- 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_;
- };
+// External CordReps are allocated together with a type erased releaser. The
+// releaser is stored in the memory directly following the CordRepExternal.
+struct alignas(ExternalRepAlignment()) CordRepExternal : public CordRep {
+ const char* base;
+ // Pointer to function that knows how to call and destroy the releaser.
+ ExternalReleaserInvoker releaser_invoker;
};
-static_assert(sizeof(InlineData) == kMaxInline + 1, "");
-
-inline CordRepConcat* CordRep::concat() {
- assert(IsConcat());
- return static_cast<CordRepConcat*>(this);
-}
-
-inline const CordRepConcat* CordRep::concat() const {
- assert(IsConcat());
- return static_cast<const CordRepConcat*>(this);
-}
-
-inline CordRepSubstring* CordRep::substring() {
- assert(IsSubstring());
- return static_cast<CordRepSubstring*>(this);
-}
-
-inline const CordRepSubstring* CordRep::substring() const {
- assert(IsSubstring());
- return static_cast<const CordRepSubstring*>(this);
-}
-
-inline CordRepExternal* CordRep::external() {
- assert(IsExternal());
- return static_cast<CordRepExternal*>(this);
-}
-
-inline const CordRepExternal* CordRep::external() const {
- assert(IsExternal());
- 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);
- }
-}
+// TODO(strel): look into removing, it doesn't seem like anything relies on this
+static_assert(sizeof(CordRepConcat) == sizeof(CordRepSubstring), "");
} // namespace cord_internal
-
ABSL_NAMESPACE_END
} // namespace absl
#endif // ABSL_STRINGS_INTERNAL_CORD_INTERNAL_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_internal_test.cc b/third_party/abseil-cpp/absl/strings/internal/cord_internal_test.cc
deleted file mode 100644
index 0758dfef38..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_internal_test.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// 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/strings/internal/cord_internal.h"
-
-#include "gmock/gmock.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-TEST(RefcountAndFlags, NormalRefcount) {
- for (bool expect_high_refcount : {false, true}) {
- SCOPED_TRACE(expect_high_refcount);
- RefcountAndFlags refcount;
- // count = 1
-
- EXPECT_FALSE(refcount.HasCrc());
- EXPECT_TRUE(refcount.IsMutable());
- EXPECT_TRUE(refcount.IsOne());
-
- refcount.Increment();
- // count = 2
-
- EXPECT_FALSE(refcount.HasCrc());
- EXPECT_FALSE(refcount.IsMutable());
- EXPECT_FALSE(refcount.IsOne());
-
- // Decrementing should return true, since a reference is outstanding.
- if (expect_high_refcount) {
- EXPECT_TRUE(refcount.DecrementExpectHighRefcount());
- } else {
- EXPECT_TRUE(refcount.Decrement());
- }
- // count = 1
-
- EXPECT_FALSE(refcount.HasCrc());
- EXPECT_TRUE(refcount.IsMutable());
- EXPECT_TRUE(refcount.IsOne());
-
- // One more decremnt will return false, as no references remain.
- if (expect_high_refcount) {
- EXPECT_FALSE(refcount.DecrementExpectHighRefcount());
- } else {
- EXPECT_FALSE(refcount.Decrement());
- }
- }
-}
-
-TEST(RefcountAndFlags, CrcRefcount) {
- for (bool expect_high_refcount : {false, true}) {
- SCOPED_TRACE(expect_high_refcount);
- RefcountAndFlags refcount(RefcountAndFlags::WithCrc{});
- // count = 1
-
- // A CRC-carrying node is never mutable, but can be unshared
- EXPECT_TRUE(refcount.HasCrc());
- EXPECT_FALSE(refcount.IsMutable());
- EXPECT_TRUE(refcount.IsOne());
-
- refcount.Increment();
- // count = 2
-
- EXPECT_TRUE(refcount.HasCrc());
- EXPECT_FALSE(refcount.IsMutable());
- EXPECT_FALSE(refcount.IsOne());
-
- // Decrementing should return true, since a reference is outstanding.
- if (expect_high_refcount) {
- EXPECT_TRUE(refcount.DecrementExpectHighRefcount());
- } else {
- EXPECT_TRUE(refcount.Decrement());
- }
- // count = 1
-
- EXPECT_TRUE(refcount.HasCrc());
- EXPECT_FALSE(refcount.IsMutable());
- EXPECT_TRUE(refcount.IsOne());
-
- // One more decremnt will return false, as no references remain.
- if (expect_high_refcount) {
- EXPECT_FALSE(refcount.DecrementExpectHighRefcount());
- } else {
- EXPECT_FALSE(refcount.Decrement());
- }
- }
-}
-
-TEST(RefcountAndFlags, ImmortalRefcount) {
- RefcountAndFlags immortal_refcount(RefcountAndFlags::Immortal{});
-
- for (int i = 0; i < 100; ++i) {
- // An immortal refcount is never unshared, and decrementing never causes
- // a collection.
- EXPECT_FALSE(immortal_refcount.HasCrc());
- EXPECT_FALSE(immortal_refcount.IsMutable());
- EXPECT_FALSE(immortal_refcount.IsOne());
- EXPECT_TRUE(immortal_refcount.Decrement());
- EXPECT_TRUE(immortal_refcount.DecrementExpectHighRefcount());
- }
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc
deleted file mode 100644
index 4404f33a12..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.cc
+++ /dev/null
@@ -1,1128 +0,0 @@
-// 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/strings/internal/cord_rep_btree.h"
-
-#include <cassert>
-#include <cstdint>
-#include <iostream>
-#include <string>
-
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_consume.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-constexpr size_t CordRepBtree::kMaxCapacity; // NOLINT: needed for c++ < c++17
-
-namespace {
-
-using NodeStack = CordRepBtree * [CordRepBtree::kMaxDepth];
-using EdgeType = CordRepBtree::EdgeType;
-using OpResult = CordRepBtree::OpResult;
-using CopyResult = CordRepBtree::CopyResult;
-
-constexpr auto kFront = CordRepBtree::kFront;
-constexpr auto kBack = CordRepBtree::kBack;
-
-inline bool exhaustive_validation() {
- return cord_btree_exhaustive_validation.load(std::memory_order_relaxed);
-}
-
-// Implementation of the various 'Dump' functions.
-// Prints the entire tree structure or 'rep'. External callers should
-// not specify 'depth' and leave it to its default (0) value.
-// Rep may be a CordRepBtree tree, or a SUBSTRING / EXTERNAL / FLAT node.
-void DumpAll(const CordRep* rep, bool include_contents, std::ostream& stream,
- int depth = 0) {
- // Allow for full height trees + substring -> flat / external nodes.
- assert(depth <= CordRepBtree::kMaxDepth + 2);
- std::string sharing = const_cast<CordRep*>(rep)->refcount.IsOne()
- ? std::string("Private")
- : absl::StrCat("Shared(", rep->refcount.Get(), ")");
- std::string sptr = absl::StrCat("0x", absl::Hex(rep));
-
- // Dumps the data contents of `rep` if `include_contents` is true.
- // Always emits a new line character.
- auto maybe_dump_data = [&stream, include_contents](const CordRep* r) {
- if (include_contents) {
- // Allow for up to 60 wide display of content data, which with some
- // indentation and prefix / labels keeps us within roughly 80-100 wide.
- constexpr size_t kMaxDataLength = 60;
- stream << ", data = \""
- << CordRepBtree::EdgeData(r).substr(0, kMaxDataLength)
- << (r->length > kMaxDataLength ? "\"..." : "\"");
- }
- stream << '\n';
- };
-
- // For each level, we print the 'shared/private' state and the rep pointer,
- // indented by two spaces per recursive depth.
- stream << std::string(depth * 2, ' ') << sharing << " (" << sptr << ") ";
-
- if (rep->IsBtree()) {
- const CordRepBtree* node = rep->btree();
- std::string label =
- node->height() ? absl::StrCat("Node(", node->height(), ")") : "Leaf";
- stream << label << ", len = " << node->length
- << ", begin = " << node->begin() << ", end = " << node->end()
- << "\n";
- for (CordRep* edge : node->Edges()) {
- DumpAll(edge, include_contents, stream, depth + 1);
- }
- } else if (rep->tag == SUBSTRING) {
- const CordRepSubstring* substring = rep->substring();
- stream << "Substring, len = " << rep->length
- << ", start = " << substring->start;
- maybe_dump_data(rep);
- DumpAll(substring->child, include_contents, stream, depth + 1);
- } else if (rep->tag >= FLAT) {
- stream << "Flat, len = " << rep->length
- << ", cap = " << rep->flat()->Capacity();
- maybe_dump_data(rep);
- } else if (rep->tag == EXTERNAL) {
- stream << "Extn, len = " << rep->length;
- maybe_dump_data(rep);
- }
-}
-
-// TODO(b/192061034): add 'bytes to copy' logic to avoid large slop on substring
-// small data out of large reps, and general efficiency of 'always copy small
-// data'. Consider making this a cord rep internal library function.
-CordRepSubstring* CreateSubstring(CordRep* rep, size_t offset, size_t n) {
- assert(n != 0);
- assert(offset + n <= rep->length);
- assert(offset != 0 || n != rep->length);
-
- if (rep->tag == SUBSTRING) {
- CordRepSubstring* substring = rep->substring();
- offset += substring->start;
- rep = CordRep::Ref(substring->child);
- CordRep::Unref(substring);
- }
- CordRepSubstring* substring = new CordRepSubstring();
- substring->length = n;
- substring->tag = SUBSTRING;
- substring->start = offset;
- substring->child = rep;
- return substring;
-}
-
-// TODO(b/192061034): consider making this a cord rep library function.
-inline CordRep* MakeSubstring(CordRep* rep, size_t offset, size_t n) {
- if (n == rep->length) return rep;
- if (n == 0) return CordRep::Unref(rep), nullptr;
- return CreateSubstring(rep, offset, n);
-}
-
-// TODO(b/192061034): consider making this a cord rep library function.
-inline CordRep* MakeSubstring(CordRep* rep, size_t offset) {
- if (offset == 0) return rep;
- return CreateSubstring(rep, offset, rep->length - offset);
-}
-
-// Resizes `edge` to the provided `length`. Adopts a reference on `edge`.
-// This method directly returns `edge` if `length` equals `edge->length`.
-// If `is_mutable` is set to true, this function may return `edge` with
-// `edge->length` set to the new length depending on the type and size of
-// `edge`. Otherwise, this function returns a new CordRepSubstring value.
-// Requires `length > 0 && length <= edge->length`.
-CordRep* ResizeEdge(CordRep* edge, size_t length, bool is_mutable) {
- assert(length > 0);
- assert(length <= edge->length);
- assert(CordRepBtree::IsDataEdge(edge));
- if (length >= edge->length) return edge;
-
- if (is_mutable && (edge->tag >= FLAT || edge->tag == SUBSTRING)) {
- edge->length = length;
- return edge;
- }
-
- return CreateSubstring(edge, 0, length);
-}
-
-template <EdgeType edge_type>
-inline absl::string_view Consume(absl::string_view s, size_t n) {
- return edge_type == kBack ? s.substr(n) : s.substr(0, s.size() - n);
-}
-
-template <EdgeType edge_type>
-inline absl::string_view Consume(char* dst, absl::string_view s, size_t n) {
- if (edge_type == kBack) {
- memcpy(dst, s.data(), n);
- return s.substr(n);
- } else {
- const size_t offset = s.size() - n;
- memcpy(dst, s.data() + offset, n);
- return s.substr(0, offset);
- }
-}
-
-// Known issue / optimization weirdness: the store associated with the
-// decrement introduces traffic between cpus (even if the result of that
-// traffic does nothing), making this faster than a single call to
-// refcount.Decrement() checking the zero refcount condition.
-template <typename R, typename Fn>
-inline void FastUnref(R* r, Fn&& fn) {
- if (r->refcount.IsOne()) {
- fn(r);
- } else if (!r->refcount.DecrementExpectHighRefcount()) {
- fn(r);
- }
-}
-
-// Deletes a leaf node data edge. Requires `rep` to be an EXTERNAL or FLAT
-// node, or a SUBSTRING of an EXTERNAL or FLAT node.
-void DeleteLeafEdge(CordRep* rep) {
- for (;;) {
- if (rep->tag >= FLAT) {
- CordRepFlat::Delete(rep->flat());
- return;
- }
- if (rep->tag == EXTERNAL) {
- CordRepExternal::Delete(rep->external());
- return;
- }
- assert(rep->tag == SUBSTRING);
- CordRepSubstring* substring = rep->substring();
- rep = substring->child;
- assert(rep->tag == EXTERNAL || rep->tag >= FLAT);
- delete substring;
- if (rep->refcount.Decrement()) return;
- }
-}
-
-// StackOperations contains the logic to build a left-most or right-most stack
-// (leg) down to the leaf level of a btree, and 'unwind' / 'Finalize' methods to
-// propagate node changes up the stack.
-template <EdgeType edge_type>
-struct StackOperations {
- // Returns true if the node at 'depth' is mutable, i.e. has a refcount
- // of one, carries no CRC, and all of its parent nodes have a refcount of one.
- inline bool owned(int depth) const { return depth < share_depth; }
-
- // Returns the node at 'depth'.
- inline CordRepBtree* node(int depth) const { return stack[depth]; }
-
- // Builds a `depth` levels deep stack starting at `tree` recording which nodes
- // are private in the form of the 'share depth' where nodes are shared.
- inline CordRepBtree* BuildStack(CordRepBtree* tree, int depth) {
- assert(depth <= tree->height());
- int current_depth = 0;
- while (current_depth < depth && tree->refcount.IsMutable()) {
- stack[current_depth++] = tree;
- tree = tree->Edge(edge_type)->btree();
- }
- share_depth = current_depth + (tree->refcount.IsMutable() ? 1 : 0);
- while (current_depth < depth) {
- stack[current_depth++] = tree;
- tree = tree->Edge(edge_type)->btree();
- }
- return tree;
- }
-
- // Builds a stack with the invariant that all nodes are private owned / not
- // shared and carry no CRC data. This is used in iterative updates where a
- // previous propagation guaranteed all nodes have this property.
- inline void BuildOwnedStack(CordRepBtree* tree, int height) {
- assert(height <= CordRepBtree::kMaxHeight);
- int depth = 0;
- while (depth < height) {
- assert(tree->refcount.IsMutable());
- stack[depth++] = tree;
- tree = tree->Edge(edge_type)->btree();
- }
- assert(tree->refcount.IsMutable());
- share_depth = depth + 1;
- }
-
- // Processes the final 'top level' result action for the tree.
- // See the 'Action' enum for the various action implications.
- static inline CordRepBtree* Finalize(CordRepBtree* tree, OpResult result) {
- switch (result.action) {
- case CordRepBtree::kPopped:
- tree = edge_type == kBack ? CordRepBtree::New(tree, result.tree)
- : CordRepBtree::New(result.tree, tree);
- if (ABSL_PREDICT_FALSE(tree->height() > CordRepBtree::kMaxHeight)) {
- tree = CordRepBtree::Rebuild(tree);
- ABSL_RAW_CHECK(tree->height() <= CordRepBtree::kMaxHeight,
- "Max height exceeded");
- }
- return tree;
- case CordRepBtree::kCopied:
- CordRep::Unref(tree);
- ABSL_FALLTHROUGH_INTENDED;
- case CordRepBtree::kSelf:
- return result.tree;
- }
- ABSL_INTERNAL_UNREACHABLE;
- return result.tree;
- }
-
- // Propagate the action result in 'result' up into all nodes of the stack
- // starting at depth 'depth'. 'length' contains the extra length of data that
- // was added at the lowest level, and is updated into all nodes of the stack.
- // See the 'Action' enum for the various action implications.
- // If 'propagate' is true, then any copied node values are updated into the
- // stack, which is used for iterative processing on the same stack.
- template <bool propagate = false>
- inline CordRepBtree* Unwind(CordRepBtree* tree, int depth, size_t length,
- OpResult result) {
- // TODO(mvels): revisit the below code to check if 3 loops with 3
- // (incremental) conditions is faster than 1 loop with a switch.
- // Benchmarking and perf recordings indicate the loop with switch is
- // fastest, likely because of indirect jumps on the tight case values and
- // dense branches. But it's worth considering 3 loops, as the `action`
- // transitions are mono directional. E.g.:
- // while (action == kPopped) {
- // ...
- // }
- // while (action == kCopied) {
- // ...
- // }
- // ...
- // We also found that an "if () do {}" loop here seems faster, possibly
- // because it allows the branch predictor more granular heuristics on
- // 'single leaf' (`depth` == 0) and 'single depth' (`depth` == 1) cases
- // which appear to be the most common use cases.
- if (depth != 0) {
- do {
- CordRepBtree* node = stack[--depth];
- const bool owned = depth < share_depth;
- switch (result.action) {
- case CordRepBtree::kPopped:
- assert(!propagate);
- result = node->AddEdge<edge_type>(owned, result.tree, length);
- break;
- case CordRepBtree::kCopied:
- result = node->SetEdge<edge_type>(owned, result.tree, length);
- if (propagate) stack[depth] = result.tree;
- break;
- case CordRepBtree::kSelf:
- node->length += length;
- while (depth > 0) {
- node = stack[--depth];
- node->length += length;
- }
- return node;
- }
- } while (depth > 0);
- }
- return Finalize(tree, result);
- }
-
- // Invokes `Unwind` with `propagate=true` to update the stack node values.
- inline CordRepBtree* Propagate(CordRepBtree* tree, int depth, size_t length,
- OpResult result) {
- return Unwind</*propagate=*/true>(tree, depth, length, result);
- }
-
- // `share_depth` contains the depth at which the nodes in the stack cannot
- // be mutated. I.e., if the top most level is shared (i.e.:
- // `!refcount.IsMutable()`), then `share_depth` is 0. If the 2nd node
- // is shared (and implicitly all nodes below that) then `share_depth` is 1,
- // etc. A `share_depth` greater than the depth of the stack indicates that
- // none of the nodes in the stack are shared.
- int share_depth;
-
- NodeStack stack;
-};
-
-} // namespace
-
-void CordRepBtree::Dump(const CordRep* rep, absl::string_view label,
- bool include_contents, std::ostream& stream) {
- stream << "===================================\n";
- if (!label.empty()) {
- stream << label << '\n';
- stream << "-----------------------------------\n";
- }
- if (rep) {
- DumpAll(rep, include_contents, stream);
- } else {
- stream << "NULL\n";
- }
-}
-
-void CordRepBtree::Dump(const CordRep* rep, absl::string_view label,
- std::ostream& stream) {
- Dump(rep, label, false, stream);
-}
-
-void CordRepBtree::Dump(const CordRep* rep, std::ostream& stream) {
- Dump(rep, absl::string_view(), false, stream);
-}
-
-void CordRepBtree::DestroyLeaf(CordRepBtree* tree, size_t begin, size_t end) {
- for (CordRep* edge : tree->Edges(begin, end)) {
- FastUnref(edge, DeleteLeafEdge);
- }
- Delete(tree);
-}
-
-void CordRepBtree::DestroyNonLeaf(CordRepBtree* tree, size_t begin,
- size_t end) {
- for (CordRep* edge : tree->Edges(begin, end)) {
- FastUnref(edge->btree(), Destroy);
- }
- Delete(tree);
-}
-
-bool CordRepBtree::IsValid(const CordRepBtree* tree, bool shallow) {
-#define NODE_CHECK_VALID(x) \
- if (!(x)) { \
- ABSL_RAW_LOG(ERROR, "CordRepBtree::CheckValid() FAILED: %s", #x); \
- return false; \
- }
-#define NODE_CHECK_EQ(x, y) \
- if ((x) != (y)) { \
- ABSL_RAW_LOG(ERROR, \
- "CordRepBtree::CheckValid() FAILED: %s != %s (%s vs %s)", #x, \
- #y, absl::StrCat(x).c_str(), absl::StrCat(y).c_str()); \
- return false; \
- }
-
- NODE_CHECK_VALID(tree != nullptr);
- NODE_CHECK_VALID(tree->IsBtree());
- NODE_CHECK_VALID(tree->height() <= kMaxHeight);
- NODE_CHECK_VALID(tree->begin() < tree->capacity());
- NODE_CHECK_VALID(tree->end() <= tree->capacity());
- NODE_CHECK_VALID(tree->begin() <= tree->end());
- size_t child_length = 0;
- for (CordRep* edge : tree->Edges()) {
- NODE_CHECK_VALID(edge != nullptr);
- if (tree->height() > 0) {
- NODE_CHECK_VALID(edge->IsBtree());
- NODE_CHECK_VALID(edge->btree()->height() == tree->height() - 1);
- } else {
- NODE_CHECK_VALID(IsDataEdge(edge));
- }
- child_length += edge->length;
- }
- NODE_CHECK_EQ(child_length, tree->length);
- if ((!shallow || exhaustive_validation()) && tree->height() > 0) {
- for (CordRep* edge : tree->Edges()) {
- if (!IsValid(edge->btree(), shallow)) return false;
- }
- }
- return true;
-
-#undef NODE_CHECK_VALID
-#undef NODE_CHECK_EQ
-}
-
-#ifndef NDEBUG
-
-CordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree, bool shallow) {
- if (!IsValid(tree, shallow)) {
- Dump(tree, "CordRepBtree validation failed:", false, std::cout);
- ABSL_RAW_LOG(FATAL, "CordRepBtree::CheckValid() FAILED");
- }
- return tree;
-}
-
-const CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,
- bool shallow) {
- if (!IsValid(tree, shallow)) {
- Dump(tree, "CordRepBtree validation failed:", false, std::cout);
- ABSL_RAW_LOG(FATAL, "CordRepBtree::CheckValid() FAILED");
- }
- return tree;
-}
-
-#endif // NDEBUG
-
-template <EdgeType edge_type>
-inline OpResult CordRepBtree::AddEdge(bool owned, CordRep* edge, size_t delta) {
- if (size() >= kMaxCapacity) return {New(edge), kPopped};
- OpResult result = ToOpResult(owned);
- result.tree->Add<edge_type>(edge);
- result.tree->length += delta;
- return result;
-}
-
-template <EdgeType edge_type>
-OpResult CordRepBtree::SetEdge(bool owned, CordRep* edge, size_t delta) {
- OpResult result;
- const size_t idx = index(edge_type);
- if (owned) {
- result = {this, kSelf};
- CordRep::Unref(edges_[idx]);
- } else {
- // Create a copy containing all unchanged edges. Unchanged edges are the
- // open interval [begin, back) or [begin + 1, end) depending on `edge_type`.
- // We conveniently cover both case using a constexpr `shift` being 0 or 1
- // as `end :== back + 1`.
- result = {CopyRaw(), kCopied};
- constexpr int shift = edge_type == kFront ? 1 : 0;
- for (CordRep* r : Edges(begin() + shift, back() + shift)) {
- CordRep::Ref(r);
- }
- }
- result.tree->edges_[idx] = edge;
- result.tree->length += delta;
- return result;
-}
-
-template <EdgeType edge_type>
-CordRepBtree* CordRepBtree::AddCordRep(CordRepBtree* tree, CordRep* rep) {
- const int depth = tree->height();
- const size_t length = rep->length;
- StackOperations<edge_type> ops;
- CordRepBtree* leaf = ops.BuildStack(tree, depth);
- const OpResult result =
- leaf->AddEdge<edge_type>(ops.owned(depth), rep, length);
- return ops.Unwind(tree, depth, length, result);
-}
-
-template <>
-CordRepBtree* CordRepBtree::NewLeaf<kBack>(absl::string_view data,
- size_t extra) {
- CordRepBtree* leaf = CordRepBtree::New(0);
- size_t length = 0;
- size_t end = 0;
- const size_t cap = leaf->capacity();
- while (!data.empty() && end != cap) {
- auto* flat = CordRepFlat::New(data.length() + extra);
- flat->length = (std::min)(data.length(), flat->Capacity());
- length += flat->length;
- leaf->edges_[end++] = flat;
- data = Consume<kBack>(flat->Data(), data, flat->length);
- }
- leaf->length = length;
- leaf->set_end(end);
- return leaf;
-}
-
-template <>
-CordRepBtree* CordRepBtree::NewLeaf<kFront>(absl::string_view data,
- size_t extra) {
- CordRepBtree* leaf = CordRepBtree::New(0);
- size_t length = 0;
- size_t begin = leaf->capacity();
- leaf->set_end(leaf->capacity());
- while (!data.empty() && begin != 0) {
- auto* flat = CordRepFlat::New(data.length() + extra);
- flat->length = (std::min)(data.length(), flat->Capacity());
- length += flat->length;
- leaf->edges_[--begin] = flat;
- data = Consume<kFront>(flat->Data(), data, flat->length);
- }
- leaf->length = length;
- leaf->set_begin(begin);
- return leaf;
-}
-
-template <>
-absl::string_view CordRepBtree::AddData<kBack>(absl::string_view data,
- size_t extra) {
- assert(!data.empty());
- assert(size() < capacity());
- AlignBegin();
- const size_t cap = capacity();
- do {
- CordRepFlat* flat = CordRepFlat::New(data.length() + extra);
- const size_t n = (std::min)(data.length(), flat->Capacity());
- flat->length = n;
- edges_[fetch_add_end(1)] = flat;
- data = Consume<kBack>(flat->Data(), data, n);
- } while (!data.empty() && end() != cap);
- return data;
-}
-
-template <>
-absl::string_view CordRepBtree::AddData<kFront>(absl::string_view data,
- size_t extra) {
- assert(!data.empty());
- assert(size() < capacity());
- AlignEnd();
- do {
- CordRepFlat* flat = CordRepFlat::New(data.length() + extra);
- const size_t n = (std::min)(data.length(), flat->Capacity());
- flat->length = n;
- edges_[sub_fetch_begin(1)] = flat;
- data = Consume<kFront>(flat->Data(), data, n);
- } while (!data.empty() && begin() != 0);
- return data;
-}
-
-template <EdgeType edge_type>
-CordRepBtree* CordRepBtree::AddData(CordRepBtree* tree, absl::string_view data,
- size_t extra) {
- if (ABSL_PREDICT_FALSE(data.empty())) return tree;
-
- const size_t original_data_size = data.size();
- int depth = tree->height();
- StackOperations<edge_type> ops;
- CordRepBtree* leaf = ops.BuildStack(tree, depth);
-
- // If there is capacity in the last edge, append as much data
- // as possible into this last edge.
- if (leaf->size() < leaf->capacity()) {
- OpResult result = leaf->ToOpResult(ops.owned(depth));
- data = result.tree->AddData<edge_type>(data, extra);
- if (data.empty()) {
- result.tree->length += original_data_size;
- return ops.Unwind(tree, depth, original_data_size, result);
- }
-
- // We added some data into this leaf, but not all. Propagate the added
- // length to the top most node, and rebuild the stack with any newly copied
- // or updated nodes. From this point on, the path (leg) from the top most
- // node to the right-most node towards the leaf node is privately owned.
- size_t delta = original_data_size - data.size();
- assert(delta > 0);
- result.tree->length += delta;
- tree = ops.Propagate(tree, depth, delta, result);
- ops.share_depth = depth + 1;
- }
-
- // We were unable to append all data into the existing right-most leaf node.
- // This means all remaining data must be put into (a) new leaf node(s) which
- // we append to the tree. To make this efficient, we iteratively build full
- // leaf nodes from `data` until the created leaf contains all remaining data.
- // We utilize the `Unwind` method to merge the created leaf into the first
- // level towards root that has capacity. On each iteration with remaining
- // data, we rebuild the stack in the knowledge that right-most nodes are
- // privately owned after the first `Unwind` completes.
- for (;;) {
- OpResult result = {CordRepBtree::NewLeaf<edge_type>(data, extra), kPopped};
- if (result.tree->length == data.size()) {
- return ops.Unwind(tree, depth, result.tree->length, result);
- }
- data = Consume<edge_type>(data, result.tree->length);
- tree = ops.Unwind(tree, depth, result.tree->length, result);
- depth = tree->height();
- ops.BuildOwnedStack(tree, depth);
- }
-}
-
-template <EdgeType edge_type>
-CordRepBtree* CordRepBtree::Merge(CordRepBtree* dst, CordRepBtree* src) {
- assert(dst->height() >= src->height());
-
- // Capture source length as we may consume / destroy `src`.
- const size_t length = src->length;
-
- // We attempt to merge `src` at its corresponding height in `dst`.
- const int depth = dst->height() - src->height();
- StackOperations<edge_type> ops;
- CordRepBtree* merge_node = ops.BuildStack(dst, depth);
-
- // If there is enough space in `merge_node` for all edges from `src`, add all
- // edges to this node, making a fresh copy as needed if not privately owned.
- // If `merge_node` does not have capacity for `src`, we rely on `Unwind` and
- // `Finalize` to merge `src` into the first level towards `root` where there
- // is capacity for another edge, or create a new top level node.
- OpResult result;
- if (merge_node->size() + src->size() <= kMaxCapacity) {
- result = merge_node->ToOpResult(ops.owned(depth));
- result.tree->Add<edge_type>(src->Edges());
- result.tree->length += src->length;
- if (src->refcount.IsOne()) {
- Delete(src);
- } else {
- for (CordRep* edge : src->Edges()) CordRep::Ref(edge);
- CordRepBtree::Unref(src);
- }
- } else {
- result = {src, kPopped};
- }
-
- // Unless we merged at the top level (i.e.: src and dst are equal height),
- // unwind the result towards the top level, and finalize the result.
- if (depth) {
- return ops.Unwind(dst, depth, length, result);
- }
- return ops.Finalize(dst, result);
-}
-
-CopyResult CordRepBtree::CopySuffix(size_t offset) {
- assert(offset < this->length);
-
- // As long as `offset` starts inside the last edge, we can 'drop' the current
- // depth. For the most extreme example: if offset references the last data
- // edge in the tree, there is only a single edge / path from the top of the
- // tree to that last edge, so we can drop all the nodes except that edge.
- // The fast path check for this is `back->length >= length - offset`.
- int height = this->height();
- CordRepBtree* node = this;
- size_t len = node->length - offset;
- CordRep* back = node->Edge(kBack);
- while (back->length >= len) {
- offset = back->length - len;
- if (--height < 0) {
- return {MakeSubstring(CordRep::Ref(back), offset), height};
- }
- node = back->btree();
- back = node->Edge(kBack);
- }
- if (offset == 0) return {CordRep::Ref(node), height};
-
- // Offset does not point into the last edge, so we span at least two edges.
- // Find the index of offset with `IndexBeyond` which provides us the edge
- // 'beyond' the offset if offset is not a clean starting point of an edge.
- Position pos = node->IndexBeyond(offset);
- CordRepBtree* sub = node->CopyToEndFrom(pos.index, len);
- const CopyResult result = {sub, height};
-
- // `pos.n` contains a non zero value if the offset is not an exact starting
- // point of an edge. In this case, `pos.n` contains the 'trailing' amount of
- // bytes of the edge preceding that in `pos.index`. We need to iteratively
- // adjust the preceding edge with the 'broken' offset until we have a perfect
- // start of the edge.
- while (pos.n != 0) {
- assert(pos.index >= 1);
- const size_t begin = pos.index - 1;
- sub->set_begin(begin);
- CordRep* const edge = node->Edge(begin);
-
- len = pos.n;
- offset = edge->length - len;
-
- if (--height < 0) {
- sub->edges_[begin] = MakeSubstring(CordRep::Ref(edge), offset, len);
- return result;
- }
-
- node = edge->btree();
- pos = node->IndexBeyond(offset);
-
- CordRepBtree* nsub = node->CopyToEndFrom(pos.index, len);
- sub->edges_[begin] = nsub;
- sub = nsub;
- }
- sub->set_begin(pos.index);
- return result;
-}
-
-CopyResult CordRepBtree::CopyPrefix(size_t n, bool allow_folding) {
- assert(n > 0);
- assert(n <= this->length);
-
- // As long as `n` does not exceed the length of the first edge, we can 'drop'
- // the current depth. For the most extreme example: if we'd copy a 1 byte
- // prefix from a tree, there is only a single edge / path from the top of the
- // tree to the single data edge containing this byte, so we can drop all the
- // nodes except the data node.
- int height = this->height();
- CordRepBtree* node = this;
- CordRep* front = node->Edge(kFront);
- if (allow_folding) {
- while (front->length >= n) {
- if (--height < 0) return {MakeSubstring(CordRep::Ref(front), 0, n), -1};
- node = front->btree();
- front = node->Edge(kFront);
- }
- }
- if (node->length == n) return {CordRep::Ref(node), height};
-
- // `n` spans at least two nodes, find the end point of the span.
- Position pos = node->IndexOf(n);
-
- // Create a partial copy of the node up to `pos.index`, with a defined length
- // of `n`. Any 'partial last edge' is added further below as needed.
- CordRepBtree* sub = node->CopyBeginTo(pos.index, n);
- const CopyResult result = {sub, height};
-
- // `pos.n` contains the 'offset inside the edge for IndexOf(n)'. As long as
- // this is not zero, we don't have a 'clean cut', so we need to make a
- // (partial) copy of that last edge, and repeat this until pos.n is zero.
- while (pos.n != 0) {
- size_t end = pos.index;
- n = pos.n;
-
- CordRep* edge = node->Edge(pos.index);
- if (--height < 0) {
- sub->edges_[end++] = MakeSubstring(CordRep::Ref(edge), 0, n);
- sub->set_end(end);
- AssertValid(result.edge->btree());
- return result;
- }
-
- node = edge->btree();
- pos = node->IndexOf(n);
- CordRepBtree* nsub = node->CopyBeginTo(pos.index, n);
- sub->edges_[end++] = nsub;
- sub->set_end(end);
- sub = nsub;
- }
- sub->set_end(pos.index);
- AssertValid(result.edge->btree());
- return result;
-}
-
-CordRep* CordRepBtree::ExtractFront(CordRepBtree* tree) {
- CordRep* front = tree->Edge(tree->begin());
- if (tree->refcount.IsMutable()) {
- Unref(tree->Edges(tree->begin() + 1, tree->end()));
- CordRepBtree::Delete(tree);
- } else {
- CordRep::Ref(front);
- CordRep::Unref(tree);
- }
- return front;
-}
-
-CordRepBtree* CordRepBtree::ConsumeBeginTo(CordRepBtree* tree, size_t end,
- size_t new_length) {
- assert(end <= tree->end());
- if (tree->refcount.IsMutable()) {
- Unref(tree->Edges(end, tree->end()));
- tree->set_end(end);
- tree->length = new_length;
- } else {
- CordRepBtree* old = tree;
- tree = tree->CopyBeginTo(end, new_length);
- CordRep::Unref(old);
- }
- return tree;
-}
-
-CordRep* CordRepBtree::RemoveSuffix(CordRepBtree* tree, size_t n) {
- // Check input and deal with trivial cases 'Remove all/none'
- assert(tree != nullptr);
- assert(n <= tree->length);
- const size_t len = tree->length;
- if (ABSL_PREDICT_FALSE(n == 0)) {
- return tree;
- }
- if (ABSL_PREDICT_FALSE(n >= len)) {
- CordRepBtree::Unref(tree);
- return nullptr;
- }
-
- size_t length = len - n;
- int height = tree->height();
- bool is_mutable = tree->refcount.IsMutable();
-
- // Extract all top nodes which are reduced to size = 1
- Position pos = tree->IndexOfLength(length);
- while (pos.index == tree->begin()) {
- CordRep* edge = ExtractFront(tree);
- is_mutable &= edge->refcount.IsMutable();
- if (height-- == 0) return ResizeEdge(edge, length, is_mutable);
- tree = edge->btree();
- pos = tree->IndexOfLength(length);
- }
-
- // Repeat the following sequence traversing down the tree:
- // - Crop the top node to the 'last remaining edge' adjusting length.
- // - Set the length for down edges to the partial length in that last edge.
- // - Repeat this until the last edge is 'included in full'
- // - If we hit the data edge level, resize and return the last data edge
- CordRepBtree* top = tree = ConsumeBeginTo(tree, pos.index + 1, length);
- CordRep* edge = tree->Edge(pos.index);
- length = pos.n;
- while (length != edge->length) {
- // ConsumeBeginTo guarantees `tree` is a clean, privately owned copy.
- assert(tree->refcount.IsMutable());
- const bool edge_is_mutable = edge->refcount.IsMutable();
-
- if (height-- == 0) {
- tree->edges_[pos.index] = ResizeEdge(edge, length, edge_is_mutable);
- return AssertValid(top);
- }
-
- if (!edge_is_mutable) {
- // We can't 'in place' remove any suffixes down this edge.
- // Replace this edge with a prefix copy instead.
- tree->edges_[pos.index] = edge->btree()->CopyPrefix(length, false).edge;
- CordRep::Unref(edge);
- return AssertValid(top);
- }
-
- // Move down one level, rinse repeat.
- tree = edge->btree();
- pos = tree->IndexOfLength(length);
- tree = ConsumeBeginTo(edge->btree(), pos.index + 1, length);
- edge = tree->Edge(pos.index);
- length = pos.n;
- }
-
- return AssertValid(top);
-}
-
-CordRep* CordRepBtree::SubTree(size_t offset, size_t n) {
- assert(n <= this->length);
- assert(offset <= this->length - n);
- if (ABSL_PREDICT_FALSE(n == 0)) return nullptr;
-
- CordRepBtree* node = this;
- int height = node->height();
- Position front = node->IndexOf(offset);
- CordRep* left = node->edges_[front.index];
- while (front.n + n <= left->length) {
- if (--height < 0) return MakeSubstring(CordRep::Ref(left), front.n, n);
- node = left->btree();
- front = node->IndexOf(front.n);
- left = node->edges_[front.index];
- }
-
- const Position back = node->IndexBefore(front, n);
- CordRep* const right = node->edges_[back.index];
- assert(back.index > front.index);
-
- // Get partial suffix and prefix entries.
- CopyResult prefix;
- CopyResult suffix;
- if (height > 0) {
- // Copy prefix and suffix of the boundary nodes.
- prefix = left->btree()->CopySuffix(front.n);
- suffix = right->btree()->CopyPrefix(back.n);
-
- // If there is an edge between the prefix and suffix edges, then the tree
- // must remain at its previous (full) height. If we have no edges between
- // prefix and suffix edges, then the tree must be as high as either the
- // suffix or prefix edges (which are collapsed to their minimum heights).
- if (front.index + 1 == back.index) {
- height = (std::max)(prefix.height, suffix.height) + 1;
- }
-
- // Raise prefix and suffixes to the new tree height.
- for (int h = prefix.height + 1; h < height; ++h) {
- prefix.edge = CordRepBtree::New(prefix.edge);
- }
- for (int h = suffix.height + 1; h < height; ++h) {
- suffix.edge = CordRepBtree::New(suffix.edge);
- }
- } else {
- // Leaf node, simply take substrings for prefix and suffix.
- prefix = CopyResult{MakeSubstring(CordRep::Ref(left), front.n), -1};
- suffix = CopyResult{MakeSubstring(CordRep::Ref(right), 0, back.n), -1};
- }
-
- // Compose resulting tree.
- CordRepBtree* sub = CordRepBtree::New(height);
- size_t end = 0;
- sub->edges_[end++] = prefix.edge;
- for (CordRep* r : node->Edges(front.index + 1, back.index)) {
- sub->edges_[end++] = CordRep::Ref(r);
- }
- sub->edges_[end++] = suffix.edge;
- sub->set_end(end);
- sub->length = n;
- return AssertValid(sub);
-}
-
-CordRepBtree* CordRepBtree::MergeTrees(CordRepBtree* left,
- CordRepBtree* right) {
- return left->height() >= right->height() ? Merge<kBack>(left, right)
- : Merge<kFront>(right, left);
-}
-
-bool CordRepBtree::IsFlat(absl::string_view* fragment) const {
- if (height() == 0 && size() == 1) {
- if (fragment) *fragment = Data(begin());
- return true;
- }
- return false;
-}
-
-bool CordRepBtree::IsFlat(size_t offset, const size_t n,
- absl::string_view* fragment) const {
- assert(n <= this->length);
- assert(offset <= this->length - n);
- if (ABSL_PREDICT_FALSE(n == 0)) return false;
- int height = this->height();
- const CordRepBtree* node = this;
- for (;;) {
- const Position front = node->IndexOf(offset);
- const CordRep* edge = node->Edge(front.index);
- if (edge->length < front.n + n) return false;
- if (--height < 0) {
- if (fragment) *fragment = EdgeData(edge).substr(front.n, n);
- return true;
- }
- offset = front.n;
- node = node->Edge(front.index)->btree();
- }
-}
-
-char CordRepBtree::GetCharacter(size_t offset) const {
- assert(offset < length);
- const CordRepBtree* node = this;
- int height = node->height();
- for (;;) {
- Position front = node->IndexOf(offset);
- if (--height < 0) return node->Data(front.index)[front.n];
- offset = front.n;
- node = node->Edge(front.index)->btree();
- }
-}
-
-Span<char> CordRepBtree::GetAppendBufferSlow(size_t size) {
- // The inlined version in `GetAppendBuffer()` deals with all heights <= 3.
- assert(height() >= 4);
- assert(refcount.IsMutable());
-
- // Build a stack of nodes we may potentially need to update if we find a
- // non-shared FLAT with capacity at the leaf level.
- const int depth = height();
- CordRepBtree* node = this;
- CordRepBtree* stack[kMaxDepth];
- for (int i = 0; i < depth; ++i) {
- node = node->Edge(kBack)->btree();
- if (!node->refcount.IsMutable()) return {};
- stack[i] = node;
- }
-
- // Must be a privately owned, mutable flat.
- CordRep* const edge = node->Edge(kBack);
- if (!edge->refcount.IsMutable() || edge->tag < FLAT) return {};
-
- // Must have capacity.
- const size_t avail = edge->flat()->Capacity() - edge->length;
- if (avail == 0) return {};
-
- // Build span on remaining capacity.
- size_t delta = (std::min)(size, avail);
- Span<char> span = {edge->flat()->Data() + edge->length, delta};
- edge->length += delta;
- this->length += delta;
- for (int i = 0; i < depth; ++i) {
- stack[i]->length += delta;
- }
- return span;
-}
-
-CordRepBtree* CordRepBtree::CreateSlow(CordRep* rep) {
- if (rep->IsBtree()) return rep->btree();
-
- CordRepBtree* node = nullptr;
- auto consume = [&node](CordRep* r, size_t offset, size_t length) {
- r = MakeSubstring(r, offset, length);
- if (node == nullptr) {
- node = New(r);
- } else {
- node = CordRepBtree::AddCordRep<kBack>(node, r);
- }
- };
- Consume(rep, consume);
- return node;
-}
-
-CordRepBtree* CordRepBtree::AppendSlow(CordRepBtree* tree, CordRep* rep) {
- if (ABSL_PREDICT_TRUE(rep->IsBtree())) {
- return MergeTrees(tree, rep->btree());
- }
- auto consume = [&tree](CordRep* r, size_t offset, size_t length) {
- r = MakeSubstring(r, offset, length);
- tree = CordRepBtree::AddCordRep<kBack>(tree, r);
- };
- Consume(rep, consume);
- return tree;
-}
-
-CordRepBtree* CordRepBtree::PrependSlow(CordRepBtree* tree, CordRep* rep) {
- if (ABSL_PREDICT_TRUE(rep->IsBtree())) {
- return MergeTrees(rep->btree(), tree);
- }
- auto consume = [&tree](CordRep* r, size_t offset, size_t length) {
- r = MakeSubstring(r, offset, length);
- tree = CordRepBtree::AddCordRep<kFront>(tree, r);
- };
- ReverseConsume(rep, consume);
- return tree;
-}
-
-CordRepBtree* CordRepBtree::Append(CordRepBtree* tree, absl::string_view data,
- size_t extra) {
- return CordRepBtree::AddData<kBack>(tree, data, extra);
-}
-
-CordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, absl::string_view data,
- size_t extra) {
- return CordRepBtree::AddData<kFront>(tree, data, extra);
-}
-
-template CordRepBtree* CordRepBtree::AddCordRep<kFront>(CordRepBtree* tree,
- CordRep* rep);
-template CordRepBtree* CordRepBtree::AddCordRep<kBack>(CordRepBtree* tree,
- CordRep* rep);
-template CordRepBtree* CordRepBtree::AddData<kFront>(CordRepBtree* tree,
- absl::string_view data,
- size_t extra);
-template CordRepBtree* CordRepBtree::AddData<kBack>(CordRepBtree* tree,
- absl::string_view data,
- size_t extra);
-
-void CordRepBtree::Rebuild(CordRepBtree** stack, CordRepBtree* tree,
- bool consume) {
- bool owned = consume && tree->refcount.IsOne();
- if (tree->height() == 0) {
- for (CordRep* edge : tree->Edges()) {
- if (!owned) edge = CordRep::Ref(edge);
- size_t height = 0;
- size_t length = edge->length;
- CordRepBtree* node = stack[0];
- OpResult result = node->AddEdge<kBack>(true, edge, length);
- while (result.action == CordRepBtree::kPopped) {
- stack[height] = result.tree;
- if (stack[++height] == nullptr) {
- result.action = CordRepBtree::kSelf;
- stack[height] = CordRepBtree::New(node, result.tree);
- } else {
- node = stack[height];
- result = node->AddEdge<kBack>(true, result.tree, length);
- }
- }
- while (stack[++height] != nullptr) {
- stack[height]->length += length;
- }
- }
- } else {
- for (CordRep* rep : tree->Edges()) {
- Rebuild(stack, rep->btree(), owned);
- }
- }
- if (consume) {
- if (owned) {
- CordRepBtree::Delete(tree);
- } else {
- CordRepBtree::Unref(tree);
- }
- }
-}
-
-CordRepBtree* CordRepBtree::Rebuild(CordRepBtree* tree) {
- // Set up initial stack with empty leaf node.
- CordRepBtree* node = CordRepBtree::New();
- CordRepBtree* stack[CordRepBtree::kMaxDepth + 1] = {node};
-
- // Recursively build the tree, consuming the input tree.
- Rebuild(stack, tree, /* consume reference */ true);
-
- // Return top most node
- for (CordRepBtree* parent : stack) {
- if (parent == nullptr) return node;
- node = parent;
- }
-
- // Unreachable
- assert(false);
- return nullptr;
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h
deleted file mode 100644
index bb38f0c3fe..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree.h
+++ /dev/null
@@ -1,939 +0,0 @@
-// 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_BTREE_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_
-
-#include <cassert>
-#include <cstdint>
-#include <iosfwd>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/optimization.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/string_view.h"
-#include "absl/types/span.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-class CordRepBtreeNavigator;
-
-// CordRepBtree is as the name implies a btree implementation of a Cordrep tree.
-// Data is stored at the leaf level only, non leaf nodes contain down pointers
-// only. Allowed types of data edges are FLAT, EXTERNAL and SUBSTRINGs of FLAT
-// or EXTERNAL nodes. The implementation allows for data to be added to either
-// end of the tree only, it does not provide any 'insert' logic. This has the
-// benefit that we can expect good fill ratios: all nodes except the outer
-// 'legs' will have 100% fill ratios for trees built using Append/Prepend
-// methods. Merged trees will typically have a fill ratio well above 50% as in a
-// similar fashion, one side of the merged tree will typically have a 100% fill
-// ratio, and the 'open' end will average 50%. All operations are O(log(n)) or
-// better, and the tree never needs balancing.
-//
-// All methods accepting a CordRep* or CordRepBtree* adopt a reference on that
-// input unless explicitly stated otherwise. All functions returning a CordRep*
-// or CordRepBtree* instance transfer a reference back to the caller.
-// Simplified, callers both 'donate' and 'consume' a reference count on each
-// call, simplifying the API. An example of building a tree:
-//
-// CordRepBtree* tree = CordRepBtree::Create(MakeFlat("Hello"));
-// tree = CordRepBtree::Append(tree, MakeFlat("world"));
-//
-// In the above example, all inputs are consumed, making each call affecting
-// `tree` reference count neutral. The returned `tree` value can be different
-// from the input if the input is shared with other threads, or if the tree
-// grows in height, but callers typically never have to concern themselves with
-// that and trust that all methods DTRT at all times.
-class CordRepBtree : public CordRep {
- public:
- // EdgeType identifies `front` and `back` enum values.
- // Various implementations in CordRepBtree such as `Add` and `Edge` are
- // generic and templated on operating on either of the boundary edges.
- // For more information on the possible edges contained in a CordRepBtree
- // instance see the documentation for `edges_`.
- enum class EdgeType { kFront, kBack };
-
- // Convenience constants into `EdgeType`
- static constexpr EdgeType kFront = EdgeType::kFront;
- static constexpr EdgeType kBack = EdgeType::kBack;
-
- // Maximum number of edges: based on experiments and performance data, we can
- // pick suitable values resulting in optimum cacheline aligned values. The
- // preferred values are based on 64-bit systems where we aim to align this
- // class onto 64 bytes, i.e.: 6 = 64 bytes, 14 = 128 bytes, etc.
- // TODO(b/192061034): experiment with alternative sizes.
- static constexpr size_t kMaxCapacity = 6;
-
- // Reasonable maximum height of the btree. We can expect a fill ratio of at
- // least 50%: trees are always expanded at the front or back. Concatenating
- // trees will then typically fold at the top most node, where the lower nodes
- // are at least at capacity on one side of joined inputs. At a lower fill
- // rate of 4 edges per node, we have capacity for ~16 million leaf nodes.
- // We will fail / abort if an application ever exceeds this height, which
- // should be extremely rare (near impossible) and be an indication of an
- // application error: we do not assume it reasonable for any application to
- // operate correctly with such monster trees.
- // Another compelling reason for the number `12` is that any contextual stack
- // required for navigation or insertion requires 12 words and 12 bytes, which
- // fits inside 2 cache lines with some room to spare, and is reasonable as a
- // local stack variable compared to Cord's current near 400 bytes stack use.
- // The maximum `height` value of a node is then `kMaxDepth - 1` as node height
- // values start with a value of 0 for leaf nodes.
- static constexpr int kMaxDepth = 12;
- static constexpr int kMaxHeight = kMaxDepth - 1;
-
- // `Action` defines the action for unwinding changes done at the btree's leaf
- // level that need to be propagated up to the parent node(s). Each operation
- // on a node has an effect / action defined as follows:
- // - kSelf
- // The operation (add / update, etc) was performed directly on the node as
- // the node is private to the current thread (i.e.: not shared directly or
- // indirectly through a refcount > 1). Changes can be propagated directly to
- // all parent nodes as all parent nodes are also then private to the current
- // thread.
- // - kCopied
- // The operation (add / update, etc) was performed on a copy of the original
- // node, as the node is (potentially) directly or indirectly shared with
- // other threads. Changes need to be propagated into the parent nodes where
- // the old down pointer must be unreffed and replaced with this new copy.
- // Such changes to parent nodes may themselves require a copy if the parent
- // node is also shared. A kCopied action can propagate all the way to the
- // top node where we then must unref the `tree` input provided by the
- // caller, and return the new copy.
- // - kPopped
- // The operation (typically add) could not be satisfied due to insufficient
- // capacity in the targeted node, and a new 'leg' was created that needs to
- // be added into the parent node. For example, adding a FLAT inside a leaf
- // node that is at capacity will create a new leaf node containing that
- // FLAT, that needs to be 'popped' up the btree. Such 'pop' actions can
- // cascade up the tree if parent nodes are also at capacity. A 'Popped'
- // action propagating all the way to the top of the tree will result in
- // the tree becoming one level higher than the current tree through a final
- // `CordRepBtree::New(tree, popped)` call, resulting in a new top node
- // referencing the old tree and the new (fully popped upwards) 'leg'.
- enum Action { kSelf, kCopied, kPopped };
-
- // Result of an operation on a node. See the `Action` enum for details.
- struct OpResult {
- CordRepBtree* tree;
- Action action;
- };
-
- // Return value of the CopyPrefix and CopySuffix methods which can
- // return a node or data edge at any height inside the tree.
- // A height of 0 defines the lowest (leaf) node, a height of -1 identifies
- // `edge` as being a plain data node: EXTERNAL / FLAT or SUBSTRING thereof.
- struct CopyResult {
- CordRep* edge;
- int height;
- };
-
- // Logical position inside a node:
- // - index: index of the edge.
- // - n: size or offset value depending on context.
- struct Position {
- size_t index;
- size_t n;
- };
-
- // Creates a btree from the given input. Adopts a ref of `rep`.
- // If the input `rep` is itself a btree, i.e., `IsBtree()`, then this
- // function immediately returns `rep->btree()`. If the input is a valid data
- // edge (see IsDataEdge()), then a new leaf node is returned containing `rep`
- // as the sole data edge. Else, the input is assumed to be a (legacy) concat
- // tree, and the input is consumed and transformed into a btree().
- static CordRepBtree* Create(CordRep* rep);
-
- // Destroys the provided tree. Should only be called by cord internal API's,
- // typically after a ref_count.Decrement() on the last reference count.
- static void Destroy(CordRepBtree* tree);
-
- // Use CordRep::Unref() as we overload for absl::Span<CordRep* const>.
- using CordRep::Unref;
-
- // Unrefs all edges in `edges` which are assumed to be 'likely one'.
- static void Unref(absl::Span<CordRep* const> edges);
-
- // Appends / Prepends an existing CordRep instance to this tree.
- // The below methods accept three types of input:
- // 1) `rep` is a data node (See `IsDataNode` for valid data edges).
- // `rep` is appended or prepended to this tree 'as is'.
- // 2) `rep` is a BTREE.
- // `rep` is merged into `tree` respecting the Append/Prepend order.
- // 3) `rep` is some other (legacy) type.
- // `rep` is converted in place and added to `tree`
- // Requires `tree` and `rep` to be not null.
- static CordRepBtree* Append(CordRepBtree* tree, CordRep* rep);
- static CordRepBtree* Prepend(CordRepBtree* tree, CordRep* rep);
-
- // Append/Prepend the data in `data` to this tree.
- // The `extra` parameter defines how much extra capacity should be allocated
- // for any additional FLAT being allocated. This is an optimization hint from
- // the caller. For example, a caller may need to add 2 string_views of data
- // "abc" and "defghi" which are not consecutive. The caller can in this case
- // invoke `AddData(tree, "abc", 6)`, and any newly added flat is allocated
- // where possible with at least 6 bytes of extra capacity beyond `length`.
- // This helps avoiding data getting fragmented over multiple flats.
- // There is no limit on the size of `data`. If `data` can not be stored inside
- // a single flat, then the function will iteratively add flats until all data
- // has been consumed and appended or prepended to the tree.
- static CordRepBtree* Append(CordRepBtree* tree, string_view data,
- size_t extra = 0);
- static CordRepBtree* Prepend(CordRepBtree* tree, string_view data,
- size_t extra = 0);
-
- // Returns a new tree, containing `n` bytes of data from this instance
- // starting at offset `offset`. Where possible, the returned tree shares
- // (re-uses) data edges and nodes with this instance to minimize the
- // combined memory footprint of both trees.
- // Requires `offset + n <= length`. Returns `nullptr` if `n` is zero.
- CordRep* SubTree(size_t offset, size_t n);
-
- // Removes `n` trailing bytes from `tree`, and returns the resulting tree
- // or data edge. Returns `tree` if n is zero, and nullptr if n == length.
- // This function is logically identical to:
- // result = tree->SubTree(0, tree->length - n);
- // Unref(tree);
- // return result;
- // However, the actual implementation will as much as possible perform 'in
- // place' modifications on the tree on all nodes and edges that are mutable.
- // For example, in a fully privately owned tree with the last edge being a
- // flat of length 12, RemoveSuffix(1) will simply set the length of that data
- // edge to 11, and reduce the length of all nodes on the edge path by 1.
- static CordRep* RemoveSuffix(CordRepBtree* tree, size_t n);
-
- // Returns the character at the given offset.
- char GetCharacter(size_t offset) const;
-
- // Returns true if this node holds a single data edge, and if so, sets
- // `fragment` to reference the contained data. `fragment` is an optional
- // output parameter and allowed to be null.
- bool IsFlat(absl::string_view* fragment) const;
-
- // Returns true if the data of `n` bytes starting at offset `offset`
- // is contained in a single data edge, and if so, sets fragment to reference
- // the contained data. `fragment` is an optional output parameter and allowed
- // to be null.
- bool IsFlat(size_t offset, size_t n, absl::string_view* fragment) const;
-
- // Returns a span (mutable range of bytes) of up to `size` bytes into the
- // last FLAT data edge inside this tree under the following conditions:
- // - none of the nodes down into the FLAT node are shared.
- // - the last data edge in this tree is a non-shared FLAT.
- // - the referenced FLAT has additional capacity available.
- // If all these conditions are met, a non-empty span is returned, and the
- // length of the flat node and involved tree nodes have been increased by
- // `span.length()`. The caller is responsible for immediately assigning values
- // to all uninitialized data reference by the returned span.
- // Requires `this->refcount.IsMutable()`: this function forces the
- // caller to do this fast path check on the top level node, as this is the
- // most commonly shared node of a cord tree.
- Span<char> GetAppendBuffer(size_t size);
-
- // Returns the `height` of the tree. The height of a tree is limited to
- // kMaxHeight. `height` is implemented as an `int` as in some places we
- // use negative (-1) values for 'data edges'.
- int height() const { return static_cast<int>(storage[0]); }
-
- // Properties: begin, back, end, front/back boundary indexes.
- size_t begin() const { return static_cast<size_t>(storage[1]); }
- size_t back() const { return static_cast<size_t>(storage[2]) - 1; }
- size_t end() const { return static_cast<size_t>(storage[2]); }
- size_t index(EdgeType edge) const {
- return edge == kFront ? begin() : back();
- }
-
- // Properties: size and capacity.
- // `capacity` contains the current capacity of this instance, where
- // `kMaxCapacity` contains the maximum capacity of a btree node.
- // For now, `capacity` and `kMaxCapacity` return the same value, but this may
- // change in the future if we see benefit in dynamically sizing 'small' nodes
- // to 'large' nodes for large data trees.
- size_t size() const { return end() - begin(); }
- size_t capacity() const { return kMaxCapacity; }
-
- // Edge access
- inline CordRep* Edge(size_t index) const;
- inline CordRep* Edge(EdgeType edge_type) const;
- inline absl::Span<CordRep* const> Edges() const;
- inline absl::Span<CordRep* const> Edges(size_t begin, size_t end) const;
-
- // Returns reference to the data edge at `index`.
- // Requires this instance to be a leaf node, and `index` to be valid index.
- inline absl::string_view Data(size_t index) const;
-
- static const char* EdgeDataPtr(const CordRep* r);
- static absl::string_view EdgeData(const CordRep* r);
-
- // Returns true if the provided rep is a FLAT, EXTERNAL or a SUBSTRING node
- // holding a FLAT or EXTERNAL child rep.
- static bool IsDataEdge(const CordRep* rep);
-
- // Diagnostics: returns true if `tree` is valid and internally consistent.
- // If `shallow` is false, then the provided top level node and all child nodes
- // below it are recursively checked. If `shallow` is true, only the provided
- // node in `tree` and the cumulative length, type and height of the direct
- // child nodes of `tree` are checked. The value of `shallow` is ignored if the
- // internal `cord_btree_exhaustive_validation` diagnostics variable is true,
- // in which case the performed validations works as if `shallow` were false.
- // This function is intended for debugging and testing purposes only.
- static bool IsValid(const CordRepBtree* tree, bool shallow = false);
-
- // Diagnostics: asserts that the provided tree is valid.
- // `AssertValid()` performs a shallow validation by default. `shallow` can be
- // set to false in which case an exhaustive validation is performed. This
- // function is implemented in terms of calling `IsValid()` and asserting the
- // return value to be true. See `IsValid()` for more information.
- // This function is intended for debugging and testing purposes only.
- static CordRepBtree* AssertValid(CordRepBtree* tree, bool shallow = true);
- static const CordRepBtree* AssertValid(const CordRepBtree* tree,
- bool shallow = true);
-
- // Diagnostics: dump the contents of this tree to `stream`.
- // This function is intended for debugging and testing purposes only.
- static void Dump(const CordRep* rep, std::ostream& stream);
- static void Dump(const CordRep* rep, absl::string_view label,
- std::ostream& stream);
- static void Dump(const CordRep* rep, absl::string_view label,
- bool include_contents, std::ostream& stream);
-
- // Adds the edge `edge` to this node if possible. `owned` indicates if the
- // current node is potentially shared or not with other threads. Returns:
- // - {kSelf, <this>}
- // The edge was directly added to this node.
- // - {kCopied, <node>}
- // The edge was added to a copy of this node.
- // - {kPopped, New(edge, height())}
- // A new leg with the edge was created as this node has no extra capacity.
- template <EdgeType edge_type>
- inline OpResult AddEdge(bool owned, CordRep* edge, size_t delta);
-
- // Replaces the front or back edge with the provided new edge. Returns:
- // - {kSelf, <this>}
- // The edge was directly set in this node. The old edge is unreffed.
- // - {kCopied, <node>}
- // A copy of this node was created with the new edge value.
- // In both cases, the function adopts a reference on `edge`.
- template <EdgeType edge_type>
- OpResult SetEdge(bool owned, CordRep* edge, size_t delta);
-
- // Creates a new empty node at the specified height.
- static CordRepBtree* New(int height = 0);
-
- // Creates a new node containing `rep`, with the height being computed
- // automatically based on the type of `rep`.
- static CordRepBtree* New(CordRep* rep);
-
- // Creates a new node containing both `front` and `back` at height
- // `front.height() + 1`. Requires `back.height() == front.height()`.
- static CordRepBtree* New(CordRepBtree* front, CordRepBtree* back);
-
- // Creates a fully balanced tree from the provided tree by rebuilding a new
- // tree from all data edges in the input. This function is automatically
- // invoked internally when the tree exceeds the maximum height.
- static CordRepBtree* Rebuild(CordRepBtree* tree);
-
- private:
- CordRepBtree() = default;
- ~CordRepBtree() = default;
-
- // Initializes the main properties `tag`, `begin`, `end`, `height`.
- inline void InitInstance(int height, size_t begin = 0, size_t end = 0);
-
- // Direct property access begin / end
- void set_begin(size_t begin) { storage[1] = static_cast<uint8_t>(begin); }
- void set_end(size_t end) { storage[2] = static_cast<uint8_t>(end); }
-
- // Decreases the value of `begin` by `n`, and returns the new value. Notice
- // how this returns the new value unlike atomic::fetch_add which returns the
- // old value. This is because this is used to prepend edges at 'begin - 1'.
- size_t sub_fetch_begin(size_t n) {
- storage[1] -= static_cast<uint8_t>(n);
- return storage[1];
- }
-
- // Increases the value of `end` by `n`, and returns the previous value. This
- // function is typically used to append edges at 'end'.
- size_t fetch_add_end(size_t n) {
- const uint8_t current = storage[2];
- storage[2] = static_cast<uint8_t>(current + n);
- return current;
- }
-
- // Returns the index of the last edge starting on, or before `offset`, with
- // `n` containing the relative offset of `offset` inside that edge.
- // Requires `offset` < length.
- Position IndexOf(size_t offset) const;
-
- // Returns the index of the last edge starting before `offset`, with `n`
- // containing the relative offset of `offset` inside that edge.
- // This function is useful to find the edges for some span of bytes ending at
- // `offset` (i.e., `n` bytes). For example:
- //
- // Position pos = IndexBefore(n)
- // edges = Edges(begin(), pos.index) // All full edges (may be empty)
- // last = Sub(Edge(pos.index), 0, pos.n) // Last partial edge (may be empty)
- //
- // Requires 0 < `offset` <= length.
- Position IndexBefore(size_t offset) const;
-
- // Returns the index of the edge ending at (or on) length `length`, and the
- // number of bytes inside that edge up to `length`. For example, if we have a
- // Node with 2 edges, one of 10 and one of 20 long, then IndexOfLength(27)
- // will return {1, 17}, and IndexOfLength(10) will return {0, 10}.
- Position IndexOfLength(size_t n) const;
-
- // Identical to the above function except starting from the position `front`.
- // This function is equivalent to `IndexBefore(front.n + offset)`, with
- // the difference that this function is optimized to start at `front.index`.
- Position IndexBefore(Position front, size_t offset) const;
-
- // Returns the index of the edge directly beyond the edge containing offset
- // `offset`, with `n` containing the distance of that edge from `offset`.
- // This function is useful for iteratively finding suffix nodes and remaining
- // partial bytes in left-most suffix nodes as for example in CopySuffix.
- // Requires `offset` < length.
- Position IndexBeyond(size_t offset) const;
-
- // Destruction
- static void DestroyLeaf(CordRepBtree* tree, size_t begin, size_t end);
- static void DestroyNonLeaf(CordRepBtree* tree, size_t begin, size_t end);
- static void DestroyTree(CordRepBtree* tree, size_t begin, size_t end);
- static void Delete(CordRepBtree* tree) { delete tree; }
-
- // Creates a new leaf node containing as much data as possible from `data`.
- // The data is added either forwards or reversed depending on `edge_type`.
- // Callers must check the length of the returned node to determine if all data
- // was copied or not.
- // See the `Append/Prepend` function for the meaning and purpose of `extra`.
- template <EdgeType edge_type>
- static CordRepBtree* NewLeaf(absl::string_view data, size_t extra);
-
- // Creates a raw copy of this Btree node, copying all properties, but
- // without adding any references to existing edges.
- CordRepBtree* CopyRaw() const;
-
- // Creates a full copy of this Btree node, adding a reference on all edges.
- CordRepBtree* Copy() const;
-
- // Creates a partial copy of this Btree node, copying all edges up to `end`,
- // adding a reference on each copied edge, and sets the length of the newly
- // created copy to `new_length`.
- CordRepBtree* CopyBeginTo(size_t end, size_t new_length) const;
-
- // Returns a tree containing the edges [tree->begin(), end) and length
- // of `new_length`. This method consumes a reference on the provided
- // tree, and logically performs the following operation:
- // result = tree->CopyBeginTo(end, new_length);
- // CordRep::Unref(tree);
- // return result;
- static CordRepBtree* ConsumeBeginTo(CordRepBtree* tree, size_t end,
- size_t new_length);
-
- // Creates a partial copy of this Btree node, copying all edges starting at
- // `begin`, adding a reference on each copied edge, and sets the length of
- // the newly created copy to `new_length`.
- CordRepBtree* CopyToEndFrom(size_t begin, size_t new_length) const;
-
- // Extracts and returns the front edge from the provided tree.
- // This method consumes a reference on the provided tree, and logically
- // performs the following operation:
- // edge = CordRep::Ref(tree->Edge(kFront));
- // CordRep::Unref(tree);
- // return edge;
- static CordRep* ExtractFront(CordRepBtree* tree);
-
- // Returns a tree containing the result of appending `right` to `left`.
- static CordRepBtree* MergeTrees(CordRepBtree* left, CordRepBtree* right);
-
- // Fallback functions for `Create()`, `Append()` and `Prepend()` which
- // deal with legacy / non conforming input, i.e.: CONCAT trees.
- static CordRepBtree* CreateSlow(CordRep* rep);
- static CordRepBtree* AppendSlow(CordRepBtree*, CordRep* rep);
- static CordRepBtree* PrependSlow(CordRepBtree*, CordRep* rep);
-
- // Recursively rebuilds `tree` into `stack`. If 'consume` is set to true, the
- // function will consume a reference on `tree`. `stack` is a null terminated
- // array containing the new tree's state, with the current leaf node at
- // stack[0], and parent nodes above that, or null for 'top of tree'.
- static void Rebuild(CordRepBtree** stack, CordRepBtree* tree, bool consume);
-
- // Aligns existing edges to start at index 0, to allow for a new edge to be
- // added to the back of the current edges.
- inline void AlignBegin();
-
- // Aligns existing edges to end at `capacity`, to allow for a new edge to be
- // added in front of the current edges.
- inline void AlignEnd();
-
- // Adds the provided edge to this node.
- // Requires this node to have capacity for the edge. Realigns / moves
- // existing edges as needed to prepend or append the new edge.
- template <EdgeType edge_type>
- inline void Add(CordRep* rep);
-
- // Adds the provided edges to this node.
- // Requires this node to have capacity for the edges. Realigns / moves
- // existing edges as needed to prepend or append the new edges.
- template <EdgeType edge_type>
- inline void Add(absl::Span<CordRep* const>);
-
- // Adds data from `data` to this node until either all data has been consumed,
- // or there is no more capacity for additional flat nodes inside this node.
- // Requires the current node to be a leaf node, data to be non empty, and the
- // current node to have capacity for at least one more data edge.
- // Returns any remaining data from `data` that was not added, which is
- // depending on the edge type (front / back) either the remaining prefix of
- // suffix of the input.
- // See the `Append/Prepend` function for the meaning and purpose of `extra`.
- template <EdgeType edge_type>
- absl::string_view AddData(absl::string_view data, size_t extra);
-
- // Replace the front or back edge with the provided value.
- // Adopts a reference on `edge` and unrefs the old edge.
- template <EdgeType edge_type>
- inline void SetEdge(CordRep* edge);
-
- // Returns a partial copy of the current tree containing the first `n` bytes
- // of data. `CopyResult` contains both the resulting edge and its height. The
- // resulting tree may be less high than the current tree, or even be a single
- // matching data edge if `allow_folding` is set to true.
- // For example, if `n == 1`, then the result will be the single data edge, and
- // height will be set to -1 (one below the owning leaf node). If n == 0, this
- // function returns null. Requires `n <= length`
- CopyResult CopyPrefix(size_t n, bool allow_folding = true);
-
- // Returns a partial copy of the current tree containing all data starting
- // after `offset`. `CopyResult` contains both the resulting edge and its
- // height. The resulting tree may be less high than the current tree, or even
- // be a single matching data edge. For example, if `n == length - 1`, then the
- // result will be a single data edge, and height will be set to -1 (one below
- // the owning leaf node).
- // Requires `offset < length`
- CopyResult CopySuffix(size_t offset);
-
- // Returns a OpResult value of {this, kSelf} or {Copy(), kCopied}
- // depending on the value of `owned`.
- inline OpResult ToOpResult(bool owned);
-
- // Adds `rep` to the specified tree, returning the modified tree.
- template <EdgeType edge_type>
- static CordRepBtree* AddCordRep(CordRepBtree* tree, CordRep* rep);
-
- // Adds `data` to the specified tree, returning the modified tree.
- // See the `Append/Prepend` function for the meaning and purpose of `extra`.
- template <EdgeType edge_type>
- static CordRepBtree* AddData(CordRepBtree* tree, absl::string_view data,
- size_t extra = 0);
-
- // Merges `src` into `dst` with `src` being added either before (kFront) or
- // after (kBack) `dst`. Requires the height of `dst` to be greater than or
- // equal to the height of `src`.
- template <EdgeType edge_type>
- static CordRepBtree* Merge(CordRepBtree* dst, CordRepBtree* src);
-
- // Fallback version of GetAppendBuffer for large trees: GetAppendBuffer()
- // implements an inlined version for trees of limited height (3 levels),
- // GetAppendBufferSlow implements the logic for large trees.
- Span<char> GetAppendBufferSlow(size_t size);
-
- // `edges_` contains all edges starting from this instance.
- // These are explicitly `child` edges only, a cord btree (or any cord tree in
- // that respect) does not store `parent` pointers anywhere: multiple trees /
- // parents can reference the same shared child edge. The type of these edges
- // depends on the height of the node. `Leaf nodes` (height == 0) contain `data
- // edges` (external or flat nodes, or sub-strings thereof). All other nodes
- // (height > 0) contain pointers to BTREE nodes with a height of `height - 1`.
- CordRep* edges_[kMaxCapacity];
-
- friend class CordRepBtreeTestPeer;
- friend class CordRepBtreeNavigator;
-};
-
-inline CordRepBtree* CordRep::btree() {
- assert(IsBtree());
- return static_cast<CordRepBtree*>(this);
-}
-
-inline const CordRepBtree* CordRep::btree() const {
- assert(IsBtree());
- return static_cast<const CordRepBtree*>(this);
-}
-
-inline void CordRepBtree::InitInstance(int height, size_t begin, size_t end) {
- tag = BTREE;
- storage[0] = static_cast<uint8_t>(height);
- storage[1] = static_cast<uint8_t>(begin);
- storage[2] = static_cast<uint8_t>(end);
-}
-
-inline CordRep* CordRepBtree::Edge(size_t index) const {
- assert(index >= begin());
- assert(index < end());
- return edges_[index];
-}
-
-inline CordRep* CordRepBtree::Edge(EdgeType edge_type) const {
- return edges_[edge_type == kFront ? begin() : back()];
-}
-
-inline absl::Span<CordRep* const> CordRepBtree::Edges() const {
- return {edges_ + begin(), size()};
-}
-
-inline absl::Span<CordRep* const> CordRepBtree::Edges(size_t begin,
- size_t end) const {
- assert(begin <= end);
- assert(begin >= this->begin());
- assert(end <= this->end());
- return {edges_ + begin, static_cast<size_t>(end - begin)};
-}
-
-inline const char* CordRepBtree::EdgeDataPtr(const CordRep* r) {
- assert(IsDataEdge(r));
- size_t offset = 0;
- if (r->tag == SUBSTRING) {
- offset = r->substring()->start;
- r = r->substring()->child;
- }
- return (r->tag >= FLAT ? r->flat()->Data() : r->external()->base) + offset;
-}
-
-inline absl::string_view CordRepBtree::EdgeData(const CordRep* r) {
- return absl::string_view(EdgeDataPtr(r), r->length);
-}
-
-inline absl::string_view CordRepBtree::Data(size_t index) const {
- assert(height() == 0);
- return EdgeData(Edge(index));
-}
-
-inline bool CordRepBtree::IsDataEdge(const CordRep* rep) {
- // The fast path is that `rep` is an EXTERNAL or FLAT node, making the below
- // if a single, well predicted branch. We then repeat the FLAT or EXTERNAL
- // check in the slow path the SUBSTRING check to optimize for the hot path.
- if (rep->tag == EXTERNAL || rep->tag >= FLAT) return true;
- if (rep->tag == SUBSTRING) rep = rep->substring()->child;
- return rep->tag == EXTERNAL || rep->tag >= FLAT;
-}
-
-inline CordRepBtree* CordRepBtree::New(int height) {
- CordRepBtree* tree = new CordRepBtree;
- tree->length = 0;
- tree->InitInstance(height);
- return tree;
-}
-
-inline CordRepBtree* CordRepBtree::New(CordRep* rep) {
- CordRepBtree* tree = new CordRepBtree;
- int height = rep->IsBtree() ? rep->btree()->height() + 1 : 0;
- tree->length = rep->length;
- tree->InitInstance(height, /*begin=*/0, /*end=*/1);
- tree->edges_[0] = rep;
- return tree;
-}
-
-inline CordRepBtree* CordRepBtree::New(CordRepBtree* front,
- CordRepBtree* back) {
- assert(front->height() == back->height());
- CordRepBtree* tree = new CordRepBtree;
- tree->length = front->length + back->length;
- tree->InitInstance(front->height() + 1, /*begin=*/0, /*end=*/2);
- tree->edges_[0] = front;
- tree->edges_[1] = back;
- return tree;
-}
-
-inline void CordRepBtree::DestroyTree(CordRepBtree* tree, size_t begin,
- size_t end) {
- if (tree->height() == 0) {
- DestroyLeaf(tree, begin, end);
- } else {
- DestroyNonLeaf(tree, begin, end);
- }
-}
-
-inline void CordRepBtree::Destroy(CordRepBtree* tree) {
- DestroyTree(tree, tree->begin(), tree->end());
-}
-
-inline void CordRepBtree::Unref(absl::Span<CordRep* const> edges) {
- for (CordRep* edge : edges) {
- if (ABSL_PREDICT_FALSE(!edge->refcount.Decrement())) {
- CordRep::Destroy(edge);
- }
- }
-}
-
-inline CordRepBtree* CordRepBtree::CopyRaw() const {
- auto* tree = static_cast<CordRepBtree*>(::operator new(sizeof(CordRepBtree)));
- memcpy(static_cast<void*>(tree), this, sizeof(CordRepBtree));
- new (&tree->refcount) RefcountAndFlags;
- return tree;
-}
-
-inline CordRepBtree* CordRepBtree::Copy() const {
- CordRepBtree* tree = CopyRaw();
- for (CordRep* rep : Edges()) CordRep::Ref(rep);
- return tree;
-}
-
-inline CordRepBtree* CordRepBtree::CopyToEndFrom(size_t begin,
- size_t new_length) const {
- assert(begin >= this->begin());
- assert(begin <= this->end());
- CordRepBtree* tree = CopyRaw();
- tree->length = new_length;
- tree->set_begin(begin);
- for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
- return tree;
-}
-
-inline CordRepBtree* CordRepBtree::CopyBeginTo(size_t end,
- size_t new_length) const {
- assert(end <= capacity());
- assert(end >= this->begin());
- CordRepBtree* tree = CopyRaw();
- tree->length = new_length;
- tree->set_end(end);
- for (CordRep* edge : tree->Edges()) CordRep::Ref(edge);
- return tree;
-}
-
-inline void CordRepBtree::AlignBegin() {
- // The below code itself does not need to be fast as typically we have
- // mono-directional append/prepend calls, and `begin` / `end` are typically
- // adjusted no more than once. But we want to avoid potential register clobber
- // effects, making the compiler emit register save/store/spills, and minimize
- // the size of code.
- const size_t delta = begin();
- if (ABSL_PREDICT_FALSE(delta != 0)) {
- const size_t new_end = end() - delta;
- set_begin(0);
- set_end(new_end);
- // TODO(mvels): we can write this using 2 loads / 2 stores depending on
- // total size for the kMaxCapacity = 6 case. I.e., we can branch (switch) on
- // size, and then do overlapping load/store of up to 4 pointers (inlined as
- // XMM, YMM or ZMM load/store) and up to 2 pointers (XMM / YMM), which is a)
- // compact and b) not clobbering any registers.
- ABSL_INTERNAL_ASSUME(new_end <= kMaxCapacity);
-#ifdef __clang__
-#pragma unroll 1
-#endif
- for (size_t i = 0; i < new_end; ++i) {
- edges_[i] = edges_[i + delta];
- }
- }
-}
-
-inline void CordRepBtree::AlignEnd() {
- // See comments in `AlignBegin` for motivation on the hand-rolled for loops.
- const size_t delta = capacity() - end();
- if (delta != 0) {
- const size_t new_begin = begin() + delta;
- const size_t new_end = end() + delta;
- set_begin(new_begin);
- set_end(new_end);
- ABSL_INTERNAL_ASSUME(new_end <= kMaxCapacity);
-#ifdef __clang__
-#pragma unroll 1
-#endif
- for (size_t i = new_end - 1; i >= new_begin; --i) {
- edges_[i] = edges_[i - delta];
- }
- }
-}
-
-template <>
-inline void CordRepBtree::Add<CordRepBtree::kBack>(CordRep* rep) {
- AlignBegin();
- edges_[fetch_add_end(1)] = rep;
-}
-
-template <>
-inline void CordRepBtree::Add<CordRepBtree::kBack>(
- absl::Span<CordRep* const> edges) {
- AlignBegin();
- size_t new_end = end();
- for (CordRep* edge : edges) edges_[new_end++] = edge;
- set_end(new_end);
-}
-
-template <>
-inline void CordRepBtree::Add<CordRepBtree::kFront>(CordRep* rep) {
- AlignEnd();
- edges_[sub_fetch_begin(1)] = rep;
-}
-
-template <>
-inline void CordRepBtree::Add<CordRepBtree::kFront>(
- absl::Span<CordRep* const> edges) {
- AlignEnd();
- size_t new_begin = begin() - edges.size();
- set_begin(new_begin);
- for (CordRep* edge : edges) edges_[new_begin++] = edge;
-}
-
-template <CordRepBtree::EdgeType edge_type>
-inline void CordRepBtree::SetEdge(CordRep* edge) {
- const int idx = edge_type == kFront ? begin() : back();
- CordRep::Unref(edges_[idx]);
- edges_[idx] = edge;
-}
-
-inline CordRepBtree::OpResult CordRepBtree::ToOpResult(bool owned) {
- return owned ? OpResult{this, kSelf} : OpResult{Copy(), kCopied};
-}
-
-inline CordRepBtree::Position CordRepBtree::IndexOf(size_t offset) const {
- assert(offset < length);
- size_t index = begin();
- while (offset >= edges_[index]->length) offset -= edges_[index++]->length;
- return {index, offset};
-}
-
-inline CordRepBtree::Position CordRepBtree::IndexBefore(size_t offset) const {
- assert(offset > 0);
- assert(offset <= length);
- size_t index = begin();
- while (offset > edges_[index]->length) offset -= edges_[index++]->length;
- return {index, offset};
-}
-
-inline CordRepBtree::Position CordRepBtree::IndexBefore(Position front,
- size_t offset) const {
- size_t index = front.index;
- offset = offset + front.n;
- while (offset > edges_[index]->length) offset -= edges_[index++]->length;
- return {index, offset};
-}
-
-inline CordRepBtree::Position CordRepBtree::IndexOfLength(size_t n) const {
- assert(n <= length);
- size_t index = back();
- size_t strip = length - n;
- while (strip >= edges_[index]->length) strip -= edges_[index--]->length;
- return {index, edges_[index]->length - strip};
-}
-
-inline CordRepBtree::Position CordRepBtree::IndexBeyond(
- const size_t offset) const {
- // We need to find the edge which `starting offset` is beyond (>=)`offset`.
- // For this we can't use the `offset -= length` logic of IndexOf. Instead, we
- // track the offset of the `current edge` in `off`, which we increase as we
- // iterate over the edges until we find the matching edge.
- size_t off = 0;
- size_t index = begin();
- while (offset > off) off += edges_[index++]->length;
- return {index, off - offset};
-}
-
-inline CordRepBtree* CordRepBtree::Create(CordRep* rep) {
- if (IsDataEdge(rep)) return New(rep);
- return CreateSlow(rep);
-}
-
-inline Span<char> CordRepBtree::GetAppendBuffer(size_t size) {
- assert(refcount.IsMutable());
- CordRepBtree* tree = this;
- const int height = this->height();
- CordRepBtree* n1 = tree;
- CordRepBtree* n2 = tree;
- CordRepBtree* n3 = tree;
- switch (height) {
- case 3:
- tree = tree->Edge(kBack)->btree();
- if (!tree->refcount.IsMutable()) return {};
- n2 = tree;
- ABSL_FALLTHROUGH_INTENDED;
- case 2:
- tree = tree->Edge(kBack)->btree();
- if (!tree->refcount.IsMutable()) return {};
- n1 = tree;
- ABSL_FALLTHROUGH_INTENDED;
- case 1:
- tree = tree->Edge(kBack)->btree();
- if (!tree->refcount.IsMutable()) return {};
- ABSL_FALLTHROUGH_INTENDED;
- case 0:
- CordRep* edge = tree->Edge(kBack);
- if (!edge->refcount.IsMutable()) return {};
- if (edge->tag < FLAT) return {};
- size_t avail = edge->flat()->Capacity() - edge->length;
- if (avail == 0) return {};
- size_t delta = (std::min)(size, avail);
- Span<char> span = {edge->flat()->Data() + edge->length, delta};
- edge->length += delta;
- switch (height) {
- case 3:
- n3->length += delta;
- ABSL_FALLTHROUGH_INTENDED;
- case 2:
- n2->length += delta;
- ABSL_FALLTHROUGH_INTENDED;
- case 1:
- n1->length += delta;
- ABSL_FALLTHROUGH_INTENDED;
- case 0:
- tree->length += delta;
- return span;
- }
- break;
- }
- return GetAppendBufferSlow(size);
-}
-
-extern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kBack>(
- CordRepBtree* tree, CordRep* rep);
-
-extern template CordRepBtree* CordRepBtree::AddCordRep<CordRepBtree::kFront>(
- CordRepBtree* tree, CordRep* rep);
-
-inline CordRepBtree* CordRepBtree::Append(CordRepBtree* tree, CordRep* rep) {
- if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {
- return CordRepBtree::AddCordRep<kBack>(tree, rep);
- }
- return AppendSlow(tree, rep);
-}
-
-inline CordRepBtree* CordRepBtree::Prepend(CordRepBtree* tree, CordRep* rep) {
- if (ABSL_PREDICT_TRUE(IsDataEdge(rep))) {
- return CordRepBtree::AddCordRep<kFront>(tree, rep);
- }
- return PrependSlow(tree, rep);
-}
-
-#ifdef NDEBUG
-
-inline CordRepBtree* CordRepBtree::AssertValid(CordRepBtree* tree,
- bool /* shallow */) {
- return tree;
-}
-
-inline const CordRepBtree* CordRepBtree::AssertValid(const CordRepBtree* tree,
- bool /* shallow */) {
- return tree;
-}
-
-#endif
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc
deleted file mode 100644
index d1f9995d00..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.cc
+++ /dev/null
@@ -1,185 +0,0 @@
-// 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/strings/internal/cord_rep_btree_navigator.h"
-
-#include <cassert>
-
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-using ReadResult = CordRepBtreeNavigator::ReadResult;
-
-namespace {
-
-// Returns a `CordRepSubstring` from `rep` starting at `offset` of size `n`.
-// If `rep` is already a `CordRepSubstring` instance, an adjusted instance is
-// created based on the old offset and new offset.
-// Adopts a reference on `rep`. Rep must be a valid data edge. Returns
-// nullptr if `n == 0`, `rep` if `n == rep->length`.
-// Requires `offset < rep->length` and `offset + n <= rep->length`.
-// TODO(192061034): move to utility library in internal and optimize for small
-// substrings of larger reps.
-inline CordRep* Substring(CordRep* rep, size_t offset, size_t n) {
- assert(n <= rep->length);
- assert(offset < rep->length);
- assert(offset <= rep->length - n);
- assert(CordRepBtree::IsDataEdge(rep));
-
- if (n == 0) return nullptr;
- if (n == rep->length) return CordRep::Ref(rep);
-
- if (rep->tag == SUBSTRING) {
- offset += rep->substring()->start;
- rep = rep->substring()->child;
- }
-
- CordRepSubstring* substring = new CordRepSubstring();
- substring->length = n;
- substring->tag = SUBSTRING;
- substring->start = offset;
- substring->child = CordRep::Ref(rep);
- return substring;
-}
-
-inline CordRep* Substring(CordRep* rep, size_t offset) {
- return Substring(rep, offset, rep->length - offset);
-}
-
-} // namespace
-
-CordRepBtreeNavigator::Position CordRepBtreeNavigator::Skip(size_t n) {
- int height = 0;
- size_t index = index_[0];
- CordRepBtree* node = node_[0];
- CordRep* edge = node->Edge(index);
-
- // Overall logic: Find an edge of at least the length we need to skip.
- // We consume all edges which are smaller (i.e., must be 100% skipped).
- // If we exhausted all edges on the current level, we move one level
- // up the tree, and repeat until we either find the edge, or until we hit
- // the top of the tree meaning the skip exceeds tree->length.
- while (n >= edge->length) {
- n -= edge->length;
- while (++index == node->end()) {
- if (++height > height_) return {nullptr, n};
- node = node_[height];
- index = index_[height];
- }
- edge = node->Edge(index);
- }
-
- // If we moved up the tree, descend down to the leaf level, consuming all
- // edges that must be skipped.
- while (height > 0) {
- node = edge->btree();
- index_[height] = index;
- node_[--height] = node;
- index = node->begin();
- edge = node->Edge(index);
- while (n >= edge->length) {
- n -= edge->length;
- ++index;
- assert(index != node->end());
- edge = node->Edge(index);
- }
- }
- index_[0] = index;
- return {edge, n};
-}
-
-ReadResult CordRepBtreeNavigator::Read(size_t edge_offset, size_t n) {
- int height = 0;
- size_t length = edge_offset + n;
- size_t index = index_[0];
- CordRepBtree* node = node_[0];
- CordRep* edge = node->Edge(index);
- assert(edge_offset < edge->length);
-
- if (length < edge->length) {
- return {Substring(edge, edge_offset, n), length};
- }
-
- // Similar to 'Skip', we consume all edges that are inside the 'length' of
- // data that needs to be read. If we exhaust the current level, we move one
- // level up the tree and repeat until we hit the final edge that must be
- // (partially) read. We consume all edges into `subtree`.
- CordRepBtree* subtree = CordRepBtree::New(Substring(edge, edge_offset));
- size_t subtree_end = 1;
- do {
- length -= edge->length;
- while (++index == node->end()) {
- index_[height] = index;
- if (++height > height_) {
- subtree->set_end(subtree_end);
- if (length == 0) return {subtree, 0};
- CordRep::Unref(subtree);
- return {nullptr, length};
- }
- if (length != 0) {
- subtree->set_end(subtree_end);
- subtree = CordRepBtree::New(subtree);
- subtree_end = 1;
- }
- node = node_[height];
- index = index_[height];
- }
- edge = node->Edge(index);
- if (length >= edge->length) {
- subtree->length += edge->length;
- subtree->edges_[subtree_end++] = CordRep::Ref(edge);
- }
- } while (length >= edge->length);
- CordRepBtree* tree = subtree;
- subtree->length += length;
-
- // If we moved up the tree, descend down to the leaf level, consuming all
- // edges that must be read, adding 'down' nodes to `subtree`.
- while (height > 0) {
- node = edge->btree();
- index_[height] = index;
- node_[--height] = node;
- index = node->begin();
- edge = node->Edge(index);
-
- if (length != 0) {
- CordRepBtree* right = CordRepBtree::New(height);
- right->length = length;
- subtree->edges_[subtree_end++] = right;
- subtree->set_end(subtree_end);
- subtree = right;
- subtree_end = 0;
- while (length >= edge->length) {
- subtree->edges_[subtree_end++] = CordRep::Ref(edge);
- length -= edge->length;
- edge = node->Edge(++index);
- }
- }
- }
- // Add any (partial) edge still remaining at the leaf level.
- if (length != 0) {
- subtree->edges_[subtree_end++] = Substring(edge, 0, length);
- }
- subtree->set_end(subtree_end);
- index_[0] = index;
- return {tree, length};
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h
deleted file mode 100644
index 971b92eda6..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator.h
+++ /dev/null
@@ -1,265 +0,0 @@
-// 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_BTREE_NAVIGATOR_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
-
-#include <cassert>
-#include <iostream>
-
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordRepBtreeNavigator is a bi-directional navigator allowing callers to
-// navigate all the (leaf) data edges in a CordRepBtree instance.
-//
-// A CordRepBtreeNavigator instance is by default empty. Callers initialize a
-// navigator instance by calling one of `InitFirst()`, `InitLast()` or
-// `InitOffset()`, which establishes a current position. Callers can then
-// navigate using the `Next`, `Previous`, `Skip` and `Seek` methods.
-//
-// The navigator instance does not take or adopt a reference on the provided
-// `tree` on any of the initialization calls. Callers are responsible for
-// guaranteeing the lifecycle of the provided tree. A navigator instance can
-// be reset to the empty state by calling `Reset`.
-//
-// A navigator only keeps positional state on the 'current data edge', it does
-// explicitly not keep any 'offset' state. The class does accept and return
-// offsets in the `Read()`, `Skip()` and 'Seek()` methods as these would
-// otherwise put a big burden on callers. Callers are expected to maintain
-// (returned) offset info if they require such granular state.
-class CordRepBtreeNavigator {
- public:
- // The logical position as returned by the Seek() and Skip() functions.
- // Returns the current leaf edge for the desired seek or skip position and
- // the offset of that position inside that edge.
- struct Position {
- CordRep* edge;
- size_t offset;
- };
-
- // The read result as returned by the Read() function.
- // `tree` contains the resulting tree which is identical to the result
- // of calling CordRepBtree::SubTree(...) on the tree being navigated.
- // `n` contains the number of bytes used from the last navigated to
- // edge of the tree.
- struct ReadResult {
- CordRep* tree;
- size_t n;
- };
-
- // Returns true if this instance is not empty.
- explicit operator bool() const;
-
- // Returns the tree for this instance or nullptr if empty.
- CordRepBtree* btree() const;
-
- // Returns the data edge of the current position.
- // Requires this instance to not be empty.
- CordRep* Current() const;
-
- // Resets this navigator to `tree`, returning the first data edge in the tree.
- CordRep* InitFirst(CordRepBtree* tree);
-
- // Resets this navigator to `tree`, returning the last data edge in the tree.
- CordRep* InitLast(CordRepBtree* tree);
-
- // Resets this navigator to `tree` returning the data edge at position
- // `offset` and the relative offset of `offset` into that data edge.
- // Returns `Position.edge = nullptr` if the provided offset is greater
- // than or equal to the length of the tree, in which case the state of
- // the navigator instance remains unchanged.
- Position InitOffset(CordRepBtree* tree, size_t offset);
-
- // Navigates to the next data edge.
- // Returns the next data edge or nullptr if there is no next data edge, in
- // which case the current position remains unchanged.
- CordRep* Next();
-
- // Navigates to the previous data edge.
- // Returns the previous data edge or nullptr if there is no previous data
- // edge, in which case the current position remains unchanged.
- CordRep* Previous();
-
- // Navigates to the data edge at position `offset`. Returns the navigated to
- // data edge in `Position.edge` and the relative offset of `offset` into that
- // data edge in `Position.offset`. Returns `Position.edge = nullptr` if the
- // provide offset is greater than or equal to the tree's length.
- Position Seek(size_t offset);
-
- // Reads `n` bytes of data starting at offset `edge_offset` of the current
- // data edge, and returns the result in `ReadResult.tree`. `ReadResult.n`
- // contains the 'bytes used` from the last / current data edge in the tree.
- // This allows users that mix regular navigation (using string views) and
- // 'read into cord' navigation to keep track of the current state, and which
- // bytes have been consumed from a navigator.
- // This function returns `ReadResult.tree = nullptr` if the requested length
- // exceeds the length of the tree starting at the current data edge.
- ReadResult Read(size_t edge_offset, size_t n);
-
- // Skips `n` bytes forward from the current data edge, returning the navigated
- // to data edge in `Position.edge` and `Position.offset` containing the offset
- // inside that data edge. Note that the state of the navigator is left
- // unchanged if `n` is smaller than the length of the current data edge.
- Position Skip(size_t n);
-
- // Resets this instance to the default / empty state.
- void Reset();
-
- private:
- // Slow path for Next() if Next() reached the end of a leaf node. Backtracks
- // up the stack until it finds a node that has a 'next' position available,
- // and then does a 'front dive' towards the next leaf node.
- CordRep* NextUp();
-
- // Slow path for Previous() if Previous() reached the beginning of a leaf
- // node. Backtracks up the stack until it finds a node that has a 'previous'
- // position available, and then does a 'back dive' towards the previous leaf
- // node.
- CordRep* PreviousUp();
-
- // Generic implementation of InitFirst() and InitLast().
- template <CordRepBtree::EdgeType edge_type>
- CordRep* Init(CordRepBtree* tree);
-
- // `height_` contains the height of the current tree, or -1 if empty.
- int height_ = -1;
-
- // `index_` and `node_` contain the navigation state as the 'path' to the
- // current data edge which is at `node_[0]->Edge(index_[0])`. The contents
- // of these are undefined until the instance is initialized (`height_ >= 0`).
- uint8_t index_[CordRepBtree::kMaxHeight];
- CordRepBtree* node_[CordRepBtree::kMaxHeight];
-};
-
-// Returns true if this instance is not empty.
-inline CordRepBtreeNavigator::operator bool() const { return height_ >= 0; }
-
-inline CordRepBtree* CordRepBtreeNavigator::btree() const {
- return height_ >= 0 ? node_[height_] : nullptr;
-}
-
-inline CordRep* CordRepBtreeNavigator::Current() const {
- assert(height_ >= 0);
- return node_[0]->Edge(index_[0]);
-}
-
-inline void CordRepBtreeNavigator::Reset() { height_ = -1; }
-
-inline CordRep* CordRepBtreeNavigator::InitFirst(CordRepBtree* tree) {
- return Init<CordRepBtree::kFront>(tree);
-}
-
-inline CordRep* CordRepBtreeNavigator::InitLast(CordRepBtree* tree) {
- return Init<CordRepBtree::kBack>(tree);
-}
-
-template <CordRepBtree::EdgeType edge_type>
-inline CordRep* CordRepBtreeNavigator::Init(CordRepBtree* tree) {
- assert(tree != nullptr);
- assert(tree->size() > 0);
- int height = height_ = tree->height();
- size_t index = tree->index(edge_type);
- node_[height] = tree;
- index_[height] = static_cast<uint8_t>(index);
- while (--height >= 0) {
- tree = tree->Edge(index)->btree();
- node_[height] = tree;
- index = tree->index(edge_type);
- index_[height] = static_cast<uint8_t>(index);
- }
- return node_[0]->Edge(index);
-}
-
-inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::Seek(
- size_t offset) {
- assert(btree() != nullptr);
- int height = height_;
- CordRepBtree* edge = node_[height];
- if (ABSL_PREDICT_FALSE(offset >= edge->length)) return {nullptr, 0};
- CordRepBtree::Position index = edge->IndexOf(offset);
- index_[height] = static_cast<uint8_t>(index.index);
- while (--height >= 0) {
- edge = edge->Edge(index.index)->btree();
- node_[height] = edge;
- index = edge->IndexOf(index.n);
- index_[height] = static_cast<uint8_t>(index.index);
- }
- return {edge->Edge(index.index), index.n};
-}
-
-inline CordRepBtreeNavigator::Position CordRepBtreeNavigator::InitOffset(
- CordRepBtree* tree, size_t offset) {
- assert(tree != nullptr);
- if (ABSL_PREDICT_FALSE(offset >= tree->length)) return {nullptr, 0};
- height_ = tree->height();
- node_[height_] = tree;
- return Seek(offset);
-}
-
-inline CordRep* CordRepBtreeNavigator::Next() {
- CordRepBtree* edge = node_[0];
- return index_[0] == edge->back() ? NextUp() : edge->Edge(++index_[0]);
-}
-
-inline CordRep* CordRepBtreeNavigator::Previous() {
- CordRepBtree* edge = node_[0];
- return index_[0] == edge->begin() ? PreviousUp() : edge->Edge(--index_[0]);
-}
-
-inline CordRep* CordRepBtreeNavigator::NextUp() {
- assert(index_[0] == node_[0]->back());
- CordRepBtree* edge;
- size_t index;
- int height = 0;
- do {
- if (++height > height_) return nullptr;
- edge = node_[height];
- index = index_[height] + 1;
- } while (index == edge->end());
- index_[height] = static_cast<uint8_t>(index);
- do {
- node_[--height] = edge = edge->Edge(index)->btree();
- index_[height] = static_cast<uint8_t>(index = edge->begin());
- } while (height > 0);
- return edge->Edge(index);
-}
-
-inline CordRep* CordRepBtreeNavigator::PreviousUp() {
- assert(index_[0] == node_[0]->begin());
- CordRepBtree* edge;
- size_t index;
- int height = 0;
- do {
- if (++height > height_) return nullptr;
- edge = node_[height];
- index = index_[height];
- } while (index == edge->begin());
- index_[height] = static_cast<uint8_t>(--index);
- do {
- node_[--height] = edge = edge->Edge(index)->btree();
- index_[height] = static_cast<uint8_t>(index = edge->back());
- } while (height > 0);
- return edge->Edge(index);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_NAVIGATOR_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator_test.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator_test.cc
deleted file mode 100644
index ce09b1992a..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_navigator_test.cc
+++ /dev/null
@@ -1,325 +0,0 @@
-// 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/strings/internal/cord_rep_btree_navigator.h"
-
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_test_util.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::Eq;
-using ::testing::Ne;
-
-using ::absl::cordrep_testing::CordRepBtreeFromFlats;
-using ::absl::cordrep_testing::CordToString;
-using ::absl::cordrep_testing::CreateFlatsFromString;
-using ::absl::cordrep_testing::CreateRandomString;
-using ::absl::cordrep_testing::MakeFlat;
-using ::absl::cordrep_testing::MakeSubstring;
-
-using ReadResult = CordRepBtreeNavigator::ReadResult;
-using Position = CordRepBtreeNavigator::Position;
-
-// CordRepBtreeNavigatorTest is a test fixture which automatically creates a
-// tree to test navigation logic on. The parameter `count' defines the number of
-// data edges in the test tree.
-class CordRepBtreeNavigatorTest : public testing::TestWithParam<int> {
- public:
- using Flats = std::vector<CordRep*>;
- static constexpr size_t kCharsPerFlat = 3;
-
- CordRepBtreeNavigatorTest() {
- data_ = CreateRandomString(count() * kCharsPerFlat);
- flats_ = CreateFlatsFromString(data_, kCharsPerFlat);
-
- // Turn flat 0 or 1 into a substring to cover partial reads on substrings.
- if (count() > 1) {
- CordRep::Unref(flats_[1]);
- flats_[1] = MakeSubstring(kCharsPerFlat, kCharsPerFlat, MakeFlat(data_));
- } else {
- CordRep::Unref(flats_[0]);
- flats_[0] = MakeSubstring(0, kCharsPerFlat, MakeFlat(data_));
- }
-
- tree_ = CordRepBtreeFromFlats(flats_);
- }
-
- ~CordRepBtreeNavigatorTest() override { CordRep::Unref(tree_); }
-
- int count() const { return GetParam(); }
- CordRepBtree* tree() { return tree_; }
- const std::string& data() const { return data_; }
- const std::vector<CordRep*>& flats() const { return flats_; }
-
- static std::string ToString(testing::TestParamInfo<int> param) {
- return absl::StrCat(param.param, "_Flats");
- }
-
- private:
- std::string data_;
- Flats flats_;
- CordRepBtree* tree_;
-};
-
-INSTANTIATE_TEST_SUITE_P(
- WithParam, CordRepBtreeNavigatorTest,
- testing::Values(1, CordRepBtree::kMaxCapacity - 1,
- CordRepBtree::kMaxCapacity,
- CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity - 1,
- CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity,
- CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity + 1,
- CordRepBtree::kMaxCapacity* CordRepBtree::kMaxCapacity * 2 +
- 17),
- CordRepBtreeNavigatorTest::ToString);
-
-TEST(CordRepBtreeNavigatorTest, Uninitialized) {
- CordRepBtreeNavigator nav;
- EXPECT_FALSE(nav);
- EXPECT_THAT(nav.btree(), Eq(nullptr));
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
- EXPECT_DEATH(nav.Current(), ".*");
-#endif
-}
-
-TEST_P(CordRepBtreeNavigatorTest, InitFirst) {
- CordRepBtreeNavigator nav;
- CordRep* edge = nav.InitFirst(tree());
- EXPECT_TRUE(nav);
- EXPECT_THAT(nav.btree(), Eq(tree()));
- EXPECT_THAT(nav.Current(), Eq(flats().front()));
- EXPECT_THAT(edge, Eq(flats().front()));
-}
-
-TEST_P(CordRepBtreeNavigatorTest, InitLast) {
- CordRepBtreeNavigator nav;
- CordRep* edge = nav.InitLast(tree());
- EXPECT_TRUE(nav);
- EXPECT_THAT(nav.btree(), Eq(tree()));
- EXPECT_THAT(nav.Current(), Eq(flats().back()));
- EXPECT_THAT(edge, Eq(flats().back()));
-}
-
-TEST_P(CordRepBtreeNavigatorTest, NextPrev) {
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
- const Flats& flats = this->flats();
-
- EXPECT_THAT(nav.Previous(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.front()));
- for (int i = 1; i < flats.size(); ++i) {
- ASSERT_THAT(nav.Next(), Eq(flats[i]));
- EXPECT_THAT(nav.Current(), Eq(flats[i]));
- }
- EXPECT_THAT(nav.Next(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.back()));
- for (int i = static_cast<int>(flats.size()) - 2; i >= 0; --i) {
- ASSERT_THAT(nav.Previous(), Eq(flats[i]));
- EXPECT_THAT(nav.Current(), Eq(flats[i]));
- }
- EXPECT_THAT(nav.Previous(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.front()));
-}
-
-TEST_P(CordRepBtreeNavigatorTest, PrevNext) {
- CordRepBtreeNavigator nav;
- nav.InitLast(tree());
- const Flats& flats = this->flats();
-
- EXPECT_THAT(nav.Next(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.back()));
- for (int i = static_cast<int>(flats.size()) - 2; i >= 0; --i) {
- ASSERT_THAT(nav.Previous(), Eq(flats[i]));
- EXPECT_THAT(nav.Current(), Eq(flats[i]));
- }
- EXPECT_THAT(nav.Previous(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.front()));
- for (int i = 1; i < flats.size(); ++i) {
- ASSERT_THAT(nav.Next(), Eq(flats[i]));
- EXPECT_THAT(nav.Current(), Eq(flats[i]));
- }
- EXPECT_THAT(nav.Next(), Eq(nullptr));
- EXPECT_THAT(nav.Current(), Eq(flats.back()));
-}
-
-TEST(CordRepBtreeNavigatorTest, Reset) {
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree);
- nav.Reset();
- EXPECT_FALSE(nav);
- EXPECT_THAT(nav.btree(), Eq(nullptr));
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
- EXPECT_DEATH(nav.Current(), ".*");
-#endif
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeNavigatorTest, Skip) {
- int count = this->count();
- const Flats& flats = this->flats();
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
-
- for (int char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {
- Position pos = nav.Skip(char_offset);
- EXPECT_THAT(pos.edge, Eq(nav.Current()));
- EXPECT_THAT(pos.edge, Eq(flats[0]));
- EXPECT_THAT(pos.offset, Eq(char_offset));
- }
-
- for (int index1 = 0; index1 < count; ++index1) {
- for (int index2 = index1; index2 < count; ++index2) {
- for (int char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
-
- size_t length1 = index1 * kCharsPerFlat;
- Position pos1 = nav.Skip(length1 + char_offset);
- ASSERT_THAT(pos1.edge, Eq(flats[index1]));
- ASSERT_THAT(pos1.edge, Eq(nav.Current()));
- ASSERT_THAT(pos1.offset, Eq(char_offset));
-
- size_t length2 = index2 * kCharsPerFlat;
- Position pos2 = nav.Skip(length2 - length1 + char_offset);
- ASSERT_THAT(pos2.edge, Eq(flats[index2]));
- ASSERT_THAT(pos2.edge, Eq(nav.Current()));
- ASSERT_THAT(pos2.offset, Eq(char_offset));
- }
- }
- }
-}
-
-TEST_P(CordRepBtreeNavigatorTest, Seek) {
- int count = this->count();
- const Flats& flats = this->flats();
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
-
- for (int char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {
- Position pos = nav.Seek(char_offset);
- EXPECT_THAT(pos.edge, Eq(nav.Current()));
- EXPECT_THAT(pos.edge, Eq(flats[0]));
- EXPECT_THAT(pos.offset, Eq(char_offset));
- }
-
- for (int index = 0; index < count; ++index) {
- for (int char_offset = 0; char_offset < kCharsPerFlat; ++char_offset) {
- size_t offset = index * kCharsPerFlat + char_offset;
- Position pos1 = nav.Seek(offset);
- ASSERT_THAT(pos1.edge, Eq(flats[index]));
- ASSERT_THAT(pos1.edge, Eq(nav.Current()));
- ASSERT_THAT(pos1.offset, Eq(char_offset));
- }
- }
-}
-
-TEST(CordRepBtreeNavigatorTest, InitOffset) {
- // Whitebox: InitOffset() is implemented in terms of Seek() which is
- // exhaustively tested. Only test it initializes / forwards properly..
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
- tree = CordRepBtree::Append(tree, MakeFlat("def"));
- CordRepBtreeNavigator nav;
- Position pos = nav.InitOffset(tree, 5);
- EXPECT_TRUE(nav);
- EXPECT_THAT(nav.btree(), Eq(tree));
- EXPECT_THAT(pos.edge, Eq(tree->Edges()[1]));
- EXPECT_THAT(pos.edge, Eq(nav.Current()));
- EXPECT_THAT(pos.offset, Eq(2));
- CordRep::Unref(tree);
-}
-
-TEST(CordRepBtreeNavigatorTest, InitOffsetAndSeekBeyondLength) {
- CordRepBtree* tree1 = CordRepBtree::Create(MakeFlat("abc"));
- CordRepBtree* tree2 = CordRepBtree::Create(MakeFlat("def"));
-
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree1);
- EXPECT_THAT(nav.Seek(3).edge, Eq(nullptr));
- EXPECT_THAT(nav.Seek(100).edge, Eq(nullptr));
- EXPECT_THAT(nav.btree(), Eq(tree1));
- EXPECT_THAT(nav.Current(), Eq(tree1->Edges().front()));
-
- EXPECT_THAT(nav.InitOffset(tree2, 3).edge, Eq(nullptr));
- EXPECT_THAT(nav.InitOffset(tree2, 100).edge, Eq(nullptr));
- EXPECT_THAT(nav.btree(), Eq(tree1));
- EXPECT_THAT(nav.Current(), Eq(tree1->Edges().front()));
-
- CordRep::Unref(tree1);
- CordRep::Unref(tree2);
-}
-
-TEST_P(CordRepBtreeNavigatorTest, Read) {
- const Flats& flats = this->flats();
- const std::string& data = this->data();
-
- for (size_t offset = 0; offset < data.size(); ++offset) {
- for (size_t length = 1; length <= data.size() - offset; ++length) {
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
-
- // Skip towards edge holding offset
- size_t edge_offset = nav.Skip(offset).offset;
-
- // Read node
- ReadResult result = nav.Read(edge_offset, length);
- ASSERT_THAT(result.tree, Ne(nullptr));
- EXPECT_THAT(result.tree->length, Eq(length));
- if (result.tree->tag == BTREE) {
- ASSERT_TRUE(CordRepBtree::IsValid(result.tree->btree()));
- }
-
- // Verify contents
- std::string value = CordToString(result.tree);
- EXPECT_THAT(value, Eq(data.substr(offset, length)));
-
- // Verify 'partial last edge' reads.
- size_t partial = (offset + length) % kCharsPerFlat;
- ASSERT_THAT(result.n, Eq(partial));
-
- // Verify ending position if not EOF
- if (offset + length < data.size()) {
- size_t index = (offset + length) / kCharsPerFlat;
- EXPECT_THAT(nav.Current(), Eq(flats[index]));
- }
-
- CordRep::Unref(result.tree);
- }
- }
-}
-
-TEST_P(CordRepBtreeNavigatorTest, ReadBeyondLengthOfTree) {
- CordRepBtreeNavigator nav;
- nav.InitFirst(tree());
- ReadResult result = nav.Read(2, tree()->length);
- ASSERT_THAT(result.tree, Eq(nullptr));
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc
deleted file mode 100644
index 5dc76966d2..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// 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/strings/internal/cord_rep_btree_reader.h"
-
-#include <cassert>
-
-#include "absl/base/config.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_btree_navigator.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-absl::string_view CordRepBtreeReader::Read(size_t n, size_t chunk_size,
- CordRep*& tree) {
- assert(chunk_size <= navigator_.Current()->length);
-
- // If chunk_size is non-zero, we need to start inside last returned edge.
- // Else we start reading at the next data edge of the tree.
- CordRep* edge = chunk_size ? navigator_.Current() : navigator_.Next();
- const size_t offset = chunk_size ? edge->length - chunk_size : 0;
-
- // Read the sub tree and verify we got what we wanted.
- ReadResult result = navigator_.Read(offset, n);
- tree = result.tree;
-
- // If the data returned in `tree` was covered entirely by `chunk_size`, i.e.,
- // read from the 'previous' edge, we did not consume any additional data, and
- // can directly return the substring into the current data edge as the next
- // chunk. We can easily establish from the above code that `navigator_.Next()`
- // has not been called as that requires `chunk_size` to be zero.
- if (n < chunk_size) return CordRepBtree::EdgeData(edge).substr(result.n);
-
- // The amount of data taken from the last edge is `chunk_size` and `result.n`
- // contains the offset into the current edge trailing the read data (which can
- // be 0). As the call to `navigator_.Read()` could have consumed all remaining
- // data, calling `navigator_.Current()` is not safe before checking if we
- // already consumed all remaining data.
- const size_t consumed_by_read = n - chunk_size - result.n;
- if (consumed_by_read >= remaining_) {
- remaining_ = 0;
- return {};
- }
-
- // We did not read all data, return remaining data from current edge.
- edge = navigator_.Current();
- remaining_ -= consumed_by_read + edge->length;
- return CordRepBtree::EdgeData(edge).substr(result.n);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h
deleted file mode 100644
index 7aa79dbf10..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader.h
+++ /dev/null
@@ -1,211 +0,0 @@
-// 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_BTREE_READER_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
-
-#include <cassert>
-
-#include "absl/base/config.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_btree_navigator.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordRepBtreeReader implements logic to iterate over cord btrees.
-// References to the underlying data are returned as absl::string_view values.
-// The most typical use case is a forward only iteration over tree data.
-// The class also provides `Skip()`, `Seek()` and `Read()` methods similar to
-// CordRepBtreeNavigator that allow more advanced navigation.
-//
-// Example: iterate over all data inside a cord btree:
-//
-// CordRepBtreeReader reader;
-// for (string_view sv = reader.Init(tree); !sv.Empty(); sv = sv.Next()) {
-// DoSomethingWithDataIn(sv);
-// }
-//
-// All navigation methods always return the next 'chunk' of data. The class
-// assumes that all data is directly 'consumed' by the caller. For example:
-// invoking `Skip()` will skip the desired number of bytes, and directly
-// read and return the next chunk of data directly after the skipped bytes.
-//
-// Example: iterate over all data inside a btree skipping the first 100 bytes:
-//
-// CordRepBtreeReader reader;
-// absl::string_view sv = reader.Init(tree);
-// if (sv.length() > 100) {
-// sv.RemovePrefix(100);
-// } else {
-// sv = reader.Skip(100 - sv.length());
-// }
-// while (!sv.empty()) {
-// DoSomethingWithDataIn(sv);
-// absl::string_view sv = reader.Next();
-// }
-//
-// It is important to notice that `remaining` is based on the end position of
-// the last data edge returned to the caller, not the cumulative data returned
-// to the caller which can be less in cases of skipping or seeking over data.
-//
-// For example, consider a cord btree with five data edges: "abc", "def", "ghi",
-// "jkl" and "mno":
-//
-// absl::string_view sv;
-// CordRepBtreeReader reader;
-//
-// sv = reader.Init(tree); // sv = "abc", remaining = 12
-// sv = reader.Skip(4); // sv = "hi", remaining = 6
-// sv = reader.Skip(2); // sv = "l", remaining = 3
-// sv = reader.Next(); // sv = "mno", remaining = 0
-// sv = reader.Seek(1); // sv = "bc", remaining = 12
-//
-class CordRepBtreeReader {
- public:
- using ReadResult = CordRepBtreeNavigator::ReadResult;
- using Position = CordRepBtreeNavigator::Position;
-
- // Returns true if this instance is not empty.
- explicit operator bool() const { return navigator_.btree() != nullptr; }
-
- // Returns the tree referenced by this instance or nullptr if empty.
- CordRepBtree* btree() const { return navigator_.btree(); }
-
- // Returns the current data edge inside the referenced btree.
- // Requires that the current instance is not empty.
- CordRep* node() const { return navigator_.Current(); }
-
- // Returns the length of the referenced tree.
- // Requires that the current instance is not empty.
- size_t length() const;
-
- // Returns the number of remaining bytes available for iteration, which is the
- // number of bytes directly following the end of the last chunk returned.
- // This value will be zero if we iterated over the last edge in the bound
- // tree, in which case any call to Next() or Skip() will return an empty
- // string_view reflecting the EOF state.
- // Note that a call to `Seek()` resets `remaining` to a value based on the
- // end position of the chunk returned by that call.
- size_t remaining() const { return remaining_; }
-
- // Resets this instance to an empty value.
- void Reset() { navigator_.Reset(); }
-
- // Initializes this instance with `tree`. `tree` must not be null.
- // Returns a reference to the first data edge of the provided tree.
- absl::string_view Init(CordRepBtree* tree);
-
- // Navigates to and returns the next data edge of the referenced tree.
- // Returns an empty string_view if an attempt is made to read beyond the end
- // of the tree, i.e.: if `remaining()` is zero indicating an EOF condition.
- // Requires that the current instance is not empty.
- absl::string_view Next();
-
- // Skips the provided amount of bytes and returns a reference to the data
- // directly following the skipped bytes.
- absl::string_view Skip(size_t skip);
-
- // Reads `n` bytes into `tree`.
- // If `chunk_size` is zero, starts reading at the next data edge. If
- // `chunk_size` is non zero, the read starts at the last `chunk_size` bytes of
- // the last returned data edge. Effectively, this means that the read starts
- // at offset `consumed() - chunk_size`.
- // Requires that `chunk_size` is less than or equal to the length of the
- // last returned data edge. The purpose of `chunk_size` is to simplify code
- // partially consuming a returned chunk and wanting to include the remaining
- // bytes in the Read call. For example, the below code will read 1000 bytes of
- // data into a cord tree if the first chunk starts with "big:":
- //
- // CordRepBtreeReader reader;
- // absl::string_view sv = reader.Init(tree);
- // if (absl::StartsWith(sv, "big:")) {
- // CordRepBtree tree;
- // sv = reader.Read(1000, sv.size() - 4 /* "big:" */, &tree);
- // }
- //
- // This method will return an empty string view if all remaining data was
- // read. If `n` exceeded the amount of remaining data this function will
- // return an empty string view and `tree` will be set to nullptr.
- // In both cases, `consumed` will be set to `length`.
- absl::string_view Read(size_t n, size_t chunk_size, CordRep*& tree);
-
- // 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
- // cord tree 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.
- // Returns an empty string view if `offset` is equal to or greater than the
- // length of the referenced tree.
- absl::string_view Seek(size_t offset);
-
- private:
- size_t remaining_ = 0;
- CordRepBtreeNavigator navigator_;
-};
-
-inline size_t CordRepBtreeReader::length() const {
- assert(btree() != nullptr);
- return btree()->length;
-}
-
-inline absl::string_view CordRepBtreeReader::Init(CordRepBtree* tree) {
- assert(tree != nullptr);
- const CordRep* edge = navigator_.InitFirst(tree);
- remaining_ = tree->length - edge->length;
- return CordRepBtree::EdgeData(edge);
-}
-
-inline absl::string_view CordRepBtreeReader::Next() {
- if (remaining_ == 0) return {};
- const CordRep* edge = navigator_.Next();
- assert(edge != nullptr);
- remaining_ -= edge->length;
- return CordRepBtree::EdgeData(edge);
-}
-
-inline absl::string_view CordRepBtreeReader::Skip(size_t skip) {
- // As we are always positioned on the last 'consumed' edge, we
- // need to skip the current edge as well as `skip`.
- const size_t edge_length = navigator_.Current()->length;
- CordRepBtreeNavigator::Position pos = navigator_.Skip(skip + edge_length);
- if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
- remaining_ = 0;
- return {};
- }
- // The combined length of all edges skipped before `pos.edge` is `skip -
- // pos.offset`, all of which are 'consumed', as well as the current edge.
- remaining_ -= skip - pos.offset + pos.edge->length;
- return CordRepBtree::EdgeData(pos.edge).substr(pos.offset);
-}
-
-inline absl::string_view CordRepBtreeReader::Seek(size_t offset) {
- const CordRepBtreeNavigator::Position pos = navigator_.Seek(offset);
- if (ABSL_PREDICT_FALSE(pos.edge == nullptr)) {
- remaining_ = 0;
- return {};
- }
- absl::string_view chunk = CordRepBtree::EdgeData(pos.edge).substr(pos.offset);
- remaining_ = length() - offset - chunk.length();
- return chunk;
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_BTREE_READER_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc
deleted file mode 100644
index 9b27a81fdb..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_reader_test.cc
+++ /dev/null
@@ -1,293 +0,0 @@
-// 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/strings/internal/cord_rep_btree_reader.h"
-
-#include <iostream>
-#include <random>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/cord.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_test_util.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::Eq;
-using ::testing::IsEmpty;
-using ::testing::Ne;
-using ::testing::Not;
-
-using ::absl::cordrep_testing::CordRepBtreeFromFlats;
-using ::absl::cordrep_testing::MakeFlat;
-using ::absl::cordrep_testing::CordToString;
-using ::absl::cordrep_testing::CreateFlatsFromString;
-using ::absl::cordrep_testing::CreateRandomString;
-
-using ReadResult = CordRepBtreeReader::ReadResult;
-
-TEST(CordRepBtreeReaderTest, Next) {
- constexpr size_t kChars = 3;
- const size_t cap = CordRepBtree::kMaxCapacity;
- int counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
-
- for (int count : counts) {
- std::string data = CreateRandomString(count * kChars);
- std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
- CordRepBtree* node = CordRepBtreeFromFlats(flats);
-
- CordRepBtreeReader reader;
- size_t remaining = data.length();
- absl::string_view chunk = reader.Init(node);
- EXPECT_THAT(chunk, Eq(data.substr(0, chunk.length())));
-
- remaining -= chunk.length();
- EXPECT_THAT(reader.remaining(), Eq(remaining));
-
- while (remaining > 0) {
- const size_t offset = data.length() - remaining;
- chunk = reader.Next();
- EXPECT_THAT(chunk, Eq(data.substr(offset, chunk.length())));
-
- remaining -= chunk.length();
- EXPECT_THAT(reader.remaining(), Eq(remaining));
- }
-
- EXPECT_THAT(reader.remaining(), Eq(0));
-
- // Verify trying to read beyond EOF returns empty string_view
- EXPECT_THAT(reader.Next(), testing::IsEmpty());
-
- CordRep::Unref(node);
- }
-}
-
-TEST(CordRepBtreeReaderTest, Skip) {
- constexpr size_t kChars = 3;
- const size_t cap = CordRepBtree::kMaxCapacity;
- int counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
-
- for (int count : counts) {
- std::string data = CreateRandomString(count * kChars);
- std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
- CordRepBtree* node = CordRepBtreeFromFlats(flats);
-
- for (size_t skip1 = 0; skip1 < data.length() - kChars; ++skip1) {
- for (size_t skip2 = 0; skip2 < data.length() - kChars; ++skip2) {
- CordRepBtreeReader reader;
- size_t remaining = data.length();
- absl::string_view chunk = reader.Init(node);
- remaining -= chunk.length();
-
- chunk = reader.Skip(skip1);
- size_t offset = data.length() - remaining;
- ASSERT_THAT(chunk, Eq(data.substr(offset + skip1, chunk.length())));
- remaining -= chunk.length() + skip1;
- ASSERT_THAT(reader.remaining(), Eq(remaining));
-
- if (remaining == 0) continue;
-
- size_t skip = std::min(remaining - 1, skip2);
- chunk = reader.Skip(skip);
- offset = data.length() - remaining;
- ASSERT_THAT(chunk, Eq(data.substr(offset + skip, chunk.length())));
- }
- }
-
- CordRep::Unref(node);
- }
-}
-
-TEST(CordRepBtreeReaderTest, SkipBeyondLength) {
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
- tree = CordRepBtree::Append(tree, MakeFlat("def"));
- CordRepBtreeReader reader;
- reader.Init(tree);
- EXPECT_THAT(reader.Skip(100), IsEmpty());
- EXPECT_THAT(reader.remaining(), Eq(0));
- CordRep::Unref(tree);
-}
-
-TEST(CordRepBtreeReaderTest, Seek) {
- constexpr size_t kChars = 3;
- const size_t cap = CordRepBtree::kMaxCapacity;
- int counts[] = {1, 2, cap, cap * cap, cap * cap + 1, cap * cap * 2 + 17};
-
- for (int count : counts) {
- std::string data = CreateRandomString(count * kChars);
- std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
- CordRepBtree* node = CordRepBtreeFromFlats(flats);
-
- for (size_t seek = 0; seek < data.length() - 1; ++seek) {
- CordRepBtreeReader reader;
- reader.Init(node);
- absl::string_view chunk = reader.Seek(seek);
- ASSERT_THAT(chunk, Not(IsEmpty()));
- ASSERT_THAT(chunk, Eq(data.substr(seek, chunk.length())));
- ASSERT_THAT(reader.remaining(),
- Eq(data.length() - seek - chunk.length()));
- }
-
- CordRep::Unref(node);
- }
-}
-
-TEST(CordRepBtreeReaderTest, SeekBeyondLength) {
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
- tree = CordRepBtree::Append(tree, MakeFlat("def"));
- CordRepBtreeReader reader;
- reader.Init(tree);
- EXPECT_THAT(reader.Seek(6), IsEmpty());
- EXPECT_THAT(reader.remaining(), Eq(0));
- EXPECT_THAT(reader.Seek(100), IsEmpty());
- EXPECT_THAT(reader.remaining(), Eq(0));
- CordRep::Unref(tree);
-}
-
-TEST(CordRepBtreeReaderTest, Read) {
- std::string data = "abcdefghijklmno";
- std::vector<CordRep*> flats = CreateFlatsFromString(data, 5);
- CordRepBtree* node = CordRepBtreeFromFlats(flats);
-
- CordRep* tree;
- CordRepBtreeReader reader;
- absl::string_view chunk;
-
- // Read zero bytes
- chunk = reader.Init(node);
- chunk = reader.Read(0, chunk.length(), tree);
- EXPECT_THAT(tree, Eq(nullptr));
- EXPECT_THAT(chunk, Eq("abcde"));
- EXPECT_THAT(reader.remaining(), Eq(10));
- EXPECT_THAT(reader.Next(), Eq("fghij"));
-
- // Read in full
- chunk = reader.Init(node);
- chunk = reader.Read(15, chunk.length(), tree);
- EXPECT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("abcdefghijklmno"));
- EXPECT_THAT(chunk, Eq(""));
- EXPECT_THAT(reader.remaining(), Eq(0));
- CordRep::Unref(tree);
-
- // Read < chunk bytes
- chunk = reader.Init(node);
- chunk = reader.Read(3, chunk.length(), tree);
- ASSERT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("abc"));
- EXPECT_THAT(chunk, Eq("de"));
- EXPECT_THAT(reader.remaining(), Eq(10));
- EXPECT_THAT(reader.Next(), Eq("fghij"));
- CordRep::Unref(tree);
-
- // Read < chunk bytes at offset
- chunk = reader.Init(node);
- chunk = reader.Read(2, chunk.length() - 2, tree);
- ASSERT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("cd"));
- EXPECT_THAT(chunk, Eq("e"));
- EXPECT_THAT(reader.remaining(), Eq(10));
- EXPECT_THAT(reader.Next(), Eq("fghij"));
- CordRep::Unref(tree);
-
- // Read from consumed chunk
- chunk = reader.Init(node);
- chunk = reader.Read(3, 0, tree);
- ASSERT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("fgh"));
- EXPECT_THAT(chunk, Eq("ij"));
- EXPECT_THAT(reader.remaining(), Eq(5));
- EXPECT_THAT(reader.Next(), Eq("klmno"));
- CordRep::Unref(tree);
-
- // Read across chunks
- chunk = reader.Init(node);
- chunk = reader.Read(12, chunk.length() - 2, tree);
- ASSERT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("cdefghijklmn"));
- EXPECT_THAT(chunk, Eq("o"));
- EXPECT_THAT(reader.remaining(), Eq(0));
- CordRep::Unref(tree);
-
- // Read across chunks landing on exact edge boundary
- chunk = reader.Init(node);
- chunk = reader.Read(10 - 2, chunk.length() - 2, tree);
- ASSERT_THAT(tree, Ne(nullptr));
- EXPECT_THAT(CordToString(tree), Eq("cdefghij"));
- EXPECT_THAT(chunk, Eq("klmno"));
- EXPECT_THAT(reader.remaining(), Eq(0));
- CordRep::Unref(tree);
-
- CordRep::Unref(node);
-}
-
-TEST(CordRepBtreeReaderTest, ReadExhaustive) {
- constexpr size_t kChars = 3;
- const size_t cap = CordRepBtree::kMaxCapacity;
- int counts[] = {1, 2, cap, cap * cap + 1, cap * cap * cap * 2 + 17};
-
- for (int count : counts) {
- std::string data = CreateRandomString(count * kChars);
- std::vector<CordRep*> flats = CreateFlatsFromString(data, kChars);
- CordRepBtree* node = CordRepBtreeFromFlats(flats);
-
- for (size_t read_size : {kChars - 1, kChars, kChars + 7, cap * cap}) {
- CordRepBtreeReader reader;
- absl::string_view chunk = reader.Init(node);
-
- // `consumed` tracks the end of last consumed chunk which is the start of
- // the next chunk: we always read with `chunk_size = chunk.length()`.
- size_t consumed = 0;
- size_t remaining = data.length();
- while (remaining > 0) {
- CordRep* tree;
- size_t n = (std::min)(remaining, read_size);
- chunk = reader.Read(n, chunk.length(), tree);
- EXPECT_THAT(tree, Ne(nullptr));
- if (tree) {
- EXPECT_THAT(CordToString(tree), Eq(data.substr(consumed, n)));
- CordRep::Unref(tree);
- }
-
- consumed += n;
- remaining -= n;
- EXPECT_THAT(reader.remaining(), Eq(remaining - chunk.length()));
-
- if (remaining > 0) {
- ASSERT_FALSE(chunk.empty());
- ASSERT_THAT(chunk, Eq(data.substr(consumed, chunk.length())));
- } else {
- ASSERT_TRUE(chunk.empty()) << chunk;
- }
- }
- }
-
- CordRep::Unref(node);
- }
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc
deleted file mode 100644
index be9473d41d..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_btree_test.cc
+++ /dev/null
@@ -1,1489 +0,0 @@
-// 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/strings/internal/cord_rep_btree.h"
-
-#include <cmath>
-#include <deque>
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/cleanup/cleanup.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_test_util.h"
-#include "absl/strings/str_cat.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-class CordRepBtreeTestPeer {
- public:
- static void SetEdge(CordRepBtree* node, size_t idx, CordRep* edge) {
- node->edges_[idx] = edge;
- }
- static void AddEdge(CordRepBtree* node, CordRep* edge) {
- node->edges_[node->fetch_add_end(1)] = edge;
- }
-};
-
-namespace {
-
-using ::absl::cordrep_testing::AutoUnref;
-using ::absl::cordrep_testing::CordCollectRepsIf;
-using ::absl::cordrep_testing::CordToString;
-using ::absl::cordrep_testing::CordVisitReps;
-using ::absl::cordrep_testing::CreateFlatsFromString;
-using ::absl::cordrep_testing::CreateRandomString;
-using ::absl::cordrep_testing::MakeConcat;
-using ::absl::cordrep_testing::MakeExternal;
-using ::absl::cordrep_testing::MakeFlat;
-using ::absl::cordrep_testing::MakeSubstring;
-using ::testing::_;
-using ::testing::AllOf;
-using ::testing::AnyOf;
-using ::testing::Conditional;
-using ::testing::ElementsAre;
-using ::testing::ElementsAreArray;
-using ::testing::Eq;
-using ::testing::HasSubstr;
-using ::testing::Le;
-using ::testing::Ne;
-using ::testing::Not;
-using ::testing::SizeIs;
-using ::testing::TypedEq;
-
-MATCHER_P(EqFlatHolding, data, "Equals flat holding data") {
- if (arg->tag < FLAT) {
- *result_listener << "Expected FLAT, got tag " << static_cast<int>(arg->tag);
- return false;
- }
- std::string actual = CordToString(arg);
- if (actual != data) {
- *result_listener << "Expected flat holding \"" << data
- << "\", got flat holding \"" << actual << "\"";
- return false;
- }
- return true;
-}
-
-MATCHER_P(IsNode, height, absl::StrCat("Is a valid node of height ", height)) {
- if (arg == nullptr) {
- *result_listener << "Expected NODE, got nullptr";
- return false;
- }
- if (arg->tag != BTREE) {
- *result_listener << "Expected NODE, got " << static_cast<int>(arg->tag);
- return false;
- }
- if (!CordRepBtree::IsValid(arg->btree())) {
- CordRepBtree::Dump(arg->btree(), "Expected valid NODE, got:", false,
- *result_listener->stream());
- return false;
- }
- if (arg->btree()->height() != height) {
- *result_listener << "Expected NODE of height " << height << ", got "
- << arg->btree()->height();
- return false;
- }
- return true;
-}
-
-MATCHER_P2(IsSubstring, start, length,
- absl::StrCat("Is a substring(start = ", start, ", length = ", length,
- ")")) {
- if (arg == nullptr) {
- *result_listener << "Expected substring, got nullptr";
- return false;
- }
- if (arg->tag != SUBSTRING) {
- *result_listener << "Expected SUBSTRING, got "
- << static_cast<int>(arg->tag);
- return false;
- }
- const CordRepSubstring* const substr = arg->substring();
- if (substr->start != start || substr->length != length) {
- *result_listener << "Expected substring(" << start << ", " << length
- << "), got substring(" << substr->start << ", "
- << substr->length << ")";
- return false;
- }
- return true;
-}
-
-// DataConsumer is a simple helper class used by tests to 'consume' string
-// fragments from the provided input in forward or backward direction.
-class DataConsumer {
- public:
- // Starts consumption of `data`. Caller must make sure `data` outlives this
- // instance. Consumes data starting at the front if `forward` is true, else
- // consumes data from the back.
- DataConsumer(absl::string_view data, bool forward)
- : data_(data), forward_(forward) {}
-
- // Return the next `n` bytes from referenced data.
- absl::string_view Next(size_t n) {
- assert(n <= data_.size() - consumed_);
- consumed_ += n;
- return data_.substr(forward_ ? consumed_ - n : data_.size() - consumed_, n);
- }
-
- // Returns all data consumed so far.
- absl::string_view Consumed() const {
- return forward_ ? data_.substr(0, consumed_)
- : data_.substr(data_.size() - consumed_);
- }
-
- private:
- absl::string_view data_;
- size_t consumed_ = 0;
- bool forward_;
-};
-
-// BtreeAdd returns either CordRepBtree::Append or CordRepBtree::Prepend.
-CordRepBtree* BtreeAdd(CordRepBtree* node, bool append,
- absl::string_view data) {
- return append ? CordRepBtree::Append(node, data)
- : CordRepBtree::Prepend(node, data);
-}
-
-// Recursively collects all leaf edges from `tree` and appends them to `edges`.
-void GetLeafEdges(const CordRepBtree* tree, std::vector<CordRep*>& edges) {
- if (tree->height() == 0) {
- for (CordRep* edge : tree->Edges()) {
- edges.push_back(edge);
- }
- } else {
- for (CordRep* edge : tree->Edges()) {
- GetLeafEdges(edge->btree(), edges);
- }
- }
-}
-
-// Recursively collects and returns all leaf edges from `tree`.
-std::vector<CordRep*> GetLeafEdges(const CordRepBtree* tree) {
- std::vector<CordRep*> edges;
- GetLeafEdges(tree, edges);
- return edges;
-}
-
-// Creates a flat containing the hexadecimal value of `i` zero padded
-// to at least 4 digits prefixed with "0x", e.g.: "0x04AC".
-CordRepFlat* MakeHexFlat(size_t i) {
- return MakeFlat(absl::StrCat("0x", absl::Hex(i, absl::kZeroPad4)));
-}
-
-CordRepBtree* MakeLeaf(size_t size = CordRepBtree::kMaxCapacity) {
- assert(size <= CordRepBtree::kMaxCapacity);
- CordRepBtree* leaf = CordRepBtree::Create(MakeHexFlat(0));
- for (size_t i = 1; i < size; ++i) {
- leaf = CordRepBtree::Append(leaf, MakeHexFlat(i));
- }
- return leaf;
-}
-
-CordRepBtree* MakeTree(size_t size, bool append = true) {
- CordRepBtree* tree = CordRepBtree::Create(MakeHexFlat(0));
- for (size_t i = 1; i < size; ++i) {
- tree = append ? CordRepBtree::Append(tree, MakeHexFlat(i))
- : CordRepBtree::Prepend(tree, MakeHexFlat(i));
- }
- return tree;
-}
-
-CordRepBtree* CreateTree(absl::Span<CordRep* const> reps) {
- auto it = reps.begin();
- CordRepBtree* tree = CordRepBtree::Create(*it);
- while (++it != reps.end()) tree = CordRepBtree::Append(tree, *it);
- return tree;
-}
-
-CordRepBtree* CreateTree(absl::string_view data, size_t chunk_size) {
- return CreateTree(CreateFlatsFromString(data, chunk_size));
-}
-
-CordRepBtree* CreateTreeReverse(absl::string_view data, size_t chunk_size) {
- std::vector<CordRep*> flats = CreateFlatsFromString(data, chunk_size);
- auto rit = flats.rbegin();
- CordRepBtree* tree = CordRepBtree::Create(*rit);
- while (++rit != flats.rend()) tree = CordRepBtree::Prepend(tree, *rit);
- return tree;
-}
-
-class CordRepBtreeTest : public testing::TestWithParam<bool> {
- public:
- bool shared() const { return GetParam(); }
-
- static std::string ToString(testing::TestParamInfo<bool> param) {
- return param.param ? "Shared" : "Private";
- }
-};
-
-INSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeTest, testing::Bool(),
- CordRepBtreeTest::ToString);
-
-class CordRepBtreeHeightTest : public testing::TestWithParam<int> {
- public:
- int height() const { return GetParam(); }
-
- static std::string ToString(testing::TestParamInfo<int> param) {
- return absl::StrCat(param.param);
- }
-};
-
-INSTANTIATE_TEST_SUITE_P(WithHeights, CordRepBtreeHeightTest,
- testing::Range(0, CordRepBtree::kMaxHeight),
- CordRepBtreeHeightTest::ToString);
-
-using TwoBools = testing::tuple<bool, bool>;
-
-class CordRepBtreeDualTest : public testing::TestWithParam<TwoBools> {
- public:
- bool first_shared() const { return std::get<0>(GetParam()); }
- bool second_shared() const { return std::get<1>(GetParam()); }
-
- static std::string ToString(testing::TestParamInfo<TwoBools> param) {
- if (std::get<0>(param.param)) {
- return std::get<1>(param.param) ? "BothShared" : "FirstShared";
- }
- return std::get<1>(param.param) ? "SecondShared" : "Private";
- }
-};
-
-INSTANTIATE_TEST_SUITE_P(WithParam, CordRepBtreeDualTest,
- testing::Combine(testing::Bool(), testing::Bool()),
- CordRepBtreeDualTest::ToString);
-
-TEST(CordRepBtreeTest, SizeIsMultipleOf64) {
- // Only enforce for fully 64-bit platforms.
- if (sizeof(size_t) == 8 && sizeof(void*) == 8) {
- EXPECT_THAT(sizeof(CordRepBtree) % 64, Eq(0)) << "Should be multiple of 64";
- }
-}
-
-TEST(CordRepBtreeTest, NewDestroyEmptyTree) {
- auto* tree = CordRepBtree::New();
- EXPECT_THAT(tree->size(), Eq(0));
- EXPECT_THAT(tree->height(), Eq(0));
- EXPECT_THAT(tree->Edges(), ElementsAre());
- CordRepBtree::Destroy(tree);
-}
-
-TEST(CordRepBtreeTest, NewDestroyEmptyTreeAtHeight) {
- auto* tree = CordRepBtree::New(3);
- EXPECT_THAT(tree->size(), Eq(0));
- EXPECT_THAT(tree->height(), Eq(3));
- EXPECT_THAT(tree->Edges(), ElementsAre());
- CordRepBtree::Destroy(tree);
-}
-
-TEST(CordRepBtreeTest, Btree) {
- CordRep* rep = CordRepBtree::New();
- EXPECT_THAT(rep->btree(), Eq(rep));
- EXPECT_THAT(static_cast<const CordRep*>(rep)->btree(), Eq(rep));
- CordRep::Unref(rep);
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
- rep = MakeFlat("Hello world");
- EXPECT_DEATH(rep->btree(), ".*");
- EXPECT_DEATH(static_cast<const CordRep*>(rep)->btree(), ".*");
- CordRep::Unref(rep);
-#endif
-}
-
-TEST(CordRepBtreeTest, EdgeData) {
- CordRepFlat* flat = MakeFlat("Hello world");
- CordRepExternal* external = MakeExternal("Hello external");
- CordRep* substr1 = MakeSubstring(1, 6, CordRep::Ref(flat));
- CordRep* substr2 = MakeSubstring(1, 6, CordRep::Ref(external));
- CordRep* concat = MakeConcat(CordRep::Ref(flat), CordRep::Ref(external));
- CordRep* bad_substr = MakeSubstring(1, 2, CordRep::Ref(substr1));
-
- EXPECT_TRUE(CordRepBtree::IsDataEdge(flat));
- EXPECT_THAT(CordRepBtree::EdgeDataPtr(flat),
- TypedEq<const void*>(flat->Data()));
- EXPECT_THAT(CordRepBtree::EdgeData(flat), Eq("Hello world"));
-
- EXPECT_TRUE(CordRepBtree::IsDataEdge(external));
- EXPECT_THAT(CordRepBtree::EdgeDataPtr(external),
- TypedEq<const void*>(external->base));
- EXPECT_THAT(CordRepBtree::EdgeData(external), Eq("Hello external"));
-
- EXPECT_TRUE(CordRepBtree::IsDataEdge(substr1));
- EXPECT_THAT(CordRepBtree::EdgeDataPtr(substr1),
- TypedEq<const void*>(flat->Data() + 1));
- EXPECT_THAT(CordRepBtree::EdgeData(substr1), Eq("ello w"));
-
- EXPECT_TRUE(CordRepBtree::IsDataEdge(substr2));
- EXPECT_THAT(CordRepBtree::EdgeDataPtr(substr2),
- TypedEq<const void*>(external->base + 1));
- EXPECT_THAT(CordRepBtree::EdgeData(substr2), Eq("ello e"));
-
- EXPECT_FALSE(CordRepBtree::IsDataEdge(concat));
- EXPECT_FALSE(CordRepBtree::IsDataEdge(bad_substr));
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
- EXPECT_DEATH(CordRepBtree::EdgeData(concat), ".*");
- EXPECT_DEATH(CordRepBtree::EdgeDataPtr(concat), ".*");
- EXPECT_DEATH(CordRepBtree::EdgeData(bad_substr), ".*");
- EXPECT_DEATH(CordRepBtree::EdgeDataPtr(bad_substr), ".*");
-#endif
-
- CordRep::Unref(bad_substr);
- CordRep::Unref(concat);
- CordRep::Unref(substr2);
- CordRep::Unref(substr1);
- CordRep::Unref(external);
- CordRep::Unref(flat);
-}
-
-TEST(CordRepBtreeTest, CreateUnrefLeaf) {
- auto* flat = MakeFlat("a");
- auto* leaf = CordRepBtree::Create(flat);
- EXPECT_THAT(leaf->size(), Eq(1));
- EXPECT_THAT(leaf->height(), Eq(0));
- EXPECT_THAT(leaf->Edges(), ElementsAre(flat));
- CordRepBtree::Unref(leaf);
-}
-
-TEST(CordRepBtreeTest, NewUnrefNode) {
- auto* leaf = CordRepBtree::Create(MakeFlat("a"));
- CordRepBtree* tree = CordRepBtree::New(leaf);
- EXPECT_THAT(tree->size(), Eq(1));
- EXPECT_THAT(tree->height(), Eq(1));
- EXPECT_THAT(tree->Edges(), ElementsAre(leaf));
- CordRepBtree::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, AppendToLeafToCapacity) {
- AutoUnref refs;
- std::vector<CordRep*> flats;
- flats.push_back(MakeHexFlat(0));
- auto* leaf = CordRepBtree::Create(flats.back());
-
- for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
- refs.RefIf(shared(), leaf);
- flats.push_back(MakeHexFlat(i));
- auto* result = CordRepBtree::Append(leaf, flats.back());
- EXPECT_THAT(result->height(), Eq(0));
- EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
- EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
- leaf = result;
- }
- CordRep::Unref(leaf);
-}
-
-TEST_P(CordRepBtreeTest, PrependToLeafToCapacity) {
- AutoUnref refs;
- std::deque<CordRep*> flats;
- flats.push_front(MakeHexFlat(0));
- auto* leaf = CordRepBtree::Create(flats.front());
-
- for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
- refs.RefIf(shared(), leaf);
- flats.push_front(MakeHexFlat(i));
- auto* result = CordRepBtree::Prepend(leaf, flats.front());
- EXPECT_THAT(result->height(), Eq(0));
- EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
- EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
- leaf = result;
- }
- CordRep::Unref(leaf);
-}
-
-// This test specifically aims at code aligning data at either the front or the
-// back of the contained `edges[]` array, alternating Append and Prepend will
-// move `begin()` and `end()` values as needed for each added value.
-TEST_P(CordRepBtreeTest, AppendPrependToLeafToCapacity) {
- AutoUnref refs;
- std::deque<CordRep*> flats;
- flats.push_front(MakeHexFlat(0));
- auto* leaf = CordRepBtree::Create(flats.front());
-
- for (size_t i = 1; i < CordRepBtree::kMaxCapacity; ++i) {
- refs.RefIf(shared(), leaf);
- CordRepBtree* result;
- if (i % 2 != 0) {
- flats.push_front(MakeHexFlat(i));
- result = CordRepBtree::Prepend(leaf, flats.front());
- } else {
- flats.push_back(MakeHexFlat(i));
- result = CordRepBtree::Append(leaf, flats.back());
- }
- EXPECT_THAT(result->height(), Eq(0));
- EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
- EXPECT_THAT(result->Edges(), ElementsAreArray(flats));
- leaf = result;
- }
- CordRep::Unref(leaf);
-}
-
-TEST_P(CordRepBtreeTest, AppendToLeafBeyondCapacity) {
- AutoUnref refs;
- auto* leaf = MakeLeaf();
- refs.RefIf(shared(), leaf);
- CordRep* flat = MakeFlat("abc");
- auto* result = CordRepBtree::Append(leaf, flat);
- ASSERT_THAT(result, IsNode(1));
- EXPECT_THAT(result, Ne(leaf));
- absl::Span<CordRep* const> edges = result->Edges();
- ASSERT_THAT(edges, ElementsAre(leaf, IsNode(0)));
- EXPECT_THAT(edges[1]->btree()->Edges(), ElementsAre(flat));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeTest, PrependToLeafBeyondCapacity) {
- AutoUnref refs;
- auto* leaf = MakeLeaf();
- refs.RefIf(shared(), leaf);
- CordRep* flat = MakeFlat("abc");
- auto* result = CordRepBtree::Prepend(leaf, flat);
- ASSERT_THAT(result, IsNode(1));
- EXPECT_THAT(result, Ne(leaf));
- absl::Span<CordRep* const> edges = result->Edges();
- ASSERT_THAT(edges, ElementsAre(IsNode(0), leaf));
- EXPECT_THAT(edges[0]->btree()->Edges(), ElementsAre(flat));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeTest, AppendToTreeOneDeep) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- AutoUnref refs;
- std::vector<CordRep*> flats;
- flats.push_back(MakeHexFlat(0));
- CordRepBtree* tree = CordRepBtree::Create(flats.back());
- for (size_t i = 1; i <= max_cap; ++i) {
- flats.push_back(MakeHexFlat(i));
- tree = CordRepBtree::Append(tree, flats.back());
- }
- ASSERT_THAT(tree, IsNode(1));
-
- for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
- // Ref top level tree based on param.
- // Ref leaf node once every 4 iterations, which should not have an
- // observable effect other than that the leaf itself is copied.
- refs.RefIf(shared(), tree);
- refs.RefIf(i % 4 == 0, tree->Edges().back());
-
- flats.push_back(MakeHexFlat(i));
- CordRepBtree* result = CordRepBtree::Append(tree, flats.back());
- ASSERT_THAT(result, IsNode(1));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- std::vector<CordRep*> edges = GetLeafEdges(result);
- ASSERT_THAT(edges, ElementsAreArray(flats));
- tree = result;
- }
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, AppendToTreeTwoDeep) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- AutoUnref refs;
- std::vector<CordRep*> flats;
- flats.push_back(MakeHexFlat(0));
- CordRepBtree* tree = CordRepBtree::Create(flats.back());
- for (size_t i = 1; i <= max_cap * max_cap; ++i) {
- flats.push_back(MakeHexFlat(i));
- tree = CordRepBtree::Append(tree, flats.back());
- }
- ASSERT_THAT(tree, IsNode(2));
- for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {
- // Ref top level tree based on param.
- // Ref child node once every 16 iterations, and leaf node every 4
- // iterrations which which should not have an observable effect other than
- // the node and/or the leaf below it being copied.
- refs.RefIf(shared(), tree);
- refs.RefIf(i % 16 == 0, tree->Edges().back());
- refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());
-
- flats.push_back(MakeHexFlat(i));
- CordRepBtree* result = CordRepBtree::Append(tree, flats.back());
- ASSERT_THAT(result, IsNode(2));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- std::vector<CordRep*> edges = GetLeafEdges(result);
- ASSERT_THAT(edges, ElementsAreArray(flats));
- tree = result;
- }
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, PrependToTreeOneDeep) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- AutoUnref refs;
- std::deque<CordRep*> flats;
- flats.push_back(MakeHexFlat(0));
- CordRepBtree* tree = CordRepBtree::Create(flats.back());
- for (size_t i = 1; i <= max_cap; ++i) {
- flats.push_front(MakeHexFlat(i));
- tree = CordRepBtree::Prepend(tree, flats.front());
- }
- ASSERT_THAT(tree, IsNode(1));
-
- for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
- // Ref top level tree based on param.
- // Ref leaf node once every 4 iterations which should not have an observable
- // effect other than than the leaf itself is copied.
- refs.RefIf(shared(), tree);
- refs.RefIf(i % 4 == 0, tree->Edges().back());
-
- flats.push_front(MakeHexFlat(i));
- CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());
- ASSERT_THAT(result, IsNode(1));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- std::vector<CordRep*> edges = GetLeafEdges(result);
- ASSERT_THAT(edges, ElementsAreArray(flats));
- tree = result;
- }
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, PrependToTreeTwoDeep) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- AutoUnref refs;
- std::deque<CordRep*> flats;
- flats.push_back(MakeHexFlat(0));
- CordRepBtree* tree = CordRepBtree::Create(flats.back());
- for (size_t i = 1; i <= max_cap * max_cap; ++i) {
- flats.push_front(MakeHexFlat(i));
- tree = CordRepBtree::Prepend(tree, flats.front());
- }
- ASSERT_THAT(tree, IsNode(2));
- for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap; ++i) {
- // Ref top level tree based on param.
- // Ref child node once every 16 iterations, and leaf node every 4
- // iterrations which which should not have an observable effect other than
- // the node and/or the leaf below it being copied.
- refs.RefIf(shared(), tree);
- refs.RefIf(i % 16 == 0, tree->Edges().back());
- refs.RefIf(i % 4 == 0, tree->Edges().back()->btree()->Edges().back());
-
- flats.push_front(MakeHexFlat(i));
- CordRepBtree* result = CordRepBtree::Prepend(tree, flats.front());
- ASSERT_THAT(result, IsNode(2));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- std::vector<CordRep*> edges = GetLeafEdges(result);
- ASSERT_THAT(edges, ElementsAreArray(flats));
- tree = result;
- }
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeDualTest, MergeLeafsNotExceedingCapacity) {
- for (bool use_append : {false, true}) {
- SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
-
- AutoUnref refs;
- std::vector<CordRep*> flats;
-
- // Build `left` side leaf appending all contained flats to `flats`
- CordRepBtree* left = MakeLeaf(3);
- GetLeafEdges(left, flats);
- refs.RefIf(first_shared(), left);
-
- // Build `right` side leaf appending all contained flats to `flats`
- CordRepBtree* right = MakeLeaf(2);
- GetLeafEdges(right, flats);
- refs.RefIf(second_shared(), right);
-
- CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
- : CordRepBtree::Prepend(right, left);
- EXPECT_THAT(tree, IsNode(0));
-
- // `tree` contains all flats originally belonging to `left` and `right`.
- EXPECT_THAT(tree->Edges(), ElementsAreArray(flats));
- CordRepBtree::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeDualTest, MergeLeafsExceedingCapacity) {
- for (bool use_append : {false, true}) {
- SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
-
- AutoUnref refs;
-
- // Build `left` side tree appending all contained flats to `flats`
- CordRepBtree* left = MakeLeaf(CordRepBtree::kMaxCapacity - 2);
- refs.RefIf(first_shared(), left);
-
- // Build `right` side tree appending all contained flats to `flats`
- CordRepBtree* right = MakeLeaf(CordRepBtree::kMaxCapacity - 1);
- refs.RefIf(second_shared(), right);
-
- CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
- : CordRepBtree::Prepend(right, left);
- EXPECT_THAT(tree, IsNode(1));
- EXPECT_THAT(tree->Edges(), ElementsAre(left, right));
- CordRepBtree::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeDualTest, MergeEqualHeightTrees) {
- for (bool use_append : {false, true}) {
- SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
-
- AutoUnref refs;
- std::vector<CordRep*> flats;
-
- // Build `left` side tree appending all contained flats to `flats`
- CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3);
- GetLeafEdges(left, flats);
- refs.RefIf(first_shared(), left);
-
- // Build `right` side tree appending all contained flats to `flats`
- CordRepBtree* right = MakeTree(CordRepBtree::kMaxCapacity * 2);
- GetLeafEdges(right, flats);
- refs.RefIf(second_shared(), right);
-
- CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
- : CordRepBtree::Prepend(right, left);
- EXPECT_THAT(tree, IsNode(1));
- EXPECT_THAT(tree->Edges(), SizeIs(5));
-
- // `tree` contains all flats originally belonging to `left` and `right`.
- EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
- CordRepBtree::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeDualTest, MergeLeafWithTreeNotExceedingLeafCapacity) {
- for (bool use_append : {false, true}) {
- SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
-
- AutoUnref refs;
- std::vector<CordRep*> flats;
-
- // Build `left` side tree appending all added flats to `flats`
- CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 2 + 2);
- GetLeafEdges(left, flats);
- refs.RefIf(first_shared(), left);
-
- // Build `right` side tree appending all added flats to `flats`
- CordRepBtree* right = MakeTree(3);
- GetLeafEdges(right, flats);
- refs.RefIf(second_shared(), right);
-
- CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
- : CordRepBtree::Prepend(right, left);
- EXPECT_THAT(tree, IsNode(1));
- EXPECT_THAT(tree->Edges(), SizeIs(3));
-
- // `tree` contains all flats originally belonging to `left` and `right`.
- EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
- CordRepBtree::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeDualTest, MergeLeafWithTreeExceedingLeafCapacity) {
- for (bool use_append : {false, true}) {
- SCOPED_TRACE(use_append ? "Using Append" : "Using Prepend");
-
- AutoUnref refs;
- std::vector<CordRep*> flats;
-
- // Build `left` side tree appending all added flats to `flats`
- CordRepBtree* left = MakeTree(CordRepBtree::kMaxCapacity * 3 - 2);
- GetLeafEdges(left, flats);
- refs.RefIf(first_shared(), left);
-
- // Build `right` side tree appending all added flats to `flats`
- CordRepBtree* right = MakeTree(3);
- GetLeafEdges(right, flats);
- refs.RefIf(second_shared(), right);
-
- CordRepBtree* tree = use_append ? CordRepBtree::Append(left, right)
- : CordRepBtree::Prepend(right, left);
- EXPECT_THAT(tree, IsNode(1));
- EXPECT_THAT(tree->Edges(), SizeIs(4));
-
- // `tree` contains all flats originally belonging to `left` and `right`.
- EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
- CordRepBtree::Unref(tree);
- }
-}
-
-void RefEdgesAt(size_t depth, AutoUnref& refs, CordRepBtree* tree) {
- absl::Span<CordRep* const> edges = tree->Edges();
- if (depth == 0) {
- refs.Ref(edges.front());
- refs.Ref(edges.back());
- } else {
- assert(tree->height() > 0);
- RefEdgesAt(depth - 1, refs, edges.front()->btree());
- RefEdgesAt(depth - 1, refs, edges.back()->btree());
- }
-}
-
-TEST(CordRepBtreeTest, MergeFuzzTest) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- std::minstd_rand rnd;
- std::uniform_int_distribution<int> coin_flip(0, 1);
- std::uniform_int_distribution<int> dice_throw(1, 6);
-
- auto random_leaf_count = [&]() {
- std::uniform_int_distribution<int> dist_height(0, 3);
- std::uniform_int_distribution<int> dist_leaf(0, max_cap - 1);
- const size_t height = dist_height(rnd);
- return (height ? pow(max_cap, height) : 0) + dist_leaf(rnd);
- };
-
- for (int i = 0; i < 10000; ++i) {
- AutoUnref refs;
- std::vector<CordRep*> flats;
-
- CordRepBtree* left = MakeTree(random_leaf_count(), coin_flip(rnd));
- GetLeafEdges(left, flats);
- if (dice_throw(rnd) == 1) {
- std::uniform_int_distribution<int> dist(0, left->height());
- RefEdgesAt(dist(rnd), refs, left);
- }
-
- CordRepBtree* right = MakeTree(random_leaf_count(), coin_flip(rnd));
- GetLeafEdges(right, flats);
- if (dice_throw(rnd) == 1) {
- std::uniform_int_distribution<int> dist(0, right->height());
- RefEdgesAt(dist(rnd), refs, right);
- }
-
- CordRepBtree* tree = CordRepBtree::Append(left, right);
- EXPECT_THAT(GetLeafEdges(tree), ElementsAreArray(flats));
- CordRepBtree::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeTest, RemoveSuffix) {
- // Create tree of 1, 2 and 3 levels high
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- for (size_t cap : {max_cap - 1, max_cap * 2, max_cap * max_cap * 2}) {
- const std::string data = CreateRandomString(cap * 512);
-
- {
- // Verify RemoveSuffix(<all>)
- AutoUnref refs;
- CordRepBtree* node = refs.RefIf(shared(), CreateTree(data, 512));
- EXPECT_THAT(CordRepBtree::RemoveSuffix(node, data.length()), Eq(nullptr));
-
- // Verify RemoveSuffix(<none>)
- node = refs.RefIf(shared(), CreateTree(data, 512));
- EXPECT_THAT(CordRepBtree::RemoveSuffix(node, 0), Eq(node));
- CordRep::Unref(node);
- }
-
- for (int n = 1; n < data.length(); ++n) {
- AutoUnref refs;
- auto flats = CreateFlatsFromString(data, 512);
- CordRepBtree* node = refs.RefIf(shared(), CreateTree(flats));
- CordRep* rep = refs.Add(CordRepBtree::RemoveSuffix(node, n));
- EXPECT_THAT(CordToString(rep), Eq(data.substr(0, data.length() - n)));
-
- // Collect all flats
- auto is_flat = [](CordRep* rep) { return rep->tag >= FLAT; };
- std::vector<CordRep*> edges = CordCollectRepsIf(is_flat, rep);
- ASSERT_THAT(edges.size(), Le(flats.size()));
-
- // Isolate last edge
- CordRep* last_edge = edges.back();
- edges.pop_back();
- const size_t last_length = rep->length - edges.size() * 512;
-
- // All flats except the last edge must be kept or copied 'as is'
- int index = 0;
- for (CordRep* edge : edges) {
- ASSERT_THAT(edge, Eq(flats[index++]));
- ASSERT_THAT(edge->length, Eq(512));
- }
-
- // CordRepBtree may optimize small substrings to avoid waste, so only
- // check for flat sharing / updates where the code should always do this.
- if (last_length >= 500) {
- EXPECT_THAT(last_edge, Eq(flats[index++]));
- if (shared()) {
- EXPECT_THAT(last_edge->length, Eq(512));
- } else {
- EXPECT_TRUE(last_edge->refcount.IsOne());
- EXPECT_THAT(last_edge->length, Eq(last_length));
- }
- }
- }
- }
-}
-
-TEST(CordRepBtreeTest, SubTree) {
- // Create tree of at least 2 levels high
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- const size_t n = max_cap * max_cap * 2;
- const std::string data = CreateRandomString(n * 3);
- std::vector<CordRep*> flats;
- for (absl::string_view s = data; !s.empty(); s.remove_prefix(3)) {
- flats.push_back(MakeFlat(s.substr(0, 3)));
- }
- CordRepBtree* node = CordRepBtree::Create(CordRep::Ref(flats[0]));
- for (size_t i = 1; i < flats.size(); ++i) {
- node = CordRepBtree::Append(node, CordRep::Ref(flats[i]));
- }
-
- for (int offset = 0; offset < data.length(); ++offset) {
- for (int length = 1; length <= data.length() - offset; ++length) {
- CordRep* rep = node->SubTree(offset, length);
- EXPECT_THAT(CordToString(rep), Eq(data.substr(offset, length)));
- CordRep::Unref(rep);
- }
- }
- CordRepBtree::Unref(node);
- for (CordRep* rep : flats) {
- CordRep::Unref(rep);
- }
-}
-
-TEST(CordRepBtreeTest, SubTreeOnExistingSubstring) {
- // This test verifies that a SubTree call on a pre-existing (large) substring
- // adjusts the existing substring if not shared, and else rewrites the
- // existing substring.
- AutoUnref refs;
- std::string data = CreateRandomString(1000);
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
- CordRep* flat = MakeFlat(data);
- leaf = CordRepBtree::Append(leaf, flat);
-
- // Setup tree containing substring.
- CordRep* result = leaf->SubTree(0, 3 + 990);
- ASSERT_THAT(result->tag, Eq(BTREE));
- CordRep::Unref(leaf);
- leaf = result->btree();
- ASSERT_THAT(leaf->Edges(), ElementsAre(_, IsSubstring(0, 990)));
- EXPECT_THAT(leaf->Edges()[1]->substring()->child, Eq(flat));
-
- // Verify substring of substring.
- result = leaf->SubTree(3 + 5, 970);
- ASSERT_THAT(result, IsSubstring(5, 970));
- EXPECT_THAT(result->substring()->child, Eq(flat));
- CordRep::Unref(result);
-
- CordRep::Unref(leaf);
-}
-
-TEST_P(CordRepBtreeTest, AddDataToLeaf) {
- const size_t n = CordRepBtree::kMaxCapacity;
- const std::string data = CreateRandomString(n * 3);
-
- for (bool append : {true, false}) {
- AutoUnref refs;
- DataConsumer consumer(data, append);
- SCOPED_TRACE(append ? "Append" : "Prepend");
-
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat(consumer.Next(3)));
- for (size_t i = 1; i < n; ++i) {
- refs.RefIf(shared(), leaf);
- CordRepBtree* result = BtreeAdd(leaf, append, consumer.Next(3));
- EXPECT_THAT(result, Conditional(shared(), Ne(leaf), Eq(leaf)));
- EXPECT_THAT(CordToString(result), Eq(consumer.Consumed()));
- leaf = result;
- }
- CordRep::Unref(leaf);
- }
-}
-
-TEST_P(CordRepBtreeTest, AppendDataToTree) {
- AutoUnref refs;
- size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;
- std::string data = CreateRandomString(n * 3);
- CordRepBtree* tree = refs.RefIf(shared(), CreateTree(data, 3));
- CordRepBtree* leaf0 = tree->Edges()[0]->btree();
- CordRepBtree* leaf1 = tree->Edges()[1]->btree();
- CordRepBtree* result = CordRepBtree::Append(tree, "123456789");
- EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- EXPECT_THAT(result->Edges(),
- ElementsAre(leaf0, Conditional(shared(), Ne(leaf1), Eq(leaf1))));
- EXPECT_THAT(CordToString(result), Eq(data + "123456789"));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeTest, PrependDataToTree) {
- AutoUnref refs;
- size_t n = CordRepBtree::kMaxCapacity + CordRepBtree::kMaxCapacity / 2;
- std::string data = CreateRandomString(n * 3);
- CordRepBtree* tree = refs.RefIf(shared(), CreateTreeReverse(data, 3));
- CordRepBtree* leaf0 = tree->Edges()[0]->btree();
- CordRepBtree* leaf1 = tree->Edges()[1]->btree();
- CordRepBtree* result = CordRepBtree::Prepend(tree, "123456789");
- EXPECT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- EXPECT_THAT(result->Edges(),
- ElementsAre(Conditional(shared(), Ne(leaf0), Eq(leaf0)), leaf1));
- EXPECT_THAT(CordToString(result), Eq("123456789" + data));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeTest, AddDataToTreeThreeLevelsDeep) {
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- const size_t n = max_cap * max_cap * max_cap;
- const std::string data = CreateRandomString(n * 3);
-
- for (bool append : {true, false}) {
- AutoUnref refs;
- DataConsumer consumer(data, append);
- SCOPED_TRACE(append ? "Append" : "Prepend");
-
- // Fill leaf
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat(consumer.Next(3)));
- for (size_t i = 1; i < max_cap; ++i) {
- tree = BtreeAdd(tree, append, consumer.Next(3));
- }
- ASSERT_THAT(CordToString(tree), Eq(consumer.Consumed()));
-
- // Fill to maximum at one deep
- refs.RefIf(shared(), tree);
- CordRepBtree* result = BtreeAdd(tree, append, consumer.Next(3));
- ASSERT_THAT(result, IsNode(1));
- ASSERT_THAT(result, Ne(tree));
- ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
- tree = result;
- for (size_t i = max_cap + 1; i < max_cap * max_cap; ++i) {
- refs.RefIf(shared(), tree);
- result = BtreeAdd(tree, append, consumer.Next(3));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
- tree = result;
- }
-
- // Fill to maximum at two deep
- refs.RefIf(shared(), tree);
- result = BtreeAdd(tree, append, consumer.Next(3));
- ASSERT_THAT(result, IsNode(2));
- ASSERT_THAT(result, Ne(tree));
- ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
- tree = result;
- for (size_t i = max_cap * max_cap + 1; i < max_cap * max_cap * max_cap;
- ++i) {
- refs.RefIf(shared(), tree);
- result = BtreeAdd(tree, append, consumer.Next(3));
- ASSERT_THAT(result, Conditional(shared(), Ne(tree), Eq(tree)));
- ASSERT_THAT(CordToString(result), Eq(consumer.Consumed()));
- tree = result;
- }
-
- CordRep::Unref(tree);
- }
-}
-
-TEST_P(CordRepBtreeTest, AddLargeDataToLeaf) {
- const size_t max_cap = CordRepBtree::kMaxCapacity;
- const size_t n = max_cap * max_cap * max_cap * 3 + 2;
- const std::string data = CreateRandomString(n * kMaxFlatLength);
-
- for (bool append : {true, false}) {
- AutoUnref refs;
- SCOPED_TRACE(append ? "Append" : "Prepend");
-
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
- refs.RefIf(shared(), leaf);
- CordRepBtree* result = BtreeAdd(leaf, append, data);
- EXPECT_THAT(CordToString(result), Eq(append ? "abc" + data : data + "abc"));
- CordRep::Unref(result);
- }
-}
-
-TEST_P(CordRepBtreeDualTest, CreateFromConcat) {
- AutoUnref refs;
- CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
- MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
- auto* left = MakeConcat(flats[0], flats[1]);
- auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
- auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
- CordRepBtree* result = CordRepBtree::Create(concat);
- ASSERT_TRUE(CordRepBtree::IsValid(result));
- EXPECT_THAT(result->length, Eq(26));
- EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeDualTest, AppendConcat) {
- AutoUnref refs;
- CordRep* flats[] = {MakeFlat("defgh"), MakeFlat("ijklm"),
- MakeFlat("nopqrstuv"), MakeFlat("wxyz")};
- auto* left = MakeConcat(flats[0], flats[1]);
- auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
- auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
- CordRepBtree* result = CordRepBtree::Create(MakeFlat("abc"));
- result = CordRepBtree::Append(result, concat);
- ASSERT_TRUE(CordRepBtree::IsValid(result));
- EXPECT_THAT(result->length, Eq(26));
- EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeDualTest, PrependConcat) {
- AutoUnref refs;
- CordRep* flats[] = {MakeFlat("abcdefgh"), MakeFlat("ijklm"),
- MakeFlat("nopqrstuv"), MakeFlat("wx")};
- auto* left = MakeConcat(flats[0], flats[1]);
- auto* right = MakeConcat(flats[2], refs.RefIf(first_shared(), flats[3]));
- auto* concat = refs.RefIf(second_shared(), MakeConcat(left, right));
- CordRepBtree* result = CordRepBtree::Create(MakeFlat("yz"));
- result = CordRepBtree::Prepend(result, concat);
- ASSERT_TRUE(CordRepBtree::IsValid(result));
- EXPECT_THAT(result->length, Eq(26));
- EXPECT_THAT(CordToString(result), Eq("abcdefghijklmnopqrstuvwxyz"));
- CordRep::Unref(result);
-}
-
-TEST_P(CordRepBtreeTest, CreateFromTreeReturnsTree) {
- AutoUnref refs;
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world"));
- refs.RefIf(shared(), leaf);
- CordRepBtree* result = CordRepBtree::Create(leaf);
- EXPECT_THAT(result, Eq(leaf));
- CordRep::Unref(result);
-}
-
-TEST(CordRepBtreeTest, GetCharacter) {
- size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;
- std::string data = CreateRandomString(n * 3);
- CordRepBtree* tree = CreateTree(data, 3);
- // Add a substring node for good measure.
- tree = tree->Append(tree, MakeSubstring(4, 5, MakeFlat("abcdefghijklm")));
- data += "efghi";
- for (size_t i = 0; i < data.length(); ++i) {
- ASSERT_THAT(tree->GetCharacter(i), Eq(data[i]));
- }
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, IsFlatSingleFlat) {
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("Hello world"));
-
- absl::string_view fragment;
- EXPECT_TRUE(leaf->IsFlat(nullptr));
- EXPECT_TRUE(leaf->IsFlat(&fragment));
- EXPECT_THAT(fragment, Eq("Hello world"));
- fragment = "";
- EXPECT_TRUE(leaf->IsFlat(0, 11, nullptr));
- EXPECT_TRUE(leaf->IsFlat(0, 11, &fragment));
- EXPECT_THAT(fragment, Eq("Hello world"));
-
- // Arbitrary ranges must check true as well.
- EXPECT_TRUE(leaf->IsFlat(1, 4, &fragment));
- EXPECT_THAT(fragment, Eq("ello"));
- EXPECT_TRUE(leaf->IsFlat(6, 5, &fragment));
- EXPECT_THAT(fragment, Eq("world"));
-
- CordRep::Unref(leaf);
-}
-
-TEST(CordRepBtreeTest, IsFlatMultiFlat) {
- size_t n = CordRepBtree::kMaxCapacity * CordRepBtree::kMaxCapacity + 2;
- std::string data = CreateRandomString(n * 3);
- CordRepBtree* tree = CreateTree(data, 3);
- // Add substring nodes for good measure.
- tree = tree->Append(tree, MakeSubstring(4, 3, MakeFlat("abcdefghijklm")));
- tree = tree->Append(tree, MakeSubstring(8, 3, MakeFlat("abcdefghijklm")));
- data += "efgijk";
-
- EXPECT_FALSE(tree->IsFlat(nullptr));
- absl::string_view fragment = "Can't touch this";
- EXPECT_FALSE(tree->IsFlat(&fragment));
- EXPECT_THAT(fragment, Eq("Can't touch this"));
-
- for (size_t offset = 0; offset < data.size(); offset += 3) {
- EXPECT_TRUE(tree->IsFlat(offset, 3, nullptr));
- EXPECT_TRUE(tree->IsFlat(offset, 3, &fragment));
- EXPECT_THAT(fragment, Eq(data.substr(offset, 3)));
-
- fragment = "Can't touch this";
- if (offset > 0) {
- EXPECT_FALSE(tree->IsFlat(offset - 1, 4, nullptr));
- EXPECT_FALSE(tree->IsFlat(offset - 1, 4, &fragment));
- EXPECT_THAT(fragment, Eq("Can't touch this"));
- }
- if (offset < data.size() - 4) {
- EXPECT_FALSE(tree->IsFlat(offset, 4, nullptr));
- EXPECT_FALSE(tree->IsFlat(offset, 4, &fragment));
- EXPECT_THAT(fragment, Eq("Can't touch this"));
- }
- }
-
- CordRep::Unref(tree);
-}
-
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferNotPrivate) {
- CordRepBtree* tree = CordRepBtree::Create(MakeExternal("Foo"));
- CordRepBtree::Ref(tree);
- EXPECT_DEATH(tree->GetAppendBuffer(1), ".*");
- CordRepBtree::Unref(tree);
- CordRepBtree::Unref(tree);
-}
-
-#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferNotFlat) {
- CordRepBtree* tree = CordRepBtree::Create(MakeExternal("Foo"));
- for (int i = 1; i <= height(); ++i) {
- tree = CordRepBtree::New(tree);
- }
- EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0));
- CordRepBtree::Unref(tree);
-}
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNotPrivate) {
- CordRepFlat* flat = MakeFlat("abc");
- CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));
- for (int i = 1; i <= height(); ++i) {
- tree = CordRepBtree::New(tree);
- }
- EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0));
- CordRepBtree::Unref(tree);
- CordRep::Unref(flat);
-}
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferTreeNotPrivate) {
- if (height() == 0) return;
- AutoUnref refs;
- CordRepFlat* flat = MakeFlat("abc");
- CordRepBtree* tree = CordRepBtree::Create(CordRep::Ref(flat));
- for (int i = 1; i <= height(); ++i) {
- if (i == (height() + 1) / 2) refs.Ref(tree);
- tree = CordRepBtree::New(tree);
- }
- EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0));
- CordRepBtree::Unref(tree);
- CordRep::Unref(flat);
-}
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatNoCapacity) {
- CordRepFlat* flat = MakeFlat("abc");
- flat->length = flat->Capacity();
- CordRepBtree* tree = CordRepBtree::Create(flat);
- for (int i = 1; i <= height(); ++i) {
- tree = CordRepBtree::New(tree);
- }
- EXPECT_THAT(tree->GetAppendBuffer(1), SizeIs(0));
- CordRepBtree::Unref(tree);
-}
-
-TEST_P(CordRepBtreeHeightTest, GetAppendBufferFlatWithCapacity) {
- CordRepFlat* flat = MakeFlat("abc");
- CordRepBtree* tree = CordRepBtree::Create(flat);
- for (int i = 1; i <= height(); ++i) {
- tree = CordRepBtree::New(tree);
- }
- absl::Span<char> span = tree->GetAppendBuffer(2);
- EXPECT_THAT(span, SizeIs(2));
- EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 3));
- EXPECT_THAT(tree->length, Eq(5));
-
- size_t avail = flat->Capacity() - 5;
- span = tree->GetAppendBuffer(avail + 100);
- EXPECT_THAT(span, SizeIs(avail));
- EXPECT_THAT(span.data(), TypedEq<void*>(flat->Data() + 5));
- EXPECT_THAT(tree->length, Eq(5 + avail));
-
- CordRepBtree::Unref(tree);
-}
-
-TEST(CordRepBtreeTest, Dump) {
- // Handles nullptr
- std::stringstream ss;
- CordRepBtree::Dump(nullptr, ss);
- CordRepBtree::Dump(nullptr, "Once upon a label", ss);
- CordRepBtree::Dump(nullptr, "Once upon a label", false, ss);
- CordRepBtree::Dump(nullptr, "Once upon a label", true, ss);
-
- // Cover legal edges
- CordRepFlat* flat = MakeFlat("Hello world");
- CordRepExternal* external = MakeExternal("Hello external");
- CordRep* substr_flat = MakeSubstring(1, 6, CordRep::Ref(flat));
- CordRep* substr_external = MakeSubstring(2, 7, CordRep::Ref(external));
-
- // Build tree
- CordRepBtree* tree = CordRepBtree::Create(flat);
- tree = CordRepBtree::Append(tree, external);
- tree = CordRepBtree::Append(tree, substr_flat);
- tree = CordRepBtree::Append(tree, substr_external);
-
- // Repeat until we have a tree
- while (tree->height() == 0) {
- tree = CordRepBtree::Append(tree, CordRep::Ref(flat));
- tree = CordRepBtree::Append(tree, CordRep::Ref(external));
- tree = CordRepBtree::Append(tree, CordRep::Ref(substr_flat));
- tree = CordRepBtree::Append(tree, CordRep::Ref(substr_external));
- }
-
- for (int api = 0; api <= 3; ++api) {
- absl::string_view api_scope;
- std::stringstream ss;
- switch (api) {
- case 0:
- api_scope = "Bare";
- CordRepBtree::Dump(tree, ss);
- break;
- case 1:
- api_scope = "Label only";
- CordRepBtree::Dump(tree, "Once upon a label", ss);
- break;
- case 2:
- api_scope = "Label no content";
- CordRepBtree::Dump(tree, "Once upon a label", false, ss);
- break;
- default:
- api_scope = "Label and content";
- CordRepBtree::Dump(tree, "Once upon a label", true, ss);
- break;
- }
- SCOPED_TRACE(api_scope);
- std::string str = ss.str();
-
- // Contains Node(depth) / Leaf and private / shared indicators
- EXPECT_THAT(str, AllOf(HasSubstr("Node(1)"), HasSubstr("Leaf"),
- HasSubstr("Private"), HasSubstr("Shared")));
-
- // Contains length and start offset of all data edges
- EXPECT_THAT(str, AllOf(HasSubstr("len = 11"), HasSubstr("len = 14"),
- HasSubstr("len = 6"), HasSubstr("len = 7"),
- HasSubstr("start = 1"), HasSubstr("start = 2")));
-
- // Contains address of all data edges
- EXPECT_THAT(
- str, AllOf(HasSubstr(absl::StrCat("0x", absl::Hex(flat))),
- HasSubstr(absl::StrCat("0x", absl::Hex(external))),
- HasSubstr(absl::StrCat("0x", absl::Hex(substr_flat))),
- HasSubstr(absl::StrCat("0x", absl::Hex(substr_external)))));
-
- if (api != 0) {
- // Contains label
- EXPECT_THAT(str, HasSubstr("Once upon a label"));
- }
-
- if (api != 3) {
- // Does not contain contents
- EXPECT_THAT(str, Not(AnyOf((HasSubstr("data = \"Hello world\""),
- HasSubstr("data = \"Hello external\""),
- HasSubstr("data = \"ello w\""),
- HasSubstr("data = \"llo ext\"")))));
- } else {
- // Contains contents
- EXPECT_THAT(str, AllOf((HasSubstr("data = \"Hello world\""),
- HasSubstr("data = \"Hello external\""),
- HasSubstr("data = \"ello w\""),
- HasSubstr("data = \"llo ext\""))));
- }
- }
-
- CordRep::Unref(tree);
-}
-
-TEST(CordRepBtreeTest, IsValid) {
- EXPECT_FALSE(CordRepBtree::IsValid(nullptr));
-
- CordRepBtree* empty = CordRepBtree::New(0);
- EXPECT_TRUE(CordRepBtree::IsValid(empty));
- CordRep::Unref(empty);
-
- for (bool as_tree : {false, true}) {
- CordRepBtree* leaf = CordRepBtree::Create(MakeFlat("abc"));
- CordRepBtree* tree = as_tree ? CordRepBtree::New(leaf) : nullptr;
- CordRepBtree* check = as_tree ? tree : leaf;
-
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- leaf->length--;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->length++;
-
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- leaf->tag--;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->tag++;
-
- // Height
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- leaf->storage[0] = static_cast<uint8_t>(CordRepBtree::kMaxHeight + 1);
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->storage[0] = 1;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->storage[0] = 0;
-
- // Begin
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- const uint8_t begin = leaf->storage[1];
- leaf->storage[1] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity);
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->storage[1] = 2;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->storage[1] = begin;
-
- // End
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- const uint8_t end = leaf->storage[2];
- leaf->storage[2] = static_cast<uint8_t>(CordRepBtree::kMaxCapacity + 1);
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->storage[2] = end;
-
- // DataEdge tag and value
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- CordRep* const edge = leaf->Edges()[0];
- const uint8_t tag = edge->tag;
- CordRepBtreeTestPeer::SetEdge(leaf, begin, nullptr);
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- CordRepBtreeTestPeer::SetEdge(leaf, begin, edge);
- edge->tag = BTREE;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- edge->tag = tag;
-
- if (as_tree) {
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- leaf->length--;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- leaf->length++;
-
- // Height
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- tree->storage[0] = static_cast<uint8_t>(2);
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- tree->storage[0] = 1;
-
- // Btree edge
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- CordRep* const edge = tree->Edges()[0];
- const uint8_t tag = edge->tag;
- edge->tag = FLAT;
- EXPECT_FALSE(CordRepBtree::IsValid(check));
- edge->tag = tag;
- }
-
- ASSERT_TRUE(CordRepBtree::IsValid(check));
- CordRep::Unref(check);
- }
-}
-
-TEST(CordRepBtreeTest, AssertValid) {
- CordRepBtree* tree = CordRepBtree::Create(MakeFlat("abc"));
- const CordRepBtree* ctree = tree;
- EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree));
- EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree));
-
-#if defined(GTEST_HAS_DEATH_TEST)
- CordRepBtree* nulltree = nullptr;
- const CordRepBtree* cnulltree = nullptr;
- EXPECT_DEBUG_DEATH(
- EXPECT_THAT(CordRepBtree::AssertValid(nulltree), Eq(nulltree)), ".*");
- EXPECT_DEBUG_DEATH(
- EXPECT_THAT(CordRepBtree::AssertValid(cnulltree), Eq(cnulltree)), ".*");
-
- tree->length--;
- EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(tree), Eq(tree)),
- ".*");
- EXPECT_DEBUG_DEATH(EXPECT_THAT(CordRepBtree::AssertValid(ctree), Eq(ctree)),
- ".*");
- tree->length++;
-#endif
- CordRep::Unref(tree);
-}
-
-TEST(CordRepBtreeTest, CheckAssertValidShallowVsDeep) {
- // Restore exhaustive validation on any exit.
- const bool exhaustive_validation = cord_btree_exhaustive_validation.load();
- auto cleanup = absl::MakeCleanup([exhaustive_validation] {
- cord_btree_exhaustive_validation.store(exhaustive_validation);
- });
-
- // Create a tree of at least 2 levels, and mess with the original flat, which
- // should go undetected in shallow mode as the flat is too far away, but
- // should be detected in forced non-shallow mode.
- CordRep* flat = MakeFlat("abc");
- CordRepBtree* tree = CordRepBtree::Create(flat);
- constexpr size_t max_cap = CordRepBtree::kMaxCapacity;
- const size_t n = max_cap * max_cap * 2;
- for (size_t i = 0; i < n; ++i) {
- tree = CordRepBtree::Append(tree, MakeFlat("Hello world"));
- }
- flat->length = 100;
-
- cord_btree_exhaustive_validation.store(false);
- EXPECT_FALSE(CordRepBtree::IsValid(tree));
- EXPECT_TRUE(CordRepBtree::IsValid(tree, true));
- EXPECT_FALSE(CordRepBtree::IsValid(tree, false));
- CordRepBtree::AssertValid(tree);
- CordRepBtree::AssertValid(tree, true);
-#if defined(GTEST_HAS_DEATH_TEST)
- EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, false), ".*");
-#endif
-
- cord_btree_exhaustive_validation.store(true);
- EXPECT_FALSE(CordRepBtree::IsValid(tree));
- EXPECT_FALSE(CordRepBtree::IsValid(tree, true));
- EXPECT_FALSE(CordRepBtree::IsValid(tree, false));
-#if defined(GTEST_HAS_DEATH_TEST)
- EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree), ".*");
- EXPECT_DEBUG_DEATH(CordRepBtree::AssertValid(tree, true), ".*");
-#endif
-
- flat->length = 3;
- CordRep::Unref(tree);
-}
-
-TEST_P(CordRepBtreeTest, Rebuild) {
- for (size_t size : {3, 8, 100, 10000, 1000000}) {
- SCOPED_TRACE(absl::StrCat("Rebuild @", size));
-
- std::vector<CordRepFlat*> flats;
- for (int i = 0; i < size; ++i) {
- flats.push_back(CordRepFlat::New(2));
- flats.back()->Data()[0] = 'x';
- flats.back()->length = 1;
- }
-
- // Build the tree into 'right', and each so many 'split_limit' edges,
- // combine 'left' + 'right' into a new 'left', and start a new 'right'.
- // This guarantees we get a reasonable amount of chaos in the tree.
- size_t split_count = 0;
- size_t split_limit = 3;
- auto it = flats.begin();
- CordRepBtree* left = nullptr;
- CordRepBtree* right = CordRepBtree::New(*it);
- while (++it != flats.end()) {
- if (++split_count >= split_limit) {
- split_limit += split_limit / 16;
- left = left ? CordRepBtree::Append(left, right) : right;
- right = CordRepBtree::New(*it);
- } else {
- right = CordRepBtree::Append(right, *it);
- }
- }
-
- // Finalize tree
- left = left ? CordRepBtree::Append(left, right) : right;
-
- // Rebuild
- AutoUnref ref;
- left = ref.Add(CordRepBtree::Rebuild(ref.RefIf(shared(), left)));
- ASSERT_TRUE(CordRepBtree::IsValid(left));
-
- // Verify we have the exact same edges in the exact same order.
- bool ok = true;
- it = flats.begin();
- CordVisitReps(left, [&](CordRep* edge) {
- if (edge->tag < FLAT) return;
- ok = ok && (it != flats.end() && *it++ == edge);
- });
- EXPECT_TRUE(ok && it == flats.end()) << "Rebuild edges mismatch";
- }
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc
deleted file mode 100644
index 81514543db..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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/strings/internal/cord_rep_consume.h"
-
-#include <array>
-#include <utility>
-
-#include "absl/container/inlined_vector.h"
-#include "absl/functional/function_ref.h"
-#include "absl/strings/internal/cord_internal.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-namespace {
-
-// 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);
- CordRep::Unref(substring);
- }
- return child;
-}
-
-// Unrefs the provided `concat`, and returns `{concat->left, concat->right}`
-// Adds or assumes a reference on `concat->left` and `concat->right`.
-// Returns an array of 2 elements containing the left and right nodes.
-std::array<CordRep*, 2> ClipConcat(CordRepConcat* concat) {
- std::array<CordRep*, 2> result{concat->left, concat->right};
- if (concat->refcount.IsOne()) {
- delete concat;
- } else {
- CordRep::Ref(result[0]);
- CordRep::Ref(result[1]);
- CordRep::Unref(concat);
- }
- return result;
-}
-
-void Consume(bool forward, CordRep* rep, ConsumeFn consume_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 == CONCAT) {
- std::array<CordRep*, 2> res = ClipConcat(rep->concat());
- CordRep* left = res[0];
- CordRep* right = res[1];
-
- 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 (forward) {
- stack.push_back({right, 0, length_right});
- rep = left;
- length = length_left;
- } else {
- stack.push_back({left, offset, length_left});
- rep = right;
- offset = 0;
- length = length_right;
- }
- } else if (rep->tag == SUBSTRING) {
- offset += rep->substring()->start;
- rep = ClipSubstring(rep->substring());
- } else {
- consume_fn(rep, offset, length);
- if (stack.empty()) return;
-
- rep = stack.back().rep;
- offset = stack.back().offset;
- length = stack.back().length;
- stack.pop_back();
- }
- }
-}
-
-} // namespace
-
-void Consume(CordRep* rep, ConsumeFn consume_fn) {
- return Consume(true, rep, std::move(consume_fn));
-}
-
-void ReverseConsume(CordRep* rep, ConsumeFn consume_fn) {
- return Consume(false, rep, std::move(consume_fn));
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.h
deleted file mode 100644
index d46fca2b21..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// 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_CONSUME_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_
-
-#include <functional>
-
-#include "absl/functional/function_ref.h"
-#include "absl/strings/internal/cord_internal.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// Functor for the Consume() and ReverseConsume() functions:
-// void ConsumeFunc(CordRep* rep, size_t offset, size_t length);
-// See the Consume() and ReverseConsume() function comments for documentation.
-using ConsumeFn = FunctionRef<void(CordRep*, size_t, size_t)>;
-
-// Consume() and ReverseConsume() consume CONCAT based trees and invoke the
-// provided functor with the contained nodes in the proper forward or reverse
-// order, which is used to convert CONCAT trees into other tree or cord data.
-// All CONCAT and SUBSTRING nodes are processed internally. The 'offset`
-// parameter of the functor is non-zero for any nodes below SUBSTRING nodes.
-// It's up to the caller to form these back into SUBSTRING nodes or otherwise
-// store offset / prefix information. These functions are intended to be used
-// only for migration / transitional code where due to factors such as ODR
-// violations, we can not 100% guarantee that all code respects 'new format'
-// settings and flags, so we need to be able to parse old data on the fly until
-// all old code is deprecated / no longer the default format.
-void Consume(CordRep* rep, ConsumeFn consume_fn);
-void ReverseConsume(CordRep* rep, ConsumeFn consume_fn);
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_CONSUME_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume_test.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume_test.cc
deleted file mode 100644
index e507824b4f..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_consume_test.cc
+++ /dev/null
@@ -1,173 +0,0 @@
-// 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/strings/internal/cord_rep_consume.h"
-
-#include <functional>
-#include <utility>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using testing::InSequence;
-using testing::MockFunction;
-
-// Returns the depth of a node
-int Depth(const CordRep* rep) {
- return (rep->tag == CONCAT) ? rep->concat()->depth() : 0;
-}
-
-// Creates a concatenation of the specified nodes.
-CordRepConcat* CreateConcat(CordRep* left, CordRep* right) {
- auto* concat = new CordRepConcat();
- concat->tag = CONCAT;
- concat->left = left;
- concat->right = right;
- concat->length = left->length + right->length;
- concat->set_depth(1 + (std::max)(Depth(left), Depth(right)));
- return concat;
-}
-
-// Creates a flat with the length set to `length`
-CordRepFlat* CreateFlatWithLength(size_t length) {
- auto* flat = CordRepFlat::New(length);
- flat->length = length;
- return flat;
-}
-
-// Creates a substring node on the specified child.
-CordRepSubstring* CreateSubstring(CordRep* child, size_t start, size_t length) {
- auto* rep = new CordRepSubstring();
- rep->length = length;
- rep->tag = SUBSTRING;
- rep->start = start;
- rep->child = child;
- return rep;
-}
-
-// Flats we use in the tests
-CordRep* flat[6];
-
-// Creates a test tree
-CordRep* CreateTestTree() {
- flat[0] = CreateFlatWithLength(1);
- flat[1] = CreateFlatWithLength(7);
- CordRepConcat* left = CreateConcat(flat[0], CreateSubstring(flat[1], 2, 4));
-
- flat[2] = CreateFlatWithLength(9);
- flat[3] = CreateFlatWithLength(13);
- CordRepConcat* right1 = CreateConcat(flat[2], flat[3]);
-
- flat[4] = CreateFlatWithLength(15);
- flat[5] = CreateFlatWithLength(19);
- CordRepConcat* right2 = CreateConcat(flat[4], flat[5]);
-
- CordRepConcat* right = CreateConcat(right1, CreateSubstring(right2, 5, 17));
- return CreateConcat(left, right);
-}
-
-TEST(CordRepConsumeTest, Consume) {
- InSequence in_sequence;
- CordRep* tree = CreateTestTree();
- MockFunction<void(CordRep*, size_t, size_t)> consume;
- EXPECT_CALL(consume, Call(flat[0], 0, 1));
- EXPECT_CALL(consume, Call(flat[1], 2, 4));
- EXPECT_CALL(consume, Call(flat[2], 0, 9));
- EXPECT_CALL(consume, Call(flat[3], 0, 13));
- EXPECT_CALL(consume, Call(flat[4], 5, 10));
- EXPECT_CALL(consume, Call(flat[5], 0, 7));
- Consume(tree, consume.AsStdFunction());
- for (CordRep* rep : flat) {
- EXPECT_TRUE(rep->refcount.IsOne());
- CordRep::Unref(rep);
- }
-}
-
-TEST(CordRepConsumeTest, ConsumeShared) {
- InSequence in_sequence;
- CordRep* tree = CreateTestTree();
- MockFunction<void(CordRep*, size_t, size_t)> consume;
- EXPECT_CALL(consume, Call(flat[0], 0, 1));
- EXPECT_CALL(consume, Call(flat[1], 2, 4));
- EXPECT_CALL(consume, Call(flat[2], 0, 9));
- EXPECT_CALL(consume, Call(flat[3], 0, 13));
- EXPECT_CALL(consume, Call(flat[4], 5, 10));
- EXPECT_CALL(consume, Call(flat[5], 0, 7));
- Consume(CordRep::Ref(tree), consume.AsStdFunction());
- for (CordRep* rep : flat) {
- EXPECT_FALSE(rep->refcount.IsOne());
- CordRep::Unref(rep);
- }
- CordRep::Unref(tree);
-}
-
-TEST(CordRepConsumeTest, Reverse) {
- InSequence in_sequence;
- CordRep* tree = CreateTestTree();
- MockFunction<void(CordRep*, size_t, size_t)> consume;
- EXPECT_CALL(consume, Call(flat[5], 0, 7));
- EXPECT_CALL(consume, Call(flat[4], 5, 10));
- EXPECT_CALL(consume, Call(flat[3], 0, 13));
- EXPECT_CALL(consume, Call(flat[2], 0, 9));
- EXPECT_CALL(consume, Call(flat[1], 2, 4));
- EXPECT_CALL(consume, Call(flat[0], 0, 1));
- ReverseConsume(tree, consume.AsStdFunction());
- for (CordRep* rep : flat) {
- EXPECT_TRUE(rep->refcount.IsOne());
- CordRep::Unref(rep);
- }
-}
-
-TEST(CordRepConsumeTest, ReverseShared) {
- InSequence in_sequence;
- CordRep* tree = CreateTestTree();
- MockFunction<void(CordRep*, size_t, size_t)> consume;
- EXPECT_CALL(consume, Call(flat[5], 0, 7));
- EXPECT_CALL(consume, Call(flat[4], 5, 10));
- EXPECT_CALL(consume, Call(flat[3], 0, 13));
- EXPECT_CALL(consume, Call(flat[2], 0, 9));
- EXPECT_CALL(consume, Call(flat[1], 2, 4));
- EXPECT_CALL(consume, Call(flat[0], 0, 1));
- ReverseConsume(CordRep::Ref(tree), consume.AsStdFunction());
- for (CordRep* rep : flat) {
- EXPECT_FALSE(rep->refcount.IsOne());
- CordRep::Unref(rep);
- }
- CordRep::Unref(tree);
-}
-
-TEST(CordRepConsumeTest, UnreachableFlat) {
- InSequence in_sequence;
- CordRepFlat* flat1 = CreateFlatWithLength(10);
- CordRepFlat* flat2 = CreateFlatWithLength(20);
- CordRepConcat* concat = CreateConcat(flat1, flat2);
- CordRepSubstring* tree = CreateSubstring(concat, 15, 10);
- MockFunction<void(CordRep*, size_t, size_t)> consume;
- EXPECT_CALL(consume, Call(flat2, 5, 10));
- Consume(tree, consume.AsStdFunction());
- EXPECT_TRUE(flat2->refcount.IsOne());
- CordRep::Unref(flat2);
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h
deleted file mode 100644
index 4d0f988697..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_flat.h
+++ /dev/null
@@ -1,146 +0,0 @@
-// 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 + 1
- : 129 + size / 32 - 1024 / 32);
-}
-
-static_assert(kMinFlatSize / 8 + 1 >= 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 <= 129) ? ((tag - 1) * 8) : (1024 + (tag - 129) * 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(225) == 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 reinterpret_cast<char*>(storage); }
- const char* Data() const { return reinterpret_cast<const char*>(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/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc b/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc
deleted file mode 100644
index 07c77eb3e5..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.cc
+++ /dev/null
@@ -1,771 +0,0 @@
-// 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_consume.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-namespace {
-
-using index_type = CordRepRing::index_type;
-
-enum class Direction { kForward, kReversed };
-
-inline bool IsFlatOrExternal(CordRep* rep) {
- return rep->IsFlat() || rep->IsExternal();
-}
-
-// 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");
- }
-}
-
-// 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 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());
- }
- }
- });
-}
-
-} // 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 child's 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->IsRing());
-#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();
-
- if (!rep->refcount.IsMutable()) {
- return Copy(rep, rep->head(), rep->tail(), extra);
- } else if (entries + extra > rep->capacity()) {
- const size_t min_grow = rep->capacity() + rep->capacity() / 2;
- const size_t min_extra = (std::max)(extra, min_grow - entries);
- 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.IsMutable());
- index_type back = retreat(tail_);
- CordRep* child = entry_child(back);
- if (child->tag >= FLAT && child->refcount.IsMutable()) {
- 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.IsMutable());
- CordRep* child = entry_child(head_);
- size_t data_offset = entry_data_offset(head_);
- if (data_offset && child->refcount.IsMutable() && 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 len, size_t extra) {
- CordRepRing* rep = CordRepRing::New(1, extra);
- rep->head_ = 0;
- rep->tail_ = rep->advance(0);
- rep->length = len;
- rep->entry_end_pos()[0] = len;
- 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_arg, size_t offset, size_t len) {
- if (IsFlatOrExternal(child_arg)) {
- rep = rep ? AppendLeaf(rep, child_arg, offset, len)
- : CreateFromLeaf(child_arg, offset, len, extra);
- } else if (rep) {
- rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len);
- } else if (offset == 0 && child_arg->length == len) {
- rep = Mutable(child_arg->ring(), extra);
- } else {
- rep = SubRing(child_arg->ring(), offset, len, 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->IsRing()) {
- 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 len) {
- assert(offset < ring->length);
- constexpr bool append = mode == AddMode::kAppend;
- Position head = ring->Find(offset);
- Position tail = ring->FindTail(head.index, offset + len);
- 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_ - len) -
- 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 += len;
- if (append) {
- rep->tail_ = filler.pos();
- } else {
- rep->head_ = filler.head();
- rep->begin_pos_ -= len;
- }
-
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::AppendSlow(CordRepRing* rep, CordRep* child) {
- Consume(child, [&rep](CordRep* child_arg, size_t offset, size_t len) {
- if (child_arg->IsRing()) {
- rep = AddRing<AddMode::kAppend>(rep, child_arg->ring(), offset, len);
- } else {
- rep = AppendLeaf(rep, child_arg, offset, len);
- }
- });
- return rep;
-}
-
-CordRepRing* CordRepRing::AppendLeaf(CordRepRing* rep, CordRep* child,
- size_t offset, size_t len) {
- 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 += len;
- rep->entry_end_pos()[back] = begin_pos + len;
- 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->IsRing()) {
- return AddRing<AddMode::kAppend>(rep, child->ring(), 0, length);
- }
- return AppendSlow(rep, child);
-}
-
-CordRepRing* CordRepRing::PrependSlow(CordRepRing* rep, CordRep* child) {
- ReverseConsume(child, [&](CordRep* child_arg, size_t offset, size_t len) {
- if (IsFlatOrExternal(child_arg)) {
- rep = PrependLeaf(rep, child_arg, offset, len);
- } else {
- rep = AddRing<AddMode::kPrepend>(rep, child_arg->ring(), offset, len);
- }
- });
- return Validate(rep);
-}
-
-CordRepRing* CordRepRing::PrependLeaf(CordRepRing* rep, CordRep* child,
- size_t offset, size_t len) {
- rep = Mutable(rep, 1);
- index_type head = rep->retreat(rep->head_);
- pos_type end_pos = rep->begin_pos_;
- rep->head_ = head;
- rep->length += len;
- rep->begin_pos_ -= len;
- 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->IsRing()) {
- 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.IsMutable()) {
- 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.IsMutable()) {
- 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 len, size_t extra) {
- assert(offset <= rep->length);
- assert(offset <= rep->length - len);
-
- if (len == 0) {
- CordRep::Unref(rep);
- return nullptr;
- }
-
- // Find position of first byte
- Position head = rep->Find(offset);
- Position tail = rep->FindTail(head.index, offset + len);
- const size_t new_entries = rep->entries(head.index, tail.index);
-
- if (rep->refcount.IsMutable() && 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 = len;
- 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.IsMutable()) {
- 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.IsMutable()) {
- // 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);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h
deleted file mode 100644
index 2000e21ea0..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring.h
+++ /dev/null
@@ -1,607 +0,0 @@
-// 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 {
-
-// 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 `len` 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 len,
- size_t extra = 0);
-
- // Returns a cord ring buffer with the first `len` 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 len,
- size_t extra = 0);
-
- // Returns a cord ring buffer with the last `len` 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;
-
- // Returns true if this instance manages a single contiguous buffer, in which
- // case the (optional) output parameter `fragment` is set. Otherwise, the
- // function returns false, and `fragment` is left unchanged.
- bool IsFlat(absl::string_view* fragment) const;
-
- // Returns true if the data starting at `offset` with length `len` is
- // managed by this instance inside a single contiguous buffer, in which case
- // the (optional) output parameter `fragment` is set to the contiguous memory
- // starting at offset `offset` with length `length`. Otherwise, the function
- // returns false, and `fragment` is left unchanged.
- bool IsFlat(size_t offset, size_t len, absl::string_view* fragment) 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 `len`.
- template <AddMode mode>
- static CordRepRing* AddRing(CordRepRing* rep, CordRepRing* ring,
- size_t offset, size_t len);
-
- // 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(IsRing());
- return static_cast<CordRepRing*>(this);
-}
-
-inline const CordRepRing* CordRep::ring() const {
- assert(IsRing());
- return static_cast<const CordRepRing*>(this);
-}
-
-inline bool CordRepRing::IsFlat(absl::string_view* fragment) const {
- if (entries() == 1) {
- if (fragment) *fragment = entry_data(head());
- return true;
- }
- return false;
-}
-
-inline bool CordRepRing::IsFlat(size_t offset, size_t len,
- absl::string_view* fragment) const {
- const Position pos = Find(offset);
- const absl::string_view data = entry_data(pos.index);
- if (data.length() >= len && data.length() - len >= pos.offset) {
- if (fragment) *fragment = data.substr(pos.offset, len);
- return true;
- }
- return false;
-}
-
-std::ostream& operator<<(std::ostream& s, const CordRepRing& rep);
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_RING_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h
deleted file mode 100644
index 7ceeaa000e..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_ring_reader.h
+++ /dev/null
@@ -1,118 +0,0 @@
-// 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 current node inside the ring buffer for this instance.
- // The returned value is undefined if this instance is empty.
- CordRep* node() const { return ring_->entry_child(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/third_party/abseil-cpp/absl/strings/internal/cord_rep_test_util.h b/third_party/abseil-cpp/absl/strings/internal/cord_rep_test_util.h
deleted file mode 100644
index ad828af2a5..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cord_rep_test_util.h
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2021 The Abseil Authors
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
-#define ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
-
-#include <cassert>
-#include <memory>
-#include <random>
-#include <string>
-#include <vector>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/string_view.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cordrep_testing {
-
-inline cord_internal::CordRepSubstring* MakeSubstring(
- size_t start, size_t len, cord_internal::CordRep* rep) {
- auto* sub = new cord_internal::CordRepSubstring;
- sub->tag = cord_internal::SUBSTRING;
- sub->start = start;
- sub->length = len <= 0 ? rep->length - start + len : len;
- sub->child = rep;
- return sub;
-}
-
-inline cord_internal::CordRepConcat* MakeConcat(cord_internal::CordRep* left,
- cord_internal::CordRep* right,
- int depth = 0) {
- auto* concat = new cord_internal::CordRepConcat;
- concat->tag = cord_internal::CONCAT;
- concat->length = left->length + right->length;
- concat->left = left;
- concat->right = right;
- concat->set_depth(depth);
- return concat;
-}
-
-inline cord_internal::CordRepFlat* MakeFlat(absl::string_view value) {
- assert(value.length() <= cord_internal::kMaxFlatLength);
- auto* flat = cord_internal::CordRepFlat::New(value.length());
- flat->length = value.length();
- memcpy(flat->Data(), value.data(), value.length());
- return flat;
-}
-
-// Creates an external node for testing
-inline cord_internal::CordRepExternal* MakeExternal(absl::string_view s) {
- struct Rep : public cord_internal::CordRepExternal {
- std::string s;
- explicit Rep(absl::string_view sv) : s(sv) {
- this->tag = cord_internal::EXTERNAL;
- this->base = s.data();
- this->length = s.length();
- this->releaser_invoker = [](cord_internal::CordRepExternal* self) {
- delete static_cast<Rep*>(self);
- };
- }
- };
- return new Rep(s);
-}
-
-inline std::string CreateRandomString(size_t n) {
- absl::string_view data =
- "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789~!@#$%^&*()_+=-<>?:\"{}[]|";
- std::minstd_rand rnd;
- std::uniform_int_distribution<size_t> dist(0, data.size() - 1);
- std::string s(n, ' ');
- for (size_t i = 0; i < n; ++i) {
- s[i] = data[dist(rnd)];
- }
- return s;
-}
-
-// Creates an array of flats from the provided string, chopping
-// the provided string up into flats of size `chunk_size` characters
-// resulting in roughly `data.size() / chunk_size` total flats.
-inline std::vector<cord_internal::CordRep*> CreateFlatsFromString(
- absl::string_view data, size_t chunk_size) {
- assert(chunk_size > 0);
- std::vector<cord_internal::CordRep*> flats;
- for (absl::string_view s = data; !s.empty(); s.remove_prefix(chunk_size)) {
- flats.push_back(MakeFlat(s.substr(0, chunk_size)));
- }
- return flats;
-}
-
-inline cord_internal::CordRepBtree* CordRepBtreeFromFlats(
- absl::Span<cord_internal::CordRep* const> flats) {
- assert(!flats.empty());
- auto* node = cord_internal::CordRepBtree::Create(flats[0]);
- for (size_t i = 1; i < flats.size(); ++i) {
- node = cord_internal::CordRepBtree::Append(node, flats[i]);
- }
- return node;
-}
-
-template <typename Fn>
-inline void CordVisitReps(cord_internal::CordRep* rep, Fn&& fn) {
- fn(rep);
- while (rep->tag == cord_internal::SUBSTRING) {
- rep = rep->substring()->child;
- fn(rep);
- }
- if (rep->tag == cord_internal::BTREE) {
- for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
- CordVisitReps(edge, fn);
- }
- } else if (rep->tag == cord_internal::CONCAT) {
- CordVisitReps(rep->concat()->left, fn);
- CordVisitReps(rep->concat()->right, fn);
- }
-}
-
-template <typename Predicate>
-inline std::vector<cord_internal::CordRep*> CordCollectRepsIf(
- Predicate&& predicate, cord_internal::CordRep* rep) {
- std::vector<cord_internal::CordRep*> reps;
- CordVisitReps(rep, [&reps, &predicate](cord_internal::CordRep* rep) {
- if (predicate(rep)) reps.push_back(rep);
- });
- return reps;
-}
-
-inline std::vector<cord_internal::CordRep*> CordCollectReps(
- cord_internal::CordRep* rep) {
- std::vector<cord_internal::CordRep*> reps;
- auto fn = [&reps](cord_internal::CordRep* rep) { reps.push_back(rep); };
- CordVisitReps(rep, fn);
- return reps;
-}
-
-inline void CordToString(cord_internal::CordRep* rep, std::string& s) {
- size_t offset = 0;
- size_t length = rep->length;
- while (rep->tag == cord_internal::SUBSTRING) {
- offset += rep->substring()->start;
- rep = rep->substring()->child;
- }
- if (rep->tag == cord_internal::BTREE) {
- for (cord_internal::CordRep* edge : rep->btree()->Edges()) {
- CordToString(edge, s);
- }
- } else if (rep->tag >= cord_internal::FLAT) {
- s.append(rep->flat()->Data() + offset, length);
- } else if (rep->tag == cord_internal::EXTERNAL) {
- s.append(rep->external()->base + offset, length);
- } else {
- ABSL_RAW_LOG(FATAL, "Unsupported tag %d", rep->tag);
- }
-}
-
-inline std::string CordToString(cord_internal::CordRep* rep) {
- std::string s;
- s.reserve(rep->length);
- CordToString(rep, s);
- return s;
-}
-
-// RAII Helper class to automatically unref reps on destruction.
-class AutoUnref {
- public:
- ~AutoUnref() {
- for (CordRep* rep : unrefs_) CordRep::Unref(rep);
- }
-
- // Adds `rep` to the list of reps to be unreffed at destruction.
- template <typename CordRepType>
- CordRepType* Add(CordRepType* rep) {
- unrefs_.push_back(rep);
- return rep;
- }
-
- // Increments the reference count of `rep` by one, and adds it to
- // the list of reps to be unreffed at destruction.
- template <typename CordRepType>
- CordRepType* Ref(CordRepType* rep) {
- unrefs_.push_back(CordRep::Ref(rep));
- return rep;
- }
-
- // Increments the reference count of `rep` by one if `condition` is true,
- // and adds it to the list of reps to be unreffed at destruction.
- template <typename CordRepType>
- CordRepType* RefIf(bool condition, CordRepType* rep) {
- if (condition) unrefs_.push_back(CordRep::Ref(rep));
- return rep;
- }
-
- private:
- using CordRep = absl::cord_internal::CordRep;
-
- std::vector<CordRep*> unrefs_;
-};
-
-} // namespace cordrep_testing
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORD_REP_TEST_UTIL_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc
deleted file mode 100644
index 20d314f03c..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_functions.cc
+++ /dev/null
@@ -1,96 +0,0 @@
-// 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/strings/internal/cordz_functions.h"
-
-#include <atomic>
-#include <cmath>
-#include <limits>
-#include <random>
-
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/profiling/internal/exponential_biased.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-// The average interval until the next sample. A value of 0 disables profiling
-// while a value of 1 will profile all Cords.
-std::atomic<int> g_cordz_mean_interval(50000);
-
-} // namespace
-
-#ifdef ABSL_INTERNAL_CORDZ_ENABLED
-
-// Special negative 'not initialized' per thread value for cordz_next_sample.
-static constexpr int64_t kInitCordzNextSample = -1;
-
-ABSL_CONST_INIT thread_local int64_t cordz_next_sample = kInitCordzNextSample;
-
-// kIntervalIfDisabled is the number of profile-eligible events need to occur
-// before the code will confirm that cordz is still disabled.
-constexpr int64_t kIntervalIfDisabled = 1 << 16;
-
-ABSL_ATTRIBUTE_NOINLINE bool cordz_should_profile_slow() {
-
- thread_local absl::profiling_internal::ExponentialBiased
- exponential_biased_generator;
- int32_t mean_interval = get_cordz_mean_interval();
-
- // Check if we disabled profiling. If so, set the next sample to a "large"
- // number to minimize the overhead of the should_profile codepath.
- if (mean_interval <= 0) {
- cordz_next_sample = kIntervalIfDisabled;
- return false;
- }
-
- // Check if we're always sampling.
- if (mean_interval == 1) {
- cordz_next_sample = 1;
- return true;
- }
-
- if (cordz_next_sample <= 0) {
- // If first check on current thread, check cordz_should_profile()
- // again using the created (initial) stride in cordz_next_sample.
- const bool initialized = cordz_next_sample != kInitCordzNextSample;
- cordz_next_sample = exponential_biased_generator.GetStride(mean_interval);
- return initialized || cordz_should_profile();
- }
-
- --cordz_next_sample;
- return false;
-}
-
-void cordz_set_next_sample_for_testing(int64_t next_sample) {
- cordz_next_sample = next_sample;
-}
-
-#endif // ABSL_INTERNAL_CORDZ_ENABLED
-
-int32_t get_cordz_mean_interval() {
- return g_cordz_mean_interval.load(std::memory_order_acquire);
-}
-
-void set_cordz_mean_interval(int32_t mean_interval) {
- g_cordz_mean_interval.store(mean_interval, std::memory_order_release);
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_functions.h b/third_party/abseil-cpp/absl/strings/internal/cordz_functions.h
deleted file mode 100644
index c9ba14508a..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_functions.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// 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_STRINGS_CORDZ_FUNCTIONS_H_
-#define ABSL_STRINGS_CORDZ_FUNCTIONS_H_
-
-#include <stdint.h>
-
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/base/optimization.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// Returns the current sample rate. This represents the average interval
-// between samples.
-int32_t get_cordz_mean_interval();
-
-// Sets the sample rate with the average interval between samples.
-void set_cordz_mean_interval(int32_t mean_interval);
-
-// Enable cordz unless any of the following applies:
-// - no thread local support
-// - MSVC build
-// - Android build
-// - Apple build
-// - DLL build
-// Hashtablez is turned off completely in opensource builds.
-// MSVC's static atomics are dynamically initialized in debug mode, which breaks
-// sampling.
-#if defined(ABSL_HAVE_THREAD_LOCAL) && !defined(_MSC_VER) && \
- !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL) && \
- !defined(__ANDROID__) && !defined(__APPLE__)
-#define ABSL_INTERNAL_CORDZ_ENABLED 1
-#endif
-
-#ifdef ABSL_INTERNAL_CORDZ_ENABLED
-
-// cordz_next_sample is the number of events until the next sample event. If
-// the value is 1 or less, the code will check on the next event if cordz is
-// enabled, and if so, will sample the Cord. cordz is only enabled when we can
-// use thread locals.
-ABSL_CONST_INIT extern thread_local int64_t cordz_next_sample;
-
-// Determines if the next sample should be profiled. If it is, the value pointed
-// at by next_sample will be set with the interval until the next sample.
-bool cordz_should_profile_slow();
-
-// Returns true if the next cord should be sampled.
-inline bool cordz_should_profile() {
- if (ABSL_PREDICT_TRUE(cordz_next_sample > 1)) {
- cordz_next_sample--;
- return false;
- }
- return cordz_should_profile_slow();
-}
-
-// Sets the interval until the next sample (for testing only)
-void cordz_set_next_sample_for_testing(int64_t next_sample);
-
-#else // ABSL_INTERNAL_CORDZ_ENABLED
-
-inline bool cordz_should_profile() { return false; }
-inline void cordz_set_next_sample_for_testing(int64_t) {}
-
-#endif // ABSL_INTERNAL_CORDZ_ENABLED
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORDZ_FUNCTIONS_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_functions_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_functions_test.cc
deleted file mode 100644
index 350623c1f3..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_functions_test.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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/strings/internal/cordz_functions.h"
-
-#include <thread> // NOLINT we need real clean new threads
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::Eq;
-using ::testing::Ge;
-using ::testing::Le;
-
-TEST(CordzFunctionsTest, SampleRate) {
- int32_t orig_sample_rate = get_cordz_mean_interval();
- int32_t expected_sample_rate = 123;
- set_cordz_mean_interval(expected_sample_rate);
- EXPECT_THAT(get_cordz_mean_interval(), Eq(expected_sample_rate));
- set_cordz_mean_interval(orig_sample_rate);
-}
-
-// Cordz is disabled when we don't have thread_local. All calls to
-// should_profile will return false when cordz is diabled, so we might want to
-// avoid those tests.
-#ifdef ABSL_INTERNAL_CORDZ_ENABLED
-
-TEST(CordzFunctionsTest, ShouldProfileDisable) {
- int32_t orig_sample_rate = get_cordz_mean_interval();
-
- set_cordz_mean_interval(0);
- cordz_set_next_sample_for_testing(0);
- EXPECT_FALSE(cordz_should_profile());
- // 1 << 16 is from kIntervalIfDisabled in cordz_functions.cc.
- EXPECT_THAT(cordz_next_sample, Eq(1 << 16));
-
- set_cordz_mean_interval(orig_sample_rate);
-}
-
-TEST(CordzFunctionsTest, ShouldProfileAlways) {
- int32_t orig_sample_rate = get_cordz_mean_interval();
-
- set_cordz_mean_interval(1);
- cordz_set_next_sample_for_testing(1);
- EXPECT_TRUE(cordz_should_profile());
- EXPECT_THAT(cordz_next_sample, Le(1));
-
- set_cordz_mean_interval(orig_sample_rate);
-}
-
-TEST(CordzFunctionsTest, DoesNotAlwaysSampleFirstCord) {
- // Set large enough interval such that the chance of 'tons' of threads
- // randomly sampling the first call is infinitely small.
- set_cordz_mean_interval(10000);
- int tries = 0;
- bool sampled = false;
- do {
- ++tries;
- ASSERT_THAT(tries, Le(1000));
- std::thread thread([&sampled] {
- sampled = cordz_should_profile();
- });
- thread.join();
- } while (sampled);
-}
-
-TEST(CordzFunctionsTest, ShouldProfileRate) {
- static constexpr int kDesiredMeanInterval = 1000;
- static constexpr int kSamples = 10000;
- int32_t orig_sample_rate = get_cordz_mean_interval();
-
- set_cordz_mean_interval(kDesiredMeanInterval);
-
- int64_t sum_of_intervals = 0;
- for (int i = 0; i < kSamples; i++) {
- // Setting next_sample to 0 will force cordz_should_profile to generate a
- // new value for next_sample each iteration.
- cordz_set_next_sample_for_testing(0);
- cordz_should_profile();
- sum_of_intervals += cordz_next_sample;
- }
-
- // The sum of independent exponential variables is an Erlang distribution,
- // which is a gamma distribution where the shape parameter is equal to the
- // number of summands. The distribution used for cordz_should_profile is
- // actually floor(Exponential(1/mean)) which introduces bias. However, we can
- // apply the squint-really-hard correction factor. That is, when mean is
- // large, then if we squint really hard the shape of the distribution between
- // N and N+1 looks like a uniform distribution. On average, each value for
- // next_sample will be about 0.5 lower than we would expect from an
- // exponential distribution. This squint-really-hard correction approach won't
- // work when mean is smaller than about 10 but works fine when mean is 1000.
- //
- // We can use R to calculate a confidence interval. This
- // shows how to generate a confidence interval with a false positive rate of
- // one in a billion.
- //
- // $ R -q
- // > mean = 1000
- // > kSamples = 10000
- // > errorRate = 1e-9
- // > correction = -kSamples / 2
- // > low = qgamma(errorRate/2, kSamples, 1/mean) + correction
- // > high = qgamma(1 - errorRate/2, kSamples, 1/mean) + correction
- // > low
- // [1] 9396115
- // > high
- // [1] 10618100
- EXPECT_THAT(sum_of_intervals, Ge(9396115));
- EXPECT_THAT(sum_of_intervals, Le(10618100));
-
- set_cordz_mean_interval(orig_sample_rate);
-}
-
-#else // ABSL_INTERNAL_CORDZ_ENABLED
-
-TEST(CordzFunctionsTest, ShouldProfileDisabled) {
- int32_t orig_sample_rate = get_cordz_mean_interval();
-
- set_cordz_mean_interval(1);
- cordz_set_next_sample_for_testing(0);
- EXPECT_FALSE(cordz_should_profile());
-
- set_cordz_mean_interval(orig_sample_rate);
-}
-
-#endif // ABSL_INTERNAL_CORDZ_ENABLED
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc
deleted file mode 100644
index a73fefed59..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_handle.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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/strings/internal/cordz_handle.h"
-
-#include <atomic>
-
-#include "absl/base/internal/raw_logging.h" // For ABSL_RAW_CHECK
-#include "absl/base/internal/spinlock.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-using ::absl::base_internal::SpinLockHolder;
-
-ABSL_CONST_INIT CordzHandle::Queue CordzHandle::global_queue_(absl::kConstInit);
-
-CordzHandle::CordzHandle(bool is_snapshot) : is_snapshot_(is_snapshot) {
- if (is_snapshot) {
- SpinLockHolder lock(&queue_->mutex);
- CordzHandle* dq_tail = queue_->dq_tail.load(std::memory_order_acquire);
- if (dq_tail != nullptr) {
- dq_prev_ = dq_tail;
- dq_tail->dq_next_ = this;
- }
- queue_->dq_tail.store(this, std::memory_order_release);
- }
-}
-
-CordzHandle::~CordzHandle() {
- ODRCheck();
- if (is_snapshot_) {
- std::vector<CordzHandle*> to_delete;
- {
- SpinLockHolder lock(&queue_->mutex);
- CordzHandle* next = dq_next_;
- if (dq_prev_ == nullptr) {
- // We were head of the queue, delete every CordzHandle until we reach
- // either the end of the list, or a snapshot handle.
- while (next && !next->is_snapshot_) {
- to_delete.push_back(next);
- next = next->dq_next_;
- }
- } else {
- // Another CordzHandle existed before this one, don't delete anything.
- dq_prev_->dq_next_ = next;
- }
- if (next) {
- next->dq_prev_ = dq_prev_;
- } else {
- queue_->dq_tail.store(dq_prev_, std::memory_order_release);
- }
- }
- for (CordzHandle* handle : to_delete) {
- delete handle;
- }
- }
-}
-
-bool CordzHandle::SafeToDelete() const {
- return is_snapshot_ || queue_->IsEmpty();
-}
-
-void CordzHandle::Delete(CordzHandle* handle) {
- assert(handle);
- if (handle) {
- handle->ODRCheck();
- Queue* const queue = handle->queue_;
- if (!handle->SafeToDelete()) {
- SpinLockHolder lock(&queue->mutex);
- CordzHandle* dq_tail = queue->dq_tail.load(std::memory_order_acquire);
- if (dq_tail != nullptr) {
- handle->dq_prev_ = dq_tail;
- dq_tail->dq_next_ = handle;
- queue->dq_tail.store(handle, std::memory_order_release);
- return;
- }
- }
- delete handle;
- }
-}
-
-std::vector<const CordzHandle*> CordzHandle::DiagnosticsGetDeleteQueue() {
- std::vector<const CordzHandle*> handles;
- SpinLockHolder lock(&global_queue_.mutex);
- CordzHandle* dq_tail = global_queue_.dq_tail.load(std::memory_order_acquire);
- for (const CordzHandle* p = dq_tail; p; p = p->dq_prev_) {
- handles.push_back(p);
- }
- return handles;
-}
-
-bool CordzHandle::DiagnosticsHandleIsSafeToInspect(
- const CordzHandle* handle) const {
- ODRCheck();
- if (!is_snapshot_) return false;
- if (handle == nullptr) return true;
- if (handle->is_snapshot_) return false;
- bool snapshot_found = false;
- SpinLockHolder lock(&queue_->mutex);
- for (const CordzHandle* p = queue_->dq_tail; p; p = p->dq_prev_) {
- if (p == handle) return !snapshot_found;
- if (p == this) snapshot_found = true;
- }
- ABSL_ASSERT(snapshot_found); // Assert that 'this' is in delete queue.
- return true;
-}
-
-std::vector<const CordzHandle*>
-CordzHandle::DiagnosticsGetSafeToInspectDeletedHandles() {
- ODRCheck();
- std::vector<const CordzHandle*> handles;
- if (!is_snapshot()) {
- return handles;
- }
-
- SpinLockHolder lock(&queue_->mutex);
- for (const CordzHandle* p = dq_next_; p != nullptr; p = p->dq_next_) {
- if (!p->is_snapshot()) {
- handles.push_back(p);
- }
- }
- return handles;
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_handle.h b/third_party/abseil-cpp/absl/strings/internal/cordz_handle.h
deleted file mode 100644
index 5df53c782a..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_handle.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// 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_STRINGS_CORDZ_HANDLE_H_
-#define ABSL_STRINGS_CORDZ_HANDLE_H_
-
-#include <atomic>
-#include <vector>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/internal/spinlock.h"
-#include "absl/synchronization/mutex.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// This base class allows multiple types of object (CordzInfo and
-// CordzSampleToken) to exist simultaneously on the delete queue (pointed to by
-// global_dq_tail and traversed using dq_prev_ and dq_next_). The
-// delete queue guarantees that once a profiler creates a CordzSampleToken and
-// has gained visibility into a CordzInfo object, that CordzInfo object will not
-// be deleted prematurely. This allows the profiler to inspect all CordzInfo
-// objects that are alive without needing to hold a global lock.
-class CordzHandle {
- public:
- CordzHandle() : CordzHandle(false) {}
-
- bool is_snapshot() const { return is_snapshot_; }
-
- // Returns true if this instance is safe to be deleted because it is either a
- // snapshot, which is always safe to delete, or not included in the global
- // delete queue and thus not included in any snapshot.
- // Callers are responsible for making sure this instance can not be newly
- // discovered by other threads. For example, CordzInfo instances first de-list
- // themselves from the global CordzInfo list before determining if they are
- // safe to be deleted directly.
- // If SafeToDelete returns false, callers MUST use the Delete() method to
- // safely queue CordzHandle instances for deletion.
- bool SafeToDelete() const;
-
- // Deletes the provided instance, or puts it on the delete queue to be deleted
- // once there are no more sample tokens (snapshot) instances potentially
- // referencing the instance. `handle` should not be null.
- static void Delete(CordzHandle* handle);
-
- // Returns the current entries in the delete queue in LIFO order.
- static std::vector<const CordzHandle*> DiagnosticsGetDeleteQueue();
-
- // Returns true if the provided handle is nullptr or guarded by this handle.
- // Since the CordzSnapshot token is itself a CordzHandle, this method will
- // allow tests to check if that token is keeping an arbitrary CordzHandle
- // alive.
- bool DiagnosticsHandleIsSafeToInspect(const CordzHandle* handle) const;
-
- // Returns the current entries in the delete queue, in LIFO order, that are
- // protected by this. CordzHandle objects are only placed on the delete queue
- // after CordzHandle::Delete is called with them as an argument. Only
- // CordzHandle objects that are not also CordzSnapshot objects will be
- // included in the return vector. For each of the handles in the return
- // vector, the earliest that their memory can be freed is when this
- // CordzSnapshot object is deleted.
- std::vector<const CordzHandle*> DiagnosticsGetSafeToInspectDeletedHandles();
-
- protected:
- explicit CordzHandle(bool is_snapshot);
- virtual ~CordzHandle();
-
- private:
- // Global queue data. CordzHandle stores a pointer to the global queue
- // instance to harden against ODR violations.
- struct Queue {
- constexpr explicit Queue(absl::ConstInitType)
- : mutex(absl::kConstInit,
- absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL) {}
-
- absl::base_internal::SpinLock mutex;
- std::atomic<CordzHandle*> dq_tail ABSL_GUARDED_BY(mutex){nullptr};
-
- // Returns true if this delete queue is empty. This method does not acquire
- // the lock, but does a 'load acquire' observation on the delete queue tail.
- // It is used inside Delete() to check for the presence of a delete queue
- // without holding the lock. The assumption is that the caller is in the
- // state of 'being deleted', and can not be newly discovered by a concurrent
- // 'being constructed' snapshot instance. Practically, this means that any
- // such discovery (`find`, 'first' or 'next', etc) must have proper 'happens
- // before / after' semantics and atomic fences.
- bool IsEmpty() const ABSL_NO_THREAD_SAFETY_ANALYSIS {
- return dq_tail.load(std::memory_order_acquire) == nullptr;
- }
- };
-
- void ODRCheck() const {
-#ifndef NDEBUG
- ABSL_RAW_CHECK(queue_ == &global_queue_, "ODR violation in Cord");
-#endif
- }
-
- ABSL_CONST_INIT static Queue global_queue_;
- Queue* const queue_ = &global_queue_;
- const bool is_snapshot_;
-
- // dq_prev_ and dq_next_ require the global queue mutex to be held.
- // Unfortunately we can't use thread annotations such that the thread safety
- // analysis understands that queue_ and global_queue_ are one and the same.
- CordzHandle* dq_prev_ = nullptr;
- CordzHandle* dq_next_ = nullptr;
-};
-
-class CordzSnapshot : public CordzHandle {
- public:
- CordzSnapshot() : CordzHandle(true) {}
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORDZ_HANDLE_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_handle_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_handle_test.cc
deleted file mode 100644
index fd68e06b3e..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_handle_test.cc
+++ /dev/null
@@ -1,265 +0,0 @@
-// 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/strings/internal/cordz_handle.h"
-
-#include <random>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/memory/memory.h"
-#include "absl/synchronization/internal/thread_pool.h"
-#include "absl/synchronization/notification.h"
-#include "absl/time/clock.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::Gt;
-using ::testing::IsEmpty;
-using ::testing::SizeIs;
-
-// Local less verbose helper
-std::vector<const CordzHandle*> DeleteQueue() {
- return CordzHandle::DiagnosticsGetDeleteQueue();
-}
-
-struct CordzHandleDeleteTracker : public CordzHandle {
- bool* deleted;
- explicit CordzHandleDeleteTracker(bool* deleted) : deleted(deleted) {}
- ~CordzHandleDeleteTracker() override { *deleted = true; }
-};
-
-TEST(CordzHandleTest, DeleteQueueIsEmpty) {
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
-}
-
-TEST(CordzHandleTest, CordzHandleCreateDelete) {
- bool deleted = false;
- auto* handle = new CordzHandleDeleteTracker(&deleted);
- EXPECT_FALSE(handle->is_snapshot());
- EXPECT_TRUE(handle->SafeToDelete());
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
-
- CordzHandle::Delete(handle);
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
- EXPECT_TRUE(deleted);
-}
-
-TEST(CordzHandleTest, CordzSnapshotCreateDelete) {
- auto* snapshot = new CordzSnapshot();
- EXPECT_TRUE(snapshot->is_snapshot());
- EXPECT_TRUE(snapshot->SafeToDelete());
- EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot));
- delete snapshot;
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
-}
-
-TEST(CordzHandleTest, CordzHandleCreateDeleteWithSnapshot) {
- bool deleted = false;
- auto* snapshot = new CordzSnapshot();
- auto* handle = new CordzHandleDeleteTracker(&deleted);
- EXPECT_FALSE(handle->SafeToDelete());
-
- CordzHandle::Delete(handle);
- EXPECT_THAT(DeleteQueue(), ElementsAre(handle, snapshot));
- EXPECT_FALSE(deleted);
- EXPECT_FALSE(handle->SafeToDelete());
-
- delete snapshot;
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
- EXPECT_TRUE(deleted);
-}
-
-TEST(CordzHandleTest, MultiSnapshot) {
- bool deleted[3] = {false, false, false};
-
- CordzSnapshot* snapshot[3];
- CordzHandleDeleteTracker* handle[3];
- for (int i = 0; i < 3; ++i) {
- snapshot[i] = new CordzSnapshot();
- handle[i] = new CordzHandleDeleteTracker(&deleted[i]);
- CordzHandle::Delete(handle[i]);
- }
-
- EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2], handle[1],
- snapshot[1], handle[0], snapshot[0]));
- EXPECT_THAT(deleted, ElementsAre(false, false, false));
-
- delete snapshot[1];
- EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2], handle[1],
- handle[0], snapshot[0]));
- EXPECT_THAT(deleted, ElementsAre(false, false, false));
-
- delete snapshot[0];
- EXPECT_THAT(DeleteQueue(), ElementsAre(handle[2], snapshot[2]));
- EXPECT_THAT(deleted, ElementsAre(true, true, false));
-
- delete snapshot[2];
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
- EXPECT_THAT(deleted, ElementsAre(true, true, deleted));
-}
-
-TEST(CordzHandleTest, DiagnosticsHandleIsSafeToInspect) {
- CordzSnapshot snapshot1;
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(nullptr));
-
- auto* handle1 = new CordzHandle();
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));
-
- CordzHandle::Delete(handle1);
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));
-
- CordzSnapshot snapshot2;
- auto* handle2 = new CordzHandle();
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle2));
- EXPECT_FALSE(snapshot2.DiagnosticsHandleIsSafeToInspect(handle1));
- EXPECT_TRUE(snapshot2.DiagnosticsHandleIsSafeToInspect(handle2));
-
- CordzHandle::Delete(handle2);
- EXPECT_TRUE(snapshot1.DiagnosticsHandleIsSafeToInspect(handle1));
-}
-
-TEST(CordzHandleTest, DiagnosticsGetSafeToInspectDeletedHandles) {
- EXPECT_THAT(DeleteQueue(), IsEmpty());
-
- auto* handle = new CordzHandle();
- auto* snapshot1 = new CordzSnapshot();
-
- // snapshot1 should be able to see handle.
- EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot1));
- EXPECT_TRUE(snapshot1->DiagnosticsHandleIsSafeToInspect(handle));
- EXPECT_THAT(snapshot1->DiagnosticsGetSafeToInspectDeletedHandles(),
- IsEmpty());
-
- // This handle will be safe to inspect as long as snapshot1 is alive. However,
- // since only snapshot1 can prove that it's alive, it will be hidden from
- // snapshot2.
- CordzHandle::Delete(handle);
-
- // This snapshot shouldn't be able to see handle because handle was already
- // sent to Delete.
- auto* snapshot2 = new CordzSnapshot();
-
- // DeleteQueue elements are LIFO order.
- EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot2, handle, snapshot1));
-
- EXPECT_TRUE(snapshot1->DiagnosticsHandleIsSafeToInspect(handle));
- EXPECT_FALSE(snapshot2->DiagnosticsHandleIsSafeToInspect(handle));
-
- EXPECT_THAT(snapshot1->DiagnosticsGetSafeToInspectDeletedHandles(),
- ElementsAre(handle));
- EXPECT_THAT(snapshot2->DiagnosticsGetSafeToInspectDeletedHandles(),
- IsEmpty());
-
- CordzHandle::Delete(snapshot1);
- EXPECT_THAT(DeleteQueue(), ElementsAre(snapshot2));
-
- CordzHandle::Delete(snapshot2);
- EXPECT_THAT(DeleteQueue(), IsEmpty());
-}
-
-// Create and delete CordzHandle and CordzSnapshot objects in multiple threads
-// so that tsan has some time to chew on it and look for memory problems.
-TEST(CordzHandleTest, MultiThreaded) {
- Notification stop;
- static constexpr int kNumThreads = 4;
- // Keep the number of handles relatively small so that the test will naturally
- // transition to an empty delete queue during the test. If there are, say, 100
- // handles, that will virtually never happen. With 10 handles and around 50k
- // iterations in each of 4 threads, the delete queue appears to become empty
- // around 200 times.
- static constexpr int kNumHandles = 10;
-
- // Each thread is going to pick a random index and atomically swap its
- // CordzHandle with one in handles. This way, each thread can avoid
- // manipulating a CordzHandle that might be operated upon in another thread.
- std::vector<std::atomic<CordzHandle*>> handles(kNumHandles);
-
- // global bool which is set when any thread did get some 'safe to inspect'
- // handles. On some platforms and OSS tests, we might risk that some pool
- // threads are starved, stalled, or just got a few unlikely random 'handle'
- // coin tosses, so we satisfy this test with simply observing 'some' thread
- // did something meaningful, which should minimize the potential for flakes.
- std::atomic<bool> found_safe_to_inspect(false);
-
- {
- absl::synchronization_internal::ThreadPool pool(kNumThreads);
- for (int i = 0; i < kNumThreads; ++i) {
- pool.Schedule([&stop, &handles, &found_safe_to_inspect]() {
- std::minstd_rand gen;
- std::uniform_int_distribution<int> dist_type(0, 2);
- std::uniform_int_distribution<int> dist_handle(0, kNumHandles - 1);
-
- while (!stop.HasBeenNotified()) {
- CordzHandle* handle;
- switch (dist_type(gen)) {
- case 0:
- handle = new CordzHandle();
- break;
- case 1:
- handle = new CordzSnapshot();
- break;
- default:
- handle = nullptr;
- break;
- }
- CordzHandle* old_handle = handles[dist_handle(gen)].exchange(handle);
- if (old_handle != nullptr) {
- std::vector<const CordzHandle*> safe_to_inspect =
- old_handle->DiagnosticsGetSafeToInspectDeletedHandles();
- for (const CordzHandle* handle : safe_to_inspect) {
- // We're in a tight loop, so don't generate too many error
- // messages.
- ASSERT_FALSE(handle->is_snapshot());
- }
- if (!safe_to_inspect.empty()) {
- found_safe_to_inspect.store(true);
- }
- CordzHandle::Delete(old_handle);
- }
- }
-
- // Have each thread attempt to clean up everything. Some thread will be
- // the last to reach this cleanup code, and it will be guaranteed to
- // clean up everything because nothing remains to create new handles.
- for (auto& h : handles) {
- if (CordzHandle* handle = h.exchange(nullptr)) {
- CordzHandle::Delete(handle);
- }
- }
- });
- }
-
- // The threads will hammer away. Give it a little bit of time for tsan to
- // spot errors.
- absl::SleepFor(absl::Seconds(3));
- stop.Notify();
- }
-
- // Confirm that the test did *something*. This check will be satisfied as
- // long as any thread has deleted a CordzSnapshot object and a non-snapshot
- // CordzHandle was deleted after the CordzSnapshot was created.
- // See also comments on `found_safe_to_inspect`
- EXPECT_TRUE(found_safe_to_inspect.load());
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_info.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_info.cc
deleted file mode 100644
index 5c18bbc566..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_info.cc
+++ /dev/null
@@ -1,445 +0,0 @@
-// 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/strings/internal/cordz_info.h"
-
-#include "absl/base/config.h"
-#include "absl/base/internal/spinlock.h"
-#include "absl/container/inlined_vector.h"
-#include "absl/debugging/stacktrace.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_ring.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/types/span.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-using ::absl::base_internal::SpinLockHolder;
-
-constexpr int CordzInfo::kMaxStackDepth;
-
-ABSL_CONST_INIT CordzInfo::List CordzInfo::global_list_{absl::kConstInit};
-
-namespace {
-
-// CordRepAnalyzer performs the analysis of a cord.
-//
-// It computes absolute node counts and total memory usage, and an 'estimated
-// fair share memory usage` statistic.
-// Conceptually, it divides the 'memory usage' at each location in the 'cord
-// graph' by the cumulative reference count of that location. The cumulative
-// reference count is the factored total of all edges leading into that node.
-//
-// The top level node is treated specially: we assume the current thread
-// (typically called from the CordzHandler) to hold a reference purely to
-// perform a safe analysis, and not being part of the application. So we
-// substract 1 from the reference count of the top node to compute the
-// 'application fair share' excluding the reference of the current thread.
-//
-// An example of fair sharing, and why we multiply reference counts:
-// Assume we have 2 CordReps, both being a Substring referencing a Flat:
-// CordSubstring A (refcount = 5) --> child Flat C (refcount = 2)
-// CordSubstring B (refcount = 9) --> child Flat C (refcount = 2)
-//
-// Flat C has 2 incoming edges from the 2 substrings (refcount = 2) and is not
-// referenced directly anywhere else. Translated into a 'fair share', we then
-// attribute 50% of the memory (memory / refcount = 2) to each incoming edge.
-// Rep A has a refcount of 5, so we attribute each incoming edge 1 / 5th of the
-// memory cost below it, i.e.: the fair share of Rep A of the memory used by C
-// is then 'memory C / (refcount C * refcount A) + (memory A / refcount A)'.
-// It is also easy to see how all incoming edges add up to 100%.
-class CordRepAnalyzer {
- public:
- // Creates an analyzer instance binding to `statistics`.
- explicit CordRepAnalyzer(CordzStatistics& statistics)
- : statistics_(statistics) {}
-
- // Analyzes the memory statistics and node counts for the provided `rep`, and
- // adds the results to `statistics`. Note that node counts and memory sizes
- // are not initialized, computed values are added to any existing values.
- void AnalyzeCordRep(const CordRep* rep) {
- // Process all linear nodes.
- // As per the class comments, use refcout - 1 on the top level node, as the
- // top level node is assumed to be referenced only for analysis purposes.
- size_t refcount = rep->refcount.Get();
- RepRef repref{rep, (refcount > 1) ? refcount - 1 : 1};
-
- // Process all top level linear nodes (substrings and flats).
- repref = CountLinearReps(repref, memory_usage_);
-
- if (repref.rep != nullptr) {
- if (repref.rep->tag == RING) {
- AnalyzeRing(repref);
- } else if (repref.rep->tag == BTREE) {
- AnalyzeBtree(repref);
- } else if (repref.rep->tag == CONCAT) {
- AnalyzeConcat(repref);
- } else {
- // We should have either a concat, btree, or ring node if not null.
- assert(false);
- }
- }
-
- // Adds values to output
- statistics_.estimated_memory_usage += memory_usage_.total;
- statistics_.estimated_fair_share_memory_usage +=
- static_cast<size_t>(memory_usage_.fair_share);
- }
-
- private:
- // RepRef identifies a CordRep* inside the Cord tree with its cumulative
- // refcount including itself. For example, a tree consisting of a substring
- // with a refcount of 3 and a child flat with a refcount of 4 will have RepRef
- // refcounts of 3 and 12 respectively.
- struct RepRef {
- const CordRep* rep;
- size_t refcount;
-
- // Returns a 'child' RepRef which contains the cumulative reference count of
- // this instance multiplied by the child's reference count.
- RepRef Child(const CordRep* child) const {
- return RepRef{child, refcount * child->refcount.Get()};
- }
- };
-
- // Memory usage values
- struct MemoryUsage {
- size_t total = 0;
- double fair_share = 0.0;
-
- // Adds 'size` memory usage to this class, with a cumulative (recursive)
- // reference count of `refcount`
- void Add(size_t size, size_t refcount) {
- total += size;
- fair_share += static_cast<double>(size) / refcount;
- }
- };
-
- // Returns `rr` if `rr.rep` is not null and a CONCAT type.
- // Asserts that `rr.rep` is a concat node or null.
- static RepRef AssertConcat(RepRef repref) {
- const CordRep* rep = repref.rep;
- assert(rep == nullptr || rep->tag == CONCAT);
- return (rep != nullptr && rep->tag == CONCAT) ? repref : RepRef{nullptr, 0};
- }
-
- // Counts a flat of the provide allocated size
- void CountFlat(size_t size) {
- statistics_.node_count++;
- statistics_.node_counts.flat++;
- if (size <= 64) {
- statistics_.node_counts.flat_64++;
- } else if (size <= 128) {
- statistics_.node_counts.flat_128++;
- } else if (size <= 256) {
- statistics_.node_counts.flat_256++;
- } else if (size <= 512) {
- statistics_.node_counts.flat_512++;
- } else if (size <= 1024) {
- statistics_.node_counts.flat_1k++;
- }
- }
-
- // Processes 'linear' reps (substring, flat, external) not requiring iteration
- // or recursion. Returns RefRep{null} if all reps were processed, else returns
- // the top-most non-linear concat or ring cordrep.
- // Node counts are updated into `statistics_`, memory usage is update into
- // `memory_usage`, which typically references `memory_usage_` except for ring
- // buffers where we count children unrounded.
- RepRef CountLinearReps(RepRef rep, MemoryUsage& memory_usage) {
- // Consume all substrings
- while (rep.rep->tag == SUBSTRING) {
- statistics_.node_count++;
- statistics_.node_counts.substring++;
- memory_usage.Add(sizeof(CordRepSubstring), rep.refcount);
- rep = rep.Child(rep.rep->substring()->child);
- }
-
- // Consume possible FLAT
- if (rep.rep->tag >= FLAT) {
- size_t size = rep.rep->flat()->AllocatedSize();
- CountFlat(size);
- memory_usage.Add(size, rep.refcount);
- return RepRef{nullptr, 0};
- }
-
- // Consume possible external
- if (rep.rep->tag == EXTERNAL) {
- statistics_.node_count++;
- statistics_.node_counts.external++;
- size_t size = rep.rep->length + sizeof(CordRepExternalImpl<intptr_t>);
- memory_usage.Add(size, rep.refcount);
- return RepRef{nullptr, 0};
- }
-
- return rep;
- }
-
- // Analyzes the provided concat node in a flattened recursive way.
- void AnalyzeConcat(RepRef rep) {
- absl::InlinedVector<RepRef, 47> pending;
-
- while (rep.rep != nullptr) {
- const CordRepConcat* concat = rep.rep->concat();
- RepRef left = rep.Child(concat->left);
- RepRef right = rep.Child(concat->right);
-
- statistics_.node_count++;
- statistics_.node_counts.concat++;
- memory_usage_.Add(sizeof(CordRepConcat), rep.refcount);
-
- right = AssertConcat(CountLinearReps(right, memory_usage_));
- rep = AssertConcat(CountLinearReps(left, memory_usage_));
- if (rep.rep != nullptr) {
- if (right.rep != nullptr) {
- pending.push_back(right);
- }
- } else if (right.rep != nullptr) {
- rep = right;
- } else if (!pending.empty()) {
- rep = pending.back();
- pending.pop_back();
- }
- }
- }
-
- // Analyzes the provided ring.
- void AnalyzeRing(RepRef rep) {
- statistics_.node_count++;
- statistics_.node_counts.ring++;
- const CordRepRing* ring = rep.rep->ring();
- memory_usage_.Add(CordRepRing::AllocSize(ring->capacity()), rep.refcount);
- ring->ForEach([&](CordRepRing::index_type pos) {
- CountLinearReps(rep.Child(ring->entry_child(pos)), memory_usage_);
- });
- }
-
- // Analyzes the provided btree.
- void AnalyzeBtree(RepRef rep) {
- statistics_.node_count++;
- statistics_.node_counts.btree++;
- memory_usage_.Add(sizeof(CordRepBtree), rep.refcount);
- const CordRepBtree* tree = rep.rep->btree();
- if (tree->height() > 0) {
- for (CordRep* edge : tree->Edges()) {
- AnalyzeBtree(rep.Child(edge));
- }
- } else {
- for (CordRep* edge : tree->Edges()) {
- CountLinearReps(rep.Child(edge), memory_usage_);
- }
- }
- }
-
- CordzStatistics& statistics_;
- MemoryUsage memory_usage_;
-};
-
-} // namespace
-
-CordzInfo* CordzInfo::Head(const CordzSnapshot& snapshot) {
- ABSL_ASSERT(snapshot.is_snapshot());
-
- // We can do an 'unsafe' load of 'head', as we are guaranteed that the
- // instance it points to is kept alive by the provided CordzSnapshot, so we
- // can simply return the current value using an acquire load.
- // We do enforce in DEBUG builds that the 'head' value is present in the
- // delete queue: ODR violations may lead to 'snapshot' and 'global_list_'
- // being in different libraries / modules.
- CordzInfo* head = global_list_.head.load(std::memory_order_acquire);
- ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(head));
- return head;
-}
-
-CordzInfo* CordzInfo::Next(const CordzSnapshot& snapshot) const {
- ABSL_ASSERT(snapshot.is_snapshot());
-
- // Similar to the 'Head()' function, we do not need a mutex here.
- CordzInfo* next = ci_next_.load(std::memory_order_acquire);
- ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(this));
- ABSL_ASSERT(snapshot.DiagnosticsHandleIsSafeToInspect(next));
- return next;
-}
-
-void CordzInfo::TrackCord(InlineData& cord, MethodIdentifier method) {
- assert(cord.is_tree());
- assert(!cord.is_profiled());
- CordzInfo* cordz_info = new CordzInfo(cord.as_tree(), nullptr, method);
- cord.set_cordz_info(cordz_info);
- cordz_info->Track();
-}
-
-void CordzInfo::TrackCord(InlineData& cord, const InlineData& src,
- MethodIdentifier method) {
- assert(cord.is_tree());
- assert(src.is_tree());
-
- // Unsample current as we the current cord is being replaced with 'src',
- // so any method history is no longer relevant.
- CordzInfo* cordz_info = cord.cordz_info();
- if (cordz_info != nullptr) cordz_info->Untrack();
-
- // Start new cord sample
- cordz_info = new CordzInfo(cord.as_tree(), src.cordz_info(), method);
- cord.set_cordz_info(cordz_info);
- cordz_info->Track();
-}
-
-void CordzInfo::MaybeTrackCordImpl(InlineData& cord, const InlineData& src,
- MethodIdentifier method) {
- if (src.is_profiled()) {
- TrackCord(cord, src, method);
- } else if (cord.is_profiled()) {
- cord.cordz_info()->Untrack();
- cord.clear_cordz_info();
- }
-}
-
-CordzInfo::MethodIdentifier CordzInfo::GetParentMethod(const CordzInfo* src) {
- if (src == nullptr) return MethodIdentifier::kUnknown;
- return src->parent_method_ != MethodIdentifier::kUnknown ? src->parent_method_
- : src->method_;
-}
-
-int CordzInfo::FillParentStack(const CordzInfo* src, void** stack) {
- assert(stack);
- if (src == nullptr) return 0;
- if (src->parent_stack_depth_) {
- memcpy(stack, src->parent_stack_, src->parent_stack_depth_ * sizeof(void*));
- return src->parent_stack_depth_;
- }
- memcpy(stack, src->stack_, src->stack_depth_ * sizeof(void*));
- return src->stack_depth_;
-}
-
-CordzInfo::CordzInfo(CordRep* rep, const CordzInfo* src,
- MethodIdentifier method)
- : rep_(rep),
- stack_depth_(absl::GetStackTrace(stack_, /*max_depth=*/kMaxStackDepth,
- /*skip_count=*/1)),
- parent_stack_depth_(FillParentStack(src, parent_stack_)),
- method_(method),
- parent_method_(GetParentMethod(src)),
- create_time_(absl::Now()) {
- update_tracker_.LossyAdd(method);
- if (src) {
- // Copy parent counters.
- update_tracker_.LossyAdd(src->update_tracker_);
- }
-}
-
-CordzInfo::~CordzInfo() {
- // `rep_` is potentially kept alive if CordzInfo is included
- // in a collection snapshot (which should be rare).
- if (ABSL_PREDICT_FALSE(rep_)) {
- CordRep::Unref(rep_);
- }
-}
-
-void CordzInfo::Track() {
- SpinLockHolder l(&list_->mutex);
-
- CordzInfo* const head = list_->head.load(std::memory_order_acquire);
- if (head != nullptr) {
- head->ci_prev_.store(this, std::memory_order_release);
- }
- ci_next_.store(head, std::memory_order_release);
- list_->head.store(this, std::memory_order_release);
-}
-
-void CordzInfo::Untrack() {
- ODRCheck();
- {
- SpinLockHolder l(&list_->mutex);
-
- CordzInfo* const head = list_->head.load(std::memory_order_acquire);
- CordzInfo* const next = ci_next_.load(std::memory_order_acquire);
- CordzInfo* const prev = ci_prev_.load(std::memory_order_acquire);
-
- if (next) {
- ABSL_ASSERT(next->ci_prev_.load(std::memory_order_acquire) == this);
- next->ci_prev_.store(prev, std::memory_order_release);
- }
- if (prev) {
- ABSL_ASSERT(head != this);
- ABSL_ASSERT(prev->ci_next_.load(std::memory_order_acquire) == this);
- prev->ci_next_.store(next, std::memory_order_release);
- } else {
- ABSL_ASSERT(head == this);
- list_->head.store(next, std::memory_order_release);
- }
- }
-
- // We can no longer be discovered: perform a fast path check if we are not
- // listed on any delete queue, so we can directly delete this instance.
- if (SafeToDelete()) {
- UnsafeSetCordRep(nullptr);
- delete this;
- return;
- }
-
- // We are likely part of a snapshot, extend the life of the CordRep
- {
- absl::MutexLock lock(&mutex_);
- if (rep_) CordRep::Ref(rep_);
- }
- CordzHandle::Delete(this);
-}
-
-void CordzInfo::Lock(MethodIdentifier method)
- ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_) {
- mutex_.Lock();
- update_tracker_.LossyAdd(method);
- assert(rep_);
-}
-
-void CordzInfo::Unlock() ABSL_UNLOCK_FUNCTION(mutex_) {
- bool tracked = rep_ != nullptr;
- mutex_.Unlock();
- if (!tracked) {
- Untrack();
- }
-}
-
-absl::Span<void* const> CordzInfo::GetStack() const {
- return absl::MakeConstSpan(stack_, stack_depth_);
-}
-
-absl::Span<void* const> CordzInfo::GetParentStack() const {
- return absl::MakeConstSpan(parent_stack_, parent_stack_depth_);
-}
-
-CordzStatistics CordzInfo::GetCordzStatistics() const {
- CordzStatistics stats;
- stats.method = method_;
- stats.parent_method = parent_method_;
- stats.update_tracker = update_tracker_;
- if (CordRep* rep = RefCordRep()) {
- stats.size = rep->length;
- CordRepAnalyzer analyzer(stats);
- analyzer.AnalyzeCordRep(rep);
- CordRep::Unref(rep);
- }
- return stats;
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_info.h b/third_party/abseil-cpp/absl/strings/internal/cordz_info.h
deleted file mode 100644
index 026d5b9981..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_info.h
+++ /dev/null
@@ -1,298 +0,0 @@
-// 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_STRINGS_CORDZ_INFO_H_
-#define ABSL_STRINGS_CORDZ_INFO_H_
-
-#include <atomic>
-#include <cstdint>
-#include <functional>
-
-#include "absl/base/config.h"
-#include "absl/base/internal/raw_logging.h"
-#include "absl/base/internal/spinlock.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cordz_functions.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/synchronization/mutex.h"
-#include "absl/types/span.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordzInfo tracks a profiled Cord. Each of these objects can be in two places.
-// If a Cord is alive, the CordzInfo will be in the global_cordz_infos map, and
-// can also be retrieved via the linked list starting with
-// global_cordz_infos_head and continued via the cordz_info_next() method. When
-// a Cord has reached the end of its lifespan, the CordzInfo object will be
-// migrated out of the global_cordz_infos list and the global_cordz_infos_map,
-// and will either be deleted or appended to the global_delete_queue. If it is
-// placed on the global_delete_queue, the CordzInfo object will be cleaned in
-// the destructor of a CordzSampleToken object.
-class ABSL_LOCKABLE CordzInfo : public CordzHandle {
- public:
- using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
-
- // TrackCord creates a CordzInfo instance which tracks important metrics of
- // a sampled cord, and stores the created CordzInfo instance into `cord'. All
- // CordzInfo instances are placed in a global list which is used to discover
- // and snapshot all actively tracked cords. Callers are responsible for
- // calling UntrackCord() before the tracked Cord instance is deleted, or to
- // stop tracking the sampled Cord. Callers are also responsible for guarding
- // changes to the 'tree' value of a Cord (InlineData.tree) through the Lock()
- // and Unlock() calls. Any change resulting in a new tree value for the cord
- // requires a call to SetCordRep() before the old tree has been unreffed
- // and/or deleted. `method` identifies the Cord public API method initiating
- // the cord to be sampled.
- // Requires `cord` to hold a tree, and `cord.cordz_info()` to be null.
- static void TrackCord(InlineData& cord, MethodIdentifier method);
-
- // Identical to TrackCord(), except that this function fills the
- // `parent_stack` and `parent_method` properties of the returned CordzInfo
- // instance from the provided `src` instance if `src` is sampled.
- // This function should be used for sampling 'copy constructed' and 'copy
- // assigned' cords. This function allows 'cord` to be already sampled, in
- // which case the CordzInfo will be newly created from `src`.
- static void TrackCord(InlineData& cord, const InlineData& src,
- MethodIdentifier method);
-
- // Maybe sample the cord identified by 'cord' for method 'method'.
- // Uses `cordz_should_profile` to randomly pick cords to be sampled, and if
- // so, invokes `TrackCord` to start sampling `cord`.
- static void MaybeTrackCord(InlineData& cord, MethodIdentifier method);
-
- // Maybe sample the cord identified by 'cord' for method 'method'.
- // `src` identifies a 'parent' cord which is assigned to `cord`, typically the
- // input cord for a copy constructor, or an assign method such as `operator=`
- // `cord` will be sampled if (and only if) `src` is sampled.
- // If `cord` is currently being sampled and `src` is not being sampled, then
- // this function will stop sampling the cord and reset the cord's cordz_info.
- //
- // Previously this function defined that `cord` will be sampled if either
- // `src` is sampled, or if `cord` is randomly picked for sampling. However,
- // this can cause issues, as there may be paths where some cord is assigned an
- // indirect copy of it's own value. As such a 'string of copies' would then
- // remain sampled (`src.is_profiled`), then assigning such a cord back to
- // 'itself' creates a cycle where the cord will converge to 'always sampled`.
- //
- // For example:
- //
- // Cord x;
- // for (...) {
- // // Copy ctor --> y.is_profiled := x.is_profiled | random(...)
- // Cord y = x;
- // ...
- // // Assign x = y --> x.is_profiled = y.is_profiled | random(...)
- // // ==> x.is_profiled |= random(...)
- // // ==> x converges to 'always profiled'
- // x = y;
- // }
- static void MaybeTrackCord(InlineData& cord, const InlineData& src,
- MethodIdentifier method);
-
- // Stops tracking changes for a sampled cord, and deletes the provided info.
- // This function must be called before the sampled cord instance is deleted,
- // and before the root cordrep of the sampled cord is unreffed.
- // This function may extend the lifetime of the cordrep in cases where the
- // CordInfo instance is being held by a concurrent collection thread.
- void Untrack();
-
- // Invokes UntrackCord() on `info` if `info` is not null.
- static void MaybeUntrackCord(CordzInfo* info);
-
- CordzInfo() = delete;
- CordzInfo(const CordzInfo&) = delete;
- CordzInfo& operator=(const CordzInfo&) = delete;
-
- // Retrieves the oldest existing CordzInfo.
- static CordzInfo* Head(const CordzSnapshot& snapshot)
- ABSL_NO_THREAD_SAFETY_ANALYSIS;
-
- // Retrieves the next oldest existing CordzInfo older than 'this' instance.
- CordzInfo* Next(const CordzSnapshot& snapshot) const
- ABSL_NO_THREAD_SAFETY_ANALYSIS;
-
- // Locks this instance for the update identified by `method`.
- // Increases the count for `method` in `update_tracker`.
- void Lock(MethodIdentifier method) ABSL_EXCLUSIVE_LOCK_FUNCTION(mutex_);
-
- // Unlocks this instance. If the contained `rep` has been set to null
- // indicating the Cord has been cleared or is otherwise no longer sampled,
- // then this method will delete this CordzInfo instance.
- void Unlock() ABSL_UNLOCK_FUNCTION(mutex_);
-
- // Asserts that this CordzInfo instance is locked.
- void AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_);
-
- // Updates the `rep` property of this instance. This methods is invoked by
- // Cord logic each time the root node of a sampled Cord changes, and before
- // the old root reference count is deleted. This guarantees that collection
- // code can always safely take a reference on the tracked cord.
- // Requires a lock to be held through the `Lock()` method.
- // TODO(b/117940323): annotate with ABSL_EXCLUSIVE_LOCKS_REQUIRED once all
- // Cord code is in a state where this can be proven true by the compiler.
- void SetCordRep(CordRep* rep);
-
- // Returns the current `rep` property of this instance with a reference
- // added, or null if this instance represents a cord that has since been
- // deleted or untracked.
- CordRep* RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_);
-
- // Returns the current value of `rep_` for testing purposes only.
- CordRep* GetCordRepForTesting() const ABSL_NO_THREAD_SAFETY_ANALYSIS {
- return rep_;
- }
-
- // Sets the current value of `rep_` for testing purposes only.
- void SetCordRepForTesting(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS {
- rep_ = rep;
- }
-
- // Returns the stack trace for where the cord was first sampled. Cords are
- // potentially sampled when they promote from an inlined cord to a tree or
- // ring representation, which is not necessarily the location where the cord
- // was first created. Some cords are created as inlined cords, and only as
- // data is added do they become a non-inlined cord. However, typically the
- // location represents reasonably well where the cord is 'created'.
- absl::Span<void* const> GetStack() const;
-
- // Returns the stack trace for a sampled cord's 'parent stack trace'. This
- // value may be set if the cord is sampled (promoted) after being created
- // from, or being assigned the value of an existing (sampled) cord.
- absl::Span<void* const> GetParentStack() const;
-
- // Retrieves the CordzStatistics associated with this Cord. The statistics
- // are only updated when a Cord goes through a mutation, such as an Append
- // or RemovePrefix.
- CordzStatistics GetCordzStatistics() const;
-
- private:
- using SpinLock = absl::base_internal::SpinLock;
- using SpinLockHolder = ::absl::base_internal::SpinLockHolder;
-
- // Global cordz info list. CordzInfo stores a pointer to the global list
- // instance to harden against ODR violations.
- struct List {
- constexpr explicit List(absl::ConstInitType)
- : mutex(absl::kConstInit,
- absl::base_internal::SCHEDULE_COOPERATIVE_AND_KERNEL) {}
-
- SpinLock mutex;
- std::atomic<CordzInfo*> head ABSL_GUARDED_BY(mutex){nullptr};
- };
-
- static constexpr int kMaxStackDepth = 64;
-
- explicit CordzInfo(CordRep* rep, const CordzInfo* src,
- MethodIdentifier method);
- ~CordzInfo() override;
-
- // Sets `rep_` without holding a lock.
- void UnsafeSetCordRep(CordRep* rep) ABSL_NO_THREAD_SAFETY_ANALYSIS;
-
- void Track();
-
- // Returns the parent method from `src`, which is either `parent_method_` or
- // `method_` depending on `parent_method_` being kUnknown.
- // Returns kUnknown if `src` is null.
- static MethodIdentifier GetParentMethod(const CordzInfo* src);
-
- // Fills the provided stack from `src`, copying either `parent_stack_` or
- // `stack_` depending on `parent_stack_` being empty, returning the size of
- // the parent stack.
- // Returns 0 if `src` is null.
- static int FillParentStack(const CordzInfo* src, void** stack);
-
- void ODRCheck() const {
-#ifndef NDEBUG
- ABSL_RAW_CHECK(list_ == &global_list_, "ODR violation in Cord");
-#endif
- }
-
- // Non-inlined implementation of `MaybeTrackCord`, which is executed if
- // either `src` is sampled or `cord` is sampled, and either untracks or
- // tracks `cord` as documented per `MaybeTrackCord`.
- static void MaybeTrackCordImpl(InlineData& cord, const InlineData& src,
- MethodIdentifier method);
-
- ABSL_CONST_INIT static List global_list_;
- List* const list_ = &global_list_;
-
- // ci_prev_ and ci_next_ require the global list mutex to be held.
- // Unfortunately we can't use thread annotations such that the thread safety
- // analysis understands that list_ and global_list_ are one and the same.
- std::atomic<CordzInfo*> ci_prev_{nullptr};
- std::atomic<CordzInfo*> ci_next_{nullptr};
-
- mutable absl::Mutex mutex_;
- CordRep* rep_ ABSL_GUARDED_BY(mutex_);
-
- void* stack_[kMaxStackDepth];
- void* parent_stack_[kMaxStackDepth];
- const int stack_depth_;
- const int parent_stack_depth_;
- const MethodIdentifier method_;
- const MethodIdentifier parent_method_;
- CordzUpdateTracker update_tracker_;
- const absl::Time create_time_;
-};
-
-inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(
- InlineData& cord, MethodIdentifier method) {
- if (ABSL_PREDICT_FALSE(cordz_should_profile())) {
- TrackCord(cord, method);
- }
-}
-
-inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeTrackCord(
- InlineData& cord, const InlineData& src, MethodIdentifier method) {
- if (ABSL_PREDICT_FALSE(InlineData::is_either_profiled(cord, src))) {
- MaybeTrackCordImpl(cord, src, method);
- }
-}
-
-inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CordzInfo::MaybeUntrackCord(
- CordzInfo* info) {
- if (ABSL_PREDICT_FALSE(info)) {
- info->Untrack();
- }
-}
-
-inline void CordzInfo::AssertHeld() ABSL_ASSERT_EXCLUSIVE_LOCK(mutex_) {
-#ifndef NDEBUG
- mutex_.AssertHeld();
-#endif
-}
-
-inline void CordzInfo::SetCordRep(CordRep* rep) {
- AssertHeld();
- rep_ = rep;
-}
-
-inline void CordzInfo::UnsafeSetCordRep(CordRep* rep) { rep_ = rep; }
-
-inline CordRep* CordzInfo::RefCordRep() const ABSL_LOCKS_EXCLUDED(mutex_) {
- MutexLock lock(&mutex_);
- return rep_ ? CordRep::Ref(rep_) : nullptr;
-}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORDZ_INFO_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_info_statistics_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_info_statistics_test.cc
deleted file mode 100644
index 7430d281ca..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_info_statistics_test.cc
+++ /dev/null
@@ -1,625 +0,0 @@
-// 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 <iostream>
-#include <random>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/strings/cord.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cord_rep_btree.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/internal/cord_rep_ring.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_sample_token.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_scope.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/synchronization/internal/thread_pool.h"
-#include "absl/synchronization/notification.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// Do not print statistics contents, the matcher prints them as needed.
-inline void PrintTo(const CordzStatistics& stats, std::ostream* s) {
- if (s) *s << "CordzStatistics{...}";
-}
-
-namespace {
-
-using ::testing::Ge;
-
-// Creates a flat of the specified allocated size
-CordRepFlat* Flat(size_t size) {
- // Round up to a tag size, as we are going to poke an exact tag size back into
- // the allocated flat. 'size returning allocators' could grant us more than we
- // wanted, but we are ok to poke the 'requested' size in the tag, even in the
- // presence of sized deletes, so we need to make sure the size rounds
- // perfectly to a tag value.
- assert(size >= kMinFlatSize);
- size = RoundUpForTag(size);
- CordRepFlat* flat = CordRepFlat::New(size - kFlatOverhead);
- flat->tag = AllocatedSizeToTag(size);
- flat->length = size - kFlatOverhead;
- return flat;
-}
-
-// Creates an external of the specified length
-CordRepExternal* External(int length = 512) {
- return static_cast<CordRepExternal*>(
- NewExternalRep(absl::string_view("", length), [](absl::string_view) {}));
-}
-
-// Creates a substring on the provided rep of length - 1
-CordRepSubstring* Substring(CordRep* rep) {
- auto* substring = new CordRepSubstring;
- substring->length = rep->length - 1;
- substring->tag = SUBSTRING;
- substring->child = rep;
- return substring;
-}
-
-// Creates a concat on the provided reps
-CordRepConcat* Concat(CordRep* left, CordRep* right) {
- auto* concat = new CordRepConcat;
- concat->length = left->length + right->length;
- concat->tag = CONCAT;
- concat->left = left;
- concat->right = right;
- return concat;
-}
-
-// Reference count helper
-struct RefHelper {
- std::vector<CordRep*> refs;
-
- ~RefHelper() {
- for (CordRep* rep : refs) {
- CordRep::Unref(rep);
- }
- }
-
- // Invokes CordRep::Unref() on `rep` when this instance is destroyed.
- template <typename T>
- T* NeedsUnref(T* rep) {
- refs.push_back(rep);
- return rep;
- }
-
- // Adds `n` reference counts to `rep` which will be unreffed when this
- // instance is destroyed.
- template <typename T>
- T* Ref(T* rep, size_t n = 1) {
- while (n--) {
- NeedsUnref(CordRep::Ref(rep));
- }
- return rep;
- }
-};
-
-// Sizeof helper. Returns the allocated size of `p`, excluding any child
-// elements for substring, concat and ring cord reps.
-template <typename T>
-size_t SizeOf(const T* rep) {
- return sizeof(T);
-}
-
-template <>
-size_t SizeOf(const CordRepFlat* rep) {
- return rep->AllocatedSize();
-}
-
-template <>
-size_t SizeOf(const CordRepExternal* rep) {
- // See cord.cc
- return sizeof(CordRepExternalImpl<intptr_t>) + rep->length;
-}
-
-template <>
-size_t SizeOf(const CordRepRing* rep) {
- return CordRepRing::AllocSize(rep->capacity());
-}
-
-// Computes fair share memory used in a naive 'we dare to recurse' way.
-double FairShareImpl(CordRep* rep, size_t ref) {
- double self = 0.0, children = 0.0;
- ref *= rep->refcount.Get();
- if (rep->tag >= FLAT) {
- self = SizeOf(rep->flat());
- } else if (rep->tag == EXTERNAL) {
- self = SizeOf(rep->external());
- } else if (rep->tag == SUBSTRING) {
- self = SizeOf(rep->substring());
- children = FairShareImpl(rep->substring()->child, ref);
- } else if (rep->tag == BTREE) {
- self = SizeOf(rep->btree());
- for (CordRep*edge : rep->btree()->Edges()) {
- children += FairShareImpl(edge, ref);
- }
- } else if (rep->tag == RING) {
- self = SizeOf(rep->ring());
- rep->ring()->ForEach([&](CordRepRing::index_type i) {
- self += FairShareImpl(rep->ring()->entry_child(i), 1);
- });
- } else if (rep->tag == CONCAT) {
- self = SizeOf(rep->concat());
- children = FairShareImpl(rep->concat()->left, ref) +
- FairShareImpl(rep->concat()->right, ref);
- } else {
- assert(false);
- }
- return self / ref + children;
-}
-
-// Returns the fair share memory size from `ShareFhareImpl()` as a size_t.
-size_t FairShare(CordRep* rep, size_t ref = 1) {
- return static_cast<size_t>(FairShareImpl(rep, ref));
-}
-
-// Samples the cord and returns CordzInfo::GetStatistics()
-CordzStatistics SampleCord(CordRep* rep) {
- InlineData cord(rep);
- CordzInfo::TrackCord(cord, CordzUpdateTracker::kUnknown);
- CordzStatistics stats = cord.cordz_info()->GetCordzStatistics();
- cord.cordz_info()->Untrack();
- return stats;
-}
-
-MATCHER_P(EqStatistics, stats, "Statistics equal expected values") {
- bool ok = true;
-
-#define STATS_MATCHER_EXPECT_EQ(member) \
- if (stats.member != arg.member) { \
- *result_listener << "\n stats." << #member \
- << ": actual = " << arg.member << ", expected " \
- << stats.member; \
- ok = false; \
- }
-
- STATS_MATCHER_EXPECT_EQ(size);
- STATS_MATCHER_EXPECT_EQ(node_count);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat_64);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat_128);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat_256);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat_512);
- STATS_MATCHER_EXPECT_EQ(node_counts.flat_1k);
- STATS_MATCHER_EXPECT_EQ(node_counts.external);
- STATS_MATCHER_EXPECT_EQ(node_counts.concat);
- STATS_MATCHER_EXPECT_EQ(node_counts.substring);
- STATS_MATCHER_EXPECT_EQ(node_counts.ring);
- STATS_MATCHER_EXPECT_EQ(node_counts.btree);
- STATS_MATCHER_EXPECT_EQ(estimated_memory_usage);
- STATS_MATCHER_EXPECT_EQ(estimated_fair_share_memory_usage);
-
-#undef STATS_MATCHER_EXPECT_EQ
-
- return ok;
-}
-
-TEST(CordzInfoStatisticsTest, Flat) {
- RefHelper ref;
- auto* flat = ref.NeedsUnref(Flat(512));
-
- CordzStatistics expected;
- expected.size = flat->length;
- expected.estimated_memory_usage = SizeOf(flat);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
- expected.node_count = 1;
- expected.node_counts.flat = 1;
- expected.node_counts.flat_512 = 1;
-
- EXPECT_THAT(SampleCord(flat), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, SharedFlat) {
- RefHelper ref;
- auto* flat = ref.Ref(ref.NeedsUnref(Flat(64)));
-
- CordzStatistics expected;
- expected.size = flat->length;
- expected.estimated_memory_usage = SizeOf(flat);
- expected.estimated_fair_share_memory_usage = SizeOf(flat) / 2;
- expected.node_count = 1;
- expected.node_counts.flat = 1;
- expected.node_counts.flat_64 = 1;
-
- EXPECT_THAT(SampleCord(flat), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, External) {
- RefHelper ref;
- auto* external = ref.NeedsUnref(External());
-
- CordzStatistics expected;
- expected.size = external->length;
- expected.estimated_memory_usage = SizeOf(external);
- expected.estimated_fair_share_memory_usage = SizeOf(external);
- expected.node_count = 1;
- expected.node_counts.external = 1;
-
- EXPECT_THAT(SampleCord(external), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, SharedExternal) {
- RefHelper ref;
- auto* external = ref.Ref(ref.NeedsUnref(External()));
-
- CordzStatistics expected;
- expected.size = external->length;
- expected.estimated_memory_usage = SizeOf(external);
- expected.estimated_fair_share_memory_usage = SizeOf(external) / 2;
- expected.node_count = 1;
- expected.node_counts.external = 1;
-
- EXPECT_THAT(SampleCord(external), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, Substring) {
- RefHelper ref;
- auto* flat = Flat(1024);
- auto* substring = ref.NeedsUnref(Substring(flat));
-
- CordzStatistics expected;
- expected.size = substring->length;
- expected.estimated_memory_usage = SizeOf(substring) + SizeOf(flat);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
- expected.node_count = 2;
- expected.node_counts.flat = 1;
- expected.node_counts.flat_1k = 1;
- expected.node_counts.substring = 1;
-
- EXPECT_THAT(SampleCord(substring), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, SharedSubstring) {
- RefHelper ref;
- auto* flat = ref.Ref(Flat(511), 2);
- auto* substring = ref.Ref(ref.NeedsUnref(Substring(flat)));
-
- CordzStatistics expected;
- expected.size = substring->length;
- expected.estimated_memory_usage = SizeOf(flat) + SizeOf(substring);
- expected.estimated_fair_share_memory_usage =
- SizeOf(substring) / 2 + SizeOf(flat) / 6;
- expected.node_count = 2;
- expected.node_counts.flat = 1;
- expected.node_counts.flat_512 = 1;
- expected.node_counts.substring = 1;
-
- EXPECT_THAT(SampleCord(substring), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, Concat) {
- RefHelper ref;
- auto* flat1 = Flat(300);
- auto* flat2 = Flat(2000);
- auto* concat = ref.NeedsUnref(Concat(flat1, flat2));
-
- CordzStatistics expected;
- expected.size = concat->length;
- expected.estimated_memory_usage =
- SizeOf(concat) + SizeOf(flat1) + SizeOf(flat2);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
- expected.node_count = 3;
- expected.node_counts.flat = 2;
- expected.node_counts.flat_512 = 1;
- expected.node_counts.concat = 1;
-
- EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, DeepConcat) {
- RefHelper ref;
- auto* flat1 = Flat(300);
- auto* flat2 = Flat(2000);
- auto* flat3 = Flat(400);
- auto* external = External(3000);
- auto* substring = Substring(external);
- auto* concat1 = Concat(flat1, flat2);
- auto* concat2 = Concat(flat3, substring);
- auto* concat = ref.NeedsUnref(Concat(concat1, concat2));
-
- CordzStatistics expected;
- expected.size = concat->length;
- expected.estimated_memory_usage = SizeOf(concat) * 3 + SizeOf(flat1) +
- SizeOf(flat2) + SizeOf(flat3) +
- SizeOf(external) + SizeOf(substring);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
-
- expected.node_count = 8;
- expected.node_counts.flat = 3;
- expected.node_counts.flat_512 = 2;
- expected.node_counts.external = 1;
- expected.node_counts.concat = 3;
- expected.node_counts.substring = 1;
-
- EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, DeepSharedConcat) {
- RefHelper ref;
- auto* flat1 = Flat(40);
- auto* flat2 = ref.Ref(Flat(2000), 4);
- auto* flat3 = Flat(70);
- auto* external = ref.Ref(External(3000));
- auto* substring = ref.Ref(Substring(external), 3);
- auto* concat1 = Concat(flat1, flat2);
- auto* concat2 = Concat(flat3, substring);
- auto* concat = ref.Ref(ref.NeedsUnref(Concat(concat1, concat2)));
-
- CordzStatistics expected;
- expected.size = concat->length;
- expected.estimated_memory_usage = SizeOf(concat) * 3 + SizeOf(flat1) +
- SizeOf(flat2) + SizeOf(flat3) +
- SizeOf(external) + SizeOf(substring);
- expected.estimated_fair_share_memory_usage = FairShare(concat);
- expected.node_count = 8;
- expected.node_counts.flat = 3;
- expected.node_counts.flat_64 = 1;
- expected.node_counts.flat_128 = 1;
- expected.node_counts.external = 1;
- expected.node_counts.concat = 3;
- expected.node_counts.substring = 1;
-
- EXPECT_THAT(SampleCord(concat), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, Ring) {
- RefHelper ref;
- auto* flat1 = Flat(240);
- auto* flat2 = Flat(2000);
- auto* flat3 = Flat(70);
- auto* external = External(3000);
- CordRepRing* ring = CordRepRing::Create(flat1);
- ring = CordRepRing::Append(ring, flat2);
- ring = CordRepRing::Append(ring, flat3);
- ring = ref.NeedsUnref(CordRepRing::Append(ring, external));
-
- CordzStatistics expected;
- expected.size = ring->length;
- expected.estimated_memory_usage = SizeOf(ring) + SizeOf(flat1) +
- SizeOf(flat2) + SizeOf(flat3) +
- SizeOf(external);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
- expected.node_count = 5;
- expected.node_counts.flat = 3;
- expected.node_counts.flat_128 = 1;
- expected.node_counts.flat_256 = 1;
- expected.node_counts.external = 1;
- expected.node_counts.ring = 1;
-
- EXPECT_THAT(SampleCord(ring), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, SharedSubstringRing) {
- RefHelper ref;
- auto* flat1 = ref.Ref(Flat(240));
- auto* flat2 = Flat(200);
- auto* flat3 = Flat(70);
- auto* external = ref.Ref(External(3000), 5);
- CordRepRing* ring = CordRepRing::Create(flat1);
- ring = CordRepRing::Append(ring, flat2);
- ring = CordRepRing::Append(ring, flat3);
- ring = ref.Ref(CordRepRing::Append(ring, external), 4);
- auto* substring = ref.Ref(ref.NeedsUnref(Substring(ring)));
-
-
- CordzStatistics expected;
- expected.size = substring->length;
- expected.estimated_memory_usage = SizeOf(ring) + SizeOf(flat1) +
- SizeOf(flat2) + SizeOf(flat3) +
- SizeOf(external) + SizeOf(substring);
- expected.estimated_fair_share_memory_usage = FairShare(substring);
- expected.node_count = 6;
- expected.node_counts.flat = 3;
- expected.node_counts.flat_128 = 1;
- expected.node_counts.flat_256 = 2;
- expected.node_counts.external = 1;
- expected.node_counts.ring = 1;
- expected.node_counts.substring = 1;
-
- EXPECT_THAT(SampleCord(substring), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, BtreeLeaf) {
- ASSERT_THAT(CordRepBtree::kMaxCapacity, Ge(3));
- RefHelper ref;
- auto* flat1 = Flat(2000);
- auto* flat2 = Flat(200);
- auto* substr = Substring(flat2);
- auto* external = External(3000);
-
- CordRepBtree* tree = CordRepBtree::Create(flat1);
- tree = CordRepBtree::Append(tree, substr);
- tree = CordRepBtree::Append(tree, external);
- size_t flat3_count = CordRepBtree::kMaxCapacity - 3;
- size_t flat3_size = 0;
- for (size_t i = 0; i < flat3_count; ++i) {
- auto* flat3 = Flat(70);
- flat3_size += SizeOf(flat3);
- tree = CordRepBtree::Append(tree, flat3);
- }
- ref.NeedsUnref(tree);
-
- CordzStatistics expected;
- expected.size = tree->length;
- expected.estimated_memory_usage = SizeOf(tree) + SizeOf(flat1) +
- SizeOf(flat2) + SizeOf(substr) +
- flat3_size + SizeOf(external);
- expected.estimated_fair_share_memory_usage = expected.estimated_memory_usage;
- expected.node_count = 1 + 3 + 1 + flat3_count;
- expected.node_counts.flat = 2 + flat3_count;
- expected.node_counts.flat_128 = flat3_count;
- expected.node_counts.flat_256 = 1;
- expected.node_counts.external = 1;
- expected.node_counts.substring = 1;
- expected.node_counts.btree = 1;
-
- EXPECT_THAT(SampleCord(tree), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, BtreeNodeShared) {
- RefHelper ref;
- static constexpr int leaf_count = 3;
- const size_t flat3_count = CordRepBtree::kMaxCapacity - 3;
- ASSERT_THAT(flat3_count, Ge(0));
-
- CordRepBtree* tree = nullptr;
- size_t mem_size = 0;
- for (int i = 0; i < leaf_count; ++i) {
- auto* flat1 = ref.Ref(Flat(2000), 9);
- mem_size += SizeOf(flat1);
- if (i == 0) {
- tree = CordRepBtree::Create(flat1);
- } else {
- tree = CordRepBtree::Append(tree, flat1);
- }
-
- auto* flat2 = Flat(200);
- auto* substr = Substring(flat2);
- mem_size += SizeOf(flat2) + SizeOf(substr);
- tree = CordRepBtree::Append(tree, substr);
-
- auto* external = External(30);
- mem_size += SizeOf(external);
- tree = CordRepBtree::Append(tree, external);
-
- for (size_t i = 0; i < flat3_count; ++i) {
- auto* flat3 = Flat(70);
- mem_size += SizeOf(flat3);
- tree = CordRepBtree::Append(tree, flat3);
- }
-
- if (i == 0) {
- mem_size += SizeOf(tree);
- } else {
- mem_size += SizeOf(tree->Edges().back()->btree());
- }
- }
- ref.NeedsUnref(tree);
-
- // Ref count: 2 for top (add 1), 5 for leaf 0 (add 4).
- ref.Ref(tree, 1);
- ref.Ref(tree->Edges().front(), 4);
-
- CordzStatistics expected;
- expected.size = tree->length;
- expected.estimated_memory_usage = SizeOf(tree) + mem_size;
- expected.estimated_fair_share_memory_usage = FairShare(tree);
-
- expected.node_count = 1 + leaf_count * (1 + 3 + 1 + flat3_count);
- expected.node_counts.flat = leaf_count * (2 + flat3_count);
- expected.node_counts.flat_128 = leaf_count * flat3_count;
- expected.node_counts.flat_256 = leaf_count;
- expected.node_counts.external = leaf_count;
- expected.node_counts.substring = leaf_count;
- expected.node_counts.btree = 1 + leaf_count;
-
- EXPECT_THAT(SampleCord(tree), EqStatistics(expected));
-}
-
-TEST(CordzInfoStatisticsTest, ThreadSafety) {
- Notification stop;
- static constexpr int kNumThreads = 8;
- int64_t sampled_node_count = 0;
-
- {
- absl::synchronization_internal::ThreadPool pool(kNumThreads);
-
- // Run analyzer thread emulating a CordzHandler collection.
- pool.Schedule([&]() {
- while (!stop.HasBeenNotified()) {
- // Run every 10us (about 100K total collections).
- absl::SleepFor(absl::Microseconds(10));
- CordzSampleToken token;
- for (const CordzInfo& cord_info : token) {
- CordzStatistics stats = cord_info.GetCordzStatistics();
- sampled_node_count += stats.node_count;
- }
- }
- });
-
- // Run 'application threads'
- for (int i = 0; i < kNumThreads; ++i) {
- pool.Schedule([&]() {
- // Track 0 - 2 cordz infos at a time, providing permutations of 0, 1
- // and 2 CordzHandle and CordzInfo queues being active, with plenty of
- // 'empty to non empty' transitions.
- InlineData cords[2];
- std::minstd_rand gen;
- std::uniform_int_distribution<int> coin_toss(0, 1);
-
- while (!stop.HasBeenNotified()) {
- for (InlineData& cord : cords) {
- // 50/50 flip the state of the cord
- if (coin_toss(gen) != 0) {
- if (cord.is_tree()) {
- // 50/50 simulate delete (untrack) or 'edit to empty'
- if (coin_toss(gen) != 0) {
- CordzInfo::MaybeUntrackCord(cord.cordz_info());
- } else {
- CordzUpdateScope scope(cord.cordz_info(),
- CordzUpdateTracker::kUnknown);
- scope.SetCordRep(nullptr);
- }
- CordRep::Unref(cord.as_tree());
- cord.set_inline_size(0);
- } else {
- // Coin toss to 25% ring, 25% btree, and 50% flat.
- CordRep* rep = Flat(256);
- if (coin_toss(gen) != 0) {
- if (coin_toss(gen) != 0) {
- rep = CordRepRing::Create(rep);
- } else {
- rep = CordRepBtree::Create(rep);
- }
- }
- cord.make_tree(rep);
-
- // 50/50 sample
- if (coin_toss(gen) != 0) {
- CordzInfo::TrackCord(cord, CordzUpdateTracker::kUnknown);
- }
- }
- }
- }
- }
- for (InlineData& cord : cords) {
- if (cord.is_tree()) {
- CordzInfo::MaybeUntrackCord(cord.cordz_info());
- CordRep::Unref(cord.as_tree());
- }
- }
- });
- }
-
- // Run for 1 second to give memory and thread safety analyzers plenty of
- // time to detect any mishaps or undefined behaviors.
- absl::SleepFor(absl::Seconds(1));
- stop.Notify();
- }
-
- std::cout << "Sampled " << sampled_node_count << " nodes\n";
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_info_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_info_test.cc
deleted file mode 100644
index b98343ae79..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_info_test.cc
+++ /dev/null
@@ -1,341 +0,0 @@
-// 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/strings/internal/cordz_info.h"
-
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/debugging/stacktrace.h"
-#include "absl/debugging/symbolize.h"
-#include "absl/strings/cordz_test_helpers.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_statistics.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/str_cat.h"
-#include "absl/types/span.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::HasSubstr;
-using ::testing::Ne;
-using ::testing::SizeIs;
-
-// Used test values
-auto constexpr kUnknownMethod = CordzUpdateTracker::kUnknown;
-auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;
-auto constexpr kChildMethod = CordzUpdateTracker::kConstructorCord;
-auto constexpr kUpdateMethod = CordzUpdateTracker::kAppendString;
-
-// Local less verbose helper
-std::vector<const CordzHandle*> DeleteQueue() {
- return CordzHandle::DiagnosticsGetDeleteQueue();
-}
-
-std::string FormatStack(absl::Span<void* const> raw_stack) {
- static constexpr size_t buf_size = 1 << 14;
- std::unique_ptr<char[]> buf(new char[buf_size]);
- std::string output;
- for (void* stackp : raw_stack) {
- if (absl::Symbolize(stackp, buf.get(), buf_size)) {
- absl::StrAppend(&output, " ", buf.get(), "\n");
- }
- }
- return output;
-}
-
-TEST(CordzInfoTest, TrackCord) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
- ASSERT_THAT(info, Ne(nullptr));
- EXPECT_FALSE(info->is_snapshot());
- EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(info));
- EXPECT_THAT(info->GetCordRepForTesting(), Eq(data.rep.rep));
- info->Untrack();
-}
-
-TEST(CordzInfoTest, MaybeTrackChildCordWithoutSampling) {
- CordzSamplingIntervalHelper sample_none(99999);
- TestCordData parent, child;
- CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);
- EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, MaybeTrackChildCordWithSampling) {
- CordzSamplingIntervalHelper sample_all(1);
- TestCordData parent, child;
- CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);
- EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, MaybeTrackChildCordWithoutSamplingParentSampled) {
- CordzSamplingIntervalHelper sample_none(99999);
- TestCordData parent, child;
- CordzInfo::TrackCord(parent.data, kTrackCordMethod);
- CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);
- CordzInfo* parent_info = parent.data.cordz_info();
- CordzInfo* child_info = child.data.cordz_info();
- ASSERT_THAT(child_info, Ne(nullptr));
- EXPECT_THAT(child_info->GetCordRepForTesting(), Eq(child.rep.rep));
- EXPECT_THAT(child_info->GetParentStack(), parent_info->GetStack());
- parent_info->Untrack();
- child_info->Untrack();
-}
-
-TEST(CordzInfoTest, MaybeTrackChildCordWithoutSamplingChildSampled) {
- CordzSamplingIntervalHelper sample_none(99999);
- TestCordData parent, child;
- CordzInfo::TrackCord(child.data, kTrackCordMethod);
- CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);
- EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, MaybeTrackChildCordWithSamplingChildSampled) {
- CordzSamplingIntervalHelper sample_all(1);
- TestCordData parent, child;
- CordzInfo::TrackCord(child.data, kTrackCordMethod);
- CordzInfo::MaybeTrackCord(child.data, parent.data, kTrackCordMethod);
- EXPECT_THAT(child.data.cordz_info(), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, UntrackCord) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
-
- info->Untrack();
- EXPECT_THAT(DeleteQueue(), SizeIs(0));
-}
-
-TEST(CordzInfoTest, UntrackCordWithSnapshot) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
-
- CordzSnapshot snapshot;
- info->Untrack();
- EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(nullptr));
- EXPECT_THAT(info->GetCordRepForTesting(), Eq(data.rep.rep));
- EXPECT_THAT(DeleteQueue(), ElementsAre(info, &snapshot));
-}
-
-TEST(CordzInfoTest, SetCordRep) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
-
- TestCordRep rep;
- info->Lock(CordzUpdateTracker::kAppendCord);
- info->SetCordRep(rep.rep);
- info->Unlock();
- EXPECT_THAT(info->GetCordRepForTesting(), Eq(rep.rep));
-
- info->Untrack();
-}
-
-TEST(CordzInfoTest, SetCordRepNullUntracksCordOnUnlock) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
-
- info->Lock(CordzUpdateTracker::kAppendString);
- info->SetCordRep(nullptr);
- EXPECT_THAT(info->GetCordRepForTesting(), Eq(nullptr));
- EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(info));
-
- info->Unlock();
- EXPECT_THAT(CordzInfo::Head(CordzSnapshot()), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, RefCordRep) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
-
- size_t refcount = data.rep.rep->refcount.Get();
- EXPECT_THAT(info->RefCordRep(), Eq(data.rep.rep));
- EXPECT_THAT(data.rep.rep->refcount.Get(), Eq(refcount + 1));
- CordRep::Unref(data.rep.rep);
- info->Untrack();
-}
-
-#if GTEST_HAS_DEATH_TEST
-
-TEST(CordzInfoTest, SetCordRepRequiresMutex) {
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
- TestCordRep rep;
- EXPECT_DEBUG_DEATH(info->SetCordRep(rep.rep), ".*");
- info->Untrack();
-}
-
-#endif // GTEST_HAS_DEATH_TEST
-
-TEST(CordzInfoTest, TrackUntrackHeadFirstV2) {
- CordzSnapshot snapshot;
- EXPECT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));
-
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info1 = data.data.cordz_info();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));
- EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));
-
- TestCordData data2;
- CordzInfo::TrackCord(data2.data, kTrackCordMethod);
- CordzInfo* info2 = data2.data.cordz_info();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));
- EXPECT_THAT(info2->Next(snapshot), Eq(info1));
- EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));
-
- info2->Untrack();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));
- EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));
-
- info1->Untrack();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, TrackUntrackTailFirstV2) {
- CordzSnapshot snapshot;
- EXPECT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));
-
- TestCordData data;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info1 = data.data.cordz_info();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info1));
- EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));
-
- TestCordData data2;
- CordzInfo::TrackCord(data2.data, kTrackCordMethod);
- CordzInfo* info2 = data2.data.cordz_info();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));
- EXPECT_THAT(info2->Next(snapshot), Eq(info1));
- EXPECT_THAT(info1->Next(snapshot), Eq(nullptr));
-
- info1->Untrack();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(info2));
- EXPECT_THAT(info2->Next(snapshot), Eq(nullptr));
-
- info2->Untrack();
- ASSERT_THAT(CordzInfo::Head(snapshot), Eq(nullptr));
-}
-
-TEST(CordzInfoTest, StackV2) {
- TestCordData data;
- // kMaxStackDepth is intentionally less than 64 (which is the max depth that
- // Cordz will record) because if the actual stack depth is over 64
- // (which it is on Apple platforms) then the expected_stack will end up
- // catching a few frames at the end that the actual_stack didn't get and
- // it will no longer be subset. At the time of this writing 58 is the max
- // that will allow this test to pass (with a minimum os version of iOS 9), so
- // rounded down to 50 to hopefully not run into this in the future if Apple
- // makes small modifications to its testing stack. 50 is sufficient to prove
- // that we got a decent stack.
- static constexpr int kMaxStackDepth = 50;
- CordzInfo::TrackCord(data.data, kTrackCordMethod);
- CordzInfo* info = data.data.cordz_info();
- std::vector<void*> local_stack;
- local_stack.resize(kMaxStackDepth);
- // In some environments we don't get stack traces. For example in Android
- // absl::GetStackTrace will return 0 indicating it didn't find any stack. The
- // resultant formatted stack will be "", but that still equals the stack
- // recorded in CordzInfo, which is also empty. The skip_count is 1 so that the
- // line number of the current stack isn't included in the HasSubstr check.
- local_stack.resize(absl::GetStackTrace(local_stack.data(), kMaxStackDepth,
- /*skip_count=*/1));
-
- std::string got_stack = FormatStack(info->GetStack());
- std::string expected_stack = FormatStack(local_stack);
- // If TrackCord is inlined, got_stack should match expected_stack. If it isn't
- // inlined, got_stack should include an additional frame not present in
- // expected_stack. Either way, expected_stack should be a substring of
- // got_stack.
- EXPECT_THAT(got_stack, HasSubstr(expected_stack));
-
- info->Untrack();
-}
-
-// Local helper functions to get different stacks for child and parent.
-CordzInfo* TrackChildCord(InlineData& data, const InlineData& parent) {
- CordzInfo::TrackCord(data, parent, kChildMethod);
- return data.cordz_info();
-}
-CordzInfo* TrackParentCord(InlineData& data) {
- CordzInfo::TrackCord(data, kTrackCordMethod);
- return data.cordz_info();
-}
-
-TEST(CordzInfoTest, GetStatistics) {
- TestCordData data;
- CordzInfo* info = TrackParentCord(data.data);
-
- CordzStatistics statistics = info->GetCordzStatistics();
- EXPECT_THAT(statistics.size, Eq(data.rep.rep->length));
- EXPECT_THAT(statistics.method, Eq(kTrackCordMethod));
- EXPECT_THAT(statistics.parent_method, Eq(kUnknownMethod));
- EXPECT_THAT(statistics.update_tracker.Value(kTrackCordMethod), Eq(1));
-
- info->Untrack();
-}
-
-TEST(CordzInfoTest, LockCountsMethod) {
- TestCordData data;
- CordzInfo* info = TrackParentCord(data.data);
-
- info->Lock(kUpdateMethod);
- info->Unlock();
- info->Lock(kUpdateMethod);
- info->Unlock();
-
- CordzStatistics statistics = info->GetCordzStatistics();
- EXPECT_THAT(statistics.update_tracker.Value(kUpdateMethod), Eq(2));
-
- info->Untrack();
-}
-
-TEST(CordzInfoTest, FromParent) {
- TestCordData parent;
- TestCordData child;
- CordzInfo* info_parent = TrackParentCord(parent.data);
- CordzInfo* info_child = TrackChildCord(child.data, parent.data);
-
- std::string stack = FormatStack(info_parent->GetStack());
- std::string parent_stack = FormatStack(info_child->GetParentStack());
- EXPECT_THAT(stack, Eq(parent_stack));
-
- CordzStatistics statistics = info_child->GetCordzStatistics();
- EXPECT_THAT(statistics.size, Eq(child.rep.rep->length));
- EXPECT_THAT(statistics.method, Eq(kChildMethod));
- EXPECT_THAT(statistics.parent_method, Eq(kTrackCordMethod));
- EXPECT_THAT(statistics.update_tracker.Value(kChildMethod), Eq(1));
-
- info_parent->Untrack();
- info_child->Untrack();
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.cc
deleted file mode 100644
index ba1270d8f0..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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/strings/internal/cordz_sample_token.h"
-
-#include "absl/base/config.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_info.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-CordzSampleToken::Iterator& CordzSampleToken::Iterator::operator++() {
- if (current_) {
- current_ = current_->Next(*token_);
- }
- return *this;
-}
-
-CordzSampleToken::Iterator CordzSampleToken::Iterator::operator++(int) {
- Iterator it(*this);
- operator++();
- return it;
-}
-
-bool operator==(const CordzSampleToken::Iterator& lhs,
- const CordzSampleToken::Iterator& rhs) {
- return lhs.current_ == rhs.current_ &&
- (lhs.current_ == nullptr || lhs.token_ == rhs.token_);
-}
-
-bool operator!=(const CordzSampleToken::Iterator& lhs,
- const CordzSampleToken::Iterator& rhs) {
- return !(lhs == rhs);
-}
-
-CordzSampleToken::Iterator::reference CordzSampleToken::Iterator::operator*()
- const {
- return *current_;
-}
-
-CordzSampleToken::Iterator::pointer CordzSampleToken::Iterator::operator->()
- const {
- return current_;
-}
-
-CordzSampleToken::Iterator::Iterator(const CordzSampleToken* token)
- : token_(token), current_(CordzInfo::Head(*token)) {}
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.h b/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.h
deleted file mode 100644
index 28a1d70ccc..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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/config.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_info.h"
-
-#ifndef ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
-#define ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// The existence of a CordzSampleToken guarantees that a reader can traverse the
-// global_cordz_infos_head linked-list without needing to hold a mutex. When a
-// CordzSampleToken exists, all CordzInfo objects that would be destroyed are
-// instead appended to a deletion queue. When the CordzSampleToken is destroyed,
-// it will also clean up any of these CordzInfo objects.
-//
-// E.g., ST are CordzSampleToken objects and CH are CordzHandle objects.
-// ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- global_delete_queue_tail
-//
-// This list tracks that CH1 and CH2 were created after ST1, so the thread
-// holding ST1 might have a referece to CH1, CH2, ST2, and CH3. However, ST2 was
-// created later, so the thread holding the ST2 token cannot have a reference to
-// ST1, CH1, or CH2. If ST1 is cleaned up first, that thread will delete ST1,
-// CH1, and CH2. If instead ST2 is cleaned up first, that thread will only
-// delete ST2.
-//
-// If ST1 is cleaned up first, the new list will be:
-// ST2 <- CH3 <- global_delete_queue_tail
-//
-// If ST2 is cleaned up first, the new list will be:
-// ST1 <- CH1 <- CH2 <- CH3 <- global_delete_queue_tail
-//
-// All new CordzHandle objects are appended to the list, so if a new thread
-// comes along before either ST1 or ST2 are cleaned up, the new list will be:
-// ST1 <- CH1 <- CH2 <- ST2 <- CH3 <- ST3 <- global_delete_queue_tail
-//
-// A thread must hold the global_delete_queue_mu mutex whenever it's altering
-// this list.
-//
-// It is safe for thread that holds a CordzSampleToken to read
-// global_cordz_infos at any time since the objects it is able to retrieve will
-// not be deleted while the CordzSampleToken exists.
-class CordzSampleToken : public CordzSnapshot {
- public:
- class Iterator {
- public:
- using iterator_category = std::input_iterator_tag;
- using value_type = const CordzInfo&;
- using difference_type = ptrdiff_t;
- using pointer = const CordzInfo*;
- using reference = value_type;
-
- Iterator() = default;
-
- Iterator& operator++();
- Iterator operator++(int);
- friend bool operator==(const Iterator& lhs, const Iterator& rhs);
- friend bool operator!=(const Iterator& lhs, const Iterator& rhs);
- reference operator*() const;
- pointer operator->() const;
-
- private:
- friend class CordzSampleToken;
- explicit Iterator(const CordzSampleToken* token);
-
- const CordzSampleToken* token_ = nullptr;
- pointer current_ = nullptr;
- };
-
- CordzSampleToken() = default;
- CordzSampleToken(const CordzSampleToken&) = delete;
- CordzSampleToken& operator=(const CordzSampleToken&) = delete;
-
- Iterator begin() { return Iterator(this); }
- Iterator end() { return Iterator(); }
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_CORDZ_SAMPLE_TOKEN_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token_test.cc
deleted file mode 100644
index 9f54301d68..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_sample_token_test.cc
+++ /dev/null
@@ -1,208 +0,0 @@
-// 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/strings/internal/cordz_sample_token.h"
-
-#include <memory>
-#include <type_traits>
-#include <vector>
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/memory/memory.h"
-#include "absl/random/random.h"
-#include "absl/strings/cordz_test_helpers.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/internal/cordz_handle.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/synchronization/internal/thread_pool.h"
-#include "absl/synchronization/notification.h"
-#include "absl/time/clock.h"
-#include "absl/time/time.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::Ne;
-
-// Used test values
-auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;
-
-TEST(CordzSampleTokenTest, IteratorTraits) {
- static_assert(std::is_copy_constructible<CordzSampleToken::Iterator>::value,
- "");
- static_assert(std::is_copy_assignable<CordzSampleToken::Iterator>::value, "");
- static_assert(std::is_move_constructible<CordzSampleToken::Iterator>::value,
- "");
- static_assert(std::is_move_assignable<CordzSampleToken::Iterator>::value, "");
- static_assert(
- std::is_same<
- std::iterator_traits<CordzSampleToken::Iterator>::iterator_category,
- std::input_iterator_tag>::value,
- "");
- static_assert(
- std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::value_type,
- const CordzInfo&>::value,
- "");
- static_assert(
- std::is_same<
- std::iterator_traits<CordzSampleToken::Iterator>::difference_type,
- ptrdiff_t>::value,
- "");
- static_assert(
- std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::pointer,
- const CordzInfo*>::value,
- "");
- static_assert(
- std::is_same<std::iterator_traits<CordzSampleToken::Iterator>::reference,
- const CordzInfo&>::value,
- "");
-}
-
-TEST(CordzSampleTokenTest, IteratorEmpty) {
- CordzSampleToken token;
- EXPECT_THAT(token.begin(), Eq(token.end()));
-}
-
-TEST(CordzSampleTokenTest, Iterator) {
- TestCordData cord1, cord2, cord3;
- CordzInfo::TrackCord(cord1.data, kTrackCordMethod);
- CordzInfo* info1 = cord1.data.cordz_info();
- CordzInfo::TrackCord(cord2.data, kTrackCordMethod);
- CordzInfo* info2 = cord2.data.cordz_info();
- CordzInfo::TrackCord(cord3.data, kTrackCordMethod);
- CordzInfo* info3 = cord3.data.cordz_info();
-
- CordzSampleToken token;
- std::vector<const CordzInfo*> found;
- for (const CordzInfo& cord_info : token) {
- found.push_back(&cord_info);
- }
-
- EXPECT_THAT(found, ElementsAre(info3, info2, info1));
-
- info1->Untrack();
- info2->Untrack();
- info3->Untrack();
-}
-
-TEST(CordzSampleTokenTest, IteratorEquality) {
- TestCordData cord1;
- TestCordData cord2;
- TestCordData cord3;
- CordzInfo::TrackCord(cord1.data, kTrackCordMethod);
- CordzInfo* info1 = cord1.data.cordz_info();
-
- CordzSampleToken token1;
- // lhs starts with the CordzInfo corresponding to cord1 at the head.
- CordzSampleToken::Iterator lhs = token1.begin();
-
- CordzInfo::TrackCord(cord2.data, kTrackCordMethod);
- CordzInfo* info2 = cord2.data.cordz_info();
-
- CordzSampleToken token2;
- // rhs starts with the CordzInfo corresponding to cord2 at the head.
- CordzSampleToken::Iterator rhs = token2.begin();
-
- CordzInfo::TrackCord(cord3.data, kTrackCordMethod);
- CordzInfo* info3 = cord3.data.cordz_info();
-
- // lhs is on cord1 while rhs is on cord2.
- EXPECT_THAT(lhs, Ne(rhs));
-
- rhs++;
- // lhs and rhs are both on cord1, but they didn't come from the same
- // CordzSampleToken.
- EXPECT_THAT(lhs, Ne(rhs));
-
- lhs++;
- rhs++;
- // Both lhs and rhs are done, so they are on nullptr.
- EXPECT_THAT(lhs, Eq(rhs));
-
- info1->Untrack();
- info2->Untrack();
- info3->Untrack();
-}
-
-TEST(CordzSampleTokenTest, MultiThreaded) {
- Notification stop;
- static constexpr int kNumThreads = 4;
- static constexpr int kNumCords = 3;
- static constexpr int kNumTokens = 3;
- absl::synchronization_internal::ThreadPool pool(kNumThreads);
-
- for (int i = 0; i < kNumThreads; ++i) {
- pool.Schedule([&stop]() {
- absl::BitGen gen;
- TestCordData cords[kNumCords];
- std::unique_ptr<CordzSampleToken> tokens[kNumTokens];
-
- while (!stop.HasBeenNotified()) {
- // Randomly perform one of five actions:
- // 1) Untrack
- // 2) Track
- // 3) Iterate over Cords visible to a token.
- // 4) Unsample
- // 5) Sample
- int index = absl::Uniform(gen, 0, kNumCords);
- if (absl::Bernoulli(gen, 0.5)) {
- TestCordData& cord = cords[index];
- // Track/untrack.
- if (cord.data.is_profiled()) {
- // 1) Untrack
- cord.data.cordz_info()->Untrack();
- cord.data.clear_cordz_info();;
- } else {
- // 2) Track
- CordzInfo::TrackCord(cord.data, kTrackCordMethod);
- }
- } else {
- std::unique_ptr<CordzSampleToken>& token = tokens[index];
- if (token) {
- if (absl::Bernoulli(gen, 0.5)) {
- // 3) Iterate over Cords visible to a token.
- for (const CordzInfo& info : *token) {
- // This is trivial work to allow us to compile the loop.
- EXPECT_THAT(info.Next(*token), Ne(&info));
- }
- } else {
- // 4) Unsample
- token = nullptr;
- }
- } else {
- // 5) Sample
- token = absl::make_unique<CordzSampleToken>();
- }
- }
- }
- for (TestCordData& cord : cords) {
- CordzInfo::MaybeUntrackCord(cord.data.cordz_info());
- }
- });
- }
- // The threads will hammer away. Give it a little bit of time for tsan to
- // spot errors.
- absl::SleepFor(absl::Seconds(3));
- stop.Notify();
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h b/third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h
deleted file mode 100644
index da4c7dbb8c..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_statistics.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// 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_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
-#define ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
-
-#include <cstdint>
-
-#include "absl/base/config.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordzStatistics captures some meta information about a Cord's shape.
-struct CordzStatistics {
- using MethodIdentifier = CordzUpdateTracker::MethodIdentifier;
-
- // Node counts information
- struct NodeCounts {
- size_t flat = 0; // #flats
- size_t flat_64 = 0; // #flats up to 64 bytes
- size_t flat_128 = 0; // #flats up to 128 bytes
- size_t flat_256 = 0; // #flats up to 256 bytes
- size_t flat_512 = 0; // #flats up to 512 bytes
- size_t flat_1k = 0; // #flats up to 1K bytes
- size_t external = 0; // #external reps
- size_t substring = 0; // #substring reps
- size_t concat = 0; // #concat reps
- size_t ring = 0; // #ring buffer reps
- size_t btree = 0; // #btree reps
- };
-
- // The size of the cord in bytes. This matches the result of Cord::size().
- int64_t size = 0;
-
- // The estimated memory used by the sampled cord. This value matches the
- // value as reported by Cord::EstimatedMemoryUsage().
- // A value of 0 implies the property has not been recorded.
- int64_t estimated_memory_usage = 0;
-
- // The effective memory used by the sampled cord, inversely weighted by the
- // effective indegree of each allocated node. This is a representation of the
- // fair share of memory usage that should be attributed to the sampled cord.
- // This value is more useful for cases where one or more nodes are referenced
- // by multiple Cord instances, and for cases where a Cord includes the same
- // node multiple times (either directly or indirectly).
- // A value of 0 implies the property has not been recorded.
- int64_t estimated_fair_share_memory_usage = 0;
-
- // The total number of nodes referenced by this cord.
- // For ring buffer Cords, this includes the 'ring buffer' node.
- // For btree Cords, this includes all 'CordRepBtree' tree nodes as well as all
- // the substring, flat and external nodes referenced by the tree.
- // A value of 0 implies the property has not been recorded.
- int64_t node_count = 0;
-
- // Detailed node counts per type
- NodeCounts node_counts;
-
- // The cord method responsible for sampling the cord.
- MethodIdentifier method = MethodIdentifier::kUnknown;
-
- // The cord method responsible for sampling the parent cord if applicable.
- MethodIdentifier parent_method = MethodIdentifier::kUnknown;
-
- // Update tracker tracking invocation count per cord method.
- CordzUpdateTracker update_tracker;
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORDZ_STATISTICS_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope.h b/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope.h
deleted file mode 100644
index 57ba75de93..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// 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_CORDZ_UPDATE_SCOPE_H_
-#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_
-
-#include "absl/base/config.h"
-#include "absl/base/optimization.h"
-#include "absl/base/thread_annotations.h"
-#include "absl/strings/internal/cord_internal.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordzUpdateScope scopes an update to the provided CordzInfo.
-// The class invokes `info->Lock(method)` and `info->Unlock()` to guard
-// cordrep updates. This class does nothing if `info` is null.
-// See also the 'Lock`, `Unlock` and `SetCordRep` methods in `CordzInfo`.
-class ABSL_SCOPED_LOCKABLE CordzUpdateScope {
- public:
- CordzUpdateScope(CordzInfo* info, CordzUpdateTracker::MethodIdentifier method)
- ABSL_EXCLUSIVE_LOCK_FUNCTION(info)
- : info_(info) {
- if (ABSL_PREDICT_FALSE(info_)) {
- info->Lock(method);
- }
- }
-
- // CordzUpdateScope can not be copied or assigned to.
- CordzUpdateScope(CordzUpdateScope&& rhs) = delete;
- CordzUpdateScope(const CordzUpdateScope&) = delete;
- CordzUpdateScope& operator=(CordzUpdateScope&& rhs) = delete;
- CordzUpdateScope& operator=(const CordzUpdateScope&) = delete;
-
- ~CordzUpdateScope() ABSL_UNLOCK_FUNCTION() {
- if (ABSL_PREDICT_FALSE(info_)) {
- info_->Unlock();
- }
- }
-
- void SetCordRep(CordRep* rep) const {
- if (ABSL_PREDICT_FALSE(info_)) {
- info_->SetCordRep(rep);
- }
- }
-
- CordzInfo* info() const { return info_; }
-
- private:
- CordzInfo* info_;
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_SCOPE_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope_test.cc
deleted file mode 100644
index 3d08c622d0..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_update_scope_test.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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/strings/internal/cordz_update_scope.h"
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/config.h"
-#include "absl/strings/cordz_test_helpers.h"
-#include "absl/strings/internal/cord_rep_flat.h"
-#include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_update_tracker.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-namespace {
-
-// Used test values
-auto constexpr kTrackCordMethod = CordzUpdateTracker::kConstructorString;
-
-TEST(CordzUpdateScopeTest, ScopeNullptr) {
- CordzUpdateScope scope(nullptr, kTrackCordMethod);
-}
-
-TEST(CordzUpdateScopeTest, ScopeSampledCord) {
- TestCordData cord;
- CordzInfo::TrackCord(cord.data, kTrackCordMethod);
- CordzUpdateScope scope(cord.data.cordz_info(), kTrackCordMethod);
- cord.data.cordz_info()->SetCordRep(nullptr);
-}
-
-} // namespace
-ABSL_NAMESPACE_END
-} // namespace cord_internal
-
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h b/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h
deleted file mode 100644
index 1f764486eb..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker.h
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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_CORDZ_UPDATE_TRACKER_H_
-#define ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
-
-#include <atomic>
-#include <cstdint>
-
-#include "absl/base/config.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-
-// CordzUpdateTracker tracks counters for Cord update methods.
-//
-// The purpose of CordzUpdateTracker is to track the number of calls to methods
-// updating Cord data for sampled cords. The class internally uses 'lossy'
-// atomic operations: Cord is thread-compatible, so there is no need to
-// synchronize updates. However, Cordz collection threads may call 'Value()' at
-// any point, so the class needs to provide thread safe access.
-//
-// This class is thread-safe. But as per above comments, all non-const methods
-// should be used single-threaded only: updates are thread-safe but lossy.
-class CordzUpdateTracker {
- public:
- // Tracked update methods.
- enum MethodIdentifier {
- kUnknown,
- kAppendBuffer,
- kAppendCord,
- kAppendExternalMemory,
- kAppendString,
- kAssignCord,
- kAssignString,
- kClear,
- kConstructorCord,
- kConstructorString,
- kCordReader,
- kFlatten,
- kGetAppendRegion,
- kMakeCordFromExternal,
- kMoveAppendCord,
- kMoveAssignCord,
- kMovePrependCord,
- kPrependBuffer,
- kPrependCord,
- kPrependString,
- kRemovePrefix,
- kRemoveSuffix,
- kSubCord,
-
- // kNumMethods defines the number of entries: must be the last entry.
- kNumMethods,
- };
-
- // Constructs a new instance. All counters are zero-initialized.
- constexpr CordzUpdateTracker() noexcept : values_{} {}
-
- // Copy constructs a new instance.
- CordzUpdateTracker(const CordzUpdateTracker& rhs) noexcept { *this = rhs; }
-
- // Assigns the provided value to this instance.
- CordzUpdateTracker& operator=(const CordzUpdateTracker& rhs) noexcept {
- for (int i = 0; i < kNumMethods; ++i) {
- values_[i].store(rhs.values_[i].load(std::memory_order_relaxed),
- std::memory_order_relaxed);
- }
- return *this;
- }
-
- // Returns the value for the specified method.
- int64_t Value(MethodIdentifier method) const {
- return values_[method].load(std::memory_order_relaxed);
- }
-
- // Increases the value for the specified method by `n`
- void LossyAdd(MethodIdentifier method, int64_t n = 1) {
- auto& value = values_[method];
- value.store(value.load(std::memory_order_relaxed) + n,
- std::memory_order_relaxed);
- }
-
- // Adds all the values from `src` to this instance
- void LossyAdd(const CordzUpdateTracker& src) {
- for (int i = 0; i < kNumMethods; ++i) {
- MethodIdentifier method = static_cast<MethodIdentifier>(i);
- if (int64_t value = src.Value(method)) {
- LossyAdd(method, value);
- }
- }
- }
-
- private:
- // Until C++20 std::atomic is not constexpr default-constructible, so we need
- // a wrapper for this class to be constexpr constructible.
- class Counter : public std::atomic<int64_t> {
- public:
- constexpr Counter() noexcept : std::atomic<int64_t>(0) {}
- };
-
- Counter values_[kNumMethods];
-};
-
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
-
-#endif // ABSL_STRINGS_INTERNAL_CORDZ_UPDATE_TRACKER_H_
diff --git a/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker_test.cc b/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker_test.cc
deleted file mode 100644
index 2348a17585..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/cordz_update_tracker_test.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// 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/strings/internal/cordz_update_tracker.h"
-
-#include <array>
-#include <thread> // NOLINT
-
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "absl/base/attributes.h"
-#include "absl/base/config.h"
-#include "absl/synchronization/notification.h"
-
-namespace absl {
-ABSL_NAMESPACE_BEGIN
-namespace cord_internal {
-namespace {
-
-using ::testing::AnyOf;
-using ::testing::Eq;
-
-using Method = CordzUpdateTracker::MethodIdentifier;
-using Methods = std::array<Method, Method::kNumMethods>;
-
-// Returns an array of all methods defined in `MethodIdentifier`
-Methods AllMethods() {
- return Methods{Method::kUnknown,
- Method::kAppendBuffer,
- Method::kAppendCord,
- Method::kAppendExternalMemory,
- Method::kAppendString,
- Method::kAssignCord,
- Method::kAssignString,
- Method::kClear,
- Method::kConstructorCord,
- Method::kConstructorString,
- Method::kCordReader,
- Method::kFlatten,
- Method::kGetAppendRegion,
- Method::kMakeCordFromExternal,
- Method::kMoveAppendCord,
- Method::kMoveAssignCord,
- Method::kMovePrependCord,
- Method::kPrependBuffer,
- Method::kPrependCord,
- Method::kPrependString,
- Method::kRemovePrefix,
- Method::kRemoveSuffix,
- Method::kSubCord};
-}
-
-TEST(CordzUpdateTracker, IsConstExprAndInitializesToZero) {
- constexpr CordzUpdateTracker tracker;
- for (Method method : AllMethods()) {
- ASSERT_THAT(tracker.Value(method), Eq(0));
- }
-}
-
-TEST(CordzUpdateTracker, LossyAdd) {
- int64_t n = 1;
- CordzUpdateTracker tracker;
- for (Method method : AllMethods()) {
- tracker.LossyAdd(method, n);
- EXPECT_THAT(tracker.Value(method), Eq(n));
- n += 2;
- }
-}
-
-TEST(CordzUpdateTracker, CopyConstructor) {
- int64_t n = 1;
- CordzUpdateTracker src;
- for (Method method : AllMethods()) {
- src.LossyAdd(method, n);
- n += 2;
- }
-
- n = 1;
- CordzUpdateTracker tracker(src);
- for (Method method : AllMethods()) {
- EXPECT_THAT(tracker.Value(method), Eq(n));
- n += 2;
- }
-}
-
-TEST(CordzUpdateTracker, OperatorAssign) {
- int64_t n = 1;
- CordzUpdateTracker src;
- CordzUpdateTracker tracker;
- for (Method method : AllMethods()) {
- src.LossyAdd(method, n);
- n += 2;
- }
-
- n = 1;
- tracker = src;
- for (Method method : AllMethods()) {
- EXPECT_THAT(tracker.Value(method), Eq(n));
- n += 2;
- }
-}
-
-TEST(CordzUpdateTracker, ThreadSanitizedValueCheck) {
- absl::Notification done;
- CordzUpdateTracker tracker;
-
- std::thread reader([&done, &tracker] {
- while (!done.HasBeenNotified()) {
- int n = 1;
- for (Method method : AllMethods()) {
- EXPECT_THAT(tracker.Value(method), AnyOf(Eq(n), Eq(0)));
- n += 2;
- }
- }
- int n = 1;
- for (Method method : AllMethods()) {
- EXPECT_THAT(tracker.Value(method), Eq(n));
- n += 2;
- }
- });
-
- int64_t n = 1;
- for (Method method : AllMethods()) {
- tracker.LossyAdd(method, n);
- n += 2;
- }
- done.Notify();
- reader.join();
-}
-
-} // namespace
-} // namespace cord_internal
-ABSL_NAMESPACE_END
-} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h b/third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h
index eaa88a8897..1a1e50c4d8 100644
--- a/third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h
+++ b/third_party/abseil-cpp/absl/strings/internal/numbers_test_common.h
@@ -170,7 +170,7 @@ inline const std::array<uint64_test_case, 34>& strtouint64_test_cases() {
{"0x1234", true, 16, 0x1234},
- // Base-10 string version.
+ // Base-10 std::string version.
{"1234", true, 0, 1234},
{nullptr, false, 0, 0},
}};
diff --git a/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h b/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h
index 49859dcc7d..e42628e394 100644
--- a/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h
+++ b/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h
@@ -17,7 +17,6 @@
#ifndef ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
#define ABSL_STRINGS_INTERNAL_RESIZE_UNINITIALIZED_H_
-#include <algorithm>
#include <string>
#include <type_traits>
#include <utility>
@@ -29,9 +28,8 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace strings_internal {
-// In this type trait, we look for a __resize_default_init member function, and
-// we use it if available, otherwise, we use resize. We provide HasMember to
-// indicate whether __resize_default_init is present.
+// Is a subclass of true_type or false_type, depending on whether or not
+// T has a __resize_default_init member.
template <typename string_type, typename = void>
struct ResizeUninitializedTraits {
using HasMember = std::false_type;
@@ -68,50 +66,6 @@ inline void STLStringResizeUninitialized(string_type* s, size_t new_size) {
ResizeUninitializedTraits<string_type>::Resize(s, new_size);
}
-// Used to ensure exponential growth so that the amortized complexity of
-// increasing the string size by a small amount is O(1), in contrast to
-// O(str->size()) in the case of precise growth.
-template <typename string_type>
-void STLStringReserveAmortized(string_type* s, size_t new_size) {
- const size_t cap = s->capacity();
- if (new_size > cap) {
- // Make sure to always grow by at least a factor of 2x.
- s->reserve((std::max)(new_size, 2 * cap));
- }
-}
-
-// In this type trait, we look for an __append_default_init member function, and
-// we use it if available, otherwise, we use append.
-template <typename string_type, typename = void>
-struct AppendUninitializedTraits {
- static void Append(string_type* s, size_t n) {
- s->append(n, typename string_type::value_type());
- }
-};
-
-template <typename string_type>
-struct AppendUninitializedTraits<
- string_type, absl::void_t<decltype(std::declval<string_type&>()
- .__append_default_init(237))> > {
- static void Append(string_type* s, size_t n) {
- s->__append_default_init(n);
- }
-};
-
-// Like STLStringResizeUninitialized(str, new_size), except guaranteed to use
-// exponential growth so that the amortized complexity of increasing the string
-// size by a small amount is O(1), in contrast to O(str->size()) in the case of
-// precise growth.
-template <typename string_type>
-void STLStringResizeUninitializedAmortized(string_type* s, size_t new_size) {
- const size_t size = s->size();
- if (new_size > size) {
- AppendUninitializedTraits<string_type>::Append(s, new_size - size);
- } else {
- s->erase(new_size);
- }
-}
-
} // namespace strings_internal
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc b/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
index ad1b9c58f3..0f8b3c2a95 100644
--- a/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized_test.cc
@@ -19,115 +19,64 @@
namespace {
int resize_call_count = 0;
-int append_call_count = 0;
// A mock string class whose only purpose is to track how many times its
-// resize()/append() methods have been called.
+// resize() method has been called.
struct resizable_string {
- using value_type = char;
size_t size() const { return 0; }
- size_t capacity() const { return 0; }
char& operator[](size_t) {
static char c = '\0';
return c;
}
void resize(size_t) { resize_call_count += 1; }
- void append(size_t, value_type) { append_call_count += 1; }
- void reserve(size_t) {}
- resizable_string& erase(size_t = 0, size_t = 0) { return *this; }
};
int resize_default_init_call_count = 0;
-int append_default_init_call_count = 0;
// A mock string class whose only purpose is to track how many times its
-// resize()/__resize_default_init()/append()/__append_default_init() methods
-// have been called.
-struct default_init_string {
+// resize() and __resize_default_init() methods have been called.
+struct resize_default_init_string {
size_t size() const { return 0; }
- size_t capacity() 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; }
- void __append_default_init(size_t) { append_default_init_call_count += 1; }
- void reserve(size_t) {}
- default_init_string& erase(size_t = 0, size_t = 0) { return *this; }
};
TEST(ResizeUninit, WithAndWithout) {
resize_call_count = 0;
- append_call_count = 0;
resize_default_init_call_count = 0;
- append_default_init_call_count = 0;
{
resizable_string rs;
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
EXPECT_FALSE(
absl::strings_internal::STLStringSupportsNontrashingResize(&rs));
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
absl::strings_internal::STLStringResizeUninitialized(&rs, 237);
EXPECT_EQ(resize_call_count, 1);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
- absl::strings_internal::STLStringResizeUninitializedAmortized(&rs, 1000);
- EXPECT_EQ(resize_call_count, 1);
- EXPECT_EQ(append_call_count, 1);
- EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
}
resize_call_count = 0;
- append_call_count = 0;
resize_default_init_call_count = 0;
- append_default_init_call_count = 0;
{
- default_init_string rus;
+ resize_default_init_string rus;
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
EXPECT_TRUE(
absl::strings_internal::STLStringSupportsNontrashingResize(&rus));
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 0);
- EXPECT_EQ(append_default_init_call_count, 0);
absl::strings_internal::STLStringResizeUninitialized(&rus, 237);
EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
- EXPECT_EQ(resize_default_init_call_count, 1);
- EXPECT_EQ(append_default_init_call_count, 0);
- absl::strings_internal::STLStringResizeUninitializedAmortized(&rus, 1000);
- EXPECT_EQ(resize_call_count, 0);
- EXPECT_EQ(append_call_count, 0);
EXPECT_EQ(resize_default_init_call_count, 1);
- EXPECT_EQ(append_default_init_call_count, 1);
- }
-}
-
-TEST(ResizeUninit, Amortized) {
- std::string str;
- size_t prev_cap = str.capacity();
- int cap_increase_count = 0;
- for (int i = 0; i < 1000; ++i) {
- absl::strings_internal::STLStringResizeUninitializedAmortized(&str, i);
- size_t new_cap = str.capacity();
- if (new_cap > prev_cap) ++cap_increase_count;
- prev_cap = new_cap;
}
- EXPECT_LT(cap_increase_count, 50);
}
} // namespace
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
index e28a29b171..4d0604e00c 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.cc
@@ -1,17 +1,3 @@
-// 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
@@ -26,13 +12,14 @@
#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);
@@ -61,179 +48,125 @@ struct IsSigned<absl::int128> : std::true_type {};
template <>
struct IsSigned<absl::uint128> : std::false_type {};
-// 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 {
+class ConvertedIntInfo {
public:
- // Print the unsigned integer as octal.
- // Supports unsigned integral types and uint128.
template <typename T>
- 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;
+ 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;
}
- PrintAsDec(u, add_neg);
+ UnsignedToStringRight(u, conv);
}
- 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;
+ string_view digits() const {
+ return {end() - size_, static_cast<size_t>(size_)};
}
+ bool is_neg() const { return is_neg_; }
- // Print the unsigned integer as hex using lowercase.
- // Supports unsigned integral types and uint128.
+ private:
+ template <typename T, bool IsSigned>
+ struct IsNegImpl {
+ static bool Eval(T v) { return v < 0; }
+ };
template <typename T>
- 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;
+ struct IsNegImpl<T, false> {
+ static bool Eval(T) {
+ return false;
}
- start_ = p;
- size_ = storage_ + sizeof(storage_) - p;
- }
+ };
- // Print the unsigned integer as hex using uppercase.
- // Supports unsigned integral types and uint128.
template <typename T>
- 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;
+ bool IsNeg(T v) {
+ return IsNegImpl<T, IsSigned<T>::value>::Eval(v);
}
- // 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};
+ template <typename T>
+ void UnsignedToStringRight(T u, ConversionChar conv) {
+ char *p = end();
+ switch (FormatConversionCharRadix(conv)) {
+ 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[FormatConversionCharIsUpper(conv) ? 1 : 0];
+ for (; u; u /= 16) *--p = digits[static_cast<size_t>(u % 16)];
+ break;
+ }
+ }
+ size_ = static_cast<int>(end() - p);
}
- bool is_negative() const { return start_[0] == '-'; }
+ const char *end() const { return storage_ + sizeof(storage_); }
+ char *end() { return storage_ + sizeof(storage_); }
- 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];
+ bool is_neg_;
+ int size_;
+ // Max size: 128 bit value as octal -> 43 digits
+ char storage_[128 / 3 + 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 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);
+string_view BaseIndicator(const ConvertedIntInfo &info,
+ const ConversionSpec conv) {
+ bool alt = conv.flags().alt;
+ int radix = FormatConversionCharRadix(conv.conv());
+ if (conv.conv() == ConversionChar::p) alt = true; // always show 0x for %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 && hex && !as_digits.without_neg_or_zero().empty()) {
- return conv.conversion_char() == FormatConversionCharInternal::X ? "0X"
- : "0x";
+ if (alt && radix == 16 && !info.digits().empty()) {
+ if (FormatConversionCharIsUpper(conv.conv())) return "0X";
+ return "0x";
}
return {};
}
-string_view SignColumn(bool neg, const FormatConversionSpecImpl conv) {
- if (conv.conversion_char() == FormatConversionCharInternal::d ||
- conv.conversion_char() == FormatConversionCharInternal::i) {
+string_view SignColumn(bool neg, const ConversionSpec conv) {
+ if (FormatConversionCharIsSigned(conv.conv())) {
if (neg) return "-";
- if (conv.has_show_pos_flag()) return "+";
- if (conv.has_sign_col_flag()) return " ";
+ if (conv.flags().show_pos) return "+";
+ if (conv.flags().sign_col) return " ";
}
return {};
}
-bool ConvertCharImpl(unsigned char v, const FormatConversionSpecImpl conv,
+bool ConvertCharImpl(unsigned char v, const ConversionSpec conv,
FormatSinkImpl *sink) {
size_t fill = 0;
if (conv.width() >= 0) fill = conv.width();
ReducePadding(1, &fill);
- if (!conv.has_left_flag()) sink->Append(fill, ' ');
+ if (!conv.flags().left) sink->Append(fill, ' ');
sink->Append(1, v);
- if (conv.has_left_flag()) sink->Append(fill, ' ');
+ if (conv.flags().left) sink->Append(fill, ' ');
return true;
}
-bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+bool ConvertIntImplInner(const ConvertedIntInfo &info,
+ const ConversionSpec 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 = as_digits.without_neg_or_zero();
+ string_view formatted = info.digits();
ReducePadding(formatted, &fill);
- string_view sign = SignColumn(as_digits.is_negative(), conv);
+ string_view sign = SignColumn(info.is_neg(), conv);
ReducePadding(sign, &fill);
- string_view base_indicator = BaseIndicator(as_digits, conv);
+ string_view base_indicator = BaseIndicator(info, conv);
ReducePadding(base_indicator, &fill);
int precision = conv.precision();
@@ -241,8 +174,7 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
if (!precision_specified)
precision = 1;
- if (conv.has_alt_flag() &&
- conv.conversion_char() == FormatConversionCharInternal::o) {
+ if (conv.flags().alt && conv.conv() == ConversionChar::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."
@@ -255,13 +187,13 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
size_t num_zeroes = Excess(formatted.size(), precision);
ReducePadding(num_zeroes, &fill);
- size_t num_left_spaces = !conv.has_left_flag() ? fill : 0;
- size_t num_right_spaces = conv.has_left_flag() ? fill : 0;
+ size_t num_left_spaces = !conv.flags().left ? fill : 0;
+ size_t num_right_spaces = conv.flags().left ? 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.has_zero_flag()) {
+ if (!precision_specified && conv.flags().zero) {
num_zeroes += num_left_spaces;
num_left_spaces = 0;
}
@@ -276,97 +208,71 @@ bool ConvertIntImplInnerSlow(const IntDigits &as_digits,
}
template <typename T>
-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);
+bool ConvertIntImplInner(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
+ ConvertedIntInfo info(v, conv.conv());
+ if (conv.flags().basic && (conv.conv() != ConversionChar::p)) {
+ if (info.is_neg()) sink->Append(1, '-');
+ if (info.digits().empty()) {
+ sink->Append(1, '0');
+ } else {
+ sink->Append(info.digits());
+ }
+ return true;
}
+ return ConvertIntImplInner(info, conv, sink);
+}
- if (conv.is_basic()) {
- sink->Append(as_digits.with_neg_and_zero());
- return true;
+template <typename T>
+bool ConvertIntArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
+ if (FormatConversionCharIsFloat(conv.conv())) {
+ return FormatConvertImpl(static_cast<double>(v), conv, sink).value;
+ }
+ if (conv.conv() == ConversionChar::c)
+ return ConvertCharImpl(static_cast<unsigned char>(v), conv, sink);
+ if (!FormatConversionCharIsIntegral(conv.conv())) return false;
+ if (!FormatConversionCharIsSigned(conv.conv()) && IsSigned<T>::value) {
+ using U = typename MakeUnsigned<T>::type;
+ return FormatConvertImpl(static_cast<U>(v), conv, sink).value;
}
- return ConvertIntImplInnerSlow(as_digits, conv, sink);
+ return ConvertIntImplInner(v, conv, sink);
}
template <typename T>
-bool ConvertFloatArg(T v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- return FormatConversionCharIsFloat(conv.conversion_char()) &&
+bool ConvertFloatArg(T v, const ConversionSpec conv, FormatSinkImpl *sink) {
+ return FormatConversionCharIsFloat(conv.conv()) &&
ConvertFloatImpl(v, conv, sink);
}
-inline bool ConvertStringArg(string_view v, const FormatConversionSpecImpl conv,
+inline bool ConvertStringArg(string_view v, const ConversionSpec conv,
FormatSinkImpl *sink) {
- if (conv.is_basic()) {
+ if (conv.conv() != ConversionChar::s) return false;
+ if (conv.flags().basic) {
sink->Append(v);
return true;
}
return sink->PutPaddedString(v, conv.width(), conv.precision(),
- conv.has_left_flag());
+ conv.flags().left);
}
} // namespace
// ==================== Strings ====================
-StringConvertResult FormatConvertImpl(const std::string &v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+ConvertResult<Conv::s> FormatConvertImpl(const std::string &v,
+ const ConversionSpec conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-StringConvertResult FormatConvertImpl(string_view v,
- const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
+ConvertResult<Conv::s> FormatConvertImpl(string_view v,
+ const ConversionSpec conv,
+ FormatSinkImpl *sink) {
return {ConvertStringArg(v, conv, sink)};
}
-ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::s, FormatConversionCharSetInternal::p)>
-FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
- FormatSinkImpl *sink) {
- if (conv.conversion_char() == FormatConversionCharInternal::p)
+ConvertResult<Conv::s | Conv::p> FormatConvertImpl(const char *v,
+ const ConversionSpec conv,
+ FormatSinkImpl *sink) {
+ if (conv.conv() == ConversionChar::p)
return {FormatConvertImpl(VoidPtr(v), conv, sink).value};
size_t len;
if (v == nullptr) {
@@ -381,99 +287,93 @@ FormatConvertImpl(const char *v, const FormatConversionSpecImpl conv,
}
// ==================== Raw pointers ====================
-ArgConvertResult<FormatConversionCharSetInternal::p> FormatConvertImpl(
- VoidPtr v, const FormatConversionSpecImpl conv, FormatSinkImpl *sink) {
+ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, const ConversionSpec conv,
+ FormatSinkImpl *sink) {
+ if (conv.conv() != ConversionChar::p) return {false};
if (!v.value) {
sink->Append("(nil)");
return {true};
}
- IntDigits as_digits;
- as_digits.PrintAsHexLower(v.value);
- return {ConvertIntImplInnerSlow(as_digits, conv, sink)};
+ return {ConvertIntImplInner(v.value, conv, sink)};
}
// ==================== Floats ====================
-FloatingConvertResult FormatConvertImpl(float v,
- const FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(float v, const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
-FloatingConvertResult FormatConvertImpl(double v,
- const FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(double v, const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
FloatingConvertResult FormatConvertImpl(long double v,
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertFloatArg(v, conv, sink)};
}
// ==================== Chars ====================
-IntegralConvertResult FormatConvertImpl(char v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(char v, const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(signed char v,
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned char v,
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
// ==================== Ints ====================
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(int v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int v, const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
-IntegralConvertResult FormatConvertImpl(unsigned v,
- const FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned v, const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(absl::int128 v,
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
IntegralConvertResult FormatConvertImpl(absl::uint128 v,
- const FormatConversionSpecImpl conv,
+ const ConversionSpec conv,
FormatSinkImpl *sink) {
return {ConvertIntArg(v, conv, sink)};
}
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
index 3c91be701f..7a93756305 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/arg.h
@@ -1,17 +1,3 @@
-// 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_
@@ -39,37 +25,16 @@ 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<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);
-}
+struct HasUserDefinedConvert<
+ T, void_t<decltype(AbslFormatConvert(
+ std::declval<const T&>(), std::declval<ConversionSpec>(),
+ std::declval<FormatSink*>()))>> : std::true_type {};
template <typename T>
class StreamedWrapper;
@@ -78,13 +43,6 @@ class StreamedWrapper;
// 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;
@@ -94,53 +52,27 @@ struct VoidPtr {
: value(ptr ? reinterpret_cast<uintptr_t>(ptr) : 0) {}
uintptr_t value;
};
-
-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);
+ConvertResult<Conv::p> FormatConvertImpl(VoidPtr v, ConversionSpec conv,
+ FormatSinkImpl* sink);
// Strings.
-StringConvertResult FormatConvertImpl(const std::string& v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-StringConvertResult FormatConvertImpl(string_view v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink);
-#if defined(ABSL_HAVE_STD_STRING_VIEW) && !defined(ABSL_USES_STD_STRING_VIEW)
-inline StringConvertResult FormatConvertImpl(std::string_view v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
- return FormatConvertImpl(absl::string_view(v.data(), v.size()), conv, sink);
-}
-#endif // ABSL_HAVE_STD_STRING_VIEW && !ABSL_USES_STD_STRING_VIEW
-
-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();
+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, absl::Cord>::value>::type* = nullptr>
+ConvertResult<Conv::s> FormatConvertImpl(const AbslCord& value,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
+ if (conv.conv() != ConversionChar::s) return {false};
+
+ bool is_left = conv.flags().left;
size_t space_remaining = 0;
int width = conv.width();
@@ -173,63 +105,55 @@ StringConvertResult FormatConvertImpl(const AbslCord& value,
return {true};
}
-using IntegralConvertResult = ArgConvertResult<FormatConversionCharSetUnion(
- FormatConversionCharSetInternal::c,
- FormatConversionCharSetInternal::kNumeric,
- FormatConversionCharSetInternal::kStar)>;
-using FloatingConvertResult =
- ArgConvertResult<FormatConversionCharSetInternal::kFloating>;
+using IntegralConvertResult =
+ ConvertResult<Conv::c | Conv::numeric | Conv::star>;
+using FloatingConvertResult = ConvertResult<Conv::floating>;
// Floats.
-FloatingConvertResult FormatConvertImpl(float v, FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(float v, ConversionSpec conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(double v, FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(double v, ConversionSpec conv,
FormatSinkImpl* sink);
-FloatingConvertResult FormatConvertImpl(long double v,
- FormatConversionSpecImpl conv,
+FloatingConvertResult FormatConvertImpl(long double v, ConversionSpec conv,
FormatSinkImpl* sink);
// Chars.
-IntegralConvertResult FormatConvertImpl(char v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(char v, ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(signed char v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(signed char v, ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned char v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned char v, ConversionSpec conv,
FormatSinkImpl* sink);
// Ints.
IntegralConvertResult FormatConvertImpl(short v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned short v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int v, ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(unsigned v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(unsigned v, ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(long long v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
IntegralConvertResult FormatConvertImpl(unsigned long long v, // NOLINT
- FormatConversionSpecImpl conv,
+ ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(int128 v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(int128 v, ConversionSpec conv,
FormatSinkImpl* sink);
-IntegralConvertResult FormatConvertImpl(uint128 v,
- FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(uint128 v, ConversionSpec conv,
FormatSinkImpl* sink);
template <typename T, enable_if_t<std::is_same<T, bool>::value, int> = 0>
-IntegralConvertResult FormatConvertImpl(T v, FormatConversionSpecImpl conv,
+IntegralConvertResult FormatConvertImpl(T v, ConversionSpec conv,
FormatSinkImpl* sink) {
return FormatConvertImpl(static_cast<int>(v), conv, sink);
}
@@ -240,12 +164,12 @@ template <typename T>
typename std::enable_if<std::is_enum<T>::value &&
!HasUserDefinedConvert<T>::value,
IntegralConvertResult>::type
-FormatConvertImpl(T v, FormatConversionSpecImpl conv, FormatSinkImpl* sink);
+FormatConvertImpl(T v, ConversionSpec conv, FormatSinkImpl* sink);
template <typename T>
-StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
- FormatConversionSpecImpl conv,
- FormatSinkImpl* out) {
+ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<T>& v,
+ ConversionSpec conv,
+ FormatSinkImpl* out) {
std::ostringstream oss;
oss << v.v_;
if (!oss) return {false};
@@ -256,24 +180,21 @@ StringConvertResult FormatConvertImpl(const StreamedWrapper<T>& v,
// until after FormatCountCapture is fully defined.
struct FormatCountCaptureHelper {
template <class T = int>
- static ArgConvertResult<FormatConversionCharSetInternal::n> ConvertHelper(
- const FormatCountCapture& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
+ static ConvertResult<Conv::n> ConvertHelper(const FormatCountCapture& v,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
const absl::enable_if_t<sizeof(T) != 0, FormatCountCapture>& v2 = v;
- if (conv.conversion_char() !=
- str_format_internal::FormatConversionCharInternal::n) {
- return {false};
- }
+ if (conv.conv() != str_format_internal::ConversionChar::n) return {false};
*v2.p_ = static_cast<int>(sink->size());
return {true};
}
};
template <class T = int>
-ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
- const FormatCountCapture& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* sink) {
+ConvertResult<Conv::n> FormatConvertImpl(const FormatCountCapture& v,
+ ConversionSpec conv,
+ FormatSinkImpl* sink) {
return FormatCountCaptureHelper::ConvertHelper(v, conv, sink);
}
@@ -282,13 +203,13 @@ ArgConvertResult<FormatConversionCharSetInternal::n> FormatConvertImpl(
struct FormatArgImplFriend {
template <typename Arg>
static bool ToInt(Arg arg, int* out) {
- // A value initialized FormatConversionSpecImpl has a `none` conv, which
- // tells the dispatcher to run the `int` conversion.
+ // A value initialized ConversionSpec 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, FormatConversionSpecImpl conv,
+ static bool Convert(Arg arg, str_format_internal::ConversionSpec conv,
FormatSinkImpl* out) {
return arg.dispatcher_(arg.data_, conv, out);
}
@@ -299,15 +220,6 @@ 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:
@@ -321,7 +233,7 @@ class FormatArgImpl {
char buf[kInlinedSpace];
};
- using Dispatcher = bool (*)(Data, FormatConversionSpecImpl, void* out);
+ using Dispatcher = bool (*)(Data, ConversionSpec, void* out);
template <typename T>
struct store_by_value
@@ -463,20 +375,15 @@ class FormatArgImpl {
}
template <typename T>
- static bool Dispatch(Data arg, FormatConversionSpecImpl spec, void* out) {
+ static bool Dispatch(Data arg, ConversionSpec spec, void* out) {
// A `none` conv indicates that we want the `int` conversion.
- if (ABSL_PREDICT_FALSE(spec.conversion_char() ==
- FormatConversionCharInternal::kNone)) {
+ if (ABSL_PREDICT_FALSE(spec.conv() == ConversionChar::none)) {
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;
}
@@ -484,9 +391,8 @@ class FormatArgImpl {
Dispatcher dispatcher_;
};
-#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
- E template bool FormatArgImpl::Dispatch<T>(Data, FormatConversionSpecImpl, \
- void*)
+#define ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(T, E) \
+ E template bool FormatArgImpl::Dispatch<T>(Data, ConversionSpec, void*)
#define ABSL_INTERNAL_FORMAT_DISPATCH_OVERLOADS_EXPAND_(...) \
ABSL_INTERNAL_FORMAT_DISPATCH_INSTANTIATE_(str_format_internal::VoidPtr, \
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
index 1261937c30..8d30d8b8ce 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/arg_test.cc
@@ -6,12 +6,6 @@
//
// https://www.apache.org/licenses/LICENSE-2.0
//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT 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>
@@ -29,17 +23,8 @@ 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));
@@ -74,7 +59,6 @@ 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);
}
@@ -111,9 +95,8 @@ TEST_F(FormatArgImplTest, OtherPtrDecayToVoidPtr) {
TEST_F(FormatArgImplTest, WorksWithCharArraysOfUnknownSize) {
std::string s;
FormatSinkImpl sink(&s);
- FormatConversionSpecImpl conv;
- FormatConversionSpecImplFriend::SetConversionChar(
- FormatConversionCharInternal::s, &conv);
+ ConversionSpec conv;
+ FormatConversionSpecImplFriend::SetConversionChar(ConversionChar::s, &conv);
FormatConversionSpecImplFriend::SetFlags(Flags(), &conv);
FormatConversionSpecImplFriend::SetWidth(-1, &conv);
FormatConversionSpecImplFriend::SetPrecision(-1, &conv);
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc
index c988ba8fd2..27522fdb4f 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/bind.cc
@@ -1,17 +1,3 @@
-// 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>
@@ -58,7 +44,7 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
if (static_cast<size_t>(arg_position - 1) >= pack_.size()) return false;
arg = &pack_[arg_position - 1]; // 1-based
- if (unbound->flags != Flags::kBasic) {
+ if (!unbound->flags.basic) {
int width = unbound->width.value();
bool force_left = false;
if (unbound->width.is_from_arg()) {
@@ -84,8 +70,9 @@ inline bool ArgContext::Bind(const UnboundConversion* unbound,
FormatConversionSpecImplFriend::SetPrecision(precision, bound);
if (force_left) {
- FormatConversionSpecImplFriend::SetFlags(unbound->flags | Flags::kLeft,
- bound);
+ Flags flags = unbound->flags;
+ flags.left = true;
+ FormatConversionSpecImplFriend::SetFlags(flags, bound);
} else {
FormatConversionSpecImplFriend::SetFlags(unbound->flags, bound);
}
@@ -160,7 +147,7 @@ class SummarizingConverter {
<< FormatConversionSpecImplFriend::FlagsToString(bound);
if (bound.width() >= 0) ss << bound.width();
if (bound.precision() >= 0) ss << "." << bound.precision();
- ss << bound.conversion_char() << "}";
+ ss << bound.conv() << "}";
Append(ss.str());
return true;
}
@@ -234,7 +221,7 @@ int FprintF(std::FILE* output, const UntypedFormatSpecImpl format,
errno = sink.error();
return -1;
}
- if (sink.count() > static_cast<size_t>(std::numeric_limits<int>::max())) {
+ if (sink.count() > std::numeric_limits<int>::max()) {
errno = EFBIG;
return -1;
}
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h b/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h
index b26cff6648..cf41b19748 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/bind.h
@@ -1,17 +1,3 @@
-// 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_
@@ -33,7 +19,7 @@ class UntypedFormatSpec;
namespace str_format_internal {
-class BoundConversion : public FormatConversionSpecImpl {
+class BoundConversion : public ConversionSpec {
public:
const FormatArgImpl* arg() const { return arg_; }
void set_arg(const FormatArgImpl* a) { arg_ = a; }
@@ -74,7 +60,7 @@ class UntypedFormatSpecImpl {
size_t size_;
};
-template <typename T, FormatConversionCharSet...>
+template <typename T, typename...>
struct MakeDependent {
using type = T;
};
@@ -82,7 +68,7 @@ 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 <FormatConversionCharSet... Args>
+template <typename... Args>
class FormatSpecTemplate
: public MakeDependent<UntypedFormatSpec, Args...>::type {
using Base = typename MakeDependent<UntypedFormatSpec, Args...>::type;
@@ -90,17 +76,17 @@ class FormatSpecTemplate
public:
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- // Honeypot overload for when the string is not constexpr.
+ // Honeypot overload for when the std::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 string is not constexpr.")));
+ __attribute__((unavailable("Format std::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
// just 'method is deleted'.
// To avoid checking the format twice, we just check that the format is
- // constexpr. If it is valid, then the overload below will kick in.
+ // constexpr. If is it valid, then the overload below will kick in.
// We add the template here to make this overload have lower priority.
template <typename = void>
FormatSpecTemplate(const char* s) // NOLINT
@@ -119,11 +105,13 @@ class FormatSpecTemplate
// Good format overload.
FormatSpecTemplate(const char* s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
+ "bad format trap")))
: Base(s) {}
FormatSpecTemplate(string_view s) // NOLINT
- __attribute__((enable_if(ValidFormatImpl<Args...>(s), "bad format trap")))
+ __attribute__((enable_if(ValidFormatImpl<ArgumentToConv<Args>()...>(s),
+ "bad format trap")))
: Base(s) {}
#else // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
@@ -133,15 +121,19 @@ class FormatSpecTemplate
#endif // ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
- template <
- FormatConversionCharSet... C,
- typename = typename std::enable_if<sizeof...(C) == sizeof...(Args)>::type,
- typename = typename std::enable_if<AllOf(Contains(Args,
- C)...)>::type>
+ template <Conv... C, typename = typename std::enable_if<
+ AllOf(sizeof...(C) == sizeof...(Args),
+ Contains(ArgumentToConv<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,
@@ -204,9 +196,9 @@ class StreamedWrapper {
private:
template <typename S>
- friend ArgConvertResult<FormatConversionCharSetInternal::s> FormatConvertImpl(
- const StreamedWrapper<S>& v, FormatConversionSpecImpl conv,
- FormatSinkImpl* out);
+ friend ConvertResult<Conv::s> FormatConvertImpl(const StreamedWrapper<S>& v,
+ ConversionSpec conv,
+ FormatSinkImpl* out);
const T& v_;
};
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/bind_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
index 1eef9c4326..64790a85fd 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/bind_test.cc
@@ -1,17 +1,3 @@
-// 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>
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h b/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h
index 2a2601eccf..8993a79b95 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/checker.h
@@ -1,17 +1,3 @@
-// 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_
@@ -38,6 +24,13 @@ 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;
+}
+
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
constexpr bool ContainsChar(const char* chars, char c) {
@@ -46,14 +39,14 @@ constexpr bool ContainsChar(const char* chars, char c) {
// A constexpr compatible list of Convs.
struct ConvList {
- const FormatConversionCharSet* array;
+ const Conv* array;
int count;
// We do the bound check here to avoid having to do it on the callers.
- // Returning an empty FormatConversionCharSet has the same effect as
- // short circuiting because it will never match any conversion.
- constexpr FormatConversionCharSet operator[](int i) const {
- return i < count ? array[i] : FormatConversionCharSet{};
+ // 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{};
}
constexpr ConvList without_front() const {
@@ -64,7 +57,7 @@ struct ConvList {
template <size_t count>
struct ConvListT {
// Make sure the array has size > 0.
- FormatConversionCharSet list[count ? count : 1];
+ Conv list[count ? count : 1];
};
constexpr char GetChar(string_view str, size_t index) {
@@ -317,7 +310,7 @@ class FormatParser {
ConvList args_;
};
-template <FormatConversionCharSet... C>
+template <Conv... C>
constexpr bool ValidFormatImpl(string_view format) {
return FormatParser(format,
{ConvListT<sizeof...(C)>{{C...}}.list, sizeof...(C)})
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
index 7c70f47d68..ea2a7681a6 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/checker_test.cc
@@ -1,17 +1,3 @@
-// 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"
@@ -23,22 +9,18 @@ ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
namespace {
-std::string ConvToString(FormatConversionCharSet conv) {
+std::string ConvToString(Conv conv) {
std::string out;
-#define CONV_SET_CASE(c) \
- if (Contains(conv, FormatConversionCharSetInternal::c)) { \
- out += #c; \
- }
+#define CONV_SET_CASE(c) \
+ if (Contains(conv, Conv::c)) out += #c;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(CONV_SET_CASE, )
#undef CONV_SET_CASE
- if (Contains(conv, FormatConversionCharSetInternal::kStar)) {
- out += "*";
- }
+ if (Contains(conv, Conv::star)) out += "*";
return out;
}
TEST(StrFormatChecker, ArgumentToConv) {
- FormatConversionCharSet conv = ArgumentToConv<std::string>();
+ Conv conv = ArgumentToConv<std::string>();
EXPECT_EQ(ConvToString(conv), "s");
conv = ArgumentToConv<const char*>();
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
index 91e0360901..cbcd7caf46 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/convert_test.cc
@@ -1,46 +1,20 @@
-// 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;
@@ -83,7 +57,7 @@ std::string Esc(const T &v) {
return oss.str();
}
-void StrAppendV(std::string *dst, const char *format, va_list ap) {
+void StrAppend(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];
@@ -124,79 +98,15 @@ void StrAppendV(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;
- StrAppendV(&result, format, ap);
+ StrAppend(&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>
@@ -229,9 +139,6 @@ TEST_F(FormatConvertTest, BasicString) {
TestStringConvert(static_cast<const char*>("hello"));
TestStringConvert(std::string("hello"));
TestStringConvert(string_view("hello"));
-#if defined(ABSL_HAVE_STD_STRING_VIEW)
- TestStringConvert(std::string_view("hello"));
-#endif // ABSL_HAVE_STD_STRING_VIEW
}
TEST_F(FormatConvertTest, NullString) {
@@ -556,130 +463,17 @@ TEST_F(FormatConvertTest, Uint128) {
}
}
-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", "%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());
+#ifdef _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
- TestWithMultipleFormatsHelper(floats, {});
-}
+ const char *const kFormats[] = {
+ "%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+",
+ "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
-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,
@@ -693,8 +487,12 @@ TEST_F(FormatConvertTest, Double) {
std::numeric_limits<double>::epsilon(),
std::numeric_limits<double>::epsilon() + 1,
std::numeric_limits<double>::infinity(),
- -std::numeric_limits<double>::infinity(),
- std::nan("")};
+ -std::numeric_limits<double>::infinity()};
+
+#ifndef __APPLE__
+ // Apple formats NaN differently (+nan) vs. (nan)
+ doubles.push_back(std::nan(""));
+#endif
// Some regression tests.
doubles.push_back(0.99999999999999989);
@@ -714,366 +512,43 @@ TEST_F(FormatConvertTest, Double) {
}
}
- // 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));
+ 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);
+ }
}
}
}
TEST_F(FormatConvertTest, LongDouble) {
- const NativePrintfTraits &native_traits = VerifyNativeImplementation();
- const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000",
+ const char *const kFormats[] = {"%", "%.3", "%8.5", "%9",
"%.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(),
@@ -1081,73 +556,28 @@ 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), result)
+ ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
+ FormatPack(format, {&arg, 1}))
<< fmt_str << " " << StrPrint("%.18Lg", d) << " "
- << StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d);
+ << StrPrint("%.999Lf", d);
}
}
}
}
-TEST_F(FormatConvertTest, IntAsDouble) {
- const NativePrintfTraits &native_traits = VerifyNativeImplementation();
+TEST_F(FormatConvertTest, IntAsFloat) {
const int kMin = std::numeric_limits<int>::min();
const int kMax = std::numeric_limits<int>::max();
const int ia[] = {
@@ -1163,17 +593,14 @@ TEST_F(FormatConvertTest, IntAsDouble) {
const char *fmt;
};
const double dx = static_cast<double>(fx);
- std::vector<Expectation> expect = {
- {__LINE__, StrPrint("%f", dx), "%f"},
- {__LINE__, StrPrint("%12f", dx), "%12f"},
- {__LINE__, StrPrint("%.12f", dx), "%.12f"},
- {__LINE__, StrPrint("%.12a", dx), "%.12a"},
+ 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" },
};
- 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) {
+ for (const Expectation &e : kExpect) {
SCOPED_TRACE(e.line);
SCOPED_TRACE(e.fmt);
UntypedFormatSpecImpl format(e.fmt);
@@ -1218,25 +645,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
index 484f6ebfc1..2e5bc2ce0b 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/extension.cc
@@ -23,50 +23,26 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-std::string FlagsToString(Flags v) {
+std::string Flags::ToString() const {
std::string s;
- s.append(FlagsContains(v, Flags::kLeft) ? "-" : "");
- s.append(FlagsContains(v, Flags::kShowPos) ? "+" : "");
- s.append(FlagsContains(v, Flags::kSignCol) ? " " : "");
- s.append(FlagsContains(v, Flags::kAlt) ? "#" : "");
- s.append(FlagsContains(v, Flags::kZero) ? "0" : "");
+ s.append(left ? "-" : "");
+ s.append(show_pos ? "+" : "");
+ s.append(sign_col ? " " : "");
+ s.append(alt ? "#" : "");
+ s.append(zero ? "0" : "");
return s;
}
-#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
-
-// 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 value, int width,
- int precision, bool left) {
+bool FormatSinkImpl::PutPaddedString(string_view v, int w, int p, bool l) {
size_t space_remaining = 0;
- 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);
+ 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);
space_remaining = Excess(shown.size(), space_remaining);
- if (!left) Append(space_remaining, ' ');
+ if (!l) Append(space_remaining, ' ');
Append(shown);
- if (left) Append(space_remaining, ' ');
+ if (l) Append(space_remaining, ' ');
return true;
}
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h b/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
index 55cbb56d0a..d1665753d1 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/extension.h
@@ -24,16 +24,11 @@
#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"
namespace absl {
ABSL_NAMESPACE_BEGIN
-
-enum class FormatConversionChar : uint8_t;
-enum class FormatConversionCharSet : uint64_t;
-
namespace str_format_internal {
class FormatRawSinkImpl {
@@ -107,7 +102,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 width, int precision, bool left);
+ bool PutPaddedString(string_view v, int w, int p, bool l);
template <typename T>
T Wrap() {
@@ -128,37 +123,23 @@ class FormatSinkImpl {
char buf_[1024];
};
-enum class Flags : uint8_t {
- kBasic = 0,
- kLeft = 1 << 0,
- kShowPos = 1 << 1,
- kSignCol = 1 << 2,
- kAlt = 1 << 3,
- kZero = 1 << 4,
- // This is not a real flag. It just exists to turn off kBasic when no other
- // flags are set. This is for when width/precision are specified.
- kNonBasic = 1 << 5,
+struct Flags {
+ bool basic : 1; // fastest conversion: no flags, width, or precision
+ bool left : 1; // "-"
+ bool show_pos : 1; // "+"
+ bool sign_col : 1; // " "
+ bool alt : 1; // "#"
+ bool zero : 1; // "0"
+ std::string ToString() const;
+ friend std::ostream& operator<<(std::ostream& os, const Flags& v) {
+ return os << v.ToString();
+ }
};
-constexpr Flags operator|(Flags a, Flags b) {
- return static_cast<Flags>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
-}
-
-constexpr bool FlagsContains(Flags haystack, Flags needle) {
- return (static_cast<uint8_t>(haystack) & static_cast<uint8_t>(needle)) ==
- static_cast<uint8_t>(needle);
-}
-
-std::string FlagsToString(Flags v);
-
-inline std::ostream& operator<<(std::ostream& os, Flags v) {
- return os << FlagsToString(v);
-}
-
// clang-format off
#define ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(X_VAL, X_SEP) \
/* text */ \
- X_VAL(c) X_SEP X_VAL(s) X_SEP \
+ X_VAL(c) X_SEP X_VAL(C) X_SEP X_VAL(s) 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 \
@@ -167,39 +148,14 @@ inline std::ostream& operator<<(std::ostream& os, Flags v) {
X_VAL(g) X_SEP X_VAL(G) X_SEP X_VAL(a) X_SEP X_VAL(A) X_SEP \
/* misc */ \
X_VAL(n) X_SEP X_VAL(p)
-// clang-format on
-
-// 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
+enum class FormatConversionChar : uint8_t {
+ c, C, s, S, // text
d, i, o, u, x, X, // int
f, F, e, E, g, G, a, A, // float
n, p, // misc
- kNone
- };
- // clang-format on
- public:
-#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);
+ kNone,
+ none = kNone
};
// clang-format on
@@ -207,56 +163,95 @@ inline FormatConversionChar FormatConversionCharFromChar(char c) {
switch (c) {
#define ABSL_INTERNAL_X_VAL(id) \
case #id[0]: \
- return FormatConversionCharInternal::id;
+ return FormatConversionChar::id;
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL, )
#undef ABSL_INTERNAL_X_VAL
}
- return FormatConversionCharInternal::kNone;
+ return FormatConversionChar::kNone;
+}
+
+inline int FormatConversionCharRadix(FormatConversionChar c) {
+ switch (c) {
+ case FormatConversionChar::x:
+ case FormatConversionChar::X:
+ case FormatConversionChar::a:
+ case FormatConversionChar::A:
+ case FormatConversionChar::p:
+ return 16;
+ case FormatConversionChar::o:
+ return 8;
+ default:
+ return 10;
+ }
}
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;
+ switch (c) {
+ case FormatConversionChar::X:
+ case FormatConversionChar::F:
+ case FormatConversionChar::E:
+ case FormatConversionChar::G:
+ case FormatConversionChar::A:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool FormatConversionCharIsSigned(FormatConversionChar c) {
+ switch (c) {
+ case FormatConversionChar::d:
+ case FormatConversionChar::i:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline bool FormatConversionCharIsIntegral(FormatConversionChar c) {
+ switch (c) {
+ case FormatConversionChar::d:
+ case FormatConversionChar::i:
+ case FormatConversionChar::u:
+ case FormatConversionChar::o:
+ case FormatConversionChar::x:
+ case FormatConversionChar::X:
+ 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;
+ switch (c) {
+ case FormatConversionChar::a:
+ case FormatConversionChar::e:
+ case FormatConversionChar::f:
+ case FormatConversionChar::g:
+ case FormatConversionChar::A:
+ case FormatConversionChar::E:
+ case FormatConversionChar::F:
+ case FormatConversionChar::G:
+ return true;
+ default:
+ return false;
}
}
inline char FormatConversionCharToChar(FormatConversionChar c) {
- if (c == FormatConversionCharInternal::kNone) {
- return '\0';
-
-#define ABSL_INTERNAL_X_VAL(e) \
- } else if (c == FormatConversionCharInternal::e) { \
+ switch (c) {
+#define ABSL_INTERNAL_X_VAL(e) \
+ case FormatConversionChar::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';
- }
-
+ ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_X_VAL,
+ ABSL_INTERNAL_X_SEP)
+ case FormatConversionChar::kNone:
+ return '\0';
#undef ABSL_INTERNAL_X_VAL
#undef ABSL_INTERNAL_X_SEP
+ }
+ return '\0';
}
// The associated char.
@@ -268,24 +263,20 @@ inline std::ostream& operator<<(std::ostream& os, FormatConversionChar v) {
struct FormatConversionSpecImplFriend;
-class FormatConversionSpecImpl {
+class FormatConversionSpec {
public:
// Width and precison are not specified, no flags are set.
- bool is_basic() const { return flags_ == Flags::kBasic; }
- bool has_left_flag() const { return FlagsContains(flags_, Flags::kLeft); }
- bool has_show_pos_flag() const {
- return FlagsContains(flags_, Flags::kShowPos);
- }
- bool has_sign_col_flag() const {
- return FlagsContains(flags_, Flags::kSignCol);
- }
- bool has_alt_flag() const { return FlagsContains(flags_, Flags::kAlt); }
- bool has_zero_flag() const { return FlagsContains(flags_, Flags::kZero); }
+ 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(FormatConversionSpecImpl, conv_) == 0, "");
+ static_assert(offsetof(FormatConversionSpec, conv_) == 0, "");
return conv_;
}
@@ -296,65 +287,41 @@ class FormatConversionSpecImpl {
// negative value.
int precision() const { return precision_; }
- template <typename T>
- T Wrap() {
- return T(*this);
- }
+ // Deprecated (use has_x_flag() instead).
+ Flags flags() const { return flags_; }
+ // Deprecated
+ FormatConversionChar conv() const { return conversion_char(); }
private:
friend struct str_format_internal::FormatConversionSpecImplFriend;
- FormatConversionChar conv_ = FormatConversionCharInternal::kNone;
+ FormatConversionChar conv_ = FormatConversionChar::kNone;
Flags flags_;
int width_;
int precision_;
};
struct FormatConversionSpecImplFriend final {
- static void SetFlags(Flags f, FormatConversionSpecImpl* conv) {
+ static void SetFlags(Flags f, FormatConversionSpec* conv) {
conv->flags_ = f;
}
static void SetConversionChar(FormatConversionChar c,
- FormatConversionSpecImpl* conv) {
+ FormatConversionSpec* conv) {
conv->conv_ = c;
}
- static void SetWidth(int w, FormatConversionSpecImpl* conv) {
- conv->width_ = w;
- }
- static void SetPrecision(int p, FormatConversionSpecImpl* conv) {
+ static void SetWidth(int w, FormatConversionSpec* conv) { conv->width_ = w; }
+ static void SetPrecision(int p, FormatConversionSpec* conv) {
conv->precision_ = p;
}
- static std::string FlagsToString(const FormatConversionSpecImpl& spec) {
- return str_format_internal::FlagsToString(spec.flags_);
+ static std::string FlagsToString(const FormatConversionSpec& 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) {
+constexpr uint64_t FormatConversionCharToConvValue(char conv) {
return
-#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
- conv == #c[0] \
- ? FormatConversionCharToConvInt(FormatConversionCharInternal::c) \
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ conv == #c[0] \
+ ? (uint64_t{1} << (1 + static_cast<uint8_t>(FormatConversionChar::c))) \
:
ABSL_INTERNAL_CONVERSION_CHARS_EXPAND_(ABSL_INTERNAL_CHAR_SET_CASE, )
#undef ABSL_INTERNAL_CHAR_SET_CASE
@@ -363,29 +330,28 @@ constexpr uint64_t FormatConversionCharToConvInt(char conv) {
: 0;
}
-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]);
+enum class FormatConversionCharSet : uint64_t {
+#define ABSL_INTERNAL_CHAR_SET_CASE(c) \
+ 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.
- 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;
+ kStar = FormatConversionCharToConvValue('*'),
+ // 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,
+
+ // The following are deprecated
+ star = kStar,
+ integral = kIntegral,
+ floating = kFloating,
+ numeric = kNumeric,
+ string = kString,
+ pointer = kPointer
};
// Type safe OR operator.
@@ -395,29 +361,18 @@ struct FormatConversionCharSetInternal {
// 2. We use "enum class" which would not work even if we accepted the decay.
constexpr FormatConversionCharSet operator|(FormatConversionCharSet a,
FormatConversionCharSet b) {
- return FormatConversionCharSetUnion(a, b);
+ return FormatConversionCharSet(static_cast<uint64_t>(a) |
+ static_cast<uint64_t>(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));
+constexpr FormatConversionCharSet ConversionCharToConv(char c) {
+ return FormatConversionCharSet(FormatConversionCharToConvValue(c));
}
-// Get a conversion with a single character in it.
-constexpr FormatConversionCharSet ToFormatConversionCharSet(
- FormatConversionCharSet c) {
- return c;
-}
-
-template <typename T>
-void ToFormatConversionCharSet(T) = delete;
-
// Checks whether `c` exists in `set`.
constexpr bool Contains(FormatConversionCharSet set, char c) {
- return (static_cast<uint64_t>(set) &
- static_cast<uint64_t>(FormatConversionCharToConvValue(c))) != 0;
+ return (static_cast<uint64_t>(set) & FormatConversionCharToConvValue(c)) != 0;
}
// Checks whether all the characters in `c` are contained in `set`
@@ -427,16 +382,31 @@ constexpr bool Contains(FormatConversionCharSet set,
static_cast<uint64_t>(c);
}
-// 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 type of the AbslFormatConvert() functions.
+// The FormatConversionCharSet template parameter is used to inform the
+// framework of what conversion characters are supported by that
+// AbslFormatConvert routine.
+template <FormatConversionCharSet C>
+struct FormatConvertResult {
+ static constexpr FormatConversionCharSet kConv = C;
+ bool value;
+};
+
+template <FormatConversionCharSet C>
+constexpr FormatConversionCharSet FormatConvertResult<C>::kConv;
// Return capacity - used, clipped to a minimum of 0.
inline size_t Excess(size_t used, size_t capacity) {
return used < capacity ? capacity - used : 0;
}
+// Type alias for use during migration.
+using ConversionChar = FormatConversionChar;
+using ConversionSpec = FormatConversionSpec;
+using Conv = FormatConversionCharSet;
+template <FormatConversionCharSet C>
+using ConvertResult = FormatConvertResult<C>;
+
} // namespace str_format_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
index 1c93fdb1c7..4e23fefbd5 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/extension_test.cc
@@ -19,26 +19,9 @@
#include <random>
#include <string>
-#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
+#include "gtest/gtest.h"
namespace {
@@ -80,19 +63,4 @@ 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/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
index b1c4068475..d4c647c3ed 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.cc
@@ -1,38 +1,12 @@
-// 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
@@ -40,905 +14,13 @@ namespace str_format_internal {
namespace {
-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) {
+char *CopyStringTo(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 FormatConversionSpecImpl &conv,
+bool FallbackToSnprintf(const Float v, const ConversionSpec &conv,
FormatSinkImpl *sink) {
int w = conv.width() >= 0 ? conv.width() : 0;
int p = conv.precision() >= 0 ? conv.precision() : -1;
@@ -951,17 +33,17 @@ bool FallbackToSnprintf(const Float v, const FormatConversionSpecImpl &conv,
if (std::is_same<long double, Float>()) {
*fp++ = 'L';
}
- *fp++ = FormatConversionCharToChar(conv.conversion_char());
+ *fp++ = FormatConversionCharToChar(conv.conv());
*fp = 0;
assert(fp < fmt + sizeof(fmt));
}
std::string space(512, '\0');
- absl::string_view result;
+ 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 = absl::string_view(space.data(), n);
+ result = string_view(space.data(), n);
break;
}
space.resize(n + 1);
@@ -1014,24 +96,21 @@ enum class FormatStyle { Fixed, Precision };
// Otherwise, return false.
template <typename Float>
bool ConvertNonNumericFloats(char sign_char, Float v,
- const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+ const ConversionSpec &conv, FormatSinkImpl *sink) {
char text[4], *ptr = text;
- if (sign_char != '\0') *ptr++ = sign_char;
+ if (sign_char) *ptr++ = sign_char;
if (std::isnan(v)) {
- ptr = std::copy_n(
- FormatConversionCharIsUpper(conv.conversion_char()) ? "NAN" : "nan", 3,
- ptr);
+ ptr = std::copy_n(FormatConversionCharIsUpper(conv.conv()) ? "NAN" : "nan",
+ 3, ptr);
} else if (std::isinf(v)) {
- ptr = std::copy_n(
- FormatConversionCharIsUpper(conv.conversion_char()) ? "INF" : "inf", 3,
- ptr);
+ ptr = std::copy_n(FormatConversionCharIsUpper(conv.conv()) ? "INF" : "inf",
+ 3, ptr);
} else {
return false;
}
return sink->PutPaddedString(string_view(text, ptr - text), conv.width(), -1,
- conv.has_left_flag());
+ conv.flags().left);
}
// Round up the last digit of the value.
@@ -1091,12 +170,7 @@ constexpr bool CanFitMantissa() {
template <typename Float>
struct Decomposed {
- 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;
+ Float mantissa;
int exponent;
};
@@ -1107,8 +181,7 @@ 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 {static_cast<typename Decomposed<Float>::MantissaType>(m), exp};
+ return {m, exp};
}
// Print 'digits' as decimal.
@@ -1277,32 +350,31 @@ bool FloatToBuffer(Decomposed<Float> decomposed, int precision, Buffer *out,
return false;
}
-void WriteBufferToSink(char sign_char, absl::string_view str,
- const FormatConversionSpecImpl &conv,
- FormatSinkImpl *sink) {
+void WriteBufferToSink(char sign_char, string_view str,
+ const ConversionSpec &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.has_left_flag()) {
+ if (conv.flags().left) {
right_spaces = missing_chars;
- } else if (conv.has_zero_flag()) {
+ } else if (conv.flags().zero) {
zeros = missing_chars;
} else {
left_spaces = missing_chars;
}
sink->Append(left_spaces, ' ');
- if (sign_char != '\0') sink->Append(1, sign_char);
+ if (sign_char) 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 FormatConversionSpecImpl &conv,
+bool FloatToSink(const Float v, const ConversionSpec &conv,
FormatSinkImpl *sink) {
// Print the sign or the sign column.
Float abs_v = v;
@@ -1310,9 +382,9 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
if (std::signbit(abs_v)) {
sign_char = '-';
abs_v = -abs_v;
- } else if (conv.has_show_pos_flag()) {
+ } else if (conv.flags().show_pos) {
sign_char = '+';
- } else if (conv.has_sign_col_flag()) {
+ } else if (conv.flags().sign_col) {
sign_char = ' ';
}
@@ -1329,91 +401,89 @@ bool FloatToSink(const Float v, const FormatConversionSpecImpl &conv,
Buffer buffer;
- FormatConversionChar c = conv.conversion_char();
+ switch (conv.conv()) {
+ 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;
- 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);
- }
- 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);
+ case ConversionChar::e:
+ case ConversionChar::E:
+ if (!FloatToBuffer<FormatStyle::Precision>(decomposed, precision, &buffer,
+ &exp)) {
+ return FallbackToSnprintf(v, conv, sink);
}
- 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;
+ if (!conv.flags().alt && buffer.back() == '.') buffer.pop_back();
+ PrintExponent(exp, FormatConversionCharIsUpper(conv.conv()) ? '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, FormatConversionCharIsUpper(conv.conv()) ? 'E' : 'e',
+ &buffer);
+ }
+ break;
+
+ case ConversionChar::a:
+ case ConversionChar::A:
+ return FallbackToSnprintf(v, conv, sink);
+
+ default:
+ return false;
}
WriteBufferToSink(sign_char,
- absl::string_view(buffer.begin, buffer.end - buffer.begin),
- conv, sink);
+ string_view(buffer.begin, buffer.end - buffer.begin), conv,
+ sink);
return true;
}
} // namespace
-bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(long double v, const ConversionSpec &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 FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(float v, const ConversionSpec &conv,
FormatSinkImpl *sink) {
- return FloatToSink(static_cast<double>(v), conv, sink);
+ return FloatToSink(v, conv, sink);
}
-bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(double v, const ConversionSpec &conv,
FormatSinkImpl *sink) {
return FloatToSink(v, conv, sink);
}
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
index 71100e7142..49a6a63630 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/float_conversion.h
@@ -1,17 +1,3 @@
-// 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_
@@ -21,13 +7,13 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-bool ConvertFloatImpl(float v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(float v, const ConversionSpec &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(double v, const ConversionSpec &conv,
FormatSinkImpl *sink);
-bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv,
+bool ConvertFloatImpl(long double v, const ConversionSpec &conv,
FormatSinkImpl *sink);
} // namespace str_format_internal
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/output.h b/third_party/abseil-cpp/absl/strings/internal/str_format/output.h
index 8030dae00f..28b288b7dd 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/output.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/output.h
@@ -30,6 +30,9 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
+
+class Cord;
+
namespace str_format_internal {
// RawSink implementation that writes into a char* buffer.
@@ -74,6 +77,12 @@ 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, absl::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);
}
@@ -82,11 +91,10 @@ 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(AbslFormatFlush(out, s)) {
- AbslFormatFlush(out, s);
+auto InvokeFlush(T* out, string_view s)
+ -> decltype(str_format_internal::AbslFormatFlush(out, s)) {
+ str_format_internal::AbslFormatFlush(out, s);
}
} // namespace str_format_internal
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/output_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/output_test.cc
index ce2e91a0bb..e54e6f70a5 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/output_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/output_test.cc
@@ -19,7 +19,6 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/cord.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -38,12 +37,6 @@ 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];
{
@@ -77,3 +70,4 @@ TEST(BufferRawSink, Limits) {
} // namespace
ABSL_NAMESPACE_END
} // namespace absl
+
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc
index 2c9c07dacc..aab68db94b 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc
@@ -1,17 +1,3 @@
-// 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>
@@ -31,70 +17,63 @@ namespace absl {
ABSL_NAMESPACE_BEGIN
namespace str_format_internal {
-using CC = FormatConversionCharInternal;
+using CC = ConversionChar;
using LM = LengthMod;
-// Abbreviations to fit in the table below.
-constexpr auto f_sign = Flags::kSignCol;
-constexpr auto f_alt = Flags::kAlt;
-constexpr auto f_pos = Flags::kShowPos;
-constexpr auto f_left = Flags::kLeft;
-constexpr auto f_zero = Flags::kZero;
-
ABSL_CONST_INIT const ConvTag kTags[256] = {
- {}, {}, {}, {}, {}, {}, {}, {}, // 00-07
- {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
- {}, {}, {}, {}, {}, {}, {}, {}, // 10-17
- {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
- f_sign, {}, {}, f_alt, {}, {}, {}, {}, // !"#$%&'
- {}, {}, {}, f_pos, {}, f_left, {}, {}, // ()*+,-./
- f_zero, {}, {}, {}, {}, {}, {}, {}, // 01234567
- {}, {}, {}, {}, {}, {}, {}, {}, // 89:;<=>?
- {}, CC::A, {}, {}, {}, CC::E, CC::F, CC::G, // @ABCDEFG
- {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
- {}, {}, {}, {}, {}, {}, {}, {}, // PQRSTUVW
- CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
- {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
- LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
- CC::p, LM::q, {}, CC::s, LM::t, CC::u, {}, {}, // pqrstuvw
- CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
- {}, {}, {}, {}, {}, {}, {}, {}, // 80-87
- {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
- {}, {}, {}, {}, {}, {}, {}, {}, // 90-97
- {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
- {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
- {}, {}, {}, {}, {}, {}, {}, {}, // a8-af
- {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
- {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
- {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
- {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
- {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
- {}, {}, {}, {}, {}, {}, {}, {}, // d8-df
- {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
- {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
- {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
- {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
+ {}, {}, {}, {}, {}, {}, {}, {}, // 00-07
+ {}, {}, {}, {}, {}, {}, {}, {}, // 08-0f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 10-17
+ {}, {}, {}, {}, {}, {}, {}, {}, // 18-1f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 20-27
+ {}, {}, {}, {}, {}, {}, {}, {}, // 28-2f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 30-37
+ {}, {}, {}, {}, {}, {}, {}, {}, // 38-3f
+ {}, CC::A, {}, CC::C, {}, CC::E, CC::F, CC::G, // @ABCDEFG
+ {}, {}, {}, {}, LM::L, {}, {}, {}, // HIJKLMNO
+ {}, {}, {}, CC::S, {}, {}, {}, {}, // PQRSTUVW
+ CC::X, {}, {}, {}, {}, {}, {}, {}, // XYZ[\]^_
+ {}, CC::a, {}, CC::c, CC::d, CC::e, CC::f, CC::g, // `abcdefg
+ LM::h, CC::i, LM::j, {}, LM::l, {}, CC::n, CC::o, // hijklmno
+ CC::p, LM::q, {}, CC::s, LM::t, CC::u, {}, {}, // pqrstuvw
+ CC::x, {}, LM::z, {}, {}, {}, {}, {}, // xyz{|}!
+ {}, {}, {}, {}, {}, {}, {}, {}, // 80-87
+ {}, {}, {}, {}, {}, {}, {}, {}, // 88-8f
+ {}, {}, {}, {}, {}, {}, {}, {}, // 90-97
+ {}, {}, {}, {}, {}, {}, {}, {}, // 98-9f
+ {}, {}, {}, {}, {}, {}, {}, {}, // a0-a7
+ {}, {}, {}, {}, {}, {}, {}, {}, // a8-af
+ {}, {}, {}, {}, {}, {}, {}, {}, // b0-b7
+ {}, {}, {}, {}, {}, {}, {}, {}, // b8-bf
+ {}, {}, {}, {}, {}, {}, {}, {}, // c0-c7
+ {}, {}, {}, {}, {}, {}, {}, {}, // c8-cf
+ {}, {}, {}, {}, {}, {}, {}, {}, // d0-d7
+ {}, {}, {}, {}, {}, {}, {}, {}, // d8-df
+ {}, {}, {}, {}, {}, {}, {}, {}, // e0-e7
+ {}, {}, {}, {}, {}, {}, {}, {}, // e8-ef
+ {}, {}, {}, {}, {}, {}, {}, {}, // f0-f7
+ {}, {}, {}, {}, {}, {}, {}, {}, // f8-ff
};
namespace {
bool CheckFastPathSetting(const UnboundConversion& conv) {
- bool width_precision_needed =
- conv.width.value() >= 0 || conv.precision.value() >= 0;
- if (width_precision_needed && conv.flags == Flags::kBasic) {
+ bool should_be_basic = !conv.flags.left && //
+ !conv.flags.show_pos && //
+ !conv.flags.sign_col && //
+ !conv.flags.alt && //
+ !conv.flags.zero && //
+ (conv.width.value() == -1) &&
+ (conv.precision.value() == -1);
+ if (should_be_basic != conv.flags.basic) {
fprintf(stderr,
"basic=%d left=%d show_pos=%d sign_col=%d alt=%d zero=%d "
"width=%d precision=%d\n",
- conv.flags == Flags::kBasic ? 1 : 0,
- FlagsContains(conv.flags, Flags::kLeft) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kShowPos) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kSignCol) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kAlt) ? 1 : 0,
- FlagsContains(conv.flags, Flags::kZero) ? 1 : 0, conv.width.value(),
- conv.precision.value());
- return false;
+ conv.flags.basic, conv.flags.left, conv.flags.show_pos,
+ conv.flags.sign_col, conv.flags.alt, conv.flags.zero,
+ conv.width.value(), conv.precision.value());
}
- return true;
+ return should_be_basic == conv.flags.basic;
}
template <bool is_positional>
@@ -138,21 +117,40 @@ const char *ConsumeConversion(const char *pos, const char *const end,
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
// We should start with the basic flag on.
- assert(conv->flags == Flags::kBasic);
+ assert(conv->flags.basic);
// Any non alpha character makes this conversion not basic.
// This includes flags (-+ #0), width (1-9, *) or precision (.).
// All conversion characters and length modifiers are alpha characters.
if (c < 'A') {
- while (c <= '0') {
- auto tag = GetTagForChar(c);
- if (tag.is_flags()) {
- conv->flags = conv->flags | tag.as_flags();
- ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
- } else {
- break;
+ conv->flags.basic = false;
+
+ for (; c <= '0';) {
+ // 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;
+ break;
+ case '+':
+ conv->flags.show_pos = true;
+ break;
+ case ' ':
+ conv->flags.sign_col = true;
+ break;
+ case '#':
+ conv->flags.alt = true;
+ break;
+ case '0':
+ conv->flags.zero = true;
+ break;
+ default:
+ goto flags_done;
}
+ ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
}
+flags_done:
if (c <= '9') {
if (c >= '0') {
@@ -161,12 +159,12 @@ const char *ConsumeConversion(const char *pos, const char *const end,
if (ABSL_PREDICT_FALSE(*next_arg != 0)) return nullptr;
// Positional conversion.
*next_arg = -1;
+ conv->flags = Flags();
+ conv->flags.basic = true;
return ConsumeConversion<true>(original_pos, end, conv, next_arg);
}
- conv->flags = conv->flags | Flags::kNonBasic;
conv->width.set_value(maybe_width);
} else if (c == '*') {
- conv->flags = conv->flags | Flags::kNonBasic;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (is_positional) {
if (ABSL_PREDICT_FALSE(c < '1' || c > '9')) return nullptr;
@@ -180,7 +178,6 @@ const char *ConsumeConversion(const char *pos, const char *const end,
}
if (c == '.') {
- conv->flags = conv->flags | Flags::kNonBasic;
ABSL_FORMAT_PARSER_INTERNAL_GET_CHAR();
if (std::isdigit(c)) {
conv->precision.set_value(parse_digits());
@@ -299,17 +296,15 @@ struct ParsedFormatBase::ParsedFormatConsumer {
char* data_pos;
};
-ParsedFormatBase::ParsedFormatBase(
- string_view format, bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs)
+ParsedFormatBase::ParsedFormatBase(string_view format, bool allow_ignored,
+ std::initializer_list<Conv> 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<FormatConversionCharSet> convs) const {
+ bool allow_ignored, std::initializer_list<Conv> convs) const {
std::unordered_set<int> used;
auto add_if_valid_conv = [&](int pos, char c) {
if (static_cast<size_t>(pos) > convs.size() ||
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h b/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h
index ad8646edff..45c90d1df0 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/parser.h
@@ -1,17 +1,3 @@
-// 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_
@@ -41,7 +27,10 @@ std::string LengthModToString(LengthMod v);
// The analyzed properties of a single specified conversion.
struct UnboundConversion {
- UnboundConversion() {}
+ UnboundConversion()
+ : flags() /* This is required to zero all the fields of flags. */ {
+ flags.basic = true;
+ }
class InputValue {
public:
@@ -76,9 +65,9 @@ struct UnboundConversion {
InputValue width;
InputValue precision;
- Flags flags = Flags::kBasic;
+ Flags flags;
LengthMod length_mod = LengthMod::none;
- FormatConversionChar conv = FormatConversionCharInternal::kNone;
+ ConversionChar conv = FormatConversionChar::kNone;
};
// Consume conversion spec prefix (not including '%') of [p, end) if valid.
@@ -90,43 +79,32 @@ const char* ConsumeUnboundConversion(const char* p, const char* end,
UnboundConversion* conv, int* next_arg);
// Helper tag class for the table below.
-// It allows fast `char -> ConversionChar/LengthMod/Flags` checking and
+// It allows fast `char -> ConversionChar/LengthMod` checking and
// conversions.
class ConvTag {
public:
- constexpr ConvTag(FormatConversionChar conversion_char) // NOLINT
- : tag_(static_cast<uint8_t>(conversion_char)) {}
+ constexpr ConvTag(ConversionChar 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_(0x80 | static_cast<uint8_t>(length_mod)) {}
- constexpr ConvTag(Flags flags) // NOLINT
- : tag_(0xc0 | static_cast<uint8_t>(flags)) {}
- constexpr ConvTag() : tag_(0xFF) {}
-
- bool is_conv() const { return (tag_ & 0x80) == 0; }
- bool is_length() const { return (tag_ & 0xC0) == 0x80; }
- bool is_flags() const { return (tag_ & 0xE0) == 0xC0; }
+ : tag_(~static_cast<std::int8_t>(length_mod)) {}
+ // Everything else is -128, which is negative to make is_conv() simpler.
+ constexpr ConvTag() : tag_(-128) {}
- FormatConversionChar as_conv() const {
+ bool is_conv() const { return tag_ >= 0; }
+ bool is_length() const { return tag_ < 0 && tag_ != -128; }
+ ConversionChar as_conv() const {
assert(is_conv());
- assert(!is_length());
- assert(!is_flags());
- return static_cast<FormatConversionChar>(tag_);
+ return static_cast<ConversionChar>(tag_);
}
LengthMod as_length() const {
- assert(!is_conv());
assert(is_length());
- assert(!is_flags());
- return static_cast<LengthMod>(tag_ & 0x3F);
- }
- Flags as_flags() const {
- assert(!is_conv());
- assert(!is_length());
- assert(is_flags());
- return static_cast<Flags>(tag_ & 0x1F);
+ return static_cast<LengthMod>(~tag_);
}
private:
- uint8_t tag_;
+ std::int8_t tag_;
};
extern const ConvTag kTags[256];
@@ -165,7 +143,7 @@ bool ParseFormatString(string_view src, Consumer consumer) {
auto tag = GetTagForChar(percent[1]);
if (tag.is_conv()) {
if (ABSL_PREDICT_FALSE(next_arg < 0)) {
- // This indicates an error in the format string.
+ // This indicates an error in the format std::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.
@@ -208,9 +186,8 @@ constexpr bool EnsureConstexpr(string_view s) {
class ParsedFormatBase {
public:
- explicit ParsedFormatBase(
- string_view format, bool allow_ignored,
- std::initializer_list<FormatConversionCharSet> convs);
+ explicit ParsedFormatBase(string_view format, bool allow_ignored,
+ std::initializer_list<Conv> convs);
ParsedFormatBase(const ParsedFormatBase& other) { *this = other; }
@@ -257,9 +234,8 @@ 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<FormatConversionCharSet> convs) const;
+ bool MatchesConversions(bool allow_ignored,
+ std::initializer_list<Conv> convs) const;
struct ParsedFormatConsumer;
@@ -304,14 +280,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 <FormatConversionCharSet... C>
+template <str_format_internal::Conv... C>
class ExtendedParsedFormat : public str_format_internal::ParsedFormatBase {
public:
explicit ExtendedParsedFormat(string_view format)
#ifdef ABSL_INTERNAL_ENABLE_FORMAT_CHECKER
__attribute__((
enable_if(str_format_internal::EnsureConstexpr(format),
- "Format string is not constexpr."),
+ "Format std::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
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc b/third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
index fe0d296360..1b1ee030f1 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
+++ b/third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc
@@ -1,17 +1,3 @@
-// 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>
@@ -55,23 +41,23 @@ TEST(LengthModTest, Names) {
TEST(ConversionCharTest, Names) {
struct Expectation {
- FormatConversionChar id;
+ ConversionChar id;
char name;
};
// clang-format off
const Expectation kExpect[] = {
-#define X(c) {FormatConversionCharInternal::c, #c[0]}
- X(c), X(s), // text
+#define X(c) {ConversionChar::c, #c[0]}
+ X(c), X(C), X(s), 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
- {FormatConversionCharInternal::kNone, '\0'},
+ {ConversionChar::none, '\0'},
};
// clang-format on
for (auto e : kExpect) {
SCOPED_TRACE(e.name);
- FormatConversionChar v = e.id;
+ ConversionChar v = e.id;
EXPECT_EQ(e.name, FormatConversionCharToChar(v));
}
}
@@ -270,22 +256,15 @@ TEST_F(ConsumeUnboundConversionTest, Flags) {
for (int k = 0; k < kNumFlags; ++k)
if ((i >> k) & 1) fmt += kAllFlags[k];
// flag order shouldn't matter
- if (rev == 1) {
- std::reverse(fmt.begin(), fmt.end());
- }
+ if (rev == 1) { std::reverse(fmt.begin(), fmt.end()); }
fmt += 'd';
SCOPED_TRACE(fmt);
EXPECT_TRUE(Run(fmt.c_str()));
- EXPECT_EQ(fmt.find('-') == std::string::npos,
- !FlagsContains(o.flags, Flags::kLeft));
- EXPECT_EQ(fmt.find('+') == std::string::npos,
- !FlagsContains(o.flags, Flags::kShowPos));
- EXPECT_EQ(fmt.find(' ') == std::string::npos,
- !FlagsContains(o.flags, Flags::kSignCol));
- EXPECT_EQ(fmt.find('#') == std::string::npos,
- !FlagsContains(o.flags, Flags::kAlt));
- EXPECT_EQ(fmt.find('0') == std::string::npos,
- !FlagsContains(o.flags, Flags::kZero));
+ EXPECT_EQ(fmt.find('-') == std::string::npos, !o.flags.left);
+ EXPECT_EQ(fmt.find('+') == std::string::npos, !o.flags.show_pos);
+ EXPECT_EQ(fmt.find(' ') == std::string::npos, !o.flags.sign_col);
+ EXPECT_EQ(fmt.find('#') == std::string::npos, !o.flags.alt);
+ EXPECT_EQ(fmt.find('0') == std::string::npos, !o.flags.zero);
}
}
}
@@ -295,14 +274,14 @@ TEST_F(ConsumeUnboundConversionTest, BasicFlag) {
for (const char* fmt : {"d", "llx", "G", "1$X"}) {
SCOPED_TRACE(fmt);
EXPECT_TRUE(Run(fmt));
- EXPECT_EQ(o.flags, Flags::kBasic);
+ EXPECT_TRUE(o.flags.basic);
}
// Flag is off
for (const char* fmt : {"3d", ".llx", "-G", "1$#X"}) {
SCOPED_TRACE(fmt);
EXPECT_TRUE(Run(fmt));
- EXPECT_NE(o.flags, Flags::kBasic);
+ EXPECT_FALSE(o.flags.basic);
}
}
@@ -370,8 +349,7 @@ TEST_F(ParsedFormatTest, ValueSemantics) {
ParsedFormatBase p2 = p1; // copy construct (empty)
EXPECT_EQ(SummarizeParsedFormat(p1), SummarizeParsedFormat(p2));
- p1 = ParsedFormatBase("hello%s", true,
- {FormatConversionCharSetInternal::s}); // move assign
+ p1 = ParsedFormatBase("hello%s", true, {Conv::s}); // move assign
EXPECT_EQ("[hello]{s:1$s}", SummarizeParsedFormat(p1));
ParsedFormatBase p3 = p1; // copy construct (nonempty)
@@ -389,7 +367,7 @@ TEST_F(ParsedFormatTest, ValueSemantics) {
struct ExpectParse {
const char* in;
- std::initializer_list<FormatConversionCharSet> conv_set;
+ std::initializer_list<Conv> conv_set;
const char* out;
};
@@ -399,9 +377,9 @@ TEST_F(ParsedFormatTest, Parsing) {
const ExpectParse kExpect[] = {
{"", {}, ""},
{"ab", {}, "[ab]"},
- {"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%d", {Conv::d}, "[a]{d:1$d}"},
+ {"a%+d", {Conv::d}, "[a]{+d:1$d}"},
+ {"a% d", {Conv::d}, "[a]{ d:1$d}"},
{"a%b %d", {}, "[a]!"}, // stop after error
};
for (const auto& e : kExpect) {
@@ -413,13 +391,13 @@ TEST_F(ParsedFormatTest, Parsing) {
TEST_F(ParsedFormatTest, ParsingFlagOrder) {
const ExpectParse kExpect[] = {
- {"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}"},
+ {"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}"},
};
for (const auto& e : kExpect) {
SCOPED_TRACE(e.in);
diff --git a/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h b/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h
index e766421617..b54f6ebe09 100644
--- a/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h
+++ b/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h
@@ -32,7 +32,7 @@
#include <array>
#include <initializer_list>
#include <iterator>
-#include <tuple>
+#include <map>
#include <type_traits>
#include <utility>
#include <vector>
@@ -51,9 +51,9 @@ ABSL_NAMESPACE_BEGIN
namespace strings_internal {
// This class is implicitly constructible from everything that absl::string_view
-// 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.
+// 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.
class ConvertibleToStringView {
public:
ConvertibleToStringView(const char* s) // NOLINT(runtime/explicit)
@@ -64,13 +64,42 @@ class ConvertibleToStringView {
ConvertibleToStringView(const std::string& s) // NOLINT(runtime/explicit)
: value_(s) {}
- // Disable conversion from rvalue strings.
- ConvertibleToStringView(std::string&& s) = delete;
- ConvertibleToStringView(const std::string&& s) = delete;
+ // 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;
+ }
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_;
};
@@ -182,13 +211,6 @@ template <typename T>
struct HasConstIterator<T, absl::void_t<typename T::const_iterator>>
: std::true_type {};
-// HasEmplace<T>::value is true iff there exists a method T::emplace().
-template <typename T, typename = void>
-struct HasEmplace : std::false_type {};
-template <typename T>
-struct HasEmplace<T, absl::void_t<decltype(std::declval<T>().emplace())>>
- : std::true_type {};
-
// IsInitializerList<T>::value is true iff T is an std::initializer_list. More
// details below in Splitter<> where this is used.
std::false_type IsInitializerListDispatch(...); // default: No
@@ -251,11 +273,7 @@ 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.
-//
-// 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>
+template <typename Delimiter, typename Predicate>
class Splitter {
public:
using DelimiterType = Delimiter;
@@ -263,12 +281,12 @@ class Splitter {
using const_iterator = strings_internal::SplitIterator<Splitter>;
using value_type = typename std::iterator_traits<const_iterator>::value_type;
- Splitter(StringType input_text, Delimiter d, Predicate p)
+ Splitter(ConvertibleToStringView 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_; }
+ absl::string_view text() const { return text_.value(); }
const Delimiter& delimiter() const { return delimiter_; }
const Predicate& predicate() const { return predicate_; }
@@ -318,7 +336,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;
@@ -379,46 +397,53 @@ class Splitter {
// value.
template <typename Container, typename First, typename Second>
struct ConvertToContainer<Container, std::pair<const First, Second>, true> {
- using iterator = typename Container::iterator;
-
Container operator()(const Splitter& splitter) const {
Container m;
- iterator it;
+ typename Container::iterator it;
bool insert = true;
- for (const absl::string_view sv : splitter) {
+ for (const auto sp : splitter) {
if (insert) {
- it = InsertOrEmplace(&m, sv);
+ it = Inserter<Container>::Insert(&m, First(sp), Second());
} else {
- it->second = Second(sv);
+ it->second = Second(sp);
}
insert = !insert;
}
return m;
}
- // Inserts the key and an empty value into the map, returning an iterator to
- // the inserted item. We use emplace() if available, otherwise insert().
- template <typename M>
- static absl::enable_if_t<HasEmplace<M>::value, iterator> InsertOrEmplace(
- M* m, absl::string_view key) {
- // Use piecewise_construct to support old versions of gcc in which pair
- // constructor can't otherwise construct string from string_view.
- return ToIter(m->emplace(std::piecewise_construct, std::make_tuple(key),
- std::tuple<>()));
- }
- template <typename M>
- static absl::enable_if_t<!HasEmplace<M>::value, iterator> InsertOrEmplace(
- M* m, absl::string_view key) {
- return ToIter(m->insert(std::make_pair(First(key), Second(""))));
- }
-
- static iterator ToIter(std::pair<iterator, bool> pair) {
- return pair.first;
- }
- static iterator ToIter(iterator iter) { return iter; }
+ // Inserts the key and value into the given map, returning an iterator to
+ // the inserted item. Specialized for std::map and std::multimap to use
+ // emplace() and adapt emplace()'s return value.
+ template <typename Map>
+ struct Inserter {
+ using M = Map;
+ template <typename... Args>
+ static typename M::iterator Insert(M* m, Args&&... args) {
+ return m->insert(std::make_pair(std::forward<Args>(args)...)).first;
+ }
+ };
+
+ template <typename... Ts>
+ struct Inserter<std::map<Ts...>> {
+ using M = std::map<Ts...>;
+ template <typename... Args>
+ static typename M::iterator Insert(M* m, Args&&... args) {
+ return m->emplace(std::make_pair(std::forward<Args>(args)...)).first;
+ }
+ };
+
+ template <typename... Ts>
+ struct Inserter<std::multimap<Ts...>> {
+ using M = std::multimap<Ts...>;
+ template <typename... Args>
+ static typename M::iterator Insert(M* m, Args&&... args) {
+ return m->emplace(std::make_pair(std::forward<Args>(args)...));
+ }
+ };
};
- StringType text_;
+ ConvertibleToStringView text_;
Delimiter delimiter_;
Predicate predicate_;
};
diff --git a/third_party/abseil-cpp/absl/strings/internal/string_constant.h b/third_party/abseil-cpp/absl/strings/internal/string_constant.h
deleted file mode 100644
index a11336b7f0..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/string_constant.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// 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/third_party/abseil-cpp/absl/strings/internal/string_constant_test.cc b/third_party/abseil-cpp/absl/strings/internal/string_constant_test.cc
deleted file mode 100644
index 392833cf15..0000000000
--- a/third_party/abseil-cpp/absl/strings/internal/string_constant_test.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// 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/third_party/abseil-cpp/absl/strings/match.cc b/third_party/abseil-cpp/absl/strings/match.cc
index 2d67250970..8127cb0c5e 100644
--- a/third_party/abseil-cpp/absl/strings/match.cc
+++ b/third_party/abseil-cpp/absl/strings/match.cc
@@ -19,22 +19,19 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-bool EqualsIgnoreCase(absl::string_view piece1,
- absl::string_view piece2) noexcept {
+bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2) {
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) noexcept {
+bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix) {
return (text.size() >= prefix.size()) &&
EqualsIgnoreCase(text.substr(0, prefix.size()), prefix);
}
-bool EndsWithIgnoreCase(absl::string_view text,
- absl::string_view suffix) noexcept {
+bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix) {
return (text.size() >= suffix.size()) &&
EqualsIgnoreCase(text.substr(text.size() - suffix.size()), suffix);
}
diff --git a/third_party/abseil-cpp/absl/strings/match.h b/third_party/abseil-cpp/absl/strings/match.h
index 038cbb3fa8..90fca98ad2 100644
--- a/third_party/abseil-cpp/absl/strings/match.h
+++ b/third_party/abseil-cpp/absl/strings/match.h
@@ -43,20 +43,14 @@ 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) noexcept {
+inline bool StrContains(absl::string_view haystack, absl::string_view needle) {
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) noexcept {
+inline bool StartsWith(absl::string_view text, absl::string_view prefix) {
return prefix.empty() ||
(text.size() >= prefix.size() &&
memcmp(text.data(), prefix.data(), prefix.size()) == 0);
@@ -65,8 +59,7 @@ inline bool StartsWith(absl::string_view text,
// EndsWith()
//
// Returns whether a given string `text` ends with `suffix`.
-inline bool EndsWith(absl::string_view text,
- absl::string_view suffix) noexcept {
+inline bool EndsWith(absl::string_view text, absl::string_view suffix) {
return suffix.empty() ||
(text.size() >= suffix.size() &&
memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
@@ -77,22 +70,19 @@ inline bool EndsWith(absl::string_view text,
//
// 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) noexcept;
+bool EqualsIgnoreCase(absl::string_view piece1, absl::string_view piece2);
// StartsWithIgnoreCase()
//
// 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) noexcept;
+bool StartsWithIgnoreCase(absl::string_view text, absl::string_view prefix);
// EndsWithIgnoreCase()
//
// 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) noexcept;
+bool EndsWithIgnoreCase(absl::string_view text, absl::string_view suffix);
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/match_test.cc b/third_party/abseil-cpp/absl/strings/match_test.cc
index 5841bc1b48..4c313dda14 100644
--- a/third_party/abseil-cpp/absl/strings/match_test.cc
+++ b/third_party/abseil-cpp/absl/strings/match_test.cc
@@ -66,23 +66,6 @@ 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/third_party/abseil-cpp/absl/strings/numbers.cc b/third_party/abseil-cpp/absl/strings/numbers.cc
index cbd84c918b..68c26dd6f8 100644
--- a/third_party/abseil-cpp/absl/strings/numbers.cc
+++ b/third_party/abseil-cpp/absl/strings/numbers.cc
@@ -31,8 +31,8 @@
#include <utility>
#include "absl/base/attributes.h"
+#include "absl/base/internal/bits.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"
@@ -46,13 +46,8 @@ ABSL_NAMESPACE_BEGIN
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(), *out);
if (result.ec == std::errc::invalid_argument) {
@@ -77,13 +72,8 @@ bool SimpleAtof(absl::string_view str, float* out) {
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(), *out);
if (result.ec == std::errc::invalid_argument) {
@@ -313,7 +303,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};
- auto shift = static_cast<unsigned>(bit_width(bits128_up));
+ int shift = 64 - base_internal::CountLeadingZeros64(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};
@@ -344,7 +334,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 = countl_zero(result.first);
+ int shift = base_internal::CountLeadingZeros64(result.first);
if (shift != 0) {
result.first = (result.first << shift) + (result.second >> (64 - shift));
result.second = (result.second << shift);
@@ -505,7 +495,7 @@ size_t numbers_internal::SixDigitsToBuffer(double d, char* const buffer) {
*out++ = '-';
d = -d;
}
- if (d > std::numeric_limits<double>::max()) {
+ if (std::isinf(d)) {
strcpy(out, "inf"); // NOLINT(runtime/printf)
return out + 3 - buffer;
}
@@ -746,18 +736,9 @@ 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<>
+template <>
const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
0,
0,
@@ -798,111 +779,6 @@ const uint128 LookupTables<uint128>::kVmaxOverBase[] = {
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());
@@ -1072,10 +948,6 @@ 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);
}
diff --git a/third_party/abseil-cpp/absl/strings/numbers.h b/third_party/abseil-cpp/absl/strings/numbers.h
index 4ae07c2d60..d872cca5dc 100644
--- a/third_party/abseil-cpp/absl/strings/numbers.h
+++ b/third_party/abseil-cpp/absl/strings/numbers.h
@@ -1,3 +1,4 @@
+//
// Copyright 2017 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -36,6 +37,7 @@
#include <type_traits>
#include "absl/base/config.h"
+#include "absl/base/internal/bits.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
@@ -46,7 +48,6 @@
#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"
@@ -96,25 +97,6 @@ ABSL_MUST_USE_RESULT bool SimpleAtod(absl::string_view str, double* out);
// unspecified state.
ABSL_MUST_USE_RESULT bool SimpleAtob(absl::string_view str, bool* out);
-// SimpleHexAtoi()
-//
-// Converts a hexadecimal string (optionally followed or preceded by ASCII
-// whitespace) to an integer, returning `true` if successful. Only valid base-16
-// hexadecimal integers whose value falls within the range of the integer type
-// (optionally preceded by a `+` or `-`) can be converted. A valid hexadecimal
-// value may include both upper and lowercase character symbols, and may
-// optionally include a leading "0x" (or "0X") number prefix, which is ignored
-// by this function. If any errors are encountered, this function returns
-// `false`, leaving `out` in an unspecified state.
-template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out);
-
-// Overloads of SimpleHexAtoi() for 128 bit integers.
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
- absl::int128* out);
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
- absl::uint128* out);
-
ABSL_NAMESPACE_END
} // namespace absl
@@ -143,11 +125,8 @@ inline void PutTwoDigits(size_t i, char* buf) {
}
// 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,
@@ -259,41 +238,28 @@ inline size_t FastHexToBufferZeroPad16(uint64_t val, char* out) {
}
#endif
// | 0x1 so that even 0 has 1 digit.
- return 16 - countl_zero(val | 0x1) / 4;
+ return 16 - absl::base_internal::CountLeadingZeros64(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 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);
}
-template <typename int_type>
-ABSL_MUST_USE_RESULT bool SimpleHexAtoi(absl::string_view str, int_type* out) {
- return numbers_internal::safe_strtoi_base(str, out, 16);
-}
-
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
- absl::int128* out) {
- return numbers_internal::safe_strto128_base(str, out, 16);
-}
-
-ABSL_MUST_USE_RESULT inline bool SimpleHexAtoi(absl::string_view str,
- absl::uint128* out) {
- return numbers_internal::safe_strtou128_base(str, out, 16);
-}
-
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/strings/numbers_test.cc b/third_party/abseil-cpp/absl/strings/numbers_test.cc
index 498c210d3b..68229b15a4 100644
--- a/third_party/abseil-cpp/absl/strings/numbers_test.cc
+++ b/third_party/abseil-cpp/absl/strings/numbers_test.cc
@@ -40,14 +40,11 @@
#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::SimpleHexAtoi;
using absl::numbers_internal::kSixDigitsToBufferSize;
using absl::numbers_internal::safe_strto32_base;
using absl::numbers_internal::safe_strto64_base;
@@ -57,6 +54,7 @@ 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;
@@ -252,7 +250,7 @@ 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;
- // (u)int128 can be streamed but not StrCat'd.
+ // uint128 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))
@@ -265,9 +263,7 @@ 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;
- // (u)int128 can be streamed but not StrCat'd.
- absl::strings_internal::OStringStream(&s) << in_value;
+ std::string s = absl::StrCat(in_value);
int_type x;
EXPECT_FALSE(SimpleAtoi(s, &x));
EXPECT_FALSE(SimpleAtoi(s.c_str(), &x));
@@ -350,71 +346,18 @@ TEST(NumbersTest, Atoi) {
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,
@@ -469,148 +412,6 @@ TEST(NumbersTest, Atoenum) {
VerifySimpleAtoiGood<E_biguint>(E_biguint_max32, E_biguint_max32);
}
-template <typename int_type, typename in_val_type>
-void VerifySimpleHexAtoiGood(in_val_type in_value, int_type exp_value) {
- std::string s;
- // uint128 can be streamed but not StrCat'd
- absl::strings_internal::OStringStream strm(&s);
- if (in_value >= 0) {
- strm << std::hex << in_value;
- } else {
- // Inefficient for small integers, but works with all integral types.
- strm << "-" << std::hex << -absl::uint128(in_value);
- }
- int_type x = static_cast<int_type>(~exp_value);
- EXPECT_TRUE(SimpleHexAtoi(s, &x))
- << "in_value=" << std::hex << in_value << " s=" << s << " x=" << x;
- EXPECT_EQ(exp_value, x);
- x = static_cast<int_type>(~exp_value);
- EXPECT_TRUE(SimpleHexAtoi(
- s.c_str(), &x)); // NOLINT: readability-redundant-string-conversions
- EXPECT_EQ(exp_value, x);
-}
-
-template <typename int_type, typename in_val_type>
-void VerifySimpleHexAtoiBad(in_val_type in_value) {
- std::string s;
- // uint128 can be streamed but not StrCat'd
- absl::strings_internal::OStringStream strm(&s);
- if (in_value >= 0) {
- strm << std::hex << in_value;
- } else {
- // Inefficient for small integers, but works with all integral types.
- strm << "-" << std::hex << -absl::uint128(in_value);
- }
- int_type x;
- EXPECT_FALSE(SimpleHexAtoi(s, &x));
- EXPECT_FALSE(SimpleHexAtoi(
- s.c_str(), &x)); // NOLINT: readability-redundant-string-conversions
-}
-
-TEST(NumbersTest, HexAtoi) {
- // SimpleHexAtoi(absl::string_view, int32_t)
- VerifySimpleHexAtoiGood<int32_t>(0, 0);
- VerifySimpleHexAtoiGood<int32_t>(0x42, 0x42);
- VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);
-
- VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::min(),
- std::numeric_limits<int32_t>::min());
- VerifySimpleHexAtoiGood<int32_t>(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max());
-
- // SimpleHexAtoi(absl::string_view, uint32_t)
- VerifySimpleHexAtoiGood<uint32_t>(0, 0);
- VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);
- VerifySimpleHexAtoiBad<uint32_t>(-0x42);
-
- VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int32_t>::min());
- VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max());
- VerifySimpleHexAtoiGood<uint32_t>(std::numeric_limits<uint32_t>::max(),
- std::numeric_limits<uint32_t>::max());
- VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::min());
- VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<int64_t>::max());
- VerifySimpleHexAtoiBad<uint32_t>(std::numeric_limits<uint64_t>::max());
-
- // SimpleHexAtoi(absl::string_view, int64_t)
- VerifySimpleHexAtoiGood<int64_t>(0, 0);
- VerifySimpleHexAtoiGood<int64_t>(0x42, 0x42);
- VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);
-
- VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::min(),
- std::numeric_limits<int32_t>::min());
- VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max());
- VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<uint32_t>::max(),
- std::numeric_limits<uint32_t>::max());
- VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::min(),
- std::numeric_limits<int64_t>::min());
- VerifySimpleHexAtoiGood<int64_t>(std::numeric_limits<int64_t>::max(),
- std::numeric_limits<int64_t>::max());
- VerifySimpleHexAtoiBad<int64_t>(std::numeric_limits<uint64_t>::max());
-
- // SimpleHexAtoi(absl::string_view, uint64_t)
- VerifySimpleHexAtoiGood<uint64_t>(0, 0);
- VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);
- VerifySimpleHexAtoiBad<uint64_t>(-0x42);
-
- VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int32_t>::min());
- VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max());
- VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint32_t>::max(),
- std::numeric_limits<uint32_t>::max());
- VerifySimpleHexAtoiBad<uint64_t>(std::numeric_limits<int64_t>::min());
- VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<int64_t>::max(),
- std::numeric_limits<int64_t>::max());
- VerifySimpleHexAtoiGood<uint64_t>(std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::max());
-
- // SimpleHexAtoi(absl::string_view, absl::uint128)
- VerifySimpleHexAtoiGood<absl::uint128>(0, 0);
- VerifySimpleHexAtoiGood<absl::uint128>(0x42, 0x42);
- VerifySimpleHexAtoiBad<absl::uint128>(-0x42);
-
- VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int32_t>::min());
- VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max());
- VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint32_t>::max(),
- std::numeric_limits<uint32_t>::max());
- VerifySimpleHexAtoiBad<absl::uint128>(std::numeric_limits<int64_t>::min());
- VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<int64_t>::max(),
- std::numeric_limits<int64_t>::max());
- VerifySimpleHexAtoiGood<absl::uint128>(std::numeric_limits<uint64_t>::max(),
- std::numeric_limits<uint64_t>::max());
- VerifySimpleHexAtoiGood<absl::uint128>(
- std::numeric_limits<absl::uint128>::max(),
- std::numeric_limits<absl::uint128>::max());
-
- // Some other types
- VerifySimpleHexAtoiGood<int>(-0x42, -0x42);
- VerifySimpleHexAtoiGood<int32_t>(-0x42, -0x42);
- VerifySimpleHexAtoiGood<uint32_t>(0x42, 0x42);
- VerifySimpleHexAtoiGood<unsigned int>(0x42, 0x42);
- VerifySimpleHexAtoiGood<int64_t>(-0x42, -0x42);
- VerifySimpleHexAtoiGood<long>(-0x42, -0x42); // NOLINT: runtime-int
- VerifySimpleHexAtoiGood<uint64_t>(0x42, 0x42);
- VerifySimpleHexAtoiGood<size_t>(0x42, 0x42);
- VerifySimpleHexAtoiGood<std::string::size_type>(0x42, 0x42);
-
- // Number prefix
- int32_t value;
- EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
- EXPECT_EQ(0x34234324, value);
-
- EXPECT_TRUE(safe_strto32_base("0X34234324", &value, 16));
- EXPECT_EQ(0x34234324, value);
-
- // ASCII whitespace
- EXPECT_TRUE(safe_strto32_base(" \t\n 34234324", &value, 16));
- EXPECT_EQ(0x34234324, value);
-
- EXPECT_TRUE(safe_strto32_base("34234324 \t\n ", &value, 16));
- EXPECT_EQ(0x34234324, value);
-}
-
TEST(stringtest, safe_strto32_base) {
int32_t value;
EXPECT_TRUE(safe_strto32_base("0x34234324", &value, 16));
@@ -680,7 +481,7 @@ TEST(stringtest, safe_strto32_base) {
EXPECT_TRUE(safe_strto32_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
- // Base-10 string version.
+ // Base-10 std::string version.
EXPECT_TRUE(safe_strto32_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
@@ -821,7 +622,7 @@ TEST(stringtest, safe_strto64_base) {
EXPECT_TRUE(safe_strto64_base(std::string("0x1234"), &value, 16));
EXPECT_EQ(0x1234, value);
- // Base-10 string version.
+ // Base-10 std::string version.
EXPECT_TRUE(safe_strto64_base("1234", &value, 10));
EXPECT_EQ(1234, value);
}
@@ -917,51 +718,6 @@ TEST(stringtest, safe_strtou128_random) {
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) {
diff --git a/third_party/abseil-cpp/absl/strings/str_cat.cc b/third_party/abseil-cpp/absl/strings/str_cat.cc
index f4a77493a4..d9afe2f385 100644
--- a/third_party/abseil-cpp/absl/strings/str_cat.cc
+++ b/third_party/abseil-cpp/absl/strings/str_cat.cc
@@ -141,12 +141,12 @@ namespace strings_internal {
std::string CatPieces(std::initializer_list<absl::string_view> pieces) {
std::string result;
size_t total_size = 0;
- for (const absl::string_view& piece : pieces) total_size += piece.size();
+ for (const absl::string_view piece : pieces) total_size += piece.size();
strings_internal::STLStringResizeUninitialized(&result, total_size);
char* const begin = &result[0];
char* out = begin;
- for (const absl::string_view& piece : pieces) {
+ for (const absl::string_view piece : pieces) {
const size_t this_size = piece.size();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
@@ -170,15 +170,15 @@ 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::STLStringResizeUninitializedAmortized(dest, total_size);
+ strings_internal::STLStringResizeUninitialized(dest, total_size);
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();
if (this_size != 0) {
memcpy(out, piece.data(), this_size);
@@ -199,7 +199,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b) {
ASSERT_NO_OVERLAP(*dest, a);
ASSERT_NO_OVERLAP(*dest, b);
std::string::size_type old_size = dest->size();
- strings_internal::STLStringResizeUninitializedAmortized(
+ strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size());
char* const begin = &(*dest)[0];
char* out = begin + old_size;
@@ -214,7 +214,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
ASSERT_NO_OVERLAP(*dest, b);
ASSERT_NO_OVERLAP(*dest, c);
std::string::size_type old_size = dest->size();
- strings_internal::STLStringResizeUninitializedAmortized(
+ strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size() + c.size());
char* const begin = &(*dest)[0];
char* out = begin + old_size;
@@ -231,7 +231,7 @@ void StrAppend(std::string* dest, const AlphaNum& a, const AlphaNum& b,
ASSERT_NO_OVERLAP(*dest, c);
ASSERT_NO_OVERLAP(*dest, d);
std::string::size_type old_size = dest->size();
- strings_internal::STLStringResizeUninitializedAmortized(
+ strings_internal::STLStringResizeUninitialized(
dest, old_size + a.size() + b.size() + c.size() + d.size());
char* const begin = &(*dest)[0];
char* out = begin + old_size;
diff --git a/third_party/abseil-cpp/absl/strings/str_cat.h b/third_party/abseil-cpp/absl/strings/str_cat.h
index a8a85c7322..292fa23597 100644
--- a/third_party/abseil-cpp/absl/strings/str_cat.h
+++ b/third_party/abseil-cpp/absl/strings/str_cat.h
@@ -253,7 +253,7 @@ class AlphaNum {
const std::basic_string<char, std::char_traits<char>, Allocator>& str)
: piece_(str) {}
- // Use string literals ":" instead of character literals ':'.
+ // Use std::string literals ":" instead of character literals ':'.
AlphaNum(char c) = delete; // NOLINT(runtime/explicit)
AlphaNum(const AlphaNum&) = delete;
diff --git a/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc
index 02c4dbe6d8..14c63b3fc9 100644
--- a/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc
+++ b/third_party/abseil-cpp/absl/strings/str_cat_benchmark.cc
@@ -23,7 +23,7 @@
namespace {
const char kStringOne[] = "Once Upon A Time, ";
-const char kStringTwo[] = "There was a string benchmark";
+const char kStringTwo[] = "There was a std::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,51 +137,4 @@ 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/third_party/abseil-cpp/absl/strings/str_cat_test.cc b/third_party/abseil-cpp/absl/strings/str_cat_test.cc
index f3770dc076..be39880be7 100644
--- a/third_party/abseil-cpp/absl/strings/str_cat_test.cc
+++ b/third_party/abseil-cpp/absl/strings/str_cat_test.cc
@@ -162,7 +162,7 @@ TEST(StrCat, Basics) {
EXPECT_EQ(result, "12345678910, 10987654321!");
std::string one =
- "1"; // Actually, it's the size of this string that we want; a
+ "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.
result = absl::StrCat("And a ", one.size(), " and a ",
@@ -375,7 +375,7 @@ TEST(StrAppend, Basics) {
EXPECT_EQ(result.substr(old_size), "12345678910, 10987654321!");
std::string one =
- "1"; // Actually, it's the size of this string that we want; a
+ "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.
old_size = result.size();
@@ -463,7 +463,7 @@ TEST(StrAppend, CornerCases) {
}
TEST(StrAppend, CornerCasesNonEmptyAppend) {
- for (std::string result : {"hello", "a string too long to fit in the SSO"}) {
+ for (std::string result : {"hello", "a std::string too long to fit in the SSO"}) {
const std::string expected = result;
absl::StrAppend(&result, "");
EXPECT_EQ(result, expected);
diff --git a/third_party/abseil-cpp/absl/strings/str_format.h b/third_party/abseil-cpp/absl/strings/str_format.h
index 4b05c70c23..2f9b4b2786 100644
--- a/third_party/abseil-cpp/absl/strings/str_format.h
+++ b/third_party/abseil-cpp/absl/strings/str_format.h
@@ -19,7 +19,7 @@
//
// 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, `str_format` uses a "format string" to
+// header. Like the `printf` family, the `str_format` uses a "format string" to
// perform argument substitutions based on types. See the `FormatSpec` section
// below for format string documentation.
//
@@ -57,7 +57,8 @@
// arbitrary sink types:
//
// * A generic `Format()` function to write outputs to arbitrary sink types,
-// which must implement a `FormatRawSink` interface.
+// which must implement a `RawSinkFormat` interface. (See
+// `str_format_sink.h` for more information.)
//
// * A `FormatUntyped()` function that is similar to `Format()` except it is
// loosely typed. `FormatUntyped()` is not a template and does not perform
@@ -65,7 +66,8 @@
// boolean from a runtime check.
//
// In addition, the `str_format` library provides extension points for
-// augmenting formatting to new types. See "StrFormat Extensions" below.
+// augmenting formatting to new types. These extensions are fully documented
+// within the `str_format_extension.h` header file.
#ifndef ABSL_STRINGS_STR_FORMAT_H_
#define ABSL_STRINGS_STR_FORMAT_H_
@@ -253,8 +255,8 @@ class FormatCountCapture {
// argument, etc.
template <typename... Args>
-using FormatSpec = str_format_internal::FormatSpecTemplate<
- str_format_internal::ArgumentToConv<Args>()...>;
+using FormatSpec =
+ typename str_format_internal::FormatSpecDeductionBarrier<Args...>::type;
// ParsedFormat
//
@@ -281,36 +283,9 @@ using FormatSpec = str_format_internal::FormatSpecTemplate<
// } 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<
- absl::str_format_internal::ToFormatConversionCharSet(Conv)...>;
-#endif // defined(__cpp_nontype_template_parameter_auto)
+ str_format_internal::ConversionCharToConv(Conv)...>;
// StrFormat()
//
@@ -457,16 +432,6 @@ 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 {
@@ -490,13 +455,12 @@ class FormatRawSink {
// `absl::FormatRawSink` interface), using a format string and zero or more
// additional arguments.
//
-// 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.
+// By default, `std::string` and `std::ostream` 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::StrAppendFormat()`, for
-// custom sinks. The format string, like format strings for `StrFormat()`, is
-// checked at compile-time.
+// `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.
//
// On failure, this function returns `false` and the state of the sink is
// unspecified.
@@ -536,7 +500,8 @@ using FormatArg = str_format_internal::FormatArgImpl;
// The arguments are provided in an `absl::Span<const absl::FormatArg>`.
// Each `absl::FormatArg` object binds to a single argument and keeps a
// reference to it. The values used to create the `FormatArg` objects must
-// outlive this function call.
+// outlive this function call. (See `str_format_arg.h` for information on
+// the `FormatArg` class.)_
//
// Example:
//
@@ -566,246 +531,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/strings/str_format_test.cc b/third_party/abseil-cpp/absl/strings/str_format_test.cc
index c60027ad29..acbdbf4a23 100644
--- a/third_party/abseil-cpp/absl/strings/str_format_test.cc
+++ b/third_party/abseil-cpp/absl/strings/str_format_test.cc
@@ -1,18 +1,3 @@
-// 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>
@@ -21,8 +6,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/strings/cord.h"
-#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
namespace absl {
@@ -258,7 +242,7 @@ class TempFile {
std::FILE* file() const { return file_; }
- // Read the file into a string.
+ // Read the file into a std::string.
std::string ReadFile() {
std::fseek(file_, 0, SEEK_END);
int size = std::ftell(file_);
@@ -361,12 +345,11 @@ 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" - string Eg: "C" -> "C", std::string("C++") -> "C++"
+ // "s" - std::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");
@@ -467,7 +450,7 @@ struct SummarizeConsumer {
if (conv.precision.is_from_arg()) {
*out += "." + std::to_string(conv.precision.get_from_arg()) + "$*";
}
- *out += str_format_internal::FormatConversionCharToChar(conv.conv);
+ *out += FormatConversionCharToChar(conv.conv);
*out += "}";
return true;
}
@@ -549,152 +532,76 @@ TEST_F(ParsedFormatTest, SimpleUncheckedIncorrect) {
EXPECT_FALSE((ParsedFormat<'s', 'd', 'g'>::New(format)));
}
-#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
+using str_format_internal::Conv;
TEST_F(ParsedFormatTest, UncheckedCorrect) {
- auto f =
- ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New("ABC%dDEF");
+ auto f = ExtendedParsedFormat<Conv::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<
- absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::kFloating>::New(format);
+ auto f2 =
+ ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(format);
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[FFF]{d:2$d}[ZZZ]{f:3$f}", SummarizeParsedFormat(*f2));
- f2 = ExtendedParsedFormat<
- absl::FormatConversionCharSet::kString, absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::kFloating>::New("%s %d %f");
+ f2 = ExtendedParsedFormat<Conv::string, Conv::d, Conv::floating>::New(
+ "%s %d %f");
ASSERT_TRUE(f2);
EXPECT_EQ("{s:1$s}[ ]{d:2$d}[ ]{f:3$f}", SummarizeParsedFormat(*f2));
- auto star =
- ExtendedParsedFormat<absl::FormatConversionCharSet::kStar,
- absl::FormatConversionCharSet::d>::New("%*d");
+ auto star = ExtendedParsedFormat<Conv::star, Conv::d>::New("%*d");
ASSERT_TRUE(star);
EXPECT_EQ("{*d:2$1$*d}", SummarizeParsedFormat(*star));
- auto dollar =
- ExtendedParsedFormat<absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::s>::New("%2$s %1$d");
+ auto dollar = ExtendedParsedFormat<Conv::d, Conv::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<
- absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::s>::New("%2$s %1$d %1$d");
+ dollar = ExtendedParsedFormat<Conv::d, Conv::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<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");
+ 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");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<
- absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::s>::NewAllowIgnored("%dABC");
+ f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("%dABC");
ASSERT_TRUE(f);
EXPECT_EQ("{d:1$d}[ABC]", SummarizeParsedFormat(*f));
- f = ExtendedParsedFormat<
- absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::s>::NewAllowIgnored("ABC%2$s");
+ f = ExtendedParsedFormat<Conv::d, Conv::s>::NewAllowIgnored("ABC%2$s");
ASSERT_TRUE(f);
EXPECT_EQ("[ABC]{2$s:2$s}", SummarizeParsedFormat(*f));
}
TEST_F(ParsedFormatTest, UncheckedMultipleTypes) {
- auto dx =
- ExtendedParsedFormat<absl::FormatConversionCharSet::d |
- absl::FormatConversionCharSet::x>::New("%1$d %1$x");
+ auto dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d %1$x");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}[ ]{1$x:1$x}", SummarizeParsedFormat(*dx));
- dx = ExtendedParsedFormat<absl::FormatConversionCharSet::d |
- absl::FormatConversionCharSet::x>::New("%1$d");
+ dx = ExtendedParsedFormat<Conv::d | Conv::x>::New("%1$d");
EXPECT_TRUE(dx);
EXPECT_EQ("{1$d:1$d}", SummarizeParsedFormat(*dx));
}
TEST_F(ParsedFormatTest, UncheckedIncorrect) {
- EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(""));
+ EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New(""));
- EXPECT_FALSE(ExtendedParsedFormat<absl::FormatConversionCharSet::d>::New(
- "ABC%dDEF%d"));
+ EXPECT_FALSE(ExtendedParsedFormat<Conv::d>::New("ABC%dDEF%d"));
std::string format = "%sFFF%dZZZ%f";
- EXPECT_FALSE(
- (ExtendedParsedFormat<absl::FormatConversionCharSet::s,
- absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::g>::New(format)));
+ EXPECT_FALSE((ExtendedParsedFormat<Conv::s, Conv::d, Conv::g>::New(format)));
}
TEST_F(ParsedFormatTest, RegressionMixPositional) {
- EXPECT_FALSE(
- (ExtendedParsedFormat<absl::FormatConversionCharSet::d,
- absl::FormatConversionCharSet::o>::New("%1$d %o")));
+ EXPECT_FALSE((ExtendedParsedFormat<Conv::d, Conv::o>::New("%1$d %o")));
}
using FormatWrapperTest = ::testing::Test;
@@ -719,38 +626,6 @@ TEST_F(FormatWrapperTest, ParsedFormat) {
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.
diff --git a/third_party/abseil-cpp/absl/strings/str_join.h b/third_party/abseil-cpp/absl/strings/str_join.h
index 33534536cf..ae5731a42b 100644
--- a/third_party/abseil-cpp/absl/strings/str_join.h
+++ b/third_party/abseil-cpp/absl/strings/str_join.h
@@ -144,7 +144,7 @@ strings_internal::DereferenceFormatterImpl<Formatter> DereferenceFormatter(
std::forward<Formatter>(f));
}
-// Function overload of `DereferenceFormatter()` for using a default
+// Function overload of `DererefenceFormatter()` for using a default
// `AlphaNumFormatter()`.
inline strings_internal::DereferenceFormatterImpl<
strings_internal::AlphaNumFormatterImpl>
diff --git a/third_party/abseil-cpp/absl/strings/str_join_test.cc b/third_party/abseil-cpp/absl/strings/str_join_test.cc
index 2be6256e43..921d9c2bfa 100644
--- a/third_party/abseil-cpp/absl/strings/str_join_test.cc
+++ b/third_party/abseil-cpp/absl/strings/str_join_test.cc
@@ -134,26 +134,26 @@ TEST(StrJoin, APIExamples) {
//
{
- // Empty range yields an empty string.
+ // Empty range yields an empty std::string.
std::vector<std::string> v;
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{
- // A range of 1 element gives a string with that element but no
+ // A range of 1 element gives a std::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 string element
+ // A range with a single empty std::string element
std::vector<std::string> v = {""};
EXPECT_EQ("", absl::StrJoin(v, "-"));
}
{
- // A range with 2 elements, one of which is an empty string
+ // A range with 2 elements, one of which is an empty std::string
std::vector<std::string> v = {"a", ""};
EXPECT_EQ("a-", absl::StrJoin(v, "-"));
}
diff --git a/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc b/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc
index 01331da29f..95b2dc105e 100644
--- a/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc
+++ b/third_party/abseil-cpp/absl/strings/str_replace_benchmark.cc
@@ -62,7 +62,7 @@ void SetUpStrings() {
}
}
// big_string->resize(50);
- // OK, we've set up the string, now let's set up expectations - first by
+ // OK, we've set up the std::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;
diff --git a/third_party/abseil-cpp/absl/strings/str_replace_test.cc b/third_party/abseil-cpp/absl/strings/str_replace_test.cc
index 9d8c7f75b5..1ca23aff55 100644
--- a/third_party/abseil-cpp/absl/strings/str_replace_test.cc
+++ b/third_party/abseil-cpp/absl/strings/str_replace_test.cc
@@ -25,7 +25,7 @@
TEST(StrReplaceAll, OneReplacement) {
std::string s;
- // Empty string.
+ // Empty std::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 string.
+ // Replace entire std::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 string.
+ // Empty std::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 string, one char at a time
+ // Replace entire std::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"}});
@@ -264,7 +264,7 @@ TEST(StrReplaceAll, Inplace) {
std::string s;
int reps;
- // Empty string.
+ // Empty std::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 string, one char at a time
+ // Replace entire std::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/third_party/abseil-cpp/absl/strings/str_split.cc b/third_party/abseil-cpp/absl/strings/str_split.cc
index e08c26b6bb..d0f8666910 100644
--- a/third_party/abseil-cpp/absl/strings/str_split.cc
+++ b/third_party/abseil-cpp/absl/strings/str_split.cc
@@ -42,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 string delimiters: always return a zero-length
+ // Special case for empty std::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);
}
@@ -127,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 string is shorter than the chunk size we say we
+ // If the std::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);
diff --git a/third_party/abseil-cpp/absl/strings/str_split.h b/third_party/abseil-cpp/absl/strings/str_split.h
index bfbca422a8..a79cd4a0ce 100644
--- a/third_party/abseil-cpp/absl/strings/str_split.h
+++ b/third_party/abseil-cpp/absl/strings/str_split.h
@@ -44,7 +44,6 @@
#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"
@@ -369,12 +368,6 @@ 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()
//------------------------------------------------------------------------------
@@ -495,50 +488,22 @@ using EnableSplitIfString =
// 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,
- absl::string_view>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, AllowEmpty>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- 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>(
+ return strings_internal::Splitter<DelimiterType, AllowEmpty>(
std::move(text), DelimiterType(d), AllowEmpty());
}
template <typename Delimiter, typename Predicate>
strings_internal::Splitter<
- typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate,
- absl::string_view>
+ typename strings_internal::SelectDelimiter<Delimiter>::type, Predicate>
StrSplit(strings_internal::ConvertibleToStringView text, Delimiter d,
Predicate p) {
using DelimiterType =
typename strings_internal::SelectDelimiter<Delimiter>::type;
- 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>(
+ return strings_internal::Splitter<DelimiterType, Predicate>(
std::move(text), DelimiterType(d), std::move(p));
}
diff --git a/third_party/abseil-cpp/absl/strings/str_split_test.cc b/third_party/abseil-cpp/absl/strings/str_split_test.cc
index 1b4427b849..02f27bc414 100644
--- a/third_party/abseil-cpp/absl/strings/str_split_test.cc
+++ b/third_party/abseil-cpp/absl/strings/str_split_test.cc
@@ -27,12 +27,8 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
-#include "absl/base/dynamic_annotations.h"
+#include "absl/base/dynamic_annotations.h" // for RunningOnValgrind
#include "absl/base/macros.h"
-#include "absl/container/btree_map.h"
-#include "absl/container/btree_set.h"
-#include "absl/container/flat_hash_map.h"
-#include "absl/container/node_hash_map.h"
#include "absl/strings/numbers.h"
namespace {
@@ -75,7 +71,7 @@ TEST(Split, TraitsTest) {
// namespaces just like callers will need to use.
TEST(Split, APIExamples) {
{
- // Passes string delimiter. Assumes the default of ByString.
+ // Passes std::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"));
@@ -101,7 +97,7 @@ TEST(Split, APIExamples) {
}
{
- // Uses the Literal string "=>" as the delimiter.
+ // Uses the Literal std::string "=>" as the delimiter.
const std::vector<std::string> v = absl::StrSplit("a=>b=>c", "=>");
EXPECT_THAT(v, ElementsAre("a", "b", "c"));
}
@@ -125,17 +121,17 @@ TEST(Split, APIExamples) {
}
{
- // Splits the input string into individual characters by using an empty
- // string as the delimiter.
+ // Splits the input std::string into individual characters by using an empty
+ // std::string as the delimiter.
std::vector<std::string> v = absl::StrSplit("abc", "");
EXPECT_THAT(v, ElementsAre("a", "b", "c"));
}
{
- // Splits string data with embedded NUL characters, using NUL as the
+ // Splits std::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 string when constructing the absl::string_view
- // delimiter. Instead, a non-empty string containing NUL can be used as the
+ // 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
// delimiter.
std::string embedded_nulls("a\0b\0c", 5);
std::string null_delim("\0", 1);
@@ -369,7 +365,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"));
@@ -407,10 +403,6 @@ TEST(Splitter, ConversionOperator) {
TestConversionOperator<std::set<std::string>>(splitter);
TestConversionOperator<std::multiset<absl::string_view>>(splitter);
TestConversionOperator<std::multiset<std::string>>(splitter);
- TestConversionOperator<absl::btree_set<absl::string_view>>(splitter);
- TestConversionOperator<absl::btree_set<std::string>>(splitter);
- TestConversionOperator<absl::btree_multiset<absl::string_view>>(splitter);
- TestConversionOperator<absl::btree_multiset<std::string>>(splitter);
TestConversionOperator<std::unordered_set<std::string>>(splitter);
// Tests conversion to map-like objects.
@@ -427,36 +419,8 @@ TEST(Splitter, ConversionOperator) {
TestMapConversionOperator<std::multimap<std::string, absl::string_view>>(
splitter);
TestMapConversionOperator<std::multimap<std::string, std::string>>(splitter);
- TestMapConversionOperator<
- absl::btree_map<absl::string_view, absl::string_view>>(splitter);
- TestMapConversionOperator<absl::btree_map<absl::string_view, std::string>>(
- splitter);
- TestMapConversionOperator<absl::btree_map<std::string, absl::string_view>>(
- splitter);
- TestMapConversionOperator<absl::btree_map<std::string, std::string>>(
- splitter);
- TestMapConversionOperator<
- absl::btree_multimap<absl::string_view, absl::string_view>>(splitter);
- TestMapConversionOperator<
- absl::btree_multimap<absl::string_view, std::string>>(splitter);
- TestMapConversionOperator<
- absl::btree_multimap<std::string, absl::string_view>>(splitter);
- TestMapConversionOperator<absl::btree_multimap<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
@@ -472,7 +436,7 @@ TEST(Splitter, ConversionOperator) {
// less-than, equal-to, and more-than 2 strings.
TEST(Splitter, ToPair) {
{
- // Empty string
+ // Empty std::string
std::pair<std::string, std::string> p = absl::StrSplit("", ',');
EXPECT_EQ("", p.first);
EXPECT_EQ("", p.second);
@@ -601,7 +565,7 @@ TEST(Split, AcceptsCertainTemporaries) {
TEST(Split, Temporary) {
// 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,
+ // 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.
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))
@@ -687,14 +651,14 @@ TEST(Split, UTF8) {
// Tests splitting utf8 strings and utf8 delimiters.
std::string utf8_string = u8"\u03BA\u1F79\u03C3\u03BC\u03B5";
{
- // A utf8 input string with an ascii delimiter.
+ // A utf8 input std::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 string and a utf8 delimiter.
+ // A utf8 input std::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 =
@@ -703,7 +667,7 @@ TEST(Split, UTF8) {
}
{
- // A utf8 input string and ByAnyChar with ascii chars.
+ // A utf8 input std::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"));
@@ -850,10 +814,10 @@ TEST(Delimiter, ByString) {
ByString comma_string(",");
TestComma(comma_string);
- // The first occurrence of empty string ("") in a string is at position 0.
+ // The first occurrence of empty std::string ("") in a std::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 string
+ // be an infinite loop in the SplitIterator code. To avoid this, empty std::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
@@ -912,7 +876,7 @@ TEST(Delimiter, ByAnyChar) {
EXPECT_FALSE(IsFoundAt("=", two_delims, -1));
// ByAnyChar behaves just like ByString when given a delimiter of empty
- // string. That is, it always returns a zero-length absl::string_view
+ // std::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));
@@ -943,19 +907,13 @@ TEST(Delimiter, ByLength) {
}
TEST(Split, WorksWithLargeStrings) {
-#if defined(ABSL_HAVE_ADDRESS_SANITIZER) || \
- defined(ABSL_HAVE_MEMORY_SANITIZER) || defined(ABSL_HAVE_THREAD_SANITIZER)
- constexpr size_t kSize = (uint32_t{1} << 26) + 1; // 64M + 1 byte
-#else
- constexpr size_t kSize = (uint32_t{1} << 31) + 1; // 2G + 1 byte
-#endif
if (sizeof(size_t) > 4) {
- std::string s(kSize, 'x');
+ std::string s((uint32_t{1} << 31) + 1, 'x'); // 2G + 1 byte
s.back() = '-';
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 string.
+ // testing::StartsWith is too slow with a 2G std::string.
EXPECT_EQ('x', v[0][0]);
EXPECT_EQ('x', v[0][1]);
EXPECT_EQ('x', v[0][3]);
diff --git a/third_party/abseil-cpp/absl/strings/string_view.cc b/third_party/abseil-cpp/absl/strings/string_view.cc
index d596e08cde..c5f5de936d 100644
--- a/third_party/abseil-cpp/absl/strings/string_view.cc
+++ b/third_party/abseil-cpp/absl/strings/string_view.cc
@@ -78,8 +78,8 @@ std::ostream& operator<<(std::ostream& o, string_view piece) {
return o;
}
-string_view::size_type string_view::find(string_view s,
- size_type pos) const noexcept {
+string_view::size_type string_view::find(string_view s, size_type pos) const
+ noexcept {
if (empty() || pos > length_) {
if (empty() && pos == 0 && s.empty()) return 0;
return npos;
@@ -98,8 +98,8 @@ string_view::size_type string_view::find(char c, size_type pos) const noexcept {
return result != nullptr ? result - ptr_ : npos;
}
-string_view::size_type string_view::rfind(string_view s,
- size_type pos) const noexcept {
+string_view::size_type string_view::rfind(string_view s, size_type pos) const
+ noexcept {
if (length_ < s.length_) return npos;
if (s.empty()) return std::min(length_, pos);
const char* last = ptr_ + std::min(length_ - s.length_, pos) + s.length_;
@@ -108,8 +108,8 @@ string_view::size_type string_view::rfind(string_view s,
}
// Search range is [0..pos] inclusive. If pos == npos, search everything.
-string_view::size_type string_view::rfind(char c,
- size_type pos) const noexcept {
+string_view::size_type string_view::rfind(char c, size_type pos) const
+ noexcept {
// Note: memrchr() is not available on Windows.
if (empty()) return npos;
for (size_type i = std::min(pos, length_ - 1);; --i) {
@@ -121,8 +121,9 @@ string_view::size_type string_view::rfind(char c,
return npos;
}
-string_view::size_type string_view::find_first_of(
- string_view s, size_type pos) const noexcept {
+string_view::size_type string_view::find_first_of(string_view s,
+ size_type pos) const
+ noexcept {
if (empty() || s.empty()) {
return npos;
}
@@ -137,8 +138,9 @@ string_view::size_type string_view::find_first_of(
return npos;
}
-string_view::size_type string_view::find_first_not_of(
- string_view s, size_type pos) const noexcept {
+string_view::size_type string_view::find_first_not_of(string_view s,
+ size_type pos) const
+ noexcept {
if (empty()) return npos;
// Avoid the cost of LookupTable() for a single-character search.
if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos);
@@ -151,8 +153,9 @@ string_view::size_type string_view::find_first_not_of(
return npos;
}
-string_view::size_type string_view::find_first_not_of(
- char c, size_type pos) const noexcept {
+string_view::size_type string_view::find_first_not_of(char c,
+ size_type pos) const
+ noexcept {
if (empty()) return npos;
for (; pos < length_; ++pos) {
if (ptr_[pos] != c) {
@@ -177,8 +180,9 @@ string_view::size_type string_view::find_last_of(string_view s,
return npos;
}
-string_view::size_type string_view::find_last_not_of(
- string_view s, size_type pos) const noexcept {
+string_view::size_type string_view::find_last_not_of(string_view s,
+ size_type pos) const
+ noexcept {
if (empty()) return npos;
size_type i = std::min(pos, length_ - 1);
if (s.empty()) return i;
@@ -194,8 +198,9 @@ string_view::size_type string_view::find_last_not_of(
return npos;
}
-string_view::size_type string_view::find_last_not_of(
- char c, size_type pos) const noexcept {
+string_view::size_type string_view::find_last_not_of(char c,
+ size_type pos) const
+ noexcept {
if (empty()) return npos;
size_type i = std::min(pos, length_ - 1);
for (;; --i) {
diff --git a/third_party/abseil-cpp/absl/strings/string_view.h b/third_party/abseil-cpp/absl/strings/string_view.h
index a4c9a6526c..1861ea62a9 100644
--- a/third_party/abseil-cpp/absl/strings/string_view.h
+++ b/third_party/abseil-cpp/absl/strings/string_view.h
@@ -36,7 +36,6 @@
#include <limits>
#include <string>
-#include "absl/base/attributes.h"
#include "absl/base/config.h"
#include "absl/base/internal/throw_delegate.h"
#include "absl/base/macros.h"
@@ -49,7 +48,7 @@
namespace absl {
ABSL_NAMESPACE_BEGIN
-using string_view = std::string_view;
+using std::string_view;
ABSL_NAMESPACE_END
} // namespace absl
@@ -62,12 +61,6 @@ ABSL_NAMESPACE_END
#define ABSL_INTERNAL_STRING_VIEW_MEMCMP memcmp
#endif // ABSL_HAVE_BUILTIN(__builtin_memcmp)
-#if defined(__cplusplus) && __cplusplus >= 201402L
-#define ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR constexpr
-#else
-#define ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
-#endif
-
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -118,11 +111,6 @@ ABSL_NAMESPACE_BEGIN
// 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
@@ -187,20 +175,18 @@ class string_view {
template <typename Allocator>
string_view( // NOLINT(runtime/explicit)
- const std::basic_string<char, std::char_traits<char>, Allocator>& str
- ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept
+ const std::basic_string<char, std::char_traits<char>, Allocator>&
+ str) noexcept
// This is implemented in terms of `string_view(p, n)` so `str.size()`
// doesn't need to be reevaluated after `ptr_` is set.
- // The length check is also skipped since it is unnecessary and causes
- // code bloat.
- : string_view(str.data(), str.size(), SkipCheckLengthTag{}) {}
+ : string_view(str.data(), str.size()) {}
// Implicit constructor of a `string_view` from NUL-terminated `str`. When
// accepting possibly null strings, use `absl::NullSafeStringView(str)`
// instead (see below).
- // The length check is skipped since it is unnecessary and causes code bloat.
constexpr string_view(const char* str) // NOLINT(runtime/explicit)
- : ptr_(str), length_(str ? StrlenInternal(str) : 0) {}
+ : ptr_(str),
+ 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)
@@ -273,7 +259,9 @@ class string_view {
// string_view::size()
//
// Returns the number of characters in the `string_view`.
- constexpr size_type size() const noexcept { return length_; }
+ constexpr size_type size() const noexcept {
+ return length_;
+ }
// string_view::length()
//
@@ -295,7 +283,7 @@ class string_view {
// 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 ABSL_HARDENING_ASSERT(i < size()), ptr_[i];
+ return ABSL_ASSERT(i < size()), ptr_[i];
}
// string_view::at()
@@ -315,14 +303,14 @@ class string_view {
//
// Returns the first element of a `string_view`.
constexpr const_reference front() const {
- return ABSL_HARDENING_ASSERT(!empty()), ptr_[0];
+ return ABSL_ASSERT(!empty()), ptr_[0];
}
// string_view::back()
//
// Returns the last element of a `string_view`.
constexpr const_reference back() const {
- return ABSL_HARDENING_ASSERT(!empty()), ptr_[size() - 1];
+ return ABSL_ASSERT(!empty()), ptr_[size() - 1];
}
// string_view::data()
@@ -331,7 +319,7 @@ class string_view {
// 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
- // string.
+ // std::string.
constexpr const_pointer data() const noexcept { return ptr_; }
// Modifiers
@@ -339,9 +327,9 @@ class string_view {
// string_view::remove_prefix()
//
// Removes the first `n` characters from the `string_view`. Note that the
- // underlying string is not changed, only the view.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
+ // underlying std::string is not changed, only the view.
+ void remove_prefix(size_type n) {
+ assert(n <= length_);
ptr_ += n;
length_ -= n;
}
@@ -349,16 +337,16 @@ class string_view {
// string_view::remove_suffix()
//
// Removes the last `n` characters from the `string_view`. Note that the
- // underlying string is not changed, only the view.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_suffix(size_type n) {
- ABSL_HARDENING_ASSERT(n <= length_);
+ // underlying std::string is not changed, only the view.
+ void remove_suffix(size_type n) {
+ assert(n <= length_);
length_ -= n;
}
// string_view::swap()
//
// Swaps this `string_view` with another `string_view`.
- ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void swap(string_view& s) noexcept {
+ void swap(string_view& s) noexcept {
auto t = *this;
*this = s;
s = t;
@@ -394,21 +382,21 @@ class string_view {
// 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`.
- // Use absl::ClippedSubstr if you need a truncating substr operation.
- constexpr string_view substr(size_type pos = 0, 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 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);
}
// string_view::compare()
//
- // Performs a lexicographical comparison between this `string_view` and
- // another `string_view` `x`, returning a negative value if `*this` is less
- // than `x`, 0 if `*this` is equal to `x`, and a positive value if `*this`
- // is greater than `x`.
+ // 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
+ // 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.
constexpr int compare(string_view x) const noexcept {
return CompareImpl(length_, x.length_,
Min(length_, x.length_) == 0
@@ -419,31 +407,31 @@ class string_view {
// Overload of `string_view::compare()` for comparing a substring of the
// 'string_view` and another `absl::string_view`.
- constexpr int compare(size_type pos1, size_type count1, string_view v) const {
+ int compare(size_type pos1, size_type count1, string_view v) const {
return substr(pos1, count1).compare(v);
}
// Overload of `string_view::compare()` for comparing a substring of the
// `string_view` and a substring of another `absl::string_view`.
- constexpr int compare(size_type pos1, size_type count1, string_view v,
- size_type pos2, size_type count2) const {
+ int compare(size_type pos1, size_type count1, string_view v, size_type pos2,
+ size_type count2) const {
return substr(pos1, count1).compare(v.substr(pos2, count2));
}
// Overload of `string_view::compare()` for comparing a `string_view` and a
- // a different C-style string `s`.
- constexpr int compare(const char* s) const { return compare(string_view(s)); }
+ // a different C-style std::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 string C-style string `s`.
- constexpr int compare(size_type pos1, size_type count1, const char* s) const {
+ // `string_view` and a different std::string C-style std::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 string `s`.
- constexpr int compare(size_type pos1, size_type count1, const char* s,
- size_type count2) const {
+ // `string_view` and a substring of a different C-style std::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));
}
@@ -460,92 +448,48 @@ class string_view {
// within the `string_view`.
size_type find(char c, size_type pos = 0) const noexcept;
- // Overload of `string_view::find()` for finding a substring of a different
- // C-style string `s` within the `string_view`.
- size_type find(const char* s, size_type pos, size_type count) const {
- return find(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find()` for finding a different C-style string
- // `s` within the `string_view`.
- size_type find(const char* s, size_type pos = 0) const {
- return find(string_view(s), pos);
- }
-
// string_view::rfind()
//
// Finds the last occurrence of a substring `s` within the `string_view`,
// returning the position of the first character's match, or `npos` if no
// match was found.
- size_type rfind(string_view s, size_type pos = npos) const noexcept;
+ size_type rfind(string_view s, size_type pos = npos) const
+ noexcept;
// Overload of `string_view::rfind()` for finding the last given character `c`
// within the `string_view`.
size_type rfind(char c, size_type pos = npos) const noexcept;
- // Overload of `string_view::rfind()` for finding a substring of a different
- // C-style string `s` within the `string_view`.
- size_type rfind(const char* s, size_type pos, size_type count) const {
- return rfind(string_view(s, count), pos);
- }
-
- // Overload of `string_view::rfind()` for finding a different C-style string
- // `s` within the `string_view`.
- size_type rfind(const char* s, size_type pos = npos) const {
- return rfind(string_view(s), pos);
- }
-
// string_view::find_first_of()
//
// Finds the first occurrence of any of the characters in `s` within the
// `string_view`, returning the start position of the match, or `npos` if no
// match was found.
- size_type find_first_of(string_view s, size_type pos = 0) const noexcept;
+ size_type find_first_of(string_view s, size_type pos = 0) const
+ noexcept;
// Overload of `string_view::find_first_of()` for finding a character `c`
// within the `string_view`.
- size_type find_first_of(char c, size_type pos = 0) const noexcept {
+ size_type find_first_of(char c, size_type pos = 0) const
+ noexcept {
return find(c, pos);
}
- // Overload of `string_view::find_first_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_first_of(const char* s, size_type pos,
- size_type count) const {
- return find_first_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_first_of()` for finding a different C-style
- // string `s` within the `string_view`.
- size_type find_first_of(const char* s, size_type pos = 0) const {
- return find_first_of(string_view(s), pos);
- }
-
// string_view::find_last_of()
//
// Finds the last occurrence of any of the characters in `s` within the
// `string_view`, returning the start position of the match, or `npos` if no
// match was found.
- size_type find_last_of(string_view s, size_type pos = npos) const noexcept;
+ size_type find_last_of(string_view s, size_type pos = npos) const
+ noexcept;
// Overload of `string_view::find_last_of()` for finding a character `c`
// within the `string_view`.
- size_type find_last_of(char c, size_type pos = npos) const noexcept {
+ size_type find_last_of(char c, size_type pos = npos) const
+ noexcept {
return rfind(c, pos);
}
- // Overload of `string_view::find_last_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_last_of(const char* s, size_type pos, size_type count) const {
- return find_last_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_last_of()` for finding a different C-style
- // string `s` within the `string_view`.
- size_type find_last_of(const char* s, size_type pos = npos) const {
- return find_last_of(string_view(s), pos);
- }
-
// string_view::find_first_not_of()
//
// Finds the first occurrence of any of the characters not in `s` within the
@@ -557,56 +501,25 @@ class string_view {
// that is not `c` within the `string_view`.
size_type find_first_not_of(char c, size_type pos = 0) const noexcept;
- // Overload of `string_view::find_first_not_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_first_not_of(const char* s, size_type pos,
- size_type count) const {
- return find_first_not_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_first_not_of()` for finding a different
- // C-style string `s` within the `string_view`.
- size_type find_first_not_of(const char* s, size_type pos = 0) const {
- return find_first_not_of(string_view(s), pos);
- }
-
// string_view::find_last_not_of()
//
// Finds the last occurrence of any of the characters not in `s` within the
// `string_view`, returning the start position of the last non-match, or
// `npos` if no non-match was found.
size_type find_last_not_of(string_view s,
- size_type pos = npos) const noexcept;
+ size_type pos = npos) const noexcept;
// Overload of `string_view::find_last_not_of()` for finding a character
// that is not `c` within the `string_view`.
- size_type find_last_not_of(char c, size_type pos = npos) const noexcept;
-
- // Overload of `string_view::find_last_not_of()` for finding a substring of a
- // different C-style string `s` within the `string_view`.
- size_type find_last_not_of(const char* s, size_type pos,
- size_type count) const {
- return find_last_not_of(string_view(s, count), pos);
- }
-
- // Overload of `string_view::find_last_not_of()` for finding a different
- // C-style string `s` within the `string_view`.
- size_type find_last_not_of(const char* s, size_type pos = npos) const {
- return find_last_not_of(string_view(s), pos);
- }
+ size_type find_last_not_of(char c, size_type pos = npos) const
+ noexcept;
private:
- // The constructor from std::string delegates to this constructor.
- // See the comment on that constructor for the rationale.
- struct SkipCheckLengthTag {};
- string_view(const char* data, size_type len, SkipCheckLengthTag) noexcept
- : ptr_(data), length_(len) {}
-
static constexpr size_type kMaxSize =
(std::numeric_limits<difference_type>::max)();
static constexpr size_type CheckLengthInternal(size_type len) {
- return ABSL_HARDENING_ASSERT(len <= kMaxSize), len;
+ return (void)ABSL_ASSERT(len <= kMaxSize), len;
}
static constexpr size_type StrlenInternal(const char* str) {
@@ -677,7 +590,6 @@ std::ostream& operator<<(std::ostream& o, string_view piece);
ABSL_NAMESPACE_END
} // namespace absl
-#undef ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR
#undef ABSL_INTERNAL_STRING_VIEW_MEMCMP
#endif // ABSL_USES_STD_STRING_VIEW
diff --git a/third_party/abseil-cpp/absl/strings/string_view_test.cc b/third_party/abseil-cpp/absl/strings/string_view_test.cc
index 2c13dd1c14..7b1d56fac7 100644
--- a/third_party/abseil-cpp/absl/strings/string_view_test.cc
+++ b/third_party/abseil-cpp/absl/strings/string_view_test.cc
@@ -28,7 +28,6 @@
#include "gtest/gtest.h"
#include "absl/base/config.h"
#include "absl/base/dynamic_annotations.h"
-#include "absl/base/options.h"
#if defined(ABSL_HAVE_STD_STRING_VIEW) || defined(__ANDROID__)
// We don't control the death messaging when using std::string_view.
@@ -411,7 +410,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 string nonsense
+ // empty std::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);
@@ -439,7 +438,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 string nonsense
+ // empty std::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);
@@ -449,24 +448,6 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(d.find('x', 4), absl::string_view::npos);
EXPECT_EQ(e.find('x', 7), absl::string_view::npos);
- EXPECT_EQ(a.find(b.data(), 1, 0), 1);
- EXPECT_EQ(a.find(c.data(), 9, 0), 9);
- EXPECT_EQ(a.find(c.data(), absl::string_view::npos, 0),
- absl::string_view::npos);
- EXPECT_EQ(b.find(c.data(), absl::string_view::npos, 0),
- absl::string_view::npos);
- // empty string nonsense
- EXPECT_EQ(d.find(b.data(), 4, 0), absl::string_view::npos);
- EXPECT_EQ(e.find(b.data(), 7, 0), absl::string_view::npos);
-
- EXPECT_EQ(a.find(b.data(), 1), absl::string_view::npos);
- EXPECT_EQ(a.find(c.data(), 9), 23);
- EXPECT_EQ(a.find(c.data(), absl::string_view::npos), absl::string_view::npos);
- EXPECT_EQ(b.find(c.data(), absl::string_view::npos), absl::string_view::npos);
- // empty string nonsense
- EXPECT_EQ(d.find(b.data(), 4), absl::string_view::npos);
- EXPECT_EQ(e.find(b.data(), 7), absl::string_view::npos);
-
EXPECT_EQ(a.rfind(b), 0);
EXPECT_EQ(a.rfind(b, 1), 0);
EXPECT_EQ(a.rfind(c), 23);
@@ -484,7 +465,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 string nonsense
+ // empty std::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()));
@@ -503,19 +484,11 @@ TEST(StringViewTest, STL2) {
EXPECT_EQ(f.rfind('\0', 12), 3);
EXPECT_EQ(f.rfind('3'), 2);
EXPECT_EQ(f.rfind('5'), 5);
- // empty string nonsense
+ // empty std::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);
EXPECT_EQ(e.rfind('o', 7), absl::string_view::npos);
-
- EXPECT_EQ(a.rfind(b.data(), 1, 0), 1);
- EXPECT_EQ(a.rfind(c.data(), 22, 0), 22);
- EXPECT_EQ(a.rfind(c.data(), 1, 0), 1);
- EXPECT_EQ(a.rfind(c.data(), 0, 0), 0);
- EXPECT_EQ(b.rfind(c.data(), 0, 0), 0);
- EXPECT_EQ(d.rfind(b.data(), 4, 0), 0);
- EXPECT_EQ(e.rfind(b.data(), 7, 0), 0);
}
// Continued from STL2
@@ -547,7 +520,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 string nonsense
+ // empty std::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);
@@ -565,7 +538,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 string nonsense
+ // empty std::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);
@@ -593,7 +566,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 string nonsense
+ // empty std::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);
@@ -633,7 +606,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 string nonsense
+ // empty std::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);
@@ -659,7 +632,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 string nonsense
+ // empty std::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);
@@ -683,7 +656,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 string nonsense
+ // empty std::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);
@@ -704,9 +677,8 @@ TEST(StringViewTest, STL2Substr) {
EXPECT_EQ(a.substr(23, 3), c);
EXPECT_EQ(a.substr(23, 99), c);
EXPECT_EQ(a.substr(0), a);
- EXPECT_EQ(a.substr(), a);
EXPECT_EQ(a.substr(3, 2), "de");
- // empty string nonsense
+ // empty std::string nonsense
EXPECT_EQ(d.substr(0, 99), e);
// use of npos
EXPECT_EQ(a.substr(0, absl::string_view::npos), a);
@@ -848,7 +820,7 @@ TEST(StringViewTest, FrontBackSingleChar) {
TEST(StringViewTest, FrontBackEmpty) {
#ifndef ABSL_USES_STD_STRING_VIEW
-#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+#ifndef NDEBUG
// 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;
@@ -887,7 +859,7 @@ TEST(StringViewTest, NULLInput) {
EXPECT_EQ(s.size(), 0);
// .ToString() on a absl::string_view with nullptr should produce the empty
- // string.
+ // std::string.
EXPECT_EQ("", std::string(s));
#endif // ABSL_HAVE_STRING_VIEW_FROM_NULLPTR
}
@@ -942,9 +914,9 @@ TEST(StringViewTest, At) {
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);
+ EXPECT_THROW(abc.at(3), std::out_of_range);
#else
- ABSL_EXPECT_DEATH_IF_SUPPORTED((void)abc.at(3), "absl::string_view::at");
+ ABSL_EXPECT_DEATH_IF_SUPPORTED(abc.at(3), "absl::string_view::at");
#endif
}
@@ -1005,7 +977,7 @@ TEST(StringViewTest, ConstexprCompiles) {
#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 string
+ // calls `std::char_traits<char>::length(const char*)` to get the std::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
@@ -1114,31 +1086,6 @@ TEST(StringViewTest, ConstexprCompiles) {
EXPECT_EQ(sp_npos, -1);
}
-constexpr char ConstexprMethodsHelper() {
-#if defined(__cplusplus) && __cplusplus >= 201402L
- absl::string_view str("123", 3);
- str.remove_prefix(1);
- str.remove_suffix(1);
- absl::string_view bar;
- str.swap(bar);
- return bar.front();
-#else
- return '2';
-#endif
-}
-
-TEST(StringViewTest, ConstexprMethods) {
- // remove_prefix, remove_suffix, swap
- static_assert(ConstexprMethodsHelper() == '2', "");
-
- // substr
- 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));
@@ -1175,7 +1122,7 @@ TEST(StringViewTest, Noexcept) {
TEST(StringViewTest, BoundsCheck) {
#ifndef ABSL_USES_STD_STRING_VIEW
-#if !defined(NDEBUG) || ABSL_OPTION_HARDENED
+#ifndef NDEBUG
// Abseil's string_view implementation has bounds-checking in debug mode.
absl::string_view h = "hello";
ABSL_EXPECT_DEATH_IF_SUPPORTED(h[5], "");
@@ -1221,11 +1168,11 @@ TEST(FindOneCharTest, EdgeCases) {
EXPECT_EQ(absl::string_view::npos, a.rfind('x'));
}
-#ifndef ABSL_HAVE_THREAD_SANITIZER // Allocates too much memory for tsan.
+#ifndef THREAD_SANITIZER // Allocates too much memory for tsan.
TEST(HugeStringView, TwoPointTwoGB) {
- if (sizeof(size_t) <= 4)
+ if (sizeof(size_t) <= 4 || RunningOnValgrind())
return;
- // Try a huge string piece.
+ // Try a huge std::string piece.
const size_t size = size_t{2200} * 1000 * 1000;
std::string s(size, 'a');
absl::string_view sp(s);
@@ -1235,7 +1182,7 @@ TEST(HugeStringView, TwoPointTwoGB) {
sp.remove_suffix(2);
EXPECT_EQ(size - 1 - 2, sp.length());
}
-#endif // ABSL_HAVE_THREAD_SANITIZER
+#endif // THREAD_SANITIZER
#if !defined(NDEBUG) && !defined(ABSL_USES_STD_STRING_VIEW)
TEST(NonNegativeLenTest, NonNegativeLen) {
diff --git a/third_party/abseil-cpp/absl/strings/substitute.cc b/third_party/abseil-cpp/absl/strings/substitute.cc
index 8980b198c2..5b69a3ef00 100644
--- a/third_party/abseil-cpp/absl/strings/substitute.cc
+++ b/third_party/abseil-cpp/absl/strings/substitute.cc
@@ -36,7 +36,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (i + 1 >= format.size()) {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid absl::Substitute() format string: \"%s\".",
+ "Invalid absl::Substitute() format std::string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -46,8 +46,8 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
#ifndef NDEBUG
ABSL_RAW_LOG(
FATAL,
- "Invalid absl::Substitute() format string: asked for \"$"
- "%d\", but only %d args were given. Full format string was: "
+ "Invalid absl::Substitute() format std::string: asked for \"$"
+ "%d\", but only %d args were given. Full format std::string was: "
"\"%s\".",
index, static_cast<int>(num_args), absl::CEscape(format).c_str());
#endif
@@ -61,7 +61,7 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
} else {
#ifndef NDEBUG
ABSL_RAW_LOG(FATAL,
- "Invalid absl::Substitute() format string: \"%s\".",
+ "Invalid absl::Substitute() format std::string: \"%s\".",
absl::CEscape(format).c_str());
#endif
return;
@@ -73,10 +73,9 @@ void SubstituteAndAppendArray(std::string* output, absl::string_view format,
if (size == 0) return;
- // Build the string.
+ // Build the std::string.
size_t original_size = output->size();
- strings_internal::STLStringResizeUninitializedAmortized(output,
- original_size + size);
+ strings_internal::STLStringResizeUninitialized(output, original_size + size);
char* target = &(*output)[original_size];
for (size_t i = 0; i < format.size(); i++) {
if (format[i] == '$') {
diff --git a/third_party/abseil-cpp/absl/strings/substitute.h b/third_party/abseil-cpp/absl/strings/substitute.h
index 151c56f543..4d0984d3d1 100644
--- a/third_party/abseil-cpp/absl/strings/substitute.h
+++ b/third_party/abseil-cpp/absl/strings/substitute.h
@@ -50,7 +50,7 @@
//
// Supported types:
// * absl::string_view, std::string, const char* (null is equivalent to "")
-// * int32_t, int64_t, uint32_t, uint64_t
+// * int32_t, int64_t, uint32_t, uint64
// * float, double
// * bool (Printed as "true" or "false")
// * pointer types other than char* (Printed as "0x<lower case hex string>",
@@ -99,7 +99,7 @@ namespace substitute_internal {
// This class has implicit constructors.
class Arg {
public:
- // Overloads for string-y things
+ // Overloads for std::string-y things
//
// Explicitly overload `const char*` so the compiler doesn't cast to `bool`.
Arg(const char* value) // NOLINT(runtime/explicit)
@@ -120,9 +120,7 @@ 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_) {}
@@ -205,11 +203,10 @@ 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
@@ -361,49 +358,43 @@ inline void SubstituteAndAppend(
// This body of functions catches cases where the number of placeholders
// doesn't match the number of data arguments.
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 string either has a $[0-9] in it or contains "
- "an unescaped $ character (use $$ instead)");
+ 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");
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 string is missing its $0, contains "
- "one of $1-$9, or contains an unescaped $ character (use "
- "$$ instead)");
+ "this format std::string is either missing its $0, or "
+ "contains one of $1-$9");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 3,
- "There were 2 substitution arguments given, but this format string is "
- "missing its $0/$1, contains one of $2-$9, or contains an "
- "unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $2-$9");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0,
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 string is missing its $0/$1/$2, contains one of "
- "$3-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $3-$9");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0,
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 string is missing its $0-$3, contains one of "
- "$4-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $4-$9");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0,
@@ -411,11 +402,10 @@ void SubstituteAndAppend(std::string* output, const char* format,
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 string is missing its $0-$4, contains one of "
- "$5-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $5-$9");
void SubstituteAndAppend(std::string* output, const char* format,
const substitute_internal::Arg& a0,
@@ -424,22 +414,20 @@ void SubstituteAndAppend(std::string* output, const char* format,
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 string is missing its $0-$5, contains one of "
- "$6-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $6-$9");
void SubstituteAndAppend(
std::string* output, 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)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 127,
- "There were 7 substitution arguments given, but "
- "this format string is missing its $0-$6, contains one of "
- "$7-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $7-$9");
void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0,
@@ -447,11 +435,10 @@ void SubstituteAndAppend(
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 string is missing its $0-$7, contains one of "
- "$8-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $8-$9");
void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0,
@@ -462,8 +449,7 @@ void SubstituteAndAppend(
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 511,
"There were 9 substitution arguments given, but "
- "this format string is missing its $0-$8, contains a $9, or "
- "contains an unescaped $ character (use $$ instead)");
+ "this format std::string is either missing its $0-$8, or contains a $9");
void SubstituteAndAppend(
std::string* output, const char* format, const substitute_internal::Arg& a0,
@@ -472,11 +458,9 @@ void SubstituteAndAppend(
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
const substitute_internal::Arg& a9)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 1023,
- "There were 10 substitution arguments given, but this "
- "format string either doesn't contain all of $0 through $9 or "
- "contains an unescaped $ character (use $$ instead)");
+ 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");
#endif // ABSL_BAD_CALL_IF
// Substitute()
@@ -602,53 +586,47 @@ 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 string either has a $[0-9] in it or "
- "contains an unescaped $ character (use $$ instead)");
+ "but this format std::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 string is missing its $0, contains one of $1-$9, "
- "or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $1-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 3,
- "There were 2 substitution arguments given, but "
- "this format string is missing its $0/$1, contains one of "
- "$2-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "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)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 7,
- "There were 3 substitution arguments given, but "
- "this format string is missing its $0/$1/$2, contains one of "
- "$3-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "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)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 15,
- "There were 4 substitution arguments given, but "
- "this format string is missing its $0-$3, contains one of "
- "$4-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "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)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 31,
- "There were 5 substitution arguments given, but "
- "this format string is missing its $0-$4, contains one of "
- "$5-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $5-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1,
@@ -656,11 +634,10 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
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 string is missing its $0-$5, contains one of "
- "$6-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $6-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1,
@@ -669,11 +646,10 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
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 string is missing its $0-$6, contains one of "
- "$7-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $7-$9");
std::string Substitute(const char* format, const substitute_internal::Arg& a0,
const substitute_internal::Arg& a1,
@@ -683,11 +659,10 @@ std::string Substitute(const char* format, const substitute_internal::Arg& a0,
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 string is missing its $0-$7, contains one of "
- "$8-$9, or contains an unescaped $ character (use $$ instead)");
+ 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 "
+ "contains one of $8-$9");
std::string Substitute(
const char* format, const substitute_internal::Arg& a0,
@@ -698,8 +673,7 @@ std::string Substitute(
ABSL_BAD_CALL_IF(
substitute_internal::PlaceholderBitmask(format) != 511,
"There were 9 substitution arguments given, but "
- "this format string is missing its $0-$8, contains a $9, or "
- "contains an unescaped $ character (use $$ instead)");
+ "this format std::string is either missing its $0-$8, or contains a $9");
std::string Substitute(
const char* format, const substitute_internal::Arg& a0,
@@ -708,11 +682,9 @@ std::string Substitute(
const substitute_internal::Arg& a5, const substitute_internal::Arg& a6,
const substitute_internal::Arg& a7, const substitute_internal::Arg& a8,
const substitute_internal::Arg& a9)
- ABSL_BAD_CALL_IF(
- substitute_internal::PlaceholderBitmask(format) != 1023,
- "There were 10 substitution arguments given, but this "
- "format string either doesn't contain all of $0 through $9 or "
- "contains an unescaped $ character (use $$ instead)");
+ 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");
#endif // ABSL_BAD_CALL_IF
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/strings/substitute_test.cc b/third_party/abseil-cpp/absl/strings/substitute_test.cc
index 442c921528..450cd2bcff 100644
--- a/third_party/abseil-cpp/absl/strings/substitute_test.cc
+++ b/third_party/abseil-cpp/absl/strings/substitute_test.cc
@@ -89,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 string.
+ // null char* is "doubly" special. Represented as the empty std::string.
char_p = nullptr;
str = absl::Substitute("$0", char_p);
EXPECT_EQ("", str);
@@ -189,14 +189,14 @@ TEST(SubstituteTest, VectorBoolRef) {
TEST(SubstituteDeathTest, SubstituteDeath) {
EXPECT_DEBUG_DEATH(
static_cast<void>(absl::Substitute(absl::string_view("-$2"), "a", "b")),
- "Invalid absl::Substitute\\(\\) format string: asked for \"\\$2\", "
+ "Invalid absl::Substitute\\(\\) format std::string: asked for \"\\$2\", "
"but only 2 args were given.");
EXPECT_DEBUG_DEATH(
static_cast<void>(absl::Substitute(absl::string_view("-$z-"))),
- "Invalid absl::Substitute\\(\\) format string: \"-\\$z-\"");
+ "Invalid absl::Substitute\\(\\) format std::string: \"-\\$z-\"");
EXPECT_DEBUG_DEATH(
static_cast<void>(absl::Substitute(absl::string_view("-$"))),
- "Invalid absl::Substitute\\(\\) format string: \"-\\$\"");
+ "Invalid absl::Substitute\\(\\) format std::string: \"-\\$\"");
}
#endif // GTEST_HAS_DEATH_TEST
diff --git a/third_party/abseil-cpp/absl/strings/testdata/getline-1.txt b/third_party/abseil-cpp/absl/strings/testdata/getline-1.txt
new file mode 100644
index 0000000000..19b909733a
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/testdata/getline-1.txt
@@ -0,0 +1,3 @@
+alpha
+
+beta gamma
diff --git a/third_party/abseil-cpp/absl/strings/testdata/getline-2.txt b/third_party/abseil-cpp/absl/strings/testdata/getline-2.txt
new file mode 100644
index 0000000000..d6842d8ee3
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/testdata/getline-2.txt
@@ -0,0 +1 @@
+one.two.three
diff --git a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
index d71954735a..3f876b9fdc 100644
--- a/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/synchronization/BUILD.bazel
@@ -14,6 +14,7 @@
# 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",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
# Internal data structure for efficiently detecting mutex dependency cycles
cc_library(
@@ -72,14 +73,15 @@ 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/futex.h",
+ "internal/mutex_nonprod.inc",
"internal/per_thread_sem.h",
"internal/waiter.h",
"mutex.h",
@@ -87,9 +89,7 @@ cc_library(
],
copts = ABSL_DEFAULT_COPTS,
linkopts = select({
- "//absl:msvc_compiler": [],
- "//absl:clang-cl_compiler": [],
- "//absl:wasm": [],
+ "//absl:windows": [],
"//conditions:default": ["-pthread"],
}) + ABSL_DEFAULT_LINKOPTS,
deps = [
@@ -135,21 +135,6 @@ cc_test(
],
)
-cc_binary(
- name = "blocking_counter_benchmark",
- testonly = 1,
- srcs = ["blocking_counter_benchmark.cc"],
- copts = ABSL_TEST_COPTS,
- linkopts = ABSL_DEFAULT_LINKOPTS,
- tags = ["benchmark"],
- visibility = ["//visibility:private"],
- deps = [
- ":synchronization",
- ":thread_pool",
- "@com_github_google_benchmark//:benchmark_main",
- ],
-)
-
cc_test(
name = "graphcycles_test",
size = "medium",
@@ -204,7 +189,6 @@ cc_test(
":synchronization",
":thread_pool",
"//absl/base",
- "//absl/base:config",
"//absl/base:core_headers",
"//absl/base:raw_logging_internal",
"//absl/memory",
@@ -226,7 +210,6 @@ cc_library(
":synchronization",
":thread_pool",
"//absl/base",
- "//absl/base:config",
"@com_github_google_benchmark//:benchmark_main",
],
alwayslink = 1,
@@ -265,7 +248,6 @@ cc_library(
deps = [
":synchronization",
"//absl/base",
- "//absl/base:config",
"//absl/strings",
"//absl/time",
"@com_google_googletest//:gtest",
diff --git a/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt b/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt
index 605efe2d02..dfe5d05df2 100644
--- a/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/synchronization/CMakeLists.txt
@@ -52,7 +52,7 @@ absl_cc_library(
"barrier.h"
"blocking_counter.h"
"internal/create_thread_identity.h"
- "internal/futex.h"
+ "internal/mutex_nonprod.inc"
"internal/per_thread_sem.h"
"internal/waiter.h"
"mutex.h"
@@ -95,7 +95,7 @@ absl_cc_test(
DEPS
absl::synchronization
absl::time
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -108,7 +108,7 @@ absl_cc_test(
DEPS
absl::synchronization
absl::time
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -122,7 +122,7 @@ absl_cc_test(
absl::graphcycles_internal
absl::core_headers
absl::raw_logging_internal
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -149,12 +149,11 @@ absl_cc_test(
absl::synchronization
absl::thread_pool
absl::base
- absl::config
absl::core_headers
absl::memory
absl::raw_logging_internal
absl::time
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -167,7 +166,7 @@ absl_cc_test(
DEPS
absl::synchronization
absl::time
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -180,10 +179,9 @@ absl_cc_library(
DEPS
absl::synchronization
absl::base
- absl::config
absl::strings
absl::time
- GTest::gmock
+ gmock
TESTONLY
)
@@ -199,7 +197,7 @@ absl_cc_test(
absl::synchronization
absl::strings
absl::time
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
diff --git a/third_party/abseil-cpp/absl/synchronization/blocking_counter.cc b/third_party/abseil-cpp/absl/synchronization/blocking_counter.cc
index d2f82da3bb..3cea7aed24 100644
--- a/third_party/abseil-cpp/absl/synchronization/blocking_counter.cc
+++ b/third_party/abseil-cpp/absl/synchronization/blocking_counter.cc
@@ -14,51 +14,41 @@
#include "absl/synchronization/blocking_counter.h"
-#include <atomic>
-
#include "absl/base/internal/raw_logging.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
-namespace {
-
-// Return whether int *arg is true.
-bool IsDone(void *arg) { return *reinterpret_cast<bool *>(arg); }
-
-} // namespace
-
-BlockingCounter::BlockingCounter(int initial_count)
- : count_(initial_count),
- num_waiting_(0),
- done_{initial_count == 0 ? true : false} {
- ABSL_RAW_CHECK(initial_count >= 0, "BlockingCounter initial_count negative");
+// Return whether int *arg is zero.
+static bool IsZero(void *arg) {
+ return 0 == *reinterpret_cast<int *>(arg);
}
bool BlockingCounter::DecrementCount() {
- int count = count_.fetch_sub(1, std::memory_order_acq_rel) - 1;
- ABSL_RAW_CHECK(count >= 0,
- "BlockingCounter::DecrementCount() called too many times");
- if (count == 0) {
- MutexLock l(&lock_);
- done_ = true;
- return true;
+ MutexLock l(&lock_);
+ count_--;
+ if (count_ < 0) {
+ ABSL_RAW_LOG(
+ FATAL,
+ "BlockingCounter::DecrementCount() called too many times. count=%d",
+ count_);
}
- return false;
+ return count_ == 0;
}
void BlockingCounter::Wait() {
MutexLock l(&this->lock_);
+ ABSL_RAW_CHECK(count_ >= 0, "BlockingCounter underflow");
// only one thread may call Wait(). To support more than one thread,
// implement a counter num_to_exit, like in the Barrier class.
ABSL_RAW_CHECK(num_waiting_ == 0, "multiple threads called Wait()");
num_waiting_++;
- this->lock_.Await(Condition(IsDone, &this->done_));
+ this->lock_.Await(Condition(IsZero, &this->count_));
- // At this point, we know that all threads executing DecrementCount
- // will not touch this object again.
+ // At this point, We know that all threads executing DecrementCount have
+ // released the lock, and so will not touch this object again.
// Therefore, the thread calling this method is free to delete the object
// after we return from this method.
}
diff --git a/third_party/abseil-cpp/absl/synchronization/blocking_counter.h b/third_party/abseil-cpp/absl/synchronization/blocking_counter.h
index 1908fdb1d9..1f53f9f240 100644
--- a/third_party/abseil-cpp/absl/synchronization/blocking_counter.h
+++ b/third_party/abseil-cpp/absl/synchronization/blocking_counter.h
@@ -20,8 +20,6 @@
#ifndef ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
#define ABSL_SYNCHRONIZATION_BLOCKING_COUNTER_H_
-#include <atomic>
-
#include "absl/base/thread_annotations.h"
#include "absl/synchronization/mutex.h"
@@ -62,7 +60,8 @@ ABSL_NAMESPACE_BEGIN
//
class BlockingCounter {
public:
- explicit BlockingCounter(int initial_count);
+ explicit BlockingCounter(int initial_count)
+ : count_(initial_count), num_waiting_(0) {}
BlockingCounter(const BlockingCounter&) = delete;
BlockingCounter& operator=(const BlockingCounter&) = delete;
@@ -90,9 +89,8 @@ class BlockingCounter {
private:
Mutex lock_;
- std::atomic<int> count_;
+ int count_ ABSL_GUARDED_BY(lock_);
int num_waiting_ ABSL_GUARDED_BY(lock_);
- bool done_ ABSL_GUARDED_BY(lock_);
};
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/synchronization/blocking_counter_benchmark.cc b/third_party/abseil-cpp/absl/synchronization/blocking_counter_benchmark.cc
deleted file mode 100644
index b504d1a57c..0000000000
--- a/third_party/abseil-cpp/absl/synchronization/blocking_counter_benchmark.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// 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 <limits>
-
-#include "absl/synchronization/blocking_counter.h"
-#include "absl/synchronization/internal/thread_pool.h"
-#include "benchmark/benchmark.h"
-
-namespace {
-
-void BM_BlockingCounter_SingleThread(benchmark::State& state) {
- for (auto _ : state) {
- int iterations = state.range(0);
- absl::BlockingCounter counter{iterations};
- for (int i = 0; i < iterations; ++i) {
- counter.DecrementCount();
- }
- counter.Wait();
- }
-}
-BENCHMARK(BM_BlockingCounter_SingleThread)
- ->ArgName("iterations")
- ->Arg(2)
- ->Arg(4)
- ->Arg(16)
- ->Arg(64)
- ->Arg(256);
-
-void BM_BlockingCounter_DecrementCount(benchmark::State& state) {
- static absl::BlockingCounter* counter =
- new absl::BlockingCounter{std::numeric_limits<int>::max()};
- for (auto _ : state) {
- counter->DecrementCount();
- }
-}
-BENCHMARK(BM_BlockingCounter_DecrementCount)
- ->Threads(2)
- ->Threads(4)
- ->Threads(6)
- ->Threads(8)
- ->Threads(10)
- ->Threads(12)
- ->Threads(16)
- ->Threads(32)
- ->Threads(64)
- ->Threads(128);
-
-void BM_BlockingCounter_Wait(benchmark::State& state) {
- int num_threads = state.range(0);
- absl::synchronization_internal::ThreadPool pool(num_threads);
- for (auto _ : state) {
- absl::BlockingCounter counter{num_threads};
- pool.Schedule([num_threads, &counter, &pool]() {
- for (int i = 0; i < num_threads; ++i) {
- pool.Schedule([&counter]() { counter.DecrementCount(); });
- }
- });
- counter.Wait();
- }
-}
-BENCHMARK(BM_BlockingCounter_Wait)
- ->ArgName("threads")
- ->Arg(2)
- ->Arg(4)
- ->Arg(8)
- ->Arg(16)
- ->Arg(32)
- ->Arg(64)
- ->Arg(128);
-
-} // namespace
diff --git a/third_party/abseil-cpp/absl/synchronization/blocking_counter_test.cc b/third_party/abseil-cpp/absl/synchronization/blocking_counter_test.cc
index 06885f5759..2926224af7 100644
--- a/third_party/abseil-cpp/absl/synchronization/blocking_counter_test.cc
+++ b/third_party/abseil-cpp/absl/synchronization/blocking_counter_test.cc
@@ -63,18 +63,6 @@ TEST(BlockingCounterTest, BasicFunctionality) {
}
}
-TEST(BlockingCounterTest, WaitZeroInitialCount) {
- BlockingCounter counter(0);
- counter.Wait();
-}
-
-#if GTEST_HAS_DEATH_TEST
-TEST(BlockingCounterTest, WaitNegativeInitialCount) {
- EXPECT_DEATH(BlockingCounter counter(-1),
- "BlockingCounter initial_count negative");
-}
-#endif
-
} // namespace
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc b/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
index 53a71b342b..fa0070a9fc 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
+++ b/third_party/abseil-cpp/absl/synchronization/internal/create_thread_identity.cc
@@ -32,9 +32,9 @@ namespace synchronization_internal {
// ThreadIdentity storage is persistent, we maintain a free-list of previously
// released ThreadIdentity objects.
-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;
+static base_internal::SpinLock freelist_lock(
+ base_internal::kLinkerInitialized);
+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.
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/futex.h b/third_party/abseil-cpp/absl/synchronization/internal/futex.h
deleted file mode 100644
index 06fbd6d072..0000000000
--- a/third_party/abseil-cpp/absl/synchronization/internal/futex.h
+++ /dev/null
@@ -1,154 +0,0 @@
-// 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/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc
index 27fec21681..6a2bcdf681 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc
+++ b/third_party/abseil-cpp/absl/synchronization/internal/graphcycles.cc
@@ -37,7 +37,6 @@
#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"
@@ -52,9 +51,9 @@ namespace {
// Avoid LowLevelAlloc's default arena since it calls malloc hooks in
// which people are doing things like acquiring Mutexes.
-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 absl::base_internal::SpinLock arena_mu(
+ absl::base_internal::kLinkerInitialized);
+static base_internal::LowLevelAlloc::Arena* arena;
static void InitArenaIfNecessary() {
arena_mu.Lock();
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h b/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
index bbd4d2d70f..d6ac5db0af 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
+++ b/third_party/abseil-cpp/absl/synchronization/internal/kernel_timeout.h
@@ -26,7 +26,6 @@
#define ABSL_SYNCHRONIZATION_INTERNAL_KERNEL_TIMEOUT_H_
#include <time.h>
-
#include <algorithm>
#include <limits>
@@ -58,10 +57,6 @@ class KernelTimeout {
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.
@@ -87,6 +82,34 @@ 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
@@ -125,30 +148,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc b/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc
new file mode 100644
index 0000000000..4590b98dbb
--- /dev/null
+++ b/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.cc
@@ -0,0 +1,320 @@
+// 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.
+
+// 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 {
+ABSL_NAMESPACE_BEGIN
+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)) {}
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc b/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc
new file mode 100644
index 0000000000..a1502e727d
--- /dev/null
+++ b/third_party/abseil-cpp/absl/synchronization/internal/mutex_nonprod.inc
@@ -0,0 +1,261 @@
+// 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 {
+ABSL_NAMESPACE_BEGIN
+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 the T.
+ alignas(T) unsigned char space_[sizeof(T)];
+};
+
+} // namespace synchronization_internal
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
index a6031787e0..821ca9b4e9 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
+++ b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.cc
@@ -68,12 +68,12 @@ ABSL_NAMESPACE_END
extern "C" {
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
+ABSL_ATTRIBUTE_WEAK void AbslInternalPerThreadSemPost(
absl::base_internal::ThreadIdentity *identity) {
absl::synchronization_internal::Waiter::GetWaiter(identity)->Post();
}
-ABSL_ATTRIBUTE_WEAK bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
+ABSL_ATTRIBUTE_WEAK bool AbslInternalPerThreadSemWait(
absl::synchronization_internal::KernelTimeout t) {
bool timeout = false;
absl::base_internal::ThreadIdentity *identity;
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
index 7beae8ef1d..8ab439153a 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
+++ b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem.h
@@ -78,7 +78,7 @@ class PerThreadSem {
// !t.has_timeout() => Wait(t) will return true.
static inline bool Wait(KernelTimeout t);
- // Permitted callers.
+ // White-listed callers.
friend class PerThreadSemTest;
friend class absl::Mutex;
friend absl::base_internal::ThreadIdentity* CreateThreadIdentity();
@@ -96,20 +96,20 @@ ABSL_NAMESPACE_END
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(
+void AbslInternalPerThreadSemPost(
absl::base_internal::ThreadIdentity* identity);
-bool ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(
+bool AbslInternalPerThreadSemWait(
absl::synchronization_internal::KernelTimeout t);
} // extern "C"
void absl::synchronization_internal::PerThreadSem::Post(
absl::base_internal::ThreadIdentity* identity) {
- ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemPost)(identity);
+ AbslInternalPerThreadSemPost(identity);
}
bool absl::synchronization_internal::PerThreadSem::Wait(
absl::synchronization_internal::KernelTimeout t) {
- return ABSL_INTERNAL_C_SYMBOL(AbslInternalPerThreadSemWait)(t);
+ return AbslInternalPerThreadSemWait(t);
}
#endif // ABSL_SYNCHRONIZATION_INTERNAL_PER_THREAD_SEM_H_
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
index db1184e679..b5a2f6d4b5 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
+++ b/third_party/abseil-cpp/absl/synchronization/internal/per_thread_sem_test.cc
@@ -23,7 +23,6 @@
#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"
@@ -159,7 +158,7 @@ TEST_F(PerThreadSemTest, Timeouts) {
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::Milliseconds(1);
+ const absl::Duration slop = absl::Microseconds(200);
EXPECT_LE(delay - slop, elapsed)
<< "Wait returned " << delay - elapsed
<< " early (with " << slop << " slop), start time was " << start;
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc b/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc
index 28ef311e4a..2949f5a84c 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc
+++ b/third_party/abseil-cpp/absl/synchronization/internal/waiter.cc
@@ -48,7 +48,6 @@
#include "absl/base/optimization.h"
#include "absl/synchronization/internal/kernel_timeout.h"
-
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace synchronization_internal {
@@ -67,6 +66,63 @@ 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;
+ }
+};
+
Waiter::Waiter() {
futex_.store(0, std::memory_order_relaxed);
}
@@ -79,7 +135,6 @@ bool Waiter::Wait(KernelTimeout t) {
// 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);
while (x != 0) {
@@ -91,6 +146,7 @@ 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) {
diff --git a/third_party/abseil-cpp/absl/synchronization/internal/waiter.h b/third_party/abseil-cpp/absl/synchronization/internal/waiter.h
index be3df180d4..a6e6d4c7ee 100644
--- a/third_party/abseil-cpp/absl/synchronization/internal/waiter.h
+++ b/third_party/abseil-cpp/absl/synchronization/internal/waiter.h
@@ -36,7 +36,6 @@
#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>
@@ -49,7 +48,12 @@
#define ABSL_WAITER_MODE ABSL_FORCE_WAITER_MODE
#elif defined(_WIN32) && _WIN32_WINNT >= _WIN32_WINNT_VISTA
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_WIN32
-#elif defined(ABSL_INTERNAL_HAVE_FUTEX)
+#elif defined(__BIONIC__)
+// Bionic supports all the futex operations we need even when some of the futex
+// definitions are missing.
+#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
+#elif defined(__linux__) && defined(FUTEX_CLOCK_REALTIME)
+// FUTEX_CLOCK_REALTIME requires Linux >= 2.6.28.
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_FUTEX
#elif defined(ABSL_HAVE_SEMAPHORE_H)
#define ABSL_WAITER_MODE ABSL_WAITER_MODE_SEM
@@ -96,8 +100,8 @@ class Waiter {
}
// How many periods to remain idle before releasing resources
-#ifndef ABSL_HAVE_THREAD_SANITIZER
- static constexpr int kIdlePeriods = 60;
+#ifndef THREAD_SANITIZER
+ static const 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
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.cc b/third_party/abseil-cpp/absl/synchronization/mutex.cc
index 76ad41fe16..e0879b059a 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.cc
@@ -39,7 +39,6 @@
#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"
@@ -50,7 +49,6 @@
#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"
@@ -60,7 +58,6 @@
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;
@@ -70,9 +67,7 @@ using absl::synchronization_internal::KernelTimeout;
using absl::synchronization_internal::PerThreadSem;
extern "C" {
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)() {
- std::this_thread::yield();
-}
+ABSL_ATTRIBUTE_WEAK void AbslInternalMutexYield() { std::this_thread::yield(); }
} // extern "C"
namespace absl {
@@ -80,7 +75,7 @@ ABSL_NAMESPACE_BEGIN
namespace {
-#if defined(ABSL_HAVE_THREAD_SANITIZER)
+#if defined(THREAD_SANITIZER)
constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kIgnore;
#else
constexpr OnDeadlockCycle kDeadlockDetectionDefault = OnDeadlockCycle::kAbort;
@@ -90,9 +85,31 @@ 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_INTERNAL_ATOMIC_HOOK_ATTRIBUTES
-absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
- submit_profile_data;
+ absl::base_internal::AtomicHook<void (*)(int64_t wait_cycles)>
+ submit_profile_data;
ABSL_INTERNAL_ATOMIC_HOOK_ATTRIBUTES absl::base_internal::AtomicHook<void (*)(
const char *msg, const void *obj, int64_t wait_cycles)>
mutex_tracer;
@@ -126,64 +143,33 @@ void RegisterSymbolizer(bool (*fn)(const void *pc, char *out, int out_size)) {
symbolizer.Store(fn);
}
+// spinlock delay on iteration c. Returns new c.
namespace {
-// 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] = {};
+ enum DelayMode { AGGRESSIVE, GENTLE };
};
-
-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];
+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;
if (c < limit) {
- // Spin.
- c++;
+ c++; // spin
} else {
- SchedulingGuard::ScopedEnable enable_rescheduling;
ABSL_TSAN_MUTEX_PRE_DIVERT(nullptr, 0);
- if (c == limit) {
- // Yield once.
- ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
+ if (c == limit) { // yield once
+ AbslInternalMutexYield();
c++;
- } else {
- // Then wait.
+ } else { // then wait
absl::SleepFor(absl::Microseconds(10));
c = 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
@@ -221,12 +207,12 @@ static void AtomicClearBits(std::atomic<intptr_t>* pv, intptr_t bits,
//------------------------------------------------------------------
// Data for doing deadlock detection.
-ABSL_CONST_INIT static absl::base_internal::SpinLock deadlock_graph_mu(
- absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+static absl::base_internal::SpinLock deadlock_graph_mu(
+ absl::base_internal::kLinkerInitialized);
-// 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);
+// graph used to detect deadlocks.
+static GraphCycles *deadlock_graph ABSL_GUARDED_BY(deadlock_graph_mu)
+ ABSL_PT_GUARDED_BY(deadlock_graph_mu);
//------------------------------------------------------------------
// An event mechanism for debugging mutex use.
@@ -287,12 +273,13 @@ static const struct {
{0, "SignalAll on "},
};
-ABSL_CONST_INIT static absl::base_internal::SpinLock synch_event_mu(
- absl::kConstInit, base_internal::SCHEDULE_KERNEL_ONLY);
+static absl::base_internal::SpinLock synch_event_mu(
+ absl::base_internal::kLinkerInitialized);
+// protects synch_event
// Hash table size; should be prime > 2.
// Can't be too small, as it's used for deadlock detection information.
-static constexpr uint32_t kNSynchEvent = 1031;
+static const uint32_t kNSynchEvent = 1031;
static struct SynchEvent { // this is a trivial hash table for the events
// struct is freed when refcount reaches 0
@@ -312,7 +299,7 @@ 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---NUL-terminated string
+ char name[1]; // actually longer---NUL-terminated std::string
} * synch_event[kNSynchEvent] ABSL_GUARDED_BY(synch_event_mu);
// Ensure that the object at "addr" has a SynchEvent struct associated with it,
@@ -503,7 +490,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 {
@@ -559,7 +546,7 @@ static SynchLocksHeld *Synch_GetAllLocks() {
}
// Post on "w"'s associated PerThreadSem.
-void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
+inline void Mutex::IncrementSynchSem(Mutex *mu, PerThreadSynch *w) {
if (mu) {
ABSL_TSAN_MUTEX_PRE_DIVERT(mu, 0);
}
@@ -717,7 +704,7 @@ static constexpr bool kDebugMode = false;
static constexpr bool kDebugMode = true;
#endif
-#ifdef ABSL_INTERNAL_HAVE_TSAN_INTERFACE
+#ifdef THREAD_SANITIZER
static unsigned TsanFlags(Mutex::MuHow how) {
return how == kShared ? __tsan_mutex_read_lock : 0;
}
@@ -763,13 +750,11 @@ void SetMutexDeadlockDetectionMode(OnDeadlockCycle mode) {
synch_deadlock_detection.store(mode, std::memory_order_release);
}
-// 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 &&
+// 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 &&
Condition::GuaranteedEqual(x->waitp->cond, y->waitp->cond);
}
@@ -788,19 +773,18 @@ 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, priority
-// and lock type (MuEquivalentWaiter() is true for all pairs in [x,
-// x->skip]).
+// 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]).
// In addition, if x->skip is valid, (x->may_skip || x->skip == null)
//
-// By the spec of MuEquivalentWaiter(), it is not necessary when removing the
+// By the spec of MuSameCondition(), 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 && MuEquivalentWaiter(x, x->next)) { x->skip = x->next; }
+// if (x->may_skip && MuSameCondition(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; }
@@ -934,17 +918,24 @@ static PerThreadSynch *Enqueue(PerThreadSynch *head,
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 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.
+ // 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.
PerThreadSynch *advance_to = head; // next value of enqueue_after
+ PerThreadSynch *cur; // successor of enqueue_after
do {
enqueue_after = advance_to;
- // (side-effect: optimizes skip chain)
- advance_to = Skip(enqueue_after->next);
+ 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
+ }
} while (s->priority <= advance_to->priority);
// termination guaranteed because s->priority > head->priority
// and head is the end of a skip chain
@@ -963,21 +954,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 MuEquivalentWaiter(s, cur).
+ // the last is used only if MuSameCondition(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 ||
- MuEquivalentWaiter(enqueue_after, s),
- "Mutex Enqueue failure");
+ ABSL_RAW_CHECK(
+ enqueue_after->skip == nullptr || MuSameCondition(enqueue_after, s),
+ "Mutex Enqueue failure");
if (enqueue_after != head && enqueue_after->may_skip &&
- MuEquivalentWaiter(enqueue_after, enqueue_after->next)) {
+ MuSameCondition(enqueue_after, enqueue_after->next)) {
// enqueue_after can skip to its new successor, s
enqueue_after->skip = enqueue_after->next;
}
- if (MuEquivalentWaiter(s, s->next)) { // s->may_skip is known to be true
+ if (MuSameCondition(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
@@ -987,7 +978,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 && MuEquivalentWaiter(head, s)) {
+ if (head->may_skip && MuSameCondition(head, s)) {
// head now has successor; may skip
head->skip = s;
}
@@ -1007,7 +998,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 && MuEquivalentWaiter(pw, pw->next)) {
+ } else if (pw != head && MuSameCondition(pw, pw->next)) {
// pw can skip to its new successor
if (pw->next->skip !=
nullptr) { // either skip to its successors skip target
@@ -1064,7 +1055,6 @@ 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 &&
@@ -1077,13 +1067,11 @@ void Mutex::TryRemove(PerThreadSynch *s) {
PerThreadSynch *w;
if ((w = pw->next) != s) { // search for thread,
do { // processing at least one element
- // If the current element isn't equivalent to the waiter to be
- // removed, we can skip the entire chain.
- if (!MuEquivalentWaiter(s, w)) {
+ if (!MuSameCondition(s, w)) { // seeking different condition
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 they are in a different equivalence class.
+ // because their condition differs from s
} else { // seeking same condition
FixSkip(w, s); // fix up any skip pointer from w to s
pw = w;
@@ -1131,7 +1119,7 @@ ABSL_XRAY_LOG_ARGS(1) void Mutex::Block(PerThreadSynch *s) {
this->TryRemove(s);
int c = 0;
while (s->next != nullptr) {
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE);
this->TryRemove(s);
}
if (kDebugMode) {
@@ -1374,9 +1362,7 @@ static GraphId DeadlockCheck(Mutex *mu) {
len += static_cast<int>(strlen(&b->buf[len]));
}
}
- ABSL_RAW_LOG(ERROR,
- "Acquiring absl::Mutex %p while holding %s; a cycle in the "
- "historical lock ordering graph has been observed",
+ ABSL_RAW_LOG(ERROR, "Acquiring %p Mutexes held: %s",
static_cast<void *>(mu), b->buf);
ABSL_RAW_LOG(ERROR, "Cycle: ");
int path_len = deadlock_graph->FindPath(
@@ -1452,19 +1438,21 @@ 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 = GetMutexGlobals().spinloop_iterations;
+ int c = mutex_globals.spinloop_iterations;
+ int result = -1; // result of operation: 0=false, 1=true, -1=unknown
+
do { // do/while somewhat faster on AMD
intptr_t v = mu->load(std::memory_order_relaxed);
- if ((v & (kMuReader|kMuEvent)) != 0) {
- return false; // a reader or tracing -> give up
+ if ((v & (kMuReader|kMuEvent)) != 0) { // a reader or tracing -> give up
+ result = 0;
} 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)) {
- return true;
+ result = 1;
}
- } while (--c > 0);
- return false;
+ } while (result == -1 && --c > 0);
+ return result == 1;
}
ABSL_XRAY_LOG_ARGS(1) void Mutex::Lock() {
@@ -1763,8 +1751,7 @@ static const intptr_t ignore_waiting_writers[] = {
};
// Internal version of LockWhen(). See LockSlowWithDeadline()
-ABSL_ATTRIBUTE_NOINLINE void Mutex::LockSlow(MuHow how, const Condition *cond,
- int flags) {
+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");
@@ -1779,7 +1766,7 @@ static inline bool EvalConditionAnnotated(const Condition *cond, Mutex *mu,
// 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
+#ifdef THREAD_SANITIZER
const int flags = read_lock ? __tsan_mutex_read_lock : 0;
const int tryflags = flags | (trylock ? __tsan_mutex_try_lock : 0);
#endif
@@ -1829,9 +1816,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);
- ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
+ ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN();
bool res = cond->Eval();
- ABSL_ANNOTATE_IGNORE_READS_AND_WRITES_END();
+ 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;
@@ -1912,7 +1899,6 @@ 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) {
@@ -2014,8 +2000,7 @@ 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");
- // delay, then try again
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE); // delay, then try again
}
ABSL_RAW_CHECK(
waitp->thread->waitp == nullptr || waitp->thread->suppress_fatal_errors,
@@ -2032,8 +2017,7 @@ 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.
-ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
- SchedulingGuard::ScopedDisable disable_rescheduling;
+void Mutex::UnlockSlow(SynchWaitParams *waitp) {
intptr_t v = mu_.load(std::memory_order_relaxed);
this->AssertReaderHeld();
CheckForMutexCorruption(v, "Unlock");
@@ -2150,7 +2134,7 @@ ABSL_ATTRIBUTE_NOINLINE 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 && MuEquivalentWaiter(old_h, old_h->next)) {
+ if (h != old_h && MuSameCondition(old_h, old_h->next)) {
old_h->skip = old_h->next; // old_h not head & can skip to successor
}
}
@@ -2310,8 +2294,7 @@ ABSL_ATTRIBUTE_NOINLINE void Mutex::UnlockSlow(SynchWaitParams *waitp) {
mu_.store(nv, std::memory_order_release);
break; // out of for(;;)-loop
}
- // aggressive here; no one can proceed till we do
- c = synchronization_internal::MutexDelay(c, AGGRESSIVE);
+ c = Delay(c, AGGRESSIVE); // aggressive here; no one can proceed till we do
} // end of for(;;)-loop
if (wake_list != kPerThreadSynchNull) {
@@ -2323,8 +2306,7 @@ ABSL_ATTRIBUTE_NOINLINE 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);
@@ -2351,7 +2333,6 @@ 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");
@@ -2401,7 +2382,7 @@ void Mutex::Fer(PerThreadSynch *w) {
return;
}
}
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE);
}
}
@@ -2450,7 +2431,6 @@ 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);;
@@ -2479,8 +2459,7 @@ void CondVar::Remove(PerThreadSynch *s) {
std::memory_order_release);
return;
} else {
- // try again after a delay
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE); // try again after a delay
}
}
}
@@ -2513,7 +2492,7 @@ static void CondVarEnqueue(SynchWaitParams *waitp) {
!cv_word->compare_exchange_weak(v, v | kCvSpin,
std::memory_order_acquire,
std::memory_order_relaxed)) {
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE);
v = cv_word->load(std::memory_order_relaxed);
}
ABSL_RAW_CHECK(waitp->thread->waitp == nullptr, "waiting when shouldn't be");
@@ -2612,7 +2591,6 @@ void CondVar::Wakeup(PerThreadSynch *w) {
}
void CondVar::Signal() {
- SchedulingGuard::ScopedDisable disable_rescheduling;
ABSL_TSAN_MUTEX_PRE_SIGNAL(nullptr, 0);
intptr_t v;
int c = 0;
@@ -2645,7 +2623,7 @@ void CondVar::Signal() {
ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
return;
} else {
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE);
}
}
ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
@@ -2682,8 +2660,7 @@ void CondVar::SignalAll () {
ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
return;
} else {
- // try again after a delay
- c = synchronization_internal::MutexDelay(c, GENTLE);
+ c = Delay(c, GENTLE); // try again after a delay
}
}
ABSL_TSAN_MUTEX_POST_SIGNAL(nullptr, 0);
@@ -2696,7 +2673,7 @@ void ReleasableMutexLock::Release() {
this->mu_ = nullptr;
}
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef THREAD_SANITIZER
extern "C" void __tsan_read1(void *addr);
#else
#define __tsan_read1(addr) // do nothing if TSan not enabled
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.h b/third_party/abseil-cpp/absl/synchronization/mutex.h
index 38338f24df..8c70c4ce61 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex.h
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.h
@@ -31,23 +31,22 @@
//
// 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
-// - Effectively an alias for `MutexLock` above, designed for use in
-// distinguishing reader and writer locks within code.
+// - 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`.
//
@@ -73,6 +72,15 @@
#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
@@ -147,7 +155,7 @@ class ABSL_LOCKABLE Mutex {
//
// Example usage:
// namespace foo {
- // ABSL_CONST_INIT absl::Mutex mu(absl::kConstInit);
+ // ABSL_CONST_INIT Mutex mu(absl::kConstInit);
// }
explicit constexpr Mutex(absl::ConstInitType);
@@ -162,7 +170,7 @@ class ABSL_LOCKABLE Mutex {
// Mutex::Unlock()
//
// Releases this `Mutex` and returns it from the exclusive/write state to the
- // free state. Calling thread must hold the `Mutex` exclusively.
+ // free state. Caller must hold the `Mutex` exclusively.
void Unlock() ABSL_UNLOCK_FUNCTION();
// Mutex::TryLock()
@@ -323,16 +331,17 @@ class ABSL_LOCKABLE Mutex {
// Mutex::AwaitWithTimeout()
// Mutex::AwaitWithDeadline()
//
- // Unlocks this `Mutex` and blocks until simultaneously:
+ // 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:
// - 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.
//
@@ -453,13 +462,24 @@ class ABSL_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 void IncrementSynchSem(Mutex *mu, base_internal::PerThreadSynch *w);
- static bool DecrementSynchSem(Mutex *mu, base_internal::PerThreadSynch *w,
- synchronization_internal::KernelTimeout t);
+ static inline void IncrementSynchSem(Mutex *mu,
+ base_internal::PerThreadSynch *w);
+ static inline bool DecrementSynchSem(
+ Mutex *mu, base_internal::PerThreadSynch *w,
+ synchronization_internal::KernelTimeout t);
// slow path acquire
void LockSlowLoop(SynchWaitParams *waitp, int flags);
@@ -485,6 +505,7 @@ class ABSL_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)
@@ -505,36 +526,22 @@ class ABSL_LOCKABLE Mutex {
// Example:
//
// Class Foo {
-// public:
+//
// Foo::Bar* Baz() {
-// MutexLock lock(&mu_);
+// MutexLock l(&lock_);
// ...
// return bar;
// }
//
// private:
-// Mutex mu_;
+// Mutex lock_;
// };
class ABSL_SCOPED_LOCKABLE MutexLock {
public:
- // 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;
@@ -556,12 +563,6 @@ class ABSL_SCOPED_LOCKABLE ReaderMutexLock {
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;
@@ -584,12 +585,6 @@ class ABSL_SCOPED_LOCKABLE WriterMutexLock {
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;
@@ -628,26 +623,16 @@ class ABSL_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 to a
-// suitable `Mutex' member function, such as `Mutex::Await()`, or to the
-// constructor of one of the scope guard classes.
+// Note: to use a `Condition`, you need only construct it and pass it within the
+// appropriate `Mutex' member function, such as `Mutex::Await()`.
//
-// Example using LockWhen/Unlock:
+// Example:
//
// // assume count_ is not internal reference count
// int count_ ABSL_GUARDED_BY(mu_);
-// Condition count_is_zero(+[](int *count) { return *count == 0; }, &count_);
-//
-// mu_.LockWhen(count_is_zero);
-// // ...
-// mu_.Unlock();
//
-// Example using a scope guard:
-//
-// {
-// MutexLock lock(&mu_, count_is_zero);
-// // ...
-// }
+// mu_.LockWhen(Condition(+[](int* count) { return *count == 0; },
+// &count_));
//
// When multiple threads are waiting on exactly the same condition, make sure
// that they are constructed with the same parameters (same pointer to function
@@ -701,11 +686,6 @@ 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
@@ -778,9 +758,9 @@ class Condition {
//
// Usage to wake T is:
// mu.Lock();
-// // process data, possibly establishing C
-// if (C) { cv->Signal(); }
-// mu.Unlock();
+// // process data, possibly establishing C
+// if (C) { cv->Signal(); }
+// mu.Unlock();
//
// If C may be useful to more than one waiter, use `SignalAll()` instead of
// `Signal()`.
@@ -790,8 +770,6 @@ class Condition {
//
class CondVar {
public:
- // A `CondVar` allocated on the heap or on the stack can use the this
- // constructor.
CondVar();
~CondVar();
@@ -854,10 +832,17 @@ 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;
};
@@ -879,15 +864,6 @@ class ABSL_SCOPED_LOCKABLE MutexLockMaybe {
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(); }
}
@@ -910,13 +886,6 @@ class ABSL_SCOPED_LOCKABLE ReleasableMutexLock {
: mu_(mu) {
this->mu_->Lock();
}
-
- 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(); }
}
@@ -931,6 +900,10 @@ class ABSL_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);
}
@@ -938,6 +911,7 @@ inline Mutex::Mutex() : mu_(0) {
inline constexpr Mutex::Mutex(absl::ConstInitType) : mu_(0) {}
inline CondVar::CondVar() : cv_(0) {}
+#endif
// static
template <typename T>
@@ -1005,7 +979,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.
@@ -1076,7 +1050,7 @@ ABSL_NAMESPACE_END
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalMutexYield)();
+void AbslInternalMutexYield();
} // extern "C"
#endif // ABSL_SYNCHRONIZATION_MUTEX_H_
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc
index b5d2fbc454..ab1880012a 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex_benchmark.cc
@@ -16,7 +16,6 @@
#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"
@@ -61,124 +60,8 @@ 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;
@@ -196,56 +79,86 @@ void BM_Contended(benchmark::State& state) {
// To achieve this amount of local work is multiplied by number of threads
// to keep ratio between local work and critical section approximately
// equal regardless of number of threads.
- DelayNs(100 * state.threads(), &local);
+ DelayNs(100 * state.threads, &local);
RaiiLocker<MutexType> locker(&shared->mu);
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)
- ->Apply([](benchmark::internal::Benchmark* bm) {
- SetupBenchmarkArgs(bm, /*do_test_priorities=*/true);
- });
+ ->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);
BENCHMARK_TEMPLATE(BM_Contended, absl::base_internal::SpinLock)
- ->Apply([](benchmark::internal::Benchmark* bm) {
- SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);
- });
+ ->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);
BENCHMARK_TEMPLATE(BM_Contended, std::mutex)
- ->Apply([](benchmark::internal::Benchmark* bm) {
- SetupBenchmarkArgs(bm, /*do_test_priorities=*/false);
- });
+ ->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);
// Measure the overhead of conditions on mutex release (when they must be
// evaluated). Mutex has (some) support for equivalence classes allowing
@@ -300,7 +213,7 @@ void BM_ConditionWaiters(benchmark::State& state) {
}
// Some configurations have higher thread limits than others.
-#if defined(__linux__) && !defined(ABSL_HAVE_THREAD_SANITIZER)
+#if defined(__linux__) && !defined(THREAD_SANITIZER)
constexpr int kMaxConditionWaiters = 8192;
#else
constexpr int kMaxConditionWaiters = 1024;
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
index 4f40317684..afb363af61 100644
--- a/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
+++ b/third_party/abseil-cpp/absl/synchronization/mutex_test.cc
@@ -26,12 +26,10 @@
#include <random>
#include <string>
#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/raw_logging.h"
#include "absl/base/internal/sysinfo.h"
#include "absl/memory/memory.h"
@@ -708,40 +706,6 @@ 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.
@@ -851,9 +815,9 @@ TEST(Mutex, MutexReaderDecrementBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
// Test that we correctly handle the situation when a lock is
// held and then destroyed (w/o unlocking).
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef THREAD_SANITIZER
// TSAN reports errors when locked Mutexes are destroyed.
-TEST(Mutex, DISABLED_LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DISABLED_LockedMutexDestructionBug) NO_THREAD_SAFETY_ANALYSIS {
#else
TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
#endif
@@ -871,6 +835,33 @@ TEST(Mutex, LockedMutexDestructionBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
}
}
+// --------------------------------------------------------
+// Test for bug with pattern of readers using a condvar. The bug was that if a
+// reader went to sleep on a condition variable while one or more other readers
+// held the lock, but there were no waiters, the reader count (held in the
+// mutex word) would be lost. (This is because Enqueue() had at one time
+// always placed the thread on the Mutex queue. Later (CL 4075610), to
+// tolerate re-entry into Mutex from a Condition predicate, Enqueue() was
+// changed so that it could also place a thread on a condition-variable. This
+// introduced the case where Enqueue() returned with an empty queue, and this
+// case was handled incorrectly in one place.)
+
+static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
+ int *running) {
+ std::random_device dev;
+ std::mt19937 gen(dev());
+ std::uniform_int_distribution<int> random_millis(0, 15);
+ mu->ReaderLock();
+ while (*running == 3) {
+ absl::SleepFor(absl::Milliseconds(random_millis(gen)));
+ cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));
+ }
+ mu->ReaderUnlock();
+ mu->Lock();
+ (*running)--;
+ mu->Unlock();
+}
+
struct True {
template <class... Args>
bool operator()(Args...) const {
@@ -919,33 +910,6 @@ TEST(Mutex, FunctorCondition) {
}
}
-// --------------------------------------------------------
-// Test for bug with pattern of readers using a condvar. The bug was that if a
-// reader went to sleep on a condition variable while one or more other readers
-// held the lock, but there were no waiters, the reader count (held in the
-// mutex word) would be lost. (This is because Enqueue() had at one time
-// always placed the thread on the Mutex queue. Later (CL 4075610), to
-// tolerate re-entry into Mutex from a Condition predicate, Enqueue() was
-// changed so that it could also place a thread on a condition-variable. This
-// introduced the case where Enqueue() returned with an empty queue, and this
-// case was handled incorrectly in one place.)
-
-static void ReaderForReaderOnCondVar(absl::Mutex *mu, absl::CondVar *cv,
- int *running) {
- std::random_device dev;
- std::mt19937 gen(dev());
- std::uniform_int_distribution<int> random_millis(0, 15);
- mu->ReaderLock();
- while (*running == 3) {
- absl::SleepFor(absl::Milliseconds(random_millis(gen)));
- cv->WaitWithTimeout(mu, absl::Milliseconds(random_millis(gen)));
- }
- mu->ReaderUnlock();
- mu->Lock();
- (*running)--;
- mu->Unlock();
-}
-
static bool IntIsZero(int *x) { return *x == 0; }
// Test for reader waiting condition variable when there are other readers
@@ -1037,6 +1001,9 @@ 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);
@@ -1100,7 +1067,7 @@ class ScopedDisableBazelTestWarnings {
const char ScopedDisableBazelTestWarnings::kVarName[] =
"TEST_WARNINGS_OUTPUT_FILE";
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef THREAD_SANITIZER
// This test intentionally creates deadlocks to test the deadlock detector.
TEST(Mutex, DISABLED_DeadlockDetectorBazelWarning) {
#else
@@ -1134,7 +1101,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, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DeadlockDetectorStessTest) 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.
@@ -1152,9 +1119,9 @@ TEST(Mutex, DeadlockDetectorStressTest) ABSL_NO_THREAD_SAFETY_ANALYSIS {
}
}
-#ifdef ABSL_HAVE_THREAD_SANITIZER
+#ifdef THREAD_SANITIZER
// TSAN reports errors when locked Mutexes are destroyed.
-TEST(Mutex, DISABLED_DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
+TEST(Mutex, DISABLED_DeadlockIdBug) NO_THREAD_SAFETY_ANALYSIS {
#else
TEST(Mutex, DeadlockIdBug) ABSL_NO_THREAD_SAFETY_ANALYSIS {
#endif
@@ -1190,6 +1157,7 @@ TEST(Mutex, DeadlockIdBug) ABSL_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
diff --git a/third_party/abseil-cpp/absl/time/BUILD.bazel b/third_party/abseil-cpp/absl/time/BUILD.bazel
index e8c49660b2..9ab2adb886 100644
--- a/third_party/abseil-cpp/absl/time/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/time/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "time",
@@ -69,7 +70,6 @@ cc_library(
],
deps = [
":time",
- "//absl/base:config",
"//absl/base:raw_logging_internal",
"//absl/time/internal/cctz:time_zone",
"@com_google_googletest//:gtest",
@@ -118,7 +118,6 @@ cc_test(
":time",
"//absl/base",
"//absl/base:core_headers",
- "//absl/flags:flag",
"//absl/hash",
"@com_github_google_benchmark//:benchmark_main",
],
diff --git a/third_party/abseil-cpp/absl/time/CMakeLists.txt b/third_party/abseil-cpp/absl/time/CMakeLists.txt
index f6ff8bd127..853563e875 100644
--- a/third_party/abseil-cpp/absl/time/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/time/CMakeLists.txt
@@ -99,10 +99,9 @@ absl_cc_library(
${ABSL_DEFAULT_COPTS}
DEPS
absl::time
- absl::config
absl::raw_logging_internal
absl::time_zone
- GTest::gmock
+ gmock
TESTONLY
)
@@ -124,5 +123,5 @@ absl_cc_test(
absl::config
absl::core_headers
absl::time_zone
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/time/civil_time.cc b/third_party/abseil-cpp/absl/time/civil_time.cc
index 6a231edb2d..ada82cbc8d 100644
--- a/third_party/abseil-cpp/absl/time/civil_time.cc
+++ b/third_party/abseil-cpp/absl/time/civil_time.cc
@@ -38,14 +38,16 @@ 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();
- return StrCat(cs.year(), FormatTime(fmt, FromCivil(ncs, utc), utc));
+ // TODO(absl-team): Avoid conversion of fmt std::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.
+ // normalized std::string.
const std::string ss = std::string(s); // TODO(absl-team): Avoid conversion.
const char* const np = ss.c_str();
char* endp;
@@ -80,7 +82,7 @@ bool ParseAs(string_view s, CivilT2* c) {
template <typename CivilT>
bool ParseLenient(string_view s, CivilT* c) {
- // A fastpath for when the given string data parses exactly into the given
+ // A fastpath for when the given std::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
@@ -96,26 +98,26 @@ bool ParseLenient(string_view s, CivilT* c) {
} // namespace
std::string FormatCivilTime(CivilSecond c) {
- return FormatYearAnd("-%m-%d%ET%H:%M:%S", c);
+ return FormatYearAnd("-%m-%dT%H:%M:%S", c);
}
std::string FormatCivilTime(CivilMinute c) {
- return FormatYearAnd("-%m-%d%ET%H:%M", c);
+ return FormatYearAnd("-%m-%dT%H:%M", c);
}
std::string FormatCivilTime(CivilHour c) {
- return FormatYearAnd("-%m-%d%ET%H", c);
+ return FormatYearAnd("-%m-%dT%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);
+ return ParseYearAnd("-%m-%dT%H:%M:%S", s, c);
}
bool ParseCivilTime(string_view s, CivilMinute* c) {
- return ParseYearAnd("-%m-%d%ET%H:%M", s, c);
+ return ParseYearAnd("-%m-%dT%H:%M", s, c);
}
bool ParseCivilTime(string_view s, CivilHour* c) {
- return ParseYearAnd("-%m-%d%ET%H", s, c);
+ return ParseYearAnd("-%m-%dT%H", s, c);
}
bool ParseCivilTime(string_view s, CivilDay* c) {
return ParseYearAnd("-%m-%d", s, c);
diff --git a/third_party/abseil-cpp/absl/time/clock.cc b/third_party/abseil-cpp/absl/time/clock.cc
index 7b204c4ee0..3b895c38e9 100644
--- a/third_party/abseil-cpp/absl/time/clock.cc
+++ b/third_party/abseil-cpp/absl/time/clock.cc
@@ -15,7 +15,6 @@
#include "absl/time/clock.h"
#include "absl/base/attributes.h"
-#include "absl/base/optimization.h"
#ifdef _WIN32
#include <windows.h>
@@ -75,7 +74,9 @@ ABSL_NAMESPACE_END
#if !ABSL_USE_CYCLECLOCK_FOR_GET_CURRENT_TIME_NANOS
namespace absl {
ABSL_NAMESPACE_BEGIN
-int64_t GetCurrentTimeNanos() { return GET_CURRENT_TIME_NANOS_FROM_SYSTEM(); }
+int64_t GetCurrentTimeNanos() {
+ return GET_CURRENT_TIME_NANOS_FROM_SYSTEM();
+}
ABSL_NAMESPACE_END
} // namespace absl
#else // Use the cyclecounter-based implementation below.
@@ -86,6 +87,13 @@ ABSL_NAMESPACE_END
::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 {
@@ -99,6 +107,72 @@ 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
@@ -150,110 +224,32 @@ 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{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
+ 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
// 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{0};
+ std::atomic<uint64_t> min_cycles_per_sample;
};
// Same again, but with non-atomic types
struct TimeSample {
- 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
+ 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
};
-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 struct TimeSampleAtomic last_sample; // the last sample; under seq
static int64_t GetCurrentTimeNanosSlowPath() ABSL_ATTRIBUTE_COLD;
@@ -321,15 +317,14 @@ 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 = time_state.seq.load(std::memory_order_acquire);
+ seq_read0 = seq.load(std::memory_order_acquire);
- 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);
+ base_ns = last_sample.base_ns.load(std::memory_order_relaxed);
+ base_cycles = last_sample.base_cycles.load(std::memory_order_relaxed);
nsscaled_per_cycle =
- 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);
+ 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);
// 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
@@ -340,7 +335,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 = time_state.seq.load(std::memory_order_relaxed);
+ seq_read1 = 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
@@ -353,9 +348,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;
+ uint64_t delta_cycles = now_cycles - base_cycles;
if (seq_read0 == seq_read1 && (seq_read0 & 1) == 0 &&
- (delta_cycles = now_cycles - base_cycles) < min_cycles_per_sample) {
+ delta_cycles < min_cycles_per_sample) {
return base_ns + ((delta_cycles * nsscaled_per_cycle) >> kScale);
}
return GetCurrentTimeNanosSlowPath();
@@ -395,25 +390,24 @@ static uint64_t UpdateLastSample(
// TODO(absl-team): Remove this attribute when our compiler is smart enough
// to do the right thing.
ABSL_ATTRIBUTE_NOINLINE
-static int64_t GetCurrentTimeNanosSlowPath()
- ABSL_LOCKS_EXCLUDED(time_state.lock) {
+static int64_t GetCurrentTimeNanosSlowPath() ABSL_LOCKS_EXCLUDED(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.
- time_state.lock.Lock();
+ 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(time_state.last_now_cycles, &now_cycles);
- time_state.last_now_cycles = now_cycles;
+ uint64_t now_ns = GetCurrentTimeNanosFromKernel(last_now_cycles, &now_cycles);
+ 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(&time_state.last_sample, &sample);
+ ReadTimeSampleAtomic(&last_sample, &sample);
// ----------
// Try running the fast path again; another thread may have updated the
@@ -424,13 +418,13 @@ static int64_t GetCurrentTimeNanosSlowPath()
// so that blocked readers can make progress without blocking new readers.
estimated_base_ns = sample.base_ns +
((delta_cycles * sample.nsscaled_per_cycle) >> kScale);
- time_state.stats_fast_slow_paths++;
+ stats_fast_slow_paths++;
} else {
estimated_base_ns =
UpdateLastSample(now_cycles, now_ns, delta_cycles, &sample);
}
- time_state.lock.Unlock();
+ lock.Unlock();
return estimated_base_ns;
}
@@ -441,10 +435,9 @@ static int64_t GetCurrentTimeNanosSlowPath()
static uint64_t UpdateLastSample(uint64_t now_cycles, uint64_t now_ns,
uint64_t delta_cycles,
const struct TimeSample *sample)
- ABSL_EXCLUSIVE_LOCKS_REQUIRED(time_state.lock) {
+ ABSL_EXCLUSIVE_LOCKS_REQUIRED(lock) {
uint64_t estimated_base_ns = now_ns;
- uint64_t lock_value =
- SeqAcquire(&time_state.seq); // acquire seqlock to block readers
+ uint64_t lock_value = SeqAcquire(&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.
@@ -454,16 +447,12 @@ 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.
- 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++;
+ 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++;
} else if (sample->raw_ns + 500 * 1000 * 1000 < now_ns &&
sample->base_cycles + 50 < now_cycles) {
// Enough time has passed to compute the cycle time.
@@ -506,32 +495,28 @@ 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
- time_state.last_sample.nsscaled_per_cycle.store(
+ 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);
- time_state.last_sample.min_cycles_per_sample.store(
+ last_sample.min_cycles_per_sample.store(
new_min_cycles_per_sample, std::memory_order_relaxed);
- time_state.stats_calibrations++;
+ stats_calibrations++;
} else { // something went wrong; forget the slope
- 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);
+ last_sample.nsscaled_per_cycle.store(0, std::memory_order_relaxed);
+ last_sample.min_cycles_per_sample.store(0, std::memory_order_relaxed);
estimated_base_ns = now_ns;
- time_state.stats_reinitializations++;
+ stats_reinitializations++;
}
- 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);
+ 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);
} else {
// have a sample, but no slope; waiting for enough time for a calibration
- time_state.stats_slow_paths++;
+ stats_slow_paths++;
}
- SeqRelease(&time_state.seq, lock_value); // release the readers
+ SeqRelease(&seq, lock_value); // release the readers
return estimated_base_ns;
}
@@ -573,8 +558,7 @@ ABSL_NAMESPACE_END
extern "C" {
-ABSL_ATTRIBUTE_WEAK void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(
- absl::Duration duration) {
+ABSL_ATTRIBUTE_WEAK void AbslInternalSleepFor(absl::Duration duration) {
while (duration > absl::ZeroDuration()) {
absl::Duration to_sleep = std::min(duration, absl::MaxSleep());
absl::SleepOnce(to_sleep);
diff --git a/third_party/abseil-cpp/absl/time/clock.h b/third_party/abseil-cpp/absl/time/clock.h
index 5fe244d638..27764a922d 100644
--- a/third_party/abseil-cpp/absl/time/clock.h
+++ b/third_party/abseil-cpp/absl/time/clock.h
@@ -64,11 +64,11 @@ ABSL_NAMESPACE_END
// By changing our extension points to be extern "C", we dodge this
// check.
extern "C" {
-void ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(absl::Duration duration);
+void AbslInternalSleepFor(absl::Duration duration);
} // extern "C"
inline void absl::SleepFor(absl::Duration duration) {
- ABSL_INTERNAL_C_SYMBOL(AbslInternalSleepFor)(duration);
+ AbslInternalSleepFor(duration);
}
#endif // ABSL_TIME_CLOCK_H_
diff --git a/third_party/abseil-cpp/absl/time/clock_test.cc b/third_party/abseil-cpp/absl/time/clock_test.cc
index bc77dbc27b..4bcfc6bc72 100644
--- a/third_party/abseil-cpp/absl/time/clock_test.cc
+++ b/third_party/abseil-cpp/absl/time/clock_test.cc
@@ -18,10 +18,6 @@
#if defined(ABSL_HAVE_ALARM)
#include <signal.h>
#include <unistd.h>
-#ifdef _AIX
-// sig_t is not defined in AIX.
-typedef void (*sig_t)(int);
-#endif
#elif defined(__linux__) || defined(__APPLE__)
#error all known Linux and Apple targets have alarm
#endif
diff --git a/third_party/abseil-cpp/absl/time/duration.cc b/third_party/abseil-cpp/absl/time/duration.cc
index 4443109a51..b1af84061a 100644
--- a/third_party/abseil-cpp/absl/time/duration.cc
+++ b/third_party/abseil-cpp/absl/time/duration.cc
@@ -67,10 +67,7 @@
#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 {
@@ -356,7 +353,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;
@@ -711,17 +708,16 @@ 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 {
- absl::string_view abbr;
+ const char* abbr;
int prec;
double pow10;
};
-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
+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
void AppendNumberUnit(std::string* out, int64_t n, DisplayUnit unit) {
char buf[sizeof("2562047788015216")]; // hours in max duration
@@ -729,16 +725,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.data(), unit.abbr.size());
+ out->append(unit.abbr);
}
}
// 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) {
- 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
+ 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
char* ep = buf + sizeof(buf);
double d = 0;
int64_t frac_part = Round(std::modf(n, &d) * unit.pow10);
@@ -752,7 +748,7 @@ void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
while (ep[-1] == '0') --ep;
out->append(bp, ep - bp);
}
- out->append(unit.abbr.data(), unit.abbr.size());
+ out->append(unit.abbr);
}
}
@@ -763,8 +759,7 @@ void AppendNumberUnit(std::string* out, double n, DisplayUnit unit) {
// 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.
-// Unlike Go, we format the zero duration as 0, with no unit.
+// is non-zero. The zero duration formats as 0, with no unit.
std::string FormatDuration(Duration d) {
const Duration min_duration = Seconds(kint64min);
if (d == min_duration) {
@@ -805,27 +800,23 @@ 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, const char* ep, int64_t* int_part,
+bool ConsumeDurationNumber(const char** dpp, 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 (; *dpp != ep; *dpp += 1) {
+ for (; std::isdigit(**dpp); *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 == ep || **dpp != '.') return !int_part_empty;
-
- for (*dpp += 1; *dpp != ep; *dpp += 1) {
+ if (**dpp != '.') return !int_part_empty;
+ for (*dpp += 1; std::isdigit(**dpp); *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;
@@ -839,56 +830,32 @@ bool ConsumeDurationNumber(const char** dpp, const char* ep, 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, 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;
- }
+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;
}
+ *start = s;
+ return ok;
}
} // namespace
@@ -898,38 +865,39 @@ bool ConsumeDurationUnit(const char** start, const char* end, Duration* unit) {
// 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(absl::string_view dur_sv, Duration* d) {
+bool ParseDuration(const std::string& dur_string, Duration* d) {
+ const char* start = dur_string.c_str();
int sign = 1;
- if (absl::ConsumePrefix(&dur_sv, "-")) {
- sign = -1;
- } else {
- absl::ConsumePrefix(&dur_sv, "+");
+
+ if (*start == '-' || *start == '+') {
+ sign = *start == '-' ? -1 : 1;
+ ++start;
+ }
+
+ // Can't parse a duration from an empty std::string.
+ if (*start == '\0') {
+ return false;
}
- if (dur_sv.empty()) return false;
- // Special case for a string of "0".
- if (dur_sv == "0") {
+ // Special case for a std::string of "0".
+ if (*start == '0' && *(start + 1) == '\0') {
*d = ZeroDuration();
return true;
}
- if (dur_sv == "inf") {
+ if (strcmp(start, "inf") == 0) {
*d = sign * InfiniteDuration();
return true;
}
- const char* start = dur_sv.data();
- const char* end = start + dur_sv.size();
-
Duration dur;
- while (start != end) {
+ while (*start != '\0') {
int64_t int_part;
int64_t frac_part;
int64_t frac_scale;
Duration unit;
- if (!ConsumeDurationNumber(&start, end, &int_part, &frac_part,
- &frac_scale) ||
- !ConsumeDurationUnit(&start, end, &unit)) {
+ if (!ConsumeDurationNumber(&start, &int_part, &frac_part, &frac_scale) ||
+ !ConsumeDurationUnit(&start, &unit)) {
return false;
}
if (int_part != 0) dur += sign * int_part * unit;
@@ -940,7 +908,7 @@ bool ParseDuration(absl::string_view dur_sv, Duration* d) {
}
bool AbslParseFlag(absl::string_view text, Duration* dst, std::string*) {
- return ParseDuration(text, dst);
+ return ParseDuration(std::string(text), dst);
}
std::string AbslUnparseFlag(Duration d) { return FormatDuration(d); }
diff --git a/third_party/abseil-cpp/absl/time/duration_benchmark.cc b/third_party/abseil-cpp/absl/time/duration_benchmark.cc
index 56820f377b..83a836c8c8 100644
--- a/third_party/abseil-cpp/absl/time/duration_benchmark.cc
+++ b/third_party/abseil-cpp/absl/time/duration_benchmark.cc
@@ -18,14 +18,9 @@
#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 {
//
@@ -430,15 +425,4 @@ 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/third_party/abseil-cpp/absl/time/duration_test.cc b/third_party/abseil-cpp/absl/time/duration_test.cc
index b7209e1c0a..4d85a2c4f4 100644
--- a/third_party/abseil-cpp/absl/time/duration_test.cc
+++ b/third_party/abseil-cpp/absl/time/duration_test.cc
@@ -17,7 +17,6 @@
#endif
#include <chrono> // NOLINT(build/c++11)
-#include <cfloat>
#include <cmath>
#include <cstdint>
#include <ctime>
@@ -1321,7 +1320,7 @@ TEST(Duration, SmallConversions) {
EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0));
// TODO(bww): Is the next one OK?
- EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(0.125e-9, 0)));
+ EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0.124999999e-9));
EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.125e-9));
EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.250e-9));
EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.375e-9));
@@ -1331,7 +1330,7 @@ TEST(Duration, SmallConversions) {
EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9));
EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9));
- EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(-0.125e-9, 0)));
+ EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(-0.124999999e-9));
EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9));
EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9));
EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9));
@@ -1370,13 +1369,10 @@ TEST(Duration, SmallConversions) {
EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv));
}
-void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) {
+void VerifySameAsMul(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);
- // 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 (direct_seconds != mul_by_one_second) {
if (*misses > 10) return;
ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more.";
EXPECT_EQ(direct_seconds, mul_by_one_second)
@@ -1388,17 +1384,8 @@ void VerifyApproxSameAsMul(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 a duration near point * Seconds(1.0). (They may
-// not be exactly equal due to fused multiply/add contraction.)
+// Seconds(point) returns the same duration as point * Seconds(1.0)
TEST(Duration, ToDoubleSecondsCheckEdgeCases) {
-#if (defined(__i386__) || defined(_M_IX86)) && FLT_EVAL_METHOD != 0
- // We're using an x87-compatible FPU, and intermediate operations can be
- // performed with 80-bit floats. This means the edge cases are different than
- // what we expect here, so just skip this test.
- GTEST_SKIP()
- << "Skipping the test because we detected x87 floating-point semantics";
-#endif
-
constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond;
constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u);
int misses = 0;
@@ -1436,8 +1423,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.
- VerifyApproxSameAsMul(low_edge, &misses);
- VerifyApproxSameAsMul(high_edge, &misses);
+ VerifySameAsMul(low_edge, &misses);
+ VerifySameAsMul(high_edge, &misses);
}
}
}
@@ -1457,8 +1444,8 @@ TEST(Duration, ToDoubleSecondsCheckRandom) {
int misses = 0;
for (int i = 0; i < 1000000; ++i) {
double d = std::exp(uniform(gen));
- VerifyApproxSameAsMul(d, &misses);
- VerifyApproxSameAsMul(-d, &misses);
+ VerifySameAsMul(d, &misses);
+ VerifySameAsMul(-d, &misses);
}
}
diff --git a/third_party/abseil-cpp/absl/time/format.cc b/third_party/abseil-cpp/absl/time/format.cc
index 4005fb704c..ee088f33c3 100644
--- a/third_party/abseil-cpp/absl/time/format.cc
+++ b/third_party/abseil-cpp/absl/time/format.cc
@@ -13,12 +13,9 @@
// 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"
@@ -27,11 +24,14 @@ namespace cctz = absl::time_internal::cctz;
namespace absl {
ABSL_NAMESPACE_BEGIN
-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";
+ABSL_DLL extern const char RFC3339_full[] =
+ "%Y-%m-%dT%H:%M:%E*S%Ez";
+ABSL_DLL extern const char RFC3339_sec[] = "%Y-%m-%dT%H:%M:%S%Ez";
-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";
+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 {
@@ -71,12 +71,12 @@ absl::Time Join(const cctz_parts& parts) {
} // namespace
-std::string FormatTime(absl::string_view format, absl::Time t,
+std::string FormatTime(const std::string& format, absl::Time t,
absl::TimeZone tz) {
- if (t == absl::InfiniteFuture()) return std::string(kInfiniteFutureStr);
- if (t == absl::InfinitePast()) return std::string(kInfinitePastStr);
+ if (t == absl::InfiniteFuture()) return kInfiniteFutureStr;
+ if (t == absl::InfinitePast()) return kInfinitePastStr;
const auto parts = Split(t);
- return cctz::detail::format(std::string(format), parts.sec, parts.fem,
+ return cctz::detail::format(format, parts.sec, parts.fem,
cctz::time_zone(tz));
}
@@ -88,50 +88,42 @@ std::string FormatTime(absl::Time t) {
return absl::FormatTime(RFC3339_full, t, absl::LocalTimeZone());
}
-bool ParseTime(absl::string_view format, absl::string_view input,
+bool ParseTime(const std::string& format, const std::string& 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(absl::string_view format, absl::string_view input,
+bool ParseTime(const std::string& format, const std::string& 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);
+ 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;
}
- };
-
- // 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;
- }
+ }
+
+ 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;
}
}
std::string error;
cctz_parts parts;
- const bool b =
- cctz::detail::parse(std::string(format), std::string(input),
- cctz::time_zone(tz), &parts.sec, &parts.fem, &error);
+ const bool b = cctz::detail::parse(format, input, cctz::time_zone(tz),
+ &parts.sec, &parts.fem, &error);
if (b) {
*time = Join(parts);
} else if (err != nullptr) {
@@ -142,7 +134,8 @@ bool ParseTime(absl::string_view format, absl::string_view input,
// 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);
+ return absl::ParseTime(RFC3339_full, std::string(text), absl::UTCTimeZone(),
+ t, error);
}
std::string AbslUnparseFlag(absl::Time t) {
diff --git a/third_party/abseil-cpp/absl/time/format_benchmark.cc b/third_party/abseil-cpp/absl/time/format_benchmark.cc
index 19e481dbd1..249c51d875 100644
--- a/third_party/abseil-cpp/absl/time/format_benchmark.cc
+++ b/third_party/abseil-cpp/absl/time/format_benchmark.cc
@@ -26,7 +26,7 @@ const char* const kFormats[] = {
absl::RFC1123_no_wday, // 1
absl::RFC3339_full, // 2
absl::RFC3339_sec, // 3
- "%Y-%m-%d%ET%H:%M:%S", // 4
+ "%Y-%m-%dT%H:%M:%S", // 4
"%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/third_party/abseil-cpp/absl/time/format_test.cc b/third_party/abseil-cpp/absl/time/format_test.cc
index a9a1eb8ee1..ab1f30594e 100644
--- a/third_party/abseil-cpp/absl/time/format_test.cc
+++ b/third_party/abseil-cpp/absl/time/format_test.cc
@@ -173,7 +173,7 @@ TEST(ParseTime, WithTimeZone) {
absl::Time t;
std::string e;
- // We can parse a string without a UTC offset if we supply a timezone.
+ // We can parse a std::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;
@@ -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 string
+ // "infinite-future" as literal std::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 string
+ // "infinite-past" as literal std::string
EXPECT_TRUE(
absl::ParseTime("infinite-past %H:%M", "infinite-past 03:04", &t, &err));
EXPECT_NE(absl::InfinitePast(), t);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel b/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
index bdc2e3091c..7a53c815b9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/BUILD.bazel
@@ -12,9 +12,11 @@
# 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"])
+licenses(["notice"]) # Apache License
filegroup(
name = "zoneinfo",
@@ -24,14 +26,14 @@ filegroup(
config_setting(
name = "osx",
constraint_values = [
- "@platforms//os:osx",
+ "@bazel_tools//platforms:osx",
],
)
config_setting(
name = "ios",
constraint_values = [
- "@platforms//os:ios",
+ "@bazel_tools//platforms:ios",
],
)
@@ -90,11 +92,6 @@ cc_library(
### tests
-test_suite(
- name = "all_tests",
- visibility = ["//visibility:public"],
-)
-
cc_test(
name = "civil_time_test",
size = "small",
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
index 8aadde57ca..4cde96f1aa 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/civil_time_detail.h
@@ -106,64 +106,54 @@ CONSTEXPR_F int days_per_month(year_t y, month_t m) noexcept {
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;
+ y += (cd / 146097) * 400;
cd %= 146097;
if (cd < 0) {
- ey -= 400;
+ y -= 400;
cd += 146097;
}
- ey += (d / 146097) * 400;
+ y += (d / 146097) * 400;
d = d % 146097 + cd;
if (d > 0) {
if (d > 146097) {
- ey += 400;
+ y += 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.
- ey -= 1;
- d += days_per_year(ey, m);
+ y -= 1;
+ d += days_per_year(y, m);
} else {
- ey -= 400;
+ y -= 400;
d += 146097;
}
}
if (d > 365) {
- for (;;) {
- int n = days_per_century(ey, m);
- if (d <= n) break;
+ for (int n = days_per_century(y, m); d > n; n = days_per_century(y, m)) {
d -= n;
- ey += 100;
+ y += 100;
}
- for (;;) {
- int n = days_per_4years(ey, m);
- if (d <= n) break;
+ for (int n = days_per_4years(y, m); d > n; n = days_per_4years(y, m)) {
d -= n;
- ey += 4;
+ y += 4;
}
- for (;;) {
- int n = days_per_year(ey, m);
- if (d <= n) break;
+ for (int n = days_per_year(y, m); d > n; n = days_per_year(y, m)) {
d -= n;
- ++ey;
+ ++y;
}
}
if (d > 28) {
- for (;;) {
- int n = days_per_month(ey, m);
- if (d <= n) break;
+ for (int n = days_per_month(y, m); d > n; n = days_per_month(y, m)) {
d -= n;
if (++m > 12) {
- ++ey;
+ ++y;
m = 1;
}
}
}
- return fields(y + (ey - oey), m, static_cast<day_t>(d), hh, mm, ss);
+ return fields(y, 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 {
@@ -416,10 +406,16 @@ class civil_time {
// Assigning arithmetic.
CONSTEXPR_M civil_time& operator+=(diff_t n) noexcept {
- return *this = *this + n;
+ f_ = step(T{}, f_, n);
+ return *this;
}
CONSTEXPR_M civil_time& operator-=(diff_t n) noexcept {
- return *this = *this - n;
+ 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; }
CONSTEXPR_M civil_time operator++(int) noexcept {
@@ -436,15 +432,13 @@ class civil_time {
// Binary arithmetic operators.
friend CONSTEXPR_F civil_time operator+(civil_time a, diff_t n) noexcept {
- return civil_time(step(T{}, a.f_, n));
+ return a += 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 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));
+ return a -= n;
}
friend CONSTEXPR_F diff_t operator-(civil_time lhs, civil_time rhs) noexcept {
return difference(T{}, lhs.f_, rhs.f_);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
index 6e382dc6c9..d05147a17c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/time_zone.h
@@ -22,7 +22,6 @@
#include <chrono>
#include <cstdint>
-#include <limits>
#include <string>
#include <utility>
@@ -42,9 +41,20 @@ using sys_seconds = seconds; // Deprecated. Use cctz::seconds instead.
namespace detail {
template <typename D>
-std::pair<time_point<seconds>, D> split_seconds(const time_point<D>& tp);
-std::pair<time_point<seconds>, seconds> split_seconds(
- const time_point<seconds>& 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) {
+ sec -= seconds(1);
+ sub += seconds(1);
+ }
+ return {sec, std::chrono::duration_cast<D>(sub)};
+}
+inline std::pair<time_point<seconds>, seconds> split_seconds(
+ const time_point<seconds>& tp) {
+ return {tp, seconds::zero()};
+}
} // namespace detail
// cctz::time_zone is an opaque, small, value-type class representing a
@@ -199,7 +209,7 @@ class time_zone {
// 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() string will be in the familar form (e.g, "2018e") or
+ // the version() std::string will be in the familar form (e.g, "2018e") or
// empty when unavailable.
//
// Note: These functions are for informational or testing purposes only.
@@ -269,20 +279,6 @@ std::string format(const std::string&, const time_point<seconds>&,
const femtoseconds&, const time_zone&);
bool parse(const std::string&, const std::string&, const time_zone&,
time_point<seconds>*, femtoseconds*, std::string* err = nullptr);
-template <typename Rep, std::intmax_t Denom>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds& fs,
- time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp);
-template <typename Rep, std::intmax_t Num>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds& fs,
- time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp);
-template <typename Rep>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds& fs,
- time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp);
-bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,
- time_point<seconds>* tpp);
} // namespace detail
// Formats the given time_point in the given cctz::time_zone according to
@@ -296,7 +292,6 @@ bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,
// - %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'.
@@ -326,8 +321,7 @@ 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, which (along with %z) includes
-// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
+// and %E*z also accept the same inputs.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
@@ -373,84 +367,15 @@ inline bool parse(const std::string& fmt, const std::string& input,
const time_zone& tz, time_point<D>* tpp) {
time_point<seconds> sec;
detail::femtoseconds fs;
- return detail::parse(fmt, input, tz, &sec, &fs) &&
- detail::join_seconds(sec, fs, tpp);
-}
-
-namespace detail {
-
-// Split a time_point<D> into a time_point<seconds> and a D subseconds.
-// Undefined behavior if time_point<seconds> is not of sufficient range.
-// Note that this means it is UB to call cctz::time_zone::lookup(tp) or
-// cctz::format(fmt, tp, tz) with a time_point that is outside the range
-// of a 64-bit std::time_t.
-template <typename D>
-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) {
- sec -= seconds(1);
- sub += seconds(1);
+ const bool b = detail::parse(fmt, input, tz, &sec, &fs);
+ if (b) {
+ // TODO: Return false if unrepresentable as a time_point<D>.
+ *tpp = std::chrono::time_point_cast<D>(sec);
+ *tpp += std::chrono::duration_cast<D>(fs);
}
- return {sec, std::chrono::duration_cast<D>(sub)};
-}
-
-inline std::pair<time_point<seconds>, seconds> split_seconds(
- const time_point<seconds>& tp) {
- return {tp, seconds::zero()};
+ return b;
}
-// Join a time_point<seconds> and femto subseconds into a time_point<D>.
-// Floors to the resolution of time_point<D>. Returns false if time_point<D>
-// is not of sufficient range.
-template <typename Rep, std::intmax_t Denom>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds& fs,
- time_point<std::chrono::duration<Rep, std::ratio<1, Denom>>>* tpp) {
- using D = std::chrono::duration<Rep, std::ratio<1, Denom>>;
- // TODO(#199): Return false if result unrepresentable as a time_point<D>.
- *tpp = std::chrono::time_point_cast<D>(sec);
- *tpp += std::chrono::duration_cast<D>(fs);
- return true;
-}
-
-template <typename Rep, std::intmax_t Num>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds&,
- time_point<std::chrono::duration<Rep, std::ratio<Num, 1>>>* tpp) {
- using D = std::chrono::duration<Rep, std::ratio<Num, 1>>;
- auto count = sec.time_since_epoch().count();
- if (count >= 0 || count % Num == 0) {
- count /= Num;
- } else {
- count /= Num;
- count -= 1;
- }
- if (count > (std::numeric_limits<Rep>::max)()) return false;
- if (count < (std::numeric_limits<Rep>::min)()) return false;
- *tpp = time_point<D>() + D{static_cast<Rep>(count)};
- return true;
-}
-
-template <typename Rep>
-bool join_seconds(
- const time_point<seconds>& sec, const femtoseconds&,
- time_point<std::chrono::duration<Rep, std::ratio<1, 1>>>* tpp) {
- using D = std::chrono::duration<Rep, std::ratio<1, 1>>;
- auto count = sec.time_since_epoch().count();
- if (count > (std::numeric_limits<Rep>::max)()) return false;
- if (count < (std::numeric_limits<Rep>::min)()) return false;
- *tpp = time_point<D>() + D{static_cast<Rep>(count)};
- return true;
-}
-
-inline bool join_seconds(const time_point<seconds>& sec, const femtoseconds&,
- time_point<seconds>* tpp) {
- *tpp = sec;
- return true;
-}
-
-} // namespace detail
} // namespace cctz
} // namespace time_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
index 012eb4ec30..912b44ba8f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/include/cctz/zone_info_source.h
@@ -37,7 +37,7 @@ class ZoneInfoSource {
// 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 string.
+ // implementation returns an empty std::string.
virtual std::string Version() const;
};
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
index 6770ad6b97..d30a644e09 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/cctz_benchmark.cc
@@ -97,8 +97,8 @@ void BM_PrevWeekday(benchmark::State& state) {
}
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 RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%dT%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";
@@ -280,7 +280,6 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan",
"America/North_Dakota/Beulah",
"America/North_Dakota/Center",
"America/North_Dakota/New_Salem",
- "America/Nuuk",
"America/Ojinaga",
"America/Panama",
"America/Pangnirtung",
@@ -648,7 +647,6 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Johnston",
- "Pacific/Kanton",
"Pacific/Kiritimati",
"Pacific/Kosrae",
"Pacific/Kwajalein",
@@ -992,12 +990,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-%d%ET%H:%M:%S", // 4
- "%Y-%m-%d", // 5
+ RFC1123_full, // 0
+ RFC1123_no_wday, // 1
+ RFC3339_full, // 2
+ RFC3339_sec, // 3
+ "%Y-%m-%dT%H:%M:%S", // 4
+ "%Y-%m-%d", // 5
};
const int kNumFormats = sizeof(kFormats) / sizeof(kFormats[0]);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
index a5a7123041..be894d7072 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/civil_time_test.cc
@@ -235,16 +235,6 @@ 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);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
index f2b3294ef7..303c0244a8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_fixed.cc
@@ -53,7 +53,7 @@ int Parse02d(const char* p) {
} // namespace
bool FixedOffsetFromName(const std::string& name, seconds* offset) {
- if (name == "UTC" || name == "UTC0") {
+ if (name.compare(0, std::string::npos, "UTC", 3) == 0) {
*offset = seconds::zero();
return true;
}
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
index d8cb047425..950b23a1d2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format.cc
@@ -67,48 +67,6 @@ 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();
@@ -126,19 +84,34 @@ std::tm ToTM(const time_zone::absolute_lookup& al) {
tm.tm_year = static_cast<int>(al.cs.year() - 1900);
}
- tm.tm_wday = ToTmWday(get_weekday(al.cs));
+ switch (get_weekday(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(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
@@ -216,7 +189,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 string
+ // the following code grows the buffer size from 2x the format std::string
// length up to 32x.
for (std::size_t i = 2; i != 32; i *= 2) {
std::size_t buf_size = fmt.size() * i;
@@ -317,7 +290,6 @@ 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
@@ -382,7 +354,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("YmdeUuWwHMSzZs%", *cur)) {
+ if (strchr("YmdeHMSzZs%", *cur)) {
if (cur - 1 != pending) {
FormatTM(&result, std::string(pending, cur - 1), tm);
}
@@ -403,22 +375,6 @@ 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));
@@ -492,14 +448,7 @@ std::string format(const std::string& format, const time_point<seconds>& tp,
if (*cur != 'E' || ++cur == end) continue;
// Format our extensions.
- 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') {
+ if (*cur == 'z') {
// Formats %Ez.
if (cur - 2 != pending) {
FormatTM(&result, std::string(pending, cur - 2), tm);
@@ -602,7 +551,7 @@ const char* ParseOffset(const char* dp, const char* mode, int* offset) {
} else {
dp = nullptr;
}
- } else if (first == 'Z' || first == 'z') { // Zulu
+ } else if (first == 'Z') { // Zulu
*offset = 0;
} else {
dp = nullptr;
@@ -653,32 +602,12 @@ 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. %ET accepts either 'T' or 't'.
+// the same inputs.
//
// The standard specifiers from RFC3339_* (%Y, %m, %d, %H, %M, and %S) are
// handled internally so that we can normally avoid strptime() altogether
@@ -722,8 +651,6 @@ 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;
@@ -762,27 +689,10 @@ 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);
@@ -832,15 +742,6 @@ bool parse(const std::string& format, const std::string& input,
data = (*data == '%' ? data + 1 : nullptr);
continue;
case 'E':
- 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;
@@ -938,7 +839,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 string.
+ // parse() must consume the entire input std::string.
if (*data != '\0') {
if (err != nullptr) *err = "Illegal trailing data in input string";
return false;
@@ -973,14 +874,6 @@ 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);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
index 6487fa9373..caebcc4d95 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -13,7 +13,6 @@
// limitations under the License.
#include <chrono>
-#include <cstdint>
#include <iomanip>
#include <sstream>
#include <string>
@@ -49,8 +48,8 @@ namespace {
EXPECT_STREQ(zone, al.abbr); \
} while (0)
-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 RFC3339_full[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
+const char RFC3339_sec[] = "%Y-%m-%dT%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";
@@ -680,34 +679,6 @@ 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()
//
@@ -796,7 +767,7 @@ TEST(Parse, WithTimeZone) {
EXPECT_TRUE(load_time_zone("America/Los_Angeles", &tz));
time_point<chrono::nanoseconds> tp;
- // We can parse a string without a UTC offset if we supply a timezone.
+ // We can parse a std::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");
@@ -1136,7 +1107,7 @@ TEST(Parse, ExtendedSeconds) {
// All %E<prec>S cases are treated the same as %E*S on input.
auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15"};
- for (const std::string prec : precisions) {
+ for (const std::string& prec : precisions) {
const std::string fmt = "%E" + prec + "S";
SCOPED_TRACE(fmt);
time_point<chrono::nanoseconds> tp = unix_epoch;
@@ -1218,7 +1189,7 @@ TEST(Parse, ExtendedSubeconds) {
// All %E<prec>f cases are treated the same as %E*f on input.
auto precisions = {"*", "0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15"};
- for (const std::string prec : precisions) {
+ for (const std::string& prec : precisions) {
const std::string fmt = "%E" + prec + "f";
SCOPED_TRACE(fmt);
time_point<chrono::nanoseconds> tp = unix_epoch - chrono::seconds(1);
@@ -1408,85 +1379,10 @@ 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 %ET also accepts "t".
+ // Check that %Ez also accepts "Z" as a synonym for "+00:00".
time_point<chrono::nanoseconds> tp2;
- EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12t20:21:00+00:00", tz, &tp2));
+ EXPECT_TRUE(parse(RFC3339_sec, "2014-02-12T20:21:00Z", 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) {
@@ -1505,7 +1401,7 @@ TEST(Parse, MaxRange) {
parse(RFC3339_sec, "292277026596-12-04T14:30:07-01:00", utc, &tp));
EXPECT_EQ(tp, time_point<absl::time_internal::cctz::seconds>::max());
EXPECT_FALSE(
- parse(RFC3339_sec, "292277026596-12-04T14:30:08-01:00", utc, &tp));
+ parse(RFC3339_sec, "292277026596-12-04T15:30:07-01:00", utc, &tp));
// tests the lower limit using +00:00 offset
EXPECT_TRUE(
@@ -1526,82 +1422,10 @@ TEST(Parse, MaxRange) {
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));
-}
-
-TEST(Parse, TimePointOverflow) {
- const time_zone utc = utc_time_zone();
- using D = chrono::duration<std::int64_t, std::nano>;
- time_point<D> tp;
-
- EXPECT_TRUE(
- parse(RFC3339_full, "2262-04-11T23:47:16.8547758079+00:00", utc, &tp));
- EXPECT_EQ(tp, time_point<D>::max());
- EXPECT_EQ("2262-04-11T23:47:16.854775807+00:00",
- format(RFC3339_full, tp, utc));
-#if 0
- // TODO(#199): Will fail until cctz::parse() properly detects overflow.
- EXPECT_FALSE(
- parse(RFC3339_full, "2262-04-11T23:47:16.8547758080+00:00", utc, &tp));
- EXPECT_TRUE(
- parse(RFC3339_full, "1677-09-21T00:12:43.1452241920+00:00", utc, &tp));
- EXPECT_EQ(tp, time_point<D>::min());
- EXPECT_EQ("1677-09-21T00:12:43.145224192+00:00",
- format(RFC3339_full, tp, utc));
- EXPECT_FALSE(
- parse(RFC3339_full, "1677-09-21T00:12:43.1452241919+00:00", utc, &tp));
-#endif
-
- using DS = chrono::duration<std::int8_t, chrono::seconds::period>;
- time_point<DS> stp;
-
- EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T00:02:07.9+00:00", utc, &stp));
- EXPECT_EQ(stp, time_point<DS>::max());
- EXPECT_EQ("1970-01-01T00:02:07+00:00", format(RFC3339_full, stp, utc));
- EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T00:02:08+00:00", utc, &stp));
-
- EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T23:57:52+00:00", utc, &stp));
- EXPECT_EQ(stp, time_point<DS>::min());
- EXPECT_EQ("1969-12-31T23:57:52+00:00", format(RFC3339_full, stp, utc));
- EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T23:57:51.9+00:00", utc, &stp));
-
- using DM = chrono::duration<std::int8_t, chrono::minutes::period>;
- time_point<DM> mtp;
-
- EXPECT_TRUE(parse(RFC3339_full, "1970-01-01T02:07:59+00:00", utc, &mtp));
- EXPECT_EQ(mtp, time_point<DM>::max());
- EXPECT_EQ("1970-01-01T02:07:00+00:00", format(RFC3339_full, mtp, utc));
- EXPECT_FALSE(parse(RFC3339_full, "1970-01-01T02:08:00+00:00", utc, &mtp));
-
- EXPECT_TRUE(parse(RFC3339_full, "1969-12-31T21:52:00+00:00", utc, &mtp));
- EXPECT_EQ(mtp, time_point<DM>::min());
- EXPECT_EQ("1969-12-31T21:52:00+00:00", format(RFC3339_full, mtp, utc));
- EXPECT_FALSE(parse(RFC3339_full, "1969-12-31T21:51:59+00:00", utc, &mtp));
-}
-
-TEST(Parse, TimePointOverflowFloor) {
- const time_zone utc = utc_time_zone();
-
- using D = chrono::duration<std::int64_t, std::micro>;
- time_point<D> tp;
-
- EXPECT_TRUE(
- parse(RFC3339_full, "294247-01-10T04:00:54.7758079+00:00", utc, &tp));
- EXPECT_EQ(tp, time_point<D>::max());
- EXPECT_EQ("294247-01-10T04:00:54.775807+00:00",
- format(RFC3339_full, tp, utc));
-#if 0
- // TODO(#199): Will fail until cctz::parse() properly detects overflow.
- EXPECT_FALSE(
- parse(RFC3339_full, "294247-01-10T04:00:54.7758080+00:00", utc, &tp));
- EXPECT_TRUE(
- parse(RFC3339_full, "-290308-12-21T19:59:05.2241920+00:00", utc, &tp));
- EXPECT_EQ(tp, time_point<D>::min());
- EXPECT_EQ("-290308-12-21T19:59:05.224192+00:00",
- format(RFC3339_full, tp, utc));
- EXPECT_FALSE(
- parse(RFC3339_full, "-290308-12-21T19:59:05.2241919+00:00", utc, &tp));
-#endif
+ // TODO: Add tests that parsing times with fractional seconds overflow
+ // appropriately. This can't be done until cctz::parse() properly detects
+ // overflow when combining the chrono seconds and femto.
}
//
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
index 7d3e42d3cd..32c0891c1e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_if.h
@@ -56,8 +56,7 @@ class TimeZoneIf {
// Convert between time_point<seconds> and a count of seconds since the
// Unix epoch. We assume that the std::chrono::system_clock and the
-// Unix clock are second aligned, and that the results are representable.
-// (That is, that they share an epoch, which is required since C++20.)
+// 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)))
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
index f34e3aec84..030ae0e19e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.cc
@@ -15,7 +15,6 @@
#include "time_zone_impl.h"
#include <deque>
-#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
@@ -49,16 +48,17 @@ std::mutex& TimeZoneMutex() {
time_zone time_zone::Impl::UTC() { return time_zone(UTCImpl()); }
bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
- const Impl* const utc_impl = UTCImpl();
+ const time_zone::Impl* const utc_impl = UTCImpl();
- // Check for UTC (which is never a key in time_zone_map).
+ // First 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;
}
- // Check whether the time zone has already been loaded.
+ // Then check, under a shared lock, whether the time zone has already
+ // been loaded. This is the common path. TODO: Move to shared_mutex.
{
std::lock_guard<std::mutex> lock(TimeZoneMutex());
if (time_zone_map != nullptr) {
@@ -70,15 +70,20 @@ bool time_zone::Impl::LoadTimeZone(const std::string& name, time_zone* tz) {
}
}
- // 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.
+ // Now check again, under an exclusive lock.
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) { // this thread won any load race
- impl = new_impl->zone_ ? new_impl.release() : utc_impl;
+ 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
+ }
}
*tz = time_zone(impl);
return impl != utc_impl;
@@ -99,11 +104,14 @@ void time_zone::Impl::ClearTimeZoneMapTestOnly() {
}
}
-time_zone::Impl::Impl(const std::string& name)
- : name_(name), zone_(TimeZoneIf::Load(name_)) {}
+time_zone::Impl::Impl(const std::string& name) : name_(name) {}
const time_zone::Impl* time_zone::Impl::UTCImpl() {
- static const Impl* utc_impl = new Impl("UTC"); // never fails
+ static Impl* utc_impl = [] {
+ Impl* impl = new Impl("UTC");
+ impl->zone_ = TimeZoneIf::Load(impl->name_); // never fails
+ return impl;
+ }();
return utc_impl;
}
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
index 7d747ba966..69806c10d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_impl.h
@@ -71,7 +71,7 @@ class time_zone::Impl {
return zone_->PrevTransition(tp, trans);
}
- // Returns an implementation-defined version string for this time zone.
+ // Returns an implementation-defined version std::string for this time zone.
std::string Version() const { return zone_->Version(); }
// Returns an implementation-defined description of this time zone.
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
index 4f175d95fc..f1697cdf04 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.cc
@@ -39,12 +39,11 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
-#include <fstream>
#include <functional>
+#include <iostream>
#include <memory>
#include <sstream>
#include <string>
-#include <utility>
#include "absl/base/config.h"
#include "absl/time/internal/cctz/include/cctz/civil_time.h"
@@ -84,27 +83,6 @@ const std::int_least32_t kSecsPerYear[2] = {
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;
@@ -210,13 +188,15 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
tt.is_dst = false;
tt.abbr_index = 0;
- // We temporarily add some redundant, contemporary (2015 through 2025)
+ // We temporarily add some redundant, contemporary (2013 through 2023)
// 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), // a "first half" transition
+ -(1LL << 59), // BIG_BANG
+ 1356998400LL, // 2013-01-01T00:00:00+00:00
+ 1388534400LL, // 2014-01-01T00:00:00+00:00
1420070400LL, // 2015-01-01T00:00:00+00:00
1451606400LL, // 2016-01-01T00:00:00+00:00
1483228800LL, // 2017-01-01T00:00:00+00:00
@@ -226,8 +206,7 @@ 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
- 1704067200LL, // 2024-01-01T00:00:00+00:00
- 1735689600LL, // 2025-01-01T00:00:00+00:00
+ 2147483647LL, // 2^31 - 1
}) {
Transition& tr(*transitions_.emplace(transitions_.end()));
tr.unix_time = unix_time;
@@ -238,8 +217,8 @@ bool TimeZoneInfo::ResetToBuiltinUTC(const seconds& offset) {
default_transition_type_ = 0;
abbreviations_ = FixedOffsetToAbbr(offset);
- abbreviations_.append(1, '\0');
- future_spec_.clear(); // never needed for a fixed-offset zone
+ abbreviations_.append(1, '\0'); // add NUL
+ future_spec_.clear(); // never needed for a fixed-offset zone
extended_ = false;
tt.civil_max = LocalTime(seconds::max().count(), tt).cs;
@@ -280,6 +259,21 @@ std::size_t TimeZoneInfo::Header::DataLength(std::size_t time_len) const {
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).
@@ -288,108 +282,117 @@ 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.utc_offset != tt2.utc_offset) return false;
if (tt1.is_dst != tt2.is_dst) return false;
+ if (tt1.utc_offset != tt2.utc_offset) 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.
-bool TimeZoneInfo::ExtendTransitions() {
+void TimeZoneInfo::ExtendTransitions(const std::string& name,
+ const Header& hdr) {
extended_ = false;
- if (future_spec_.empty()) return true; // last transition prevails
+ bool extending = !future_spec_.empty();
PosixTimeZone posix;
- 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);
+ 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
}
- // 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.
- // We may need two additional transitions for the current year.
- transitions_.reserve(transitions_.size() + 400 * 2 + 2);
+ // 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);
extended_ = true;
- 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();
+ // 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();
bool leap_year = IsLeap(last_year_);
- 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;
+ 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
jan1_time += kSecsPerYear[leap_year];
jan1_weekday = (jan1_weekday + kDaysPerYear[leap_year]) % 7;
- leap_year = !leap_year && IsLeap(last_year_ + 1);
- }
-
- return true;
+ 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());
}
-bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
+bool TimeZoneInfo::Load(const std::string& name, ZoneInfoSource* zip) {
// Read and validate the header.
tzhead tzh;
if (zip->Read(&tzh, sizeof(tzh)) != sizeof(tzh)) return false;
@@ -427,7 +430,7 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
const char* bp = tbuf.data();
// Decode and validate the transitions.
- transitions_.reserve(hdr.timecnt + 2);
+ transitions_.reserve(hdr.timecnt + 2); // We might add a couple.
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);
@@ -446,7 +449,6 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
}
// 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 =
@@ -473,7 +475,6 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
}
// Copy all the abbreviations.
- abbreviations_.reserve(hdr.charcnt + 10);
abbreviations_.assign(bp, hdr.charcnt);
bp += hdr.charcnt;
@@ -505,7 +506,7 @@ bool TimeZoneInfo::Load(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 string it may be privy to.
+ // ZoneInfoSource for any out-of-bound version std::string it may be privy to.
if (version_.empty()) {
version_ = zip->Version();
}
@@ -524,29 +525,19 @@ bool TimeZoneInfo::Load(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 below) so that the signed
- // difference between a civil_second and the civil_second of its
- // previous transition is always representable, without overflow.
+ // 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.
if (transitions_.empty() || transitions_.front().unix_time >= 0) {
Transition& tr(*transitions_.emplace(transitions_.begin()));
- tr.unix_time = -(1LL << 59); // -18267312070-10-26T17:01:52+00:00
+ tr.unix_time = -(1LL << 59); // see tz/zic.c "BIG_BANG"
tr.type_index = default_transition_type_;
+ hdr.timecnt += 1;
}
// Extend the transitions using the future specification.
- 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;
- }
+ ExtendTransitions(name, hdr);
// Compute the local civil time for each transition and the preceding
// second. These will be used for reverse conversions in MakeTime().
@@ -578,17 +569,14 @@ bool TimeZoneInfo::Load(ZoneInfoSource* zip) {
namespace {
-using FilePtr = std::unique_ptr<FILE, int (*)(FILE*)>;
-
// fopen(3) adaptor.
-inline FilePtr FOpen(const char* path, const char* mode) {
+inline FILE* FOpen(const char* path, const char* mode) {
#if defined(_MSC_VER)
FILE* fp;
if (fopen_s(&fp, path, mode) != 0) fp = nullptr;
- return FilePtr(fp, fclose);
+ return fp;
#else
- // TODO: Enable the close-on-exec flag.
- return FilePtr(fopen(path, mode), fclose);
+ return fopen(path, mode); // TODO: Enable the close-on-exec flag.
#endif
}
@@ -616,11 +604,11 @@ class FileZoneInfoSource : public ZoneInfoSource {
protected:
explicit FileZoneInfoSource(
- FilePtr fp, std::size_t len = std::numeric_limits<std::size_t>::max())
- : fp_(std::move(fp)), len_(len) {}
+ FILE* fp, std::size_t len = std::numeric_limits<std::size_t>::max())
+ : fp_(fp, fclose), len_(len) {}
private:
- FilePtr fp_;
+ std::unique_ptr<FILE, int (*)(FILE*)> fp_;
std::size_t len_;
};
@@ -649,9 +637,17 @@ std::unique_ptr<ZoneInfoSource> FileZoneInfoSource::Open(
path.append(name, pos, std::string::npos);
// Open the zoneinfo file.
- auto fp = FOpen(path.c_str(), "rb");
+ FILE* fp = FOpen(path.c_str(), "rb");
if (fp == nullptr) return nullptr;
- return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(std::move(fp)));
+ std::size_t length = 0;
+ if (fseek(fp, 0, SEEK_END) == 0) {
+ long offset = ftell(fp);
+ if (offset >= 0) {
+ length = static_cast<std::size_t>(offset);
+ }
+ rewind(fp);
+ }
+ return std::unique_ptr<ZoneInfoSource>(new FileZoneInfoSource(fp, length));
}
class AndroidZoneInfoSource : public FileZoneInfoSource {
@@ -660,9 +656,8 @@ class AndroidZoneInfoSource : public FileZoneInfoSource {
std::string Version() const override { return version_; }
private:
- explicit AndroidZoneInfoSource(FilePtr fp, std::size_t len,
- std::string version)
- : FileZoneInfoSource(std::move(fp), len), version_(std::move(version)) {}
+ explicit AndroidZoneInfoSource(FILE* fp, std::size_t len, const char* vers)
+ : FileZoneInfoSource(fp, len), version_(vers) {}
std::string version_;
};
@@ -674,8 +669,8 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
// See Android's libc/tzcode/bionic.cpp for additional information.
for (const char* tzdata : {"/data/misc/zoneinfo/current/tzdata",
"/system/usr/share/zoneinfo/tzdata"}) {
- auto fp = FOpen(tzdata, "rb");
- if (fp == nullptr) continue;
+ std::unique_ptr<FILE, int (*)(FILE*)> fp(FOpen(tzdata, "rb"), fclose);
+ if (fp.get() == nullptr) continue;
char hbuf[24]; // covers header.zonetab_offset too
if (fread(hbuf, 1, sizeof(hbuf), fp.get()) != sizeof(hbuf)) continue;
@@ -701,7 +696,7 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
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(
- std::move(fp), static_cast<std::size_t>(length), vers));
+ fp.release(), static_cast<std::size_t>(length), vers));
}
}
}
@@ -709,69 +704,6 @@ std::unique_ptr<ZoneInfoSource> AndroidZoneInfoSource::Open(
return nullptr;
}
-// A zoneinfo source for use inside Fuchsia components. This attempts to
-// read zoneinfo files from one of several known paths in a component's
-// incoming namespace. [Config data][1] is preferred, but package-specific
-// resources are also supported.
-//
-// Fuchsia's implementation supports `FileZoneInfoSource::Version()`.
-//
-// [1]:
-// https://fuchsia.dev/fuchsia-src/development/components/data#using_config_data_in_your_component
-class FuchsiaZoneInfoSource : public FileZoneInfoSource {
- public:
- static std::unique_ptr<ZoneInfoSource> Open(const std::string& name);
- std::string Version() const override { return version_; }
-
- private:
- explicit FuchsiaZoneInfoSource(FilePtr fp, std::string version)
- : FileZoneInfoSource(std::move(fp)), version_(std::move(version)) {}
- std::string version_;
-};
-
-std::unique_ptr<ZoneInfoSource> FuchsiaZoneInfoSource::Open(
- const std::string& name) {
- // Use of the "file:" prefix is intended for testing purposes only.
- const std::size_t pos = (name.compare(0, 5, "file:") == 0) ? 5 : 0;
-
- // Prefixes where a Fuchsia component might find zoneinfo files,
- // in descending order of preference.
- const auto kTzdataPrefixes = {
- "/config/data/tzdata/",
- "/pkg/data/tzdata/",
- "/data/tzdata/",
- };
- const auto kEmptyPrefix = {""};
- const bool name_absolute = (pos != name.size() && name[pos] == '/');
- const auto prefixes = name_absolute ? kEmptyPrefix : kTzdataPrefixes;
-
- // Fuchsia builds place zoneinfo files at "<prefix><format><name>".
- for (const std::string prefix : prefixes) {
- std::string path = prefix;
- if (!prefix.empty()) path += "zoneinfo/tzif2/"; // format
- path.append(name, pos, std::string::npos);
-
- auto fp = FOpen(path.c_str(), "rb");
- if (fp == nullptr) continue;
-
- std::string version;
- if (!prefix.empty()) {
- // Fuchsia builds place the version in "<prefix>revision.txt".
- std::ifstream version_stream(prefix + "revision.txt");
- if (version_stream.is_open()) {
- // revision.txt should contain no newlines, but to be
- // defensive we read just the first line.
- std::getline(version_stream, version);
- }
- }
-
- return std::unique_ptr<ZoneInfoSource>(
- new FuchsiaZoneInfoSource(std::move(fp), std::move(version)));
- }
-
- return nullptr;
-}
-
} // namespace
bool TimeZoneInfo::Load(const std::string& name) {
@@ -786,13 +718,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& n) -> std::unique_ptr<ZoneInfoSource> {
- if (auto z = FileZoneInfoSource::Open(n)) return z;
- if (auto z = AndroidZoneInfoSource::Open(n)) return z;
- if (auto z = FuchsiaZoneInfoSource::Open(n)) return z;
+ 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;
return nullptr;
});
- return zip != nullptr && Load(zip.get());
+ return zip != nullptr && Load(name, zip.get());
}
// BreakTime() translation for a particular transition type.
@@ -966,8 +897,8 @@ 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 some zoneinfo data as it is
- // really a sentinel, not a transition. See pre-2018f tz/zic.c.
+ // Do not report the BIG_BANG found in recent zoneinfo data as it is
+ // really a sentinel, not a transition. See tz/zic.c.
++begin;
}
std::int_fast64_t unix_time = ToUnixSeconds(tp);
@@ -992,8 +923,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 some zoneinfo data as it is
- // really a sentinel, not a transition. See pre-2018f tz/zic.c.
+ // Do not report the BIG_BANG found in recent zoneinfo data as it is
+ // really a sentinel, not a transition. See tz/zic.c.
++begin;
}
std::int_fast64_t unix_time = ToUnixSeconds(tp);
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
index 2467ff559d..2a10c06c77 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_info.h
@@ -95,14 +95,15 @@ class TimeZoneInfo : public TimeZoneIf {
std::size_t DataLength(std::size_t time_len) const;
};
- bool GetTransitionType(std::int_fast32_t utc_offset, bool is_dst,
- const std::string& abbr, std::uint_least8_t* index);
+ void CheckTransition(const std::string& name, const TransitionType& tt,
+ std::int_fast32_t offset, bool is_dst,
+ const std::string& abbr) const;
bool EquivTransitions(std::uint_fast8_t tt1_index,
std::uint_fast8_t tt2_index) const;
- bool ExtendTransitions();
+ void ExtendTransitions(const std::string& name, const Header& hdr);
bool ResetToBuiltinUTC(const seconds& offset);
- bool Load(ZoneInfoSource* zip);
+ bool Load(const std::string& name, ZoneInfoSource* zip);
// Helpers for BreakTime() and MakeTime().
time_zone::absolute_lookup LocalTime(std::int_fast64_t unix_time,
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
index 887dd097c6..47cf84c663 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_libc.cc
@@ -27,12 +27,6 @@
#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 {
@@ -50,7 +44,7 @@ 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)
+#elif defined(__sun)
// Uses the globals: 'timezone', 'altzone' and 'tzname'.
auto tm_gmtoff(const std::tm& tm) -> decltype(timezone) {
const bool is_dst = tm.tm_isdst > 0;
@@ -159,8 +153,7 @@ 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;
- std::tm* tmp = local_time(&mid, &tm);
- if (tmp != nullptr) {
+ if (std::tm* tmp = local_time(&mid, &tm)) {
if (tm_gmtoff(*tmp) == offset) {
hi = mid;
} else {
@@ -170,8 +163,7 @@ 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) {
- tmp = local_time(&lo, &tm);
- if (tmp != nullptr) {
+ if (std::tm* tmp = local_time(&lo, &tm)) {
if (tm_gmtoff(*tmp) == offset) break;
}
}
@@ -231,10 +223,11 @@ 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};
}
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
index 898d04c125..efdea64b4e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup.cc
@@ -28,13 +28,6 @@
#include <vector>
#endif
-#if defined(__Fuchsia__)
-#include <fuchsia/intl/cpp/fidl.h>
-#include <lib/async-loop/cpp/loop.h>
-#include <lib/sys/cpp/component_context.h>
-#include <zircon/types.h>
-#endif
-
#include <cstdlib>
#include <cstring>
#include <string>
@@ -147,48 +140,6 @@ time_zone local_time_zone() {
}
CFRelease(tz_default);
#endif
-#if defined(__Fuchsia__)
- std::string primary_tz;
- [&]() {
- // Note: We can't use the synchronous FIDL API here because it doesn't
- // allow timeouts; if the FIDL call failed, local_time_zone() would never
- // return.
-
- const zx::duration kTimeout = zx::msec(500);
-
- // Don't attach to the thread because otherwise the thread's dispatcher
- // would be set to null when the loop is destroyed, causing any other FIDL
- // code running on the same thread to crash.
- async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
- std::unique_ptr<sys::ComponentContext> context =
- sys::ComponentContext::Create();
-
- fuchsia::intl::PropertyProviderHandle handle;
- zx_status_t status = context->svc()->Connect(handle.NewRequest());
- if (status != ZX_OK) {
- return;
- }
-
- fuchsia::intl::PropertyProviderPtr intl_provider;
- status = intl_provider.Bind(std::move(handle), loop.dispatcher());
- if (status != ZX_OK) {
- return;
- }
-
- intl_provider->GetProfile(
- [&loop, &primary_tz](fuchsia::intl::Profile profile) {
- if (!profile.time_zones().empty()) {
- primary_tz = profile.time_zones()[0].id;
- }
- loop.Quit();
- });
- loop.Run(zx::deadline_after(kTimeout));
- }();
-
- if (!primary_tz.empty()) {
- zone = primary_tz.c_str();
- }
-#endif
// Allow ${TZ} to override to default zone.
char* tz_env = nullptr;
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
index 0226ab71ab..99137a082a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -211,7 +211,6 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan",
"America/North_Dakota/Beulah",
"America/North_Dakota/Center",
"America/North_Dakota/New_Salem",
- "America/Nuuk",
"America/Ojinaga",
"America/Panama",
"America/Pangnirtung",
@@ -579,7 +578,6 @@ const char* const kTimeZoneNames[] = {"Africa/Abidjan",
"Pacific/Guam",
"Pacific/Honolulu",
"Pacific/Johnston",
- "Pacific/Kanton",
"Pacific/Kiritimati",
"Pacific/Kosrae",
"Pacific/Kwajalein",
@@ -718,18 +716,6 @@ TEST(TimeZones, LoadZonesConcurrently) {
}
#endif
-TEST(TimeZone, UTC) {
- const time_zone utc = utc_time_zone();
-
- time_zone loaded_utc;
- EXPECT_TRUE(load_time_zone("UTC", &loaded_utc));
- EXPECT_EQ(loaded_utc, utc);
-
- time_zone loaded_utc0;
- EXPECT_TRUE(load_time_zone("UTC0", &loaded_utc0));
- EXPECT_EQ(loaded_utc0, utc);
-}
-
TEST(TimeZone, NamedTimeZones) {
const time_zone utc = utc_time_zone();
EXPECT_EQ("UTC", utc.name());
@@ -763,7 +749,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 string timezone should fail.
+ // Loading an empty std::string timezone should fail.
tz = LoadZone("America/Los_Angeles");
EXPECT_FALSE(load_time_zone("", &tz));
EXPECT_EQ(chrono::system_clock::from_time_t(0),
@@ -946,7 +932,7 @@ TEST(MakeTime, Normalization) {
// NOTE: Run this with -ftrapv to detect overflow problems.
TEST(MakeTime, SysSecondsLimits) {
- const char RFC3339[] = "%Y-%m-%d%ET%H:%M:%S%Ez";
+ const char RFC3339[] = "%Y-%m-%dT%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));
@@ -1017,21 +1003,13 @@ 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 cut = LoadZone("libc:UTC");
+ const time_zone utc = 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), 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
+ 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));
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), cut);
-#if defined(__Fuchsia__)
- // Fuchsia's gmtime_r() fails on extreme negative values (fxbug.dev/78527).
-#else
- EXPECT_EQ("-2147481748-01-01T00:00:00+00:00", format(RFC3339, tp, cut));
-#endif
+ 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));
#endif
}
}
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h b/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
index 31e8598257..1ed55e0f95 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/tzfile.h
@@ -43,7 +43,7 @@
struct tzhead {
char tzh_magic[4]; /* TZ_MAGIC */
- char tzh_version[1]; /* '\0' or '2'-'4' as of 2021 */
+ 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 */
@@ -83,13 +83,13 @@ struct tzhead {
** 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 string for use in handling
+** then a POSIX-TZ-environment-variable-style std::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 string's hour offset may range from -167
+** First, the POSIX TZ std::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
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
index 5ab5a59ecf..98ea161267 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/zone_info_source.cc
@@ -65,7 +65,7 @@ ZoneInfoSourceFactory zone_info_source_factory __attribute__((weak)) =
extern ZoneInfoSourceFactory zone_info_source_factory;
extern ZoneInfoSourceFactory default_factory;
ZoneInfoSourceFactory default_factory = DefaultFactory;
-#if defined(_M_IX86) || defined(_M_ARM)
+#if defined(_M_IX86)
#pragma comment( \
linker, \
"/alternatename:?zone_info_source_factory@cctz_extension@time_internal@" ABSL_INTERNAL_MANGLED_NS \
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/version b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/version
index 8ee898ba7d..db18f8311d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/version
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/version
@@ -1 +1 @@
-2021e
+2019c
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Abidjan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
index 8906e88c81..697b9933eb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Accra
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Addis_Ababa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
index 56a4dd2a19..ae04342313 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Algiers
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmara
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Asmera
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bamako
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bangui
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Banjul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
index 0da1d1e211..82ea5aaf0c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bissau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Blantyre
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Brazzaville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Bujumbura
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
index ea38c97008..d3f819623f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Cairo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
index 0263c90bd0..245f4ebe18 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Casablanca
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
index a461dceaa2..850c8f06fa 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ceuta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Conakry
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dakar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Dar_es_Salaam
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Djibouti
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Douala
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
index 772e23c4cd..a91f65f242 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/El_Aaiun
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Freetown
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Gaborone
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Harare
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
index bada0638f8..b1c425dace 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Johannesburg
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
index 0aba9ffd89..625b1acccf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Juba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kampala
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
index 3f8e44b8a6..8ee8cb92e7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Khartoum
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kigali
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Kinshasa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lagos
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Libreville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lome
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Luanda
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lubumbashi
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Lusaka
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Malabo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
index 651e5cf67a..52753c0f87 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maputo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
index bada0638f8..b1c425dace 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Maseru
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
index bada0638f8..b1c425dace 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mbabane
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Mogadishu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
index 837780922f..6d688502a1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Monrovia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nairobi
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
index ecbc0966dc..a968845e29 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ndjamena
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Niamey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Nouakchott
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Ouagadougou
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
index 3d7a71ba0e..0c80137c74 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Porto-Novo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
index 425ad3fda7..59f3759c40 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Sao_Tome
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Timbuktu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
index e0c89971aa..07b393bb7d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tripoli
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
index ca324cb4cd..427fa56303 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Tunis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
index 0edc52b9b7..abecd137b1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Africa/Windhoek
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adak b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
index b1497bda63..43236498f6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Adak
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
index cdf0572be3..9bbb2fd3b3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anchorage
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Anguilla
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Antigua
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
index f66c9f79d6..49381b4108 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Araguaina
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
index d6f999b860..260f86a918 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Buenos_Aires
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
index 1dcc8d8543..0ae222a2f8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Catamarca
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
index 1dcc8d8543..0ae222a2f8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/ComodRivadavia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
index 35a52e53d1..da4c23a545 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Cordoba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
index b275f27c02..604b856636 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Jujuy
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
index 23fca12205..2218e36bfd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/La_Rioja
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
index 691c56978a..f9e677f171 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Mendoza
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
index 991d1fae69..c36587e1c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Rio_Gallegos
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
index 58863e0436..0e797f2215 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Salta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
index 7eba33c1c5..2698495bb3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Juan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
index 0a81cbddfa..fe50f6211c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/San_Luis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
index 10556d5d85..c954000ba9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Tucuman
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
index e031750276..3643628a24 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Argentina/Ushuaia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
index 47b4dc3416..f7ab6efcc0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Aruba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
index 6225036742..2f3bbda6d3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Asuncion
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
index 9154643f4c..629ed42319 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atikokan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atka b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
index b1497bda63..43236498f6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Atka
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
index 7969e30766..15808d30fb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
index cbe22a7622..896af3f56a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bahia_Banderas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
index 720c9863f2..9b90e306a6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Barbados
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belem b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
index e0d7653c64..60b5924dc1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belem
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belize b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
index bfc19f4e58..851051ae94 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Belize
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
index 47b4dc3416..f9f13a1679 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Blanc-Sablon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
index fca97207b2..978c33100f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boa_Vista
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
index 6cb53d4e61..b2647d7a83 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Bogota
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boise b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
index 72fec9e8c5..f8d54e2747 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Boise
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
index d6f999b860..260f86a918 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Buenos_Aires
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
index 0a2225244a..f8db4b6ebf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cambridge_Bay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
index 6855e4e9fe..81206247d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Campo_Grande
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
index 640b259fd0..f907f0a5ba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cancun
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
index 8dbe6ff741..eedf725e8d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Caracas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
index 1dcc8d8543..0ae222a2f8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Catamarca
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
index cd49f05344..e5bc06fdbe 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayenne
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
index 9154643f4c..9964b9a334 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cayman
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
index b016880653..a5b1617c7f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chicago
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
index e1780a5750..8ed5f93b02 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Chihuahua
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
index 9154643f4c..629ed42319 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Coral_Harbour
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
index 35a52e53d1..da4c23a545 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cordoba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
index 08f0128ee6..37cb85e4db 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Costa_Rica
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Creston b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
index c2bd2f949b..ca648573e4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Creston
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
index c09a87558d..9bea3d4079 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Cuiaba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
index 47b4dc3416..f7ab6efcc0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Curacao
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
index 8718efcce2..9549adcb65 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Danmarkshavn
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
index 07e4c5f4ac..db9ceadd96 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
index 761d1d9af5..db9e339655 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dawson_Creek
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denver b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
index 09e54e5c7c..5fbe26b1d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Denver
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
index 6eb3ac46ec..e104faa465 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Detroit
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Dominica
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
index 645ee94530..cd78a6f8be 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Edmonton
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
index 7da4b98fe3..39d6daeb9b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Eirunepe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
index 43484117e2..e2f22304aa 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/El_Salvador
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
index 19ccd3576d..ada6bf78b2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ensenada
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
index 2a49c6c50f..5a0b7f1ca0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Nelson
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
index 6b08d15bda..09511ccdcf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fort_Wayne
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
index 092e40d701..be57dc20b4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Fortaleza
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
index f85eb34157..48412a4cbf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Glace_Bay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
index 4ddc99d8b7..0160308bf6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Godthab
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
index 820e0dd2cd..a3f299079a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Goose_Bay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
index 9d90e745b0..b9bb063b62 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grand_Turk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Grenada
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guadeloupe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
index 8aa8e588e3..407138caf9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guatemala
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
index 381ae6c463..0559a7a4a4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guayaquil
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
index bcc66881c1..d5dab14969 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Guyana
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
index 9fa850a7d4..756099abe6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Halifax
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havana b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
index e06629d368..b69ac45107 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Havana
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
index 8283239eca..791a9fa2b3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Hermosillo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
index 6b08d15bda..09511ccdcf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Indianapolis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
index b187d5f8c7..fcd408d74d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Knox
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
index a730fe666b..1abf75e7e8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Marengo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
index 341a0235ef..0133548eca 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Petersburg
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
index 76e1f6285b..7bbb653cd7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Tell_City
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
index f2acf6cbbd..d236b7c077 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vevay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
index c255f89b6d..c818929d19 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Vincennes
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
index 8700ed9f06..630935c1e1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indiana/Winamac
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
index 6b08d15bda..09511ccdcf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Indianapolis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
index af3107db51..87bb355295 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Inuvik
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
index eb2c99cca5..c8138bdbb3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Iqaluit
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
index be6b1b6f1e..2a9b7fd52d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jamaica
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
index b275f27c02..604b856636 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Jujuy
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
index e347b369f7..451f349009 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Juneau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
index f2136d6ed4..177836e4fd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Louisville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
index d9f54a18bb..438e3eab4a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kentucky/Monticello
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
index b187d5f8c7..fcd408d74d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Knox_IN
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
index 47b4dc3416..f7ab6efcc0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Kralendijk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
index 68ddaae768..a101372435 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/La_Paz
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lima b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
index b643c5517f..3c6529b756 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lima
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
index aaf07787ad..9dad4f4c75 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Los_Angeles
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
index f2136d6ed4..177836e4fd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Louisville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
index 47b4dc3416..f7ab6efcc0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Lower_Princes
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
index dbb8d57d91..bc8b951d2e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Maceio
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managua b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
index 86ef76bf22..e0242bff6e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Managua
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
index 59c952ebc6..63d58f80f5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Manaus
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Marigot
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
index 25c0232d95..8df43dcf1c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Martinique
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
index 722751b20e..047968dfff 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Matamoros
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
index 4c819fab02..e4a785743d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mazatlan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
index 691c56978a..f9e677f171 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mendoza
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
index 28d2c56e1a..314613866d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Menominee
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Merida b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
index d3b0ca12c9..ea852da33a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Merida
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
index 9fefee388e..1e94be3d55 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Metlakatla
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
index ffcf8bee10..e7fb6f2953 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Mexico_City
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
index 3b62585d0a..b924b71004 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Miquelon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
index ecb69ef2c9..9df8d0f2ec 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Moncton
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
index dea9e3f586..a8928c8dc9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Monterrey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
index 4b2fb3e560..2f357bcf50 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montevideo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
index fe6be8ea8c..6752c5b052 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montreal
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Montserrat
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
index fe6be8ea8c..33cc6c6265 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nassau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_York b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
index 2b6c2eea14..2f75480e06 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/New_York
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
index b9f67a9f94..f6a856e693 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nipigon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nome b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
index 23ead1c004..10998df3bb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nome
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
index 9e74745ca7..f140726f2a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Noronha
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
index becf438330..246345dde7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Beulah
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
index d03bda045d..1fa0703778 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/Center
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
index ecefc15d8c..123f2aeecf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/North_Dakota/New_Salem
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
deleted file mode 100644
index 4ddc99d8b7..0000000000
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Nuuk
+++ /dev/null
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
index da0909cb21..fc4a03e369 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Ojinaga
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panama b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
index 9154643f4c..9964b9a334 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Panama
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
index 5be6f9b016..3e4e0db6ae 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Pangnirtung
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
index 24f925a2dd..bc8a6edf13 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Paramaribo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
index c2bd2f949b..ac6bb0c782 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Phoenix
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
index 3e75731baa..287f143926 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port-au-Prince
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Port_of_Spain
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
index fb5185ca60..a374cb43d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Acre
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
index 7f8047d939..2e873a5aa8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Porto_Velho
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
index 47b4dc3416..a662a57137 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Puerto_Rico
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
index 5c9a20b947..a5a8af52c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Punta_Arenas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
index d6ddda4822..ea66099155 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rainy_River
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
index 92e2ed2dbe..3a70587472 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rankin_Inlet
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recife b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
index 305abcb8a2..d7abb168a7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Recife
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Regina b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
index a3f8217a54..20c9c84df4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Regina
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
index a84d1dfdb3..0a73b753ba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Resolute
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
index fb5185ca60..a374cb43d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rio_Branco
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
index 35a52e53d1..da4c23a545 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Rosario
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
index 19ccd3576d..ada6bf78b2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santa_Isabel
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
index f81d144206..c28f36063b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santarem
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
index 8d6032264b..816a042818 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santiago
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
index 3e07850866..4fe36fd4c1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Santo_Domingo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
index a16da2c4d5..13ff083869 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sao_Paulo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
index 6db49124e2..e20e9e1c42 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Scoresbysund
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
index 09e54e5c7c..5fbe26b1d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Shiprock
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
index 36681ed78e..31f7061371 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Sitka
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Barthelemy
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
index e5f2aec2bb..65a5b0c720 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Johns
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Kitts
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Lucia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Thomas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/St_Vincent
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
index bdbb494487..8e9ef255ee 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Swift_Current
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
index 38036a3283..2adacb2e50 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tegucigalpa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thule b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
index f38dc56bf2..6f802f1c2a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thule
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
index fcb0328043..e504c9acf1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Thunder_Bay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
index 19ccd3576d..ada6bf78b2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tijuana
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
index fe6be8ea8c..6752c5b052 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Toronto
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Tortola
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
index c998491112..bb60cbced3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Vancouver
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
index 47b4dc3416..697cf5bcf7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Virgin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
index 878b6a92f7..fb3cd71a69 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Whitehorse
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
index 7e646d18e1..ac40299f6b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Winnipeg
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
index 773feba89d..da209f9f0a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yakutat
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
index c779cef92c..e6afa390e8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/America/Yellowknife
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
index 30315cc078..f100f47461 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Casey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
index 3ec32224f2..916f2c2592 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Davis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
index 5d8fc3a1b2..a71b39c004 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/DumontDUrville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
index 3fc1f231cb..616afd9c83 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Macquarie
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
index 05e4c6c586..b32e7fd6c6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Mawson
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
index afb3929318..6575fdce31 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/McMurdo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
index 32c1941634..3dd85f84ff 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Palmer
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
index ea49c00b22..8b2430a20e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Rothera
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
index afb3929318..6575fdce31 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/South_Pole
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
index 01c47ccb86..254af7d12f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Syowa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
index 4e31affb50..5e565da2f6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Troll
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
index 6e3290717e..728305305d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Antarctica/Vostok
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
index dfc509570a..15a34c3ced 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Arctic/Longyearbyen
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
index 01c47ccb86..2aea25f8c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aden
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
index 3ec4fc89fe..a4b0077900 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Almaty
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
index d97d308d7a..c9e8707912 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Amman
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
index 551884d322..6ed8b7cb07 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Anadyr
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
index 3a40d1175a..e2d0f91954 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
index 62c5840a83..06f0a13a66 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Aqtobe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
index 8482167269..73891af1ee 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashgabat
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
index 8482167269..73891af1ee 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ashkhabad
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
index cb2c82f657..8b5153e054 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Atyrau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
index a3ce975991..f7162edf93 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baghdad
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
index 7409d74983..63188b269d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bahrain
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
index 96203d7a42..a0de74b958 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Baku
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
index ed687d2985..c292ac5b5f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bangkok
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
index ff976dd3b2..759592a255 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Barnaul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
index 55dce5722c..fb266ede22 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Beirut
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
index fe7832cdf9..f6e20dd3a8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Bishkek
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
index e67b411b9f..3dab0abf4e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Brunei
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
index 00bc80a65e..0014046d29 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Calcutta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
index 9d49cd35cd..c4149c05ce 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chita
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
index 0a948c2eac..e48daa8243 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Choibalsan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
index d6b66984a2..3c0bef2061 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chongqing
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
index d6b66984a2..3c0bef2061 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Chungking
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
index 3eeb1b72b6..62c64d85df 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Colombo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
index 28136808b6..b11c928410 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dacca
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
index 168ef9baa4..d9104a7ab8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Damascus
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
index 28136808b6..b11c928410 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dhaka
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
index bb7be9f3a4..30943bbd0a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dili
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
index 58d75bc26e..fc0a589e2b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dubai
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
index d83fb076a2..82d85b8c1b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Dushanbe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
index cc44179564..653b146a60 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Famagusta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
index ccc57c9ce1..592b632606 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Gaza
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
index d6b66984a2..3c0bef2061 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Harbin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
index 906d8d5cba..ae82f9b546 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hebron
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
index 7ca9972502..e2934e371b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ho_Chi_Minh
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
index c80e364801..23d0375fba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hong_Kong
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
index 6e08a26127..4cb800a918 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Hovd
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
index 550e2a0877..4dcbbb7ea2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Irkutsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
index c891866873..508446bb6a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Istanbul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
index c9752d2f23..5baa3a8f2e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jakarta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
index 7c22f539d9..3002c82022 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jayapura
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
index 4c49bbf524..440ef06b5d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Jerusalem
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
index 660ce4cf69..d19b9bd51d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kabul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
index c65155402d..3e80b4e09f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kamchatka
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
index e56d5afdaf..ba65c0e8d3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Karachi
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
index 69ff7f6fb4..faa14d92d5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kashgar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
index 3a0d330ffd..a5d510753f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kathmandu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
index 3a0d330ffd..a5d510753f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Katmandu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
index aeb733202a..72bea64ba8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Khandyga
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
index 00bc80a65e..0014046d29 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kolkata
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
index e0d4fcb5c3..30c6f16505 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Krasnoyarsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
index e93dd5141b..612b01e71c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuala_Lumpur
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
index 59bc6e40b7..c86750cb7d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuching
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
index 01c47ccb86..2aea25f8c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Kuwait
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
index c22f75e42d..cac65063d0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macao
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
index c22f75e42d..cac65063d0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Macau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
index 16bac84446..b4fcac18e3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Magadan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
index 5990010b64..556ba86693 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Makassar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
index 3c3584e09a..f4f4b04efa 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Manila
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
index 58d75bc26e..fc0a589e2b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Muscat
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
index c210d0a598..f7f10ab766 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Nicosia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
index 9378d50539..d983276119 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novokuznetsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
index 65a9fa2cd2..e0ee5fcea9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Novosibirsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
index dc0ed422f6..b29b769311 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Omsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
index 25a63ec8b9..ad1f9ca1ca 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Oral
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
index ed687d2985..c292ac5b5f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Phnom_Penh
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
index 285bed2c63..12ce24cbea 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pontianak
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
index 57240cf89f..7ad7e0b2cf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Pyongyang
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
index 7409d74983..63188b269d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qatar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
index ff6fe61d50..73b9d963ef 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qostanay
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
index fe4d6c6d6d..c2fe4c144c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Qyzylorda
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
index 14b2ad09ea..dd77395b05 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Rangoon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
index 01c47ccb86..2aea25f8c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Riyadh
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
index 7ca9972502..e2934e371b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Saigon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
index 69f0faad1e..485459ce03 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Sakhalin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
index c43e27c5d4..030d47ce07 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Samarkand
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
index 1755147fab..96199e73e7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Seoul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
index d6b66984a2..3c0bef2061 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Shanghai
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
index 350d77e28e..2364b2178b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Singapore
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
index 7fdee5cbee..261a9832b3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Srednekolymsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
index 35d89d036d..24c43444b6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Taipei
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
index 65ee428ce1..32a9d7d0c9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tashkent
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
index 166e4341d6..b608d79748 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tbilisi
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
index f1555f0032..8cec5ad7de 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tehran
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
index 4c49bbf524..440ef06b5d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tel_Aviv
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
index 0edc72cfe4..fe409c7a2a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimbu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
index 0edc72cfe4..fe409c7a2a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Thimphu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
index 1aa066ce38..26f4d34d67 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tokyo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
index c3c307d7b9..670e2ad2ce 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Tomsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
index 5990010b64..556ba86693 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ujung_Pandang
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
index 6f5d3a15ab..2e20cc3a43 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulaanbaatar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
index 6f5d3a15ab..2e20cc3a43 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ulan_Bator
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
index 69ff7f6fb4..faa14d92d5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Urumqi
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
index c39331e3aa..9e4a78f6a5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Ust-Nera
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
index ed687d2985..c292ac5b5f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vientiane
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
index 72a3d4e87a..8ab253ce73 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Vladivostok
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
index 336f932e8d..c815e99b1a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yakutsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
index 14b2ad09ea..dd77395b05 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yangon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
index a3bf7f29b6..6958d7eddd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yekaterinburg
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
index 6dd927cb94..250bfe020a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Asia/Yerevan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
index e6e2616e98..56593dbfff 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Azores
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
index abc75ea7ef..419c660ba7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Bermuda
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
index 5ab3243a5f..f3192156ff 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Canary
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
index 8f7de1c0a1..e2a49d248d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Cape_Verde
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
index 9558bf7180..4dab7ef085 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faeroe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
index 9558bf7180..4dab7ef085 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Faroe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
index dfc509570a..15a34c3ced 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Jan_Mayen
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
index cf965c3f92..5213761f89 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Madeira
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
index 2451aca76d..10e0fc8190 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Reykjavik
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
index 7fa5f46835..4466608612 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/South_Georgia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
index 8906e88c81..28b32ab2e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/St_Helena
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
index 1a4c8ea863..88077f1107 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Atlantic/Stanley
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
index 1975a3a4bd..7636592aa7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/ACT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
index 3bfbbc563c..0b1252abb7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Adelaide
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
index dc9a980a65..3021bdb614 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Brisbane
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
index 947b50995f..1ac3fc8f52 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Broken_Hill
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
index 1975a3a4bd..7636592aa7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Canberra
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
index dc2ef554dc..f65a990efe 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Currie
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
index a6a67300dd..1cf502984a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Darwin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
index 9080f5cdb1..98ae557064 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Eucla
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
index dc2ef554dc..02b07ca232 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Hobart
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
index 4d4ec8ceea..9e04a80ece 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/LHI
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
index 131d77b54a..eab0fb998a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lindeman
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
index 4d4ec8ceea..9e04a80ece 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Lord_Howe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
index d3f195ac2f..ba457338ba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Melbourne
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
index 1975a3a4bd..7636592aa7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/NSW
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/North b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
index a6a67300dd..1cf502984a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/North
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
index 4f771828c9..a876b9e785 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Perth
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
index dc9a980a65..3021bdb614 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Queensland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/South b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
index 3bfbbc563c..0b1252abb7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/South
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
index 1975a3a4bd..7636592aa7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Sydney
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
index dc2ef554dc..02b07ca232 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Tasmania
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
index d3f195ac2f..ba457338ba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Victoria
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/West b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
index 4f771828c9..a876b9e785 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/West
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
index 947b50995f..1ac3fc8f52 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Australia/Yancowinna
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
index fb5185ca60..a374cb43d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/Acre
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
index 9e74745ca7..f140726f2a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/DeNoronha
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
index a16da2c4d5..13ff083869 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/East
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
index 59c952ebc6..63d58f80f5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Brazil/West
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CET b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CET
index 546748d6ea..122e934210 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CET
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CET
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
index d931558058..ca67929fbe 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/CST6CDT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
index 9fa850a7d4..756099abe6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Atlantic
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
index 7e646d18e1..ac40299f6b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Central
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
index fe6be8ea8c..6752c5b052 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Eastern
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
index 645ee94530..cd78a6f8be 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Mountain
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
index e5f2aec2bb..65a5b0c720 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Newfoundland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
index c998491112..bb60cbced3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Pacific
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
index a3f8217a54..20c9c84df4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Saskatchewan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
index 878b6a92f7..fb3cd71a69 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Canada/Yukon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
index 8d6032264b..816a042818 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/Continental
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
index d29bcd68b0..cae3744096 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Chile/EasterIsland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Cuba b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Cuba
index e06629d368..b69ac45107 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Cuba
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Cuba
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EET b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EET
index 378919ea11..cbdb71ddd3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EET
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EET
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST
index 3ae9691145..21ebc00b3f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
index 50c95e0cb0..9bce5007d4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/EST5EDT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Egypt b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Egypt
index ea38c97008..d3f819623f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Egypt
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Egypt
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Eire b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Eire
index 4a45ea8f73..1d994902db 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Eire
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Eire
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
index 98d5dcf917..4dab6f9005 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+1
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
index ecb287e667..c749290af2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+10
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
index e941412971..d969982309 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+11
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
index 9c95bd0736..cdeec90973 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+12
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
index 6d5ce3db73..fbd2a941fd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+2
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
index 5ef7be71fd..ee246ef56f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+3
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
index 75f16216f0..5a25ff2a6a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+4
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
index 589990ae89..c0b745f1cc 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+5
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
index fcb60ca246..06e777d57e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+6
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
index c0427a40ee..4e0b53a082 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+7
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
index 9bdc2283c0..714b0c5628 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+8
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
index ca7a81f656..78b9daa373 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT+9
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
index cb45601c95..a838bebf5e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-1
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
index 11d988e10a..68ff77db0d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-10
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
index f4c5d5cc29..66af5a42be 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-11
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
index cd397b02cd..17ba505772 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-12
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
index 8fad7c6b0b..5f3706ce64 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-13
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
index a595e60eea..7e9f9c465c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-14
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
index 97b44a9bae..fcef6d9acb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-2
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
index 4eb17ff005..27973bc857 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-3
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
index 13aef80cbb..1efd841261 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-4
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
index 83a2816955..1f761844fc 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-5
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
index 79a983e545..952681ed46 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-6
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
index e136690e16..cefc9126c6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-7
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
index bc70fe416f..afb093da00 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-8
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
index d18cedd524..9265fb7c20 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT-9
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/GMT0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Greenwich
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UCT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/UTC
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Universal
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Etc/Zulu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
index 4a6fa1d494..c3ff07b436 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Amsterdam
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
index 38685d4219..5962550392 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Andorra
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
index aff8d82d2a..73a4d013fc 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Astrakhan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
index 231bf9c3b7..9f3a0678d7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Athens
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belfast
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Belgrade
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
index 465546bd39..7f6d958f86 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Berlin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
index fb7c145ac4..ce8f433ece 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bratislava
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
index 31973271d2..40d7124e53 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Brussels
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
index efa689ba9e..4303b903e5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Bucharest
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
index 940be4670a..6b94a4f312 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Budapest
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
index 388df2969f..ad6cf59281 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Busingen
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
index 6970b14c50..5ee23fe0e5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Chisinau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
index 45984a7599..776be6e4a6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Copenhagen
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
index 4a45ea8f73..1d994902db 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Dublin
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
index 017bb2e347..117aadb836 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Gibraltar
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Guernsey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
index ff5e565305..b4f8f9cbb5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Helsinki
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Isle_of_Man
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
index c891866873..508446bb6a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Istanbul
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Jersey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
index 0ec4756470..cc99beabe4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kaliningrad
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
index 8f83cefbcc..9337c9ea27 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kiev
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
index d1c93c540c..a3b5320a0b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Kirov
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
index f0c70b6906..355817b52b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Lisbon
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ljubljana
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/London b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/London
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
index 682bcbf61a..c4ca733f53 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Luxembourg
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
index 60bdf4d07e..16f6420ab7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Madrid
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
index 27539c2243..bf2452da40 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Malta
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
index ff5e565305..b4f8f9cbb5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Mariehamn
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
index 30d3a672bf..453306c075 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Minsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
index f30dfc7014..686ae88315 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Monaco
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
index 5e6b6de645..ddb3f4e99a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Moscow
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
index c210d0a598..f7f10ab766 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Nicosia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
index dfc509570a..15a34c3ced 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Oslo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
index 00a27264c2..ca85435168 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Paris
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Podgorica
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
index fb7c145ac4..ce8f433ece 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Prague
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
index 26af4c90b3..8db477d017 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Riga
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
index 639ca3be40..ac4c16342b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Rome
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
index 8d0c26e5c8..97d5dd9e6e 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Samara
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
index 639ca3be40..ac4c16342b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/San_Marino
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sarajevo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
index 2684d8f8b8..8fd5f6d4b8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Saratov
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
index 88a6f3bdb4..432e8315bc 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Simferopol
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Skopje
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
index eabc972a22..0e4d879332 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Sofia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
index dd3eb32278..f3e0c7f0f2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Stockholm
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
index 5321bbd46e..b5acca3cf5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tallinn
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
index 743a7337ff..0b86017d24 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tirane
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
index 6970b14c50..5ee23fe0e5 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Tiraspol
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
index bb842cb1f5..7b61bdc522 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Ulyanovsk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
index a5755685e3..66ae8d69e3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Uzhgorod
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
index 388df2969f..ad6cf59281 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vaduz
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
index 639ca3be40..ac4c16342b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vatican
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
index 75339e98d0..3582bb15cd 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vienna
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
index 75b2eebb57..7abd63fa60 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Vilnius
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
index c517002604..d1cfac0e38 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Volgograd
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
index efe1a40f2a..e33cf67171 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Warsaw
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
index a1bf9281ed..27de456f16 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zagreb
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
index 4ea8dae45a..e42edfc850 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zaporozhye
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
index 388df2969f..ad6cf59281 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Europe/Zurich
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Factory b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Factory
index b4dd7735ed..60aa2a0d69 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Factory
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Factory
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
index 323cd3818a..ac02a81440 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GB-Eire
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT+0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT-0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0 b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/GMT0
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwich b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
index 157573b1d3..c63474664a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Greenwich
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/HST b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/HST
index 160a53e045..cccd45eb8c 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/HST
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/HST
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkong b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
index c80e364801..23d0375fba 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Hongkong
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iceland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iceland
index 2451aca76d..10e0fc8190 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iceland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iceland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Antananarivo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
index 8b8ce226b6..93d6dda50f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Chagos
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
index 766024b36c..d18c3810d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Christmas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
index 117503410c..f8116e7025 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Cocos
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Comoro
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
index 8ce93e0124..cde4cf7ea7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Kerguelen
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
index e7fccf8296..cba7dfe735 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mahe
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
index 58a82e4eb7..7c839cfa9b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Maldives
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
index 7c11134882..17f2616990 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mauritius
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
index 5f4ebcb7f9..9a2918f404 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Mayotte
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
index 248a7c93a5..dfe08313df 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Indian/Reunion
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran
index f1555f0032..8cec5ad7de 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Iran
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Israel b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Israel
index 4c49bbf524..440ef06b5d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Israel
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Israel
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaica b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
index be6b1b6f1e..2a9b7fd52d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Jamaica
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Japan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Japan
index 1aa066ce38..26f4d34d67 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Japan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Japan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
index 9416d522d0..1a7975fad7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Kwajalein
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Libya b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Libya
index e0c89971aa..07b393bb7d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Libya
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Libya
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MET b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MET
index 6f0558c3b6..4a826bb185 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MET
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MET
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST
index a0953d1e79..c93a58eee8 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
index 137867c8bf..4506a6e150 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/MST7MDT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
index 19ccd3576d..ada6bf78b2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaNorte
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
index 4c819fab02..e4a785743d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/BajaSur
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
index ffcf8bee10..e7fb6f2953 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Mexico/General
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ
index afb3929318..6575fdce31 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
index f06065ebd1..c004109882 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/NZ-CHAT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajo
index 09e54e5c7c..5fbe26b1d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Navajo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PRC b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PRC
index d6b66984a2..3c0bef2061 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PRC
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PRC
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
index fde4833f6b..99d246baa3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/PST8PDT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
index a6b835aab4..dab1f3f602 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Apia
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
index afb3929318..6575fdce31 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Auckland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
index 7c667093c5..2892d26809 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Bougainville
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
index f06065ebd1..c004109882 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chatham
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
index ea3fb5cd3c..07c84b7110 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Chuuk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
index d29bcd68b0..cae3744096 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Easter
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
index bf7471dd3f..60150175c0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Efate
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
index 2b6a06088e..f0b8252362 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Enderbury
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
index b7b30213e1..e40307f6aa 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fakaofo
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
index 8b2dd52b17..d39bf53645 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Fiji
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
index 78ab35b6b0..ea728637ac 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Funafuti
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
index a9403eca46..31f0921ea0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Galapagos
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
index ddfc34ffc0..e1fc3daa55 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Gambier
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
index 720c679017..7e9d10a100 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guadalcanal
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
index bf9a2d955f..66490d25df 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Guam
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
index 40e3d492e6..c7cd060159 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Honolulu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
index 40e3d492e6..c7cd060159 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Johnston
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kanton b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kanton
deleted file mode 100644
index 2b6a06088e..0000000000
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kanton
+++ /dev/null
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
index 2f676d3bf5..7cae0cb756 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kiritimati
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
index f5d58242c8..a584aae5eb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kosrae
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
index 9416d522d0..1a7975fad7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Kwajalein
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
index 9228ee02ed..9ef8374de4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Majuro
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
index 6ea24b72cd..74d6792bf6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Marquesas
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
index 001289ceec..cb56709a77 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Midway
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
index ae13aac779..acec0429f1 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Nauru
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
index be874e2472..684b010e8b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Niue
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
index 79e2a9419a..53c1aad4e0 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Norfolk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
index 824f814160..931a1a306f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Noumea
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
index 001289ceec..cb56709a77 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pago_Pago
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
index bc8eb7a55b..146b35152a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Palau
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
index 8a4ba4d30a..ef91b061bb 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pitcairn
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
index b92b254a9a..c298ddd4de 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Pohnpei
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
index b92b254a9a..c298ddd4de 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Ponape
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
index 5d8fc3a1b2..920ad27e62 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Port_Moresby
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
index 7220bda0ad..da6b0fadea 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Rarotonga
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
index bf9a2d955f..66490d25df 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Saipan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
index 001289ceec..cb56709a77 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Samoa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
index 50a064fa01..442b8eb5a4 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tahiti
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
index 6bc216823e..3db6c75033 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tarawa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
index f28c840184..5553c6009a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Tongatapu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
index ea3fb5cd3c..07c84b7110 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Truk
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
index 71cca8877d..c9e310670f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wake
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
index 4bce893003..b35344b312 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Wallis
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
index ea3fb5cd3c..07c84b7110 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Pacific/Yap
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Poland b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Poland
index efe1a40f2a..e33cf67171 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Poland
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Poland
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugal b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugal
index f0c70b6906..355817b52b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugal
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Portugal
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROC b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROC
index 35d89d036d..24c43444b6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROC
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROC
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROK b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROK
index 1755147fab..96199e73e7 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROK
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/ROK
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Singapore b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Singapore
index 350d77e28e..2364b2178b 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Singapore
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Singapore
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkey b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkey
index c891866873..508446bb6a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkey
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Turkey
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UCT b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UCT
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UCT
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UCT
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
index cdf0572be3..9bbb2fd3b3 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Alaska
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
index b1497bda63..43236498f6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Aleutian
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
index c2bd2f949b..ac6bb0c782 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Arizona
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Central b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Central
index b016880653..a5b1617c7f 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Central
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Central
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
index 6b08d15bda..09511ccdcf 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/East-Indiana
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
index 2b6c2eea14..2f75480e06 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Eastern
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
index 40e3d492e6..c7cd060159 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Hawaii
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
index b187d5f8c7..fcd408d74d 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Indiana-Starke
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
index 6eb3ac46ec..e104faa465 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Michigan
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
index 09e54e5c7c..5fbe26b1d9 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Mountain
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
index aaf07787ad..9dad4f4c75 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Pacific
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
index 001289ceec..cb56709a77 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/US/Samoa
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UTC b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UTC
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UTC
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/UTC
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Universal b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Universal
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Universal
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Universal
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SU b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SU
index 5e6b6de645..ddb3f4e99a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SU
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/W-SU
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/WET b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/WET
index 423c6c203a..c27390b5b6 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/WET
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/WET
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulu b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulu
index 00841a6221..91558be0c2 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulu
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/Zulu
Binary files differ
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
index c614be81f4..822ffa1f1a 100644
--- a/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
+++ b/third_party/abseil-cpp/absl/time/internal/cctz/testdata/zoneinfo/zone1970.tab
@@ -40,9 +40,11 @@ AL +4120+01950 Europe/Tirane
AM +4011+04430 Asia/Yerevan
AQ -6617+11031 Antarctica/Casey Casey
AQ -6835+07758 Antarctica/Davis Davis
+AQ -6640+14001 Antarctica/DumontDUrville Dumont-d'Urville
AQ -6736+06253 Antarctica/Mawson Mawson
AQ -6448-06406 Antarctica/Palmer Palmer
AQ -6734-06808 Antarctica/Rothera Rothera
+AQ -690022+0393524 Antarctica/Syowa Syowa
AQ -720041+0023206 Antarctica/Troll Troll
AQ -7824+10654 Antarctica/Vostok Vostok
AR -3436-05827 America/Argentina/Buenos_Aires Buenos Aires (BA, CF)
@@ -61,7 +63,8 @@ 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
+AU -4253+14719 Australia/Hobart Tasmania (most areas)
+AU -3956+14352 Australia/Currie Tasmania (King Island)
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)
@@ -95,6 +98,7 @@ BR +0249-06040 America/Boa_Vista Roraima
BR -0308-06001 America/Manaus Amazonas (east)
BR -0640-06952 America/Eirunepe Amazonas (west)
BR -0958-06748 America/Rio_Branco Acre
+BS +2505-07721 America/Nassau
BT +2728+08939 Asia/Thimphu
BY +5354+02734 Europe/Minsk
BZ +1730-08812 America/Belize
@@ -103,11 +107,13 @@ CA +4439-06336 America/Halifax Atlantic - NS (most areas); PE
CA +4612-05957 America/Glace_Bay Atlantic - NS (Cape Breton)
CA +4606-06447 America/Moncton Atlantic - New Brunswick
CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas)
-CA,BS +4339-07923 America/Toronto Eastern - ON, QC (most areas), Bahamas
+CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore)
+CA +4339-07923 America/Toronto Eastern - ON, QC (most areas)
CA +4901-08816 America/Nipigon Eastern - ON, QC (no DST 1967-73)
CA +4823-08915 America/Thunder_Bay Eastern - ON (Thunder Bay)
CA +6344-06828 America/Iqaluit Eastern - NU (most east areas)
CA +6608-06544 America/Pangnirtung Eastern - NU (Pangnirtung)
+CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H)
CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba
CA +4843-09434 America/Rainy_River Central - ON (Rainy R, Ft Frances)
CA +744144-0944945 America/Resolute Central - NU (Resolute)
@@ -118,14 +124,15 @@ CA +5333-11328 America/Edmonton Mountain - AB; BC (E); SK (W)
CA +690650-1050310 America/Cambridge_Bay Mountain - NU (west)
CA +6227-11421 America/Yellowknife Mountain - NT (central)
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,GH,GM,GN,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
+CI,BF,GM,GN,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
CK -2114-15946 Pacific/Rarotonga
CL -3327-07040 America/Santiago Chile (most areas)
CL -5309-07055 America/Punta_Arenas Region of Magallanes
@@ -136,6 +143,7 @@ CO +0436-07405 America/Bogota
CR +0956-08405 America/Costa_Rica
CU +2308-08222 America/Havana
CV +1455-02331 Atlantic/Cape_Verde
+CW,AW,BQ,SX +1211-06900 America/Curacao
CX -1025+10543 Indian/Christmas
CY +3510+03322 Asia/Nicosia Cyprus (most areas)
CY +3507+03357 Asia/Famagusta Northern Cyprus
@@ -163,8 +171,9 @@ FR +4852+00220 Europe/Paris
GB,GG,IM,JE +513030-0000731 Europe/London
GE +4143+04449 Asia/Tbilisi
GF +0456-05220 America/Cayenne
+GH +0533-00013 Africa/Accra
GI +3608-00521 Europe/Gibraltar
-GL +6411-05144 America/Nuuk Greenland (most areas)
+GL +6411-05144 America/Godthab 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
@@ -196,7 +205,7 @@ JP +353916+1394441 Asia/Tokyo
KE,DJ,ER,ET,KM,MG,SO,TZ,UG,YT -0117+03649 Africa/Nairobi
KG +4254+07436 Asia/Bishkek
KI +0125+17300 Pacific/Tarawa Gilbert Islands
-KI -0247-17143 Pacific/Kanton Phoenix Islands
+KI -0308-17105 Pacific/Enderbury Phoenix Islands
KI +0152-15720 Pacific/Kiritimati Line Islands
KP +3901+12545 Asia/Pyongyang
KR +3733+12658 Asia/Seoul
@@ -254,19 +263,19 @@ NR -0031+16655 Pacific/Nauru
NU -1901-16955 Pacific/Niue
NZ,AQ -3652+17446 Pacific/Auckland New Zealand time
NZ -4357-17633 Pacific/Chatham Chatham Islands
-PA,CA,KY +0858-07932 America/Panama EST - Panama, Cayman, ON (Atikokan), NU (Coral H)
+PA,KY +0858-07932 America/Panama
PE -1203-07703 America/Lima
PF -1732-14934 Pacific/Tahiti Society Islands
PF -0900-13930 Pacific/Marquesas Marquesas Islands
PF -2308-13457 Pacific/Gambier Gambier Islands
-PG,AQ -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas), Dumont d'Urville
+PG -0930+14710 Pacific/Port_Moresby Papua New Guinea (most areas)
PG -0613+15534 Pacific/Bougainville Bougainville
PH +1435+12100 Asia/Manila
PK +2452+06703 Asia/Karachi
PL +5215+02100 Europe/Warsaw
PM +4703-05620 America/Miquelon
PN -2504-13005 Pacific/Pitcairn
-PR,AG,CA,AI,AW,BL,BQ,CW,DM,GD,GP,KN,LC,MF,MS,SX,TT,VC,VG,VI +182806-0660622 America/Puerto_Rico AST
+PR +182806-0660622 America/Puerto_Rico
PS +3130+03428 Asia/Gaza Gaza Strip
PS +313200+0350542 Asia/Hebron West Bank
PT +3843-00908 Europe/Lisbon Portugal (mainland)
@@ -281,10 +290,10 @@ 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
# Mention RU and UA alphabetically. See "territorial claims" above.
-RU,UA +4457+03406 Europe/Simferopol Crimea
+RU,UA +4457+03406 Europe/Simferopol MSK+00 - 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
@@ -306,12 +315,12 @@ RU +4658+14242 Asia/Sakhalin MSK+08 - Sakhalin Island
RU +6728+15343 Asia/Srednekolymsk MSK+08 - Sakha (E); North Kuril Is
RU +5301+15839 Asia/Kamchatka MSK+09 - Kamchatka
RU +6445+17729 Asia/Anadyr MSK+09 - Bering Sea
-SA,AQ,KW,YE +2438+04643 Asia/Riyadh Arabia, Syowa
+SA,KW,YE +2438+04643 Asia/Riyadh
SB -0932+16012 Pacific/Guadalcanal
SC -0440+05528 Indian/Mahe
SD +1536+03232 Africa/Khartoum
SE +5920+01803 Europe/Stockholm
-SG,MY +0117+10351 Asia/Singapore Singapore, peninsular Malaysia
+SG +0117+10351 Asia/Singapore
SR +0550-05510 America/Paramaribo
SS +0451+03137 Africa/Juba
ST +0020+00644 Africa/Sao_Tome
@@ -326,13 +335,14 @@ TK -0922-17114 Pacific/Fakaofo
TL -0833+12535 Asia/Dili
TM +3757+05823 Asia/Ashgabat
TN +3648+01011 Africa/Tunis
-TO -210800-1751200 Pacific/Tongatapu
+TO -2110-17510 Pacific/Tongatapu
TR +4101+02858 Europe/Istanbul
+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 Transcarpathia
-UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk
+UA +4837+02218 Europe/Uzhgorod Ruthenia
+UA +4750+03510 Europe/Zaporozhye Zaporozh'ye/Zaporizhia; Lugansk/Luhansk (east)
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)
@@ -353,7 +363,7 @@ US +465042-1012439 America/North_Dakota/New_Salem Central - ND (Morton rural)
US +471551-1014640 America/North_Dakota/Beulah Central - ND (Mercer)
US +394421-1045903 America/Denver Mountain (most areas)
US +433649-1161209 America/Boise Mountain - ID (south); OR (east)
-US,CA +332654-1120424 America/Phoenix MST - Arizona (except Navajo), Creston BC
+US +332654-1120424 America/Phoenix MST - Arizona (except Navajo)
US +340308-1181434 America/Los_Angeles Pacific
US +611305-1495401 America/Anchorage Alaska (most areas)
US +581807-1342511 America/Juneau Alaska - Juneau area
diff --git a/third_party/abseil-cpp/absl/time/internal/test_util.cc b/third_party/abseil-cpp/absl/time/internal/test_util.cc
index 9a485a0750..9bffe121da 100644
--- a/third_party/abseil-cpp/absl/time/internal/test_util.cc
+++ b/third_party/abseil-cpp/absl/time/internal/test_util.cc
@@ -18,7 +18,6 @@
#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"
diff --git a/third_party/abseil-cpp/absl/time/time.cc b/third_party/abseil-cpp/absl/time/time.cc
index 1ec2026e25..6bb36cb3e7 100644
--- a/third_party/abseil-cpp/absl/time/time.cc
+++ b/third_party/abseil-cpp/absl/time/time.cc
@@ -60,10 +60,9 @@ 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() {
diff --git a/third_party/abseil-cpp/absl/time/time.h b/third_party/abseil-cpp/absl/time/time.h
index 5abd815a79..33a4a630c2 100644
--- a/third_party/abseil-cpp/absl/time/time.h
+++ b/third_party/abseil-cpp/absl/time/time.h
@@ -182,29 +182,18 @@ class Duration {
// Overloads that forward to either the int64_t or double overloads above.
// Integer operands must be representable as int64_t.
- template <typename T, time_internal::EnableIfIntegral<T> = 0>
+ template <typename T>
Duration& operator*=(T r) {
int64_t x = r;
return *this *= x;
}
-
- template <typename T, time_internal::EnableIfIntegral<T> = 0>
+ template <typename T>
Duration& operator/=(T r) {
int64_t x = r;
return *this /= x;
}
-
- template <typename T, time_internal::EnableIfFloat<T> = 0>
- Duration& operator*=(T r) {
- double x = r;
- return *this *= x;
- }
-
- template <typename T, time_internal::EnableIfFloat<T> = 0>
- Duration& operator/=(T r) {
- double x = r;
- return *this /= x;
- }
+ Duration& operator*=(float r) { return *this *= static_cast<double>(r); }
+ Duration& operator/=(float r) { return *this /= static_cast<double>(r); }
template <typename H>
friend H AbslHashValue(H h, Duration d) {
@@ -403,30 +392,12 @@ constexpr Duration InfiniteDuration();
//
// absl::Duration a = absl::Seconds(60);
// absl::Duration b = absl::Minutes(1); // b == a
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Nanoseconds(T n) {
- return time_internal::FromInt64(n, std::nano{});
-}
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Microseconds(T n) {
- return time_internal::FromInt64(n, std::micro{});
-}
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Milliseconds(T n) {
- return time_internal::FromInt64(n, std::milli{});
-}
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Seconds(T n) {
- return time_internal::FromInt64(n, std::ratio<1>{});
-}
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Minutes(T n) {
- return time_internal::FromInt64(n, std::ratio<60>{});
-}
-template <typename T, time_internal::EnableIfIntegral<T> = 0>
-constexpr Duration Hours(T n) {
- return time_internal::FromInt64(n, std::ratio<3600>{});
-}
+constexpr Duration Nanoseconds(int64_t n);
+constexpr Duration Microseconds(int64_t n);
+constexpr Duration Milliseconds(int64_t n);
+constexpr Duration Seconds(int64_t n);
+constexpr Duration Minutes(int64_t n);
+constexpr Duration Hours(int64_t n);
// Factory overloads for constructing `Duration` values from a floating-point
// number of the unit indicated by the factory function's name. These functions
@@ -480,20 +451,19 @@ Duration Hours(T n) {
// ToInt64Hours()
//
// Helper functions that convert a Duration to an integral count of the
-// indicated unit. These return the same results as the `IDivDuration()`
-// function, though they usually do so more efficiently; see the
-// documentation of `IDivDuration()` for details about overflow, etc.
+// indicated unit. These functions are shorthand for the `IDivDuration()`
+// function above; see its documentation for details about overflow, etc.
//
// Example:
//
// absl::Duration d = absl::Milliseconds(1500);
// int64_t isec = absl::ToInt64Seconds(d); // isec == 1
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Nanoseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Microseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Milliseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Seconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Minutes(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d);
+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);
// ToDoubleNanoSeconds()
// ToDoubleMicroseconds()
@@ -510,12 +480,12 @@ ABSL_ATTRIBUTE_PURE_FUNCTION int64_t ToInt64Hours(Duration d);
//
// absl::Duration d = absl::Milliseconds(1500);
// double dsec = absl::ToDoubleSeconds(d); // dsec == 1.5
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleNanoseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMicroseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMilliseconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleSeconds(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleMinutes(Duration d);
-ABSL_ATTRIBUTE_PURE_FUNCTION double ToDoubleHours(Duration d);
+double ToDoubleNanoseconds(Duration d);
+double ToDoubleMicroseconds(Duration d);
+double ToDoubleMilliseconds(Duration d);
+double ToDoubleSeconds(Duration d);
+double ToDoubleMinutes(Duration d);
+double ToDoubleHours(Duration d);
// FromChrono()
//
@@ -575,22 +545,12 @@ 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(absl::string_view dur_string, Duration* d);
+bool ParseDuration(const std::string& dur_string, Duration* d);
-// AbslParseFlag()
-//
-// Parses a command-line flag string representation `text` into a a Duration
-// value. Duration flags must be specified in a format that is valid input for
-// `absl::ParseDuration()`.
+// 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);
-
-
-// AbslUnparseFlag()
-//
-// Unparses a Duration value into a command-line string representation using
-// the format specified by `absl::ParseDuration()`.
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.")
@@ -679,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]
@@ -853,12 +813,8 @@ Time FromChrono(const std::chrono::system_clock::time_point& tp);
// // tp == std::chrono::system_clock::from_time_t(123);
std::chrono::system_clock::time_point ToChronoTime(Time);
-// AbslParseFlag()
-//
-// Parses the command-line flag string representation `text` into a Time value.
-// Time flags must be specified in a format that matches absl::RFC3339_full.
-//
-// For example:
+// Support for flag values of type Time. Time flags must be specified in a
+// format that matches absl::RFC3339_full. For example:
//
// --start_time=2016-01-02T03:04:05.678+08:00
//
@@ -868,13 +824,7 @@ std::chrono::system_clock::time_point ToChronoTime(Time);
// 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);
-
-// AbslUnparseFlag()
-//
-// Unparses a Time value into a command-line string representation using
-// the format specified by `absl::ParseTime()`.
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.")
@@ -1071,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(absl::string_view name, TimeZone* tz) {
+inline bool LoadTimeZone(const std::string& 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(std::string(name), &cz);
+ const bool b = time_internal::cctz::load_time_zone(name, &cz);
*tz = TimeZone(cz);
return b;
}
@@ -1230,15 +1180,11 @@ 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 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.
+// 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).
Time FromTM(const struct tm& tm, TimeZone tz);
// ToTM()
@@ -1257,15 +1203,18 @@ 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.
-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
+ABSL_DLL extern const char
+ RFC3339_full[]; // %Y-%m-%dT%H:%M:%E*S%Ez
+ABSL_DLL extern const char RFC3339_sec[]; // %Y-%m-%dT%H:%M:%S%Ez
// RFC1123_full
// RFC1123_no_wday
//
// FormatTime()/ParseTime() format specifiers for RFC1123 date/time strings.
-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
+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()
//
@@ -1280,7 +1229,6 @@ ABSL_DLL 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'.
@@ -1304,7 +1252,7 @@ ABSL_DLL extern const char RFC1123_no_wday[]; // %d %b %E4Y %H:%M:%S %z
// `absl::InfinitePast()`, the returned string will be exactly "infinite-past".
// In both cases the given format string and `absl::TimeZone` are ignored.
//
-std::string FormatTime(absl::string_view format, Time t, TimeZone tz);
+std::string FormatTime(const std::string& 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
@@ -1323,8 +1271,7 @@ 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, which (along with %z) includes
-// 'z' and 'Z' as synonyms for +00:00. %ET accepts either 'T' or 't'.
+// and %E*z also accept the same inputs.
//
// %Y consumes as many numeric characters as it can, so the matching data
// should always be terminated with a non-numeric. %E4Y always consumes
@@ -1366,7 +1313,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(absl::string_view format, absl::string_view input, Time* time,
+bool ParseTime(const std::string& format, const std::string& input, Time* time,
std::string* err);
// Like ParseTime() above, but if the format string does not contain a UTC
@@ -1376,7 +1323,7 @@ bool ParseTime(absl::string_view format, absl::string_view 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(absl::string_view format, absl::string_view input, TimeZone tz,
+bool ParseTime(const std::string& format, const std::string& input, TimeZone tz,
Time* time, std::string* err);
// ============================================================================
@@ -1401,8 +1348,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>(
- std::round((n - static_cast<double>(int_secs)) * kTicksPerSecond));
+ const uint32_t ticks =
+ static_cast<uint32_t>((n - int_secs) * kTicksPerSecond + 0.5);
return ticks < kTicksPerSecond
? MakeDuration(int_secs, ticks)
: MakeDuration(int_secs + 1, ticks - kTicksPerSecond);
@@ -1526,13 +1473,34 @@ T ToChronoDuration(Duration d) {
} // namespace time_internal
+constexpr Duration Nanoseconds(int64_t n) {
+ return time_internal::FromInt64(n, std::nano{});
+}
+constexpr Duration Microseconds(int64_t n) {
+ return time_internal::FromInt64(n, std::micro{});
+}
+constexpr Duration Milliseconds(int64_t n) {
+ return time_internal::FromInt64(n, std::milli{});
+}
+constexpr Duration Seconds(int64_t n) {
+ return time_internal::FromInt64(n, std::ratio<1>{});
+}
+constexpr Duration Minutes(int64_t n) {
+ return time_internal::FromInt64(n, std::ratio<60>{});
+}
+constexpr Duration Hours(int64_t n) {
+ return time_internal::FromInt64(n, std::ratio<3600>{});
+}
+
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) {
diff --git a/third_party/abseil-cpp/absl/time/time_test.cc b/third_party/abseil-cpp/absl/time/time_test.cc
index cde9423feb..6f89672c66 100644
--- a/third_party/abseil-cpp/absl/time/time_test.cc
+++ b/third_party/abseil-cpp/absl/time/time_test.cc
@@ -58,7 +58,8 @@ 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;
@@ -68,7 +69,8 @@ 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;
@@ -101,7 +103,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);
@@ -226,9 +228,6 @@ 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) {
@@ -359,21 +358,19 @@ 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) {
@@ -1048,15 +1045,15 @@ 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(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(ci.cs));
EXPECT_EQ(1, absl::GetYearDay(ci.cs));
@@ -1070,8 +1067,7 @@ 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);
@@ -1079,8 +1075,7 @@ 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);
@@ -1094,8 +1089,7 @@ 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);
@@ -1104,8 +1098,7 @@ 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);
@@ -1178,13 +1171,14 @@ 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/third_party/abseil-cpp/absl/time/time_zone_test.cc b/third_party/abseil-cpp/absl/time/time_zone_test.cc
index 229fcfccb0..8f1e74aca5 100644
--- a/third_party/abseil-cpp/absl/time/time_zone_test.cc
+++ b/third_party/abseil-cpp/absl/time/time_zone_test.cc
@@ -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 string timezone should fail.
+ // Loading an empty std::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/third_party/abseil-cpp/absl/types/BUILD.bazel b/third_party/abseil-cpp/absl/types/BUILD.bazel
index 38ed228679..f2ea9f395a 100644
--- a/third_party/abseil-cpp/absl/types/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/types/BUILD.bazel
@@ -12,7 +12,9 @@
# WITHOUT 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",
@@ -22,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "any",
@@ -33,7 +35,6 @@ cc_library(
":bad_any_cast",
"//absl/base:config",
"//absl/base:core_headers",
- "//absl/base:fast_type_id",
"//absl/meta:type_traits",
"//absl/utility",
],
@@ -214,15 +215,11 @@ cc_library(
"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/debugging:demangle_internal",
"//absl/meta:type_traits",
"//absl/strings",
"//absl/utility",
diff --git a/third_party/abseil-cpp/absl/types/CMakeLists.txt b/third_party/abseil-cpp/absl/types/CMakeLists.txt
index d7e8614e0d..c7c882507f 100644
--- a/third_party/abseil-cpp/absl/types/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/types/CMakeLists.txt
@@ -24,7 +24,6 @@ absl_cc_library(
absl::bad_any_cast
absl::config
absl::core_headers
- absl::fast_type_id
absl::type_traits
absl::utility
PUBLIC
@@ -69,7 +68,7 @@ absl_cc_test(
absl::exception_testing
absl::raw_logging_internal
absl::test_instance_tracker
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -85,7 +84,7 @@ absl_cc_test(
absl::exception_testing
absl::raw_logging_internal
absl::test_instance_tracker
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -99,7 +98,7 @@ absl_cc_test(
absl::any
absl::config
absl::exception_safety_testing
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -136,7 +135,7 @@ absl_cc_test(
absl::inlined_vector
absl::hash_testing
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -156,7 +155,7 @@ absl_cc_test(
absl::inlined_vector
absl::hash_testing
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -222,7 +221,7 @@ absl_cc_test(
absl::raw_logging_internal
absl::strings
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -236,7 +235,7 @@ absl_cc_test(
absl::optional
absl::config
absl::exception_safety_testing
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -246,20 +245,15 @@ absl_cc_library(
"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_DEFAULT_COPTS}
DEPS
- absl::algorithm
absl::debugging
absl::type_traits
absl::strings
absl::utility
- GTest::gmock_main
- TESTONLY
+ gmock_main
+ PUBLIC
)
absl_cc_test(
@@ -275,7 +269,7 @@ absl_cc_test(
DEPS
absl::conformance_testing
absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_test(
@@ -287,8 +281,7 @@ absl_cc_test(
${ABSL_TEST_COPTS}
DEPS
absl::conformance_testing
- absl::type_traits
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -324,7 +317,7 @@ absl_cc_test(
absl::memory
absl::type_traits
absl::strings
- GTest::gmock_main
+ gmock_main
)
absl_cc_library(
@@ -350,9 +343,12 @@ absl_cc_test(
DEPS
absl::base
absl::compare
- GTest::gmock_main
+ gmock_main
)
+# TODO(cohenjon,zhangxy) Figure out why this test is failing on gcc 4.8
+if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
+else()
absl_cc_test(
NAME
variant_exception_safety_test
@@ -365,5 +361,6 @@ absl_cc_test(
absl::config
absl::exception_safety_testing
absl::memory
- GTest::gmock_main
+ gmock_main
)
+endif()
diff --git a/third_party/abseil-cpp/absl/types/any.h b/third_party/abseil-cpp/absl/types/any.h
index fc5a07469f..16bda79cc7 100644
--- a/third_party/abseil-cpp/absl/types/any.h
+++ b/third_party/abseil-cpp/absl/types/any.h
@@ -47,9 +47,9 @@
// this abstraction, make sure that you should not instead be rewriting your
// code to be more specific.
//
-// Abseil has also released an `absl::variant` type (a C++11 compatible version
-// of the C++17 `std::variant`), which is generally preferred for use over
-// `absl::any`.
+// 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`.
#ifndef ABSL_TYPES_ANY_H_
#define ABSL_TYPES_ANY_H_
@@ -80,7 +80,6 @@ ABSL_NAMESPACE_END
#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"
@@ -96,6 +95,26 @@ ABSL_NAMESPACE_END
namespace absl {
ABSL_NAMESPACE_BEGIN
+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
+
class any;
// swap()
@@ -404,11 +423,11 @@ class any {
using NormalizedType =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
- return base_internal::FastTypeId<NormalizedType>();
+ return any_internal::FastTypeId<NormalizedType>();
}
const void* GetObjTypeId() const {
- return obj_ ? obj_->ObjTypeId() : base_internal::FastTypeId<void>();
+ return obj_ ? obj_->ObjTypeId() : any_internal::FastTypeId<void>();
}
// `absl::any` nonmember functions //
diff --git a/third_party/abseil-cpp/absl/types/bad_optional_access.h b/third_party/abseil-cpp/absl/types/bad_optional_access.h
index 049e72ad9a..a500286adc 100644
--- a/third_party/abseil-cpp/absl/types/bad_optional_access.h
+++ b/third_party/abseil-cpp/absl/types/bad_optional_access.h
@@ -67,7 +67,7 @@ class bad_optional_access : public std::exception {
namespace optional_internal {
// throw delegator
-[[noreturn]] ABSL_DLL void throw_bad_optional_access();
+[[noreturn]] void throw_bad_optional_access();
} // namespace optional_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/types/bad_variant_access.h b/third_party/abseil-cpp/absl/types/bad_variant_access.h
index 8ab215e97d..095969f91e 100644
--- a/third_party/abseil-cpp/absl/types/bad_variant_access.h
+++ b/third_party/abseil-cpp/absl/types/bad_variant_access.h
@@ -70,8 +70,8 @@ class bad_variant_access : public std::exception {
namespace variant_internal {
-[[noreturn]] ABSL_DLL void ThrowBadVariantAccess();
-[[noreturn]] ABSL_DLL void Rethrow();
+[[noreturn]] void ThrowBadVariantAccess();
+[[noreturn]] void Rethrow();
} // namespace variant_internal
ABSL_NAMESPACE_END
diff --git a/third_party/abseil-cpp/absl/types/compare.h b/third_party/abseil-cpp/absl/types/compare.h
index 19b076e7f1..62ca70f9a7 100644
--- a/third_party/abseil-cpp/absl/types/compare.h
+++ b/third_party/abseil-cpp/absl/types/compare.h
@@ -86,8 +86,7 @@ enum class ncmp : value_type { unordered = -127 };
// 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_BASECLASS_DECL(name)
#define ABSL_COMPARE_INLINE_SUBCLASS_DECL(type, name) \
static const type name
@@ -100,8 +99,7 @@ enum class ncmp : value_type { unordered = -127 };
#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_SUBCLASS_DECL(type, name)
#define ABSL_COMPARE_INLINE_INIT(type, name, init) \
template <typename T> \
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_profile.h b/third_party/abseil-cpp/absl/types/internal/conformance_profile.h
index cf64ff4fcd..e62004fdf2 100644
--- a/third_party/abseil-cpp/absl/types/internal/conformance_profile.h
+++ b/third_party/abseil-cpp/absl/types/internal/conformance_profile.h
@@ -36,19 +36,10 @@
#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.
@@ -56,187 +47,6 @@ 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 {};
@@ -260,100 +70,31 @@ using PropertiesOfT = typename PropertiesOf<T>::type;
// 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;
-}
+enum class function_kind { maybe, yes, nothrow, trivial };
-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(name) \
+ enum class name { maybe, yes, nothrow, trivial }
-#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);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(default_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(move_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(copy_constructible);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(move_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(copy_assignable);
+ABSL_INTERNAL_SPECIAL_MEMBER_FUNCTION_ENUM(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.
+#define ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(name) \
+ enum class name { maybe, yes, nothrow }
-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(equality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(inequality_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(less_than_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(less_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(greater_equal_comparable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(greater_than_comparable);
-ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM("support for swap", swappable);
+ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM(swappable);
#undef ABSL_INTERNAL_INTRINSIC_FUNCTION_ENUM
@@ -363,184 +104,6 @@ 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,
@@ -653,45 +216,6 @@ struct ConformanceProfile {
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, \
@@ -737,80 +261,12 @@ 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...);
+// Converts an enum to its underlying integral value.
+template <class Enum>
+constexpr absl::underlying_type_t<Enum> UnderlyingValue(Enum value) {
+ return static_cast<absl::underlying_type_t<Enum>>(value);
}
-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>
@@ -913,17 +369,6 @@ 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
diff --git a/third_party/abseil-cpp/absl/types/internal/conformance_testing.h b/third_party/abseil-cpp/absl/types/internal/conformance_testing.h
deleted file mode 100644
index 487b0f786b..0000000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing.h
+++ /dev/null
@@ -1,1386 +0,0 @@
-// 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/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h b/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
deleted file mode 100644
index 00775f960c..0000000000
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing_helpers.h
+++ /dev/null
@@ -1,391 +0,0 @@
-// 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/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc b/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc
index cf262fa6c2..3dcf530567 100644
--- a/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc
+++ b/third_party/abseil-cpp/absl/types/internal/conformance_testing_test.cc
@@ -12,8 +12,6 @@
// 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>
@@ -21,7 +19,6 @@
#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 {
@@ -1184,373 +1181,6 @@ 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);
- }
-}
+// TODO(calabrese) Test runtime results
} // namespace
diff --git a/third_party/abseil-cpp/absl/types/internal/parentheses.h b/third_party/abseil-cpp/absl/types/internal/parentheses.h
deleted file mode 100644
index 5aebee8fde..0000000000
--- a/third_party/abseil-cpp/absl/types/internal/parentheses.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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/third_party/abseil-cpp/absl/types/internal/transform_args.h b/third_party/abseil-cpp/absl/types/internal/transform_args.h
deleted file mode 100644
index 4a0ab42ac4..0000000000
--- a/third_party/abseil-cpp/absl/types/internal/transform_args.h
+++ /dev/null
@@ -1,246 +0,0 @@
-// 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/third_party/abseil-cpp/absl/types/internal/variant.h b/third_party/abseil-cpp/absl/types/internal/variant.h
index 772008c74e..71bd3adfc6 100644
--- a/third_party/abseil-cpp/absl/types/internal/variant.h
+++ b/third_party/abseil-cpp/absl/types/internal/variant.h
@@ -45,7 +45,7 @@ ABSL_NAMESPACE_BEGIN
template <class... Types>
class variant;
-ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, static_cast<size_t>(-1));
+ABSL_INTERNAL_INLINE_CONSTEXPR(size_t, variant_npos, -1);
template <class T>
struct variant_size;
@@ -292,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>());
}
};
@@ -424,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());
}
}
};
@@ -488,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}>()...);
@@ -930,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)))...);
diff --git a/third_party/abseil-cpp/absl/types/optional.h b/third_party/abseil-cpp/absl/types/optional.h
index 61540cfdb2..2025e29f86 100644
--- a/third_party/abseil-cpp/absl/types/optional.h
+++ b/third_party/abseil-cpp/absl/types/optional.h
@@ -136,10 +136,10 @@ class optional : private optional_internal::optional_data<T>,
constexpr optional(nullopt_t) noexcept {} // NOLINT(runtime/explicit)
// Copy constructor, standard semantics
- optional(const optional&) = default;
+ optional(const optional& src) = default;
// Move constructor, standard semantics
- optional(optional&&) = default;
+ optional(optional&& src) = default;
// Constructs a non-empty `optional` direct-initialized value of type `T` from
// the arguments `std::forward<Args>(args)...` within the `optional`.
@@ -412,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 {
- ABSL_HARDENING_ASSERT(this->engaged_);
+ assert(this->engaged_);
return std::addressof(this->data_);
}
T* operator->() {
- ABSL_HARDENING_ASSERT(this->engaged_);
+ assert(this->engaged_);
return std::addressof(this->data_);
}
@@ -425,17 +425,17 @@ 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 ABSL_HARDENING_ASSERT(this->engaged_), reference();
+ return ABSL_ASSERT(this->engaged_), reference();
}
T& operator*() & {
- ABSL_HARDENING_ASSERT(this->engaged_);
+ assert(this->engaged_);
return reference();
}
constexpr const T&& operator*() const && {
- return ABSL_HARDENING_ASSERT(this->engaged_), absl::move(reference());
+ return absl::move(reference());
}
T&& operator*() && {
- ABSL_HARDENING_ASSERT(this->engaged_);
+ assert(this->engaged_);
return std::move(reference());
}
@@ -444,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 or opt->;
+ // // do something with opt.value();
// } else {
// // opt is empty.
// }
diff --git a/third_party/abseil-cpp/absl/types/optional_test.cc b/third_party/abseil-cpp/absl/types/optional_test.cc
index 7ef142cb99..47d5c8a29e 100644
--- a/third_party/abseil-cpp/absl/types/optional_test.cc
+++ b/third_party/abseil-cpp/absl/types/optional_test.cc
@@ -1051,13 +1051,14 @@ TEST(optionalTest, Value) {
#ifdef ABSL_HAVE_EXCEPTIONS
EXPECT_THROW((void)empty.value(), absl::bad_optional_access);
#else
- EXPECT_DEATH_IF_SUPPORTED((void)empty.value(), "Bad optional access");
+ EXPECT_DEATH((void)empty.value(), "Bad optional access");
#endif
// test constexpr value()
constexpr absl::optional<int> o1(1);
static_assert(1 == o1.value(), ""); // const &
-#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
+ !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
using COI = const absl::optional<int>;
static_assert(2 == COI(2).value(), ""); // const &&
#endif
@@ -1097,7 +1098,8 @@ TEST(optionalTest, DerefOperator) {
constexpr absl::optional<int> opt1(1);
static_assert(*opt1 == 1, "");
-#if !defined(_MSC_VER) && !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
+#if !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_MSVC_BUG) && \
+ !defined(ABSL_SKIP_OVERLOAD_TEST_DUE_TO_GCC_BUG)
using COI = const absl::optional<int>;
static_assert(*COI(2) == 2, "");
#endif
diff --git a/third_party/abseil-cpp/absl/types/span.h b/third_party/abseil-cpp/absl/types/span.h
index 6272bb7ad1..3283145a56 100644
--- a/third_party/abseil-cpp/absl/types/span.h
+++ b/third_party/abseil-cpp/absl/types/span.h
@@ -17,29 +17,32 @@
// span.h
// -----------------------------------------------------------------------------
//
-// 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.
+// 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.
//
// 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++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)
+// 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`
// * `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
// * 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
@@ -74,9 +77,9 @@ ABSL_NAMESPACE_BEGIN
// Span
//------------------------------------------------------------------------------
//
-// 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
+// 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
// contiguous sequences without needing to manage pointers and array lengths
// manually.
@@ -94,8 +97,7 @@ ABSL_NAMESPACE_BEGIN
// constructors.
//
// A `Span<T>` is somewhat analogous to an `absl::string_view`, but for an array
-// 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
+// of elements of type `T`. 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:
@@ -125,7 +127,7 @@ ABSL_NAMESPACE_BEGIN
// 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 spans should not invoke operations that may reallocate memory
+// associated span views 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
@@ -169,7 +171,6 @@ class Span {
typename std::enable_if<!std::is_const<T>::value, U>::type;
public:
- using element_type = T;
using value_type = absl::remove_cv_t<T>;
using pointer = T*;
using const_pointer = const T*;
@@ -243,8 +244,8 @@ class Span {
//
template <typename LazyT = T,
typename = EnableIfConstView<LazyT>>
- Span(std::initializer_list<value_type> v
- ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept // NOLINT(runtime/explicit)
+ Span(
+ std::initializer_list<value_type> v) noexcept // NOLINT(runtime/explicit)
: Span(v.begin(), v.size()) {}
// Accessors
@@ -275,7 +276,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 ABSL_HARDENING_ASSERT(i < size()), *(data() + i);
+ return *(data() + i);
}
// Span::at()
@@ -291,74 +292,60 @@ class Span {
// Span::front()
//
- // Returns a reference to the first element of this span. The span must not
- // be empty.
+ // Returns a reference to the first element of this span.
constexpr reference front() const noexcept {
- return ABSL_HARDENING_ASSERT(size() > 0), *data();
+ return ABSL_ASSERT(size() > 0), *data();
}
// Span::back()
//
- // Returns a reference to the last element of this span. The span must not
- // be empty.
+ // Returns a reference to the last element of this span.
constexpr reference back() const noexcept {
- return ABSL_HARDENING_ASSERT(size() > 0), *(data() + size() - 1);
+ return ABSL_ASSERT(size() > 0), *(data() + size() - 1);
}
// Span::begin()
//
- // Returns an iterator pointing to the first element of this span, or `end()`
- // if the span is empty.
+ // Returns an iterator to the first element of this span.
constexpr iterator begin() const noexcept { return data(); }
// Span::cbegin()
//
- // Returns a const iterator pointing to the first element of this span, or
- // `end()` if the span is empty.
+ // Returns a const iterator to the first element of this span.
constexpr const_iterator cbegin() const noexcept { return begin(); }
// Span::end()
//
- // 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.
+ // Returns an iterator to the last element of this span.
constexpr iterator end() const noexcept { return data() + size(); }
// Span::cend()
//
- // 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.
+ // Returns a const iterator to the last element of this span.
constexpr const_iterator cend() const noexcept { return end(); }
// Span::rbegin()
//
- // Returns a reverse iterator pointing to the last element at the end of this
- // span, or `rend()` if the span is empty.
+ // Returns a reverse iterator starting at the last element of this span.
constexpr reverse_iterator rbegin() const noexcept {
return reverse_iterator(end());
}
// Span::crbegin()
//
- // Returns a const reverse iterator pointing to the last element at the end of
- // this span, or `crend()` if the span is empty.
+ // Returns a reverse const iterator starting at the last element of this span.
constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); }
// Span::rend()
//
- // 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.
+ // Returns a reverse iterator starting at the first element of this span.
constexpr reverse_iterator rend() const noexcept {
return reverse_iterator(begin());
}
// Span::crend()
//
- // 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.
+ // Returns a reverse iterator starting at the first element of this span.
constexpr const_reverse_iterator crend() const noexcept { return rend(); }
// Span mutations
@@ -367,7 +354,7 @@ class Span {
//
// Removes the first `n` elements from the span.
void remove_prefix(size_type n) noexcept {
- ABSL_HARDENING_ASSERT(size() >= n);
+ assert(size() >= n);
ptr_ += n;
len_ -= n;
}
@@ -376,7 +363,7 @@ class Span {
//
// Removes the last `n` elements from the span.
void remove_suffix(size_type n) noexcept {
- ABSL_HARDENING_ASSERT(size() >= n);
+ assert(size() >= n);
len_ -= n;
}
@@ -664,7 +651,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_HARDENING_ASSERT(begin <= end), Span<T>(begin, end - begin);
+ return ABSL_ASSERT(begin <= end), Span<T>(begin, end - begin);
}
template <int&... ExplicitArgumentBarrier, typename C>
@@ -709,7 +696,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_HARDENING_ASSERT(begin <= end), Span<const T>(begin, end - begin);
+ return ABSL_ASSERT(begin <= end), Span<const T>(begin, end - begin);
}
template <int&... ExplicitArgumentBarrier, typename C>
diff --git a/third_party/abseil-cpp/absl/types/span_test.cc b/third_party/abseil-cpp/absl/types/span_test.cc
index 13264aae14..22467a0a76 100644
--- a/third_party/abseil-cpp/absl/types/span_test.cc
+++ b/third_party/abseil-cpp/absl/types/span_test.cc
@@ -27,7 +27,6 @@
#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"
@@ -233,11 +232,6 @@ 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) {
@@ -274,13 +268,6 @@ 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) {
@@ -661,8 +648,6 @@ TEST(IntSpan, ExposesContainerTypesAndConsts) {
CheckType<absl::Span<int>::const_reverse_iterator>(slice.crend());
testing::StaticAssertTypeEq<int, absl::Span<int>::value_type>();
testing::StaticAssertTypeEq<int, absl::Span<const int>::value_type>();
- testing::StaticAssertTypeEq<int, absl::Span<int>::element_type>();
- testing::StaticAssertTypeEq<const int, absl::Span<const int>::element_type>();
testing::StaticAssertTypeEq<int*, absl::Span<int>::pointer>();
testing::StaticAssertTypeEq<const int*, absl::Span<const int>::pointer>();
testing::StaticAssertTypeEq<int&, absl::Span<int>::reference>();
diff --git a/third_party/abseil-cpp/absl/types/variant.h b/third_party/abseil-cpp/absl/types/variant.h
index ac93464bf8..776d19a1c5 100644
--- a/third_party/abseil-cpp/absl/types/variant.h
+++ b/third_party/abseil-cpp/absl/types/variant.h
@@ -604,10 +604,7 @@ class variant<T0, Tn...> : private variant_internal::VariantBase<T0, Tn...> {
// emplace() Functions
- // 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.
+ // Constructs a value of the given alternative type T within the variant.
//
// Example:
//
@@ -627,9 +624,7 @@ 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. 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.
+ // an initializer list.
//
// Example:
//
@@ -648,7 +643,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:
@@ -667,7 +662,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:
diff --git a/third_party/abseil-cpp/absl/types/variant_test.cc b/third_party/abseil-cpp/absl/types/variant_test.cc
index cf237334da..96393333b8 100644
--- a/third_party/abseil-cpp/absl/types/variant_test.cc
+++ b/third_party/abseil-cpp/absl/types/variant_test.cc
@@ -50,7 +50,7 @@
#else
#define ABSL_VARIANT_TEST_EXPECT_FAIL(expr, exception_t, text) \
- EXPECT_DEATH_IF_SUPPORTED(expr, text)
+ EXPECT_DEATH(expr, text)
#endif // ABSL_HAVE_EXCEPTIONS
@@ -679,7 +679,7 @@ TEST(VariantTest, TestSelfAssignment) {
object.operator=(object);
EXPECT_EQ(0, counter);
- // A string long enough that it's likely to defeat any inline representation
+ // A std::string long enough that it's likely to defeat any inline representation
// optimization.
const std::string long_str(128, 'a');
@@ -2311,8 +2311,7 @@ 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
@@ -2454,8 +2453,7 @@ 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
diff --git a/third_party/abseil-cpp/absl/utility/BUILD.bazel b/third_party/abseil-cpp/absl/utility/BUILD.bazel
index ca4bc0a6b8..6881f939c5 100644
--- a/third_party/abseil-cpp/absl/utility/BUILD.bazel
+++ b/third_party/abseil-cpp/absl/utility/BUILD.bazel
@@ -14,6 +14,7 @@
# limitations under the License.
#
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
load(
"//absl:copts/configure_copts.bzl",
"ABSL_DEFAULT_COPTS",
@@ -23,7 +24,7 @@ load(
package(default_visibility = ["//visibility:public"])
-licenses(["notice"])
+licenses(["notice"]) # Apache 2.0
cc_library(
name = "utility",
diff --git a/third_party/abseil-cpp/absl/utility/CMakeLists.txt b/third_party/abseil-cpp/absl/utility/CMakeLists.txt
index 865b758f23..e1edd19aa0 100644
--- a/third_party/abseil-cpp/absl/utility/CMakeLists.txt
+++ b/third_party/abseil-cpp/absl/utility/CMakeLists.txt
@@ -40,5 +40,5 @@ absl_cc_test(
absl::core_headers
absl::memory
absl::strings
- GTest::gmock_main
+ gmock_main
)
diff --git a/third_party/abseil-cpp/absl/utility/utility.h b/third_party/abseil-cpp/absl/utility/utility.h
index bf9232209a..e6647c7b2e 100644
--- a/third_party/abseil-cpp/absl/utility/utility.h
+++ b/third_party/abseil-cpp/absl/utility/utility.h
@@ -236,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))...);
}
diff --git a/third_party/abseil-cpp/ci/absl_alternate_options.h b/third_party/abseil-cpp/ci/absl_alternate_options.h
index 29b020d9fa..f0c21fea9d 100644
--- a/third_party/abseil-cpp/ci/absl_alternate_options.h
+++ b/third_party/abseil-cpp/ci/absl_alternate_options.h
@@ -1,3 +1,6 @@
+#ifndef ABSL_BASE_OPTIONS_H_
+#define ABSL_BASE_OPTIONS_H_
+
// Copyright 2019 The Abseil Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,15 +18,11 @@
// 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/third_party/abseil-cpp/ci/cmake_common.sh b/third_party/abseil-cpp/ci/cmake_common.sh
deleted file mode 100644
index 51f310693e..0000000000
--- a/third_party/abseil-cpp/ci/cmake_common.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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="8d51ffdfab10b3fba636ae69bc03da4b54f8c235"
-
-# 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/third_party/abseil-cpp/ci/cmake_install_test.sh b/third_party/abseil-cpp/ci/cmake_install_test.sh
index 97ed8478e0..55fb4f120b 100755..100644
--- a/third_party/abseil-cpp/ci/cmake_install_test.sh
+++ b/third_party/abseil-cpp/ci/cmake_install_test.sh
@@ -16,31 +16,17 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+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 \
+time docker run \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
--workdir=/abseil-cpp \
+ --tmpfs=/buildfs:exec \
--cap-add=SYS_PTRACE \
- -e "ABSL_GOOGLETEST_COMMIT=${ABSL_GOOGLETEST_COMMIT}" \
- -e "ABSL_GOOGLETEST_DOWNLOAD_URL=${ABSL_GOOGLETEST_DOWNLOAD_URL}" \
- -e "LINK_TYPE=${link_type}" \
--rm \
- ${DOCKER_EXTRA_ARGS:-} \
- ${DOCKER_CONTAINER} \
- /bin/bash -c "cp -r /abseil-cpp-ro/* . && CMake/install_test_project/test.sh"
-done
+ -e CFLAGS="-Werror" \
+ -e CXXFLAGS="-Werror" \
+ gcr.io/google.com/absl-177019/linux_gcc-latest:20200106 \
+ /bin/bash CMake/install_test_project/test.sh $@
diff --git a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh
index 5245933a5f..24efe3b7a0 100755..100644
--- a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_asan_bazel.sh
@@ -20,29 +20,28 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
- STD="c++11 c++14 c++17 c++20"
+if [ -z ${STD:-} ]; then
+ STD="c++11 c++14 c++17"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102"
# 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:-}"
+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
@@ -51,24 +50,17 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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 \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
-e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_COMPILER="llvm" \
-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" \
@@ -77,13 +69,15 @@ for std in ${STD}; do
/usr/local/bin/bazel test ... \
--compilation_mode="${compilation_mode}" \
--copt="${exceptions_mode}" \
+ --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \
+ --copt="-DADDRESS_SANITIZER" \
+ --copt="-DUNDEFINED_BEHAVIOR_SANITIZER" \
--copt="-fsanitize=address" \
--copt="-fsanitize=float-divide-by-zero" \
--copt="-fsanitize=nullability" \
--copt="-fsanitize=undefined" \
--copt="-fno-sanitize-blacklist" \
--copt=-Werror \
- --distdir="/bazel-distdir" \
--keep_going \
--linkopt="-fsanitize=address" \
--linkopt="-fsanitize-link-c++-runtime" \
diff --git a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh
index e0fe653de7..127e7bc7b2 100755..100644
--- a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_bazel.sh
@@ -20,29 +20,28 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
- STD="c++11 c++14 c++17 c++20"
+if [ -z ${STD:-} ]; then
+ STD="c++11 c++14 c++17"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102"
# 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:-}"
+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
@@ -51,25 +50,18 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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 \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \
--tmpfs=/abseil-cpp \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
-e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_COMPILER="llvm" \
-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" \
@@ -85,7 +77,6 @@ for std in ${STD}; do
--copt=\"${exceptions_mode}\" \
--copt=-Werror \
--define=\"absl=1\" \
- --distdir=\"/bazel-distdir\" \
--keep_going \
--show_timestamps \
--test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
diff --git a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh
index 555f6b1c2a..00257b36ad 100755..100644
--- a/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_clang-latest_libcxx_tsan_bazel.sh
@@ -20,29 +20,28 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
- STD="c++11 c++14 c++17 c++20"
+if [ -z ${STD:-} ]; then
+ STD="c++11 c++14 c++17"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102"
# 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:-}"
+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
@@ -51,24 +50,17 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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 \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
-e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_COMPILER="llvm" \
-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" \
@@ -78,10 +70,11 @@ for std in ${STD}; do
--build_tag_filters="-notsan" \
--compilation_mode="${compilation_mode}" \
--copt="${exceptions_mode}" \
+ --copt="-DDYNAMIC_ANNOTATIONS_ENABLED=1" \
+ --copt="-DTHREAD_SANITIZER" \
--copt="-fsanitize=thread" \
--copt="-fno-sanitize-blacklist" \
--copt=-Werror \
- --distdir="/bazel-distdir" \
--keep_going \
--linkopt="-fsanitize=thread" \
--show_timestamps \
diff --git a/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh b/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
index 36fdf82c1d..9fe71d3760 100755..100644
--- a/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_clang-latest_libstdcxx_bazel.sh
@@ -20,29 +20,28 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
+if [ -z ${STD:-} ]; then
STD="c++11 c++14 c++17"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_clang-latest:20200102"
# 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:-}"
+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
@@ -51,36 +50,27 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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 \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
-e CC="/opt/llvm/clang/bin/clang" \
+ -e BAZEL_COMPILER="llvm" \
-e BAZEL_CXXOPTS="-std=${std}" \
+ -e CPLUS_INCLUDE_PATH="/usr/include/c++/6" \
${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" \
- --distdir="/bazel-distdir" \
--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" \
diff --git a/third_party/abseil-cpp/ci/linux_docker_containers.sh b/third_party/abseil-cpp/ci/linux_docker_containers.sh
deleted file mode 100644
index 32865b8348..0000000000
--- a/third_party/abseil-cpp/ci/linux_docker_containers.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-# 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:20210617"
-readonly LINUX_GCC_LATEST_CONTAINER="gcr.io/google.com/absl-177019/linux_hybrid-latest:20210617"
-readonly LINUX_GCC_FLOOR_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-floor:20210617"
diff --git a/third_party/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh b/third_party/abseil-cpp/ci/linux_gcc-4.9_libstdcxx_bazel.sh
index 54ab68a37e..f8102cc0a1 100755..100644
--- a/third_party/abseil-cpp/ci/linux_gcc-floor_libstdcxx_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_gcc-4.9_libstdcxx_bazel.sh
@@ -1,6 +1,6 @@
#!/bin/bash
#
-# Copyright 2020 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.
@@ -20,28 +20,27 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
+if [ -z ${STD:-} ]; then
STD="c++11 c++14"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-4.9:20191018"
# 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
+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
@@ -51,14 +50,6 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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
@@ -68,7 +59,7 @@ for std in ${STD}; do
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
--rm \
- -e CC="/usr/local/bin/gcc" \
+ -e CC="/usr/bin/gcc-4.9" \
-e BAZEL_CXXOPTS="-std=${std}" \
${DOCKER_EXTRA_ARGS:-} \
${DOCKER_CONTAINER} \
@@ -77,7 +68,6 @@ for std in ${STD}; do
--copt="${exceptions_mode}" \
--copt=-Werror \
--define="absl=1" \
- --distdir="/bazel-distdir" \
--keep_going \
--show_timestamps \
--test_env="GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1" \
diff --git a/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh b/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh
index 0555ecedb5..59647031f8 100755..100644
--- a/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh
+++ b/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_bazel.sh
@@ -20,29 +20,28 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+if [ -z ${ABSEIL_ROOT:-} ]; then
ABSEIL_ROOT="$(realpath $(dirname ${0})/..)"
fi
-if [[ -z ${STD:-} ]]; then
- STD="c++11 c++14 c++17 c++20"
+if [ -z ${STD:-} ]; then
+ STD="c++11 c++14 c++17"
fi
-if [[ -z ${COMPILATION_MODE:-} ]]; then
+if [ -z ${COMPILATION_MODE:-} ]; then
COMPILATION_MODE="fastbuild opt"
fi
-if [[ -z ${EXCEPTIONS_MODE:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/linux_gcc-latest:20200106"
# 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:-}"
+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
@@ -51,20 +50,12 @@ if [[ ${USE_BAZEL_CACHE:-0} -ne 0 ]]; then
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 \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp-ro:ro" \
--tmpfs=/abseil-cpp \
--workdir=/abseil-cpp \
--cap-add=SYS_PTRACE \
@@ -83,7 +74,6 @@ for std in ${STD}; do
--copt=\"${exceptions_mode}\" \
--copt=-Werror \
--define=\"absl=1\" \
- --distdir=\"/bazel-distdir\" \
--keep_going \
--show_timestamps \
--test_env=\"GTEST_INSTALL_FAILURE_SIGNAL_HANDLER=1\" \
diff --git a/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh b/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh
index ab06aa0574..38ad99f7ef 100755..100644
--- a/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh
+++ b/third_party/abseil-cpp/ci/linux_gcc-latest_libstdcxx_cmake.sh
@@ -14,52 +14,48 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# TODO(absl-team): This script isn't fully hermetic because
+# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
+# version of GoogleTest. This means that an upstream change to GoogleTest could
+# break this test. Fix this by allowing this script to pin to a known-good
+# version of GoogleTest.
+
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+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"
+if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then
+ ABSL_CMAKE_CXX_STANDARDS="11 14 17"
fi
-if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+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
+ echo "--------------------------------------------------------------------"
+ echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}"
+
+ time docker run \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+ --workdir=/abseil-cpp \
+ --tmpfs=/buildfs:exec \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CFLAGS="-Werror" \
+ -e CXXFLAGS="-Werror" \
+ gcr.io/google.com/absl-177019/linux_gcc-latest:20200106 \
+ /bin/bash -c "
+ cd /buildfs && \
+ cmake /abseil-cpp \
+ -DABSL_USE_GOOGLETEST_HEAD=ON \
+ -DABSL_RUN_TESTS=ON \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=${std} && \
+ make -j$(nproc) && \
+ ctest -j$(nproc) --output-on-failure"
done
done
diff --git a/third_party/abseil-cpp/ci/linux_gcc_alpine_cmake.sh b/third_party/abseil-cpp/ci/linux_gcc_alpine_cmake.sh
index bce27d295f..830a1360a3 100755..100644
--- a/third_party/abseil-cpp/ci/linux_gcc_alpine_cmake.sh
+++ b/third_party/abseil-cpp/ci/linux_gcc_alpine_cmake.sh
@@ -14,51 +14,50 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+# TODO(absl-team): This script isn't fully hermetic because
+# -DABSL_USE_GOOGLETEST_HEAD=ON means that this script isn't pinned to a fixed
+# version of GoogleTest. This means that an upstream change to GoogleTest could
+# break this test. Fix this by allowing this script to pin to a known-good
+# version of GoogleTest.
+
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+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
+if [ -z ${ABSL_CMAKE_CXX_STANDARDS:-} ]; then
ABSL_CMAKE_CXX_STANDARDS="11 14 17"
fi
-if [[ -z ${ABSL_CMAKE_BUILD_TYPES:-} ]]; then
+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}
+readonly DOCKER_CONTAINER="gcr.io/google.com/absl-177019/alpine:20191016"
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
+ echo "--------------------------------------------------------------------"
+ echo "Testing with CMAKE_BUILD_TYPE=${compilation_mode} and -std=c++${std}"
+
+ time docker run \
+ --volume="${ABSEIL_ROOT}:/abseil-cpp:ro" \
+ --workdir=/abseil-cpp \
+ --tmpfs=/buildfs:exec \
+ --cap-add=SYS_PTRACE \
+ --rm \
+ -e CFLAGS="-Werror" \
+ -e CXXFLAGS="-Werror" \
+ "${DOCKER_CONTAINER}" \
+ /bin/sh -c "
+ cd /buildfs && \
+ cmake /abseil-cpp \
+ -DABSL_USE_GOOGLETEST_HEAD=ON \
+ -DABSL_RUN_TESTS=ON \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=${std} && \
+ make -j$(nproc) && \
+ ctest -j$(nproc) --output-on-failure"
done
done
diff --git a/third_party/abseil-cpp/ci/macos_xcode_bazel.sh b/third_party/abseil-cpp/ci/macos_xcode_bazel.sh
index 9e14e66039..f5f2d759cf 100755..100644
--- a/third_party/abseil-cpp/ci/macos_xcode_bazel.sh
+++ b/third_party/abseil-cpp/ci/macos_xcode_bazel.sh
@@ -19,13 +19,13 @@
set -euox pipefail
-if [[ -z ${ABSEIL_ROOT:-} ]]; then
+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-3.7.0-darwin-x86_64"
-if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then
+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
@@ -41,7 +41,7 @@ echo "---------------"
cd ${ABSEIL_ROOT}
-if [[ -n "${ALTERNATE_OPTIONS:-}" ]]; then
+if [ -n "${ALTERNATE_OPTIONS:-}" ]; then
cp ${ALTERNATE_OPTIONS:-} absl/base/options.h || exit 1
fi
diff --git a/third_party/abseil-cpp/ci/macos_xcode_cmake.sh b/third_party/abseil-cpp/ci/macos_xcode_cmake.sh
index 2a870cf4e9..a1f4a857be 100755..100644
--- a/third_party/abseil-cpp/ci/macos_xcode_cmake.sh
+++ b/third_party/abseil-cpp/ci/macos_xcode_cmake.sh
@@ -14,43 +14,31 @@
# 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
+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
+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
+ 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 \
+ -DCMAKE_BUILD_TYPE=${compilation_mode} \
+ -DCMAKE_CXX_STANDARD=11 \
+ -DABSL_USE_GOOGLETEST_HEAD=ON \
+ -DABSL_RUN_TESTS=ON
+ time cmake --build .
+ time ctest -C ${compilation_mode} --output-on-failure
done
diff --git a/third_party/abseil-cpp/conanfile.py b/third_party/abseil-cpp/conanfile.py
index 926ec5ccd6..926ec5ccd6 100755..100644
--- a/third_party/abseil-cpp/conanfile.py
+++ b/third_party/abseil-cpp/conanfile.py
diff --git a/third_party/abseil-cpp/create_lts.py b/third_party/abseil-cpp/create_lts.py
deleted file mode 100755
index 561708063f..0000000000
--- a/third_party/abseil-cpp/create_lts.py
+++ /dev/null
@@ -1,133 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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/config.h', {
- '#undef ABSL_LTS_RELEASE_VERSION':
- '#define ABSL_LTS_RELEASE_VERSION {}'.format(datestamp),
- '#undef ABSL_LTS_RELEASE_PATCH_LEVEL':
- '#define ABSL_LTS_RELEASE_PATCH_LEVEL 0'
- })
- 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 YYMM.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. Note that we
- # only use the last two digits of the year and the month because the
- # MacOS linker requires the first part of the SOVERSION to fit into
- # 16 bits.
- # https://www.sicpers.info/2013/03/how-to-version-a-mach-o-library/
- ReplaceStringsInFile(
- 'CMake/AbseilHelpers.cmake',
- {'SOVERSION 0': 'SOVERSION "{}.0.0"'.format(datestamp[2:6])})
- StripContentBetweenTags('CMakeLists.txt', '# absl:lts-remove-begin',
- '# absl:lts-remove-end')
-
-
-if __name__ == '__main__':
- main(sys.argv)